8.5. 配置动态准入

此流程概述了配置动态准入的高级步骤。通过配置 webhook 准入插件来调用 webhook 服务器以扩展准入链的功能。

webhook 服务器也被配置为一个聚合的 API 服务器。这允许其他 OpenShift Container Platform 组件使用内部凭证与 webhook 通信,并可使用 oc 命令进行测试。另外,这还可在 webhook 中启用基于角色的访问控制(RBAC),并防止向 webhook 公开其他 API 服务器的令牌信息。

先决条件

  • 一个具有集群管理员权限的 OpenShift Container Platform 账户。
  • 已安装 OpenShift Container Platform CLI (oc)。
  • 公布的 webhook 服务器容器镜像。

流程

  1. 使用镜像 registry 构建 webhook 服务器容器镜像,并将其提供给集群。
  2. 创建本地 CA 密钥和证书,并使用它们为 webhook 服务器的证书签名请求(CSR)签名。
  3. 为 webhook 资源创建新项目:

    $ oc new-project my-webhook-namespace  1
    1
    请注意,webhook 服务器可能会需要一个特定的名称。
  4. 在名为 rbac.yaml 的文件中为聚合的 API 服务定义 RBAC 规则:

    apiVersion: v1
    kind: List
    items:
    
    - apiVersion: rbac.authorization.k8s.io/v1  1
      kind: ClusterRoleBinding
      metadata:
        name: auth-delegator-my-webhook-namespace
      roleRef:
        kind: ClusterRole
        apiGroup: rbac.authorization.k8s.io
        name: system:auth-delegator
      subjects:
      - kind: ServiceAccount
        namespace: my-webhook-namespace
        name: server
    
    - apiVersion: rbac.authorization.k8s.io/v1  2
      kind: ClusterRole
      metadata:
        annotations:
        name: system:openshift:online:my-webhook-server
      rules:
      - apiGroups:
        - online.openshift.io
        resources:
        - namespacereservations  3
        verbs:
        - get
        - list
        - watch
    
    - apiVersion: rbac.authorization.k8s.io/v1  4
      kind: ClusterRole
      metadata:
        name: system:openshift:online:my-webhook-requester
      rules:
      - apiGroups:
        - admission.online.openshift.io
        resources:
        - namespacereservations 5
        verbs:
        - create
    
    - apiVersion: rbac.authorization.k8s.io/v1  6
      kind: ClusterRoleBinding
      metadata:
        name: my-webhook-server-my-webhook-namespace
      roleRef:
        kind: ClusterRole
        apiGroup: rbac.authorization.k8s.io
        name: system:openshift:online:my-webhook-server
      subjects:
      - kind: ServiceAccount
        namespace: my-webhook-namespace
        name: server
    
    - apiVersion: rbac.authorization.k8s.io/v1  7
      kind: RoleBinding
      metadata:
        namespace: kube-system
        name: extension-server-authentication-reader-my-webhook-namespace
      roleRef:
        kind: Role
        apiGroup: rbac.authorization.k8s.io
        name: extension-apiserver-authentication-reader
      subjects:
      - kind: ServiceAccount
        namespace: my-webhook-namespace
        name: server
    
    - apiVersion: rbac.authorization.k8s.io/v1  8
      kind: ClusterRole
      metadata:
        name: my-cluster-role
      rules:
      - apiGroups:
        - admissionregistration.k8s.io
        resources:
        - validatingwebhookconfigurations
        - mutatingwebhookconfigurations
        verbs:
        - get
        - list
        - watch
      - apiGroups:
        - ""
        resources:
        - namespaces
        verbs:
        - get
        - list
        - watch
    
    - apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: my-cluster-role
      roleRef:
        kind: ClusterRole
        apiGroup: rbac.authorization.k8s.io
        name: my-cluster-role
      subjects:
      - kind: ServiceAccount
        namespace: my-webhook-namespace
        name: server
    1
    将身份验证和授权委托给 webhook 服务器 API。
    2
    允许 webhook 服务器访问集群资源。
    3
    指向资源。在这个示例中指向 namespacereservations 资源。
    4
    启用聚合的 API 服务器创建准入审核。
    5
    指向资源。在这个示例中指向 namespacereservations 资源。
    6
    启用 webhook 服务器访问集群资源。
    7
    角色绑定来读取终止身份验证的配置。
    8
    聚合的 API 服务器的默认集群角色和集群角色绑定。
  5. 将这些 RBAC 规则应用到集群:

    $ oc auth reconcile -f rbac.yaml
  6. 创建一个名为 webhook-daemonset.yaml 的 YAML 文件,用于将 webhook 部署为命名空间中的 DaemonSet 服务器:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      namespace: my-webhook-namespace
      name: server
      labels:
        server: "true"
    spec:
      selector:
        matchLabels:
          server: "true"
      template:
        metadata:
          name: server
          labels:
            server: "true"
        spec:
          serviceAccountName: server
          containers:
          - name: my-webhook-container  1
            image: <image_registry_username>/<image_path>:<tag>  2
            imagePullPolicy: IfNotPresent
            command:
            - <container_commands>  3
            ports:
            - containerPort: 8443 4
            volumeMounts:
            - mountPath: /var/serving-cert
              name: serving-cert
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8443 5
                scheme: HTTPS
          volumes:
          - name: serving-cert
            secret:
              defaultMode: 420
              secretName: server-serving-cert
    1
    请注意,webhook 服务器可能会预期有一个特定的容器名称。
    2
    指向 webhook 服务器容器镜像。将 <image_registry_username>/<image_path>:<tag> 替换为适当的值。
    3
    指定 webhook 容器运行命令。将 <container_commands> 替换为适当的值。
    4
    定义 pod 中的目标端口。这个示例使用端口 8443。
    5
    指定就绪探测使用的端口。这个示例使用端口 8443。
  7. 部署 DaemonSet:

    $ oc apply -f webhook-daemonset.yaml
  8. 在名为 webhook-secret.yaml 的 YAML 文件中为 service serving 证书签名程序定义 secret:

    apiVersion: v1
    kind: Secret
    metadata:
      namespace: my-webhook-namespace
      name: server-serving-cert
    type: kubernetes.io/tls
    data:
      tls.crt: <server_certificate>  1
      tls.key: <server_key>  2
    1
    引用签名的 webhook 服务器证书。将 <server_certificate> 替换为适当的 base64 格式的证书。
    2
    引用签名的 webhook 服务器密钥。将 <server_key> 替换为 base64 格式的适当密钥。
  9. 创建 secret:

    $ oc apply -f webhook-secret.yaml
  10. 在名为 webhook-service.yaml 的 YAML 文件中定义服务帐户和服务:

    apiVersion: v1
    kind: List
    items:
    
    - apiVersion: v1
      kind: ServiceAccount
      metadata:
        namespace: my-webhook-namespace
        name: server
    
    - apiVersion: v1
      kind: Service
      metadata:
        namespace: my-webhook-namespace
        name: server
        annotations:
          service.alpha.openshift.io/serving-cert-secret-name: server-serving-cert
      spec:
        selector:
          server: "true"
        ports:
        - port: 443  1
          targetPort: 8443  2
    1
    定义服务侦听的端口。这个示例使用端口 443。
    2
    定义服务转发连接到的 pod 中的目标端口。这个示例使用端口 8443。
  11. 在集群中公开 webhook 服务器:

    $ oc apply -f webhook-service.yaml
  12. 在名为 webhook-crd.yaml 的文件中为 webhook 服务器定义一个自定义资源定义(CRD):

    apiVersion: apiextensions.k8s.io/v1beta1
    kind: CustomResourceDefinition
    metadata:
      name: namespacereservations.online.openshift.io  1
    spec:
      group: online.openshift.io  2
      version: v1alpha1  3
      scope: Cluster  4
      names:
        plural: namespacereservations  5
        singular: namespacereservation  6
        kind: NamespaceReservation  7
    1
    反映自定义资源定义 spec 值,格式为 <plural>.<group>。在这个示例中使用 namespacereservations 资源。
    2
    REST API 组名称。
    3
    REST API 版本名称。
    4
    可接受的值是 NamespacedCluster
    5
    URL 中包括的复数名称。
    6
    oc 输出中的别名。
    7
    资源清单的引用。
  13. 应用自定义资源定义:

    $ oc apply -f webhook-crd.yaml
  14. 在名为 webhook-api-service.yaml 的文件中配置 webhook 服务器也作为一个聚合的 API 服务器:

    apiVersion: apiregistration.k8s.io/v1beta1
    kind: APIService
    metadata:
      name: v1beta1.admission.online.openshift.io
    spec:
      caBundle: <ca_signing_certificate>  1
      group: admission.online.openshift.io
      groupPriorityMinimum: 1000
      versionPriority: 15
      service:
        name: server
        namespace: my-webhook-namespace
      version: v1beta1
    1
    为 webhook 服务器使用的服务器证书签名的 PEM 编码的 CA 证书。将 <ca_signing_certificate> 替换为采用 base64 格式的适当证书。
  15. 部署聚合的 API 服务:

    $ oc apply -f webhook-api-service.yaml
  16. 在名为 webhook-config.yaml 的文件中定义 webhook 准入插件配置。本例使用验证准入插件:

    apiVersion: admissionregistration.k8s.io/v1beta1
    kind: ValidatingWebhookConfiguration
    metadata:
      name: namespacereservations.admission.online.openshift.io  1
    webhooks:
    - name: namespacereservations.admission.online.openshift.io  2
      clientConfig:
        service:  3
          namespace: default
          name: kubernetes
          path: /apis/admission.online.openshift.io/v1beta1/namespacereservations  4
        caBundle: <ca_signing_certificate>  5
      rules:
      - operations:
        - CREATE
        apiGroups:
        - project.openshift.io
        apiVersions:
        - "*"
        resources:
        - projectrequests
      - operations:
        - CREATE
        apiGroups:
        - ""
        apiVersions:
        - "*"
        resources:
        - namespaces
      failurePolicy: Fail
    1
    webhook 对象的名称。在这个示例中使用 namespacereservations 资源。
    2
    要调用的 webhook 的名称。在这个示例中使用 namespacereservations 资源。
    3
    通过聚合的 API 启用对 webhook 服务器的访问。
    4
    用于准入请求的 webhook URL。在这个示例中使用 namespacereservation 资源。
    5
    为 webhook 服务器使用的服务器证书签名的 PEM 编码的 CA 证书。将 <ca_signing_certificate> 替换为采用 base64 格式的适当证书。
  17. 部署 webhook:

    $ oc apply -f webhook-config.yaml
  18. 验证 webhook 是否如预期运行。例如,如果您配置了动态准入以保留特定的命名空间,请确认创建这些命名空间的请求会被拒绝,并且创建非保留命名空间的请求会成功。