파드소개 & PAUSE 컨테이너
- Pod 는 1개 이상의 컨테이너를 가질 수 있습니다 ==> sidecar 패턴 등 - 링크
- Pod 내에 실행되는 컨테이너들은 반드시 동일한 노드에 할당되며 동일한 생명 주기를 갖습니다 → Pod 삭제 시, Pod 내 모든 컨테이너가 삭제
- Pod IP - Pod 는 노드 IP 와 별개로 클러스터 내에서 접근 가능한 IP를 할당 받으며, 다른 노드에 위치한 Pod 도 NAT 없이 Pod IP로 접근 가능 ⇒
CNI 가 처리
- IP 공유 - Pod 내에 있는 컨테이너들은 서로 IP를 공유, 컨테이너끼리는 localhost 통해 서로 접근하며 포트를 이용해 구분
- pause 컨테이너가 ‘parent’ 처럼 network namespace 를 만들어 주고, 내부의 나머지 컨테이너들은 해당 net ns 를 공유
- volume 공유 - Pod 안의 컨테이너들은 동일한 볼륨과 연결이 가능하여 파일 시스템을 기반으로 서로 파일을 주고받을 수 있음
- IPC & UDS 관련 정보 링크 - UDS 소개2 IPC방법들
사이드카 & PAUSE 컨테이너
PAUSE 컨테이너는 POD와 함께 기본적으로 생성되며, Network namespace와 IPC namespace를 제공하는 역할을 합니다.
이번 실습은 컨테이너를 2개를 가진 POD를 생성하고 내부 Network를 확인해봅니다.
아래와 같은 yaml 생성합니다.
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
배포 후 podDML NET IPC 공유
를 확인합니다.
# 파드 생성
$ kubectl apply -f https://raw.githubusercontent.com/gasida/NDKS/main/3/myweb2.yaml
# 확인
# pod 정보 READY 에 2/2 를 확인 : pod 내 모든 컨테이너가 정상이여야지 status 가 Running 가 됨
$ kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myweb2 2/2 Running 0 63s 172.16.46.6 k8s-w2 <none> <none>
# 배포된 워커노드에서 docker ps 로 확인
$ docker ps --format "table \t\t" | 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
# Pod 상세 정보에 컨테이너 2개 정보가 보인다
$ kubectl describe pod myweb2
Name: myweb2
...
Containers:
myweb2-nginx:
Container ID: docker://2717dd093ee5c69a918c6c52461f47cf5f0c0330378730ce717d1fcabb0fc748
Image: nginx
...
myweb2-netshoot:
Container ID: docker://e3e3aef9ee53ef805336d4b6e0986f63e23c767b1648d18ff09948815c5f06a9
Image: nicolaka/netshoot
...
# 파드의 각각 컨테이너 IP 확인 >> IP가 같다!
$ kubectl exec myweb2 -c myweb2-netshoot -- ip addr
$ kubectl exec myweb2 -c myweb2-nginx -- apt update
$ kubectl exec myweb2 -c myweb2-nginx -- apt install -y net-tools
$ kubectl exec myweb2 -c myweb2-nginx -- ifconfig
# 워커 노드에서 컨테이너 프로세스 정보 확인
$ ps -ef | grep 'nginx -g' | grep -v grep
root 14508 14483 0 09:23 ? 00:00:00 nginx: master process nginx -g daemon off;
$ ps -ef | grep 'curl' | grep -v grep
root 14596 14574 0 09:23 ? 00:00:00 /bin/bash -c while true; do sleep 5; curl localhost; done
# docker top <컨테이너 ID 혹은 NAME>
$ docker top k8s_myweb2-nginx_myweb2_default_333e6cd3-40c1-43ba-8517-2eaf14d2968a_0
UID PID PPID C STIME TTY TIME CMD
root 68723 68695 0 08:47 ? 00:00:00 nginx: master process nginx -g daemon off;
systemd+ 68764 68723 0 08:47 ? 00:00:00 nginx: worker process
systemd+ 68765 68723 0 08:47 ? 00:00:00 nginx: worker process
# 각각 프로세스를 변수에 지정
$ NGINXPID=$(ps -ef | grep 'nginx -g' | grep -v grep | awk '{print $2}')
$ echo $NGINXPID
$ NETSHPID=$(ps -ef | grep 'curl' | grep -v grep | awk '{print $2}')
$ echo $NETSHPID
# 한 파드 내의 각 컨테이너의 네임스페이스 정보 확인
## cgroup, user 네임스페이스는 따로 격리하지 않음
## mnt, uts, pid 네임스페이스는 컨테이너별로 격리
## ipc, net 네임스페이스는 파드 내의 컨테이너 간 공유 (IPC : 컨테이너 프로세스간 공유 - signal, socket, pipe 등)
## Pause 컨테이너는 IPC, Network 네임스페이스를 생성하고 유지 -> 나머지 컨테이너들은 해당 네임스페이스를 공유하여 사용
## 유저가 실행한 특정 컨테이너가 비정상 종료되어 컨터이너 전체에서 공유되는 네임스페이스에 문제가 발생하는 것을 방지
$ lsns -p $NGINXPID
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 126 1 root /sbin/init
4026531837 user 126 1 root /sbin/init
4026532211 ipc 6 14385 root /pause
4026532214 net 6 14385 root /pause
4026532287 mnt 3 14508 root nginx: master process nginx -g daemon off;
4026532288 uts 3 14508 root nginx: master process nginx -g daemon off;
4026532289 pid 3 14508 root nginx: master process nginx -g daemon off;
$ lsns -p $NETSHPID
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 126 1 root /sbin/init
4026531837 user 126 1 root /sbin/init
4026532211 ipc 6 14385 root /pause
4026532214 net 6 14385 root /pause
4026532290 mnt 2 14596 root /bin/bash -c while true; do sleep 5; curl localhost; done
4026532291 uts 2 14596 root /bin/bash -c while true; do sleep 5; curl localhost; done
4026532292 pid 2 14596 root /bin/bash -c while true; do sleep 5; curl localhost; done
# 컨테이너의 ID 변수 지정
$ NGINXCID=$(docker ps --format "table \t\t" | grep nginx | awk '{print $1}')
$ NETSHCID=$(docker ps --format "table \t\t" | grep netshoot | awk '{print $1}')
$ PAUSECID=$(docker ps --format "table \t\t" | grep POD_myweb2 | awk '{print $1}')
$ echo $NGINXCID
$ echo $NETSHCID
$ echo $PAUSECID
# 컨테이너의 IP 확인 >> IP가 같다!
$ docker exec $NGINXCID ifconfig
$ docker exec $NETSHCID ip addr
# 컨테이너의 네트워크모드 정보와 PAUSE 컨테이너의 Id 정보 확인
# 아래 처럼 위 pause 컨네이너를 nginx, netshoot 컨테이너가 공유하고 있음을 확인
# 즉, 내부 컨테이너가 pause 컨테이너의 network namespace 를 공유
$ docker inspect $NGINXCID | grep NetworkMode
$ docker inspect $NETSHCID | grep NetworkMode
$ docker inspect $PAUSECID | egrep 'Id|Pid\"'
# PAUSE 의 NET 네임스페이스 PID 확인 및 IP 정보 확인
$ lsns -t net
$ PAUSEPID=$(docker inspect $PAUSECID | grep 'Pid\"' | awk '{print $2}' | cut -d "," -f 1)
$ echo $PAUSEPID
$ nsenter -t $PAUSEPID -n ip -c addr
$ nsenter -t $NGINXPID -n ip -c addr
$ nsenter -t $NETSHPID -n ip -c addr
마치며
다른 분들이 정리한 것에 비해서 내 정리는 제공되는 자료를 따라하는 정도밖에 안되네요. 사실 네트워크에 대하여 깊게 알고 있지 않아서 따라가는 것으로 충분하게 벅차네요.
3주를 기대하며 마칩니다.
참고 자료
- K8S Docs - Components & Cluster Architecture & Pods & Learn Kubernetes Basics & 치트 시트
- K8S Blog (v1.22) - New Peaks & Nginx-Ingress & API
- CNCF - 링크 & CNCF Landscape - 링크
- 44bits(Youtube) - 초보를 위한 쿠버네티스 안내서 & Subicura(WebSite) - 실습편
- [devinjeon] Container & Pod - 링크
- [learnk8s] Tracing the path of network traffic in Kubernetes - 링크
- (심화) ETCD 기본 동작 원리의 이해 - 링크 & ETCD? - 링크