大量内容参考了https://k8smeetup.github.io
基于1.11
用户可以通过kubectl命令, 客户端库, 或者发送REST请求来访问API 。kubernetes用户和服务账号都可以用于API访问时的授权。 当请求到达API时, 它会经历几个阶段,如下图所示:
在一个典型的 Kubernetes集群里, API 的侦听端口是443, TLS连接会被建立。API server会提供一个证书。 这个证书是自签名的, 因此在$USER/.kube/config
路径下会包含API server证书的根证书,你可以指定这个证书用来替换系统默认的根证书。当你使用kube-up.sh来创建集群时,这个证书会自动写入到$USER/.kube/config
目录下。如果集群有多个用户, 那么集群创建者需要和其它用户共享这个证书。
###(3)授权
--insecure-port
指定别的端口--insecure-bind-address
指定别的地址--tls-cert-file
参数指定证书路径, --tls-private-key-file
参数指定证书的私钥--secure-port
指定别的端口--bind-address
指定IP地址kube-up.sh
创建集群的话, API Server会侦听443端口。 在GCE上, 默认会开放防火墙策略允许从外部通过HTTPS访问集群的API. 其它云供应商的策略不尽相同。openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"
看看用kubeadm创建的集群中的apiServer启动参数:
[root@server .kube]# ps -ef |grep -v grep |grep -i
kube-apiserver --authorization-mode=Node,RBAC \
--advertise-address=10.40.2.230 \
--allow-privileged=true \
--client-ca-file=/etc/kubernetes/pki/ca.crt \
--disable-admission-plugins=PersistentVolumeLabel \
--enable-admission-plugins=NodeRestriction \
--enable-bootstrap-token-auth=true \
--etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt \
--etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt \
--etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key \
--etcd-servers=https://127.0.0.1:2379 \
--insecure-port=0 \
--kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt \
--kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key \
--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
--proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt \
--proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key \
--requestheader-allowed-names=front-proxy-client \
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--secure-port=6443 \
--service-account-key-file=/etc/kubernetes/pki/sa.pub \
--service-cluster-ip-range=10.96.0.0/12 \
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt \
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key
token,user,uid,"group1,group2,group3"
Bearer TOKEN
的值。Bearer token 必须是一个字符串序列,只需使用 HTTP 的编码和引用功能就可以将其放入到 HTTP header 中。
Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269
password,user,uid,"group1,group2,group3"
Authorization header 中包含 Basic BASE64ENCODED(USER:PASSWORD)
的值--service-account-key-file
一个包含签名 bearer token 的 PEM 编码文件。如果未指定,将使用 API server 的 TLS 私钥。--service-account-lookup
如果启用,从 API 中删除掉的 token 将被撤销。system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)
,被指定到组 system:serviceaccounts
和 system:serviceaccounts:(NAMESPACE)
。--requestheader-username-headers
必需,大小写敏感。按 header 名称和顺序检查用户标识。包含值的第一个 header 将被作为用户名。--requestheader-group-headers
1.6 以上版本。可选。大小写敏感。建议为 “X-Remote-Group”。按 header 名称和顺序检查用户组。所有指定的 header 中的所有值都将作为组名。--requestheader-extra-headers-prefix
1.6 以上版本。可选,大小写敏感。建议为 “X-Remote-Extra-”。标题前缀可用于查找有关用户的额外信息(通常由配置的授权插件使用)。以任何指定的前缀开头的 header 都会删除前缀,header 名称的其余部分将成为额外的键值,而 header 值则是额外的值。--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-
GET / HTTP/1.1
X-Remote-User: fido
X-Remote-Group: dogs
X-Remote-Group: dachshunds
X-Remote-Extra-Scopes: openid
X-Remote-Extra-Scopes: profile
name: fido
groups:
- dogs
- dachshunds
extra:
scopes:
- openid
- profile
参考:https://v1-11.docs.kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation
Impersonate-User
: The username to act asImpersonate-Group
: A group name to act as. Can be provided multiple times to set multiple groups. Optional. Requires “Impersonate-User”Impersonate-Extra-( extra name )
: A dynamic header used to associate extra fields with the user. Optional. Requires “Impersonate-User”Impersonate-User: [email protected]
Impersonate-Group: developers
Impersonate-Group: admins
Impersonate-Extra-dn: cn=jane,ou=engineers,dc=example,dc=com
Impersonate-Extra-scopes: view
Impersonate-Extra-scopes: development
# When using kubectl set the --as flag to configure the Impersonate-User header,
# set the --as-group flag to configure the Impersonate-Group header
$ kubectl drain mynode --as=superman --as-group=system:masters
node "mynode" cordoned
node "mynode" drained
# user, group
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonator
rules:
- apiGroups: [""]
resources: ["users", "groups", "serviceaccounts"]
verbs: ["impersonate"]
# extra fields
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: scopes-impersonator
rules:
# Can set "Impersonate-Extra-scopes" header.
- apiGroups: ["authentication.k8s.io"]
resources: ["userextras/scopes"]
verbs: ["impersonate"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: limited-impersonator
rules:
# Can impersonate the user "[email protected]"
- apiGroups: [""]
resources: ["users"]
verbs: ["impersonate"]
resourceNames: ["[email protected]"]
# Can impersonate the groups "developers" and "admins"
- apiGroups: [""]
resources: ["groups"]
verbs: ["impersonate"]
resourceNames: ["developers","admins"]
# Can impersonate the extras field "scopes" with the values "view" and "development"
- apiGroups: ["authentication.k8s.io"]
resources: ["userextras/scopes"]
verbs: ["impersonate"]
resourceNames: ["view", "development"]
参考:https://v1-11.docs.kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
cluster/saltbase/salt/generate-cert/make-ca-cert.sh
curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz
tar xzf easy-rsa.tar.gz
cd easy-rsa-master/easyrsa3
./easyrsa init-pki
./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
./easyrsa --subject-alt-name="IP:${MASTER_IP}" build-server-full server nopass
--client-ca-file=/yourdirectory/ca.crt
--tls-cert-file=/yourdirectory/server.crt
--tls-private-key-file=/yourdirectory/server.key
openssl 可以用来手动为集群生成证书。
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
openssl genrsa -out server.key 2048
openssl req -new -key server.key -subj "/CN=${MASTER_IP}" -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 10000
openssl x509 -noout -text -in ./server.crt
Kubernetes 仅查看以下API请求属性:
要确定资源 API 端点的请求动词,请查看所使用的HTTP动词以及请求是否对单个资源或资源集合进行操作:
HTTP动词 | 请求动作 |
---|---|
POST | 创建 |
GET,HEAD | 获取(个人资源),列表(结合) |
PUT | 更新 |
PATCH | 补丁 |
DELETE | 删除(个人资源),删除(收藏) |
Kubernetes 有时会使用专门的动词检查授权以获得额外的权限。例如:
参考:https://k8smeetup.github.io/docs/admin/authorization/#检查api访问
服务账号的自动化由三个独立的组件共同配合实现:
服务帐号控制器在命名空间内管理 ServiceAccount,需要保证名为 “default” 的 ServiceAccount 在每个命名空间中存在。
对于 pods 的操作是通过一个叫做 准入控制器 的插件(plugin)实现的。它是 APIserver 的一部分。 当 pod 被创建或更新时,它会同步更改 pod。当这个插件是活动状态时(大部分版本默认是活动状态),在 pod 被创建或者更改时, 它会做如下操作:
令牌控制器(TokenController)作为 controller-manager 的一部分运行。它异步运行。它会:
你必须给令牌控制器传递一个服务帐号的私钥(private key),通过 --service-account-private-key-file 参数完成。传递的私钥将被用来对服务帐号令牌进行签名。 类似的,你必须给 kube-apiserver 传递一个公钥(public key),通过 --service-account-key-file 参数完成。传递的公钥在认证过程中会被用于验证令牌
控制器的循环运行会确保对于每个服务帐号都存在一个带有 API 令牌的 secret。 如需要为服务帐号创建一个额外的 API 令牌,可以创建一个 ServiceAccountToken 类型的 secret,并添加与服务帐号对应的 annotation 属性,控制器会为它更新令牌:
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "mysecretname",
"annotations": {
"kubernetes.io/service-account.name": "myserviceaccount"
}
},
"type": "kubernetes.io/service-account-token"
}
kubectl create -f ./secret.json
kubectl describe secret mysecretname
# 删除服务账号
kubectl delete secret mysecretname
注意:
上面的实验,myserviceaccount的serviceAccount必须提前存在???
[root@server apis]# kubectl get pods hello-world-86cddf59d5-9b8zz -o yaml
spec
serviceAccount: default
serviceAccountName: default
containers:
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-qc6t2
readOnly: true
spec.automountServiceAccountToken: false
来取消,但是必须用sepc.serviceAccountName: build-rebot
来设置一个[root@server apis]# kubectl get serviceAccounts
NAME SECRETS AGE
default 1 16d
$ cat > /tmp/serviceaccount.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
$ kubectl create -f /tmp/serviceaccount.yaml
serviceaccount "build-robot" created
[root@server apis]# kubectl get serviceaccounts/build-robot -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2018-12-24T07:01:20Z
name: build-robot
namespace: default
resourceVersion: "2046916"
selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
uid: b7424d09-0749-11e9-92e8-005056b6756e
secrets:
- name: build-robot-token-h2h97
# 删除
$ kubectl delete serviceaccount/build-robot
[root@server apis]# kubectl describe serviceaccounts/build-robot
Name: build-robot
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: build-robot-token-h2h97
Tokens: build-robot-token-h2h97
Events: <none>
重点:就是一个Tokens,访问apiServer的认证信息
[root@server apis]# kubectl get secret build-robot-token-h2h97 -o yaml
apiVersion: v1
data:
ca.crt:
......
namespace: ZGVmYXVsdA==
token:
......
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: build-robot
kubernetes.io/service-account.uid: b7424d09-0749-11e9-92e8-005056b6756e
creationTimestamp: 2018-12-24T07:01:20Z
name: build-robot-token-h2h97
namespace: default
resourceVersion: "2046915"
selfLink: /api/v1/namespaces/default/secrets/build-robot-token-h2h97
uid: b743aba5-0749-11e9-92e8-005056b6756e
type: kubernetes.io/service-account-token
重点:
- ca.crt
- 这个是API Server的CA公钥证书,用于Pod中的Process对API Server的服务端数字证书进行校验时使用的;
- namespace
- 这个就是Secret所在namespace的值的base64编码,echo -n "default"|base64的输出
- token
$ cat > /tmp/build-robot-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
$ kubectl create -f /tmp/build-robot-secret.yaml
secret "build-robot-secret" created
[root@server apis]# kubectl get serviceaccounts/build-robot -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2018-12-24T07:01:20Z
name: build-robot
namespace: default
resourceVersion: "2046916"
selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
uid: b7424d09-0749-11e9-92e8-005056b6756e
secrets:
- name: build-robot-token-h2h97
[root@server apis]# kubectl get secrets
NAME TYPE DATA AGE
build-robot-secret kubernetes.io/service-account-token 3 6m
build-robot-token-h2h97 kubernetes.io/service-account-token 3 17m
default-token-qc6t2 kubernetes.io/service-account-token 3 16d
[root@server apis]# kubectl describe secret build-robot-token-h2h97
......
这样做是为了不用每个使用私有仓库的 pod 进行操作进时指定ImagePullSecret,默认会继承serviceAccount的对应值
创建一个secret:
$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
$ kubectl get secrets myregistrykey
NAME TYPE DATA AGE
myregistrykey kubernetes.io/.dockerconfigjson 1 1d
修改 namespace 中的默认 service account 使用该 secret 作为 imagePullSecret
$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
然后所有当前 namespace 中新创建的 pod 的 spec 中都会增加如下内容
spec:
imagePullSecrets:
- name: myregistrykey
基于属性的访问控制(Attribute-based access control - ABAC)
当策略有更新时需要重启apiServer
apiVersion
,字符串类型: 有效值为"abac.authorization.kubernetes.io/v1beta1",允许版本控制和转换策略格式。kind
,字符串类型: 有效值为 “Policy”,允许版本控制和转换策略格式。spec
配置为具有以下映射的属性:
user
,字符串类型; 来自 --token-auth-file
的用户字符串,如果你指定user
,它必须与验证用户的用户名匹配。group
,字符串类型; 如果指定group
,它必须与经过身份验证的用户的一个组匹配,system:authenticated
匹配所有经过身份验证的请求。system:unauthenticated
匹配所有未经过身份验证的请求。apiGroup
,字符串类型; 一个 API 组。
extensions
*
匹配所有 API 组。namespace
,字符串类型; 一个命名空间。
kube-system
*
匹配所有资源请求。resource
,字符串类型; 资源类型。
pods
*
匹配所有资源请求。nonResourcePath
,字符串类型; 非资源请求路径。
/version
或/apis
*
匹配所有非资源请求。/foo/*
匹配/foo/
的所有子路径。readonly
,键入 boolean,如果为 true,则表示该策略仅适用于 get,list 和 watch 操作。{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "alice",
"namespace": "*",
"resource": "*",
"apiGroup": "*"
}
}
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "kubelet",
"namespace": "*",
"resource": "pods",
"readonly": true
}
}
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "kubelet",
"namespace": "*",
"resource": "events"
}
}
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "bob",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"group": "system:authenticated",
"readonly": true,
"nonResourcePath": "*"
}
}
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"group": "system:unauthenticated",
"readonly": true,
"nonResourcePath": "*"
}
}
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
# 鉴于ClusterRole是集群范围对象,所以这里不需要定义"namespace"字段
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
# 以下角色绑定定义将允许用户"jane"从"default"名字空间中读取pod。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
# 以下角色绑定允许用户"dave"读取"development"名字空间中的secret。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets
namespace: development # 这里表明仅授权读取"development"名字空间中的资源。
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
# 以下`ClusterRoleBinding`对象允许在用户组"manager"中的任何用户都可以读取集群中任何名字空间中的secret。
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
子资源:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
,在此,”pods”是名字空间资源,而”log”是pods的子资源。kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
资源名称列表:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["configmap"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
一些角色定义的例子
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch", "extensions"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"] # 在非资源URL中,'*'代表后缀通配符
verbs: ["get", "post"]
角色绑定的例子:
subjects:
- kind: User
name: "[email protected]"
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
subjects:
- kind: Group
name: system:serviceaccounts:qa
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
kubectl create rolebinding
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
kubectl create clusterrolebinding
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace
# 下面的例子将在”my-namespace”名字空间内授予”default”服务账号只读权限:
kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace
# 目前,许多[加载项(addon)](/ docs / concepts / cluster-administration / addons /)作为”kube-system”名字空间中的”default”服务帐户运行。 要允许这些加载项使用超级用户访问权限,请将cluster-admin权限授予”kube-system”名字空间中的”default”服务帐户。
# 注意:启用上述操作意味着”kube-system”名字空间将包含允许超级用户访问API的秘钥。
kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
# 下面的例子将授予”my-namespace”名字空间中的所有服务账户只读权限:
kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace
# 下面的例子将所有名字空间中的只读权限授予集群中的所有服务账户:
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts
# 警告:这种做法将允许任何具有读取权限的用户访问secret或者通过创建一个容器的方式来访问超级用户的凭据。
kubectl create clusterrolebinding serviceaccounts-cluster-admin --clusterrole=cluster-admin --group=system:serviceaccounts
```shell
# 警告:以下政策略允许所有服务帐户作为集群管理员。 运行在容器中的任何应用程序都会自动接收服务帐户凭据,并且可以对API执行任何操作,包括查看secret和修改权限。
# 因此,并不推荐使用这种策略。
kubectl create clusterrolebinding permissive-binding \
--clusterrole=cluster-admin \
--user=admin \
--user=kubelet \
--group=system:serviceaccounts
```
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds