【发布时间】:2020-12-30 18:38:37
【问题描述】:
Kubernetes v1.20.0,在 Ubuntu 20.04.1 上,docker 19.3.11
使用以下配置,我可以使用此服务帐户的令牌在命名空间“live”中创建部署,但我无法使用相同的令牌删除部署。
试图找到正确的角色以绑定到我的编程 ServiceAccount 用户,但我无法获得正确的角色映射以进行部署删除。我尝试过在资源名称中使用和不使用斜杠、星号以及资源的复数形式。
这是我从 API 得到的错误:
warnings.warn(
Exception (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Cache-Control': 'no-cache, private', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff', 'X-Kubernetes-Pf-Flowschema-Uid': 'xxxx-bf2f-43b3-af5d-3ce15b086080', 'X-Kubernetes-Pf-Prioritylevel-Uid': 'xxxx-0d42-4b08-820e-396249f74107', 'Date': 'Mon, 28 Dec 2020 13:33:00 GMT', 'Content-Length': '408'})
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"deployments.apps \"live-stream-deploy-testing123\" is forbidden: User \"system:serviceaccount:live:live-serviceaccount\" cannot delete resource \"deployments\" in API group \"apps\" in the namespace \"live\"","reason":"Forbidden","details":{"name":"live-stream-deploy-testing123","group":"apps","kind":"deployments"},"code":403}
这是我要删除的部署:
$ kubectl -n live get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
live-stream-deploy-testing123 1/1 1 1 76m
这是我目前在角色定义中所处的位置(我也尝试在资源名称中使用星号,这也不适用于创建,后来进行了多次迭代:):
$ kubectl -n live describe role
Name: live-serviceaccount-role
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
deployment/ [] [] [get watch create list delete]
deployment [] [] [get watch create list delete]
deployments/ [] [] [get watch create list delete]
deployments [] [] [get watch create list delete]
service/ [] [] [get watch create list delete]
service [] [] [get watch create list delete]
services/ [] [] [get watch create list delete]
services [] [] [get watch create list delete]
services [] [] [get watch create list delete]
deployment.apps/ [] [] [get watch create list delete]
deployment.apps [] [] [get watch create list delete]
deployments.apps/ [] [] [get watch create list delete]
deployments.apps [] [] [get watch create list delete]
service.apps/ [] [] [get watch create list delete]
service.apps [] [] [get watch create list delete]
services.apps/ [] [] [get watch create list delete]
services.apps [] [] [get watch create list delete]
角色绑定:
$ kubectl -n live describe rolebindings
Name: live-serviceaccount-rolebinding
Labels: <none>
Annotations: <none>
Role:
Kind: Role
Name: live-serviceaccount-role
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount live-serviceaccount live
pip 包 kubernetes==12.0.1。我没有针对以前的版本对其进行测试。 导致错误的脚本:
import kubernetes.client
from kubernetes.client.rest import ApiException
import logging
logger = logging.getLogger(__name__)
DEPLOYMENT_NAME = "live-stream-deploy-testing123"
configuration = kubernetes.client.Configuration()
configuration.api_key['authorization'] = "service account token here..."
configuration.api_key_prefix['authorization'] = 'Bearer'
configuration.verify_ssl = False
configuration.host = "https://my_k8s_API:6443"
with kubernetes.client.ApiClient(configuration) as api_client:
try:
api_instance = kubernetes.client.AppsV1Api(api_client)
api_instance.delete_namespaced_deployment(
name=DEPLOYMENT_NAME, namespace="live")
logger.info("Deployment deleted. %s" % DEPLOYMENT_NAME)
except ApiException as e:
logger.error("Exception %s\n" % e)
一些额外的“can-i”动作:
$ kubectl -n live auth can-i --as=system:serviceaccount:live:live-serviceaccount delete deploy
yes
$ kubectl auth can-i --as=system:serviceaccount:live:live-serviceaccount --list -n live
Resources Non-Resource URLs Resource Names Verbs
selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
deployment/ [] [] [get watch create list delete]
deployment [] [] [get watch create list delete]
deployments/ [] [] [get watch create list delete]
deployments [] [] [get watch create list delete]
service/ [] [] [get watch create list delete]
service [] [] [get watch create list delete]
services/ [] [] [get watch create list delete]
services [] [] [get watch create list delete]
deployment.apps/ [] [] [get watch create list delete]
deployment.apps [] [] [get watch create list delete]
deployments.apps/ [] [] [get watch create list delete]
deployments.apps [] [] [get watch create list delete]
service.apps/ [] [] [get watch create list delete]
service.apps [] [] [get watch create list delete]
services.apps/ [] [] [get watch create list delete]
services.apps [] [] [get watch create list delete]
[/.well-known/openid-configuration] [] [get]
[/api/*] [] [get]
[/api] [] [get]
[/apis/*] [] [get]
[/apis] [] [get]
[/healthz] [] [get]
[/healthz] [] [get]
[/livez] [] [get]
[/livez] [] [get]
[/openapi/*] [] [get]
[/openapi] [] [get]
[/openid/v1/jwks] [] [get]
[/readyz] [] [get]
[/readyz] [] [get]
[/version/] [] [get]
[/version/] [] [get]
[/version] [] [get]
[/version] [] [get]
这里是产生上述输出的 YAML。它们都在 live 命名空间上。原谅角色的混乱,但我一直在尝试迭代解决方案:
$ cat role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: live-serviceaccount-role
namespace: live
rules:
- apiGroups: ["","apps"]
resources: ["services", "services/", "deployment", "deployment/", "service", "service/", "deployments", "deployments/"]
resourceNames: [""]
verbs: ["get", "watch", "create", "list", "delete"]
- apiGroups: [""]
resources: ["services"]
resourceNames: [""]
verbs: ["get", "watch", "create", "list", "delete"]
$ cat serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: live-serviceaccount
namespace: live
$ cat rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: live-serviceaccount-rolebinding
namespace: live
subjects:
- kind: ServiceAccount
name: live-serviceaccount # "name" is case sensitive
namespace: live
roleRef:
kind: Role #this must be Role or ClusterRole
name: live-serviceaccount-role # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: "rbac.authorization.k8s.io"
以下是在 live 命名空间中成功点亮部署的脚本示例:
import kubernetes.client
from kubernetes import client
import logging
logger = logging.getLogger(__name__)
DEPLOYMENT_NAME = "live-stream-deploy-testing123"
POD_APP_LABEL = "lab"
configuration = kubernetes.client.Configuration()
# Configure API key authorization: BearerToken
configuration.api_key['authorization'] = "service account token here..."
# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
configuration.api_key_prefix['authorization'] = 'Bearer'
configuration.verify_ssl = False
# Defining host is optional and default to http://localhost
configuration.host = "https://<myk8sapi>:6443"
# Enter a context with an instance of the API kubernetes.client
#with kubernetes.client.ApiClient(configuration) as api_client:
with kubernetes.client.ApiClient(configuration) as api_client:
api_instance = kubernetes.client.AppsV1Api(api_client)
def create_deployment_object():
# Configureate Pod template container
container = kubernetes.client.V1Container(
name="lab-container",
# redacted for privacy
image="nginx:latest",
termination_message_path="/var/log/messages",
image_pull_policy="IfNotPresent",
resources=client.V1ResourceRequirements(
requests={"memory": "5Gi"},
limits={"memory": "16Gi"}
),
volume_mounts=[
client.V1VolumeMount(mount_path="/etc/nginx/nginx.conf.template", name="nginxconftemplate", sub_path="nginx.conf")
]
)
volume1 = client.V1Volume(
name="nginxconftemplate",
config_map=client.V1ConfigMapVolumeSource(
name="live-nginx-conf",
default_mode=0o0777
)
)
# Create and configurate a spec section
template = client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(labels={"app": POD_APP_LABEL}),
spec=client.V1PodSpec(containers=[container],
volumes=[volume1],
node_selector={"backend": "yes"},
)
)
# Create the specification of deployment
spec = client.V1DeploymentSpec(
replicas=1,
template=template,
selector={'matchLabels': {'app': POD_APP_LABEL}})
# Instantiate the deployment object
deployment = client.V1Deployment(
api_version="apps/v1",
kind="Deployment",
metadata=client.V1ObjectMeta(name=DEPLOYMENT_NAME),
spec=spec)
return deployment
def create_deployment(api_instance, deployment):
# Create deployement
api_response = api_instance.create_namespaced_deployment(
body=deployment,
namespace="live")
logger.info("Deployment created. status='%s'" % str(api_response.status))
deployment = create_deployment_object()
create_deployment(api_instance, deployment)
【问题讨论】:
-
能否提供yaml配置文件(服务账号、角色、角色绑定)?
-
我提供了 yaml 配置文件,并更新了问题以包含成功启动部署的代码示例。
标签: kubernetes rbac