Kubernetes-Kubernetes准入控制-《K8S实战学习笔记》

admin 2025-11-02 23:59:27 系统网络 来源:ZONE.CI 全球网 0 阅读模式
  • 准入控制器概述
  • 启用/关闭一个准入控制器
  • 内置准入控制器功能概述
  • 自定义准入控制器
  • 准入 Webhook 实战
    • 示例准入 webhook 应用

    准入控制器概述

    准入控制器是指当用户请求通过认证和授权之后,对象被持久化之前拦截 apiserver 的请求。

    准入控制器可以可以执行”验证”和”变更”操作。 其中,”变更”操作是指可以修改被接收的对象的meta信息。

    默认的控制器代码是编译进入 kube-apiserver 二进制文件的,只能由集群管理员配置。

    准入控制过程分为两个阶段。

    第一阶段,运行”变更”准入控制器。

    第二阶段,运行”验证”准入控制器。

    Ps: 某些控制器既是变更准入控制器又是验证准入控制器。

    如果任何一个阶段的任何控制器拒绝了该请求,则整个请求将立即被拒绝,并向终端用户返回一个错误。

    启用/关闭一个准入控制器

    kube-apiserverenable-admission-plugins 参数接受一个以逗号分隔的准入控制插件顺序列表。

    1. kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger

    上述命令中启用了 NamespaceLifecycleLimitRanger 准入控制插件。

    同样,disable-admission-plugins 参数也可以将传入的(以逗号分隔的) 准入控制插件列表禁用,即使是默认启用的插件也会被禁用。

    1. kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny

    我们可以查询哪些准入控制插件是默认启用的:

    1. kube-apiserver -h | grep enable-admission-plugins

    这些准入控制器都是 kubernetes 内置推荐的准入控制器。

    内置准入控制器功能概述

    自定义准入控制器

    除了上述我们提到的 Kubernetes 中内置的准入控制器插件外,Kubernetes 还提供了一种可以自定义开发的准入控制插件, 它是通过在运行时所配置的 webhook 的形式来运行的。

    准入 Webhook 是一种用于接收准入请求并对其进行处理的 HTTP 回调机制。

    我们可以定义两种类型的准入 webhook:

    • “验证”性质的准入 Webhook: ValidatingWebhookConfiguration
    • “修改”性质的准入 Webhook: MutatingWebhookConfiguration

    修改性质的准入 Webhook 会先被调用。 它们可以更改发送到 API 服务器的对象以执行自定义的设置默认值操作。

    在完成了所有对象修改并且 API 服务器也验证了所传入的对象之后, 验证性质的 Webhook 会被调用,并通过拒绝请求的方式来强制实施自定义的策略。

    准入 Webhook 实战

    准入 Webhook 本质上是集群控制平面的一部分。 因此,对于准入 Webhook 的编写,应该非常是谨慎的编写和部署。 下面,我们来看看如何快速编写一个 Webhook 。

    准入 Webhook 生效需要具备如下条件:

    • Kubernetes 集群版本至少为 v1.16
    • 确保启用 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 控制器。

    示例准入 webhook 应用

    对于一个准入 webhook 而言,需要包含如下三个步骤:

    1. 编写一个准入 webhook 应用。
    2. 部署 webhook 应用。
    3. 配置对应的 WebhookConfiguration 。

    在如下代码中,包含了 admission webhook 服务器 的示例实现。

    具体来说,webhook 处理由 apiserver 发送的 AdmissionReview 请求,并且将其决定作为 AdmissionResponse 对象以相同版本发送回去。

    下面,我们来一个示例的 ValidatingWebhookConfiguration 的配置:

    1. apiVersion: admissionregistration.k8s.io/v1
    2. kind: ValidatingWebhookConfiguration
    3. metadata:
    4. name: "pod-policy.example.com"
    5. webhooks:
    6. - name: "pod-policy.example.com"
    7. rules: # webhook 生效范围
    8. - apiGroups: [""] # "" 表示核心组,*匹配所有组
    9. apiVersions: ["v1"] # * 匹配所有组
    10. operations: ["CREATE"] # 支持 CREATE, UPDATE, DELETE, CONNECT, *
    11. resources: ["pods"] # "*" 匹配所有资源,但不包括子资源。"*/*" 匹配所有资源,包括子资源。"pods/*" 匹配 pod 的所有子资源。"*/status" 匹配所有 status 子资源。
    12. scope: "Namespaced" # 表示 namespace 级别生效, Cluster表示集群有效, * 表示全局生效
    13. clientConfig: # Webhook 的地址
    14. service:
    15. namespace: "example-namespace"
    16. name: "example-service"
    17. caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle containing the CA that signed the webhook's serving certificate>...tLS0K"
    18. admissionReviewVersions: ["v1", "v1beta1"]
    19. sideEffects: None
    20. timeoutSeconds: 5 # 超时时间默认为 10s

    当 apiserver 收到与 rules 相匹配的请求时,apiserver 按照 clientConfig 中指定的方式向 webhook 发送一个 admissionReview 请求。

    创建 webhook 配置后,系统将花费几秒钟使新配置生效。

    那么,apiserver 发送给 webhook 服务器的请求的格式是什么样的呢?一个示例如下:

    1. {
    2. "apiVersion": "admission.k8s.io/v1",
    3. "kind": "AdmissionReview",
    4. "request": {
    5. # 唯一标识此准入回调的随机 uid
    6. "uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
    7. # 传入完全正确的 group/version/kind 对象
    8. "kind": {"group":"autoscaling","version":"v1","kind":"Scale"},
    9. # 修改 resource 的完全正确的的 group/version/kind
    10. "resource": {"group":"apps","version":"v1","resource":"deployments"},
    11. # subResource(如果请求是针对 subResource 的)
    12. "subResource": "scale",
    13. # 在对 API 服务器的原始请求中,传入对象的标准 group/version/kind
    14. # 仅当 webhook 指定 `matchPolicy: Equivalent` 且将对 API 服务器的原始请求转换为 webhook 注册的版本时,这才与 `kind` 不同。
    15. "requestKind": {"group":"autoscaling","version":"v1","kind":"Scale"},
    16. # 在对 API 服务器的原始请求中正在修改的资源的标准 group/version/kind
    17. # 仅当 webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为 webhook 注册的版本时,这才与 `resource` 不同。
    18. "requestResource": {"group":"apps","version":"v1","resource":"deployments"},
    19. # subResource(如果请求是针对 subResource 的)
    20. # 仅当 webhook 指定了 `matchPolicy:Equivalent` 并且将对 API 服务器的原始请求转换为该 webhook 注册的版本时,这才与 `subResource` 不同。
    21. "requestSubResource": "scale",
    22. # 被修改资源的名称
    23. "name": "my-deployment",
    24. # 如果资源是属于名字空间(或者是名字空间对象),则这是被修改的资源的名字空间
    25. "namespace": "my-namespace",
    26. # 操作可以是 CREATE、UPDATE、DELETE 或 CONNECT
    27. "operation": "UPDATE",
    28. "userInfo": {
    29. # 向 API 服务器发出请求的经过身份验证的用户的用户名
    30. "username": "admin",
    31. # 向 API 服务器发出请求的经过身份验证的用户的 UID
    32. "uid": "014fbff9a07c",
    33. # 向 API 服务器发出请求的经过身份验证的用户的组成员身份
    34. "groups": ["system:authenticated","my-admin-group"],
    35. # 向 API 服务器发出请求的用户相关的任意附加信息
    36. # 该字段由 API 服务器身份验证层填充,并且如果 webhook 执行了任何 SubjectAccessReview 检查,则应将其包括在内。
    37. "extra": {
    38. "some-key":["some-value1", "some-value2"]
    39. }
    40. },
    41. # object 是被接纳的新对象。
    42. # 对于 DELETE 操作,它为 null。
    43. "object": {"apiVersion":"autoscaling/v1","kind":"Scale",...},
    44. # oldObject 是现有对象。
    45. # 对于 CREATE 和 CONNECT 操作,它为 null。
    46. "oldObject": {"apiVersion":"autoscaling/v1","kind":"Scale",...},
    47. # options 包含要接受的操作的选项,例如 meta.k8s.io/v CreateOptions、UpdateOptions 或 DeleteOptions。
    48. # 对于 CONNECT 操作,它为 null。
    49. "options": {"apiVersion":"meta.k8s.io/v1","kind":"UpdateOptions",...},
    50. # dryRun 表示 API 请求正在以 `dryrun` 模式运行,并且将不会保留。
    51. # 带有副作用的 Webhook 应该避免在 dryRun 为 true 时激活这些副作用。
    52. # 有关更多详细信息,请参见 http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request
    53. "dryRun": false
    54. }
    55. }

    Webhook 使用 HTTP 200 状态码、Content-Type: application/json 和一个包含 AdmissionReview 对象的 JSON 序列化格式来发送响应。

    该 AdmissionReview 对象与发送的版本相同,且其中包含的 response 字段已被有效填充。

    response 至少必须包含以下字段:

    • uid,从发送到 webhook 的 request.uid 中复制而来
    • allowed,设置为 true 或 false

    一个最简单允许请求的示例如下:

    1. {
    2. "apiVersion": "admission.k8s.io/v1",
    3. "kind": "AdmissionReview",
    4. "response": {
    5. "uid": "<value from request.uid>",
    6. "allowed": true
    7. }
    8. }

    Webhook 禁止请求的最简单响应示例:

    1. {
    2. "apiVersion": "admission.k8s.io/v1",
    3. "kind": "AdmissionReview",
    4. "response": {
    5. "uid": "<value from request.uid>",
    6. "allowed": false
    7. }
    8. }

    当拒绝请求时,Webhook 可以使用 status 字段自定义 http 响应码和返回给用户的消息。示例如下:

    1. {
    2. "apiVersion": "admission.k8s.io/v1",
    3. "kind": "AdmissionReview",
    4. "response": {
    5. "uid": "<value from request.uid>",
    6. "allowed": false,
    7. "status": {
    8. "code": 403,
    9. "message": "You cannot do this because it is Tuesday and your name starts with A"
    10. }
    11. }
    12. }

    当允许请求时,mutating准入 Webhook 也可以选择修改传入的对象。 这是通过在响应中使用 patch 和 patchType 字段来完成的。 当前唯一支持的 patchType 是 JSONPatch,其中的 patch 字段包含一个以 base64 编码的 JSON patch 操作数组。

    例如,设置 spec.replicas 的单个补丁操作将是:

    1. [{"op": "add", "path": "/spec/replicas", "value": 3}]

    如果以 Base64 形式编码,结果将是 W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0=

    因此,添加该标签的 webhook 响应为:

    1. {
    2. "apiVersion": "admission.k8s.io/v1",
    3. "kind": "AdmissionReview",
    4. "response": {
    5. "uid": "<value from request.uid>",
    6. "allowed": true,
    7. "patchType": "JSONPatch",
    8. "patch": "W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvcmVwbGljYXMiLCAidmFsdWUiOiAzfV0="
    9. }
    10. }
    01-shell脚本介绍-《shell脚本》 系统网络

    01-shell脚本介绍-《shell脚本》

    一、shell脚本是什么二、为什么要学shell,而不是其他计算机语言三、学习这门课程的优势四、学了能干什么五、学习什么内容六、学习的技巧七、成长路径八、学习环
    评论:0   参与:  17