⭐ 가시다(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개의 컨테이너가 동작
- 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 |