연재 시리즈

쿠버네티스 네트워크 스터디 2주차 2편: pause컨테이너

악분 2022. 1. 19. 19:26
반응형

스터디 목차

 

안녕하세요. 이 글은 facebook 쿠버네티스 그룹에서 올라온 "쿠버네티스 네트워크 스터디" 2주차 내용을 정리했습니다.

스터디 모집글: https://www.facebook.com/groups/k8skr/posts/3202691746679143

 

1. 2주차 두번째 주제

2주차 두번째 주제는 pause컨테이너 이해입니다. 스터디 진행 목차는 아래 그림과 같습니다.

 

2. 실습환경

vagrant로 실습환경을 구성했습니다. 쿠버네티스 클러스터는 ControlPlane 노드 1대, Worker 노드 2대로 구성되어 있습니다.

 

 

3. Pause컨테이너

3.1 pod는 1개 이상의 컨테이너 집합

pod는 1개 이상의 컨테이너로 구성된 구성된 쿠버네티스 리소스입니다. pod에 생성될 때 컨테이너가 같이 생성되고 pod가 삭제되면 모든 컨테이너가 삭제됩니다. 컨테이너는 pod에서 설정한 볼륨과 다른 리소스를 공유하여 사용할 수 있습니다.

 

3.2 pod의 네트워크 네임스페이스

pod의 각 컨테이너는 네임스페이스를 이용하여 커널 자원을 격리합니다. 특별하게도 pod의 모든 컨테이너가 똑같은 네임스페이스를 사용하는 커널 리소스가 있습니다. 바로, IPC 네임스페이스와 네트워크 네임스페이스입니다. 

 

네트워크 네임스페이스를 공유하기 때문에 127.0.0.1(localhost):port로 다른 컨테이너가 실행한 서비스에 접근할 수 있습니다. 아래 예제에서는 nginx컨테이너가 nginx2컨테이너 81/tcp에 접근할 때 127.0.0.1:81로 접근할 수 있습니다. 반대로, nginx2컨테이너도 nginx 컨테이너 80/tcp에 접근할때 127.0.0.1:80으로 접근할 수 있습니다.

아래 yaml은 예제를 위해 작성했습니다. 실제로 실행이 되지 않을 수 있습니다.

 

3.3 네트워크 네임스페이스는 어떤 컨테이너가 생성할까?

pod의 모든 컨테이너가 공유하는 네트워크 네임스페이스는 누가 생성할까요? 바로 pause컨테이너입니다. pause컨테이너는 디폴트로 자동으로 생성됩니다. 

 

4. 실습

4.1 pod생성

아래 yaml파일을 사용하여 pod를 생성합니다. pod는 2개의 컨테이너를 실행합니다. pod의 컨테이너는 80/tcp를 사용하는 nginx와 8080/tcp를 사용하는 python 웹애플리케이션입니다.

kubectl apply -f <yaml경로>
apiVersion: v1
kind: Pod
metadata:
  name: sample
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
  - name: simple-http
    image: trinitronx/python-simplehttpserver
    ports:
    - containerPort: 8080
  - name: netshoot
    image: nicolaka/netshoot
    command: ["/bin/bash"]
    args: ["-c", "while true; do sleep 5; curl localhost; done"]

 

컨테이너 3개가 실행되었는지 확인합니다.

kubectl get po sample

 

컨테이너 3개를 생성했지만 pause컨테이너가 자동으로 생성되어 총 4개의 컨테이너가 sample pod안에 있습니다. 각 컨테이너는 같은 네트워크 네임스페이스를 사용합니다.

 

4.2 puase컨테이너 확인

sample pod를 실행하는 노드에서 puase컨테이너를 확인할 수 있습니다. 

 

 

컨테이너는 결국 리눅스 프로세스로 실행되므로 프로세스 목록에서 puase프로세스를 찾을 수 있습니다. 아래 예제그림에서는 controlplane노드에서 sample pod를 실행하는 worker노드로 원격접속한 후, ps와 grep명령어로 pause컨테이너를 찾았습니다.

 

 

4.3 pod의 컨테이너 네트워크네임스페이스 확인

pod의 컨테이너는 같은 네트워크 네임스페이스를 사용하므로 네트워크 네임스페이스가 ID가 같습니다. pod의 컨테이너도 결국 리눅스 프로세스이므로 컨테이너의 PID를 구한 후, /proc/<PID>/ns에서 네트워크 네임스페이스를 확인할 수 있습니다.

 

먼저 pod에서 실행한 컨테이너 PID를 구합니다.

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

PYTHONWEB=$(ps -ef | grep -i simplehttp | grep -v grep | awk '{print $2}')
echo $PYTHONWEB

 

/proc/<PID>/ns에 네임스페이스를 조회하고 grep명령어로 네트워크 네임스페이스를 필터링합니다. 결과를 보면 전부 네트워크 네임스페이스 ID가 동일한 것을 알 수 있습니다.

ls -l /proc/$NGINXPID/ns | grep net
ls -l /proc/$NETSHPID/ns | grep net
ls -l /proc/$PYTHONWEB/ns | grep net

 

4.4 127.0.0.1을 이용하여 다른 컨테이너 접근

netshot에서 127.0.0.1:80로 nginx컨테이너, 127.0.0.1:8080으로 simple-http 컨테이너에 접근해보겠습니다. 

 

먼저 netshot 프로세스 목록을 조회합니다. 80/tcp를 사용하고 있는 프로세스가 보이지 않습니다.

kubectl exec -it -c netshoot sample -- ps -ef

 

사용하고 있는 포트를 조회해도 아무것도 보이지 않습니다.

kubectl exec -it -c netshoot sample -- ss -tp

 

netshot에서는 80/tcp를 사용하고 있지 않지만 네트워크 네임스페이스를 공유하기 때문에 127.0.0.1:80로 nginx컨테이너에 접근이 가능합니다.

kubectl exec -it -c netshoot sample -- curl 127.0.0.1:80

 

8080/tcp도 사용하지 않지만 127.0.0.1:8080으로 simple-http컨테이너에 접근이 가능합니다.

 

4.5 컨테이너의 포트가 중복되면 어떻게 될까?

pod의 컨테이너들이 중복된 포트를 사용하면 당연히 오류가 발생합니다.

 

아래 yaml파일을 이용하여 sample2 pod를 생성합니다. pod에 속해 있는 nginx1, nginx2 컨테이너는 80번 포트를 사용하려고 합니다.

apiVersion: v1
kind: Pod
metadata:
  name: sample2
spec:
  containers:
  - name: nginx1
    image: nginx:1.14.2
    ports:
    - containerPort: 80
  - name: nginx2
    image: nginx:1.14.2
    ports:
    - containerPort: 80

 

pod상태를 확인하면 예상대로 정상적으로 실행되지 않았습니다. READY를 보면 컨테이너 1개가 정상적으로 실행되지 않았습니다.

kubectl get po sample2

 

컨테이너 로그를 보면 nginx1컨테이너는 정상적으로 실행되었고 nginx2컨테이너는 80번포트가 이미 사용중이어서 오류가 발생했습니다.

kubectl logs sample2 -c nginx1
kubectl logs sample2 -c nginx2

 

참고자료

[1] [쿠버네티스 공식문서] pod - https://kubernetes.io/docs/concepts/workloads/pods/#how-pods-manage-multiple-containers

 

반응형