Engineering/Kubernetes (K8S)

[Kubernetes] Pod 이해하기 - Deep Dive

[앙금빵] 2021. 11. 21.

Pod 이론

Pod 소개

파드는 하나 이상의 컨테이너로 구성된 그룹이며 쿠버네티스의 기본 빌딩 블록이다.

  • 파드는 언제라도 죽을 수 있는 존재이며 쿠버네티스는 이를 가정하고 설계를 하였다.
  • 파드는 항상 두 개 이상의 컨테이너를 포함하는 것을 의미하지 않는다. 일반적으로 파드는 하나의 컨테이너만 포함한다.
  • 모든 컨테이너는 항상 하나의 워커노드에서 실행되며 여러 워커노드에 걸쳐 시행되지 않는다.

Pod가 필요한 이유

Multi Process Single Container vs Single Process Multi Container

컨테이너는 단일 프로세스를 실행하는 것을 목적으로 설계하였다.
(프로세스가 Children Process를 생성하는 것을 제외)


여러 프로세스를 실행하는 Single Container의 단점

  • Single Contianer에서 관련이 없는 다른 프로세스를 실행하는 경우 모든 프로세스를 실행하고 로그를 관리하는 것은 모두 사용자 책임이다.
  • 모든 프로세스는 동일한 Standard Output으로 로그를 기록하기에 어떤 프로세스가 남긴 로그인지 파악을 하는 것이 어렵다.

이에 각 프로세스를 자체 개별 컨테이너로 실행해야 하는 것을 권장한다.

Q. 그렇다면 컨테이너를 직접 이용하지 않고 왜 Pod라는 개념이 존재하는가?

A: Pod 내부에 존재하는 컨테이너가 Running 할 수 있는 동일한 환경을 제공하면서 독립성을 보존할 수 있는 Container보다 더 상위 레벨의 요구되었다.

Container Group(=Pod)를 사용하여 밀접하게 연관된 프로세스를 함께 실행하고 단일 컨테이너 안에서 모두 함께 실행되는 것처럼 동일한 환경을 제공할 수 있으면서도 이들을 격리된 상태로 유지할 수 있다.

Pod 이해하기

Pod를 이용함으로서 아래와 같은 기대효과를 얻는다.

 

① 컨테이너가 제공하는 모든 기능을 활용하는 동시 프로세스가 함께 실행

② 이들을 격리된 상태로 유지

 

Pod를 통해 컨테이너가 제공하는 모든 기능을 활용하는 동시에 프로세스가 함께 실행되는 것 처럼 보이게 할 수 있다.

 

같은 Pod에서 Container 간 부분 격리

 

Pod 안에 있는 컨테이너가 특정한 리소스를 공유하기 위해 각 컨테이너가 완벽하게 격리되지 않도록 한다. 쿠버네티스는 파드 안에 있는 모든 컨테이너가 자체 네임스페이스가 아닌 동일한 리눅스 네임스페이스를 공유하도록 도커를 설정한다.

 

  • 모든 컨테이너는 동일한 네트워크 네임스페이스와 UTS 네임스페이스 안에서 실행되기 때문에 모든 컨테이너는 같은 호스트 이름과 네트워크 인터페이스를 공유한다.
  • 모든 컨테이너는 동일한 IPC 네임스페이스 아래에서 실행되어 IPC를 통해 서로 통신할 수 있다.
  • 최근 동일한 PID 네임스페이스를 공유할 수 있지만 기본적으로 활성화 되어 있지 않다.
  • Filesystem에 한해서는 조금 다르다. 대부분 컨테이너 파일 시스템은 컨테이너 이미지에서 나오기에, 파일시스템은 다른 컨테이너와 완전히 분리된다.
UTS namespace (Unix Timesharing System)
system의 hostname을 namespace 별로 격리시켜 준다.
Linux System Call 중 하나인 uname에서 struct에 정의된 식별자 중 nodename을 isolate하는 것이다.
IPC namespace (Inter-Process Communication)
프로세스간 서로 데이터를 주고 받는 경로를 의미한다.
Linux에서 사용되는 대표적인 IPC 방식은 Signal, Socket, pipe 등이 있다. 이러한 IPC resource를 격리 시켜 제공한다.

 

컨테이너가 동일한 IP와 포트공간을 공유하는 방법

 

파드안의 컨테이너가 동일한 네트워크 네임스페이스에서 실행되기에 동일한 IP 주소와 포트 공간을 공유한다.

  • 동일한 파드 안 컨테이너에서 실행 중인 프로세스가 같은 포트 번호를 사용하지 않도록 주의
  • 다른 Pod 경우 서로 다른 포트 공간을 가지기에 포트 충돌이 일어나지 않는다.
  • Pod 안에 있는 모든 컨테이너는 동일한 루프백 네트워크 인터페이스를 가지기에 컨테이너들이 Localhost를 통해 서로 통신할 수 있다.

 

파드 간 Flat Network

파드는 논리적인 호스트로서 컨테이너가 아닌 환경에서의 물리적 호스트 혹은 VM과 유사하게 동작한다.

 

  • 클러스터의 모든 Pod는 하나의 Flat한 공유 네트워크 주소 공간에 상주한다.
  • 모든 Pod는 다른 Pod의 IP 주소를 사용하여 접근하는 것이 가능하다.
    (Pod간 어떠한 NAT도 존재하지 않으며 마치 LAN처럼 통신이 가능하다.)
  • 두 파드가 서로 네트워크 패킷을 보내면, 상대방의 실제 IP주소를 패킷 안에 있는 출발지 IP 주소에서 찾을 수 있다.


Pod 실습

 

파드를 정의하는 간단한 YAML 정의 작성

# 쿠버네티스 API v1 을 준수함
apiVersion: v1

# 오브젝트 종류는 Pod, Pod 이름은 kubia-manual
kind: Pod
metadata:
 name: kubia-manual

spec:
# 컨테이너를 생성하는 컨테이너 이미지
 containers:
 - image: luksa/kubia
   name: kubia
# 어플리케이션이 수신하는 포트
   ports:
   - containerPort: 8080
     protocol: TCP

 

파드 생성하기

  • YAML 파일을 이용해 파드를 만드려면 kubectl create 명령을 이용한다.
  • kubectl create -f 명령은 YAML 또는 JSON 파일로 (Not only Pod) 리소스를 생성하는데 사용
root@k8s-m:~# kubectl create -f kubia-manual.yaml
pod/kubia-manual created
💡 kubectl create vs kubectl apply

kubectl create = 명령형 (Imperative)
kubectl apply = 선언형 (Declarative)

create 명령은 각 오브젝트의 구성이 그 구성파일 내에 완전하게 정의되고 기록되어질 경우 잘 작동한다. 하지만 활성 오브젝트가 업데이트 되고, 구성파일 안에 병합하지 않으면 업데이트 내용은 다음 replace가 될 때 삭제될 것이다. 동일 오브젝트에 대하여 여러 명의 작성자들로부터 지원이 필요할 경우 오브젝트를 관리하기 위해 kubectl apply를 사용할 수 있다.

참조: https://stackoverflow.com/questions/47369351/kubectl-apply-vs-kubectl-create

 

실행중인 파드의 전체 정의 가져오기

  • 파드 전체 정의를 볼 수 있다.
    kubectl get po kubia-manual -o yaml
  • JSON 형식으로 보기 원하면, kubectl 명령으로 YAML 대신 JSON을 반환할 수 있다. 
    kubectl get po kubia-manual -o json​

파드 목록에서 새로 생성된 파드 보기

  • kubectl get pods 명령을 통해 생성된 파드가 정상적으로 동작하는지 조회할 수 있다.
root@k8s-m:~# kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
kubia-manual   1/1     Running   0          22h

 

Application 로그 보기

  • 존재하는 파드의 컨테이너 로그만 가져올 수 있다는 점에 유의하자
  • 어떠한 웹 요청도 Node.js Application으로 보내지 않았기에 서버가 시작할 때 남긴 로그 한줄만 표시된다.
root@k8s-m:~# kubectl logs kubia-manual 
Kubia server starting...

 

컨테이너 상태 모니터링

  • 컨테이너 생성 시점과 실제 서비스 준비가능 시점은 차이점이 존재한다.
  • 서버를 실행하면 바로 접속할 수 없으며 짧게는 수 초 길게는 수 분의 초기화 시간이 필요하다.

( ※ 실질적으로 서버에 접속이 가능할 때 서비스가 준비되었다라고 말할 수 있다. ※ )


참조

쿠버네티스 인 액션

댓글