Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

Pod

다른 컨테이너 오케스트레이션 툴과 달리, Kubernetes는 컨테이너를 직접 실행하지 않는다. 대신에 하나 이상의 컨테이너를 그룹으로 묶어서 구조화한 pod를 관리한다. 같은 pod에 포함된 컨테이너들은 네트워크, IPC, 볼륨등을 공유한다. Pod에 포함된 컨테이너들은 하나의 물리적 노드에 배치가 되는데, 때문에 이들 자원의 공유와 커뮤니케이션이 쉬워진다. 하나의 노드에는 여러 pod가 배치될 수 있는데, 이들 pod는 다른 pod와 완전히 격리(isolation)된다.

 Pod

Kubernetes의 복제(replica)도 pod 단위로 이루어진다. 단일 pod로 클라이언트 요청을 감당 할 수 없을 경우, pod의 복제본을 다른 클러스터에 전개하도록 할 수 있다. 부하가 과중하지 않더라도 가용성을 위해서 두 개 이상의 pod 복제본을 만드는게 표준적인 구성이다.

Pod는 하나 이상의 컨테이너로 구성할 수 있지만, 멀티 컨테이너로 구성하는 건 주의를 해야 한다. 일단 pod를 복제하면 각 개별 컨테이너의 요구에 상관없이 확장을 해야 한다. 이는 자원의 낭비로 이어질 수 있다. Pod는 가능한 작게 유지하고, 주 프로세스와 단단히 열결된 헬퍼 컨테이너(helper container)를 운영하는게 좋은 방법이다.(Helper container를 보통 "side-cars"라고 한다.)

  • 단일 컨테이너로 구성된 pod : "one-container-per-Pod"는 kubernetes에서 이용하는 일반적인 pod 구성이다. 이 구성에서 pod는 단지 컨테이너의 wrapper 정도로 볼 수 있다.
  • 멀티 컨테이너로 구성된 pod : 함께 작동하는 여러 컨테이너를 하나의 pod에 배포하는 경우다. 컨테이너들이 밀접하게 연결돼 있으며, 자원을 공유 해야 할 때 사용하는 방법이다. 함께 배치된 컨테이너는 볼륨과 파일을 공유할 수 있다.

Pod와 Container

도커 컨테이너와 Pod와의 관계를 살펴보자.

도커 컨테이너라는 용어 때문에 헷갈릴 수 있을 것 같은데, 엄밀히 말하자면 리눅스에 "컨테이너"라는 것은 존재하지 않는다. 리눅스에 "컨테이너"라는 것은 없다. 사람들이 말하는 컨테이너라는 것은 리눅스의 네임 스페이스(namespace)와 cgroup이라는 두 가지 리눅스 커널 기능을 사용하여 실행되는 "프로세스"일 뿐이다. 이것을 컨테이너라고 부르는 이유는 namespace와 cgroup으로 만들어진 프로세스가 다른 프로세스와 완전히 격리되는 모습이 컨테이너와 닯아서 그렇게 부르는 거다. 리눅스 namespace와 cgroup으로 격리된 프로세스는 외부프로세스에서 접근을 할 수 없다.

아래의 자원에 대해서 네임스페이스를 설정 할 수 있다.
  • Hostname
  • Process IDs
  • File System
  • Network Interface
  • IPC(Inter Process Communication)
3개의 Nginx 컨테이너를 실행하면 대략 아래의 모습을 가진다.

 컨테이너의 구성

그림에서 처럼 3개의 Nginx 프로세스는 다른 프로세스와 독립적인 IPC, PIDs, 네트워크 환경을 가진다.

컨테이너는 프로세스에 격리된 환경을 제공하므로, 하나의 컨테이너는 하나 이상의 프로세스로 구성될 수 있다. Nginx와 wordpress, mysql로 구성된 컨테이너는 아래와 같이 구성될 것이다.

 멀티 프로세스 컨테이너

하나의 격리된 환경(컨테이너)에 3개의 프로세스가 돌아가는 모습이다. nginx와 wordpress는 localhost로 통신을 하고, wordpress와 mysql은 file(unix domain socket)으로 통신을 한다.

Pod는 컨테이너다

Cgroup과 네임스페이스를 이용한 하나의 격리된 환경에서 다수의 프로세스를 실행시킬 수 있다는 것을 알았다. Kubernetes의 Pods도 (컨테이너와 역할을 같고 방법에 있어서 약간의 차이가 있는 정도)정확히 같은 모습으로 보면 된다. Kubernetes는 나름대로의 방법으로 네임스페이스와 cgroup을 관리한다. 그리고 Docker 네트워크가 아닌 CNI를 사용함으로써 유연한 네트워크를 구성 할 수 있다.

 Pods

단순하게 각 프로세스가 동일한 머신위에서 실행한다고 생각하면 된다. 이들 프로세스는 localhost(127.0.0.1)로 네트워크 통신을 할 수 있으며, 볼륨에 있는 파일을 공유 할 수 있다. 또는 IPC를 이용하거나 HUP, TERM 시그널을 보낼 수도 있다.

Networking

Pod는 유일한 IP를 할당 받는다. Pod 안에 있는 모든 컨테이너들은 IP와 포트번호를 포함한 네트워크 네임스페이스를 공유한다. Pod에 있는 컨테이너들은 localhost를 사용해서 통신 할 수 있다. 만약 pod에 있는 컨테이너가 외부 pod의 컨테이너와 통신을 해야 한다면, 공유 네트워크 리소스를 이용해야 한다.

스토리지

Pod는 스토리지 볼륨을 공유한다. Pod에 있는 모든 컨테이너는 볼륨과 볼륨에 있는 파일들에 접근 할 수 있다. 볼륨을 사용하면 컨테이너를 재 시작하는 경우에도 pod의 데이터를 영구히 저장 할 수 있다.

Pod 작업

Kubernetes는 단일하게 실행하는 pod 조차도 "직접" 만들지는 않는다. 이것은 "pod는 일시적일 수 있다"관점을 유지하기 때문이다. Pod가 만들어지면 클러스터의 노드에서 실행되도록 예약이 된다. Pod는 리소스의 부족, 노드의 실패 등으로 삭제 될 수 있는데, Pod는 self-heal과 같은 고수준의 기능을 제공하지 않는다. 대신에 컨트롤러(controller)를 이용해서 Pod 인스턴스를 관리한다.

Pod Controllers

컨트롤러는 pod의 복제, rollout, 자가치유(self-healing)등의 기능을 제공하며, 여러 개의 pod를 만들고 관리한다. 예를 들어 노드에 장애가 발생하면 컨트롤러는 장애가 발생한 노드에 있던 pod를 다른 노드에서 실행해서 장애에 대응 한다. 컨트롤러는 애플리케이션 운용 방식에 따라서 아래의 3가지 타입을 선택해서 사용 할 수 있다.
  • Deployment
  • StatefulSet
  • DaemonSet

Pod 템플릿

Pod 템플릿에는 복제 컨트롤러 이름, 작업(job)등 pod 사양을 저장하고 있다. 컨트롤러는 pod 템플릿을 읽어서 실제 pod를 만든다. 아래는 nginx를 실행하는 간단한 pod 템플릿이다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
  • apiVersion : 템플릿을 실행하기 위해서 사용할 API의 버전
  • kind : pod의 타입
  • metadata : 객체를 식별하기 위한 name등의 데이터들, UID와 namespace를 옵션으로 설정 할 수 있다.

pod의 실행

kubernetes 환경을 갖췄다고 가정한다. 혹은 kubernetes 사이트의 Interactive Tutorial를 이용하자.

kubectl create 명령으로 pod를 전개 할 수 있다. 사용방법은 아래와 같다.
kubectl create -f [pod template file]
Pod 템플릿 파일은 JSON과 YAML 포맷을 지원한다. 예를 들어 nginx.yaml 템플릿에서 pod를 전개하겠다고 하면 아래와 같이하면 된다.
kubectl create -f ./nginx.yaml

원격에 있는 템플릿 파일을 읽어서 실행 할 수도 있다. 직접 실행해 보자. nginx 컨테이너가 실행되는 걸 확인 할 수 있을 거다.
# kubectl create -f https://k8s.io/examples/application/deployment.yaml --record
deployment.apps/nginx-deployment created

잘 돌아가고 있는지 확인해보자.
# kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-67594d6bf6-gj2wp   1/1       Running   0          1m
nginx-deployment-67594d6bf6-j96pr   1/1       Running   0          1m

pod의 상태

Pod는 아래 4개의 상태를 가지고 있다.
  • Pending: Kubernetes 시스템은 pod 요청을 받아들였다. 하지만 아직 컨테이너를 실행하지는 않았다.
  • Running: 적어도 하나 이상의 컨테이너가 실행됐다.
  • Succeeded : Pod의 모든 컨테이너가 정상상태(종료값이 0)로 종료됐으며, 재 시작하지 않았다.
  • Failed : Pod의 모든 컨테이너가 종료 됐으나 하나 이상의 컨테이너가 0이 아닌 값을 반환 했다.
  • CrashLoopBackoff: 컨테이너가 실패해서, 계속해서 재 실행하고 있다.

참고