Kubernetes 多租户:Pod 安全策略
默认情况下,Kubernetes 允许创建一个有特权容器的 Pod,这些容器很可能会危机系统安全,而 Pod 安全策略(PSP)则通过确保请求者有权限按配置来创建 Pod,从而来保护集群免受特权 Pod 的影响。
PodSecurityPolicy 是 Kubernetes API 对象,你可以在不对 Kubernetes 进行任何修改的情况下创建它们,但是,默认情况下不会强制执行我们创建的一些策略,我们需要一个准入控制器、kube-controller-manager 配置以及 RBAC 权限配置,下面我们就来对这些配置进行一一说明。
Admission Controller
Admission Controller(准入控制器)拦截对 kube-apiserver 的请求,拦截发生在请求的对象被持久化之前,但是在请求被验证和授权之后。这样我们就可以查看请求对象的来源,并验证需要的内容是否正确。通过将它们添加到 kube-apiserver 的 --enable-admission-plugins 参数中来启用准入控制器。在1.10版本之前,使用现在已经弃用的 --admision-control 参数,另外需要注意准入控制器的顺序很重要。
将 PodSecurityPolicy 添加到 kube-apiserver 上的 --enabled-admission-plugins 参数中,然后重启 kube-apiserver:
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodSecurityPolicy
其他插件来自 Kubernetes 文档中推荐的一些插件列表。
PodSecurityPolicy 已经添加到上面的列表中了,现在 PSP 的控制器已经启用了,但是我们集群中现在缺少一些安全策略,那么新的 Pod 创建就会失败。
比如现在我们创建一个 Nginx 的 Deployment,YAML 文件内容如下所示:(nginx.yaml)
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
然后直接创建上面的 Deployment:
$ kubectl apply -f nginx.yaml
deployment.apps/nginx-deploy created
我们可以看到 Deployment 已经创建成功了,现在检查下 default 命名空间下面的 pod、replicaset、deployment:
$ kubectl get po,rs,deploy -l app=nginx
NAME READY STATUS RESTARTS AGE
NAME DESIRED CURRENT READY AGE
replicaset.extensions/nginx-deploy-77f7d4c6b4 1 0 0 40s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nginx-deploy 0/1 0 0 40s
可以看到 replicaset 和 deployment 都创建成功了,但是 replicaset 控制器却并没有创建 Pod,这个时候就需要使用 PodSecurityPolicy 对象和 ServiceAccount 了。
策略
PodSecurityPolicy 对象提供了一种声明式的方式,用于表达我们运行用户和 ServiceAccount 在我们的集群中创建的内容。我们可以查看策略文档来了解如何设置。在我们当前示例中,我们来创建两个策略,第一个是提供限制访问的“默认”策略,保证使用特权设置(例如使用 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:
- '*'
直接创建上面的 psp 对象:
$ kubectl apply -f psp-restrictive.yaml
podsecuritypolicy.policy/restrictive configured
虽然限制性的访问对于大多数 Pod 创建是足够的了,但是对于需要提升访问权限的 Pod 来说,就需要一些允许策略了,例如,kube-proxy 就需要启用 hostNetwork:
$ kubectl get pods -n kube-system -l k8s-app=kube-proxy
NAME READY STATUS RESTARTS AGE
kube-proxy-4z4vf 1/1 Running 0 18d
$ kubectl get pods -n kube-system kube-proxy-4z4vf -o yaml |grep hostNetwork
hostNetwork: true
这就需要创建一个用于提升创建权限的许可策略了:(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:
- '*'
同样直接创建上面的 psp 对象:
$ kubectl apply -f psp-permissive.yaml
podsecuritypolicy.policy/permissive configured
$ kubectl get psp
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES
permissive true RunAsAny RunAsAny RunAsAny RunAsAny false *
restrictive false * RunAsAny RunAsAny RunAsAny RunAsAny false configMap,downwardAPI,emptyDir,persistentVolumeClaim,secret,projected
现在配置都已经就绪了,但是我们需要引入到 Kubernetes 授权,这样才可以确定请求 Pod 创建的用户或者 ServiceAccount 是否解决了限制性或许可性策略,这就需要用到 RBAC 了。
RBAC
在我们启用 Pod 安全策略的时候,可能会对 RBAC 引起混淆,它确定了一个账户可以使用的策略,使用集群范围的 ClusterRoleBinding 可以为 ServiceAccount(例如 replicaset-controller)提供对限制性策略的访问权限。使用命名空间范围的 RoleBinding,可以启用对许可策略的访问,这样可以在特定的命名空间(如 kube-system)中进行操作。
我们首先创建允许使用 restrictive 策略的 ClusterRole。然后创建一个 ClusterRoleBinding,将 restrictive 策略和系统中所有的控制器 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
直接创建上面的 RBAC 相关的资源对象:
$ kubectl apply -f psp-restrictive-rbac.yaml
clusterrole.rbac.authorization.k8s.io/psp-restrictive created
clusterrolebinding.rbac.authorization.k8s.io/psp-default created
然后现在我们再重新创建上面我们的定义的 Deployment:
$ kubectl delete -f nginx.yaml
deployment.apps "nginx-deploy" deleted
$ kubectl apply -f nginx.yaml
deployment.apps/nginx-deploy created
创建完成后同样查看下 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 被成功创建了,但是,如果我们尝试做一些策略不允许的事情,正常来说就应该被拒绝了。首先删除上面的这个 Deployment:
$ kubectl delete -f nginx.yaml
deployment.apps "nginx-deploy" deleted
现在我们在 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
hostNetwork: true # 注意添加hostNetwork
然后直接创建上面的 Deployment 这个资源对象:
$ kubectl apply -f nginx-hostnetwork.yaml
deployment.apps/nginx-hostnetwork-deploy created
创建完成后同样查看 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
然后直接创建上面的 RBAC 相关的资源对象:
$ kubectl apply -f psp-permissive-rbac.yaml
clusterrole.rbac.authorization.k8s.io/psp-permissive created
rolebinding.rbac.authorization.k8s.io/psp-permissive created
现在,我们就可以在 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
重新创建这个 Deployment:
$ kubectl apply -f nginx-hostnetwork.yaml
deployment.apps/nginx-hostnetwork-deploy created
创建完成后同样查看下对应的资源对象创建情况:
$ 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 这个命名空间下面创建成功了。
如果我们现在有这样的一个需求,在某个命名空间下面要强制执行我们创建的 restrictive(限制性)策略,但是这个命名空间下面的某个应用需要使用 permissive(许可)策略,那么应该怎么办呢?在当前模型中,我们只有集群级别和命名空间级别的配置。为了给某个应用提供单独的许可策略,我们可以为应用的 ServiceAccount 提供使用 permissive 这个 ClusterRole 的能力。
比如,还是在默认的命名空间下面创建一个名为 specialsa 的 ServiceAccount:
$ kubectl create serviceaccount specialsa
serviceaccount/specialsa created
然后创建一个 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
创建上面的 RoleBinding 对象:
$ kubectl apply -f specialsa-psp.yaml
rolebinding.rbac.authorization.k8s.io/specialsa-psp-permissive created
然后为我们上面的 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
hostNetwork: true
serviceAccount: specialsa # 注意这里使用的sa的权限绑定
然后直接创建即可:
$ kubectl apply -f nginx-hostnetwork-sa.yaml
deployment.apps/nginx-hostnetwork-deploy configured
这个时候我们查看 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
Pod 安全策略是一种通过使用 PSP 授权策略来保护 Kubernetes 集群中的 Pod 的创建过程的方法。
Kubernetes 多租户:Pod 安全策略的更多相关文章
- kubernetes高级之pod安全策略
系列目录 什么是pod安全策略 pod安全策略是集群级别的用于控制pod安全相关选项的一种资源.PodSecurityPolicy定义了一系列pod相要进行在系统中必须满足的约束条件,以衣一些默认的约 ...
- Kubernetes 中的 Pod 安全策略
来源:伪架构师作者:崔秀龙很多人分不清 SecurityContext 和 PodSecurityPolicy 这两个关键字的差别,其实很简单:•SecurityContext 是 Pod 中的一个字 ...
- 实操教程丨使用Pod安全策略强化K8S安全
本文来自Rancher Labs 什么是Pod安全策略? Kubernetes Pod安全策略(PSP)是Kubernetes安全版块中极为重要的组件.Pod安全策略是集群级别的资源,用于控制Pod安 ...
- Kubernetes 多租户:多租户介绍
多租户集群由多个用户和/或工作负载共享,这些用户和/或工作负载被称为"租户".多租户集群的运营方必须将租户彼此隔离,以最大限度地减少被盗用的租户或恶意租户可能对集群和其他租户造成的 ...
- 实例演示:如何简化生产中的Pod安全策略?
Pod安全策略对于强化K8S集群安全至关重要.本文将延续之前的文章继续深入介绍Pod安全策略. 首先,简单介绍了如何将Pod与Pod安全策略相关联,并使用RBAC来展示具体步骤.然后介绍如何在Ranc ...
- 一文读懂k8s之Pod安全策略
导读 Pod容器想要获取集群的资源信息,需要配置角色和ServiceAccount进行授权.为了更精细地控制Pod对资源的使用方式,Kubernetes从1.4版本开始引入了PodSecurityPo ...
- Kubernetes 实战 —— 03. pod: 运行于 Kubernetes 中的容器
介绍 pod P53 pod 是 Kubernetes 中最为重要的核心概念,而其他对象仅仅用于 pod 管理. pod 暴露或被 pod 使用. pod 是一组并置的容器,代表了 Kubernete ...
- Kubernetes部署单元-Pod
在 k8s 搞出 pod 概念的时候,其实 docker 官方就已经推出自己的容器编排应用 swarm.这一套服务可以帮助在不同节点上的容器,进行统一的管理,主要针对容器的启停,运维,还有部署,注意我 ...
- Kubernetes — 深入解析Pod对象:基本概念(二)
作为 Kubernetes 项目里最核心的编排对象,Pod 携带的信息非常丰富.其中,资源定义(比如 CPU.内存等),以及调度相关的字段.在本篇,我们就先从一种特殊的 Volume 开始,来帮助你更 ...
随机推荐
- 没想到吧,Spring中还有一招集合注入的写法
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. Spring作为项目中不可缺少的底层框架,提供的最基础的功能就是bean的管理了.bean的注入相信大家都比较熟 ...
- 2018 CSP-J 初赛解析
做题记录与答案 今天这个做的是真的烂,60分,妙极了(微笑 可以看看人家的解析 选择: 选择好多不太懂的,一个个的来解析 先分析一下选择的知识点: 计算机基础 :T1.T3.T4.T5.T8 进制转换 ...
- 001 Redis 配置
Redis缓存 1.配置Redis //Redis 配置文件 @Configuration public class RedisConfiguration { @Bean public RedisTe ...
- Solution -「CF645F」Cowslip Collections
设 \(f(i)\) 表示大小为 \(k\),\(\gcd\) 为 \(i\) 的方案数.\(F(i)\) 表示大小为 \(k\),\(\gcd\) 为 \(i\) 的倍数的方案数. 不难看出:\(F ...
- VirtualBox 相关命令行
简介 由于之前项目有一个需求,则是自动化创建虚拟机并加载相关配置,创建虚拟机无法避免对于虚拟机系统的设置,因此采用导入虚拟机的方式,并通过查阅virtualbox相关手册,知晓virtualbox可以 ...
- 当我们谈论算法我们在谈论什么:由疫情核酸检测想到的分治算法(Divide-and-Conquer)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_159 北京的疫情一波未平一波又起,由此看来,战"疫"将是一场旷日持久的战争,绝不能掉以轻心.轻易言胜.病毒随时 ...
- CF242E XOR on Segment
CF242E XOR on Segment codeforces 洛谷 关于异或,无法运用懒标记实现区间异或: 可以像trie树一样拆位,将每个值拆成二进制数,对此建相应个数的线段树. 0 1与 0异 ...
- Python基础之list和tuple的使用
list和tuple的使用 list Python内置的一种数据类型列表:list list是一种有序的集合,可以随身添加和删除其中的元素. 比如列出办理所有同学的名字,就可以用一个list表示: & ...
- LuoguP5322 [BJOI2019]排兵布阵(DP)
城为物,人为容,价值?排序后,一切都明了 #include <iostream> #include <cstdio> #include <cstring> #inc ...
- Luogu1919 【模板】A*B Problem升级版(FFT)
简单的\(A*B\) \(Problem\),卡精度卡到想女装 #include <iostream> #include <cstdio> #include <cstri ...