카테고리 없음

[ Kans 3 Study - 2w ] 4. 파드 & PAUSE 컨테이너

su''@ 2024. 9. 8. 15:49
CloudNetaStudy - Kubernets Networtk 3기 실습 스터디 게시글입니다.

 

[ 요약 ]

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

 

k8s CRI - Old_Docs
더보기
Container Runtime : kubelet → CRI High Level Runtime (containerd) ← OCI → Low Level Runtime (Runc)
더보기

CRI 배경 - Old_Docs

  • 쿠버네티스 노드의 가장 낮은 계층(Low Level)에는 컨테이너를 시작하고 중지하는 것 외에도 소프트웨어가 있습니다. 이를 "컨테이너 런타임(Runc 등)"이라고 합니다. 가장 널리 알려진 컨테이너 런타임은 Docker이지만 이 분야에서 유일한 것은 아닙니다. 사실, 컨테이너 런타임 공간은 빠르게 진화해 왔습니다. 쿠버네티스를 더 확장 가능하게 만들기 위한 노력의 일환으로, "CRI"라고 하는 쿠버네티스의 컨테이너 런타임을 위한 새로운 플러그인 API를 개발해 왔습니다.
  • CRI란 무엇이고 쿠버네티스에 왜 필요한가요? 표준 인터페이스를 통해서 kubelet 재컴파일 없이 다양한 컨테이너 런타임 사용
    • 각 컨테이너 런타임에는 고유한 강점이 있으며, 많은 사용자가 Kubernetes가 더 많은 런타임을 지원하도록 요청했습니다. Kubernetes 1.5 릴리스에서, 우리는 컨테이너 런타임 인터페이스 (CRI)를 소개하게 되어 자랑스럽습니다. 이 플러그인 인터페이스 kubelet 재컴파일할 필요 없이 다양한 컨테이너 런타임을 사용할 수 있도록 해줍니다. CRI는 프로토콜 버퍼 와 gRPC API , 라이브러리 로 구성되어 있으며, 추가 사양과 도구가 활발하게 개발 중입니다. CRI는 Kubernetes 1.5 에서 알파로 릴리스됩니다 .
    • 쿠버네티스에서 상호 교환 가능한 컨테이너 런타임을 지원하는 것은 새로운 개념이 아닙니다. 1.3 릴리스에서 Docker 컨테이너 런타임의 대안으로 rkt 컨테이너 엔진을 활성화하는 rktnetes 프로젝트를 발표했습니다 . 그러나 Docker와 rkt는 모두 내부적이고 휘발성 있는 인터페이스를 통해 kubelet 소스 코드에 직접적이고 깊이 통합되었습니다. 이러한 통합 프로세스에는 Kubelet 내부 구조에 대한 심층적인 이해가 필요하며 쿠버네티스 커뮤니티에 상당한 유지 관리 오버헤드가 발생합니다. 이러한 요소는 신생 컨테이너 런타임에 대한 진입 장벽을 높입니다. 명확하게 정의된 추상화 계층을 제공함으로써 장벽을 제거하고 개발자가 컨테이너 런타임을 빌드하는 데 집중할 수 있도록 합니다. 이는 플러그형 컨테이너 런타임을 진정으로 활성화하고 보다 건강한 생태계를 구축하기 위한 작지만 중요한 단계입니다.
더보기

CRI 아키텍처 개선 과정 - Blog

  • containerd 1.0의 경우 Kubelet과 containerd 사이에서 작동하려면 cri-containerd라는 데몬이 필요했습니다. Cri-containerd는 Kubelet의 컨테이너 런타임 인터페이스(CRI) 서비스 요청을 처리하고 containerd를 사용하여 컨테이너와 컨테이너 이미지를 적절히 관리했습니다. Docker CRI 구현( dockershim )과 비교했을 때, 스택에서 하나의 추가 홉을 제거했습니다.
  • 그러나 cri-containerd와 containerd 1.0은 여전히 grpc를 통해 상호 작용하는 2개의 다른 데몬이었습니다. 루프에 데몬이 추가되어 사용자가 이해하고 배포하기가 더 복잡해졌고 불필요한 통신 오버헤드가 발생했습니다.
  • containerd 1.1에서 cri-containerd 데몬은 이제 containerd CRI 플러그인으로 리팩토링되었습니다. CRI 플러그인은 containerd 1.1에 내장되어 있으며 기본적으로 활성화되어 있습니다. cri-containerd와 달리 CRI 플러그인은 직접 함수 호출을 통해 containerd와 상호 작용합니다. 이 새로운 아키텍처는 통합을 보다 안정적이고 효율적으로 만들고 스택에서 또 다른 grpc 홉을 제거합니다. 이제 사용자는 Kubernetes를 containerd 1.1과 함께 직접 사용할 수 있습니다. cri-containerd 데몬은 더 이상 필요하지 않습니다.
    https://kubernetes.io/blog/2022/05/03/dockershim-historical-context/
더보기

CRI

  • KubeletgRPC 프레임워크를 사용하여 Unix 소켓을 통해 컨테이너 런타임(또는 런타임용 CRI shim)과 통신합니다.
  • 여기서 kubelet클라이언트 역할을 하고 CRI shim서버 역할을 합니다.
  • 프로토콜 버퍼 API에는 두 가지 gRPC 서비스인 ImageServiceRuntimeService가 포함되어 있습니다. ImageService는 리포지토리에서 이미지를 가져오고, 이미지를 검사하고, 제거하는 RPC를 제공합니다. RuntimeService에는 포드와 컨테이너의 수명 주기를 관리하는 RPC와 컨테이너와 상호 작용하기 위한 호출(exec/attach/port-forward)이 포함되어 있습니다. 이미지와 컨테이너(예: Docker 및 rkt)를 모두 관리하는 모놀리식 컨테이너 런타임은 단일 소켓으로 두 서비스를 동시에 제공할 수 있습니다. 소켓은 Kubelet에서 --container-runtime-endpoint 및 --image-service-endpoint 플래그로 설정할 수 있습니다.

 

더보기

- Pod는 리소스 제약이 있는 격리된 환경애플리케이션 컨테이너 그룹으로 구성됩니다. CRI에서 이 환경을 PodSandbox라고 합니다.

  • 우리는 의도적으로 컨테이너 런타임이 내부적으로 작동하는 방식에 따라 PodSandbox를 다르게 해석할 수 있는 여지를 남겨둡니다. 하이퍼바이저 기반 런타임의 경우 PodSandbox는 가상 머신을 나타낼 수 있습니다. Docker와 같은 다른 경우 Linux 네임스페이스일 수 있습니다. PodSandbox는 Pod 리소스 사양을 준수해야 합니다. v1alpha1 API에서 이는 kubelet이 생성하여 런타임에 전달하는 Pod 수준 cgroup 내의 모든 프로세스를 시작하여 달성됩니다.

- 포드를 시작하기 전에 kubelet RuntimeService.RunPodSandbox호출하여 환경을 만듭니다. 여기에는 포드에 대한 네트워킹 설정(예: IP 할당)이 포함됩니다. PodSandbox가 활성화되면 개별 컨테이너를 독립적으로 생성/시작/중지/제거할 수 있습니다. 포드를 삭제하기 위해 kubelet은 PodSandbox를 중지하고 제거하기 전에 컨테이너를 중지하고 제거합니다.

- Kubelet은 RPC를 통해 컨테이너의 수명 주기를 관리하고, 컨테이너 수명 주기 후크와 활성/준비 확인을 실행하며, Pod의 재시작 정책을 준수합니다.

 

 

Containerd Brings More Container Runtime Options for Kubernetes - Blog
  • cri-containerd
  • Architecture : 그림에 sandbox container = pause contianer

    https://www.alibabacloud.com/blog/a-discussion-on-container-runtime---starting-with-dockershim-being-deleted-by-kubernetes_600118
파드(Pod) : 컨테이너 애플리케이션의 기본 단위를 파드(Pod)라고 부르며, 파드는 1개 이상의 컨테이너로 구성된 컨테이너의 집합 - 링크 , code

 

  • 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 컨테이너는 포드의 모든 컨테이너에 대한 "부모 컨테이너" 역할을 합니다 - Link
    • pause 컨테이너에는 두 가지 핵심 책임이 있습니다.
      • 첫째, 포드에서 Linux 네임스페이스 공유의 기반 역할을 합니다.
      • 둘째, PID(프로세스 ID) 네임스페이스 공유가 활성화되면 각 포드에 대한 PID 1 역할을 하며 좀비 프로세스를 거둡니다.
  • volume 공유 - Pod 안의 컨테이너들은 동일한 볼륨과 연결이 가능하여 파일 시스템을 기반으로 서로 파일을 주고받을 수 있음
  • Pod는 리소스 제약이 있는 격리된 환경의 애플리케이션 컨테이너 그룹으로 구성됩니다. CRI에서 이 환경을 PodSandbox라고 합니다.
  • 포드를 시작하기 전에 kubelet은 RuntimeService.RunPodSandbox를 호출하여 환경을 만듭니다. (파드 네트워킹 설정 ’IP 할당’ 포함)
  • Kubelet은 RPC를 통해 컨테이너의 수명 주기를 관리하고, 컨테이너 수명 주기 후크와 활성/준비 확인을 실행하며, Pod의 재시작 정책을 준수합니다
pause.c - Code
더보기
/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define STRINGIFY(x) #x
#define VERSION_STRING(x) STRINGIFY(x)

#ifndef VERSION
#define VERSION HEAD
#endif

static void sigdown(int signo) {
  psignal(signo, "Shutting down, got signal");
  exit(0);
}

static void sigreap(int signo) {
  while (waitpid(-1, NULL, WNOHANG) > 0)
    ;
}

int main(int argc, char **argv) {
  int i;
  for (i = 1; i < argc; ++i) {
    if (!strcasecmp(argv[i], "-v")) {
      printf("pause.c %s\n", VERSION_STRING(VERSION));
      return 0;
    }
  }

  if (getpid() != 1)
    /* Not an error because pause sees use outside of infra containers. */
    fprintf(stderr, "Warning: pause should be the first process\n");

  if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 1;
  if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 2;
  if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
                                             .sa_flags = SA_NOCLDSTOP},
                NULL) < 0)
    return 3;

  for (;;)
    pause();
  fprintf(stderr, "Error: infinite loop terminated\n");
  return 42;
}

 

 

실습 환경 구성
  • 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 배율) : macOS 사용자
    echo -e "KUBE-OPS-VIEW URL = http://localhost:30000/#scale=1.5"
    echo -e "KUBE-OPS-VIEW URL = http://localhost:30000/#scale=2"
    
    # kube-ops-view 접속 URL 확인 (1.5 , 2 배율) : Windows 사용자
    echo -e "KUBE-OPS-VIEW URL = http://192.168.50.10:30000/#scale=1.5"
    echo -e "KUBE-OPS-VIEW URL = http://192.168.50.10:30000/#scale=2"
  • 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/
    
    ----------------------------------
  • 신규 파드를 배포하고 확인
    # [터미널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
  • myweb2 파드 정보 : myweb2 파드에 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
  • 배포 후 확인NET IPC UTS 공유 확인
    # [터미널1] 파드 생성
    kubectl apply -f https://raw.githubusercontent.com/gasida/NDKS/main/3/myweb2.yaml
    
    # kind POD 정보 확인 : 컨테이너의 집합
    kubectl explain pod
    KIND:       Pod
    VERSION:    v1
    DESCRIPTION:
        Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.
    ...
    
    # 확인
    # 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"
              }
            ],
    ...
  • 실습 완료 후 kind 삭제 : kind delete cluster --name myk8s