KANS 스터디 2주차 Pause 컨테이너 내용 정리. 참고로 면접 때 질문이 pause 컨테이너 역할이었다. 실행 중인거 보았다고 버벅되다 모른다고 하였다.
pause 컨테이너란?
- 파드 내 컨테이너에게 부모처럼 net namespace 제공해준다. 파드 내 복수의 컨테이너는 공통으로 pause 컨테이너가 제공한 network namespace를 공유한다. (리눅스 네임스페이스 설명)
- 모든 파드에 반드시 실행된다. (세상에서 가장 많이 사용되는 컨테이너, 참조 https://eddie.ee/170 )
pause 컨테이너 왜 필요할까?
- 파드란 쿠버네티스 환경의 증설하는 기본 단위이다. 파드 내 여러 컨테이너에 같은 net namespace 공유하는게 필요해서 사용한다. (그런데 파드 내 컨테이너들이 서로 다른 네트워크를 가지면 왜 안될까?)
pause 컨테이너를 실습으로 알아보자. 먼저 2개의 컨테이너를 가지는 파드를 실행한다.
## 2개의 컨테이너를 가지는 파드다. apiVersion: v1 kind: Pod metadata: name: myweb2 spec: containers: - name: myweb2-nginx image: nginx ports: - containerPort: 80 protocol: TCP - name: myweb2-netshoot image: nicolaka/netshoot command: ["/bin/bash"] args: ["-c", "while true; do sleep 5; curl localhost; done"] # 포드가 종료되지 않도록 유지합니다 terminationGracePeriodSeconds: 0 |
파드를 실행한다. 하나의 파드에 2개의 컨테이너가 실행된다. (READY 상태가 2/2이다.)
kubectl apply -f https://raw.githubusercontent.com/gasida/NDKS/main/3/myweb2.yaml [spkr@erdia22 ~ (ubun71:default)]$ kgp ## k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myweb2 2/2 Running 0 5s 10.233.67.18 ubun20-74 <none> <none> |
Pause 컨테이너 역할이 파드 내 컨테이너에 net namespace 제공하는 것이다. 2개의 컨테이너가 서로 net namespace를 공유하는지 확인해보자.
참조 : https://eddie.ee/170
각 컨테이너의 IP와 net namespace를 확인한다. 먼저 컨테이너 이름을 확인한다.
[spkr@erdia22 ~ (ubun71:default)]$ k describe pod myweb2 (생략) myweb2-nginx: myweb2-netshoot: Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m52s default-scheduler Successfully assigned default/myweb2 to ubun20-74 Normal Pulling 2m52s kubelet Pulling image "nginx" Normal Pulled 2m50s kubelet Successfully pulled image "nginx" in 1.907152063s Normal Created 2m50s kubelet Created container myweb2-nginx Normal Started 2m50s kubelet Started container myweb2-nginx Normal Pulling 2m50s kubelet Pulling image "nicolaka/netshoot" Normal Pulled 2m48s kubelet Successfully pulled image "nicolaka/netshoot" in 1.801422476s Normal Created 2m48s kubelet Created container myweb2-netshoot Normal Started 2m48s kubelet Started container myweb2-netshoot |
myweb2-nginx, myweb2-netshoot 2가지 컨테이너가 실행 중이다. 각각 이름으로 컨테이너 접속한다.
## 창을 2개로 나누어서 위, 아래에서 작업한다. [spkr@erdia22 ~ (ubun71:default)]$ k exec -it myweb2 -c myweb2-nginx -- bash root@myweb2:/# apt update -y root@myweb2:/# apt install -y net-tools root@myweb2:/# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.233.67.18 netmask 255.255.255.0 broadcast 10.233.67.255 [spkr@erdia22 ~ (ubun71:default)]$ k exec -it myweb2 -c myweb2-netshoot -- bash bash-5.1# ip a show (생략) 2: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default link/ether 16:be:51:bc:a2:45 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.233.67.18/24 brd 10.233.67.255 scope global eth0 valid_lft forever preferred_lft forever |
2개의 컨테이너 모두 동일한 IP 10.233.67.18 가진다. 서로 다른 컨테이너가 동일한 IP를 가지는 희한한 상태다. 왜 그럴까?
2개의 컨테이너가 동일한 net namespace 가지기 때문이다. 각각의 컨테이너에서 net namespace를 확인해보자. 호스트 노드에서 각 프로세스 ID를 조회해서 각 프로세스가 사용하는 namespace 정보를 조회한다. NGINX와 NETSHOOT 컨테이너 각각 확인한다.
## 파드가 실행 중인 노드에 접속한다. [spkr@erdia22 ~ (ubun71:default)]$ ssh ubun20-74 root@ubun20-74:~# NGINXPID=$(ps -ef | grep 'nginx -g' | grep -v grep | awk '{print $2}') ## nginxpid 2개인데 390721를 사용한다. 다른 nginx 파드가 실행 중이라 2개 보인다. root@ubun20-74:~# echo $NGINXPID 7267 390721 ## netshoot 컨테이너에 curl 프로세스를 실행하고 있다. root@ubun20-74:~# NETSHPID=$(ps -ef | grep 'curl' | grep -v grep | awk '{print $2}') root@ubun20-74:~# echo $NETSHPID 390785 |
각 프로세스, 즉 컨테이너의 namespace를 확인해보자. 아래와 같이 net namespace는 동일하게 390680 PID를 가진다. 같은 net namespace 라서 nginx, netshoot 컨테이너 같은 IP를 가진다.
root@ubun20-74:~# lsns -p 390721 NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 153 1 root /sbin/init maybe-ubiquity 4026531837 user 153 1 root /sbin/init maybe-ubiquity 4026532250 net 10 390680 root /pause 4026532333 uts 10 390680 root /pause 4026532334 ipc 10 390680 root /pause 4026532336 mnt 6 390721 root nginx: master process nginx -g daemon off; 4026532337 pid 6 390721 root nginx: master process nginx -g daemon off; root@ubun20-74:~# lsns -p $NETSHPID NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 153 1 root /sbin/init maybe-ubiquity 4026531837 user 153 1 root /sbin/init maybe-ubiquity 4026532250 net 10 390680 root /pause 4026532333 uts 10 390680 root /pause 4026532334 ipc 10 390680 root /pause 4026532338 mnt 3 390785 root /bin/bash -c while true; do sleep 5; curl localhost; done 4026532340 pid 3 390785 root /bin/bash -c while true; do sleep 5; curl localhost; done |
(참고로 cgroup, user 네임스페이스는 따로 격리하지 않음
## mnt, uts, pid 네임스페이스는 컨테이너별로 격리
## ipc, net 네임스페이스는 파드 내의 컨테이너 간 공유 (IPC : 컨테이너 프로세스간 공유 - signal, socket, pipe 등)
명령어를 보면 /pause 이다. nginx, netshoot 컨테이너는 pause 명령어를 실행하지 않는다. pause 컨테이너가 /pause 명령어를 실행하였다. (아쉽게도 containerd 런타임에서는 pause 컨테이너를 확인할 수 없었다.)
참고로 docker 런타임을 사용하면 docker ps에서 pause 컨테이너를 확인할 수 있다.
root@k8s-w2:~# docker ps --format "table {{.Image}}\t{{.Status}}\t{{.Names}}" | grep myweb2 nicolaka/netshoot Up About a minute k8s_myweb2-netshoot_myweb2_default_829cf80a-f55d-4ea6-b458-45e2b73620e7_0 nginx Up About a minute k8s_myweb2-nginx_myweb2_default_829cf80a-f55d-4ea6-b458-45e2b73620e7_0 k8s.gcr.io/pause:3.4.1 Up 2 minutes k8s_POD_myweb2_default_829cf80a-f55d-4ea6-b458-45e2b73620e7_0 |
그런데 나는 containerd를 사용하고 있어서 아래처럼 pause 컨테이너가 조회되지 않는다.
root@ubun20-74:~# crictl ps CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID 92b1f46dcdc03 f4c8dceca780a 22 minutes ago Running myweb2-netshoot 0 6b8b8f0367a8f fa290e797b7c8 605c77e624ddb 22 minutes ago Running myweb2-nginx 0 6b8b8f0367a8f |
아쉽게도 컨테이너 images 정보로만 pause 컨테이너를 확인할 수 있다.
root@ubun20-74:~# crictl images IMAGE TAG IMAGE ID SIZE (생략) k8s.gcr.io/pause 3.3 0184c1613d929 299kB |
추가로 netshoot 컨테이너에 접속하면 (황당하게) nginx 프로세스가 실행되지 않는 컨테이너인데 nginx 컨테이너와 동일하게 80 port를 listen하고 있다. nginx 컨테이너와 동일한 네트워크 정보를 가지고 있어서 그렇다.
[spkr@erdia22 ~ (ubun71:default)]$ k exec -it myweb2 -c myweb2-netshoot -- bash bash-5.1# ps aux PID USER TIME COMMAND 1 root 0:00 /bin/bash -c while true; do sleep 5; curl localhost; done 178 root 0:00 bash 1045 root 0:00 sleep 5 1046 root 0:00 ps aux ## nginx 프로세스는 실행되지 않지만 80 port를 listen 하고 있는 황당한 상태 bash-5.1# ss -tln State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 511 0.0.0.0:80 0.0.0.0:* LISTEN 0 511 [::]:80 [::]:* |
정리하면
파드 내 컨테이너는 pause 컨테이너가 마치 부모처럼 제공하는 net namespace을 공유해서 네트워크로 사용한다. 그래서 2개의 컨테이너가 실행되면 동일한 네트워크를 가진다. 하나의 파드에 2개 컨테이너를 실행하려면 포트 충돌나지 않도록 유의해야 한다. (VM에서 프로세스들이 공통 eth0 인터페이스 가지는 것과 동일하다.)
'쿠버네티스 일반' 카테고리의 다른 글
온프렘 아재의 eks 사용기 (2) | 2022.03.06 |
---|---|
스테이트풀셋 on Kubernetes (0) | 2022.02.06 |
Flannel CNI (0) | 2022.01.12 |
컨테이너 격리 및 보안 설정 - KAN 1차 스터디 (2) | 2022.01.10 |
Kubernetes 컨설팅/구축 서비스 (0) | 2021.07.30 |