118
9
我们甚至可以就
Kubernetes
原生的准入控制功能撰写一本书。但是在本书中
这不太现实,所以我们只会讲解一些比较流行的控制器,并展示如何自己动
手实现控制器。
9.1
配置
启用准入控制非常简单。由于这是一个
API
函数,所以只需将
--enable-
admission-plugins
参数添加到
kube-apiserver
运行时参数中。与其他配置
项一样,这个配置参数也是一个逗号分隔的列表,里面包含了我们想要启用
的准入控制器。
Kubernetes 1.10
之前,准入控制器的指定顺序很重要。但在
--enable-
admission-plugins
命令行参数引入后,顺序就没关系了。对于
1.9
及更早
版本,应该使用依赖顺序的
--admission-control
参数。
9.2
常见的控制器
Kubernetes
,许多用户默认可以使用的功能实际上都是通过准入
控制器实现的。例如
ServiceAccount
准入控制器会自动将
Pod
分配
ServiceAccount
。同样,如果将新的资源添加到当前处于终止状态的
Namespace
,则
NamespaceLifecycle
控制器会拒绝请求。
Kubernetes
开箱即用的准入控制器有两个主要目标:第一,确保在用户没有
指定值的情况下,使用合理的默认值第二,确保用户没有必要之外的功能。
许多用户经过授权执行的操作都是通过
RBAC
控制的,但是准入控制器允许
管理员定义额外的精细控制策略,这些策略超出了授权提供的有关资源、操
作以及对象策略的范围。
准入控制
119
9.2.1 PodSecurityPolicies
PodSecurityPolicies
控制器是一个广泛使用的准入控制器。管理员可
以通过该控制器,指定
Kubernetes
的控制下进程的约束。管理员可以通
PodSecurityPolicies
,保证
Pod
不能在特权环境中运行,不能绑定到
hostNetwork
,必须通过特定的用户运行,还可以保证它们受到各种安全属性
的约束。
在启用
PodSecurityPolicies
后,除非有适当的授权策略,否则用户无法添
加新的
Pod
。你可以根据组织的安全状况,设置许可性或限制性的策略。在
多用户的生产环境中,管理员应使用
PodSecurityPolicies
提供的大部分策略,
因为这些策略能够显著地提高集群整体的安全性。
来看一个典型的例子,假设我们希望确保
Pod
无法在特权环境中运行。像往
常一样,通过
Kubernetes API
定义策略:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: non-privileged
spec:
privileged: false
如果你想创建这个策略,并应用到
API
服务器,然后尝试创建一个符合该策
略的
Pod
,那么你的请求会被拒绝,因为你的用户和或
ServiceAccount
没有
use
这个策略的权限。为了应对这种情况,你只需创建一个
RBAC Role
,允
许其中一种对象类型使用这个
PodSecurityPolicy
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: non-privileged-user
namespace: user-namespace
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resources:
- non-privileged
120
9
以及相应的
RoleBinding
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: non-privileged-user
namespace: user-namespace
roleRef:
kind: Role
name: non-privileged-user
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: some-service-account
namespace: user-namespace
在用户获得
use PodSecurityPolicy
的权限后,就可以声明符合该策略定义
Pod
由于
PodSecurityPolicy
是一个准入控制器(在
API
请求流程中强制执行策
略),因此那些在
PodSecurityPolicy
启动之前就完成了调度的
Pod
可能不
符合策略要求。请记住这一点,因为重新启动这些
Pod
可能会导致它们的调
度失败。理想情况下,
PodSecurityPolicy
准入控制器应该在安装时就启用。
9.2.2 ResourceQuota
一般来说,最好在集群上强制实施配额(
quota
)。配额可以确保用户无法使
用配额之外的资源,这个组件对于提高集群整体的利用率非常关键。如果你
打算限制用户的配额,则应该启用
ResourceQuota
控制器。
这个控制器可以确保根据指定命名空间的当前配额利用率,率先评估新声明
Pod
。可以在添加工作负载期间执行该检查,然后立即通知用户他的
Pod
是否在配额内。同时还需注意,如果命名空间定义了配额,那么所有
Pod
义(即使是来自
Deployment
ReplicaSet
等其他资源的
Pod
)都必须指定资
源请求和限制。
准入控制
121
很多资源都实现了配额,最常见的配额资源包括
CPU
、内存和卷。你也可以
Namespace
内针对各种
Kubernetes
资源(如
Pod
Deployments
Jobs
等)
的数量设置配额。
设置配额的方法很简单:
$ cat quota.yml
apiVersion: v1
kind: ResourceQuota
metadata:
name: memoryquota
namespace: memoryexample
spec:
hard:
requests.memory: 256Mi
limits.memory: 512Mi
接下来,一旦超过了这个限制,即使只有一个
Pod
,我们的声明也会当即遭
ResourceQuota
准入控制器的拒绝:
$ cat pod.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: memoryexample
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
resources:
limits:
memory: 1Gi
requests:
memory: 512Mi
$ kubectl apply -f pod.yml
Error from server (Forbidden): error when creating "pod.yml": pods "nginx" is
forbidden: exceeded quota: memoryquota, requested:
limits.memory=1Gi,requests.memory=512Mi, used: limits.memory=0,requests.memory=0,
limited: limits.memory=512Mi,requests.memory=256Mi
为其他高阶资源(如
Deployments
)设置配额的方法也与
Pod
一样,尽管看
上去没有那么直观:
122
9
$ cat deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: memoryexample
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
resources:
limits:
memory: 256Mi
requests:
memory: 128Mi
$ kubectl apply -f deployment.yml
deployment.apps "nginx-deployment" configured
$ kubectl get po -n memoryexample
NAME READY STATUS RESTARTS AGE
nginx-deployment-55dd98c6c8-9xmjn 1/1 Running 0 25s
nginx-deployment-55dd98c6c8-hc2pf 1/1 Running 0 24s
尽管这里指定了三个副本,但是只有两个满足配额。如果
describe
生成的
ReplicaSet
,就会看到结果失败了:
Warning FailedCreate 3s (x4 over 3s) replicaset-controller
(combined from similar events): Error creating: pods
"nginx-deployment-55dd98c6c8-tkrtz" is forbidden: exceeded quota:
memoryquota, requested: limits.memory=256Mi,requests.memory=128Mi,
used: limits.memory=512Mi,requests.memory=256Mi, limited:
limits.memory=512Mi,requests.memory=256Mi
这个错误源自
ResourceQuota
准入控制器,但这次的错误在某种程度上是隐藏
的,因为这个错误返回给了
Deployment
ReplicaSet
Pod
的创建者)。

Get 管理Kubernetes now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.