如何使用cert-manager管理webhook证书

2024-01-03  本文已影响0人  wwq2020

准备证书

创建cert.yaml,内容如下,执行kubectl apply -f cert.yaml

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: admission-webhook-demo-issuer
  namespace: default
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: admission-webhook-demo-tls-secret
  namespace: default
spec:
  duration: 8760h
  renewBefore: 8000h
  subject:
    organizations:
      - xx.com
  commonName: admission-webhook-demo.default
  isCA: false
  privateKey:
    algorithm: RSA
    encoding: PKCS1
    size: 2048
  usages:
    - digital signature
    - key encipherment
    - server auth
  dnsNames:
    - admission-webhook-demo
    - admission-webhook-demo.default
    - admission-webhook-demo.default.svc
    - admission-webhook-demo.default.svc:443
  issuerRef:
    kind: Issuer
    name: admission-webhook-demo-issuer
  secretName: admission-webhook-demo-certs

准备webhook

webhook内annotations的cert-manager.io/inject-ca-from对应的值一定要和上面的Certificate的namespace和name一致

创建webhook.yaml,内容如下,执行kubectl apply -f webhook.yaml

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: validation-webhook-demo-cfg
  annotations:
    cert-manager.io/inject-ca-from: default/admission-webhook-demo-tls-secret
webhooks:
  - name: tenant-labels.xx.com
    admissionReviewVersions:
      - v1
    clientConfig:
      caBundle: ""
      service:
        name: admission-webhook-demo
        namespace: default
        port: 443
        path: /pods/validate
    rules:
      - operations: ["CREATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
    namespaceSelector:
      matchLabels:
        admission-webhook-demo: enabled
    failurePolicy: Fail
    matchPolicy: Exact
    sideEffects: None

demo

创建main.go,内容如下,构建镜像webhook-demo:v0.1

package main

import (
    "context"
    "net/http"

    "log/slog"

    admissionv1 "k8s.io/api/admission/v1"
    corev1 "k8s.io/api/core/v1"

    "k8s.io/apimachinery/pkg/runtime"
    clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    ctrl "sigs.k8s.io/controller-runtime"
    "sigs.k8s.io/controller-runtime/pkg/webhook"
    "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

var (
    scheme = runtime.NewScheme()
)

func init() {
    clientgoscheme.AddToScheme(scheme)
}

func main() {
    server := webhook.NewServer(webhook.Options{
        CertDir: "/tls",
    })

    decoder := admission.NewDecoder(scheme)
    server.Register("/pods/validate", &webhook.Admission{Handler: &podValidationHandler{decoder}})
    if err := server.Start(ctrl.SetupSignalHandler()); err != nil {
        slog.Error("failed to Start", "err", err)
        return
    }
}

type podValidationHandler struct {
    decoder *admission.Decoder
}

func (h *podValidationHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
    switch req.Operation {
    case admissionv1.Create:
        return h.HandleCreate(ctx, req)
    default:
        return webhook.Allowed(string(req.Operation))
    }
}

func (h *podValidationHandler) HandleCreate(ctx context.Context, req admission.Request) admission.Response {
    pod := &corev1.Pod{}
    if err := h.decoder.Decode(req, pod); err != nil {
        return webhook.Errored(http.StatusBadRequest, err)
    }
    if len(pod.Labels) == 0 {
        return webhook.Denied("missing labels")
    }
    if pod.Labels["tenant"] != "dev" {
        return webhook.Denied("invalid tenant")
    }
    return admission.Allowed("allowed")
}

创建service.yaml,内容如下,执行kubectl apply -f service.yaml

apiVersion: v1
kind: Service
metadata:
  name: admission-webhook-demo
  namespace: default
spec:
  ports:
  - port: 443
    protocol: TCP
    targetPort: 9443
  selector:
    app: admission-webhook-demo
  type: ClusterIP

创建deployment.yaml,内容如下,执行kubectl apply -f deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: admission-webhook-demo
  namespace: default
spec:
  selector:
    matchLabels:
      app: admission-webhook-demo
  template:
    metadata:
      labels:
        app: admission-webhook-demo
    spec:
      containers:
      - image: webhook-demo:v0.1
        name: app
        volumeMounts:
        - mountPath: /tls
          name: tls
          readOnly: true
      dnsPolicy: ClusterFirst
      volumes:
      - name: tls
        secret:
          defaultMode: 420
          secretName: admission-webhook-demo-certs
上一篇 下一篇

猜你喜欢

热点阅读