命煦砌 发表于 2026-1-5 11:40:00

从手动到自动:基于 Mutating Admission Webhook 实现 Envoy Sidecar 自动注入

前言

上一小节我们详细讨论了如何做流量劫持,并且使用initContainers来做自动劫持的配置。但是目前还有一个问题,如果我们的系统有好几百个微服务,那作为重要的代理envoy,是手动注入的,难道每个微服务都要手动编辑一次 ?这显然是不可承受的,所以这一节,我们来详细讨论一下自动注入的问题
环境准备

由于本节只讨论容器注入,所以只需要准备一个普通的deployment就行了
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: default
spec:
replicas: 1
selector:
    matchLabels:
      app: backend
template:
    metadata:
      labels:
      app: backend
    spec:
      containers:
      - image: backend-service:v1
      imagePullPolicy: Never
      name: backend
      ports:
      - containerPort: 10000
          protocol: TCP
      resources: {}
      restartPolicy: Alwaysmutating admission webhooks


简单来说,就是当pod重启的时候,会发起一系列的过程,其中在mutating admission controller 这里,k8s提供了一个webhooks,可以回调到指定的地方去,所以我们需要创建一个server来处理该回调,添加一个容器进去,完成容器注入的工作
创建相关证书

cd /etc/kubernetes/pki创建openssl.cnf
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[ req_distinguished_name ]
CN = sidecar-webhook.default.svc

[ v3_req ]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = sidecar-webhook
DNS.2 = sidecar-webhook.default
DNS.3 = sidecar-webhook.default.svc从k8s根证书中创建证书
sudo openssl req -x509 -newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-days 365 -nodes \
-config openssl.cnf \
-extensions v3_req创建MutatingWebhookConfiguration

mytls=`cat tls.crt | base64 | tr -d '\n'`

echo 'apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: sidecar-injector
webhooks:
- name: sidecar.demo.io
clientConfig:
    service:
      name: sidecar-webhook
      namespace: default
      path: /mutate
    caBundle: '$mytls'
rules:
- apiGroups: [""]
    apiVersions: ["v1"]
    operations: ["CREATE"]
    resources: ["pods"]
admissionReviewVersions: ["v1"]
sideEffects: None' | kubectl apply -f -创建服务来接收webhook

自动注入服务
这没什么可说的,需要注意的就是注入pod的配置直接写在了代码里面,并且注入了2个部分,首先是sidecar container,其次是sidecar的volumes配置(pod级别的)
      patch := []mapinterface{}{
                {
                        "op":   "add",
                        "path": "/spec/containers/-",
                        "value": mapinterface{}{
                              "image":         "registry.cn-beijing.aliyuncs.com/wilsonchai/envoy:v1.32-latest",
                              "imagePullPolicy": "IfNotPresent",
                              "name":            "envoy",
                              "args":            []string{"-c", "/etc/envoy/envoy.yaml"},
                              "volumeMounts": []mapinterface{}{
                                        {
                                                "mountPath": "/etc/envoy",
                                                "name":      "envoy-config",
                                        },
                              },
                        },
                },
                {
                        "op":   "add",
                        "path": "/spec/volumes/-",
                        "value": mapinterface{}{
                              "configMap": mapinterface{}{
                                        "defaultMode": 420,
                                        "name":      "envoy-config",
                              },
                              "name": "envoy-config",
                        },
                },
      }▶ go run inject.go
2025/12/29 14:58:19 Webhook listening on :8443打开8443端口以便接收请求
创建访问路径

我们的服务在集群外,所以创建一个endpoint指向集群之外
echo 'apiVersion: v1
kind: Service
metadata:
name: sidecar-webhook
spec:
ports:
- port: 443
    targetPort: 8443
    protocol: TCP
type: ClusterIP

---

apiVersion: v1
kind: Endpoints
metadata:
name: sidecar-webhook
namespace: default
subsets:
- addresses:
- ip: 10.22.12.178
ports:
- port: 8443
    protocol: TCP' | kubectl apply -f -验证

重启backend服务,kubectl rollout restart deploy backend
cannot bind '0.0.0.0:10000': Address already in use出现了报错,这应该是由于envoy是监听10000端口,backend服务监听的也是10000端口,现在它们在一个net namespace,就肯定要报错了,所以改一下envoy的配置,监听另外一个端口吧,10000改成10001
      listeners:
      - name: ingress_listener
          address:
            socket_address:
            address: 0.0.0.0
            port_value: 10001再次重启查看pod状态
▶ kubectl get pod -owide -l app=backend
NAME                     READY   STATUS    RESTARTS   AGE    IP             NODE   NOMINATED NODE   READINESS GATES
backend-6bdf5d484b-5czgx   2/2   Running   0          100s   10.244.0.184   wilson   <none>         <none>查看详情

自动注入了envoy容器
至此,架构图如下:

精细化注入

按照目前的配置,只要有pod create,就立刻回调集群外的注入服务,如果k8s集群的服务很多,并且频繁的create/destroy,那就会对注入服务产生较大的压力。如果在这些服务中,只有一些服务是需要使用自动注入功能的,那 就需要更精细化的注入管理
namespace打标签

首先要调整一下MutatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: sidecar-injector
webhooks:
- name: sidecar.demo.io
namespaceSelector:
    matchLabels:
      sidecar-inject: "true"
...加上标签 sidecar-inject: "true",只有满足这个标签,才会回调到外部的注入服务,这样就可以大大减轻注入服务的压力了
再给namespace打上标签
kubectl label ns default sidecar-inject=truedefault namespace里面所有的pod,都会回调至外部注入服务
pod 打标签

这次不在namespace下,而是基于某个pod label
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: sidecar-injector
webhooks:
- name: sidecar.demo.io
objectSelector:
    matchLabels:
      sidecar-inject-pod: "true"
...然后再给deployment打标签,这里要注意打的是pod的标签
kubectl patch deployment backend \
--type='merge' \
-p '{
    "spec": {
      "template": {
      "metadata": {
          "labels": {
            "sidecar-inject-pod": "true"
          }
      }
      }
    }
}'小结

本文详细描述了怎么做自动注入:k8s配置修改+外部注入服务。其中需要注入的pod是写死在注入服务的,这部分可以抽出来,将配置写成configmap,或者在其他的配置中心中,这样就不用频繁的修改注入服务了
另外mutating webhooks可以拦截大部分k8s支持的资源,并且发送到所配置的外部服务中进行需要的配置,这就不单单是pod自动注入,而是资源拦截。比如我需要拦截configmap
echo 'apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: callback-configmap
webhooks:
- name: sidecar.demo.io
clientConfig:
    service:
      name: sidecar-webhook
      namespace: default
      path: /mutate
    caBundle: '$mytls'
rules:
- apiGroups: [""]
    apiVersions: ["v1"]
    operations: ["CREATE", "UPDATE"]
    resources: ["configmaps"]
admissionReviewVersions: ["v1"]
sideEffects: None' | kubectl apply -f -resources变更为configmap之后,就可以直接回调到外部服务。本章由于篇幅有限,就不对这个话题展开了,这个以后有需要再来详细讨论
联系我


[*]联系我,做深入的交流

至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

明思义 发表于 2026-1-14 05:42:03

谢谢分享,辛苦了

嗳诿 发表于 2026-1-14 15:36:25

这个有用。

后沛若 发表于 2026-1-15 07:53:32

收藏一下   不知道什么时候能用到

舒娅友 发表于 2026-1-15 20:42:37

这个有用。

祖柔惠 发表于 2026-1-19 12:45:58

谢谢分享,试用一下

聚怪闩 发表于 2026-1-20 17:10:08

不错,里面软件多更新就更好了

赐度虻 发表于 2026-1-20 21:49:07

东西不错很实用谢谢分享

栓州 发表于 2026-1-21 18:46:48

过来提前占个楼

啪炽 发表于 2026-1-22 10:46:09

用心讨论,共获提升!

任修 发表于 2026-1-23 08:16:33

喜欢鼓捣这些软件,现在用得少,谢谢分享!

酝垓 发表于 2026-1-23 10:09:32

感谢,下载保存了

撵延兵 发表于 2026-1-26 13:49:52

前排留名,哈哈哈

赏勿 发表于 2026-1-27 02:49:24

过来提前占个楼

班闵雨 发表于 2026-1-28 03:34:42

收藏一下   不知道什么时候能用到

嗳诿 发表于 2026-1-30 03:44:19

感谢,下载保存了

哈妙思 发表于 2026-2-2 02:53:30

用心讨论,共获提升!

郗燕岚 发表于 2026-2-7 09:55:44

东西不错很实用谢谢分享

任佳湍 发表于 2026-2-8 18:02:30

东西不错很实用谢谢分享

富账慕 发表于 2026-2-9 10:45:31

感谢分享,下载保存了,貌似很强大
页: [1] 2
查看完整版本: 从手动到自动:基于 Mutating Admission Webhook 实现 Envoy Sidecar 自动注入