kubernetes中其他控制器之PodSecurityPolicy
PodSecurityPolicy是集群级别的Pod安全策略,自动为集群中的Pod和Volume设置Security Context。
Admission Controller(准入控制器)拦截对 kube-apiserver 的请求,拦截发生在请求的对象被持久化之前,但是在请求被验证和授权之后。这样我们就可以查看请求对象的来源,并验证需要的内容是否正确。通过将它们添加到 kube-apiserver 的--enable-admission-plugins参数中来启用准入控制器。所以如果我们要使用PSP,我们就需要在kube-apiserver中添加起参数,如下:
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodSecurityPolicy
其他插件是kubernetes官方推荐的插件。
然后重启kube-apiserver:
# systemctl daemon-reload# systemctl restart kube-apiserver
这时候就已经启动了PSP控制器,如果我们现在创建Pod试试:
apiVersion: apps/v1kind: Deploymentmetadata: name: nginxspec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent
然后我们kubectl get pod的时候发现并没有pod。我们再查看deploy的状态,如下:
# kubectl get deployments.NAME READY UP-TO-DATE AVAILABLE AGEnginx 0/1 0 0 117s# kubectl get replicasets.NAME DESIRED CURRENT READY AGEnginx-55fc968d9 1 0 0 2m17s
我们看到replicaset和deploy都创建成功了,但是replicaset并没有创建pod,这是因为我们集群现在缺少安全策略,所以创建新的Pod不会成功,这时我们就需要使用ServiceAccount。
正常情况下,我们并不会直接创建Pod,都是通过其他控制器比如Deployment、StatefulSet等来创建Pod。我们现在要使用PSP,需要配置kube-controller-manager来为其包含的每个控制器单独使用ServiceAccount,我们可以通过以下参数来添加,如下:
--use-service-account-credentials=true
然后重启controller-manager:
# systemctl daemon-reload# systemctl restart kube-controller-manager
然后kubenetes就会自动生成如下一些SA,这些SA就指定了哪个控制器可以解析哪些策略:
# kubectl get serviceaccount -n kube-system | egrep -o '[A-Za-z0-9-]+-controller'attachdetach-controllercertificate-controllerclusterrole-aggregation-controllercronjob-controllerdaemon-set-controllerdeployment-controllerdisruption-controllerendpoint-controllerexpand-controllerjob-controllernamespace-controllernode-controllerpv-protection-controllerpvc-protection-controllerreplicaset-controllerreplication-controllerresourcequota-controllerservice-account-controllerservice-controllerstatefulset-controllertraefik-ingress-controllerttl-controller
PSP提供一种声明式的方式,用于表达运行的用户和ServiceAccount在我们集群中创建的内容。其主要的策略有:
在上面的示例中,我们需要两个策略:
1、提供限制访问的默认策略,保证使用特权设置无法创建Pod;
2、提升许可策略,允许将特权设置用于某些Pod,比如允许在特定命名空间下创建Pod;
首先,创建一个默认策略:
psp-restrictive.yaml
apiVersion: policy/v1beta1kind: PodSecurityPolicymetadata: name: restrictivespec: privileged: false hostNetwork: false allowPrivilegeEscalation: false defaultAllowPrivilegeEscalation: false hostPID: false hostIPC: false runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny volumes: - 'configMap' - 'downwardAPI' - 'emptyDir' - 'persistentVolumeClaim' - 'secret' - 'projected' allowedCapabilities: - '*'
然后直接创建这个PSP对象:
# kubectl apply -f psp-restrictive.yamlpodsecuritypolicy.policy/restrictive created# kubectl get pspNAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMESrestrictive false * RunAsAny RunAsAny RunAsAny RunAsAny false configMap,downwardAPI,emptyDir,persistentVolumeClaim,secret,projected
其次,创建一个提升策略,用于那些需要提升权限的Pod,比如kube-proxy,它就需要hostNetwork权限:
psp-permissive.yaml
apiVersion: policy/v1beta1kind: PodSecurityPolicymetadata: name: permissivespec: privileged: true hostNetwork: true hostIPC: true hostPID: true seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny hostPorts: - min: 0 max: 65535 volumes: - '*'
然后创建这个PSP对象:
# kubectl apply -f psp-permissive.yamlpodsecuritypolicy.policy/permissive created# kubectl get pspNAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMESpermissive true RunAsAny RunAsAny RunAsAny RunAsAny false *restrictive false * RunAsAny RunAsAny RunAsAny RunAsAny false configMap,downwardAPI,emptyDir,persistentVolumeClaim,secret,projected
但是仅仅部署了这两个策略是不够的,我们RBAC进行授权,不然我们的Pod还是不能创建成功。RBAC确定一个ServiceAccount可以使用的策略,如果使用ClusterRoleBinding可以为ServiceAccount提供限制性策略(restrictive)的访问,如果使用RoleBinding可以为SeriveAccount提供虚空策略的访问。
首先创建允许使用restrictive策略的ClusterRole,然后再创建一个ClusterRoleBinding将所有控制器的ServiceAccount进行绑定:
psp-restrictive-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: psp-restrictiverules:- apiGroups: - extensions resources: - podsecruritypolicies resourceNames: - restrictive verbs: - use---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: psp-defaultsubjects:- kind: Group name: system:serviceaccounts namespace: kube-systemroleRef: kind: ClusterRole name: psp-restrictive apiGroup: rbac.authorization.k8s.io
然后创建RBAC资源对象:
# kubectl apply -f psp-restrictive-rbac.yamlclusterrole.rbac.authorization.k8s.io/psp-restrictive createdclusterrolebinding.rbac.authorization.k8s.io/psp-default created
然后我们可以看到外面刚开始创建的Pod现在可以创建了:
# kubectl get podNAME READY STATUS RESTARTS AGEnginx-55fc968d9-qn2vr 1/1 Running 0 17m
但是如果我们现在给这个Deployment清单加一个hostNetwork=true这个特权,观察Pod是否能够创:
nginx-deploy.yaml
apiVersion: apps/v1kind: Deploymentmetadata: name: nginxspec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent hostNetwork: true
然后我们再次创建这个Deployment:
# kubectl apply -f nginx-deploy.yamldeployment.apps/nginx created# kubectl get podNAME READY STATUS RESTARTS AGE# kubectl get deployments.NAME READY UP-TO-DATE AVAILABLE AGEnginx 0/1 0 0 12s# kubectl get replicasets.NAME DESIRED CURRENT READY AGEnginx-5cd65fd4c6 1 0 0 18s
我们可以看到Pod并未被创建,我们describe一个replicaset,发现如下日志:
# kubectl describe rs nginx-5cd65fd4c6......Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedCreate 41s (x16 over 3m24s) replicaset-controller Error creating: pods "nginx-5cd65fd4c6-" is forbidden: unable to validate against any pod security policy: [spec.securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used]
提示我们hostNetwork不允许被使用。
但是在某些情况下,我们需要在某个命名空间下使用特权,这时候我们就可以创建一个允许使用特权的ClusterRole,但是这里我们为特定ServiceAccount设置RoleBinding,如下:
psp-permissive-rbac.yaml
kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata: name: psp-permissiverules:- apiGroups: - extensions resources: - podsecuritypolicies resourceNames: - permissive verbs: - use---apiVersion: rbac.authorization.k8s.io/v1beta1kind: RoleBindingmetadata: name: psp-permissive namespace: kube-systemroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: psp-permissivesubjects:- kind: ServiceAccount name: daemon-set-controller namespace: kube-system- kind: ServiceAccount name: replicaset-controller namespace: kube-system- kind: ServiceAccount name: job-controller namespace: kube-system
上面定义了对kube-system中的daemonset,replicaset,job拥有特权创建Pod。
然后我们创建RBAC资源清单:
# kubectl apply -f psp-permissive-rbac.yamlclusterrole.rbac.authorization.k8s.io/psp-permissive createdrolebinding.rbac.authorization.k8s.io/psp-permissive created
现在我们定义一个测试Deployment:
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx namespace: kube-systemspec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent hostNetwork: true
然后创建资源对象:
# kubectl apply -f nginx-deploy.yamldeployment.apps/nginx created[root@ecs-5704-0003 kubernetes]# kubectl get pod -n kube-systemNAME READY STATUS RESTARTS AGE......nginx-5cd65fd4c6-7pn9z 1/1 Running 0 4s
然后我们可以看到Pod可以正常被创建。
另外还有一种特殊的需求,就是在某个命令空间下只有某个应用可以使用特权,那么针对这类应用就需要单独创建一个SA,然后和permissive策略镜像RoleBinding了,如下:
(1)、创建可以使用特权的SA
# kubectl create serviceaccount specialsaserviceaccount/specialsa created
(2)、创建RoleBinding
specialsa-psp.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1kind: RoleBindingmetadata: name: specialsa-psp-permissive namespace: defaultroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: psp-permissivesubjects:- kind: ServiceAccount name: specialsa namespace: default
然后创建上面的RoleBinding对象:
# kubectl apply -f specialsa-psp.yamlrolebinding.rbac.authorization.k8s.io/specialsa-psp-permissive created
然后创建一个测试的Deployment:
ng-deploy.yaml
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-hostnetwork-deploy namespace: default labels: app: nginxspec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent hostNetwork: true serviceAccount: specialsa # 注意这里使用的sa的权限绑定
然后创建资源对象:
# kubectl apply -f ng-deploy.yamldeployment.apps/nginx-hostnetwork-deploy created# kubectl get podNAME READY STATUS RESTARTS AGEnginx-hostnetwork-deploy-7b65cf7bbd-g5wl5 1/1 Running 0 2s
然后可以发现在default命名空间下可以创建拥有特权的Pod了。
完
©著作权归作者所有:来自51CTO博客作者mb5ff97f7b72697的原创作品,如需转载,请注明出处,否则将追究法律责任
更多相关文章
- 在kubernetes中用Glusterfs做持久化存储
- kubernetes中用NFS做后端存储支不支持PVC扩容?
- 使用Operator部署Prometheus
- Weblogic中间件创建文件权限问题解决
- ListView适配器 Activity案例
- Android 开发后台
- Postgresql管理_创建数据库
- 初次撩MYCAT小姐姐
- 15、华为 华三中小型企业网络架构搭建 【防火墙篇之路由部署(根据