Kubernetes PodSecurityPolicy怎么创建

54次阅读
没有评论

共计 10043 个字符,预计需要花费 26 分钟才能阅读完成。

这篇文章主要讲解了“Kubernetes PodSecurityPolicy 怎么创建”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“Kubernetes PodSecurityPolicy 怎么创建”吧!

PodSecurityPolicy 介绍

默认情况下,Kubernetes 允许创建一个有特权容器的 Pod,这些容器很可能会威胁系统安全,而 PodSecurityPolicy(PSP)则通过确保请求者有权限按配置来创建 Pod,从而来保护集群免受特权 Pod 的影响。

PodSecurityPolicy 是集群级别的资源,它能够控制 Pod 运行的行为,以及它具有访问什么的能力。PodSecurityPolicy 对象定义了一组条件,指示 Pod 必须按系统所能接受条件运行。

以下是 PodSecurityPolicy 可以控制的内容:

PodSecurityPolicy 是 Kubernetes API 对象,你可以在不对 Kubernetes 进行任何修改的情况下创建它们,但是,默认情况下不会强制执行我们创建的一些策略,我们需要一个准入控制器、kube-controller-manager 配置以及 RBAC 权限配置,下面我们就来对这些配置进行一一说明。

Admission Controller

编辑 /etc/kubernetes/manifest/kube-apiserver.yaml,添加 PodSecurityPolicy,启用 PSP 的控制器。

- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy

但是此时我们集群中现在缺少一些安全策略,那么新的 Pod 创建就会失败。通过下面文件创建 Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deploy
 namespace: default
 labels:
 app: nginx
spec:
 replicas: 1
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx:1.15.4

但是 replicaset 控制器却并没有创建 Pod,这个时候就需要使用 ServiceAccount 了。

#kubectl describe rs nginx-hostnetwork-deploy-76c46fdb6 
Name: nginx-hostnetwork-deploy-76c46fdb6
Namespace: default
Selector: app=nginx,pod-template-hash=76c46fdb6
Labels: app=nginx
 pod-template-hash=76c46fdb6
Annotations: deployment.kubernetes.io/desired-replicas: 1
 deployment.kubernetes.io/max-replicas: 2
 deployment.kubernetes.io/revision: 1
Controlled By: Deployment/nginx-hostnetwork-deploy
Replicas: 0 current / 1 desired
Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
 Labels: app=nginx
 pod-template-hash=76c46fdb6
 Containers:
 nginx:
 Image: nginx:1.15.4
 Port:  none 
 Host Port:  none 
 Environment:  none 
 Mounts:  none 
 Volumes:  none 
Conditions:
 Type Status Reason
 ---- ------ ------
 ReplicaFailure True FailedCreate
Events:
 Type Reason Age From Message
 ---- ------ ---- ---- -------
 Warning FailedCreate 1s (x12 over 11s) replicaset-controller Error creating: pods  nginx-hostnetwork-deploy-76c46fdb6-  is forbidden: PodSecurityPolicy: no providers available to validate pod request

ServiceAccount Controller Manager

一般来说用户很少会直接创建 Pod,通常是通过 Deployment、StatefulSet、Job 或者 DasemonSet 这些控制器来创建 Pod 的,我们这里需要配置 kube-controller-manager 来为其包含的每个控制器使用单独的 ServiceAccount,我们可以通过在其命令启动参数中添加如下标志来实现。编辑 /etc/kubernetes/manifest/kube-controller-manager.yaml,添加:

--use-service-account-credentials=true

一般情况下上面这个标志在大多数安装工具(如 kubeadm)中都是默认开启的,所以不需要单独配置了。

当 kube-controller-manager 开启上面的标志后,它将使用由 Kubernetes 自动生成的以下 ServiceAccount:

# kubectl get serviceaccount -n kube-system | egrep -o  [A-Za-z0-9-]+-controller 
attachdetach-controller
calico-kube-controller
certificate-controller
clusterrole-aggregation-controller
cronjob-controller
daemon-set-controller
deployment-controller
disruption-controller
endpoint-controller
expand-controller
job-controller
namespace-controller
node-controller
pv-protection-controller
pvc-protection-controller
replicaset-controller
replication-controller
resourcequota-controller
service-account-controller
service-controller
statefulset-controller
ttl-controller

这些 ServiceAccount 指定了哪个控制器可以解析哪些策略的配置。

PodSecurityPolicy

在我们当前示例中,我们将创建 2 个策略,第一个是提供限制访问的“默认”策略,保证使用某些特权设置时(例如使用 hostNetwork)无法创建 Pod。第二种是一个“提升”的许可策略,允许将特权设置用于某些 Pod,例如在 kube-system 命名空间下面创建的 Pod 的权限。

首先,创建一个限制性策略,作为默认策略:(psp-restrictive.yaml)

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
 name: restrictive
spec:
 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:
 -  *

虽然限制性的访问对于大多数 Pod 创建是足够的了,但是对于需要提升访问权限的 Pod 来说,就需要一些允许策略了,例如,kube-proxy 就需要启用 hostNetwork,这就需要创建一个用于提升创建权限的许可策略了:(psp-permissive.yaml)

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
 name: permissive
spec:
 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:
 -  *

RBAC

现在配置都已经就绪了,但是我们需要引入到 Kubernetes 授权,这样才可以确定请求 Pod 创建的用户或者 ServiceAccount 是否解决了限制性或许可性策略,这就需要用到 RBAC 了。

在我们启用 Pod 安全策略的时候,可能会对 RBAC 引起混淆。它确定了一个账户可以使用的策略,使用集群范围的 ClusterRoleBinding 可以为 ServiceAccount(例如 replicaset-controller)提供对限制性策略的访问权限。使用命名空间范围的 RoleBinding,可以启用对许可策略的访问,这样可以在特定的命名空间(如 kube-system)中进行操作。下面演示了 daemonset-controller 创建 kube-proxy Pod 的解析路径:

首先创建允许使用 restrictive 策略的 ClusterRole。然后创建一个 ClusterRoleBinding,将 restrictive 策略和系统中 kube-system 命名空间内所有的控制器 ServiceAccount 进行绑定:(psp-restrictive-rbac.yaml)

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: psp-restrictive
rules:
- apiGroups:
 - extensions
 resources:
 - podsecuritypolicies
 resourceNames:
 - restrictive
 verbs:
 - use
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: psp-default
subjects:
- kind: Group
 name: system:serviceaccounts
 namespace: kube-system
roleRef:
 kind: ClusterRole
 name: psp-restrictive
 apiGroup: rbac.authorization.k8s.io

然后现在我们再重新创建上面我们的定义的 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deploy
 namespace: default
 labels:
 app: nginx
spec:
 replicas: 1
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx:1.15.4

创建完成后同样查看下 default 命名空间下面我们创建的一些资源对象:

# kubectl get po,rs,deploy -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-deploy-77f7d4c6b4-njfdl 1/1 Running 0 13s
NAME DESIRED CURRENT READY AGE
replicaset.extensions/nginx-deploy-77f7d4c6b4 1 1 1 13s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nginx-deploy 1/1 1 1 13s

我们可以看到 Pods 被成功创建了,但是,如果我们尝试做一些策略不允许的事情,正常来说就应该被拒绝了。现在我们在 nginx-deploy 基础上添加 hostNetwork: true 来使用 hostNetwork 这个特权:(nginx-hostnetwork.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-hostnetwork-deploy
 namespace: default
 labels:
 app: nginx
spec:
 replicas: 1
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx:1.15.4
 hostNetwork: true #  注意添加 hostNetwork

创建完成后同样查看 default 这个命名空间下面的一些资源对象:

# kubectl get po,rs,deploy -l app=nginx
NAME READY STATUS RESTARTS AGE
NAME DESIRED CURRENT READY AGE
replicaset.extensions/nginx-hostnetwork-deploy-74c8fbd687 1 0 0 44s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nginx-hostnetwork-deploy 0/1 0 0 44s

现在我们发现 ReplicaSet 又没有创建 Pod 了,可以使用 kubectl describe 命令去查看这里我们创建的 ReplicaSet 资源对象来了解更多的信息:

# kubectl describe rs nginx-hostnetwork-deploy-74c8fbd687
Name: nginx-hostnetwork-deploy-74c8fbd687
......
Events:
 Type Reason Age From Message
 ---- ------ ---- ---- -------
 Warning FailedCreate 80s (x15 over 2m42s) replicaset-controller Error creating: pods  nginx-hostnetwork-deploy-74c8fbd687-  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 不被允许使用,但是在某些情况下,我们的确有在某个命名空间(比如 kube-system)下面创建使用 hostNetwork 的 Pod,这里就需要我们创建一个允许执行的 ClusterRole,然后为特定的命名空间创建一个 RoleBinding,将这里的 ClusterRole 和相关的控制器 ServiceAccount 进行绑定:(psp-permissive-rbac.yaml)

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: psp-permissive
rules:
- apiGroups:
 - extensions
 resources:
 - podsecuritypolicies
 resourceNames:
 - permissive
 verbs:
 - use
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
 name: psp-permissive
 namespace: kube-system
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: psp-permissive
subjects:
- 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 这个命名空间下面使用 hostNetwork 来创建 Pod 了,将上面的 nginx 资源清单更改成 kube-system 命名空间下面:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-hostnetwork-deploy
 namespace: kube-system
 labels:
 app: nginx
spec:
 replicas: 1
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx:1.15.4
 hostNetwork: true

创建完成后同样查看下对应的资源对象创建情况:

# kubectl get po,rs,deploy -n kube-system -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-hostnetwork-deploy-74c8fbd687-7x8px 1/1 Running 0 2m1s
NAME DESIRED CURRENT READY AGE
replicaset.extensions/nginx-hostnetwork-deploy-74c8fbd687 1 1 1 2m1s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nginx-hostnetwork-deploy 1/1 1 1 2m1s

现在我们可以看到 Pod 在 kube-system 这个命名空间下面创建成功了。

特定应用的 ServiceAccount

如果我们现在有这样的一个需求,在某个命名空间下面要强制执行我们创建的 restrictive(限制性)策略,但是这个命名空间下面的某个应用需要使用 permissive(许可)策略,那么应该怎么办呢?在当前模型中,我们只有集群级别和命名空间级别的解析。为了给某个应用提供单独的许可策略,我们可以为应用的 ServiceAccount 提供使用 permissive 这个 ClusterRole 的能力。

比如,还是在默认的命名空间下面创建一个名为 specialsa 的 ServiceAccount:

kubectl create serviceaccount specialsa

然后创建一个 RoleBinding 将 specialsa 绑定到上面的 psp-permissive 这个 CluterRole 上:(specialsa-psp.yaml)

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
 name: specialsa-psp-permissive
 namespace: default
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: psp-permissive
subjects:
- kind: ServiceAccount
 name: specialsa
 namespace: default

然后为我们上面的 Deployment 添加上 serviceAccount 属性:(nginx-hostnetwork-sa.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-hostnetwork-deploy
 namespace: default
 labels:
 app: nginx
spec:
 replicas: 1
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 containers:
 - name: nginx
 image: nginx:1.15.4
 hostNetwork: true
 serviceAccount: specialsa #  注意这里使用的 sa 的权限绑定 

这个时候我们查看 default 这个命名空间下面带有 hostNetwork 的 Pod 也创建成功了:

# kubectl get po,rs,deploy -l app=nginx
NAME READY STATUS RESTARTS AGE
pod/nginx-hostnetwork-deploy-6c85dfbf95-hqt8j 1/1 Running 0 65s
NAME DESIRED CURRENT READY AGE
replicaset.extensions/nginx-hostnetwork-deploy-6c85dfbf95 1 1 1 65s
replicaset.extensions/nginx-hostnetwork-deploy-74c8fbd687 0 0 0 31m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nginx-hostnetwork-deploy 1/1 1 1 31m

感谢各位的阅读,以上就是“Kubernetes PodSecurityPolicy 怎么创建”的内容了,经过本文的学习后,相信大家对 Kubernetes PodSecurityPolicy 怎么创建这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计10043字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)