
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.