Chapter 4

파드와 YAML

  • 4.1 파드
  • 4.2 파드와 YAML
  • 4.3 YAML로 파드 만들기 실습

Kubernetes에서 배포의 최소 단위는 컨테이너가 아니라 파드야. 파드가 뭔지, YAML로 어떻게 정의하는지, 실제로 만들어보는 것까지 이 챕터에서 다뤄.

Kubernetes는 컨테이너를 직접 워커 노드에 배포하지 않아. 컨테이너는 **파드(Pod)**라는 Kubernetes 오브젝트로 캡슐화되고, 파드가 배포의 최소 단위가 돼. 파드는 애플리케이션의 단일 인스턴스야.

스케일업이 필요하면 어떻게 할까? 같은 파드 안에 컨테이너를 추가하는 게 아니라, 새로운 파드를 생성해. 스케일다운할 때는 기존 파드를 삭제하고. 파드와 컨테이너는 일반적으로 1:1 관계야. 현재 노드에 용량이 부족하면 클러스터의 새 노드에 추가 파드를 배포할 수도 있어.

그럼 단일 파드에 컨테이너가 하나만 들어갈 수 있냐? 아니야, 여러 컨테이너를 넣을 수 있어. 다만 같은 종류의 컨테이너를 여러 개 넣는 건 아니야. 헬퍼 컨테이너가 있는 경우에 같은 파드에 넣지. 예를 들어 사용자가 입력한 데이터를 처리하거나 업로드한 파일을 처리하는 보조 컨테이너가 있을 때, 이 헬퍼 컨테이너를 애플리케이션 컨테이너와 같은 파드에 넣을 수 있어. 이렇게 하면 애플리케이션 컨테이너가 생성될 때 헬퍼도 같이 생성되고, 죽을 때 같이 죽어. 같은 네트워크 공간을 공유하니까 localhost로 직접 통신할 수 있고, 같은 스토리지도 쉽게 공유할 수 있어.

이게 왜 좋은지 Docker 관점에서 생각해보자. Docker만 쓸 때 앱 컨테이너와 헬퍼 컨테이너를 함께 운영하려면, 어떤 앱과 헬퍼가 연결되어 있는지 맵을 관리해야 하고, 링크와 커스텀 네트워크로 직접 네트워크를 설정해야 하고, 공유 볼륨을 만들어서 연결해야 하고, 앱 컨테이너가 죽으면 헬퍼도 수동으로 종료해야 하고, 새 컨테이너 배포 시 헬퍼도 같이 배포해야 해. 이 모든 걸 Kubernetes가 파드라는 개념으로 자동으로 해줘. 파드가 어떤 컨테이너로 구성되는지 정의만 하면, 같은 스토리지, 같은 네트워크 네임스페이스를 공유하고, 함께 생성되고 함께 소멸해.

다만 다중 컨테이너 파드는 드문 사용 사례야. 이 과정에서는 주로 파드당 단일 컨테이너를 다뤄.

파드를 배포하는 가장 간단한 방법은 kubectl run 명령이야:

kubectl run nginx --image=nginx

이 명령이 파드를 자동으로 생성하고 nginx Docker 이미지의 인스턴스를 배포해. 이미지는 Docker Hub 같은 리포지토리에서 다운로드되는데, 프라이빗 리포지토리에서 가져오도록 설정할 수도 있어.

파드 목록을 확인하려면:

kubectl get pods

처음에는 ContainerCreating 상태였다가 곧 Running 상태로 바뀌는 걸 볼 수 있어. 지금 상태에서는 외부 사용자가 nginx 웹 서버에 접근할 수 있도록 설정하지 않았어. 네트워킹과 서비스에 대해서는 이후 강의에서 다뤄.

명령어 한 줄로 파드를 만들 수 있지만, 실무에서는 YAML 정의 파일을 쓰는 게 일반적이야. Kubernetes 정의 파일(YAML)에는 항상 네 가지 최상위 필드가 있어야 해: apiVersion, kind, metadata, spec. 이건 필수야.

apiVersion은 오브젝트를 생성하는 데 사용하는 Kubernetes API 버전이야. 파드의 경우 v1을 써. 다른 값으로는 apps/v1, extensions/v1beta1 같은 것도 있는데, 오브젝트 종류에 따라 달라.

kind는 생성하려는 오브젝트의 유형이야. Pod, ReplicaSet, Deployment, Service 같은 게 올 수 있어. 대소문자를 구분하니까 주의해.

metadata는 오브젝트에 대한 데이터로, 사전(dictionary) 형식이야. name과 labels 같은 게 들어가. name은 문자열이고, labels는 사전 안의 사전이야. labels 아래에는 원하는 키-값 쌍을 자유롭게 넣을 수 있어. 예를 들어 app: myapp 같은 레이블을 붙이면 나중에 파드를 필터링할 때 유용해. 프론트엔드, 백엔드, 데이터베이스 파드가 수백 개씩 있을 때 레이블로 구분할 수 있거든. 다만 metadata 바로 아래에는 Kubernetes가 기대하는 항목(name, labels 등)만 넣을 수 있어. 임의의 속성을 추가할 수 없어. 하지만 labels 아래에는 아무 키-값 쌍이나 넣을 수 있어.

들여쓰기가 중요해. name과 labels는 metadata의 하위 항목이니까 metadata보다 오른쪽에 있어야 하고, 서로 형제니까 같은 수준의 들여쓰기를 가져야 해.

spec은 오브젝트에 따라 내용이 달라지는 섹션이야. 파드의 경우 containers라는 속성이 있는데, 이건 목록(배열)이야. 파드에 여러 컨테이너가 들어갈 수 있으니까. 목록의 각 항목에는 name과 image가 있어.

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
    - name: nginx
      image: nginx

파일이 준비되면 이렇게 파드를 만들어:

kubectl create -f pod-definition.yaml

파드를 확인하려면:

kubectl get pods

파드에 대한 상세 정보를 보려면:

kubectl describe pod myapp-pod

이러면 파드가 생성된 시기, 레이블, Docker 컨테이너 정보, 관련 이벤트 등을 볼 수 있어.

그러면 직접 해보자. YAML 정의 파일을 사용해서 파드를 만드는 실습이야. kubectl run 명령 대신 YAML 파일을 직접 작성해서 만들어볼 거야.

먼저 YAML 파일을 작성해. 편집기는 뭘 써도 되는데, YAML 언어를 지원하는 편집기(Windows의 Notepad++, Linux의 vim 등)를 쓰면 구문 작성에 도움이 돼.

네 가지 루트 레벨 속성부터 시작해:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
    - name: nginx
      image: nginx

apiVersion은 파드니까 v1, kind는 Pod(대문자 P, 대소문자 구분해). metadata는 사전이고, 그 아래 name과 labels를 넣어. labels도 사전이라 그 아래에 원하는 만큼 키-값 쌍을 넣을 수 있어. app: nginx, tier: frontend 같은 식으로.

들여쓰기가 중요해. app과 tier는 labels의 하위 항목이니까 같은 수직선에 있어야 하고, name과 labels는 metadata의 하위 항목이니까 역시 같은 수준에 있어야 해. 보통 두 칸 공백을 쓰고, 탭은 쓰지 않는 게 좋아. 전체적으로 일관되게 유지해.

spec 아래 containers는 객체의 목록이야. 하이픈(-)이 목록의 항목을 나타내. 각 컨테이너에는 name과 image가 있어. name은 파드 내 컨테이너 이름이고, image는 Docker Hub(또는 다른 레지스트리)의 이미지 이름이야. 다른 레지스트리를 쓴다면 이미지 리포지토리의 전체 경로를 지정해야 해.

멀티 컨테이너 파드를 만들려면 목록에 항목을 추가하면 돼:

spec:
  containers:
    - name: nginx
      image: nginx
    - name: busybox
      image: busybox

파일을 저장한 후 파드를 생성해:

kubectl create -f pod.yaml

kubectl create이나 kubectl apply 둘 다 사용할 수 있어. 새 오브젝트를 만들 때는 둘 다 동일하게 작동하거든.

상태를 확인하면 처음에는 ContainerCreating이었다가 곧 Running으로 바뀌는 걸 볼 수 있어:

kubectl get pods

더 자세한 정보가 필요하면:

kubectl describe pod nginx

정리

4장 읽고 기억할 거 세 가지:

  1. 파드 = 배포의 최소 단위. 스케일업은 파드를 추가하는 거지, 컨테이너를 추가하는 게 아니야. 파드:컨테이너는 일반적으로 1:1
  2. YAML의 네 가지 필수 필드: apiVersion, kind, metadata, spec. 이 구조를 외우면 모든 Kubernetes 오브젝트 정의의 뼈대가 잡혀
  3. labels가 핵심이야. 지금은 단순한 태그처럼 보이지만, 나중에 ReplicaSet이나 Service가 파드를 찾을 때 selector로 labels를 사용해