Kubernetes cluster 운영 환경에서 Pod간 주고 받은 IP packet을 tcpdump하는 방법을 알아보겠다.
방식 A: Container 내부에 tcpdump 프로그램을 설치하고, Container 내부에서 직접 tcpdump 명령을 수행
$ kubectl exec -n my-namespace my-pod -c my-container -it -- bash
(In-Container) $ apt install -y tcpdump
... 중간 생략 ...
##
## 참고: Kubernetes Pod 내부의 기본 NIC은 eth0이다.
## 만약, Multus CNI를 사용해서 Multi-NIC을 사용하는 경우라면,
## eth0 이외에 net1, net2 같은 이름으로 NIC이 있을 것이다.
## 따라서, 내가 운영하는 CNI가 1개인지 또는 어떤 종류의 CNI이 인지에 따라
## NIC의 이름이 다를 수 있으니까, ifconfig 명령 또는 `ip a` 같은 명령으로
## NIC 이름을 확인하고 tcpdump 명령을 수행해야 한다.
##
(In-Container) $ tcpdump -i eth0 -w my-capture.pcap
... 중간 생략 ...
위와 같이 생성한 pcap 파일은 Pod 외부에서 볼 수 없기 때문에
1) Pod 내부에서 scp 명령으로 외부로 옮겨주던지
2) 또는 NFS, Ceph storage 같은 PV를 이용하여 저장하는 것을 권장한다.
방식 B: Worker node에서 특정 Pod의 namespace를 이용하여 tcpdump 명령을 수행
예제를 이용하여 설명해보겠다.
'productpage' Pod가 주고 받은 IP packet을 tcpdump하려는 상황을 가정해보자.
우선 'productpage' Pod가 어느 worker node에 있는지 확인한다.
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
... 중간 생략 ...
productpage-v1-6b746f74dc-xfjdz 2/2 Running 0 2d17h 10.244.2.4 worker-1
... 중간 생략 ...
'productpage' pod가 worker-1 node에 있으니까, worker-1에 ssh 접속하여 아래의 스크립트를 수행한다.
##
## Filename : run-tcpdump.sh
##
#!/usr/bin/bash
container_id=$(docker container ls | grep k8s_istio-proxy_productpage | awk '{ print $1 }')
echo "Container ID: $container_id"
container_pid=$(docker inspect -f '{{.State.Pid}}' $container_id)
echo "Container PID: $container_pid"
nsenter -t $container_pid -n /bin/bash -xec 'tcpdump -i any -w productpage-envoy-any.pcap'
## NOTE: After running this script to capture the packet,
## Use the packet filter as 'tls or http' with your Wireshark program !
위 `run-tcpdump.sh` 스크립트를 수행하고 나서 만들어진 pcap 파일을 Wireshark으로 열어본다.
그런데, 위 "방식 A, 방식 B"는 Kubernetes를 사용했을 때나 가능한 얘기이고, OCP(Openshift Container Platform)을 사용하는 경우라면 위 방식으로 container 내부의 network packet을 dump할 수 없다 !!! 왜? OCP, OKD Cluster의 Worker Node에는 'docker' command가 없다. 그러면 어떻게 하는가? 아래와 같이 "방식 C"를 따라해야 한다.
방식 C: OCP의 Node에서 특정 Pod의 namespace를 이용하여 tcpdump 명령을 수행
예제를 이용하여 설명해보겠다.
(worker2 node에 Pod가 구동되어 있다고 가정하고 설명한다)
##
## Working Location: Bastion Node, or PC (MacBook)
##
$ oc debug node/worker1.andrew.space
Starting pod/worker1.andrew.space-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.10.11.12
If you don't see a command prompt, try pressing enter.
sh-4.4# chroot /host
sh-4.4# container_id=$(crictl ps | grep my-example-app | awk '{ print $1 }')
sh-4.4# echo $container_id
378f096238fdd
sh-4.4# container_pid=$(crictl inspect $container_id | jq '.info.pid')
sh-4.4# echo $container_pid
3458673
sh-4.4# nsenter -t $container_pid -n /bin/bash -xec 'tcpdump -i eth0'
... TCPDUMP 출력 결과 생략 ...
만약, OCP 또는 OKD Cluster를 구축할 때, OS를 CoreOS를 사용한 경우라면 위와 같이 `nsenter -t .... 'tcpdump -i eth0'` 명령을 사용할 수 없다. 왜냐고? CoreOS는 TCPDUMP 명령을 가지고 있지 않기 때문이다. ㅠㅠ 단, 임시로 CoreOS에 tcpdump command를 설치하고 위 절차를 따라하는 꼼수가 있기는 하다.
##
## brew 명령으로 bash를 설치한다.
##
$ brew install bash
...
...
$ which -a bash
/usr/local/bin/bash
/bin/bash
$ /usr/local/bin/bash --version
GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
##
## /etc/shells에 '/usr/local/bin/bash'를 추가한다.
##
$ sudo vim /etc/shells
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/bash ## 이 라인을 추가한다.
##
## Set default shell
##
$ chsh -s /usr/local/bin/bash
## TODO: 위 chsh 명령을 수행한 후에
## 반드시 기존 iTerm2 터미널을 종료하고, 새로운 iTerm2 터미널을 열어야
## 새로운 버전의 bash 명령을 사용할 수 있다.
$ echo $BASH_VERSION
5.1.8(1)-release
Bash auto-completion
MacOS에 설치된 Bash가 v4.1+ 인 것을 확인했다면, 아래 Web docs를 따라서 설정해주면 모든 것이 끝!
위 Web Site의 Docs를 읽으면서, 아래 내가 작성한 문서를 비교하면서 작업해야 한다.
위 Web Docs만 따라하면 bash 패키지 설치 디렉토리가 설치 대상 장비마다 달라서, 잘못된 설정을 하게 된다.
##
## 아래 문서를 따라서 설정할 때, 주의할 점이 있다.
## https://kubernetes.io/docs/tasks/tools/included/optional-kubectl-configs-bash-mac/
## 위 문서의 설명을 따라하다보면, bash-completion@2를 설치하고 나서,
## .bash_profile에 바로 bash_completion.sh 정보를 작성하라고 되어 있는데
## 이때, Web Docs에 있는 것을 Copy & Paste하면 안 된다.
## 왜냐고?
## bash-completion@2가 minor 버전이 릴리즈될 때마다 설치 디렉토리가
## - /usr/local/etc/... 인 경우가 있고,
## - /opt/homebrew/... 인 경우가 있기 때문에
## Web Docs만 따라하면 제대로 설정할 수 없다.
## 따라서 아래 설치 명령의 제일 밑에 출력되는 내용을 copy해서 .bash_profile에 붙여 넣어야 한다.
## 즉, 결론적으로
## Kubernetes의 Web Docs는 전체 절차만 이해하는 수준으로 읽고,
## 아래 명령의 출력 결과에 나오는 안내 글을 읽고 따라서 설정 작업을 해야 잘 동작한다.
##
$ brew install bash-completion@2
... 중간 생략 ...
## 주의: 바로 이 안내 글을 꼭 주의깊게 읽고, .bash_profile 설정 작업을 해야 한다.
Add the following line to your ~/.bash_profile:
[[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]] && . "/opt/homebrew/etc/profile.d/bash_completion.sh"
==> Summary
🍺 /opt/homebrew/Cellar/bash-completion@2/2.11: 753 files, 1MB
$
Istio를 설치할 때, 다양한 설치 방법이 있다. 그래서 Istio를 처음 접할 때, 다양할 설치 방법 때문에 무엇부터 시작해야 할지 망설이게 된다. 이런 고민을 조금이라도 덜기 위해 각 설치 방법의 장점과 단점을 알아보고자 한다.
우선, 가장 흔하게 사용하는 Istio 설치 방법은 아래의 4가지가 있다.
istioctl install <-- 내가 생각하는 Best Choice
istio operator
istioctl manifest generate
helm chart
각 설치 방법의 특징과 장점 및 단점은 아래와 같다.
istioctl install
`istioctl` 명령 도구를 사용하여 istio를 설치하는 것이 가장 보편적인 설치 방법이다. 그리고 'istio dev community`에서 이 설치 방법을 권장하고 있다.
Pros:
`istioctl` 명령 도구가 설정 오류에 대한 확인을 해준다.
`istioctl` 명령 도구가 'IstioOperator' API를 사용한다.
'In-cluster privileged pods'가 필요하지 않다. `istioctl` 명령 도구를 이용해서 설정 변경이 필요할 때마다 설정을 적용해준다.
Cons:
다른 설치 방식에 비해서 `istioctl` 명령 도구 프로그램의 버전을 실제 istio의 버전과 맞추어줘야 하는 일이 필요하다.
istio operator
Pros:
`istioctl` 같은 별도의 명령 도구 프로그램이 없이, kubernetes의 Operator 패턴을 이용하면 된다.
Cons:
'Istio Operator'가 istio가 설치되는 kubernetes cluster 내부에 있어야 하고, 상당히 높은 cluster management 권한을 가지게 되므로, 자칫하면 보안(security)가 허술해지는 실수를 범할 수 있다.
istioctl manifest generate
나처럼 Istio 자체를 분석하려는 사람이 쓰는 방법이지 않을까 싶다. Kubernetes와 Istio를 많이 아는 사람이 아니라면, 이 방법은 복잡하게 느껴질 수 있을 것이다. Kubernetes와 Istio를 파헤치고 배우는 학생이라면 한번쯤 시도해볼만한 설치 방법이다. (나의 개인적인 느낌으로 하는 말이다 ^^)
어짜피 istioctl이나 istio operator도 원본 Application의 Pod manifest를 hooking하여 istio에 필요한 설정 항목을 Patch하는 것이기 때문에, Istio 및 app이 구동하는 과정을 동일한 흐름일 것이다.
Pros:
`istioctl`이 생성한 chart를 사람이 직접 열람할 수 있다.
Cons:
chart, manifest를 직접 이용하는 방식이기 때문에 `istioctl`의 설정 검증 같은 절차가 없다.
초보자가 사용하기에 절차가 복잡하다.
Error reporting이 허술하다.
Helm chart
개인적인 생각에 helm chart에 익숙한 사용자라면 써볼만한 설치 방식이지만, 설정 validation이 허술해서 권장할 만한 설치 방법은 아닌 듯 하다.
결론
개발자가 Istio를 스터디하고, 분석해야 하는 상황이 아니라면 `istioctl` 명령 도구를 이용하여 istio를 설치하고 관리하는 것이 좋다. 아래 Web Docs를 따라하는 것이 Best Choice 라고 생각한다.
위 Web Docs가 너무 길어서 다 읽고, 따라하기 귀찮다면, 아래 2개의 명령만 수행해보길~~~
## Istio Controller 설치 및 Ingress, Egress Gateway까지 한번에 설치하려면, 아래 명령을 수행
$ istioctl install --set profile=demo
## Test가 끝나고, Istio 관련 모든 Kubernetes Resource를 삭제하려면, 아래 명령을 수행
$ istioctl x uninstall --purge
만약, Istio를 포함해서 Example App이 실제로 돌아가는 것까지 테스트하고 싶다면 아래 Web Docs를 따라하는 것이 좋다.
## 참고로, scc는 namespace마다 있는 것이 아니다.
## 따라서 namespace를 지정하지 않고, 아래 명령처럼 scc를 생성한다.
$ oc apply -f my-scc.yaml
이렇게 생성한 SCC를 내가 사용할 ServiceAccount와 binding한다.
$ oc create ns andrew-project
$ oc adm policy add-scc-to-group andrew-scc system:serviceaccounts:andrew
$ oc adm policy add-scc-to-user andrew-scc -z andrew -n andrew-project
# SCC 정보를 확인하는 명령
$ oc describe scc andrew-scc
# 'andrew' ServiceAccount로부터 'andrew-scc' SCC를 삭제하는 명령
$ oc adm policy remove-scc-from-user andrew-scc -z andrew -n andrew-project
추가로 Pod Deploy할 때, 아래와 같이 'securityContext' 항목을 설정해야 한다.
# File name: my-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ubuntu-pv
labels:
app: ubuntu-pv
spec:
replicas: 1
selector:
matchLabels:
app: ubuntu-pv
template:
metadata:
labels:
app: ubuntu-pv
spec:
## NOTE: 이 부분을 추가 !!!
securityContext:
runAsUser: 0
containers:
- name: ubuntu-pv
image: myharbor.andrew.space:8080/my-ubuntu:0.1.2
## NOTE: 이 부분을 추가 !!!
securityContext:
capabilities:
add:
- "NET_ADMIN"
- "NET_RAW"
- "NET_BIND_SERVICE"
여기까지는 그냥 SecurityContextConstraints에 관한 이해없이 따라해도 잘 동작한다.
그런데 만약 SecurityContextConstraints에 대해서 깊이 있는 지식을 얻고 싶다면, 아래의 Red Hat Blog를 읽어볼 것을 추천한다.
SecurityContextConstraints 방식으로 Process의 실행 권한을 제어하는 방법 외에도 Linux에서 전통적으로 사용하는 Stick Bit(SETUID)와 File Capability 방식으로 Binary File을 만들고, Container Image를 미리 제작하는 방법도 같이 소개하고 있다.
어떤 방식이 더 편하고, 보안(Security)이 우수한지는 사용하는 사람이 판단할 일이다.
공황장애(Panic)가 심해지면서 정신건강의학과 의원에 다니고 약물 치료를 한 이후로 Panic 증상이 많이 줄었지만, 여전히 공황장애 때문에 못 하는 것이 고속도로에 있는 2km가 넘는 긴 터널을 통과하지 못 한다.
약물 치료 전에는 500m짜리 터널도 못 지나가서 터널 입구에서 차를 세운 적도 있었서 그때보다는 많이 좋다고 생각하지만, 힘들고 두려운 것은 어쩔 수 없다. 이성적으로 제어할 수 있는 영역의 문제가 아니다보니, 그냥 순응하는 수 밖에 없네.
그래서 어디 멀리 여행을 갈 때는 목적지까지 중간에 긴 터널이 있는지 확인한다. 경로에 2km 넘는 터널이 있다면, 고속도로를 포기하고 구불구불하고 제한 속도가 있는 국도, 지방도를 이용한다.
같이 동행하는 가족은 1시간 정도 차를 타는 시간이 더 길어져서 힘들겠지만, 나름 국도 주변의 풍경은 고속도로보다는 볼만하다. 산 경치가 터널에 비교할 바가 아니지 않겠는가 ^^ (좋게 생각하자~ 긍정적인 생각이 병을 고치게한다)
안양(인덕원) ~ 강원도 양양
긴 터널에 대한 폐소 공포 증상 때문에 터널을 피한다고 생각하는 것보다는 터널을 지날 때 느껴보지 못한 좋은 풍경과 작은 마을에 들러서 느끼는 여유로움 때문에 국도, 지방도를 간다고 생각하면 마음이 편안해진다.
그래서 나는 강원도 양양을 갈 때, 인제군청과 한계령휴게소를 지나는 도로를 이용한다.
서울 -> 홍천군 -> 인제군 -> 한계령휴게소 -> 양양군(해변) * 홍천군: 운전 피로를 풀기에 좋은 국밥집이 있다. 뜨끈한 국밥 한 그릇 먹고 출발하면 기분이 좋아진다. * 인제군: 인제군청과 인제 성당에서 멀지 않은 곳에 철판짜장면으로 유명한 식당이 있는데, 짜장면의 비쥬얼이 이색적이고, 철판이라서 짜장면에서 불맛을 느낄 수 있다. * 한계령휴게소: 경치가 너무 좋아서, 저절로 차를 멈워 세우게 된다. 이 맛에 국도로 운전한다 :)
홍천에서 인제군을 가는 국도에도 터널이 몇개 있기는 하지만, 서울양양고속도로만큼 긴 터널은 아니고 수백 미터짜리 짧은 터널이다. 그래서 폐소공포에 대한 부담없이 운전할 수 있다.
안양(인덕원) ~ 전라남도 여수
서울에서 출발해서 논산까지는 고속도로인데도 불구하고 터널이 없다. 그러나 논산 이남으로 가면, 2km가 넘는 터널이 나온다.
따라서 서울~논산 구간은 고속도로를 이용하고, 논산~여수 구간은 국도를 이용하면 좋다.
특이한 점은 논산~여수 구간의 국도가 속도 제한이 80km/h이지만, 실제 이 도로를 이용하는 차량의 평균 속도는 100~110km 정도이고 신호등이 거의 없어서 고속도로와 시간 차이가 많이 나지 않는다.
그리고 국도를 이용해서 여수를 가다보면, 중간에 살짝 빠져서 지리산 노고단을 갈 수 있어서 좋다.
요구사항 경청하고, 요구 사항 분석하고, 구조 설계, 개발(구현), 테스트, 회의, 멤버 관리 등 매일 해야 하는 업무에 시간이 쫓기고
집에 오면 아내와 아이들과도 시간을 보내야 하니까 솔직히 긴 호흡으로 깊은 내용의 블로그를 쓴다는게 쉽지 않다.
그런데 Git 개념을 1~2시간 이내의 글을 쓴다고 될 일은 아니라서, 한달 정도 매일 시간을 조금씩 내면서 써볼까 한다.
( 아마 작성 중간에 글을 읽는 분도 계실텐데, 양해를 구합니다~ )
처음부터Git을 사용한 사람이라면 Git의 Version과 Work Space 관리가 당연하게, 자연스럽게 받아들여질 것이다.
그런데 나처럼 개발을 시작한지 20년이 사람은 비슷한 듯 다른SVN과 Git의 Version 관리 방식이 헷갈린다.
자꾸 SVN을 사용하던 버릇으로 Git 사용하니까 제대로 Git을 사용하지 못하는 나를 발견했다.
그래서 SVN을 화끈하게 머릿속에서 지워버리고, 새 마음으로 Git을 받아들이기로 했다. :)
SVN 그리고 Git 이들은 뭐가 다를까?
대략적으로 SVN과 Git을 비교해보면 이렇다. (개인적인 느낌, 생각이 많이 들어 갔으니까 그냥 참고용으로 봐주세요)
비교표
Git
SVN (SubVersion)
전반적인 느낌
어렵다. 개념 설명이 잘 된 책을 한번 쭉 읽어야 Git을 Git답게 쓸 수 있다.
개념이 쉽고, 명령어 사용법도 쉽다.
Feature
없는게 없다. Version 관리의 끝판왕!!!
딱 필요한 핵심 기능을 제공한다.
Branch 관리
Branch, Tag 관리가 편리하다.
Bad T.T
코드 분산 관리
OK
No
Code Collision(충돌)
조금 관리에 신경쓰면 그럭저럭 충돌을 피할 수 있다.
Poor T.T
Multi User 동시 작업
OK
불편하다.
복구
특정 Commit 시점으로 복구하기 편함
Poor
그리고 위 표에 언급한 것 말고도, Git은 Github 또는 Bitbucket, GitLab 처럼 Cloud 환경을 제공해주니까 내가 별도로 SVN 서버를 구축하지 않아도 된다. 그냥 내 PC에서 코드 작성하고 GitHub 또는 Bitbucket, GitLab Cloud에 Push하면 되니까 아주 편하다.
또 하나, Git이 어려운 이유는 아마도 여러 사람이 같은 Code를 수정하고, 동일한 Repository에 Push를 하면서 어려움을 겪는 것 같다. (내 경우는 특히 그랬다.)
혼자 Git과 GitHub를 사용할 때는 별 문제 없이 잘 사용했는데 여러 명이 같이 코드를 수정하고 Push하고 Merge를 하려니까 자꾸 불편한 상황이 생겼다.
Git 스터디해보니, 모르고 써서 생기는 불편함이었다. Git 개념과 사용법을 잘 익히고 사용했다면 분명 문제가 없었을 것이다.
GitHub, GitLab, BitBucket 이들은 무엇인가?
처음에 Git를 접할 때는 GitHub만 보였는데, 실무에서 Git을 많이 사용하다보니 GitLab도 보이고, BitBucket도 보였다.
이들은 비슷하면서 다른데, 아래 표로 정리해봤다.
GitHub
GitLab
Bitbucket
서비스 제공 회사
Microsoft
GitLab Inc.
Atlassian
Feature
우리가 OpenSource를 다운로드할 때 접할 수 있는 바로 그 곳
GitHub랑 Feature의 차이를 잘 모르겠다. (내 생각임)
Jira 연동이 되서 좋다. (내 생각임)
Web UI
3개 모두 비슷하다. Repository 자체에 대한 관리 UI를 제외하면 거의 같다.
CLI (Command)
Git command는 3개 모두 똑같다. (CLI가 제품마다 다르면 큰일나지 않을까? ^^)
Price
Free (Private Repository는 유료)
Free (Private Repository는 유료)
Free (Private Repository는 유료)
결국, 3개 모두 기능(Feature)는 비슷하고 가격도 경쟁이 붙어서 그런지 가격도 비슷해졌다.
나는 회사에서 Bitbucket을 구입해서 사용하고 있는데, 확실히 회사의 Project 관리 시스템(Jira, Confluence 등)과 연동되니까 관리하는 입장에서는 Bitbucket이 SW 품질 관리에서 유리한 면이 있다. 즉, 회사에서 사용할 거라면 위 3개 중에서 Bitbucket이 좋다는 뜻 :)
그렇다면, 개인적으로 사용할 거라면?
그래도 Bitbucket Cloud 서비스를 이용하는 것이 다른 2가지 제품보다 좋은 것 같다 (개인 의견임)
해외의 대형 Open Source Project에 좀 참여해서 일을 해보니, Atlassian 제품을 이용해서 Open Source Project를 관리하는 Community가 꽤 많고, 나에게 그런 경험이 있어서 그런지 Atlassian의 Bitbucket이 좀더 익숙한 느낌이다.
Git 설치 (Installation)
##
## Mac OS 컴퓨터에 설치하는 경우
##
$ brew install git
$ git --version
git version 2.32.0 (Apple Git-132)
$ git config --global user.name "Peter"
$ git config --global user.email "peter@example.com"
Git 개념, 동작 방식
나처럼 Version 관리 도구로써 SVN을 먼저 접한 사람은 Git의 동작 방식이 쉽게 이해되지 않는다.
그래도 찬찬히 살펴보면, 알게 되리라 :)
Repository가 Local가 Remote로 나누어져있다. 이 부분이 처음 Git을 접하는 사람이 헷갈려하는 부분이다.
Repository를 2개로 나누어서 관리하다보니, Local과 Remote를 명확하게 구분해서 이해하지 않으면 git 명령을 수행할 때마다 헷갈리게 된다.
아래 그림이 쉽게 Local Repository에서 처리되는 내용, Remote Repository에서 처리되는 내용이 잘 구분되서 설명되고 있다.
위 그림을 이해했다면, 아래 그림을 이용해서 생각을 더 넓혀보자.
Repository (저장소)는 Remote, Local만 있는게 아니다. Forked Repository라는 것이 있다. 아마 꽤 활성화된(참여자가 많은) Open Source Project는 이 Forked Repository가 꽤 많을 것이다.
TODO : 위 동작 절차(프로세스)에 관해서 상세하게 설명하기 (작성 중) --> Coming Soon !!!
App을 개발해서 Container image로 build하여 Kubernetes cluster에 배포하다보면, 어느 순간 비슷하면서 반복적인 YAML 파일을 작성하는 나를 보게된다.
좀더 구체적으로 얘기하자면, HelloWorld라는 App을 구성하는 Pod가 hw-frontend, hw-backend, hw-db 등 3개의 Pod로 구성되어 있다면 Kubernetes cluster에 HelloWorld App을 배포하기 위해서는 이 3개의 Pod를 모두 배포할 수 있는 deployment.yaml을 작성해야 한다.
아마 Kubernetes 운영 경험이 있는 개발자라면 Helm chart로 반복적이거나 뻔한 YAML code를 template 파일로 만들고, 변경되어야 할 부분만 values.yaml로 작성할 것이다.
그런데 이 helm chart도 일정 부분의 반복적이고 루틴한 작업이 계속 만들어지게 된다.
뻔하면서 반복되는 비슷하지만 약간씩 다른 설정 작업을 기계가 대신 해주면 좋겠다는 소망이 생긴다.
(아마 Kubernetes를 1년 정도 사용해서 App을 반복 배포하다보면, 이런 느낌적인 느낌이 생길 듯 ^^)
그래서 이런 저런 고민을 해결할 방법을 찾다가 'Mutating Admission Controller + WebHook'이라는 Kubernetes에 내장된 기능을 발견했다.
서론이 길어졌다.
이제 본론으로 들어가서, Kubernetes가 제공하는 Admission controller가 무엇이고 일반 개발자가 이 기능을 어떻게 확장할 수 있는지 설명해보겠다.
Mutating WebHook 사용 사례 (Use Case)
Admisson controller를 통한 Mutating Webhook 기능을 개발하는 사례는 많이 다양할 것이다.
내가 Mutating Webhook 서버를 개발한 Case를 나열해보면,
특정 namespace에 기동하는 모든 pod의 /etc/hosts에 'ip address + domain name'을 Patch하기 더 구체적으로 설명하면, Pod의 Deployment를 위한 원본 YAML(Manifest)에 일괄적으로 'hostAliases' item을 추가하는 기능이 필요했고, 이 기능을 Mutating Webhook 서버에 개발했다.
사내에서 사용하는 운영 관리용 Container(EMS, O&M Container)를 모든 Pod에 Inject하기 더 구체적으로 설명하면, Pod의 Deployment를 위한 원본 YAML(Manifest)에 일괄적으로 Sidecar Container를 Patch하는 기능을 수행하도록 Mutating Webhook 서버를 개발했다.
특정 조건(namespace, labels)을 만족하는 Pod가 있는 검사하여, 해당 Pod에만 /my_volume/pkg 같은 storage를 Mount하도록 원본 Menifest를 Patch하기
Admission Controller와 Mutating WebHook의 개념 및 동작 원리
## TODO: 이 부분은 작성 중... (언제 그림을 그리고 글을 작성하나 ~~~, 2021년이 끝나기 전에 작성을 마무리해야 할텐데 ㅠㅠ)
Practical Practice (실전 예제)
실제 동작하는 그럴 듯한 Mutating WebHook Server의 code를 작성해보자.
Mutating WebHook Server를 구현하기 위한 Programming language는 아무거나 사용해도 상관없지만, 나는 Golang이 편해서 Golang을 예제 코드를 작성했다.
처음부터 모든 코드를 작성할 필요가 없다. 아래 stackrox 라는 github repository에 완성도가 높고, 간단하게 만들어 놓은 예제 코드가 있니, 이 Example Code를 git clone해서 사용하면 된다.