自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇帶你kubebuilder 進階: webhook

開發(fā) 項目管理
準入控制存在兩種 WebHook,變更準入控制 MutatingAdmissionWebhook,和驗證準入控制 ValidatingAdmissionWebhook,執(zhí)行的順序是先執(zhí)行 MutatingAdmissionWebhook 再執(zhí)行 ValidatingAdmissionWebhook。

[[399996]]

在前面的文章當中我們已經(jīng)完成了 NodePool Operator 的基本功能開發(fā)與測試,但是有時候我們會有這種需求,例如創(chuàng)建或者刪除資源的時候需要對資源進行一些檢查的操作,如果校驗不成功就不通過?;蛘呤切枰谕瓿蓪嶋H的創(chuàng)建之前做一些其他操作,例如我創(chuàng)建一個 pod 之前對 pod 的資源做一些調(diào)整等。這些都可以通過準入控制的WebHook來實現(xiàn)。

準入控制存在兩種 WebHook,變更準入控制 MutatingAdmissionWebhook,和驗證準入控制 ValidatingAdmissionWebhook,執(zhí)行的順序是先執(zhí)行 MutatingAdmissionWebhook 再執(zhí)行 ValidatingAdmissionWebhook。

創(chuàng)建 webhook

我們通過命令創(chuàng)建相關(guān)的腳手架代碼和 api

  1. kubebuilder create webhook --group nodes --version v1 --kind NodePool --defaulting --programmatic-validation 

執(zhí)行之后可以看到多了一些 webhook 相關(guān)的文件和配置

  1.   ├── api 
  2.   │   └── v1 
  3.   │       ├── groupversion_info.go 
  4.   │       ├── nodepool_types.go 
  5. + │       ├── nodepool_webhook.go # 在這里實現(xiàn) webhook 的相關(guān)接口 
  6. + │       ├── webhook_suite_test.go # webhook 測試 
  7.   │       └── zz_generated.deepcopy.go 
  8.   ├── bin 
  9.   ├── config 
  10. + │   ├── certmanager # 用于部署 
  11.   │   ├── crd 
  12.   │   │   ├── bases 
  13.   │   │   │   └── nodes.lailin.xyz_nodepools.yaml 
  14.   │   │   ├── kustomization.yaml 
  15.   │   │   ├── kustomizeconfig.yaml 
  16.   │   │   └── patches 
  17.   │   │       ├── cainjection_in_nodepools.yaml 
  18. + │   │       └── webhook_in_nodepools.yaml 
  19.   │   ├── default 
  20.   │   │   ├── kustomization.yaml 
  21.   │   │   ├── manager_auth_proxy_patch.yaml 
  22.   │   │   ├── manager_config_patch.yaml 
  23. + │   │   ├── manager_webhook_patch.yaml 
  24. + │   │   └── webhookcainjection_patch.yaml 
  25.   │   ├── manager 
  26.   │   ├── prometheus 
  27.   │   ├── rbac 
  28.   │   ├── samples 
  29.   │   │   └── nodes_v1_nodepool.yaml 
  30. + │   └── webhook # webhook 部署配置 
  31.   ├── controllers 
  32.   ├── main.go 

實現(xiàn)邏輯

實現(xiàn) MutatingAdmissionWebhook 接口

這個只需要實現(xiàn) Default 方法就行

  1. // Default implements webhook.Defaulter so a webhook will be registered for the type 
  2. func (r *NodePool) Default() { 
  3.  nodepoollog.Info("default""name", r.Name
  4.  
  5.  // 如果 labels 為空,我們就給 labels 加一個默認值 
  6.  if len(r.Labels) == 0 { 
  7.   r.Labels["node-pool.lailin.xyz"] = r.Name 
  8.  } 

實現(xiàn) ValidatingAdmissionWebhook 接口

實現(xiàn) ValidatingAdmissionWebhook也是一樣只需要實現(xiàn)對應的方法就行了,默認是注冊了 Create 和 Update 事件的校驗,我們這里主要是限制 Labels 和 Taints 的 key 只能是滿足正則 ^node-pool.lailin.xyz/*[a-zA-z0-9]*$ 的固定格式

  1. // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. 
  2. //+kubebuilder:webhook:path=/validate-nodes-lailin-xyz-v1-nodepool,mutating=false,failurePolicy=fail,sideEffects=None,groups=nodes.lailin.xyz,resources=nodepools,verbs=create;update,versions=v1,name=vnodepool.kb.io,admissionReviewVersions={v1,v1beta1} 
  3.  
  4. var _ webhook.Validator = &NodePool{} 
  5.  
  6. // ValidateCreate implements webhook.Validator so a webhook will be registered for the type 
  7. func (r *NodePool) ValidateCreate() error { 
  8.  nodePoolLog.Info("validate create""name", r.Name
  9.  
  10.  return r.validate() 
  11.  
  12. // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type 
  13. func (r *NodePool) ValidateUpdate(old runtime.Object) error { 
  14.  nodePoolLog.Info("validate update""name", r.Name
  15.  
  16.  return r.validate() 
  17.  
  18. // ValidateDelete implements webhook.Validator so a webhook will be registered for the type 
  19. func (r *NodePool) ValidateDelete() error { 
  20.  nodePoolLog.Info("validate delete""name", r.Name
  21.  
  22.  // TODO(user): fill in your validation logic upon object deletion. 
  23.  return nil 
  24.  
  25. // validate 驗證 
  26. func (r *NodePool) validate() error { 
  27.  err := errors.Errorf("taint or label key must validatedy by %s", keyReg.String()) 
  28.  
  29.  for k := range r.Spec.Labels { 
  30.   if !keyReg.MatchString(k) { 
  31.    return errors.WithMessagef(err, "label key: %s", k) 
  32.   } 
  33.  } 
  34.  
  35.  for _, taint := range r.Spec.Taints { 
  36.   if !keyReg.MatchString(taint.Key) { 
  37.    return errors.WithMessagef(err, "taint key: %s", taint.Key
  38.   } 
  39.  } 
  40.  
  41.  return nil 

部署

實現(xiàn)了之后直接在 make run 是跑不起來的,因為 webhook 注冊的地址不對,我們這里先看一下如何進行部署運行,然后再來看如何對 WebHook 進行本地調(diào)試。

WebHook 的運行需要校驗證書,kubebuilder 官方建議我們使用 cert-manager 簡化對證書的管理,所以我們先部署一下 cert-manager 的服務

  1. kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml 

然后我們 build 鏡像并且將鏡像 load 到集群中

  1. make docker-build 
  2.  
  3. kind load docker-image --name kind --nodes kind-worker controller:latest 

然后查看一下 config/default/kustomization.yaml文件,確認 webhook 相關(guān)的配置沒有被注釋掉

  1. # Adds namespace to all resources. 
  2. namespace: node-pool-operator-system 
  3.  
  4. # Value of this field is prepended to the 
  5. # names of all resources, e.g. a deployment named 
  6. "wordpress" becomes "alices-wordpress"
  7. # Note that it should also match with the prefix (text before '-'of the namespace 
  8. # field above. 
  9. namePrefix: node-pool-operator- 
  10.  
  11. # Labels to add to all resources and selectors. 
  12. #commonLabels: 
  13. #  someName: someValue 
  14.  
  15. bases: 
  16. - ../crd 
  17. - ../rbac 
  18. - ../manager 
  19. # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 
  20. # crd/kustomization.yaml 
  21. - ../webhook 
  22. # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER''WEBHOOK' components are required. 
  23. - ../certmanager 
  24. # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'
  25. #- ../prometheus 
  26.  
  27. patchesStrategicMerge: 
  28. # Protect the /metrics endpoint by putting it behind auth. 
  29. # If you want your controller-manager to expose the /metrics 
  30. # endpoint w/o any authn/z, please comment the following line. 
  31. - manager_auth_proxy_patch.yaml 
  32.  
  33. # Mount the controller config file for loading manager configurations 
  34. # through a ComponentConfig type 
  35. #- manager_config_patch.yaml 
  36.  
  37. # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 
  38. # crd/kustomization.yaml 
  39. - manager_webhook_patch.yaml 
  40.  
  41. # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'
  42. # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 
  43. 'CERTMANAGER' needs to be enabled to use ca injection 
  44. - webhookcainjection_patch.yaml 
  45.  
  46. # the following config is for teaching kustomize how to do var substitution 
  47. vars: 
  48. # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 
  49. name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 
  50.   objref: 
  51.     kind: Certificate 
  52.     group: cert-manager.io 
  53.     version: v1 
  54.     name: serving-cert # this name should match the one in certificate.yaml 
  55.   fieldref: 
  56.     fieldpath: metadata.namespace 
  57. name: CERTIFICATE_NAME 
  58.   objref: 
  59.     kind: Certificate 
  60.     group: cert-manager.io 
  61.     version: v1 
  62.     name: serving-cert # this name should match the one in certificate.yaml 
  63. name: SERVICE_NAMESPACE # namespace of the service 
  64.   objref: 
  65.     kind: Service 
  66.     version: v1 
  67.     name: webhook-service 
  68.   fieldref: 
  69.     fieldpath: metadata.namespace 
  70. name: SERVICE_NAME 
  71.   objref: 
  72.     kind: Service 
  73.     version: v1 
  74.     name: webhook-service 

檢查一下 manager/manager.yaml 是否存在 imagePullPolicy: IfNotPresent不存在要加上

然后執(zhí)行部署命令即可

  1. make deploy 
  2.  
  3. # 檢查 pod 是否正常啟動 
  4. ▶ kubectl -n node-pool-operator-system get pods 
  5. NAME                                                     READY   STATUS              RESTARTS   AGE 
  6. node-pool-operator-controller-manager-66bd747899-lf7xb   0/2     ContainerCreating   0          7s 

使用 yaml 文件測試一下

  1. apiVersion: nodes.lailin.xyz/v1 
  2. kind: NodePool 
  3. metadata: 
  4.   name: worker 
  5. spec: 
  6.   labels: 
  7.     "xxx""10" 
  8.   handler: runc 

提交之后可以發(fā)現(xiàn)報錯,因為 label key 不滿足我們的要求

  1. ▶ kubectl apply -f config/samples/                                           
  2. Error from server (label key: xxx: taint or label key must validatedy by ^node-pool.lailin.xyz/*[a-zA-z0-9]*$): error when applying patch: 
  3. {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"nodes.lailin.xyz/v1\",\"kind\":\"NodePool\",\"metadata\":{\"annotations\":{},\"name\":\"worker\"},\"spec\":{\"handler\":\"runc\",\"labels\":{\"xxx\":\"10\"}}}\n"}},"spec":{"labels":{"node-pool.lailin.xyz/worker":null,"xxx":"10"},"taints":null}} 
  4. to
  5. Resource: "nodes.lailin.xyz/v1, Resource=nodepools", GroupVersionKind: "nodes.lailin.xyz/v1, Kind=NodePool" 
  6. Name"worker", Namespace: "" 
  7. for"config/samples/nodes_v1_nodepool.yaml": admission webhook "vnodepool.kb.io" denied the request: label key: xxx: taint or label key must validatedy by ^node-pool.lailin.xyz/*[a-zA-z0-9]*$ 

再用一個正常的 yaml 測試

  1. apiVersion: nodes.lailin.xyz/v1 
  2. kind: NodePool 
  3. metadata: 
  4.   name: worker 
  5. spec: 
  6.   labels: 
  7.     "node-pool.lailin.xyz/xxx""10" 
  8.   handler: runc 

可以正常提交

  1. ▶ kubectl apply -f config/samples/                      
  2. nodepool.nodes.lailin.xyz/worker configured 

本地調(diào)試

雖然 kubebuilder 已經(jīng)為我們做了很多事情將服務部署運行基本傻瓜化了,但是每次做一點點修改就需要重新編譯部署還是非常的麻煩,所以我們來看看如何在本地進行聯(lián)調(diào)。

  • PS: 這里會用到之前 4. kustomize 簡明教程 講到的 kustomize 的特性構(gòu)建開發(fā)環(huán)境,如果忘記了可以先看看之前的文章哦

我們先看看 config/webhook/manifests.yaml這里面包含了兩個準入控制的信息,不過他們的配置類似,我們看一個就行了,這里以 MutatingWebhookConfiguration 為例

  1. apiVersion: admissionregistration.k8s.io/v1 
  2. kind: MutatingWebhookConfiguration 
  3. metadata: 
  4.   creationTimestamp: null 
  5.   name: mutating-webhook-configuration 
  6. webhooks: 
  7. - admissionReviewVersions: 
  8.   - v1 
  9.   - v1beta1 
  10.   clientConfig: 
  11.     service: 
  12.       name: webhook-service 
  13.       namespace: system 
  14.       path: /mutate-nodes-lailin-xyz-v1-nodepool 
  15.   failurePolicy: Fail 
  16.   name: mnodepool.kb.io 
  17.   rules: 
  18.   - apiGroups: 
  19.     - nodes.lailin.xyz 
  20.     apiVersions: 
  21.     - v1 
  22.     operations: 
  23.     - CREATE 
  24.     - UPDATE 
  25.     resources: 
  26.     - nodepools 
  27.   sideEffects: None 

主要是 clientConfig 的配置,如果想要本地聯(lián)調(diào),我們需要將 clientConfig.service 刪掉,替換成

  1. clientConfig: 
  2.   url: https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool 

注意: host.docker.internal是 docker desktop 的默認域名,通過這個可以調(diào)用到宿主機上的服務,url path mutate-nodes-lailin-xyz-v1-nodepool需要和 service 中的 path 保持一致

然后再加上 caBundle

  1. clientConfig: 
  2.   caBundle: CA證書 base64 后的字符串 

證書

想要本地聯(lián)調(diào)需要先生成證書,我們使用 openssl 來生成,先創(chuàng)建一個 config/cert 文件夾,我們把證書都放到這里

首先創(chuàng)建一個 csr.conf文件

  1. [ req ] 
  2. default_bits = 2048 
  3. prompt = no 
  4. default_md = sha256 
  5. req_extensions = req_ext 
  6. distinguished_name = dn 
  7.  
  8. [ dn ] 
  9. C = CN 
  10. ST = Guangzhou 
  11. L = Shenzhen 
  12. CN = host.docker.internal 
  13.  
  14. [ req_ext ] 
  15. subjectAltName = @alt_names 
  16.  
  17. [ alt_names ] 
  18. DNS.1 = host.docker.internal # 這里由于我們直接訪問的是域名所以用 DNS 
  19.  
  20. [ v3_ext ] 
  21. authorityKeyIdentifier=keyid,issuer:always 
  22. basicConstraints=CA:FALSE 
  23. keyUsage=keyEncipherment,dataEncipherment 
  24. extendedKeyUsage=serverAuth,clientAuth 
  25. subjectAltName=@alt_names 

然后生成 CA 證書并且簽發(fā)本地證書

  1. # 生成 CA 證書 
  2. openssl genrsa -out ca.key 2048 
  3. openssl req -x509 -new -nodes -key ca.key -subj "/CN=host.docker.internal" -days 10000 -out ca.crt 
  4.  
  5. # 簽發(fā)本地證書 
  6. openssl genrsa -out tls.key 2048 
  7. openssl req -new -SHA256 -newkey rsa:2048 -nodes -keyout tls.key -out tls.csr -subj "/C=CN/ST=Shanghai/L=Shanghai/O=/OU=/CN=host.docker.internal" 
  8. openssl req -new -key tls.key -out tls.csr -config csr.conf 
  9. openssl x509 -req -in tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt -days 10000 -extensions v3_ext -extfile csr.conf 

配置變更

我們?yōu)榱撕驮镜拈_發(fā)體驗保持一致,所以利用 kustomize 的特性新建一個 config/dev 文件夾,包含兩個文件修改我們想要的配置

  1. ▶ tree config/dev 
  2. config/dev 
  3. ├── kustomization.yaml 
  4. └── webhook_patch.yaml 

先看一下 kustomization.yaml,從 default 文件夾中繼承配置,然后使用 patches 修改一些配置,主要是分別給兩種準入控制 WebHook 添加 url 字段,然后使用 webhook_patch.yaml對兩個文件做些統(tǒng)一的配置

  1. resources: 
  2. - ../default 
  3.  
  4. patches: 
  5. - patch: | 
  6.     - op: "add" 
  7.       path: "/webhooks/0/clientConfig/url" 
  8.       value: "https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool" 
  9.   target: 
  10.     kind: MutatingWebhookConfiguration 
  11. - patch: | 
  12.     - op: "add" 
  13.       path: "/webhooks/0/clientConfig/url" 
  14.       value: "https://host.docker.internal:9443/validate-nodes-lailin-xyz-v1-nodepool" 
  15.   target: 
  16.     kind: ValidatingWebhookConfiguration 
  17. - path: webhook_patch.yaml 
  18.   target: 
  19.     group: admissionregistration.k8s.io 

webhook_patch.yaml 這個主要是移除 cert-manager.io 的 annotation,本地調(diào)試不需要使用它進行證書注入,然后移除掉 service 并且添加 CA 證書

  1. - op: "remove" 
  2.   path: "/metadata/annotations/cert-manager.io~1inject-ca-from" 
  3. - op: "remove" 
  4.   path: "/webhooks/0/clientConfig/service" 
  5. - op: "add" 
  6.   path: "/webhooks/0/clientConfig/caBundle" 
  7.   value: CA 證書 base64 后的值 

CA 證書的值可以通過以下命令獲取

  1. cat config/cert/ca.crt | base64 | tr -d '\n' 

然后修改一下 main.go將證書文件夾指定到我們剛剛生成好的文件目錄

  1. mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ 
  2.   Scheme:                 scheme, 
  3.   MetricsBindAddress:     metricsAddr, 
  4.   Port:                   9443, 
  5.   HealthProbeBindAddress: probeAddr, 
  6.   LeaderElection:         enableLeaderElection, 
  7.   LeaderElectionID:       "97acaccf.lailin.xyz"
  8. +  CertDir:                "config/cert/", // 手動指定證書位置用于測試 
  9. }) 

為了方便調(diào)試,在 makefile 中添加

  1. dev: manifests kustomize 
  2.  cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 
  3.  $(KUSTOMIZE) build config/dev | kubectl apply -f - 

最后執(zhí)行一下 make dev 然后再執(zhí)行 make run 就行了

總結(jié)

今天完成了準入控制 WebHook 的實現(xiàn),雖然這個例子可能不太好,如果只需要校驗正則,直接配置一下//+kubebuilder:validation:Pattern=string就行了,但是學習了這個之后其實可以做很多事情,例如給 pod 增加 sidecar 根據(jù)應用類型的不同注入不同的一些 agent 等等.

本文轉(zhuǎn)載自微信公眾號「mohuishou」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系mohuishou公眾號。

 

責任編輯:姜華 來源: mohuishou
相關(guān)推薦

2021-05-17 05:51:31

KubeBuilderOperator測試

2021-05-12 06:18:19

KubeBuilderOperatork8s

2021-05-16 10:52:58

kubebuilderstatus event

2021-05-08 09:02:48

KubeBuilderOperatork8s

2021-01-01 09:20:20

操作DjangoORM

2021-05-20 06:57:16

RabbitMQ開源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2021-06-16 08:28:25

unary 方法函數(shù)技術(shù)

2022-03-10 08:31:51

REST接口規(guī)范設(shè)計Restful架構(gòu)

2025-01-17 07:00:00

2022-02-24 07:56:42

開發(fā)Viteesbuild

2021-10-27 09:59:35

存儲

2022-02-21 09:44:45

Git開源分布式

2023-05-12 08:19:12

Netty程序框架

2021-06-30 00:20:12

Hangfire.NET平臺

2021-07-28 10:02:54

建造者模式代碼

2021-07-14 08:24:23

TCPIP 通信協(xié)議

2022-04-08 08:32:40

mobx狀態(tài)管理庫redux

2021-08-11 07:02:21

npm包管理器工具

2021-05-17 09:50:06

Kubebuilde源碼CURD
點贊
收藏

51CTO技術(shù)棧公眾號