概述
Kubernetes 已经能够允许人们大规模地运行分布式应用程序来彻底改变云原生生态系统。虽然 Kubernetes 是一个功能丰富、健壮的容器编排平台,但它也有自己的一套复杂性。与多个团队一起大规模管理 Kubernetes 并不容易,而且要确保人们做正确的事情并且不越界是很难管理的。
Kyverno 正是解决这个问题的合适工具。它是一个开源的 Kubernetes 原生策略引擎,可以帮助您使用简单的 Kubernetes manifests 定义策略。它可以验证、修改和生成 Kubernetes 资源。因此,它允许组织定义和执行策略,以便开发人员和管理员保持一定的标准。
Kyverno 是如何工作的?
Kyverno
通过使用动态准入控制器来工作,该控制器检查您通过 Kubectl
发送到 Kube API
服务端的每个请求。如果请求与策略匹配,Kyverno
就应用它。否则,它将使用已定义的消息拒绝请求。
所以这使得 Kyverno
能够提供如下特性:
- 检查 CPU 和内存限制。
- 确保用户不更改默认的网络策略。
- 检查资源名称是否与特定模式匹配。
- 确保特定的资源总是包含特定的标签。
- 拒绝对特定资源的删除和更改。
- 如果镜像标签是
latest
将自动更改imagePullPolicy
为Always
- 为每个新的命名空间生成一个默认的网络策略。
Kyverno
使用自定义资源定义来定义策略,编写策略就像使用 kubectl 应用它们一样简单。
Kyverno
提供了三个主要功能:
- 验证(Validation)
- 变更(Mutation)
- 生成(Generation)
让我们看一下它们各自的示例清单。
Validation
一个很好的用例是确保所有的 pods 都设置了资源请求和限制。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-resources
spec:
validationFailureAction: enforce
rules:
- name: check-pod-resources
match:
resources:
kinds:
- Pod
validate:
message: "CPU and memory resource requests and limits are required"
pattern:
spec:
containers:
- name: "*"
resources:
limits:
memory: "?*"
cpu: "?*"
requests:
memory: "?*"
cpu: "?*"
大多数配置都是比较清楚明白的,validationFailureAction
申明是强制执行(通过使用 enforcement
)还是只审计它(通过 audit
)并报告违规情况。
Mutation
Mutation 意味着如果匹配到满足特定的场景就变更资源属性。一个很好的例子是,如果镜像标签是最新的,那么将 imagePullPolicy
更改为 Always
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: image-pull-policy-always
spec:
rules:
- name: image-pull-policy-latest
match:
resources:
kinds:
- Pod
mutate:
overlay:
spec:
containers:
- (image): "*:latest"
imagePullPolicy: "Always"
Generate
顾名思义,针对特定事件生成资源。例如,如果有人创建了一个新的名称空间,我们可能希望执行默认的网络策略。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: "default"
spec:
rules:
- name: "default-deny"
match:
resources:
kinds:
- Namespace
name: "*"
exclude:
namespaces:
- "kube-system"
- "default"
- "kube-public"
- "kyverno"
generate:
kind: NetworkPolicy
name: default-deny-all-traffic
namespace: "{{request.object.metadata.namespace}}"
data:
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
体验一把
现在让我们亲自动手,看看 Kyverno
的行为。我们将安装 Kyverno
,然后应用验证策略来检查特定的标签。如果标签不存在,Kyverno
将拒绝请求。否则,它将应用它。
安装 Kyverno
安装 Kyverno
很简单。你可以应用 GitHub 上的 Kyverno Kubernetes manifest
,或者安装最新的 helm chart
。
使用 manifest
1 | kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/master/definitions/release/install.yaml |
使用 helm chart
1 | helm repo add kyverno https://kyverno.github.io/kyverno/ |
检查我们是否成功安装了 Kyverno
,列出 Kyverno
命名空间中的所有资源:1
2
3
4
5
6
7
8
9# kubectl get all -n kyverno
NAME READY STATUS RESTARTS AGE
pod/kyverno-5f7769d697-x8lkj 0/1 Running 0 21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kyverno-svc ClusterIP 10.96.167.8 <none> 443/TCP 21s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kyverno 0/1 1 0 21s
NAME DESIRED CURRENT READY AGE
replicaset.apps/kyverno-5f7769d697 1 1 0 21s
应用策略
让我们应用一个策略来确保所有 pods
都应该包含一个名为 app
的标签。创建名为require-app-label.yaml
的文件,其内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-app-label
spec:
validationFailureAction: enforce
rules:
- name: check-for-app-label
match:
resources:
kinds:
- Pod
validate:
message: "label `app` is required"
pattern:
metadata:
labels:
app: "?*"
如果您查看 YAML,会看到有一个匹配部分,其中包含我们应该匹配的资源类型。在这个场景中,我们看到一个 pod。validate
部分定义了验证失败时应该输出的消息,以及定义需要匹配什么内容的模式。
由于这是一个 CRD,我们可以直接应用它,得到想要的结果:1
kubectl apply -f require-app-label.yaml
测试
让我们创建一个没有标签的 pod,看看我们会得到什么:1
kubectl run nginx --image=nginx
所以正如我们所看到的,验证失败的原因如下:1
2
3
4Error from server: admission webhook "nirmata.kyverno.resource.validating-webhook" denied the request:
resource Deployment/default/nginx was blocked due to the following policies
require-app-label:
autogen-check-for-app-label: 'Validation error: label `app` is required; Validation rule autogen-check-for-app-label failed at path /spec/template/metadata/labels/app/'
这和预期的一样,因为我们还没有提供标签。现在让我们尝试使用标签 name=nginx
:1
kubectl run nginx --image=nginx --labels="name=nginx" --generator=run-pod/v1
这个也失败了,因为 app 标签仍然缺失。让我们用 app=NGINX
标签创建一个 NGINX pod:1
kubectl run nginx --image=nginx --labels="app=nginx" --generator=run-pod/v1
正如我们所看到的,pod 已经成功创建。现在,让我们使用 kubectl 来获取 pod 和标签:1
kubectl get pod nginx --show-labels
pod 正在运行,并包含 app=nginx
标签。
总结
Kyverno
是一款优秀的 “policy-as-code” 工具,它在组织层执行最佳实践方面非常强大。由于它是 kubernets 原生的,所以编写和操作都很简单,不需要专门的开发人员进行维护。
感谢你的阅读!希望你喜欢这篇文章。
译自:https://medium.com/better-programming/policy-as-code-on-kubernetes-with-kyverno-b144749f144