kubernetes支持PodSecurityPolicy
by 伊布
PodSecurityPolicy是什么
PodSecurityPolicy是一种用来控制Pod安全相关配置的全局资源。
在开启RBAC的kubernetes集群上,如果允许用户使用kubectl,那么必须开启PodSecurityPolicy,否则用户可能会使用一些特权资源(例如privileged,hostNetwork,hostPath等等),影响node机器的稳定性。
开启PSP后,用户只能使用管理员允许的资源。PSP支持以下方面(具体请见官网):
Control Aspect | Field Names |
---|---|
Running of privileged containers | privileged |
Usage of host namespaces | hostPID , hostIPC |
Usage of host networking and ports | hostNetwork , hostPorts |
Usage of volume types | volumes |
Usage of the host filesystem | allowedHostPaths |
White list of Flexvolume drivers | allowedFlexVolumes |
Allocating an FSGroup that owns the pod’s volumes | fsGroup |
Requiring the use of a read only root file system | readOnlyRootFilesystem |
The user and group IDs of the container | runAsUser , runAsGroup , supplementalGroups |
Restricting escalation to root privileges | allowPrivilegeEscalation , defaultAllowPrivilegeEscalation |
Linux capabilities | defaultAddCapabilities , requiredDropCapabilities , allowedCapabilities |
The SELinux context of the container | seLinux |
The Allowed Proc Mount types for the container | allowedProcMountTypes |
The AppArmor profile used by containers | annotations |
The seccomp profile used by containers | annotations |
The sysctl profile used by containers | annotations |
开启PodSecurityPolicy
开启很简单,配置apiserver增加admission plugin PodSecurityPolicy即可。
--enable-admission-plugins=NodeRestriction,PodSecurityPolicy
修改后apiserver会重启。由于这里没有配置任何Policy,所以重启后PSP会阻止所有Pod的创建。
由于PSP API policy/v1beta1/podsecuritypolicy
与admission controller是独立的,对于现存的集群,建议先配置psp以及授权,再开启PS。
授权策略
Policy本身并不会产生实际作用,需要将其与用户或者serviceaccount绑定才可以完成授权。
绑定方法:创建Role,该Role可以use 该PodSecurityPolicy,然后将该role与用户或者serviceaccount绑定。
示例
下面举个例子。
1. 创建Policy
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: example
spec:
privileged: false # Don't allow privileged pods!
# The rest fills in some required fields.
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
2. 创建serviceaccount
kubectl create namespace hellobaby
kubectl create sa fake-user
alias kubectl-admin='kubectl -n hellobaby'
alias kubectl-user='kubectl --as=system:serviceaccount:hellobaby:fake-user -n hellobaby'
3. 创建Pod
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
此时使用kubectl-user创建Pod会提示Error from server (Forbidden): error when creating "STDIN": pods "nginx" is forbidden: unable to validate against any pod security policy: []
,因为sa fake-user并没有psp example的权限,可以通过auth检查下。
kubectl-user auth can-i use podsecuritypolicy/example
所以下面需要创建role、rolebinding。
4. 创建带psp example use权限的role,并与sa hellobaby绑定
kubectl-admin create role psp:unprivileged --verb=use \
--resource=podsecuritypolicy \
--resource-name=example
kubectl-admin create rolebinding fake-user:psp:unprivileged \
--role=psp:unprivileged \
--serviceaccount=hellobaby:fake-user
rolebinding "fake-user:psp:unprivileged" created
现在再去创建上述Pod nginx,就可以创建了,而且可以创建成功,因为这个Pod没有请求任何特殊权限,是个乖孩子。
加上特权字段,再创建呢?
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
securityContext:
privileged: true
kubectl-user会返回Error from server (Forbidden): error when creating "STDIN": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
提示很清楚:Privileged containers are not allowed
。
PodSecurityPolicy 生效了。
5. 非sa直接创建的Pod
大部分情况我们并不会直接创建Pod,而是会创建Deployment。试试看。
$ kubectl-user run nginx --image=nginx
deployment "nginx" created
$ kubectl-user get pods
No resources found.
$ kubectl-user get events | head -n 2
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
1m 2m 15 nginx-7774d79b5 ReplicaSet Warning FailedCreate replicaset-controller Error creating: pods "nginx-7774d79b5-" is forbidden: no providers available to validate pod request
提示没有providers用来检查Pod请求,可是我们已经给sa hellobaby:fake-user授权了呀。
原因是,这个Pod是replicaset controller创建的,默认kubectl run的形式创建的应用指定的spec.template.spec.serviceAccount
和spec.template.spec.serviceAccountName
都是default,而上面我们RBAC绑定的SA是hellobaby:fake-user
,并不是hellobaby:default
。
怎么解决呢?官网给的方法是,再给hellobaby:default
绑定 role psp:unprivileged
。的确这样可以解决问题,但这个解决方法并不合理。
我们知道,一个namespace下是可以创建多个serviceaccount的,如果我需要给同一namespace下不同是sa授予不同的psp,那么应该如何给sa default授权呢?显然就无法绑定了。
事实上,我认为官网的这个例子并不合理,而且kubectl run
命令也要被取消了。
更好的做法是创建一个deployment,并且设置其spec.template.spec.serviceAccount
和spec.template.spec.serviceAccountName
为实际的sa。
下面是一个实际的例子。
metadata:
labels:
run: nginx-test
name: nginx-test
namespace: hellobaby
spec:
replicas: 1
selector:
matchLabels:
run: nginx-test
template:
metadata:
labels:
run: nginx-test
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx-test
#securityContext:
# privileged: true
dnsPolicy: ClusterFirst
restartPolicy: Always
serviceAccount: fake-user
serviceAccountName: fake-user
此时replicaset controller会使用 sa hellobaby:fake-user
创建pod,由于前面已经为该sa绑定了psp example,所以可以成功创建Pod。
Ref:
Subscribe via RSS