1.知識準備
1.Webhook 是一種用於接收准入請求並對其進行處理的 HTTP 回撥機制
2.Webhook 接收來自apiserver的回撥,對回撥資源做一些校驗、注入、修改後設資料等工作
3.來一張圖片
2.環境準備
元件 | 版本 |
---|---|
OS | CentOS Linux release 7.6.1810 (Core) |
docker | 18.09.7 |
k8s | v1.15.2 |
golang | go1.16.9 darwin/amd64 |
ip | hostname |
---|---|
10.248.33.220 | k8s-master |
3.部署
3.1 建立相關證書
|># sh webhook-create-signed-cert.sh
creating certs in tmpdir ./webhook-certs
Generating RSA private key, 2048 bit long modulus
..................................................+++
.................+++
e is 65537 (0x10001)
certificatesigningrequest.certificates.k8s.io/wilsonchai-webhook-svc.default created
NAME AGE REQUESTOR CONDITION
wilsonchai-webhook-svc.default 0s kubernetes-admin Pending
certificatesigningrequest.certificates.k8s.io/wilsonchai-webhook-svc.default approved
secret/wilsonchai-webhook-certs created
3.2 建立許可權
|># kubectl apply -f yaml/rbac.yaml
serviceaccount/wilsonchai-webhook-sa changed
clusterrole.rbac.authorization.k8s.io/wilsonchai-webhook-cr changed
clusterrolebinding.rbac.authorization.k8s.io/wilsonchai-webhook-crb changed
3.3 建立 mutetingwebhookconfiguration
|># cat yaml/mutatingwebhookconfiguration.yaml | sh webhook-patch-ca-bundle.sh | kubectl apply -f -
mutatingwebhookconfiguration.admissionregistration.k8s.io/wilsonchai-webhook-example-cfg created
|># kubectl get mutatingwebhookconfiguration
NAME CREATED AT
wilsonchai-webhook-example-cfg 2021-11-08T03:34:39Z
3.4 namespace 打 label
kubectl label namespace default wilsonchai-webhook=enabled
3.5編譯程式碼並且上傳映象
|># sh build.sh 0.0.1
go: downloading github.com/golang/glog v1.0.0
go: downloading k8s.io/apimachinery v0.22.3
go: downloading github.com/unrolled/secure v1.0.9
go: downloading k8s.io/api v0.22.3
go: downloading github.com/gin-gonic/gin v1.7.4
go: downloading golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
go: downloading github.com/golang/protobuf v1.5.2
go: downloading github.com/go-playground/validator/v10 v10.4.1
go: downloading google.golang.org/protobuf v1.26.0
go: downloading github.com/gogo/protobuf v1.3.2
go: downloading k8s.io/klog/v2 v2.9.0
go: downloading github.com/google/gofuzz v1.1.0
go: downloading github.com/go-logr/logr v0.4.0
go: downloading sigs.k8s.io/structured-merge-diff/v4 v4.1.2
go: downloading github.com/json-iterator/go v1.1.11
go: downloading golang.org/x/net v0.0.0-20210520170846-37e1c6afe023
go: downloading github.com/google/go-cmp v0.5.5
Sending build context to Docker daemon 22.04MB
Step 1/3 : FROM alpine:latest
---> 389fef711851
Step 2/3 : Add wilsonchai-webhook /wilsonchai-webhook
---> 05381b24d25c
Step 3/3 : ENTRYPOINT ["./wilsonchai-webhook"]
---> Running in c36e1e7a0bfb
Removing intermediate container c36e1e7a0bfb
---> c4a4c7042625
Successfully built c4a4c7042625
Successfully tagged registry.cn-beijing.aliyuncs.com/wilsonchai/mutating-webhook:0.0.1
The push refers to repository [registry.cn-beijing.aliyuncs.com/wilsonchai/mutating-webhook]
85e0257311fe: Pushed
777b2c648970: Pushed
0.0.1: digest: sha256:6750fe64823810caa0ad7551a61ba4b4e6ee0ccd40ab93a76b6a1fb8bcdc5bee size: 740
3.6部署映象
|># kubectl apply -f yaml/deploy.yaml
deployment.apps/wilsonchai-webhook-deployment created
service/wilsonchai-webhook-svc created
|># kubectl get pod | grep wilsonchai-webhook
wilsonchai-webhook-deployment-8444c7d8dd-89qwp 1/1 Running 0 19s
至此,整個部署完成,是不是非常簡單,現在我們來測試一下是否能夠正常工作
4.測試
4.1 先開啟一個shell 1,監控wilsonchai-webhook的日誌輸出
|># kubectl logs -f wilsonchai-webhook-deployment-8444c7d8dd-89qwp
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /mutate --> main.WebhookCallback (4 handlers)
[GIN-debug] Listening and serving HTTPS on :443
4.2 開啟另一個shell 2,部署一個測試的deployment,busybox-test
|># kubectl apply -f yaml/busybox.yaml
deployment.apps/busybox-test created
4.3 回到shell 1,wilsonchai-webhook成功接收到來自api的回撥
[GIN] 2021/11/08 - 03:53:59 | 200 | 176.172µs | 10.244.0.0 | POST "/mutate?timeout=30s"
4.4 回到shell 2,檢視busybox-test是否部署成功
|># kubectl get pod | grep busybox
busybox-test-59c6487468-h4zx9 1/1 Running 0 110s
至此,部署成功
5.除錯模式
由於我們的開發環境在遠端(相對於k8s叢集),我們想要配置可以直接回撥到遠端的開發環境,方便我們除錯程式碼,here we go!!
5.1 k8s master上操作
5.1.1 刪除 k8s 叢集中的 wilsonchai-webhook
|># kubectl delete -f yaml/deploy.yaml
deployment.apps "wilsonchai-webhook-deployment" deleted
service "wilsonchai-webhook-svc" deleted
5.1.2 部署除錯模式
|># kubectl apply -f yaml/debug.yaml
service/wilsonchai-webhook-svc created
endpoints/wilsonchai-webhook-svc created
注意: 這裡的10.248.33.220,是我的k8s master ip,請大家自行替換成k8s master ip
...
apiVersion: v1
kind: Endpoints
metadata:
name: wilsonchai-webhook-svc
subsets:
- addresses:
- ip: 10.248.33.220
ports:
- port: 443
5.1.3 修改k8s master 的ssh配置(如果沒有,請新增),然後重啟
|># grep GatewayPorts /etc/ssh/sshd_config
GatewayPorts yes
|># systemctl restart sshd
5.2 回到開發機器操作
5.2.1 開啟一條ssh隧道
▶ ssh -N -R 10.248.33.220:443:127.0.0.1:443 root@10.248.33.220
root@10.248.33.220's password:
5.2.2 執行wilsonchai-webhook,這裡需要手工指向證書位置(證書就在“建立相關證書”小節中建立出來的webhook-certs中)
▶ go run main.go webhook.go -tlsCertFile webhook-certs/server-cert.pem -tlsKeyFile webhook-certs/server-key.pem
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /mutate --> main.WebhookCallback (4 handlers)
[GIN-debug] Listening and serving HTTPS on :443
至此,開發環境搭建完成,我們來測試一下
5.3 重建busybox-test
|># kubectl delete -f yaml/busybox.yaml
deployment.apps "busybox-test" deleted
|># kubectl apply -f yaml/busybox.yaml
deployment.apps/busybox-test created
5.4 檢視開發環境
[GIN] 2021/11/08 - 12:08:59 | 200 | 3.812455ms | 127.0.0.1 | POST "/mutate?timeout=30s"
沒錯,apiserver已經回撥到我們的開發環境了
6.原理淺析
6.1 mutate webhook
● 通過mutatingwebhookconfiguration,告訴apiserver哪一種資源需要回撥
● 用一個wilsonchai-webhook來接收回撥,並且進行適當的處理(本文只是打通流程,並沒有處理回撥內容)
● wilsonchai-webhook最後將回撥內容經過處理之後,回寫到apiserver去
● mutate webhook有30s的超時時間,超時之後apiserver將進入自己的流程,並在日誌列印一行錯誤
6.2 除錯
● 第一步,修改service 的endpoint,把請求流出k8s叢集
● 第二步,修改k8s master 的sshd_config,這樣做的目的是讓隧道監聽0.0.0.0,否則只能監聽127.0.0.1
● 第三步,建立一條ssh隧道,將訪問到k8s master的請求匯入到開發環境來
● 總的來說:apiserver --> wilsonchai-webhook-svc --> k8s master ip --> 開發環境
注意:如果你的k8s叢集能夠直接訪問開發環境,那就更加簡單,只需要把endpoint的address指向你的開發環境ip即可
7.小結
● 需要注意的是,本文的k8s是1.15.2版本的,如果是高於 v1.16,mutatingwebhookconfiguration的apiversion有變化,具體請參考官網
● 本文只是打通了流程,並沒有演示webhook的具體作用
● 本文中的程式碼:程式碼
8.參考
https://kubernetes.io/zh/docs/reference/access-authn-authz/extensible-admission-controllers/
https://www.qikqiak.com/post/k8s-admission-webhook/
至此,本文結束
在下才疏學淺,有撒湯漏水的,請各位不吝賜教...