kubernetes中开发自定义webhook

前言

关于webhook的应用场景网络上有很多介绍,这里就不再阐述了,这篇文章将带着我们从头开始部署自己的webhook。
本文适合对kubernetes和webhook有一定认知和了解的读者,帮助读者快速部署自己的webhook,话不多说直接开始。

准备

  1. 您需要会容器和镜像的知识,至少确保您会制作与运行镜像。
  2. 您已经部署好kubernetes环境。
  3. 您或许需要有一定编码来编写自己的webhook。

编写webhook服务

webhook是一个web服务,对外提供http接口供kubernetes调用,接口的定义参考:webhook请求与响应
目前各语言都有一些对开源依赖提供了对webhook请求对象的封装,笔者使用Java开发的webhook,使用了如下Maven依赖:

			<dependency>
                <groupId>io.fabric8</groupId>
                <artifactId>kubernetes-model</artifactId>
                <version>5.5.0</version>
            </dependency>

接口代码如下:

@RequestMapping("/validate")
    public AdmissionReview validateAdmissionReview(@RequestBody AdmissionReview requestBody) {
        AdmissionRequest request = requestBody.getRequest();
        AdmissionResponse response = new AdmissionResponse();
        response.setAllowed(true);
        response.setUid(request.getUid());
        requestBody.setResponse(response);
        return requestBody;
    }

另外webhook服务被要求提供HTTPS服务,所以我们需要为服务创建证书。

证书创建

kubernetes要求webhook使用带有SAN的证书,这里直接为大家提供生成脚本(请准备好openssl,按顺序执行一遍):

# 根密钥
openssl genpkey -algorithm RSA -out ca_key.pem -aes256

# 根证书生成请求
openssl req -sha256 -new -key ca_key.pem -out ca.csr

# 签名生成根证书
openssl x509 -req -sha256 -in ca.csr -signkey ca_key.pem -out ca.pem


# 生成服务器密钥和服务器证书请求
openssl req -sha256 -newkey rsa:2048 -nodes -keyout key.pem -out csr.pem -config cert.conf
# 用根证书签署请求文件得到服务器证书
openssl x509 -req -sha256 -in ca.csr -out cert.pem -CA ca.pem -CAkey ca_key.pem -CAcreateserial -days 365 -extensions v3_req -extfile cert.conf
# 服务器证书+根密钥打包为PKCS12
openssl pkcs12 -export -in cert.pem -inkey ca_key.pem -out cert.p12  

其中 cert.conf 文件内容如下:

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = webhooks.default.svc
DNS.2 = webhooks
DNS.3 = webhooks.default.cluster.local

cert.conf 的 DNS 列出了证书生效的域名,这里根据webhook在集群中实际访问域名修改

执行命令过程中会要求输入一些信息如下:

Enter PEM pass phrase:

上面的信息提示我们为密钥设置密码,最少4位数,如:1234.

Country Name (2 letter code) []: 
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:webhooks.default.svc
Email Address []:

需要注意 Common Name 是webhook的域名,需要根据实际访问域名做调整。

最终生成的 cert.p12 就是服务器证书的 PKCS12 文件,将证书配在服务中即可,如下以Springboot项目为例配置yaml:

server:
  ssl:
    key-store-type: PKCS12
    key-store: classpath:cert.p12
    key-store-password: 1234
    enabled: true
  port: 443

至此 webhook 服务本身的工作基本完成,可以先在本地用浏览器测试接口和证书的正确性(添加系统根证书)。

将 webhook 部署到 kubernetes

首先我们需要将webhook打包成镜像,这里就不再讲解打包镜像的方法。
这里我直接贴出webhook的deployment.yaml (其实就是部署Deployment和Service):

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webhooks
  name: webhooks
  namespace: default
spec:
  selector:
    matchLabels:
      app: webhooks
  template:
    metadata:
      labels:
        app: webhooks
    spec:
      containers:
        - image: 'k8s-webhooks:latest'
          imagePullPolicy: Always
          livenessProbe:
            failureThreshold: 3
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            tcpSocket:
              port: 443
            timeoutSeconds: 5
          name: webhooks
          ports:
            - containerPort: 443
              name: https
              protocol: TCP

---
apiVersion: v1
kind: Service
metadata:
  annotations: {}
  labels:
    app: webhooks
  name: webhooks
  namespace: default
spec:
  clusterIP: None
  clusterIPs:
    - None
  internalTrafficPolicy: Cluster
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack
  ports:
    - name: 5nb2b7
      port: 443
      protocol: TCP
      targetPort: 443
  selector:
    app: webhooks
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

至此,我们可以验证一下kubernetes中的webhook和service是否能正常访问。

添加RBAC

webhook需要一个用户承载监听和修改对象的权限(可以参考如下yaml创建):

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admission-webhook
  labels:
    app: admission-webhook

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: admission-webhook-cr
  labels:
    app: admission-webhook
rules:
  - apiGroups:
      - qikqiak.com
    resources:
      - "*"
    verbs:
      - "*"
  - apiGroups:
      - ""
    resources:
      - pods
      - events
    verbs:
      - "*"
  - apiGroups:
      - apps
    resources:
      - deployments
      - daemonsets
      - replicasets
      - statefulsets
    verbs:
      - "*"
  - apiGroups:
      - autoscaling
    resources:
      - '*'
    verbs:
      - '*'

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: admission-webhook-crb
  labels:
    app: admission-webhook
subjects:
  - kind: ServiceAccount
    name: admission-webhook-sa
    namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admission-webhook-cr

创建 webhook 对象

最后我们在 kubernetes 中部署一个 MutatingWebhookConfiguration:

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: mutating-webhook-cfg
  labels:
    app: admission-webhook
webhooks:
  - name: mutating-k8s.webhook.hkvax.com
    clientConfig:
      service:
        name: webhooks
        namespace: default
        path: "/validate"
        port: 443
      caBundle: $CA_BUNDLE
    sideEffects: None
    admissionReviewVersions: ["v1", "v1beta1"]
    rules:
      - operations: [ "CREATE","UPDATE" ]
        apiGroups: ["apps", ""]
        apiVersions: ["v1"]
        resources: ["deployments","services"]
    objectSelector:
      matchLabels:
        admission-webhook: enabled

objectSelector 字段中指定了webhook的匹配规则,这里只匹配了标签中拥有admission-webhook: enabled 的对象。
yaml中 $CA_BUNDLE 是webhook服务的根证书(BASE64编码),可以直接通过以下脚本获取:

$(< ca.pem base64 | tr -d '\n')

其中 ca.pem 是我们在篇头创建证书时生成的文件。

验证

我们可以通过 kubectl 修改 deployment, 添加admission-webhook: enabled标签后保存。具体指令如下:

kubectl edit deployment  xxx

当然我们也可以通过譬如kubord这样的管理控制台直接修改。

修改完成后观察 webhook 服务中的日志,如果webhook正常收到了请求则表示证书没有问题(笔者在证书环境卡了很长时间,最终才得出了文中给出的证书脚本)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值