Kubernetes 工作负载最常见的定义是 YAML 格式的文件。使用 YAML 所面临的挑战之一是,它相当难以表达 manifest 文件之间的约束或关系。
如果你想检查所有部署到集群中的镜像是否从受信任的镜像仓库中提取应该怎么做?如何防止没有 PodDisruptionBudgets 的部署被提交到集群?
集成静态检查可以在接近开发生命周期的时候发现错误和策略违规。而且由于围绕资源定义的有效性和安全性的保证得到了改善,你可以相信生产工作负载是遵循最佳实践的。
Kubernetes YAML 文件静态检查的生态系统可以分为以下几类:
API 验证器:这一类工具可以针对 Kubernetes API 服务器验证给定的 YAML manifest。
内置检查器:这一类工具捆绑了安全、最佳实践等方面的意见检查。
自定义验证器:这一类工具允许用几种语言编写自定义检查,如 Rego 和 Javascript。
在本文中,你将了解并比较六种不同的工具:
Kubeval
Kube-score
Config-lint
Copper
Conftest
Polaris
让我们开始吧!
验证 Deployment
在开始比较各类工具之前,你应该设置一个基准。以下 manifest 并没有遵循最佳实践,可能存在一些问题,你能发现几个问题呢?
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo
复制代码
我们将会使用这个 YAML 文件来对比不同的工具。
你可以在这个 git 仓库中找到上面的 YAML 清单、文件 base-valid.yaml 以及文章中提到的其他 manifest:
https://github.com/amitsaha/kubernetes-static-checkers-demo
manifest 描述了一个总是在 5678 端口回复“Hello World”消息的 web 应用程序。
你可以通过以下方式部署该应用程序:
kubectl apply -f hello-world.yaml
复制代码
你可以使用以下命令测试它:
kubectl port-forward svc/http-echo 8080:5678
复制代码
你可以访问 http://localhost:8080 并确认该应用程序能否按照预期运行。但是它是否遵循了最佳实践呢?
让我们往下看。
Kubeval
主页:https://www.kubeval.com/
Kubeval 的前提是,与 Kubernetes 的任何交互都要通过它的 REST API。因此,你可以使用 API 模式来验证一个给定的 YAML 输入是否符合该模式。我们来看看一个例子。
你可以按照项目网站上的说明来安装 kubeval,撰写此文时最新版本 是 0.15.0。安装完成之后,让我们用前文讨论的 manifest 来运行它:
kubeval base-valid.yaml
PASS - base-valid.yaml contains a valid Deployment (http-echo)
PASS - base-valid.yaml contains a valid Service (http-echo)
复制代码
当成功之后,kubeval 退出时代码为 0。你可以使用以下代码验证退出代码:
现在,让我们使用另一个 manifest 来测试 kubeval:
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo
复制代码
你能发现问题吗?
让我们运行 kubeval:
kubeval kubeval-invalid.yaml
WARN - kubeval-invalid.yaml contains an invalid Deployment (http-echo) - selector: selector is required
PASS - kubeval-invalid.yaml contains a valid Service (http-echo)
# let's check the return value
echo $?
1
复制代码
资源并没有通过验证。使用app/v1
API 版本的 Deployment 必须包含一个匹配 Pod 标签的 selector。上面的 manifest 没有包含 selector,针对 manifest 运行 kubeval 报告了一个错误和一个非零的退出代码。
你可能想知道,当你用上面的 manifest 运行kubectl apply -f
时会发生什么?
让我们试一试:
kubectl apply -f kubeval-invalid.yaml
error: error validating "kubeval-invalid.yaml": error validating data: ValidationError(Deployment.spec):
missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec; if you choose to ignore these errors,
turn validation off with --validate=false
复制代码
这正是 kubeval 警告你的错误。你可以通过添加像这样的 selector 来修复资源。
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: http-echo
spec:
ports:
- port: 5678
protocol: TCP
targetPort: 5678
selector:
app: http-echo
复制代码
像 kubeval 这样的工具的好处是,你可以在部署周期的早期发现这样的错误。此外,你不需要访问集群来运行检查——它们可以离线运行。默认情况下,kubeval 会根据最新的未发布的 Kubernetes API 模式验证资源。然而,在大多数情况下,你可能希望根据特定的 Kubernetes 版本运行验证。你可以使用标志--kubernetes-version
来测试特定的 API 版本:
kubeval --kubernetes-version 1.16.1 base-valid.yaml
复制代码
请注意,版本应该是Major.Minor.Patch.
的形式。要查看可用于验证的版本,请查看 GitHub 上的 JSON schema,kubeval 使用它来执行验证。
如果你需要离线运行 kubeval,你可以下载 schemas,然后使用--schema-location
标志来使用本地目录。除了单个 YAML 文件,你还可以针对目录以及标准输入运行 kubeval。你还应该知道,Kubeval 易于与你的持续集成流水线集成。如果你想在提交你的 manifest 到集群之前包含检查,那么 kubeval 支持三种输出格式也许能够对你有所帮助。
而且你可以使用其中一种格式来进一步解析输出,以创建一个自定义的结果摘要。但是,kubeval 存在一个局限性,就是它目前还不能对自定义资源定义(CRD)进行验证。不过 kubeval 可以忽略它们。
尽管 Kubeval 是检查和验证资源的绝佳选择,但请注意,通过测试的资源并不能保证符合最佳实践。举个例子,在容器镜像中使用最新的标签被认为不是最佳实践。然而,Kubeval 并不会将其作为错误报告,它会在没有警告的情况下验证 YAML。
如果你想对 YAML 进行打分,并抓住诸如使用最新的标签这样的违规行为怎么办?如何根据最佳实践检查你的 YAML 文件?
Kube-score
主页:https://github.com/zegl/kube-score
Kube-score 分析 YAML 清单,并根据内置的检查进行评分。这些检查是根据安全建议和最佳实践而选择的,例如:
你可以在线试用 kube-score,也可以在本地安装。在写这篇文章时,最新的版本是 1.7.0 让我们试着用之前的 manifest base-valid.yaml
来运行它:
kube-score score base-valid.yaml
apps/v1/Deployment http-echo
[CRITICAL] Container Image Tag
· http-echo -> Image with latest tag
Using a fixed tag is recommended to avoid accidental upgrades
[CRITICAL] Pod NetworkPolicy
· The pod does not have a matching network policy
Create a NetworkPolicy that targets this pod
[CRITICAL] Pod Probes
· Container is missing a readinessProbe
A readinessProbe should be used to indicate when the service is ready to receive traffic.
Without it, the Pod is risking to receive traffic before it has booted. It is also used during
rollouts, and can prevent downtime if a new version of the application is failing.
More information: https://github.com/zegl/kube-score/blob/master/README_PROBES.md
[CRITICAL] Container Security Context
· http-echo -> Container has no configured security context
Set securityContext to run the container in a more secure context.
[CRITICAL] Container Resources
· http-echo -> CPU limit is not set
Resource limits are recommended to avoid resource DDOS. Set resources.limits.cpu
· http-echo -> Memory limit is not set
Resource limits are recommended to avoid resource DDOS. Set resources.limits.memory
· http-echo -> CPU request is not set
Resource requests are recommended to make sure that the application can start and run without
crashing. Set resources.requests.cpu
· http-echo -> Memory request is not set
Resource requests are recommended to make sure that the application can start and run without crashing.
Set resources.requests.memory
[CRITICAL] Deployment has PodDisruptionBudget
· No matching PodDisruptionBudget was found
It is recommended to define a PodDisruptionBudget to avoid unexpected downtime during Kubernetes
maintenance operations, such as when draining a node.
[WARNING] Deployment has host PodAntiAffinity
· Deployment does not have a host podAntiAffinity set
It is recommended to set a podAntiAffinity that stops multiple pods from a deployment from
being scheduled on the same node. This increases availability in case the node becomes unavailable.
复制代码
YAML 文件通过了 kubeval 检查,但kube-score
指出了几个不足之处。
缺少了 readiness probe
缺少内存和 CPU 请求和限制。
缺少 Poddisruptionbudgets
缺少反亲和规则以最大化可用性。
容器以 root 身份运行。
这些都是你应该解决的有效点,以使你的部署更加健壮和可靠。kube-score
命令会输出一个可读性高的结果,包含所有的 WARNING 和 CRITICAL 违规行为,这在开发过程中是非常好的。如果你打算把它作为持续集成流水线的一部分,你可以用--output-format ci
这个标志来使用更简洁的输出,它还可以打印级别为 OK 的检查:
kube-score score base-valid.yaml --output-format ci
[OK] http-echo apps/v1/Deployment
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory limit is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) CPU request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Memory request is not set
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Image with latest tag
[OK] http-echo apps/v1/Deployment
[CRITICAL] http-echo apps/v1/Deployment: The pod does not have a matching network policy
[CRITICAL] http-echo apps/v1/Deployment: Container is missing a readinessProbe
[CRITICAL] http-echo apps/v1/Deployment: (http-echo) Container has no configured security context
[CRITICAL] http-echo apps/v1/Deployment: No matching PodDisruptionBudget was found
[WARNING] http-echo apps/v1/Deployment: Deployment does not have a host podAntiAffinity set
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
[OK] http-echo v1/Service
复制代码
与 kubeval 类似,当有一个 CRITICAL 检查失败时,kube-score
会返回一个非零的退出代码,但你配置它在 WARNINGs 时也会失败。还有一个内置的检查来验证不同 API 版本的资源,类似于 kubeval。然而,这些信息是硬编码在 kube-score 本身,你不能选择不同的 Kubernetes 版本。因此,如果你升级你的集群或你有几个不同的集群运行不同的版本,这可能会限制你使用这一工具。
请注意,有一个 open issue 可以实现这个功能。你可以在官方网站上了解更多关于 kube-score 的信息:https://github.com/zegl/kube-score
Kube-score 检查是执行最佳实践的优秀工具,但如果你想自定义,或者添加自己的规则呢?暂时不可以,Kube-score 的设计不是可扩展的,你不能添加或调整政策。如果你想写自定义检查来遵守你的组织政策,你可以使用接下来的四个选项之——config-lint、copper、conftest 或 polaris。
Config-lint
Config-lint 是一个旨在验证以 YAML、JSON、Terraform、CSV 和 Kubernetes manifest 编写的配置文件的工具。你可以使用项目网站上的说明安装它:
https://stelligent.github.io/config-lint/#/install
在撰写本文时,最新的版本是 1.5.0。
Config-lint 没有内置对 Kubernetes manifest 的检查。你必须编写自己的规则来执行验证。这些规则被写成 YAML 文件,称为规则集,具有以下结构:
version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
- "*.yaml"
rules:
# list of rules
复制代码
让我们来详细看看。type
字段表示你将用config-lint
检查什么类型的配置——一般是 Kubernetes manifest。
files
字段除了接受单个文件外,还接受一个目录作为输入。
rules
字段是你可以定义自定义检查的地方。比方说,你希望检查 Deployment 中的镜像是否总是从受信任的镜像仓库(如my-company.com/myapp:1.0
)中提取。实现这种检查的 config-lint
规则可以是这样的:
- id: MY_DEPLOYMENT_IMAGE_TAG
severity: FAILURE
message: Deployment must use a valid image tag
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"
复制代码
每条规则必须具有以下属性。
id
——这是对规则的唯一标识。
severity
——它必须是 FAILURE、WARNING 和 NON_COMPLIANT 中的一个。
message
——如果违反了一个规则,这个字符串的内容会被显示出来。
resource
——你希望这个规则被应用到的资源种类。
assertions
——将对指定资源进行评估的条件列表。
在上面的规则中,every
assertion 检查每个容器中的 Deployment(key:spec.templates.spec.contains
)是否使用受信任的镜像(即以 "my-company.com/"
开头的镜像)。
完整的规则集看起来如下:
version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
- "*.yaml"
rules:
- id: DEPLOYMENT_IMAGE_REPOSITORY
severity: FAILURE
message: Deployment must use a valid image repository
resource: Deployment
assertions:
- every:
key: spec.template.spec.containers
expressions:
- key: image
op: starts-with
value: "my-company.com/"
复制代码
如果你想要测试检查,你可以将规则集保存为check_image_repo.yaml
。
现在,让我们对base-valid.yaml
文件进行验证。
config-lint -rules check_image_repo.yaml base-valid.yaml
[
{
"AssertionMessage": "Every expression fails: And expression fails: image does not start with my-company.com/",
"Category": "",
"CreatedAt": "2020-06-04T01:29:25Z",
"Filename": "test-data/base-valid.yaml",
"LineNumber": 0,
"ResourceID": "http-echo",
"ResourceType": "Deployment",
"RuleID": "DEPLOYMENT_IMAGE_REPOSITORY",
"RuleMessage": "Deployment must use a valid image repository",
"Status": "FAILURE"
}
]
复制代码
它失败了。现在,让我们考虑以下 manifest 和有效的镜像仓库:
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
spec:
replicas: 2
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: http-echo
image: my-company.com/http-echo:1.0
args: ["-text", "hello-world"]
ports:
- containerPort: 5678
复制代码
使用以上 manifest 运行相同的检查并且将不会报告违规:
config-lint -rules check_image_repo.yaml image-valid-mycompany.yaml
[]
复制代码
Config-lint 是一个很有前途的框架,它可以让你使用 YAML DSL 为 Kubernetes YAML manifest 编写自定义检查。但如果你想表达更复杂的逻辑和检查呢?是不是 YAML 的限制性太大?如果你能用真正的编程语言来表达这些检查呢?
Copper
主页:https://github.com/cloud66-oss/copper
Copper V2 是一个使用自定义检查来验证清单的框架——就像 config-lint 一样。然而,Copper 并没有使用 YAML 来定义检查。取而代之的是,测试是用 JavaScript 编写的,Copper 提供了一个库,里面有一些基本的帮助程序来协助读取 Kubernetes 对象和报告错误。
你可以按照官方文档来安装 Copper。在写这篇文章的时候,最新的版本是 2.0.1:
https://github.com/cloud66-oss/copper#installation
与config-lint
类似,Copper 没有内置检查。让我们写一个检查,以确保部署只能从受信任的仓库(如my-company.com
)拉取容器镜像。创建一个新文件check_image_repo.js
,内容如下:
$$.forEach(function($){
if ($.kind === 'Deployment') {
$.spec.template.spec.containers.forEach(function(container) {
var image = new DockerImage(container.image);
if (image.registry.lastIndexOf('my-company.com/') != 0) {
errors.add_error('no_company_repo',"Image " + $.metadata.name + " is not from my-company.com repo", 1)
}
});
}
});
复制代码
现在,要根据我们的base-valid.yaml
manifest 运行这项检查,可以使用 copper validate 命令:
copper validate --in=base-valid.yaml --validator=check_image_tag.js
Check no_company_repo failed with severity 1 due to Image http-echo is not from my-company.com repo
Validation failed
复制代码
正如你所想的,你可以编写更复杂的检查,比如验证 Ingress manifest 的域名,或者拒绝任何作为特权运行的 Pod。Copper 有一些内置的助手:
DockerImage
函数读取指定的输入文件并创建一个包含以下属性的对象:
name-
包含镜像名称
tag-
包含镜像 tag
registry-
镜像仓库
registry_url-
包含协议和镜像仓库
fqin
代表整个完全合格的镜像位置。
findByName
函数可以帮助从输入文件中找到给定 kind 和 name 的资源。
findByLabels
函数可以帮助查找资源提供的kind
和labels
。
你可以在这里看到所有可用的帮助程序:
https://github.com/cloud66-oss/copper/tree/master/libjs
默认情况下,它将整个输入的 YAML 文件加载到$$
变量中,并使其在你的脚本中可用(如果你过去使用 jQuery,你可能会发现这个模式很熟悉)。
除了不用学习自定义语言外,你还可以使用整个 JavaScript 语言来编写你的检查,如字符串插值、函数等。值得注意的是,目前的 copper 版本嵌入了 ES5 版本的 JavaScript 引擎,而不是 ES6。想要了解更多,可以访问项目官网:
https://github.com/cloud66-oss/copper
如果 Javascript 不是你的首选语言,或者你更喜欢用于查询和描述策略的语言,你应该看看 conftest。
Conftest
Conftest 是一个配置数据的测试框架,可用于检查和验证 Kubernetes manifest。测试使用专门构建的查询语言 Rego 编写。
你可以按照项目网站上的说明安装 conftest,在撰写本文时,最新的版本是 0.18.2:
https://www.conftest.dev/install/
与 config-lint 和 copper 类似,conftest 也没有任何内置的检查。所以我们通过编写一个策略来试试。和前面的例子一样,你将检查容器是否来自一个可信的来源。
创建一个新的目录,conftest-checks
和一个名为check_image_registry.rego
的文件,内容如下:
package main
deny[msg] {
input.kind == "Deployment"
image := input.spec.template.spec.containers[_].image
not startswith(image, "my-company.com/")
msg := sprintf("image '%v' doesn't come from my-company.com repository", [image])
}
复制代码
现在让我们运行 conftest 来验证 manifest base-valid.yaml:
conftest test --policy ./conftest-checks base-valid.yaml
FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
1 tests, 1 passed, 0 warnings, 1 failure
复制代码
当然,它是失败的,因为镜像不受信任。上面的 Rego 文件指定了一个 deny 块,当为 true 时就会评估为违规。当你有多个 deny 块时,conftest 会独立检查它们,总体结果是任何一个块的违规都会导致整体违规。
除了默认的输出格式外,conftest 还支持 JSON、TAP 和通过--output
标志的表格格式,如果你希望将报告与现有的持续集成流水线集成,那么这些格式将会很有帮助。为了帮助调试策略,conftest 有一个方便的--trace
标志,它可以打印 conftest 如何解析指定策略文件的跟踪。
Conftest 策略可以作为 artefacts 在 OCI(Open Container Initiative)仓库中发布和共享。命令 push 和 pull 允许发布一个工件和从远程仓库中提取一个现有的 artefact。
让我们看看使用 conftest push 将上述策略发布到本地 docker 仓库的演示。使用以下命令启动本地 docker 仓库:
docker run -it --rm -p 5000:5000 registry
复制代码
从另一个终端,导航到上面创建的 conftest-checks 目录,并运行以下命令:
conftest push 127.0.0.1:5000/amitsaha/opa-bundle-example:latest
复制代码
该命令应成功完成,并显示以下信息:
2020/06/10 14:25:43 pushed bundle with digest: sha256:e9765f201364c1a8a182ca637bc88201db3417bacc091e7ef8211f6c2fd2609c
复制代码
现在,创建一个临时目录,运行 conftest pull 命令,将上述 bundle 下载到临时目录中:
cd $(mktemp -d)
conftest pull 127.0.0.1:5000/amitsaha/opa-bundle-example:latest
复制代码
你会看到,在包含之前 push 的策略文件的临时目录中,有一个新的子目录策略:
tree
.
└── policy
└── check_image_registry.rego
复制代码
你甚至可以直接从仓库中运行测试:
conftest test --update 127.0.0.1:5000/amitsaha/opa-bundle-example:latest base-valid.yaml
..
FAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository
2 tests, 1 passed, 0 warnings, 1 failure
复制代码
不幸的是,DockerHub 还不是支持的镜像仓库之一。然而,如果你正在使用 Azure 容器仓库(ACR)或运行你的容器仓库,可能会通过测试。
artefact 格式与开放策略代理 (OPA) 绑定使用的格式相同,这使得使用 conftest 从现有的 OPA 绑定中运行测试成为可能。
你可以在官方网站上了解更多关于共享策略和 conftest 的其他功能:
https://www.conftest.dev/
Polaris
主页:https://github.com/FairwindsOps/polaris
本文将探讨的最后一个工具是 polaris。Polaris 既可以安装在集群内部,也可以作为命令行工具静态地分析 Kubernetes manifest。当作为命令行工具运行时,它包括几个内置的检查,涵盖安全和最佳实践等领域,类似于 kube-score。此外,你还可以用它来编写类似 config-lint、copper 和 conftest 的自定义检查。换句话说,polaris 结合了两个类别中最好的:内置和自定义检查器。
你可以按照项目网站上的说明安装 polaris 命令行工具。在写这篇文章的时候,最新的版本是 1.0.3:
https://github.com/FairwindsOps/polaris/blob/master/docs/usage.md#cli
安装完成后,你可以使用以下命令针对base-valid.yaml
manifest 运行 polaris:
polaris audit --audit-path base-valid.yam
复制代码
上述命令将打印一个 JSON 格式的字符串,详细说明运行的检查和每个测试的结果。输出结果的结构如下:
{
"PolarisOutputVersion": "1.0",
"AuditTime": "0001-01-01T00:00:00Z",
"SourceType": "Path",
"SourceName": "test-data/base-valid.yaml",
"DisplayName": "test-data/base-valid.yaml",
"ClusterInfo": {
"Version": "unknown",
"Nodes": 0,
"Pods": 2,
"Namespaces": 0,
"Controllers": 2
},
"Results": [
/* long list */
]
}
复制代码
你可以在下方链接中获取完整的输出:
https://github.com/amitsaha/kubernetes-static-checkers-demo/blob/master/base-valid-polaris-result.json
与 kube-score 类似,polaris 也发现了一些 manifest 未达到建议的最佳实践的情况,其中包括:
缺少健康检查的 pod。
容器镜像没有指定标签。
容器以 root 身份运行。
没有设置 CPU 和内存请求和限制。
每项检查都被划分为警告或危险的严重程度。
要了解有关当前内置检查的更多信息,请参阅文档:
https://github.com/FairwindsOps/polaris/blob/master/docs/usage.md#checks
如果你对详细的结果不感兴趣,传递标志--format score
会打印一个范围为 1-100 的数字,polaris 将其称为分数(score):
polaris audit --audit-path test-data/base-valid.yaml --format score
68
复制代码
分数越接近 100,符合度越高。如果你检查 polaris audit 命令的退出代码,你会发现它是 0。要使 polaris 审计退出时的代码是非 0,可以利用另外两个标志。
--set-exit-code-below-score
标志接受范围为 1-100 的阈值分数,当分数低于阈值时,将以 4 的退出代码退出。当你的基线分数是 75 分,而你想在分数低于 75 分时发出警报时,这非常有用。
当任何危险检查失败时,--set-exit-code-on-danger
标志将以 3 的退出代码退出。
现在让我们看看如何为 polaris 定义一个自定义检查,以测试 Deployment 中的容器镜像是否来自可信任的镜像仓库。自定义检查以 YAML 格式定义,测试本身使用 JSON Schema 描述。下面的 YAML 代码段定义了一个新的检查checkImageRepo
:
checkImageRepo:
successMessage: Image registry is valid
failureMessage: Image registry is not valid
category: Images
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$
复制代码
让我们仔细看看:
successMessage
是检查成功时显示的字符串。
failureMessage
是指当测试不成功时显示的信息。
category
指的是其中一个类别—镜像、健康检查、安全、网络和资源。
target
是一个字符串,用于确定检查所针对的规范对象,应该是 Container、Pod 或 Controller 中的一个。
测试本身是在 schema 对象中使用 JSON 模式定义的。这里的检查使用模式关键字来匹配镜像是否来自允许的仓库。
要运行上面定义的检查,你需要创建一个 Polaris 配置文件,如下所示:
checks:
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Image registry is valid
failureMessage: Image registry is not valid
category: Images
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$
复制代码
让我们来分析一下这个文件。
你可以将上面的文件保存为custom_check.yaml
,然后用你想要验证的 YAML manifest 运行polaris audit
。
你可以用base-valid.yaml
manifest 进行测试:
polaris audit --config custom_check.yaml --audit-path base-valid.yaml
复制代码
你会发现,polaris audit
只运行了上面定义的自定义检查,但没有成功。如果你将容器镜像修改为my-company.com/http-echo:1.0
,polaris 将报告成功。Github 仓库中包含了修改后的 manifest,所以你可以根据image-valid-mycompany.yaml
manifest 测试前面的命令。
但是如何同时运行内置和自定义检查呢?上面的配置文件应该更新所有内置的检查标识符,看起来应该如下:
checks:
cpuRequestsMissing: warning
cpuLimitsMissing: warning
# Other inbuilt checks..
# ..
# custom checks
checkImageRepo: danger
customChecks:
checkImageRepo:
successMessage: Image registry is valid
failureMessage: Image registry is not valid
category: Images
target: Container
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
image:
type: string
pattern: ^my-company.com/.+$
复制代码
你可以在这里看到一个完整的配置文件的例子:
https://github.com/amitsaha/kubernetes-static-checkers-demo/blob/master/polaris-configs/config_with_custom_check.yaml
你可以用自定义和内置检查来测试 base-valid.yaml manifest:
polaris audit --config config_with_custom_check.yaml --audit-path base-valid.yaml
复制代码
Polaris 用你的自定义检查增强了内置检查,从而结合了两种方式的最佳状态。然而,如果不能使用更强大的语言,如 Rego 或 JavaScript,可能会限制编写更复杂的检查。
要了解更多关于 polaris 的信息,请查看项目网站:
https://github.com/FairwindsOps/polaris
总结
虽然有很多工具可以验证、打分和精简 Kubernetes YAML 文件,但重要的是要有一个心理模型来了解你将如何设计和执行检查。举个例子,如果你想让 Kubernetes manifest 通过一个流水线,kubeval 可以是这样一个流水线的第一步,因为它验证对象定义是否符合 Kubernetes API 模式。一旦这项检查成功,也许你可以继续进行更详细的测试,比如标准最佳实践和自定义策略。Kube-score 和 polaris 在这里是最优秀的选择。
如果你有复杂的需求,并且想要自定义检查的细节,你应该考虑 copper、config-lint 和 conftest。虽然 conftest 和 config-lint 都使用了更多的 YAML 来定义自定义验证规则,但 copper 给你提供了一个真正的编程语言,使其相当有吸引力。但是,你应该使用其中的一个,从头开始写所有的检查,还是应该使用 Polaris,只写额外的自定义检查?这要根据情况而定。
原文链接:
https://learnk8s.io/validating-kubernetes-yaml
本文转载自公众号 RancherLabs(ID:RancherLabs)。
原文链接:
不确定K8S YAML文件是否符合最佳实践?这6个工具可以帮你!
评论