⭐ 가시다(gasida) 님이 진행하는 KANS(**K**ubernetes **A**dvanced **N**etworking **S**tudy)3기 실습 게시글입니다.
게시글 상 소스코드, 사진에서 ****굵게**** '''코드쉘''' 에 대한 부분이 들어가있을수도 있습니다.

⭐코드에서 실습 시 사용하는 변수가 들어갈 수 있습니다. 아래의 정보를 사용하고있습니다. 
#route53 Domain: jjongguet.com
#AWS Secret Key: jjongkey
#Aws .pem Key: jjong-key.pem

게시글 한줄요약

파드는 1개 이상의 컨테이너로 구성된 컨테이너의 집합이며, PAUSE 컨테이너가 Network/IPC/UTS 네임스페이스를 생성하고 유지/공유합니다.


K8s CRI

  • Container Runtime : kubelet → CRI → High Level Runtime (containerd) ← OCI → Low Level Runtime (Runc)

가장 최하단의 로우레벨에선 RunC 가 존재, 상위레벨에서는 containerd 가 존재

CRI 를 통해 표준인터페이스를 제공, kubelet 재컴파일 없이 다양한 컨테이너 런타임을 사용가능한다는게 특징

 

 

Pod

정의: 컨테이너 애플리케이션의 기본 단위를 파드(Pod)라고 부르며, 파드는 1개 이상의 컨테이너로 구성된 컨테이너의 집합

 

 

특징

  • Pod 는 1개 이상의 컨테이너를 가질 수 있습니다 ⇒ sidecar 패턴 등
  • Pod 내에 실행되는 컨테이너들은 반드시 동일한 노드에 할당되며 동일한 생명 주기를 갖습니다 → Pod 삭제 시, Pod 내 모든 컨테이너가 삭제
  • Pod IP - Pod 는 노드 IP 와 별개로 클러스터 내에서 접근 가능한 IP를 할당 받으며, 다른 노드에 위치한 Pod 도 NAT 없이 Pod IP로 접근 가능 ⇒ 요걸 CNI 해줌!
  • IP 공유 - Pod 내에 있는 컨테이너들은 서로 IP를 공유, 컨테이너끼리는 localhost 통해 서로 접근하며 포트를 이용해 구분
  • pause 컨테이너가 'parent' 처럼 network ns 를 만들어 주고, 내부의 컨테이너들은 해당 net ns 를 공유
    pause 컨테이너가 만든 network ns 를 다른 컨테이너와 공유하기때문에, 파드 내부의 컨테이너는 모두 동일한 ip 주소를 갖는다.
  • pause 컨테이너는 Pod 의 모든 컨테이너에 대한 ‘부모 컨테이너’ 역할을 한다.

 

 

실습 환경 구성 : Multi-Node Cluster (Control-plane, Nodes) with kube-ops-view

# '컨트롤플레인, 워커 노드 1대' 클러스터 배포 : 파드에 접속하기 위한 포트 맵핑 설정
cat <<EOT> **kind-2node.yaml**
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: **control-plane**
- role: **worker**
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
EOT
kind create cluster --config **kind-2node.yaml** --name **myk8s**

#
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump htop git nano -y'
docker exec -it myk8s-worker        sh -c 'apt update && apt install tree jq psmisc lsof wget bridge-utils tcpdump htop -y'

# 확인
kubectl get nodes -o wide
docker ps
**docker port myk8s-worker**
docker exec -it **myk8s-control-plane** ip -br -c -4 addr
docker exec -it **myk8s-worker**  ip -br -c -4 addr

# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=**NodePort**,service.main.ports.http.nodePort=**30000** --set env.TZ="Asia/Seoul" --namespace kube-system

# 설치 확인
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view

# kube-ops-view 접속 URL 확인 (1.5 , 2 배율)
echo -e "KUBE-OPS-VIEW URL = http://localhost:30000/#scale=1.5"
echo -e "KUBE-OPS-VIEW URL = http://localhost:30000/#scale=2"

30000, 30001 포트를 연결해놓은 상태로배포

 

 

Pod 배포 및 격리 확인

# [터미널1] myk8s-worker bash 진입 후 실행 및 확인
**docker exec -it myk8s-worker bash**
----------------------------------
**systemctl list-unit-files | grep 'enabled         enabled'**
containerd.service                                                                    enabled         enabled
kubelet.service                                                                       enabled         enabled
...

#
**crictl ps**

# 확인 : kubelet에 --container-runtime-endpoint=**unix:///run/containerd/containerd.sock**
**pstree -aln**
systemd
  |-systemd-journal
  |-**containerd**
  |   \-12*[{containerd}]
  |-**kubelet** --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml **--container-runtime-endpoint=unix:///run/containerd/containerd.sock** --node-ip=172.18.0.4 --node-labels=mynode=worker2 --pod-infra-container-image=registry.k8s.io/pause:3.9 --provider-id=kind://docker/myk8s/myk8s-worker2 --runtime-cgroups=/system.slice/containerd.service
  |   \-14*[{kubelet}]
  |-**containerd-shim** -namespace k8s.io -id e41d2d62c1bb44a955fe13ddef0dbb006c44352fda493e8d76c489138756d2fa -address /run/containerd/containerd.sock
  |   |-12*[{containerd-shim}]
  |   |-**pause**
  |   \-kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=myk8s-worker2
  |       \-9*[{kube-proxy}]
  |-**containerd-shim** -namespace k8s.io -id 9768cd57beeee9b0d1dc38e46dce44697113c3e3924d098e7b8c776909852f63 -address /run/containerd/containerd.sock
  |   |-11*[{containerd-shim}]
  |   |-**pause**
  |   \-flanneld --ip-masq --kube-subnet-mgr
  |       \-10*[{flanneld}]
  \-**containerd-shim** -namespace k8s.io -id 6bd147995b3a6c17384459eb4d3ceab4369329e6b57c009bdc6257b72254e1fb -address /run/containerd/containerd.sock
      |-11*[{containerd-shim}]
      |-**pause**
      \-metrics-server --cert-dir=/tmp --secure-port=10250 --kubelet-insecure-tls --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --kubelet-use-node-status-port --metric-resolution=15s
          \-12*[{metrics-server}]

# 확인 : 파드내에 pause 컨테이너와 metrics-server 컨테이너, 네임스페이스 정보
**pstree -aclnpsS**
...
    \-**containerd-shim**,1776 -namespace k8s.io -id 6bd147995b3a6c17384459eb4d3ceab4369329e6b57c009bdc6257b72254e1fb -address /run/containerd/containerd.sock
    |-{containerd-shim},1777
  ...
    |-pause,1797,**ipc**,mnt,**net,**pid**,uts**
    |-metrics-server,1896,cgroup,**ipc**,mnt,**net**,pid,**uts** --cert-dir=/tmp --secure-port=10250 --kubelet-insecure-tls --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --kubelet-use-node-status-port --metric-resolution=15s
    |   |-{metrics-server},1912
  ...

# 네임스페이스 확인 : lsns - List system namespaces
**lsns -p 1
lsns -p $$**
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time       15   1 root /sbin/init
4026531837 user       15   1 root /sbin/init
4026532525 mnt         9   1 root /sbin/init
4026532550 uts        13   1 root /sbin/init
4026532551 ipc         9   1 root /sbin/init
4026532577 pid         9   1 root /sbin/init
4026532579 net        13   1 root /sbin/init
4026532891 cgroup     13   1 root /sbin/init

# 해당 파드에 pause 컨테이너는 호스트NS와 다른 5개의 NS를 가짐 : mnt/pid 는 pasue 자신만 사용, **net/uts/ipc**는 app 컨테이너를 위해서 먼저 생성해둠
**lsns -p 1797**
        NS TYPE   NPROCS   PID USER  COMMAND
4026531834 time       15     1 root  /sbin/init
4026531837 user       15     1 root  /sbin/init
4026532891 cgroup     13     1 root  /sbin/init
4026533496 net         2  1797 65535 /pause
4026533625 uts         2  1797 65535 /pause
4026533626 ipc         2  1797 65535 /pause
4026533624 mnt         1  1797 65535 /pause
4026533627 pid         1  1797 65535 /pause

# app 컨테이너(metrics-server)는 호스트NS와 다른 6개의 NS를 가짐 : mnt/pid/cgroup 는 자신만 사용, net/uts/ipc는 pause 컨테이너가 생성한 것을 공유 사용함
**pgrep python3**
**lsns -p $(pgrep python3)**
~~pgrep metrics-server
1896
lsns -p $(pgrep metrics-server)~~
        NS TYPE   NPROCS   PID USER  COMMAND
4026531834 time       15     1 root  /sbin/init
4026531837 user       15     1 root  /sbin/init
4026533496 net         2  1797 65535 /pause
4026533625 uts         2  1797 65535 /pause
4026533626 ipc         2  1797 65535 /pause
4026533628 mnt         1  1896 1000  /metrics-server --cert-dir=/tmp --secure-port=10250 --kubelet-insecure-tls --kubelet-preferred-address-types=Inte
4026533629 pid         1  1896 1000  /metrics-server --cert-dir=/tmp --secure-port=10250 --kubelet-insecure-tls --kubelet-preferred-address-types=Inte
4026533630 cgroup      1  1896 1000  /metrics-server --cert-dir=/tmp --secure-port=10250 --kubelet-insecure-tls --kubelet-preferred-address-types=Inte

#
**ls -l /run/containerd/containerd.sock**

# 특정 소켓 파일을 사용하는 프로세스 확인
**lsof /run/containerd/containerd.sock**

#
**ss -xl | egrep 'Netid|containerd'**

#
**findmnt -A**
TARGET                                                  SOURCE                 FSTYPE    OPTIONS
/                                                       overlay                overlay   rw,relatime,lowerdir=/var/lib/docker/overlay2/l/HW4BGGJ4LV6M5
...
|-**/sys**                                                  sysfs                  sysfs     ro,nosuid,nodev,noexec,relatime
| |-/sys/kernel/debug                                   debugfs                debugfs   rw,nosuid,nodev,noexec,relatime
| |-/sys/kernel/tracing                                 tracefs                tracefs   rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/fuse/connections                            fusectl                fusectl   rw,nosuid,nodev,noexec,relatime
| |-/sys/kernel/config                                  configfs               configfs  rw,nosuid,nodev,noexec,relatime
| \-**/sys/fs/cgroup**                                      cgroup                 **cgroup2**   rw,nosuid,nodev,noexec,relatime

**findmnt -t cgroup2**
**grep cgroup /proc/filesystems**
**stat -fc %T /sys/fs/cgroup/**

----------------------------------

Pod 를 배포한 상태에서 pstree -aclnpsS 로 확인한 모습.

1번프로세스 와 임의의프로세스(689) 를 확인해봤는데, /pause 가 있는것확인.

또한 time,user,cgroup 은 1번프로세스가 만들었음을 확인가능

또한 Python command 를 사용하고있는 kube-ops-view 도 확인가능했음.

여기서 확인가능한건 time, user 는 host 의 name space 를 그대로 사용하고있지만, net, uts, ipc 는 puase container 에서 만들어진걸 사용하고있다.

mnt, pid, cgroup 은 자체로 만든걸 사용한다.

 

 

신규 파드를 배포하고 확인

# [터미널2] kubectl 명령 실행 및 확인

# Pod 생성 : YAML 파일에 컨테이너가 사용할 포트(TCP 80)을 설정
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: myweb
spec:
  containers:
  - image: **nginx:alpine**
    name: myweb-container
    ports:
    - containerPort: 80
      protocol: TCP
  terminationGracePeriodSeconds: 0
EOF

# Pod 정보 확인 : pause 컨테이너 정보가 보이는가?
kubectl get pod -o wide
kubectl describe pod myweb
kubectl get pod myweb -o json # status.conditions 에 Type 정보 확인 : 시간 정렬은 안되어 있음..

---

# [터미널1] myk8s-worker bash 진입 후 실행 및 확인
**docker exec -it myk8s-worker bash**
----------------------------------
**crictl ps**
**pstree -aln**
**pstree -aclnpsS #** 파드내에 pause 컨테이너와 app 컨테이너, 네임스페이스 정보

# 네임스페이스 확인 : lsns - List system namespaces
**lsns -p 1
lsns -p $$**
**lsns -p** *<pstree -aclnpsS에서 출력된 pause 컨테이너 PID>* 
**lsns -p $(pgrep nginx)** # app 컨테이너(metrics-server)

----------------------------------

# [터미널2] kubectl 명령 실행 및 확인
kubectl delete pod myweb

describe 했을때에 pause 는 보이지 않는다.

crictl 로도 pause 는 보이지 않고, pstree 를 사용해야 보인다.

myweb2 파드 정보 : myweb2 파드에 2개의 컨테이너가 동작

그림 가운데 uts ns 추가 필요함

 

  • myweb2.yaml : containers 가 복수형을 주목!
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

 

 

 

배포 후 확인 ⇒ NET IPC UTS 공유 확인

# [터미널1] 파드 생성
kubectl apply -f https://raw.githubusercontent.com/gasida/NDKS/main/3/myweb2.yaml
****
# 확인
# pod 정보 READY 에 2/2 를 확인 : pod 내 모든 컨테이너가 정상이여야지 status 가 Running 가 됨
kubectl get pod -owide

# Pod 상세 정보에 컨테이너 2개 정보가 보인다
kubectl describe pod myweb2
root@k8s-m:~# 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

# myweb2-netshoot 컨테이너 zsh 진입
kubectl exec myweb2 -c myweb2-netshoot -it -- zsh
----------------------------------
ifconfig
ss -tnlp
curl localhost # nginx 컨테이너가 아닌데, 로컬 접속 되고 tcp 80 listen 이다. 왜그럴까?
ps -ef # nginx 프로세스 정보가 안보이는데... 
exit
----------------------------------

# 터미널3 : nginx 컨테이너 웹 접속 로그 출력 : 접속자(myweb2-netshoot)의 IP 가 ::1(ipv6) 혹은 127.0.0.1(ipv4) 이닷!
**kubectl logs -f myweb2 -c myweb2-nginx**
::1 - - [01/Sep/2024:06:33:26 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1" "-"
혹은
127.0.0.1 - - [16/Jun/2021:06:22:24 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.77.0" "-"

# [터미널2] 
**docker exec -it myk8s-worker bash**
----------------------------------
# 컨테이너 정보 확인 : POD 와 POD ID가 같음을 확인
**crictl ps**
CONTAINER           IMAGE               CREATED              STATE               NAME                ATTEMPT             **POD ID**              POD
f0401ef30af36       e286c635d1232       About a minute ago   Running             myweb2-netshoot     0                   40f9a3021011a       myweb2
1f83b080de52d       a9dfdba8b7190       About a minute ago   Running             myweb2-nginx        0                   40f9a3021011a       myweb2
...

# 워커 노드에서 컨테이너 프로세스 정보 확인
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

# 각각 프로세스를 변수에 지정
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

**#  파드 내의  컨테이너의 네임스페이스 정보 확인**
## **time**, **user** 네임스페이스는 호스트와 같음, 격리하지 않음
## **mnt, uts, pid** 네임스페이스는 컨테이너별로 격리
## **ipc, uts, net** 네임스페이스는 파드 내의 컨테이너 간 공유 (IPC : 컨테이너 프로세스간 공유 - signal, socket, pipe 등)
## Pause 컨테이너는 IPC, Network, UTS 네임스페이스를 생성하고 유지 -> 나머지 컨테이너들은 해당 네임스페이스를 공유하여 사용
## 유저가 실행한 특정 컨테이너가 비정상 종료되어 컨터이너 전체에서 공유되는 네임스페이스에 문제가 발생하는 것을 방지

**lsns -p $NGINXPID**
        NS TYPE   NPROCS   PID USER  COMMAND
4026531834 **time**       28     1 root  **/sbin/init**
4026531837 **user**       28     1 root  **/sbin/init**
4026533482 **net**        12  2112 65535 /**pause**
4026533611 **uts**        12  2112 65535 /**pause**
4026533612 **ipc**        12  2112 65535 /**pause**
4026533614 **mnt**         9  2172 root  nginx: master process nginx -g daemon off;
4026533615 **pid**         9  2172 root  nginx: master process nginx -g daemon off;
4026533616 **cgroup**      9  2172 root  nginx: master process nginx -g daemon off;

**lsns -p $NETSHPID**
        NS TYPE   NPROCS   PID USER  COMMAND
4026531834 **time**       28     1 root  **/sbin/init**
4026531837 **user**       28     1 root  **/sbin/init**
4026533482 **net**        12  2112 65535 /**pause**
4026533611 **uts**        12  2112 65535 /**pause**
4026533612 **ipc**        12  2112 65535 /**pause**
4026533617 **mnt**         2  2296 root  /bin/bash -c while true; do sleep 5; curl localhost; done
4026533618 **pid**         2  2296 root  /bin/bash -c while true; do sleep 5; curl localhost; done
4026533619 **cgroup**      2  2296 root  /bin/bash -c while true; do sleep 5; curl localhost; done

# pause 정보 확인 : 
PAUSEPID**=<각자 자신의 pause PID>**
PAUSEPID=2112
lsns -p $PAUSEPID
        NS TYPE   NPROCS   PID USER  COMMAND
4026531834 **time**       28     1 root  **/sbin/init**
4026531837 **user**       28     1 root  **/sbin/init**
4026532760 **cgroup**     15     1 root  **/sbin/init #** cgroup 호스트와 같은 이유는?
4026533482 **net**        12  2112 65535 /pause
4026533610 **mnt**         1  2112 65535 /pause     # app 컨테이너와 다른 이유는?
4026533611 **uts**        12  2112 65535 /pause
4026533612 **ipc**        12  2112 65535 /pause
4026533613 **pid**         1  2112 65535 /pause     # app 컨테이너와 다른 이유는?

# 개별 컨테이너에 명령 실행 : IP 동일 확인
crictl ps
crictl ps -q
crictl exec -its 904e43d8fca65 ifconfig
crictl exec -its 63f82edc9caa6 ifconfig

# PAUSE 의 NET 네임스페이스 PID 확인 및 IP 정보 확인
lsns -t net
nsenter -t $PAUSEPID -n ip -c addr
nsenter -t $NGINXPID -n ip -c addr
nsenter -t $NETSHPID -n ip -c addr

# 2개의 네임스페이스 비교 , 아래 2112 프로세스의 정제는?
crictl inspect <myweb2-nginx    컨테이너ID> | jq
crictl inspect <myweb2-netshoot 컨테이너ID> | jq
crictl inspect 904e43d8fca65 | jq
**crictl inspect** 63f82edc9caa6 **| jq**
...
        "namespaces": [
          {
            "type": "pid"
          },
          {
            "type": "ipc",
            "path": "/proc/**2112**/ns/ipc"
          },
          {
            "type": "uts",
            "path": "/proc/**2112**/ns/uts"
          },
          {
            "type": "mount"
          },
          {
            "type": "network",
            "path": "/proc/**2112**/ns/net"
          },
          {
            "type": "cgroup"
          }
        ],
...
  • 파드 삭제: kubectl delete pod myweb2

Pod 안에 컨테니어가 2개있다는걸 확인가능함

파드 내부에 있는 Container 각각 주소를 확인하면 10.244.1.4 로 동일한 ip 를 갖는다

crictl명령어로도 확인 가능하다. 한개의 파드에 두개의 container 가 뜬다는걸 확인가능함.

  • 실습 완료 후 kind 삭제 : kind delete cluster --name myk8s

'외부활동' 카테고리의 다른 글

[KANS3] Service  (2) 2024.09.29
[OSSCA] LoxiLB 1주차: yaml, swagger, cmd, api  (0) 2024.09.28
[KANS3] Kubernetes, kind  (0) 2024.09.07
[KANS3] 도커 없이 컨테이너 만들기  (5) 2024.09.01
[KANS3] Docker  (2) 2024.09.01
jjongguet