From deb0a662b47094e3ac00c57803f7d213adfc7af4 Mon Sep 17 00:00:00 2001 From: chentanjun <2799194073@qq.com> Date: Sat, 8 Feb 2020 20:29:52 +0800 Subject: [PATCH] zh trans /docs/reference/access-authn-authz/extensible-admission-controllers.md (#18856) --- .../extensible-admission-controllers.md | 1253 +++++++++-------- 1 file changed, 670 insertions(+), 583 deletions(-) diff --git a/content/zh/docs/reference/access-authn-authz/extensible-admission-controllers.md b/content/zh/docs/reference/access-authn-authz/extensible-admission-controllers.md index 341d2d91d1225..53a08310ddc39 100644 --- a/content/zh/docs/reference/access-authn-authz/extensible-admission-controllers.md +++ b/content/zh/docs/reference/access-authn-authz/extensible-admission-controllers.md @@ -1,48 +1,32 @@ --- -reviewers: -- smarterclayton -- lavalamp -- caesarxuchao -- deads2k -- liggitt -- jpbetz - title: 动态准入控制 content_template: templates/concept weight: 40 --- -{{% capture overview %}} -[admission 控制器文档](/docs/reference/access-authn-authz/admission-controllers/) -介绍如何使用标准的插件式 admission 控制器。然而, -由于以下原因插件 admission 控制器对于所有用例来说都不够灵活: - -* 他们需要编译到 kube-apiserver 里面。 -* 它们仅在 apiserver 启动时可配置。 -*Admission Webhooks*(1.9 版中的 beta)解决了这些限制。 -它允许 admission 控制器能被独立开发以及在运行时配置。 - -本页介绍如何使用 Admission Webhooks。 +{{% capture overview %}} + +除了[内置的 admission 插件](/docs/reference/access-authn-authz/admission-controllers/),admission 插件可以作为扩展独立开发,并以运行时所配置的 webhook 的形式运行。 +此页面描述了如何构建、配置、使用和监视 admission webhook。 {{% /capture %}} {{% capture body %}} - -### 什么是 admission webhook? + +## 什么是 admission webhook? -Admission webhooks 是 HTTP 回调,它接收 admission 请求并对它们做一些事情。 -您可以定义两种类型的 admission webhook, -[validating admission Webhook](/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook) -和 -[mutating admission webhook](/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook)。 -通过 validating admission Webhook,您可以拒绝请求以执行自定义的 admission 策略。 -通过 mutating admission webhook,您可以更改请求以执行自定义的默认值。 +Admission webhook 是一种用于接收准入请求并对其进行处理的 HTTP 回调机制。 +可以定义两种类型的 admission webhook,即 [validating admission webhook](/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook) 和 [mutating admission webhook](/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook)。 +Mutating admission webhook 会先被调用。它们可以更改发送到 API 服务器的对象以执行自定义的设置默认值操作。 + + +在完成了所有对象修改并且 API 服务器也验证了所传入的对象之后,validating admission webhook 会被调用,并通过拒绝请求的方式来强制实施自定义的策略。 + + +{{< note >}} +如果 admission webhook 需要保证它们所看到的是对象的最终状态以实施某种策略。则应使用 validating admission webhook,因为对象被 mutating webhook 看到之后仍然可能被修改。 +{{< /note >}} + ### 尝试 admission webhook -admission webhook 本质上是集群控制平面的一部分。 您应该非常谨慎地编写和部署它们。 -如果您打算编写/部署生产级 admission webhook,请阅读[用户指南](/docs/reference/access-authn-authz/extensible-admission-controllers/#write-an-admission-webhook-server)以获取相关说明。 +admission webhook 本质上是集群控制平面的一部分。您应该非常谨慎地编写和部署它们。 +如果您打算编写或者部署生产级 admission webhook,请阅读[用户指南](/docs/reference/access-authn-authz/extensible-admission-controllers/#write-an-admission-webhook-server)以获取相关说明。 在下文中,我们将介绍如何快速试验 admission webhook。 -### 先决条件 +### 先决条件 {#prerequisites} -* 确保 Kubernetes 集群版本至少为 v1.9。 +* 确保 Kubernetes 集群版本至少为 v1.16(以便使用 `admissionregistration.k8s.io/v1` API) 或者 v1.9 (以便使用 `admissionregistration.k8s.io/v1beta1` API)。 * 确保启用 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 控制器。 [这里](/docs/reference/access-authn-authz/admission-controllers/#is-there-a-recommended-set-of-admission-controllers-to-use) 是一组推荐的 admission 控制器,通常可以启用。 -* 确保启用了`admissionregistration.k8s.io/v1beta1` API。 +* 确保启用了 `admissionregistration.k8s.io/v1beta1` API。 +### 编写一个 admission webhook 服务器 + +请参阅 Kubernetes e2e 测试中的 [admission webhook 服务器](https://github.com/kubernetes/kubernetes/blob/v1.13.0/test/images/webhook/main.go) 的实现。webhook 处理由 apiserver 发送的 `AdmissionReview` 请求,并且将其决定作为 `AdmissionReview` 对象以相同版本发送回去。 -the `admissionReview` request can have different versions (e.g. v1beta1 or `v1` in a future version). -The webhook can define what version they accept using `admissionReviewVersions` field. API server -will try to use first version in the list which it supports. If none of the versions specified -in this list supported by API server, validation will fail for this object. If the webhook -configuration has already been persisted, calls to the webhook will fail and be -subject to the failure policy. + +有关发送到 webhook 的数据的详细信息,请参阅 [webhook 请求](#request)。 + + +要获取来自 webhook 的预期数据,请参阅 [webhook 响应](#response)。 + -### 编写一个admission webhook 服务器 - -请参阅 Kubernetes e2e 测试中的 -[admission webhook 服务器](https://github.com/kubernetes/kubernetes/blob/v1.13.0/test/images/webhook/main.go)实现。 - webhook 处理由 apiservers 发送的 `admissionReview` 请求,并将其决定包含在 `admissionResponse` 中发回。 - -`admissionReview` 请求可以有不同的版本(例如,`v1beta1` 或未来版本中的 `v1`)。 -webhook 可以使用 `admissionReviewVersions` 字段定义它们接受的版本。 -apiserver 将尝试在其支持的列表中使用第一个版本。 -如果 apiserver 不支持此列表中指定的任何版本,则此对象的验证将失败。 -如果 webhook 配置依然如此,则对 webhook 的调用将失败并受到失败策略的控制。 - -示例 admission webhook 服务器置 `ClientAuth` 字段为 -[空](https://github.com/kubernetes/kubernetes/blob/v1.13.0/test/images/webhook/config.go#L47-L48), -默认为 `NoClientCert` 。这意味着 webhook 服务器不会验证客户端的身份,认为其是 apiservers。 -如果您需要双向 TLS 或其他方式来验证客户端,请参阅如何 [验证-apiservers](#验证-apiservers)。 +示例 admission webhook 服务器置 `ClientAuth` 字段为[空](https://github.com/kubernetes/kubernetes/blob/v1.13.0/test/images/webhook/config.go#L47-L48),默认为 `NoClientCert` 。这意味着 webhook 服务器不会验证客户端的身份,认为其是 apiservers。 +如果您需要双向 TLS 或其他方式来验证客户端,请参阅如何[对 apiservers 进行身份认证](#authenticate-apiservers)。 +### 部署 admission webhook 服务 + +e2e 测试中的 webhook 服务器通过 [deployment API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#deployment-v1-apps) 部署在 Kubernetes 集群中。该测试还将创建一个 [service](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core) 作为 webhook 服务器的前端。参见[相关代码](https://github.com/kubernetes/kubernetes/blob/v1.15.0/test/e2e/apimachinery/webhook.go#L301)。 + -### 部署 admission webhook 服务 - -e2e 测试中的 webhook 服务器部署在 Kubernetes 集群中,通过 [deployment API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#deployment-v1-apps)。 -该测试还创建了 [service](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core) 作为 webhook 服务器的前端。 -参见 [code](https://github.com/kubernetes/kubernetes/blob/v1.15.0/test/e2e/apimachinery/webhook.go#L301)。 - -您还可以在集群外部署 Webhook, -这需要相应地更新 [webhook 客户端配置](https://github.com/kubernetes/kubernetes/blob/v1.13.0/staging/src/k8s.io/api/admissionregistration/v1beta1/types.go#L247)。 +您也可以在集群外部署 webhook。这样做需要相应地更新您的 webhook 配置。 +### 即时配置 admission webhook + +您可以通过 [ValidatingWebhookConfiguration](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#validatingwebhookconfiguration-v1-admissionregistration-k8s-io) 或者 [MutatingWebhookConfiguration](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#mutatingwebhookconfiguration-v1-admissionregistration-k8s-io) 动态配置哪些资源要被哪些 admission webhook 处理。 + -### 即时配置 admission webhook - -您可以动态配置哪些资源需要接受什么许可通过webhooks [ValidatingWebhookConfiguration](/docs/reference/produced/kubernetes-api/{{}}/#validatingwebhookconfiguration-v1-admissionregistration-k8s-io) 要么 -[MutatingWebhookConfiguration](/docs/reference/Generated/kubernetes-api/{{}}/#mutatingwebhookconfiguration-v1-admissionregistration-k8s-io)。 - -以下是一个示例`ValidatingWebhookConfiguration`,一个变异的 webhook 配置与此类似。有关每个配置字段的详细信息,请参见 [webhook 配置](#webhook-配置)部分。 +以下是一个 `ValidatingWebhookConfiguration` 示例,mutating webhook 配置与此类似。有关每个配置字段的详细信息,请参阅 [webhook 配置](#webhook-configuration) 部分。 {{< tabs name="ValidatingWebhookConfiguration_example_1" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -206,7 +194,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# 1.16 中被淘汰,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration metadata: @@ -234,26 +222,26 @@ webhooks: The scope field specifies if only cluster-scoped resources ("Cluster") or namespace-scoped resources ("Namespaced") will match this rule. "*" means that there are no scope restrictions. --> -范围字段指定是仅集群范围的资源(Cluster)还是命名空间范围的资源资源(Namespaced)将与此规则匹配。`*`表示没有范围限制。 +scope 字段指定是仅集群范围的资源(Cluster)还是命名空间范围的资源资源(Namespaced)将与此规则匹配。`*` 表示没有范围限制。 -{{< note >}} -当使用`clientConfig.service`时,服务器证书必须对`. .svc`有效。 - +{{< note >}} +当使用 `clientConfig.service` 时,服务器证书必须对 `..svc` 有效。 {{< /note >}} -{{< note >}} -Webhook 呼叫的默认超时为 30 秒,但从 kubernetes 1.14 开始,可以设置超时,因此建议对 Webhooks 使用非常小的超时。 -如果 webhook 呼叫超时,则根据 webhook 的请求处理请求失败政策。 +{{< note >}} +对于使用 `admissionregistration.k8s.io/v1` 创建的 webhook 而言,其 webhook 调用的默认超时是 10 秒;对于使用 `admissionregistration.k8s.io/v1beta1` 创建的 webhook 而言,其默认超时是 30 秒。从 kubernetes 1.14 开始,可以设置超时。建议对 webhooks 设置较短的超时时间。 +如果 webhook 调用超时,则根据 webhook 的失败策略处理请求。 {{< /note >}} +当 apiserver 收到与 `rules` 相匹配的请求时,apiserver 按照 `clientConfig` 中指定的方式向 webhook 发送一个 `admissionReview` 请求。 -当 apiserver 收到与`rules`匹配的请求时,apiserver 根据`clientConfig`配置定向给 webhook 发送`admissionReview`请求。 - -创建 webhook 配置后,系统将花费几秒钟来完成新配置的生效。 - +创建 webhook 配置后,系统将花费几秒钟使新配置生效。 +### 对 apiservers 进行身份认证 {#authenticate-apiservers} + +如果您的 webhook 需要身份验证,则可以将 apiserver 配置为使用基本身份验证、持有者令牌或证书来向 webhook 提供身份证明。完成此配置需要三个步骤。 + -### 验证-apiservers +* 启动 apiserver 时,通过 `--admission-control-config-file` 参数指定准入控制配置文件的位置。 -如果您的 webhooks 需要身份验证,您可以将 apiservers 配置为使用基本身份验证,不记名令牌或证书来对 webhook 进行身份验证。 -完成配置有三个步骤。 +* 在准入控制配置文件中,指定 MutatingAdmissionWebhook 控制器和 ValidatingAdmissionWebhook 控制器应该读取凭据的位置。 +凭证存储在 kubeConfig 文件中(是​​的,与 kubectl 使用的模式相同),因此字段名称为 `kubeConfigFile`。 +以下是一个准入控制配置文件示例: -* 启动apiserver时,通过 `--admission-control-config-file` 参数指定许可控制配置文件的位置。 + -* 在准入控制配置文件中,指定 MutatingAdmissionWebhook 控制器和 ValidatingAdmissionWebhook 控制器应该读取凭据的位置。 -凭证存储在 kubeConfig 文件中(是​​的,与 kubectl 使用的模式相同),因此字段名称为`kubeConfigFile`。 -以下是一个示例准入控制配置文件: +{{< tabs name="admissionconfiguration_example1" >}} +{{% tab name="apiserver.config.k8s.io/v1" %}} +```yaml +apiVersion: apiserver.config.k8s.io/v1 +kind: AdmissionConfiguration +plugins: +- name: ValidatingAdmissionWebhook + configuration: + apiVersion: apiserver.config.k8s.io/v1 + kind: WebhookAdmissionConfiguration + kubeConfigFile: "" +- name: MutatingAdmissionWebhook + configuration: + apiVersion: apiserver.config.k8s.io/v1 + kind: WebhookAdmissionConfiguration + kubeConfigFile: "" +``` +{{% /tab %}} +{{% tab name="apiserver.k8s.io/v1alpha1" %}} ```yaml +# 1.17 中被淘汰,推荐使用 apiserver.config.k8s.io/v1 apiVersion: apiserver.k8s.io/v1alpha1 kind: AdmissionConfiguration plugins: - name: ValidatingAdmissionWebhook configuration: + # 1.17 中被淘汰,推荐使用 apiserver.config.k8s.io/v1,kind = WebhookAdmissionConfiguration apiVersion: apiserver.config.k8s.io/v1alpha1 kind: WebhookAdmission kubeConfigFile: "" - name: MutatingAdmissionWebhook configuration: + # 1.17 中被淘汰,推荐使用 apiserver.config.k8s.io/v1,kind = WebhookAdmissionConfiguration apiVersion: apiserver.config.k8s.io/v1alpha1 kind: WebhookAdmission kubeConfigFile: "" ``` +{{% /tab %}} +{{< /tabs >}} -`admissionConfiguration`的 shcema 定义在 [这里](https://github.com/kubernetes/kubernetes/blob/v1.13.0/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go#L27). -有关每个配置字段的详细信息,请参见 [webhook配置](#webhook-配置)部分。 +有关 `AdmissionConfiguration` 的更多信息,请参见 [AdmissionConfiguration schema](https://github.com/kubernetes/kubernetes/blob/v1.17.0/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1/types.go#L27)。 +有关每个配置字段的详细信息,请参见 [webhook 配置](#webhook-配置)部分。 * 在 kubeConfig 文件中,提供证书凭据: -```yaml -apiVersion: v1 -kind: Config -users: -# name should be set to the DNS name of the service or the host (including port) of the URL the webhook is configured to speak to. -# If a non-443 port is used for services, it must be included in the name when configuring 1.16+ API servers. -# -# For a webhook configured to speak to a service on the default port (443), specify the DNS name of the service: -# - name: webhook1.ns1.svc -# user: ... -# -# For a webhook configured to speak to a service on non-default port (e.g. 8443), specify the DNS name and port of the service in 1.16+: -# - name: webhook1.ns1.svc:8443 -# user: ... -# and optionally create a second stanza using only the DNS name of the service for compatibility with 1.15 API servers: -# - name: webhook1.ns1.svc -# user: ... -# -# For webhooks configured to speak to a URL, match the host (and port) specified in the webhook's URL. Examples: -# A webhook with `url: https://www.example.com`: -# - name: www.example.com -# user: ... -# -# A webhook with `url: https://www.example.com:443`: -# - name: www.example.com:443 -# user: ... -# -# A webhook with `url: https://www.example.com:8443`: -# - name: www.example.com:8443 -# user: ... -# -- name: 'webhook1.ns1.svc' - user: - client-certificate-data: "" - client-key-data: "" -# The `name` supports using * to wildcard-match prefixing segments. -- name: '*.webhook-company.org' - user: - password: "" - username: "" -# '*' is the default match. -- name: '*' - user: - token: "" -``` + ```yaml + apiVersion: v1 + kind: Config + users: + # 名称应设置为服务的 DNS 名称或配置了 Webhook 的 URL 的主机名(包括端口)。 + # 如果将非 443 端口用于服务,则在配置 1.16+ API 服务器时,该端口必须包含在名称中。 + # + # 对于配置在默认端口(443)上与服务对话的 Webhook,请指定服务的 DNS 名称: + # - name: webhook1.ns1.svc + # user: ... + # + # 对于配置在非默认端口(例如 8443)上与服务对话的 Webhook,请在 1.16+ 中指定服务的 DNS 名称和端口: + # - name: webhook1.ns1.svc:8443 + # user: ... + # 并可以选择仅使用服务的 DNS 名称来创建第二节,以与 1.15 API 服务器版本兼容: + # - name: webhook1.ns1.svc + # user: ... + # + # 对于配置为使用 URL 的 webhook,请匹配在 webhook 的 URL 中指定的主机(和端口)。 + # 带有 `url: https://www.example.com` 的 webhook: + # - name: www.example.com + # user: ... + # + # 带有 `url: https://www.example.com:443` 的 webhook: + # - name: www.example.com:443 + # user: ... + # + # 带有 `url: https://www.example.com:8443` 的 webhook: + # - name: www.example.com:8443 + # user: ... + # + - name: 'webhook1.ns1.svc' + user: + client-certificate-data: "" + client-key-data: "" + # `name` 支持使用 * 通配符匹配前缀段。 + - name: '*.webhook-company.org' + user: + password: "" + username: "" + # '*' 是默认匹配项。 + - name: '*' + user: + token: "" + ``` @@ -386,12 +404,11 @@ Webhooks can specify what versions of `AdmissionReview` objects they accept with the `admissionReviewVersions` field in their configuration: --> -### 请求 +### 请求 {#request} -向 Webhooks 发送 POST 请求,头域带上`Content-Type:application/json`,与`admission.k8s.io` API groups 中的`AdmissionReview` API 对象一起使用 -序列化为 JSON 作为主体。 +向 Webhook 发送 POST 请求时,请设置 `Content-Type: application/json` 并对 `admission.k8s.io` API 组中的 `AdmissionReview` 对象进行序列化,将所得到的 JSON 作为请求的主体。 -Webhooks 可以指定他们接受的`AdmissionReview`对象的版本在配置中使用`admissionReviewVersions`字段: +Webhook 可以在配置中的 `admissionReviewVersions` 字段指定可接受的 `AdmissionReview` 对象版本: {{< tabs name="ValidatingWebhookConfiguration_admissionReviewVersions" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -404,19 +421,19 @@ webhooks: admissionReviewVersions: ["v1", "v1beta1"] ... ``` + -创建时,`admissionReviewVersions`是必填字段`admissionregistration.k8s.io/v1` Webhook配置。 -需要 Webhooks 支持至少一项`AdmissionReview`当前和以前的 apiserver 可以解释的版本。 - +创建 `admissionregistration.k8s.io/v1` webhook 配置时,`admissionReviewVersions` 是必填字段。 +Webhook 必须支持至少一个当前和以前的 apiserver 都可以解析的 `AdmissionReview` 版本。 {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被淘汰,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... @@ -425,12 +442,12 @@ webhooks: admissionReviewVersions: ["v1beta1"] ... ``` + - -如果未指定`admissionReviewVersions`,则创建时的默认值`admissionregistration.k8s.io/v1beta1` Webhook 配置为`v1beta1`。 +如果未指定 `admissionReviewVersions`,则创建 `admissionregistration.k8s.io/v1beta1` Webhook 配置时的默认值为 `v1beta1`。 {{% /tab %}} {{< /tabs >}} @@ -443,11 +460,11 @@ versions the API server knows how to send, attempts to call to the webhook will This example shows the data contained in an `AdmissionReview` object for a request to update the `scale` subresource of an `apps/v1` `Deployment`: --> -apiserver 在其支持的`admissionReviewVersions`列表中发送第一个`AdmissionReview`版本。如果 apiserver 不支持列表中的任何版本,则不允许创建配置。 -如果 apiserver 遇到先前创建的 Webhook 配置,并且不支持任何`AdmissionReview` -apiserver 知道如何发送的版本,调用 Webhook 的尝试将失败,并受 [失败策略](#失败策略) 的约束。 +API 服务器将发送的是 `admissionReviewVersions` 列表中所支持的第一个 `AdmissionReview` 版本。如果 API 服务器不支持列表中的任何版本,则不允许创建配置。 -此示例显示了`AdmissionReview`对象中包含的数据请求更新apps/v1 Deployment 的 scale 子资源: +如果 API 服务器遇到以前创建的 Webhook 配置,并且不支持该 API 服务器知道如何发送的任何 `AdmissionReview` 版本,则调用 Webhook 的尝试将失败,并依据[失败策略](#failure-policy)进行处理。 + +此示例显示了 `AdmissionReview` 对象中包含的数据,该数据用于请求更新 `apps/v1` `Deployment` 的 `scale` 子资源: {{< tabs name="AdmissionReview_request" >}} {{% tab name="admission.k8s.io/v1" %}} @@ -456,65 +473,61 @@ apiserver 知道如何发送的版本,调用 Webhook 的尝试将失败,并 "apiVersion": "admission.k8s.io/v1", "kind": "AdmissionReview", "request": { - # Random uid uniquely identifying this admission call + # 唯一标识此准入回调的随机 uid "uid": "705ab4f5-6393-11e8-b7cc-42010a800002", - # Fully-qualified group/version/kind of the incoming object + # 传入完全正确的 group/version/kind 对象 "kind": {"group":"autoscaling","version":"v1","kind":"Scale"}, - # Fully-qualified group/version/kind of the resource being modified + # 修改 resource 的完全正确的的 group/version/kind "resource": {"group":"apps","version":"v1","resource":"deployments"}, - # subresource, if the request is to a subresource + # subResource(如果请求是针对 subResource 的) "subResource": "scale", - # Fully-qualified group/version/kind of the incoming object in the original request to the API server. - # This only differs from `kind` if the webhook specified `matchPolicy: Equivalent` and the - # original request to the API server was converted to a version the webhook registered for. + # 在对 API 服务器的原始请求中,传入对象的标准 group/version/kind + # 仅当 webhook 指定 `matchPolicy: Equivalent` 且将对 API 服务器的原始请求转换为 webhook 注册的版本时,这才与 `kind` 不同。 "requestKind": {"group":"autoscaling","version":"v1","kind":"Scale"}, - # Fully-qualified group/version/kind of the resource being modified in the original request to the API server. - # This only differs from `resource` if the webhook specified `matchPolicy: Equivalent` and the - # original request to the API server was converted to a version the webhook registered for. + # 在对 API 服务器的原始请求中正在修改的资源的标准 group/version/kind + # 仅当 webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为 webhook 注册的版本时,这才与 `resource` 不同。 "requestResource": {"group":"apps","version":"v1","resource":"deployments"}, - # subresource, if the request is to a subresource - # This only differs from `subResource` if the webhook specified `matchPolicy: Equivalent` and the - # original request to the API server was converted to a version the webhook registered for. + # subResource(如果请求是针对 subResource 的) + # 仅当 webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为该 webhook 注册的版本时,这才与 `subResource` 不同。 "requestSubResource": "scale", - # Name of the resource being modified + # 被修改资源的名称 "name": "my-deployment", - # Namespace of the resource being modified, if the resource is namespaced (or is a Namespace object) + # 如果资源是属于命名空间(或者是命名空间对象),则这是被修改的资源的命名空间 "namespace": "my-namespace", - # operation can be CREATE, UPDATE, DELETE, or CONNECT + # 操作可以是 CREATE、UPDATE、DELETE 或 CONNECT "operation": "UPDATE", "userInfo": { - # Username of the authenticated user making the request to the API server + # 向 API 服务器发出请求的经过身份验证的用户的用户名 "username": "admin", - # UID of the authenticated user making the request to the API server + # 向 API 服务器发出请求的经过身份验证的用户的 UID "uid": "014fbff9a07c", - # Group memberships of the authenticated user making the request to the API server + # 向 API 服务器发出请求的经过身份验证的用户的组成员身份 "groups": ["system:authenticated","my-admin-group"], - # Arbitrary extra info associated with the user making the request to the API server. - # This is populated by the API server authentication layer and should be included - # if any SubjectAccessReview checks are performed by the webhook. + # 向 API 服务器发出请求的用户相关的任意附加信息 + # 该字段由 API 服务器身份验证层填充,并且如果 webhook 执行了任何 SubjectAccessReview 检查,则应将其包括在内。 "extra": { "some-key":["some-value1", "some-value2"] } }, - # object is the new object being admitted. - # It is null for DELETE operations. + # object 是被接纳的新对象。 + # 对于 DELETE 操作,它为 null。 "object": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, - # oldObject is the existing object. - # It is null for CREATE and CONNECT operations. + # oldObject 是现有对象。 + # 对于 CREATE 和 CONNECT 操作,它为 null。 "oldObject": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, - # options contains the options for the operation being admitted, like meta.k8s.io/v1 CreateOptions, UpdateOptions, or DeleteOptions. - # It is null for CONNECT operations. + # options 包含要接受的操作的选项,例如 meta.k8s.io/v CreateOptions、UpdateOptions 或 DeleteOptions。 + # 对于 CONNECT 操作,它为 null。 "options": {"apiVersion":"meta.k8s.io/v1","kind":"UpdateOptions",...}, - # dryRun indicates the API request is running in dry run mode and will not be persisted. - # Webhooks with side effects should avoid actuating those side effects when dryRun is true. - # See http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request for more details. + # dryRun 表示 API 请求正在以 `dryrun` 模式运行,并且将不会保留。 + # 带有副作用的 Webhook 应该避免在 dryRun 为 true 时激活这些副作用。 + # 有关更多详细信息,请参见 http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request "dryRun": false } } @@ -523,73 +536,69 @@ apiserver 知道如何发送的版本,调用 Webhook 的尝试将失败,并 {{% tab name="admission.k8s.io/v1beta1" %}} ```yaml { - # Deprecated in v1.16 in favor of admission.k8s.io/v1 + # v1.16 中被废弃,推荐使用 admission.k8s.io/v1 "apiVersion": "admission.k8s.io/v1beta1", "kind": "AdmissionReview", "request": { - # Random uid uniquely identifying this admission call + # 唯一标识此准入回调的随机 uid "uid": "705ab4f5-6393-11e8-b7cc-42010a800002", - # Fully-qualified group/version/kind of the incoming object + # 传入完全正确的 group/version/kind 对象 "kind": {"group":"autoscaling","version":"v1","kind":"Scale"}, - # Fully-qualified group/version/kind of the resource being modified + # 修改 resource 的完全正确的的 group/version/kind "resource": {"group":"apps","version":"v1","resource":"deployments"}, - # subresource, if the request is to a subresource + # subResource(如果请求是针对 subResource 的) "subResource": "scale", - # Fully-qualified group/version/kind of the incoming object in the original request to the API server. - # This only differs from `kind` if the webhook specified `matchPolicy: Equivalent` and the - # original request to the API server was converted to a version the webhook registered for. - # Only sent by v1.15+ API servers. + # 在对 API 服务器的原始请求中,传入对象的标准 group/version/kind。 + # 仅当 Webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为该 Webhook 注册的版本时,这与 `kind` 不同。 + # 仅由 v1.15+ API 服务器发送。 "requestKind": {"group":"autoscaling","version":"v1","kind":"Scale"}, - # Fully-qualified group/version/kind of the resource being modified in the original request to the API server. - # This only differs from `resource` if the webhook specified `matchPolicy: Equivalent` and the - # original request to the API server was converted to a version the webhook registered for. - # Only sent by v1.15+ API servers. + # 在对 API 服务器的原始请求中正在修改的资源的标准 group/version/kind + # 仅当 webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为 webhook 注册的版本时,这才与 `resource` 不同。 + # 仅由 v1.15+ API 服务器发送。 "requestResource": {"group":"apps","version":"v1","resource":"deployments"}, - # subresource, if the request is to a subresource - # This only differs from `subResource` if the webhook specified `matchPolicy: Equivalent` and the - # original request to the API server was converted to a version the webhook registered for. - # Only sent by v1.15+ API servers. + # subResource(如果请求是针对 subResource 的) + # 仅当 webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为该 webhook 注册的版本时,这才与 `subResource` 不同。 + # 仅由 v1.15+ API 服务器发送。 "requestSubResource": "scale", - # Name of the resource being modified + # 被修改资源的名称 "name": "my-deployment", - # Namespace of the resource being modified, if the resource is namespaced (or is a Namespace object) + # 如果资源是属于命名空间(或者是命名空间对象),则这是被修改的资源的命名空间 "namespace": "my-namespace", - # operation can be CREATE, UPDATE, DELETE, or CONNECT + # 操作可以是 CREATE、UPDATE、DELETE 或 CONNECT "operation": "UPDATE", "userInfo": { - # Username of the authenticated user making the request to the API server + # 向 API 服务器发出请求的经过身份验证的用户的用户名 "username": "admin", - # UID of the authenticated user making the request to the API server + # 向 API 服务器发出请求的经过身份验证的用户的 UID "uid": "014fbff9a07c", - # Group memberships of the authenticated user making the request to the API server + # 向 API 服务器发出请求的经过身份验证的用户的组成员身份 "groups": ["system:authenticated","my-admin-group"], - # Arbitrary extra info associated with the user making the request to the API server. - # This is populated by the API server authentication layer and should be included - # if any SubjectAccessReview checks are performed by the webhook. + # 向 API 服务器发出请求的用户相关的任意附加信息 + # 该字段由 API 服务器身份验证层填充,并且如果 webhook 执行了任何 SubjectAccessReview 检查,则应将其包括在内。 "extra": { "some-key":["some-value1", "some-value2"] } }, - # object is the new object being admitted. - # It is null for DELETE operations. + # object 是被接纳的新对象。 + # 对于 DELETE 操作,它为 null。 "object": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, - # oldObject is the existing object. - # It is null for CREATE and CONNECT operations (and for DELETE operations in API servers prior to v1.15.0) + # oldObject 是现有对象。 + # 对于 CREATE 和 CONNECT 操作(对于 v1.15.0 之前版本的 API 服务器中的 DELETE 操作),它为 null。 "oldObject": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, - # options contains the options for the operation being admitted, like meta.k8s.io/v1 CreateOptions, UpdateOptions, or DeleteOptions. - # It is null for CONNECT operations. - # Only sent by v1.15+ API servers. + # options 包含要接受的操作的选项,例如 meta.k8s.io/v CreateOptions、UpdateOptions 或 DeleteOptions。 + # 对于 CONNECT 操作,它为 null。 + # 仅由 v1.15+ API 服务器发送。 "options": {"apiVersion":"meta.k8s.io/v1","kind":"UpdateOptions",...}, - # dryRun indicates the API request is running in dry run mode and will not be persisted. - # Webhooks with side effects should avoid actuating those side effects when dryRun is true. - # See http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request for more details. + # dryRun 表示 API 请求正在以 `dryrun` 模式运行,并且将不会保留。 + # 带有副作用的 Webhook 应该避免在 dryRun 为 true 时激活这些副作用。 + # 有关更多详细信息,请参见 http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request "dryRun": false } } @@ -598,27 +607,33 @@ apiserver 知道如何发送的版本,调用 Webhook 的尝试将失败,并 {{< /tabs >}} +### 响应{#response} + +Webhook 使用 HTTP 200 状态码、`Content-Type: application/json` 和一个包含 `AdmissionReview` 对象的 JSON 序列化格式来发送响应。该 `AdmissionReview` 对象与发送的版本相同,且其中包含的 `response` 字段已被有效填充。 + -### 响应 +`response` 至少必须包含以下字段: -Webhooks 会以 200 HTTP 状态代码`Content-Type:application/json`响应,以及包含`AdmissionReview`对象的xaingy(与发送的版本相同), -带有`response`节的序列,并序列化为 JSON。 +* `uid`,从发送到 webhook 的 `request.uid` 中复制而来 +* `allowed`,设置为 `true` 或 `false` -`response`节至少必须包含以下字段: -*`uid`,从发送到 webhook 的`request.uid`复制而来 -*`allowed`,设置为`true`或`false` - -Webhook 允许请求的最简单响应示例: + +Webhook 禁止请求的最简单响应示例: {{< tabs name="AdmissionReview_response_allow" >}} {{% tab name="admission.k8s.io/v1" %}} @@ -646,6 +661,7 @@ Webhook 允许请求的最简单响应示例: ``` {{% /tab %}} {{< /tabs >}} + @@ -680,12 +696,12 @@ Webhook 禁止请求的最简单响应示例: -当拒绝请求时,webhook 可以使用`status`字段自定义http代码和消息体返回给用户。 -指定的状态对象返回给用户。有关状态类型的详细信息,请参见 [API 文档](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#status-v1-meta)。 -禁止请求,定制 HTTP 状态代码和显示给用户的消息的响应示例: +当拒绝请求时,webhook 可以使用 `status` 字段自定义 http 响应码和返回给用户的消息。 +有关状态类型的详细信息,请参见 [API 文档](/docs/reference/generated/kubernetes-api/v1.14/#status-v1-meta)。 +禁止请求的响应示例,它定制了向用户显示的 HTTP 状态码和消息: {{< tabs name="AdmissionReview_response_forbid_details" >}} {{% tab name="admission.k8s.io/v1" %}} @@ -721,29 +737,33 @@ Example of a response to forbid a request, customizing the HTTP status code and ``` {{% /tab %}} {{< /tabs >}} + +当允许请求时,mutating admission webhook 也可以选择修改传入的对象。 +这是通过在响应中使用 `patch` 和 `patchType` 字段来完成的。 +当前唯一支持的 `patchType` 是 `JSONPatch`。 +有关更多详细信息,请参见 [JSON patch](http://jsonpatch.com/)。 +对于 `patchType: JSONPatch`,`patch` 字段包含一个以 base64 编码的 JSON patch 操作数组。 + -当允许请求时,变异接纳 Webhook 也可以选择修改传入对象。这是通过在响应中使用`patch`和`patchType`字段来完成的。 -当前唯一支持的`patchType`是`JSONPatch`。有关更多详细信息,请参见 [JSON 补丁](http://jsonpatch.com/) 文档。 -对于`patchType:JSONPatch`,`patch`字段包含一个以 base64 编码的 JSON 补丁操作数组。 - -例如,设置`spec.replicas`的单个补丁操作将是`[{"op":"add","path":"/spec/replicas","value":3}]]`。 +例如,设置 `spec.replicas` 的单个补丁操作将是 `[{"op": "add", "path": "/spec/replicas", "value": 3}]`。 -以 Base64 编码,这将是`W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0=` +如果以 Base64 形式编码,这将是 `W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0=` + 因此,添加该标签的 webhook 响应为: - {{< tabs name="AdmissionReview_response_modify" >}} {{% tab name="admission.k8s.io/v1" %}} ```json @@ -776,7 +796,10 @@ So a webhook response to add that label would be: {{< /tabs >}} +## webhook 配置{#webhook-configuration} + -## Webhook-配置 - -要注册 admssion webhook,请创建`MutatingWebhookConfiguration`或`ValidatingWebhookConfiguration` API 对象。 +要注册 admssion webhook,请创建 `MutatingWebhookConfiguration` 或 `ValidatingWebhookConfiguration` API 对象。 -每种配置可以包含一个或多个 Web 钩子。如果在单个配置中指定了多个 webhook,则应为每个 webhook 赋予一个唯一的名称。 -这在`admissionregistration.k8s.io/v1`中是必需的,但在使用`admissionregistration.k8s.io/v1beta1`时强烈建议, -为了使生成的审核日志和指标更易于与活动配置匹配。 +每种配置可以包含一个或多个 webhook。如果在单个配置中指定了多个 webhook,则应为每个 webhook 赋予一个唯一的名称。 +这在 `admissionregistration.k8s.io/v1` 中是必需的,但是在使用 `admissionregistration.k8s.io/v1beta1` 时强烈建议使用,以使生成的审核日志和指标更易于与活动配置相匹配。 -每个 Webhook 定义以下内容。 +每个 webhook 定义以下内容。 +### 匹配请求-规则{#matching-requests-rules} + +每个 webhook 必须指定用于确定是否应将对 apiserver 的请求发送到 webhook 的规则列表。 +每个规则都指定一个或多个 operations、apiGroups、apiVersions 和 resources 以及资源的 scope: + +* `operations` 列出一个或多个要匹配的操作。可以是 `CREATE`、`UPDATE`、`DELETE`、`CONNECT` 或 `*` 以匹配所有内容。 +* `apiGroups` 列出了一个或多个要匹配的 API 组。`""` 是核心 API 组。`"*"` 匹配所有 API 组。 +* `apiVersions` 列出了一个或多个要匹配的 API 版本。`"*"` 匹配所有 API 版本。 +* `resources` 列出了一个或多个要匹配的资源。 + * `"*"` 匹配所有资源,但不包括子资源。 + * `"*/*"` 匹配所有资源,包括子资源。 + * `"pods/*"` 匹配 pod 的所有子资源。 + * `"*/status"` 匹配所有 status 子资源。 +* `scope` 指定要匹配的范围。有效值为 `"Cluster"`、`"Namespaced"` 和 `"*"`。子资源匹配其父资源的范围。在 Kubernetes v1.14+ 版本中才被支持。默认值为 `"*"`,对应 1.14 版本之前的行为。 + * `"Cluster"` 表示只有集群作用域的资源才能匹配此规则(API 对象 Namespace 是集群作用域的)。 + * `"Namespaced"` 意味着仅具有命名空间的资源才符合此规则。 + * `"*"` 表示没有范围限制。 + - -### 匹配请求-规则 - -每个 Webhook 必须指定用于确定是否应将对 apiserver 的请求发送到 Webhook 的规则列表。 -每个规则都指定一个或多个操作,apiGroups,apiVersions 和资源以及资源范围: - -*`operations`列出一个或多个要匹配的操作。可以是`CREATE`,`UPDATE`,`DELETE`,`CONNECT`或 `*` 以匹配所有内容。 - -*`apiGroups`列出了一个或多个要匹配的 API 组。``是核心 API 组。`*` 匹配所有 API 组。 - -*`apiVersions`列出了一个或多个要匹配的 API 版本。`*` 匹配所有 API 版本。 - -*`resources`列出了一个或多个要匹配的资源。 - *`*`匹配所有资源,但不匹配子资源。 - *`*/*` 匹配所有资源和子资源。 - *`pod/*` 匹配 pod 的所有子资源。 - *`*/status` 匹配所有状态子资源。 - -*`scope`指定要匹配的范围。有效值为`Cluster`,`Namespaced`和 `*`。子资源匹配其父资源的范围。在 v1.14+ 中受支持。默认值为`*`,匹配 1.14 之前的行为。 - *`Cluster`表示只有群集作用域的资源才能匹配此规则(名称空间 API 对象是群集作用域的)。 - *`Namespaced`意味着只有命名空间资源才符合此规则。 - *`*` 表示没有范围限制。 - -如果传入请求与任何 Webhook 规则的指定操作,组,版本,资源和范围匹配,则该请求将发送到 Webhook。 +如果传入请求与任何 Webhook 规则的指定操作、组、版本、资源和范围匹配,则该请求将发送到 Webhook。 以下是可用于指定应拦截哪些资源的规则的其他示例。 -将`CREATE`或`UPDATE`请求匹配到`apps/v1`和`apps/v1beta1`,`deployments`和`replicasets`: +匹配针对 `apps/v1` 和 `apps/v1beta1` 组中 `deployments` 和 `replicasets` 资源的 `CREATE` 或 `UPDATE` 请求: {{< tabs name="ValidatingWebhookConfiguration_rules_1" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -859,7 +877,7 @@ kind: ValidatingWebhookConfiguration webhooks: - name: my-webhook.example.com rules: - - operations: ["CREATE", "UPDATE"] + - operations: ["CREATE", "UPDATE"] apiGroups: ["apps"] apiVersions: ["v1", "v1beta1"] resources: ["deployments", "replicasets"] @@ -869,14 +887,14 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... webhooks: - name: my-webhook.example.com rules: - - operations: ["CREATE", "UPDATE"] + - operations: ["CREATE", "UPDATE"] apiGroups: ["apps"] apiVersions: ["v1", "v1beta1"] resources: ["deployments", "replicasets"] @@ -910,7 +928,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... @@ -927,9 +945,12 @@ webhooks: {{% /tab %}} {{< /tabs >}} + +匹配所有 API 组和版本中所有 `status` 子资源的更新请求: -{{< tabs name="ValidatingWebhookConfiguration_rules_3" >}} +{{< tabs name="ValidatingWebhookConfiguration_rules_2" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} ```yaml apiVersion: admissionregistration.k8s.io/v1 @@ -938,63 +959,64 @@ kind: ValidatingWebhookConfiguration webhooks: - name: my-webhook.example.com rules: - - operations: ["UPDATE"] + - operations: ["CREATE"] apiGroups: ["*"] apiVersions: ["*"] - resources: ["*/status"] + resources: ["*"] scope: "*" ... ``` {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... webhooks: - name: my-webhook.example.com rules: - - operations: ["UPDATE"] + - operations: ["CREATE"] apiGroups: ["*"] apiVersions: ["*"] - resources: ["*/status"] + resources: ["*"] scope: "*" ... ``` {{% /tab %}} {{< /tabs >}} + +### 匹配请求:objectSelector{#matching-requests-objectselector} + +在版本 v1.15+ 中, 通过指定 `objectSelector`,webhook 能够根据可能发送的对象的标签来限制哪些请求被拦截。如果指定,则将对 `objectSelector` 和可能发送到 webhook 的 object 和 oldObject 进行评估。如果两个对象之一与选择器匹配,则认为该请求已匹配。 + +空对象(对于创建操作而言为 oldObject,对于删除操作而言为 newObject),或不能带标签的对象(例如 `DeploymentRollback` 或 `PodProxyOptions` 对象)被认为不匹配。 + +仅当选择使用 webhook 时才使用对象选择器,因为最终用户可以通过设置标签来跳过 admission webhook。 + -### 匹配请求-对象选择器 - -在v1.15 +中,基于Web服务的标签,webhook 可以选择限制拦截哪些请求 -通过指定一个 objectSelector 来发送它们的对象。如果指定,则为 objectSelector同时针对将要发送到Webhook的对象和oldObject进行评估, -并且如果两个对象中的任何一个与选择器都匹配,则视为匹配。 +这个例子展示了一个 mutating webhook,它将匹配带有标签 `foo:bar` 的任何资源的 `CREATE` 的操作: -空对象(对于 create 而言为 oldObject,对于 delete 而言为 newObject), -或没有标签的对象(例如 DeploymentDeployRollback 或 PodProxyOptions 对象) -被认为不匹配。 - -仅在选择加入 Webhook 时才使用对象选择器,因为最终用户可以通过设置标签来跳过 admission Webhook。 - -这个例子展示了一个可变的 webhook,它将匹配带有标签`foo:bar`的任何资源的`CREATE`: - -{{< tabs name="ValidatingWebhookConfiguration_example_1" >}} +{{< tabs name="objectSelector_example" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} ```yaml apiVersion: admissionregistration.k8s.io/v1 @@ -1016,7 +1038,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration ... @@ -1037,33 +1059,35 @@ webhooks: {{< /tabs >}} +有关标签选择器的更多示例,请参见[标签](/docs/concepts/overview/working-with-objects/labels)。 + +### 匹配请求:namespaceSelector {#matching-requests-namespaceselector} + +通过指定 `namespaceSelector`,Webhook 可以根据具有命名空间的资源所处的命名空间的标签来选择拦截哪些资源的操作。 + +`namespaceSelector` 根据命名空间的标签是否匹配选择器,决定是否针对具命名空间的资源(或 Namespace 对象)的请求运行 webhook。 +如果对象是除 Namespace 以外的集群范围的资源,则 `namespaceSelector` 标签无效。 + -有关标签选择器的更多示例,请参见 [更多](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels)。 - -### 匹配请求-命名空间选择器 - -Webhooks 可以选择限制拦截对命名空间资源的请求, -通过指定`namespaceSelector`,基于包含名称空间的标签。 +本例给出的 mutating webhook 将匹配到对命名空间中具命名空间的资源的 `CREATE` 请求,前提是这些资源不含值为 "0" 或 "1" 的 "runlevel" 标签: -namespaceSelector 命名空间选择器决定是否在对命名空间资源的请求上运行 webhook(或命名空间对象),取决于命名空间的标签是否与选择器匹配。 -如果对象本身是名称空间,则对`object.metadata.labels`执行匹配。 -如果对象是除命名空间以外的群集范围内的资源,则`namespaceSelector`无效。 - -这个例子展示了一个可变的webhook,它匹配命名空间内任何命名空间资源的`CREATE` -没有`0`或`1`的`runlevel`标签: {{< tabs name="MutatingWebhookConfiguration_namespaceSelector_1" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} ```yaml @@ -1088,7 +1112,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration ... @@ -1109,14 +1133,12 @@ webhooks: ``` {{% /tab %}} {{< /tabs >}} + - -此示例显示了一个验证 Webhook,该 Webhook 与名称空间内任何名称空间资源的`CREATE`匹配 -与`产品`或`阶段`的`环境`相关联: - +此示例显示了一个 validating webhook,它将匹配到对某命名空间中的任何具命名空间的资源的 `CREATE` 请求,前提是该命名空间具有值为 "prod" 或 "staging" 的 "environment" 标签: {{< tabs name="ValidatingWebhookConfiguration_namespaceSelector_2" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} ```yaml @@ -1141,7 +1163,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... @@ -1164,70 +1186,74 @@ webhooks: {{< /tabs >}} +有关标签选择器的更多示例,请参见[标签](/docs/concepts/overview/working-with-objects/labels)。 + +### 匹配请求:matchPolicy {#matching-requests-matchpolicy} + +API 服务器可以通过多个 API 组或版本来提供对象。 +例如,Kubernetes API 服务器允许通过 `extensions/v1beta1`、`apps/v1beta1`、`apps/v1beta2` 和 `apps/v1` API 创建和修改 `Deployment` 对象。 + +例如,如果一个 webhook 仅为某些 API 组/版本指定了规则(例如 `apiGroups:["apps"], apiVersions:["v1","v1beta1"]`),而修改资源的请求是通过另一个 API 组/版本(例如 `extensions/v1beta1`)发出的,该请求将不会被发送到 Webhook。 + +在 v1.15+ 中,`matchPolicy` 允许 webhook 定义如何使用其 `rules` 匹配传入的请求。 +允许的值为 `Exact` 或 `Equivalent`。 + +* `Exact` 表示仅当请求与指定规则完全匹配时才应拦截该请求。 +* `Equivalent` 表示如果某个请求意在修改 `rules` 中列出的资源,即使该请求是通过其他 API 组或版本发起,也应拦截该请求。 + +在上面给出的示例中,仅为 `apps/v1` 注册的 webhook 可以使用 `matchPolicy`: +* `matchPolicy: Exact` 表示不会将 `extensions/v1beta1` 请求发送到 Webhook +* `matchPolicy:Equivalent` 表示将 `extensions/v1beta1` 请求发送到 webhook(将对象转换为 webhook 指定的版本:`apps/v1`) -Specifying `Equivalent` is recommended, and ensures that webhooks continue to intercept the + +建议指定 `Equivalent`,确保升级后启用 API 服务器中资源的新版本时,webhook 继续拦截他们期望的资源。 + +当 API 服务器停止提供某资源时,该资源不再被视为等同于该资源的其他仍在提供服务的版本。 +例如,`extensions/v1beta1` 中的 Deployment 已被废弃,计划在 v1.16 中默认停止使用。 +在这种情况下,带有 `apiGroups:["extensions"], apiVersions:["v1beta1"], resources: ["deployments"]` 规则的 webhook 将不再拦截通过 `apps/v1` API 来创建 Deployment 的请求。 +["deployments"] 规则将不再拦截通过 `apps/v1` API 创建的部署。 + - -有关标签选择器的更多示例,请参见 [更多](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels)。 - -### 匹配请求-策略匹配 - -apiserver 可以通过多个 API 组或版本使对象可用。 -例如,Kubernetes apiserver 允许创建和修改`Deployment`对象 -通过 `extensions/v1beta1`,`apps/v1beta1`,`apps/v1beta2`和`apps/v1` APIs 进行。 - -例如,如果一个 Webhook 仅为某些`Api groups/version`指定了规则(例如`apiGroups:["apps"]`,`apiVersions:[`v1`,`v1beta1`]`), -并提出了通过另一个`Api groups/version`(例如`extensions/v1beta1`)修改资源的请求, -该请求将不会发送到 Webhook。 - -在 v1.15+ 中,`matchPolicy`允许 webhook 定义如何使用其`rules`匹配传入的请求。 -允许的值为`Exact`或`Equivalent`。 - -*`Exact`表示仅当请求与指定规则完全匹配时才应拦截该请求。 -*`Equivalent`表示如果修改了`rules`中列出的资源,即使通过另一个`Api groups/version`,也应拦截请求。 - -在上面给出的示例中,仅为`apps/v1`注册的 webhook 可以使用`matchPolicy`,`matchPolicy:Exact`表示将不会将`extensions/v1beta1`请求发送到 Webhook -*`matchPolicy:Equivalent`意味着将`extensions/v1beta1`请求发送到 webhook(将对象转换为 webhook 指定的版本:`apps/v1`) - -建议指定`Equivalent`,并确保 Webhook 继续拦截他们期望在升级时启用 apiserver 中资源的新版本的资源。 - -当资源停止由 apiserver 提供服务时,它不再被视为等同于仍在提供服务的该资源的其他版本。 -例如,计划在 v1.16 中默认停止使用已弃用的`extensions/v1beta1`部署。 -一旦发生,带有`apiGroups:["extensions"]`,`apiVersions:["v1beta1"]`,`resources:["deployments"]`规则的 webhook -将不再拦截通过`apps/v1` API 创建的部署。因此,webhooks 应该更优先注册用于稳定版本的资源。 - -此示例显示了一个验证 Webhook,该 Webhook 拦截对部署的修改(无论 API 组或版本), -并始终会发送一个`apps/v1`部署对象: +此示例显示了一个 validating webhook,该 Webhook 拦截对 Deployment 的修改(无论 API 组或版本是什么), +始终会发送一个 `apps/v1` 版本的 Deployment 对象: {{< tabs name="ValidatingWebhookConfiguration_matchPolicy" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -1246,15 +1272,16 @@ webhooks: scope: "Namespaced" ... ``` + -使用`admissionregistration.k8s.io/v1`创建的 admission webhhok 默认为`Equivalent`。 +使用 `admissionregistration.k8s.io/v1` 创建的 admission webhhok 默认为 `Equivalent`。 {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... @@ -1269,15 +1296,20 @@ webhooks: scope: "Namespaced" ... ``` + -使用`admissionregistration.k8s.io/v1beta1`创建的 admission webhhok 默认为`Exact`。 +使用 `admissionregistration.k8s.io/v1beta1` 创建的 admission webhhok 默认为 `Exact`。 {{% /tab %}} {{< /tabs >}} + +### 调用 Webhook + -### 调用 Webhook - -apiserver 确定请求应发送到 Webhook 后, -它需要知道如何调用 Webhook。这在`clientConfig`中指定 webhook 配置的节。 +API 服务器确定请求应发送到 webhook 后,它需要知道如何调用 webhook。此信息在 webhook 配置的 `clientConfig` 节中指定。 -可以通过 URL 或服务引用来调用 Webhooks,并且可以选择包含自定义 CA 包,以用于验证 TLS 连接。 +Webhook 可以通过 URL 或服务引用来调用,并且可以选择包含自定义 CA 包,以用于验证 TLS 连接。 +#### URL{#url} + +`url` 以标准 URL 形式给出 webhook 的位置(`scheme://host:port/path`)。 + +`host` 不应引用集群中运行的服务;通过指定 `service` 字段来使用服务引用。 +主机可以通过某些 apiserver 中的外部 DNS 进行解析。 +(例如,`kube-apiserver` 无法解析集群内 DNS,因为这将违反分层规则)。`host` 也可以是 IP 地址。 + +请注意,将 `localhost` 或 `127.0.0.1` 用作 `host` 是有风险的,除非您非常小心地在所有运行 apiserver 的、可能需要对此 webhook 进行调用的主机上运行。这样的安装可能不具有可移植性,即很难在新集群中启用。 + +scheme 必须为 "https";URL 必须以 "https://" 开头。 + +使用用户或基本身份验证(例如:"user:password@")是不允许的。 +使用片段("#...")和查询参数("?...")也是不允许的。 + -#### URL - -url以标准URL形式给出webhook的位置(`scheme://host:port/path`)。 - -`host`不应引用集群中运行的服务;采用通过指定`service`字段来提供服务引用。主机可以通过某些 apiserver 中的外部 DNS 进行解析 -(例如,`kube-apiserver`无法解析集群内 DNS 违反分层规则)。主机也可以是IP地址。 - -请注意,将 localhost 或 127.0.0.1 用作主机是除非您非常小心在所有主机上运行此 Webhook,否则风险很大 -运行一个 apiserver 可能需要对此进行调用 webhook。这样的安装很可能是不可移植的,即不容易出现在新集群中。 - -方案必须为`https`; URL 必须以`https://`开头。 - -尝试使用用户或基本身份验证,例如不允许使用`user:password@`。片段(`#...`)和查询参数(`?...`)也不允许。 +--> +这是配置为调用 URL 的 mutating Webhook 的示例(并且期望使用系统信任根证书来验证 TLS 证书,因此不指定 caBundle): -这是配置为调用 URL 的可变 Webhook 的示例(并且期望使用系统信任根来验证 TLS 证书,因此不指定 caBundle): {{< tabs name="MutatingWebhookConfiguration_url" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} ```yaml @@ -1348,7 +1385,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration ... @@ -1360,25 +1397,26 @@ webhooks: ``` {{% /tab %}} {{< /tabs >}} + +#### 服务引用 {#service-reference} + +`clientConfig` 内部的 Service 是对该 Webhook 服务的引用。如果 Webhook 在集群中运行,则应使用 `service` 而不是 `url`。服务的 `namespace` 和 `name` 是必需的。`port` 是可选的,默认值为 443。`path` 是可选的,默认为 "/"。 + -#### 服务参考 - -clientConfig 内部的 service 节是对该 Webhook 服务的引用。如果 Webhook 在集群中运行,则应使用`service`而不是`url`。 -服务名称空间和名称是必需的。端口是可选的,默认为 443。该路径是可选的,默认为`/`。 - -这是配置为在端口`1234`上调用服务的可变 Webhook 的示例在子路径`/my-path`下,并针对 ServerName 验证 TLS 连接 -使用自定义 CA 包的`my-service-name.my-service-namespace.svc`: +这是一个 mutating Webhook 的示例,该 mutating Webhook 配置为在子路径 "/my-path" 端口 "1234" 上调用服务,并使用自定义 CA 包针对 ServerName `my-service-name.my-service-namespace.svc` 验证 TLS 连接: {{< tabs name="MutatingWebhookConfiguration_service" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -1400,7 +1438,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration ... @@ -1419,21 +1457,36 @@ webhooks: {{< /tabs >}} +### 副作用{#side-effects} + +Webhook 通常仅对发送给他们的 `AdmissionReview` 内容进行操作。但是,某些 Webhook 在处理 admission 请求时会进行带外更改。 + +进行带外更改的(产生“副作用”的) Webhook 必须具有协调机制(如控制器),该机制定期确定事物的实际状态,并调整由 admission Webhook 修改的带外数据以反映现实情况。 +这是因为对 admission Webhook 的调用不能保证所准入的对象将原样保留,或根本不保留。 +以后,webhook 可以修改对象的内容,在写入存储时可能会发生冲突,或者服务器可以在持久保存对象之前关闭电源。 + +此外,处理 `dryRun: true` admission 请求时,具有副作用的 webhook 必须避免产生副作用。 +一个 webhook 必须明确指出在使用 `dryRun` 运行时不会有副作用,否则 `dry-run` 请求将不会发送到该 webhook,而 API 请求将会失败。 + +Webhook 使用 webhook 配置中的 `sideEffects` 字段显示它们是否有副作用: +* `Unknown`:有关调用 Webhook 的副作用的信息是不可知的。 +如果带有 `dryRun:true` 的请求将触发对该 Webhook 的调用,则该请求将失败,并且不会调用该 Webhook。 +* `None`:调用 webhook 没有副作用。 +* `Some`:调用 webhook 可能会有副作用。 +如果请求具有 `dry-run` 属性将触发对此 Webhook 的调用,则该请求将会失败,并且不会调用该 Webhook。 +* `NoneOnDryRun`:调用 webhook 可能会有副作用,但是如果将带有 `dryRun: true` 属性的请求发送到 webhook,则 webhook 将抑制副作用(该 webhook 可识别 `dryRun`)。 + +允许值: +* 在 `admissionregistration.k8s.io/v1beta1` 中,`sideEffects` 可以设置为 `Unknown`、`None`、`Some` 或者 `NoneOnDryRun`,并且默认值为 `Unknown`。 +* 在 `admissionregistration.k8s.io/v1` 中, `sideEffects` 必须设置为 `None` 或者 `NoneOnDryRun`。 + -### 副作用 - -Webhook 通常只对发送给他们的`AdmissionReview`的内容起作用。 -但是,某些 Webhook 在处理接纳请求时会进行带外更改。 - -进行带外更改(`副作用`)的 Webhooks 也必须具有协调机制(如控制器)定期确定世界的实际状态并进行调整录入 Webhook 修改的带外数据以反映现实情况。 -这是因为对 admission Webhook 的调用不能保证所准入的对象将原样保留或完全保留。后来的 webhook 可以修改对象的内容,在写入存储设备时可能会发生冲突, -否则服务器可以在持久保存对象之前关闭电源。 - -另外,当处理`dryRun:true`接纳请求时,具有副作用的 webhooks 必须跳过那些副作用。 -一个webhook必须明确指出在使用`dryRun`运行时不会产生副作用, -否则试运行请求将不会发送到 Webhook,而 API 请求将失败。 +这是一个 validating webhook 的示例,表明它对 `dryRun: true` 请求没有副作用: -Webhooks 使用 webhook 配置中的`sideEffects`字段指示它们是否有副作用: -*`Unknown`:未知有关调用 Webhook 的副作用的信息。 -如果带有`dryRun:true`的请求将触发对该 Webhook 的调用,则该请求将失败,并且不会调用该 Webhook。 -*`None`:调用 webhook 不会有副作用。 -*`Some`:调用 webhook 可能会有副作用。 -如果具有 dry-run 属性的请求将触发对此 Webhook 的调用,则该请求将失败,并且不会调用该 Webhook。 -*`NoneOnDryRun`:调用 webhook 可能会有副作用, -但是如果将带有`dryRun:true`的请求发送到 Webhook,则该 Webhook 将抑制副作用(该 Webhook 可识别`dryRun`)。 - -允许值: -*在`admissionregistration.k8s.io/v1beta1`中,`sideEffects`可以设置为`Unknown`,`None`,`Some`,或者`NoneOnDryRun`,并且默认为`Unknown`。 -*在`admissionregistration.k8s.io/v1`中,`sideEffects`必须设置为`None`或`NoneOnDryRun`。 - -这是一个验证 webhook 的示例,表明它对`dryRun:true`请求没有副作用: {{< tabs name="ValidatingWebhookConfiguration_sideEffects" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} ```yaml @@ -1490,7 +1532,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... @@ -1501,30 +1543,33 @@ webhooks: ``` {{% /tab %}} {{< /tabs >}} + +### 超时{#timeouts} + +由于 Webhook 会增加 API 请求的延迟,因此应尽快完成自身的操作。 +`timeoutSeconds` 用来配置在将调用视为失败之前,允许 API 服务器等待 Webhook 响应的时间长度。 -If the timeout expires before the webhook responds, the webhook call will be ignored or + +如果超时在 Webhook 响应之前被触发,则基于[失败策略](#failure-policy),将忽略 Webhook 调用或拒绝 API 调用。 -### 超时 - -由于 Webhooks 会增加 API 请求的延迟,因此应尽快评估。timeoutSeconds 允许配置 apiserver 等待 Webhook 响应的时间在将通话视为失败之前。 - -如果超时在 Webhook 响应之前到期,则 Webhook 调用将被忽略或 API 调用将基于 [失败策略](#失败策略) 被拒绝。 - -超时值必须在 1 到 30 秒之间。 +超时值必须设置在 1 到 30 秒之间。 -这是一个自定义超时为 2 秒的验证 Webhook 的示例: +这是一个自定义超时设置为 2 秒的 validating Webhook 的示例: {{< tabs name="ValidatingWebhookConfiguration_timeoutSeconds" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -1537,14 +1582,15 @@ webhooks: timeoutSeconds: 2 ... ``` + -使用`admissionregistration.k8s.io/v1`创建的 admission Webhook 默认超时为 10 秒。 +使用 `admissionregistration.k8s.io/v1` 创建的 admission webhook 默认超时为 10 秒。 {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration ... @@ -1553,61 +1599,67 @@ webhooks: timeoutSeconds: 2 ... ``` + -使用`admissionregistration.k8s.io/v1`创建的 admission Webhook 默认超时为 30 秒。 +使用 `admissionregistration.k8s.io/v1beta1` 创建的 admission webhook 默认超时为 30 秒。 {{% /tab %}} {{< /tabs >}} + +### 再调用策略 {#reinvocation-policy} + +mutating 准入插件(包括 Webhook)的任何一种排序方式都不会适用于所有情况。(参见 https://issue.k8s.io/64333 示例)。mutating Webhook 可以向对象中添加新的子结构(例如向 `pod` 中添加 `container`),已经运行的其他 mutating 插件可能会对这些新结构有影响(就像在所有容器上设置 `imagePullPolicy` 一样)。 + +在 v1.15+ 中,允许 mutating 准入插件感应到其他插件所做的更改,如果 mutating webhook 修改了一个对象,则会重新运行内置的 mutating 准入插件,并且 mutating webhook 可以指定 `reinvocationPolicy` 来控制是否也重新调用它们。 + +可以将 `reinvocationPolicy` 设置为 `Never` 或 `IfNeeded`。 默认为 `Never`。 + +* `Never`: 在一次准入测试中,不得多次调用 Webhook。 +* `IfNeeded`: 如果在最初的 webhook 调用之后被其他对象的插件修改了被接纳的对象,则可以作为准入测试的一部分再次调用该 webhook。 + +要注意的重要因素有: + +* 不能保证附加调用的次数恰好是一。 +* 如果其他调用导致对该对象的进一步修改,则不能保证再次调用 webhook。 +* 使用此选项的 Webhook 可能会重新排序,以最大程度地减少额外调用的次数。 +* 要在确保所有 mutation 都完成后验证对象,请改用 validating admission webhook(推荐用于有副作用的 webhook)。 + -### 撤销策略 - -可变准入插件(包括 Webhooks)的单次订购不适用于所有情况(例如,请参见 [更多](#https://issue.k8s.io/64333)。可变的 Webhook 可以添加新的子结构 -到对象(例如向`pod`中添加`container`),以及其他已经运行可能会对这些新结构有影响(例如在所有容器上设置`imagePullPolicy`)。 - -在 v1.15+ 中,允许准入插件观察到其他插件所做的更改,如果可变的 Webhook 修改了一个对象,则会重新运行内置的可变准入插件, -并且可变的 Webhook 可以指定`reinvocationPolicy`来控制是否也重新调用它们。 - -可以将`reinvocationPolicy`设置为`Never`或者`IfNeeded`. 默认为`Never`.。 - -*`Never`:Webhook 在一次接纳评估中不得被多次调用 -*`IfNeeded`:如果对象被接纳,则可以再次调用 Webhook 作为准入评估的一部分 -最初的 webhook 调用之后,其他准入插件会被修改。 - -要注意的重要元素是: - -*附加调用的数量不能保证完全是一个。 -*如果其他调用导致对该对象的进一步修改,则不能保证再次调用 webhooks。 -*使用此选项的 Webhook 可能会重新排序,以最大程度地减少其他调用。 -*要在所有可变都保证完成后验证对象,请改用 验证 admission Webhook(建议对有副作用的 Webhook 使用)。 - -这是一个可变的 webhook 选择在以后的准入插件修改对象时重新调用的示例: +这是一个 mutating webhook 的示例,该 Webhook 在以后的准入插件修改对象时被重新调用: {{< tabs name="MutatingWebhookConfiguration_reinvocationPolicy" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -1623,7 +1675,7 @@ webhooks: {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration ... @@ -1634,13 +1686,20 @@ webhooks: ``` {{% /tab %}} {{< /tabs >}} + +mutating webhook 必须具有 [幂等](#idempotence) 性,并且能够成功处理已被接纳并可能被修改的对象的 mutating Web 钩子。对于所有 mutating admission webhook 都是如此,因为它们可以在对象中进行的任何更改可能已经存在于用户提供的对象中,但是对于选择重新调用的 webhook 来说是必不可少的。 + +### 失败策略 {#failure-policy} + +`failurePolicy` 定义了如何处理 admission webhook 中无法识别的错误和超时错误。允许的值为 `Ignore` 或 `Fail`。 -可变的 Webhook 必须是 [幂等](#幂等),能够成功处理他们已经允许的对象并可能进行修改。可变的 Webhook 都是如此,因为它们可以 -进行任何更改用户提供的对象中可能已经存在一个对象,但是对于选择重新调用的 Webhook 来说这是必不可少的。 - -### 失败策略 - -`failurePolicy`定义了来自 admission webhook 的无法识别的错误和超时错误被处理。允许的值为`Ignore`或者`Fail`。 +* `Ignore` 表示调用 webhook 的错误将被忽略并且允许 API 请求继续。 +* `Fail` 表示调用 webhook 的错误导致准入失败并且 API 请求被拒绝。 -*`Ignore`意味着调用 webhook 的错误将被忽略并且允许 API 请求继续。 -*`Fail`表示调用 webhook 的错误导致准入失败并且 API 请求被拒绝。 - -这是一个变异的 Webhook,配置为在调用接纳 Webhook 遇到错误时拒绝 API 请求: +这是一个 mutating webhook,配置为在调用准入 Webhook 遇到错误时拒绝 API 请求: {{< tabs name="MutatingWebhookConfiguration_failurePolicy" >}} {{% tab name="admissionregistration.k8s.io/v1" %}} @@ -1673,14 +1726,16 @@ webhooks: failurePolicy: Fail ... ``` + -使用`admissionregistration.k8s.io/v1`创建的 admission Webhook 将默认`failurePolicy`设置为`Fail`。 +使用 `admissionregistration.k8s.io/v1beta1` 创建的 admission webhook 将 `failurePolicy` 默认设置为 `Ignore`。 + {{% /tab %}} {{% tab name="admissionregistration.k8s.io/v1beta1" %}} ```yaml -# Deprecated in v1.16 in favor of admissionregistration.k8s.io/v1 +# v1.16 中被废弃,推荐使用 admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration ... @@ -1692,12 +1747,16 @@ webhooks: -使用`admissionregistration.k8s.io/v1`创建的 admission Webhook 将默认`failurePolicy`设置为`Ignore`。 +使用 `admissionregistration.k8s.io/v1beta1` 创建的 admission webhook 将 `failurePolicy` 默认设置为 `Ignore`。 {{% /tab %}} {{< /tabs >}} + +## 监控 Admission Webhook {#monitoring-admission-webhooks} + -## 监控 Admission Webhook +API 服务器提供了监视 admission Webhook 行为的方法。这些监视机制可帮助集群管理员回答以下问题: -apiserver 提供了监控 admission Webhook 行为的方法。这些监控机制可帮助集群管理员回答以下问题: +1. 哪个 mutating webhook 改变了 API 请求中的对象? -1. 哪个可变 webhook 使 API 请求中的对象变化? - -2. 可变 webhook 应用于对象有什么变化? +2. mutating webhook 对对象做了哪些更改? 3. 哪些 webhook 经常拒绝 API 请求?是什么原因拒绝? +### Mutating Webhook 审计注解 + +有时,了解 API 请求中的哪个 mutating Webhook 使对象改变以及该 Webhook 应用了哪些更改很有用。 + +在 v1.16+ 中,kube-apiserver 针对每个 mutating webhook 调用执行[审计](/docs/tasks/debug-application-cluster/audit/)操作。 +每个调用都会生成一个审计注解,记述请求对象是否发生改变,可选地还可以根据 webhook 的准入响应生成一个注解,记述所应用的修补。 +针对给定请求的给定执行阶段,注解被添加到审计事件中,然后根据特定策略进行预处理并写入后端。 + +事件的审计级别决定了要记录哪些注解: + +在 `Metadata` 或更高审计级别上,将使用 JSON 负载记录带有键名 `mutation.webhook.admission.k8s.io/round_{round idx}_index_{order idx}` 的注解, +该注解表示针对给定请求调用了 Webhook,以及该 Webhook 是否更改了对象。 + -### 更改 Webhook 审核注释 - -有时候了解API要求中的哪个可变 webhook 修改了对象,以及 webhook 适用。 - -在 v1.16+ 中,kube-apiserver 在每个可变的 Webhook 上执行 [auditing](/docs/tasks/debug-application-cluster/audit/)调用。每次调用都会生成审核注释 -捕获请求对象是否因调用而发生了变化,并可选地生成注释来捕获应用的对象来自 Webhook 接纳响应的补丁。在审核事件中为注释的给定阶段的给定请求设置注释。 -它的执行,然后根据某种策略进行预处理,并写入后端。 +例如,对于正在被重新调用的某 Webhook,所记录的注解如下。 +Webhook 在 mutating Webhook 链中排在第三个位置,并且在调用期间未改变请求对象。 -事件的审核级别确定要记录哪些注释: - -- 在`Metadata`审核级别或更高级别,带有键的注释`mutation.webhook.admission.k8s.io/round_{round idx} _index_ {order idx}`记录了 JSON 有效负载,表明 -Webhook 会针对给定的请求以及是否更改了对象而被调用。 - -例如,对于正在被重新调用的 Webhook,记录了以下注释。Webhook 在更改 webhook 链,并且在调用期间未更改请求对象。 ```yaml -# the audit event recorded +# 审计事件相关记录 { "kind": "Event", "apiVersion": "audit.k8s.io/v1", "annotations": { "mutation.webhook.admission.k8s.io/round_1_index_2": "{\"configuration\":\"my-mutating-webhook-configuration.example.com\",\"webhook\":\"my-webhook.example.com\",\"mutated\": false}" - # other annotations + # 其他注解 ... } - # other fields + # 其他字段 ... } ``` ```yaml -# the annotation value deserialized +# 反序列化的注解值 { "configuration": "my-mutating-webhook-configuration.example.com", "webhook": "my-webhook.example.com", @@ -1777,26 +1841,30 @@ Webhook 会针对给定的请求以及是否更改了对象而被调用。 } ``` -The following annotatino gets recorded for a webhook being invoked in the first round. The webhook is ordered the first in\ + +对于在第一轮中调用的 Webhook,所记录的注解如下。 +Webhook 在 mutating Webhook 链中排在第一位,并在调用期间改变了请求对象。 ```yaml -# the audit event recorded +# 审计事件相关记录 { "kind": "Event", "apiVersion": "audit.k8s.io/v1", "annotations": { "mutation.webhook.admission.k8s.io/round_0_index_0": "{\"configuration\":\"my-mutating-webhook-configuration.example.com\",\"webhook\":\"my-webhook-always-mutate.example.com\",\"mutated\": true}" - # other annotations + # 其他注解 ... } - # other fields + # 其他字段 ... } ``` ```yaml -# the annotation value deserialized +# 反序列化的注解值 { "configuration": "my-mutating-webhook-configuration.example.com", "webhook": "my-webhook-always-mutate.example.com", @@ -1804,30 +1872,38 @@ the mutating webhook chain, and mutated the request object during the invocation } ``` + +在 `Request` 或更高审计级别上,将使用 JSON 负载记录带有键名为 `patch.webhook.admission.k8s.io/round_{round idx}_index_{order idx}` 的注解, +该注解表明针对给定请求调用了 Webhook 以及应用于请求对象之上的修改。 + +例如,以下是针对正在被重新调用的某 Webhook 所记录的注解。 +Webhook 在 mutating Webhook 链中排在第四,并在其响应中包含一个 JSON 补丁,该补丁已被应用于请求对象。 ```yaml -# the audit event recorded +# 审计事件相关记录 { "kind": "Event", "apiVersion": "audit.k8s.io/v1", "annotations": { "patch.webhook.admission.k8s.io/round_1_index_3": "{\"configuration\":\"my-other-mutating-webhook-configuration.example.com\",\"webhook\":\"my-webhook-always-mutate.example.com\",\"patch\":[{\"op\":\"add\",\"path\":\"/data/mutation-stage\",\"value\":\"yes\"}],\"patchType\":\"JSONPatch\"}" - # other annotations + # 其他注解 ... } - # other fields + # 其他字段 ... } ``` ```yaml -# the annotation value deserialized +# 反序列化的注解值 { "configuration": "my-other-mutating-webhook-configuration.example.com", "webhook": "my-webhook-always-mutate.example.com", @@ -1841,20 +1917,36 @@ mutating webhook chain, and responded with a JSON patch which got applied to the ] } ``` + +### Amission webhook metrics + +Kube-apiserver 从 `/metrics` 端点公开 Prometheus 指标,这些指标可用于监控和诊断 apiserver 状态。以下指标记录了与 admission Webhook 相关的状态。 + +#### apiserver Admission Webhook rejection count + +有时,了解哪些 admission webhook 经常拒绝 API 请求以及拒绝的原因是很有用的。 + +在 v1.16+ 中,kube-apiserver 提供了 Prometheus 计数器度量值,记录了 admission Webhook 的拒绝次数。 +度量值的标签给出了 Webhook 拒绝该请求的原因: + +- `name`:拒绝请求 Webhook 的名称。 +- `operation`:请求的操作类型可以是 `CREATE`、`UPDATE`、`DELETE` 和 `CONNECT` 其中之一。 +- `type`:Admission webhook 类型,可以是 `admit` 和 `validating` 其中之一。 +- `error_type`:标识在 webhook 调用期间是否发生了错误并且导致了拒绝。其值可以是以下之一: + - `calling_webhook_error`:发生了来自 Admission Webhook 的无法识别的错误或超时错误,并且 webhook 的 [失败策略](#failure-policy) 设置为 `Fail`。 + - `no_error`:未发生错误。Webhook 在准入响应中以 `allowed: false` 值拒绝了请求。度量标签 `rejection_code` 记录了在准入响应中设置的 `.status.code`。 + - `apiserver_internal_error`:apiserver 发生内部错误。 +- `rejection_code`:当 Webhook 拒绝请求时,在准入响应中设置的 HTTP 状态码。 -### Amission webhook 监控指标 - -Kube-apiserver 从`/metrics`端点公开 Prometheus 指标,可用于监控和诊断 apiserver 状态。以下指标记录与准入网络挂钩相关的状态。 - -#### Apiserver Admission Webhook 拒绝次数 - -有时,了解哪些 Admission Webhook 经常拒绝 API 请求非常有用,并且拒绝的原因。 - -在 v1.16+ 中,kube-apiserver 公开了 Prometheus 计数器度量记录 Admission Webhook 拒绝。度量标准被标记为识别 Webhook 拒绝的原因: - --`name`:拒绝请求 Webhook 的名称。 --`operation`:请求的操作类型,可以是`CREATE`之一,更新,删除和连接。 --`type`:Admission webhook 类型,可以是`admit`和`validating`中的一种。 --`error_type`:标识在 webhook 调用期间是否发生了错误导致了拒绝。其值可以是以下之一: - -`calling_webhook_error`:发生了来自Admission Webhook 的无法识别的错误或超时错误,并且 - webhook 的 [失败策略](#失败策略) 设置为`Fail`。 - -`no_error`:未发生错误。Webhook 在准入中以`allowed:false`拒绝了请求响应。 - 度量标签`rejection_code`记录了在准入响应中设置的`.status.code`。 - -`apiserver_internal_error`:发生 apiserver 内部错误。 --`rejection_code`:在以下情况下在准入响应中设置的 HTTP 状态代码 webhook 拒绝了请求。 - -<-- + - 拒绝计数指标示例: ``` @@ -1909,11 +1987,19 @@ apiserver_admission_webhook_rejection_count{error_type="no_error",name="deny-unw ## Best practices and warnings ### Idempotence +--> +## 最佳实践和警告 +### 幂等性 {#idempotence} + + +幂等的 mutating admission Webhook 能够成功处理已经被它接纳甚或修改的对象。即使多次执行该准入测试,也不会产生与初次执行结果相异的结果。 + +#### 幂等 mutating admission Webhook 的示例: -## 最佳实践和警告 - -### 幂等 - -一个幂等的可变 Admission Webhook 能够成功处理它已经被接纳的对象并可能进行修改。可以多次应用准入,而不会改变结果初始应用程序。 +1. 对于 `CREATE` Pod 请求,将 Pod 的字段 `.spec.securityContext.runAsNonRoot` 设置为 true,以实施安全最佳实践。 -#### 幂等可变 Webhook 的示例: +2. 对于 `CREATE` Pod 请求,如果未设置容器的字段 `.spec.containers[].resources.limits`,设置默认资源限制值。 -1. 对于`CREATE` Pod 请求,请设置以下字段的`.spec.securityContext.runAsNonRoot`字段:转换为`true`,以实施安全性最佳做法。 +3. 对于 `CREATE` pod 请求,盲目地添加一个名为 `foo-sidecar` 的 sidecar 容器,而未查看 Pod 中是否已经有 `foo-sidecar` 容器。 -2. 对于`CREATE` Pod 请求,如果字段`.spec.containers[].resources.limits`未设置容器的容器,请设置默认资源限制。 - -3. 对于`CREATE` Pod 请求,如果尚不存在名称为`foo-sidecar`的容器,则注入名称为`foo-sidecar`的边车容器。 - -在上述情况下,可以安全地重新调用 Webhook,或接受已设置字段的对象。 +在上述情况下,可以安全地重新调用 Webhook,或接受已经设置了字段的对象。 +#### 非幂等 mutating admission Webhook 的示例: + +1. 对于 `CREATE` pod 请求,注入名称为 `foo-sidecar` 并带有当前时间戳的 sidecar 容器(例如 `foo-sidecar-19700101-000000`)。 + +2. 对于 `CREATE/UPDATE` pod 请求,如果容器已设置标签 `"env"` 则拒绝,否则将 `"env": "prod"` 标签添加到容器。 +3. 对于 `CREATE` pod 请求,盲目地添加一个名为 `foo-sidecar` 的 sidecar 容器,而未查看 Pod 中是否已经有 `foo-sidecar` 容器。 + + - -#### 非幂等可变 Admission Webhooks 的示例: - -1.对于`CREATE` pod 请求,注入一个名为`foo-sidecar`的边车容器当前时间戳后缀(例如`foo-sidecar-19700101-000000`)。 - -2.对于`CREATE/UPDATE` pod 请求,如果设置了标签`env`,则拒绝该请求,否则,将`env:prod`标签添加到标签组中。 - -3.对于`CREATE` pod 请求,附加一个名为`foo-sidecar`的 sidecar 容器而无需查看是否已经有`foo-sidecar`容器。 - -在上述第一种情况下,重新调用 Webhook 可能导致同一侧边车每次被多次注入 Pod 使用不同的容器名称。同样,如果 sidecar 已存在,则 webhook 可以注入重复的容器。 +在上述第一种情况下,重新调用该 Webhook 可能导致同一个 Sidecar 容器多次注入到 Pod 中,而且每次使用不同的容器名称。 +类似地,如果 Sidecar 已存在于用户提供的 Pod 中,则 Webhook 可能注入重复的容器。 在上述第二种情况下,重新调用 Webhook 将导致 Webhook 自身输出失败。 -在上述第三种情况下,重新调用 Webhook 将导致 pod 规范中的容器重复,这使得该请求无效,并被 apiserver 拒绝。 +在上述第三种情况下,重新调用 Webhook 将导致 Pod 规范中的容器重复,从而使请求无效并被 API 服务器拒绝。 ### 拦截对象的所有版本 -建议通过设置`.webhooks[].matchPolicy`,Admission webhooks 应该始终拦截对象的所有版本。到`Equivalent`。建议 Admission Webhook 应该优先注册资源的稳定版本。 -如果未能拦截对象的所有版本,则可能导致某些请求中的请求未实施准入策略版本。有关示例,请参见 [匹配请求-策略匹配](#匹配请求-策略匹配)。 +建议通过将 `.webhooks[].matchPolicy` 设置为 `Equivalent`,以确保 admission webhooks 始终拦截对象的所有版本。 +建议 admission webhooks 应该更偏向注册资源的稳定版本。如果无法拦截对象的所有版本,可能会导致准入策略未再某些版本的请求上执行。 +有关示例,请参见[匹配请求:matchPolicy](#matching-requests-matchpolicy)。 -### 可用性 +### 可用性 {#availability} -建议 Admission webhook 尽快评估(通常以毫秒为单位),因为它们会增加 API 请求的延迟。期望对 Webhooks 使用较小的超时。有关更多详细信息,请参见 [超时](#超时)。 +建议 admission webhook 尽快完成执行(时长通常是毫秒级),因为它们会增加 API 请求的延迟。 +建议对 Webhook 使用较小的超时值。有关更多详细信息,请参见[超时](#timeouts)。 -建议 Admission Webhook 应该利用某种形式的负载平衡,以提供高可用性和性能优势。如果群集中正在运行 Webhook,则可以在服务后面运行多个 Webhook 后端利用服务支持的负载平衡。 +建议 Admission Webhook 应该采用某种形式的负载均衡机制,以提供高可用性和高性能。 +如果集群中正在运行 Webhook,则可以在服务后面运行多个 Webhook 后端,以利用该服务支持的负载均衡。 ### 避免自托管的 Webhooks 中出现死锁 -如果配置了群集,则在群集内运行的 Webhook 可能会导致死锁拦截启动自己的 Pod 所需的资源。 +如果集群内的 Webhook 配置能够拦截启动其自己的 Pod 所需的资源,则该 Webhook 可能导致其自身部署时发生死锁。 -例如,可变 Admission Webhook 被配置为仅当在标签中设置了某个标签时才接纳`CREATE` pod 请求(例如`env:prod`)。Webhook 服务器在未设置`env`标签的部署中运行。 -当运行 Webhook 服务器 Pod 的节点变得不正常后,webhook 部署将尝试将 Pod 重新安排到另一个节点。但是请求将 -因为未设置`env`标签,所以现有的 webhook 服务器拒绝了它,并且无法进行迁移。 +例如,某 mutating admission webhook 配置为仅当 Pod 中设置了某个标签(例如 `"env": "prod"`)时,才接受 `CREATE` Pod 请求。 +Webhook 服务器在未设置 `"env"` 标签的 Deployment 中运行。当运行 Webhook 服务器的容器的节点运行不正常时,Webhook 部署尝试将容器重新调度到另一个节点。 +但是,由于未设置 `"env"` 标签,因此请求将被现有的 webhook 服务器拒绝,并且调度迁移不会发生。 -建议使用 [namespaceSelector](#匹配请求-命名空间选择器) 排除运行 Webhook 的名称空间。 +建议使用 [namespaceSelector](#matching-requests-namespaceselector) 排除 Webhook 所在的命名空间。 ### Side Effects + +建议 admission webhook 应尽可能避免副作用,这意味着该 admission webhook 仅对发送给他们的 `AdmissionReview` 的内容起作用,并且不要进行额外更改。 +如果 Webhook 没有任何副作用,则 `.webhooks[].sideEffects` 字段应设置为 `None`。 -建议 Admission Webhook 尽可能避免副作用,这意味着 Webhook 只能在发送给他们的`AdmissionReview`的内容,请勿进行带外更改。如果 Webhook 没有任何副作用,将`.webhooks[].sideEffects`字段应设置为`None`。 - -如果在准入评估过程中需要副作用,则在处理 AdmissionReview 对象将`DryRun`设置为`true`,并将`.webhooks[].sideEffects`字段设置为`NoneOnDryRun`。有关更多详细信息,请参见 [副作用](#副作用)。 +如果在 admission 执行期间存在副作用,则应在处理 `dryRun` 为 `true` 的 `AdmissionReview` 对象时避免产生副作用,并且其 `.webhooks[].sideEffects` 字段应设置为 `NoneOnDryRun`。 有关更多详细信息,请参见[副作用](#side-effects)。 +### 避免对 kube-system 命名空间进行操作 + +`kube-system` 命名空间包含由 Kubernetes 系统创建的对象,例如用于控制平面组件的服务账号,诸如 `kube-dns` 之类的 Pod 等。 +意外更改或拒绝 `kube-system` 命名空间中的请求可能会导致控制平面组件停止运行或者导致未知行为发生。 +如果您的 admission webhook 不想修改 Kubernetes 控制平面的行为,请使用 [`namespaceSelector`](#matching-requests-namespaceselector) 避免拦截 `kube-system` 命名空间。 -### 避免对 kube-system 名称空间进行操作 - -`kube-system`名称空间包含由 Kubernetes 系统创建的对象,例如服务负责控制平面组件,如`kube-dns`之类的 Pod。 -意外地更改或拒绝`kube-system`名称空间中的请求导致控制平面组件停止运行或引入未知行为。 -如果您的 Webhook 不打算修改控制平面上 Kubernetes 的行为,将`kube-system`命名空间排除在使用 [命名空间选择器](#匹配请求-命名空间选择器)。 {{% /capture %}}