写点什么

不确定 K8S YAML 文件是否符合最佳实践?这 6 个工具可以帮你!

  • 2020-09-12
  • 本文字数:12475 字

    阅读完需:约 41 分钟

不确定K8S YAML文件是否符合最佳实践?这6个工具可以帮你!

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/v1kind: Deploymentmetadata:  name: http-echospec:  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: v1kind: Servicemetadata:  name: http-echospec:  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.yamlPASS - base-valid.yaml contains a valid Deployment (http-echo)PASS - base-valid.yaml contains a valid Service (http-echo)
复制代码


当成功之后,kubeval 退出时代码为 0。你可以使用以下代码验证退出代码:


echo $?0
复制代码


现在,让我们使用另一个 manifest 来测试 kubeval:


apiVersion: apps/v1kind: Deploymentmetadata:  name: http-echospec:  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: v1kind: Servicemetadata:  name: http-echospec:  ports:  - port: 5678    protocol: TCP    targetPort: 5678  selector:    app: http-echo
复制代码


你能发现问题吗?


让我们运行 kubeval:


kubeval kubeval-invalid.yamlWARN - kubeval-invalid.yaml contains an invalid Deployment (http-echo) - selector: selector is requiredPASS - kubeval-invalid.yaml contains a valid Service (http-echo)
# let's check the return valueecho $?1
复制代码


资源并没有通过验证。使用app/v1 API 版本的 Deployment 必须包含一个匹配 Pod 标签的 selector。上面的 manifest 没有包含 selector,针对 manifest 运行 kubeval 报告了一个错误和一个非零的退出代码。


你可能想知道,当你用上面的 manifest 运行kubectl apply -f时会发生什么?


让我们试一试:


kubectl apply -f kubeval-invalid.yamlerror: 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/v1kind: Deploymentmetadata:  name: http-echospec:  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: v1kind: Servicemetadata:  name: http-echospec:  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 支持三种输出格式也许能够对你有所帮助。


  • 纯文本

  • JSON

  • 测试任何东西协议(TAP)


而且你可以使用其中一种格式来进一步解析输出,以创建一个自定义的结果摘要。但是,kubeval 存在一个局限性,就是它目前还不能对自定义资源定义(CRD)进行验证。不过 kubeval 可以忽略它们。


尽管 Kubeval 是检查和验证资源的绝佳选择,但请注意,通过测试的资源并不能保证符合最佳实践。举个例子,在容器镜像中使用最新的标签被认为不是最佳实践。然而,Kubeval 并不会将其作为错误报告,它会在没有警告的情况下验证 YAML。


如果你想对 YAML 进行打分,并抓住诸如使用最新的标签这样的违规行为怎么办?如何根据最佳实践检查你的 YAML 文件?

Kube-score

主页:https://github.com/zegl/kube-score


Kube-score 分析 YAML 清单,并根据内置的检查进行评分。这些检查是根据安全建议和最佳实践而选择的,例如:


  • 以非 root 用户身份运行容器。

  • 为 pods 指定健康检查。

  • 定义资源请求和限制。

  • 检查的结果可以是 OK、WARNING 或 CRITICAL。


你可以在线试用 kube-score,也可以在本地安装。在写这篇文章时,最新的版本是 1.7.0 让我们试着用之前的 manifest base-valid.yaml来运行它:


kube-score score base-valid.yamlapps/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: 1description: Rules for Kubernetes spec filestype: Kubernetesfiles:  - "*.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: 1description: Rules for Kubernetes spec filestype: Kubernetesfiles:  - "*.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/v1kind: Deploymentmetadata:  name: http-echospec:  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.jsCheck no_company_repo failed with severity 1 due to Image http-echo is not from my-company.com repoValidation failed
复制代码


正如你所想的,你可以编写更复杂的检查,比如验证 Ingress manifest 的域名,或者拒绝任何作为特权运行的 Pod。Copper 有一些内置的助手:


DockerImage函数读取指定的输入文件并创建一个包含以下属性的对象:


  • name-包含镜像名称

  • tag-包含镜像 tag

  • registry-镜像仓库

  • registry_url-包含协议和镜像仓库

  • fqin代表整个完全合格的镜像位置。


findByName函数可以帮助从输入文件中找到给定 kind 和 name 的资源。


findByLabels函数可以帮助查找资源提供的kindlabels


你可以在这里看到所有可用的帮助程序:


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.yamlFAIL - base-valid.yaml - image 'hashicorp/http-echo' doesn't come from my-company.com repository1 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 repository2 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 score68
复制代码


分数越接近 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: dangercustomChecks:  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/.+$
复制代码


让我们来分析一下这个文件。


  • check 字段指定了检查和它们的严重性。由于你想在镜像不受信任时发出警报,所以checkImageRepo被分配了一个danger严重程度。

  • 然后在customChecks对象中定义 checkImageRepo 检查本身。


你可以将上面的文件保存为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: dangercustomChecks:  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个工具可以帮你!


2020-09-12 10:003651

评论

发布
暂无评论
发现更多内容
不确定K8S YAML文件是否符合最佳实践?这6个工具可以帮你!_软件工程_Rancher_InfoQ精选文章