쿠버네티스는 기본적으로 API 요청이 오면 위와 같은 순서로 작업을 처리합니다.

그 중간에 Mutating admission 부분에 Webhook을

이용한 pod injection 예제로 pod injection 하는 부분을 알아보고

예제가 오래된 관계로 v1beta1인 예제를 v1으로 업데이트하는 부분까지 할 예정입니다.

Webhook의 작동 방식

  • 출처 mutating webhook tutorial 깃헙

MutatingWebhook은 요청이 etcd에 등록되기 전에 MutatingWebhookConfiguration 의 rule과

일치하는 request를 intercept 합니다.

MutatingWebhook은 webhook 서버에 승인을 요청하여

mutation ( injection이라던지 수정같은 작업) 을 수행합니다.

( webhook 서버는 API를 준수하는 일반 http 서버)

예제

https://github.com/morvencao/kube-mutating-webhook-tutorial

이 튜토리얼은 nginx 사이드카 컨테이너를 파드에 injection 하는 MutatingAdmissionWebhook을 빌드하고 배포하는 방법을 보여줍니다.

조건

  • git
  • go version v1.12+
  • docker version 17.03+
  • kubectl version v1.11.3+
  • kubernetes v1.11.3+ cluster with admissionregistration.k8s.io/v1beta1 API enabled
    • 처음은 v1beta1로 작업하고 추후에 v1으로 수정할 예정.

admissionregistration.k8s.io/v1beta1 API enabled 확인 방법

kubectl api-versions | grep admissionregistration.k8s.io

결과는 아래와 같이 나와야합니다.

admissionregistration.k8s.io/v1 admissionregistration.k8s.io/v1beta1

빌드

  1. Build binary

# make build

  1. Build docker image

# make build-image

  1. push docker image

# make push-image

deploy

  1. sidecar injector webhook이 배포될 sidecar-injector  namespace를 생성

# kubectl create ns sidecar-injector

  1. sidecar injector deployment에 사용될 secret 생성

    (이 시크릿은 cert와 key 정보를 가지고 있다):

# ./deployment/webhook-create-signed-cert.sh \\ --service sidecar-injector-webhook-svc \\ --secret sidecar-injector-webhook-certs \\ --namespace sidecar-injector

  1. 위에서 생성한 caBundle 값을 mutatingwebhook.yaml 에 패치를 한 결과를 mutatingwebhook-ca-bundle.yaml로 생성한다.:

# cat deployment/mutatingwebhook.yaml | \\ deployment/webhook-patch-ca-bundle.sh > \\ deployment/mutatingwebhook-ca-bundle.yaml

  1. 리소스들을 배포한다.:

# kubectl create -f deployment/nginxconfigmap.yaml # kubectl create -f deployment/configmap.yaml # kubectl create -f deployment/deployment.yaml # kubectl create -f deployment/service.yaml # kubectl create -f deployment/mutatingwebhook-ca-bundle.yaml

확인

  1. sidecar injector webhook이 잘 배포됬나 확인한다.

# kubectl -n sidecar-injector get pod NAME READY STATUS RESTARTS AGE sidecar-injector-webhook-deployment-7c8bc5f4c9-28c84 1/1 Running 0 30s # kubectl -n sidecar-injector get deploy NAME READY UP-TO-DATE AVAILABLE AGE sidecar-injector-webhook-deployment 1/1 1 1 67s

  1. injection namespace 생성 그리고  sidecar-injector=enabled로 라벨링 한다.

# kubectl create ns injection # kubectl label namespace injection sidecar-injection=enabled # kubectl get namespace -L sidecar-injection NAME STATUS AGE SIDECAR-INJECTION default Active 26m injection Active 13s enabled kube-public Active 26m kube-system Active 26m sidecar-injector Active 17m

  1. alpine app을 예제로 쿠버네티스 클러스터에 배포한다.

# kubectl run alpine --image=alpine --restart=Never -n injection --overrides='{"apiVersion":"v1","metadata":{"annotations":{"sidecar-injector-webhook.morven.me/inject":"yes"}}}' --command -- sleep infinity

  1. sidecar container가 injected 됬는지 확인한다.

# kubectl get pod NAME READY STATUS RESTARTS AGE alpine 2/2 Running 0 1m # kubectl -n injection get pod alpine -o jsonpath="{.spec.containers[*].name}" alpine sidecar-nginx

admissionregistration.k8s.io/v1beta1 를 v1으로 업그레이드 하기

webhook의 작동방식부분에서 mutatingadmissionwebhook 부분과 webhook 서버를 보면

admissionReview를 요청하고 응답받는것을 보실수 있습니다.

v1beta1버전에서는 요청에 대한 응답시 kind와 apiversion 을 넣지 않아도 응답을 정상으로 판단 했습니다.

하지만 v1버전에서는 요청에 대한 응답시 kind와 apiversion 버전을 추가시켜줘야 합니다.

https://github.com/morvencao/kube-mutating-webhook-tutorial/blob/e72f4d5e501d61f22023efb26e16cda35a335941/cmd/webhook.go#L296

위 빈 라인에 아래와 같이 요청으로 들어온 api version 과 kind , uid를 그대로 review 응답에 넣어줍니다.

admissionReview.Response.UID = ar.Request.UID admissionReview.APIVersion = ar.APIVersion admissionReview.Kind = ar.Kind

위와 같이 할 경우 v1beta1로 요청이 들어왔을 경우 그대로 v1beta1로 응답하며

v1로 요청이 왔을 경우 그대로 v1로 응답이 갑니다.

그 후 deployment/mutatingwebhook.yaml 을 수정합니다.

apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: sidecar-injector-webhook-cfg labels: app: sidecar-injector webhooks: - name: sidecar-injector.morven.me clientConfig: service: name: sidecar-injector-webhook-svc namespace: sidecar-injector path: "/mutate" caBundle: ${CA_BUNDLE} rules: - operations: ["CREATE", "UPDATE"] apiGroups: [""] apiVersions: ["v1"] resources: ["pods"] namespaceSelector: matchLabels: sidecar-injection: enabled admissionReviewVersions: ["v1"] sideEffects: None

위와 같이 수정하면 v1로 업데이트 완료입니다.

Injection 수정하기

webhook 서버에서 injection 처리 부분은 webhook.go 파일 입니다.

https://github.com/morvencao/kube-mutating-webhook-tutorial/blob/e72f4d5e501d61f22023efb26e16cda35a335941/cmd/webhook.go#L234

webhook.go 안에 createPatch 부분이 injection 할 내용을 생성하는 부분입니다.

이 부분으로 생성 후 apiserver로 다시 요청을 응답하는 작업이 이루어집니다.

이때 이 부분도 같이 response에 담겨서 응답하게 됩니다.

createPatch 부분을 참고하셔서 수정하시면 자신만의 injection 을 만드실수 있습니다.

createPath의 추가적인 참고는 하단의 tumblr github을 참고해주세요.

https://github.com/tumblr/k8s-sidecar-injector/blob/2478960ca6686798d26319956354b48e37108c29/pkg/server/webhook.go#L448

정리

mutating webhook은 추가적인 변경이나, 검증을 쉽게 제공해줘서 go를 처음접하는 저로써도

손쉽게 수정하여 저만의 injection 을 만들수 있었습니다.

다만 v1beta1에서 v1 patch부분이나 인증서 관련 부분은 삽질이 좀 필요해서 글로 남기게 됬습니다.

인증서 부분과 webhook 소스내부 설명은 다음글에 남겨보도록 하겠습니다.

'개발 > Kubernetes' 카테고리의 다른 글

왜 apiversion이 변경되어 있을까  (0) 2021.06.11
컨테이너 런타임  (0) 2021.03.07
쿠버네티스의 클러스터 구성  (0) 2021.01.28
k8s 에서 spring boot jib image command 수정  (0) 2020.12.24
클러스터 구성  (0) 2020.09.13

+ Recent posts