상세 컨텐츠

본문 제목

쿠버네티스 기초실습 (GCP 기반) - 2 - Pod

소프트웨어/인프라

by moonionn 2022. 10. 1. 17:48

본문

 

1. Pod란?

Pod는 쿠버네티스에서 가장 작은 배포단위이자, 컨테이너를 관리하는 가장 작은 논리적인 단위입니다.

하나의 Pod에는 여러 컨테이너가 포함될 수 있으며, 이들은 같은 네트워크, 같은 볼륨(저장공간)을 공유합니다.

 

출처: https://speakerdeck.com/devinjeon/kubernetes-pod-internals-with-the-fundamentals-of-containers

 

왜 컨테이너를 직접 다루지 않고 Pod라는 단위로 관리할까?

우리는 흔히들 컨테이너하면 도커 컨테이너만 떠올리기 쉽지만 컨테이너의 종류는 그보다 더 다양합니다. 

종류별로 스펙도 상이하여 사람이 컨테이너별 요구사항을 다 알고 관리하는 것은 쉽지 않기 때문에 하나로 묶을 수 있는 논리적 단위가 필요하다고 합니다.

 

2. Pod 배포해보기

쿠버네티스 배포를 위해서는 스펙이 적힌 yaml 파일이 필요합니다.

# pods01.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hello-pod
spec:
  containers:
    - name: hello-pod
      image: nginx:latest
      ports:
        - containerPort: 80

파일 내용 들여다보기

apiVersion

쿠버네티스 배포는, 쿠버네티스 api에게 쿠버네티스 객체 생성을 요청하는 방식이라고 이해하면 될 것 같습니다. 따라서 배포 형식에 알맞은 api 스펙을 명시해주어야 합니다. 

참고: https://blog.knoldus.com/what-is-apiversion-in-kubernetes-part-1/

 

kind

생성할 객체의 종류를 명시합니다. 현재 가장 작은 배포 단위인 Pod에 대해 스터디하고 있으므로 Pod이라고 적어두었습니다.

 

metadata

객체의 이름(name)이나 네임스페이스(namespace)... 를 지정해줍니다. 위 yaml 파일의 내용에 따르면 hello-pod라는 이름의 객체가 default namepsace에 생성될 것입니다. (따로 namespace를 지정해주지 않았으므로)

하나의 namespace안에서 name은 중복될 수 없습니다.

 

spec

컨테이너, 볼륨 등 Pod의 내부적인 스펙을 정해줍니다. 컨테이너 이름과 이미지, 포트 등을 설정해줍니다. 여기서는 nginx 이미지를 사용해보았습니다.

 

파일이 준비되었으면 apply 명령어로 배포합니다. -f는 force 옵션이며, 여기서 쓰인 apply 명령어 외에도 create 명령어를 사용할 수도 있습니다. 기존에 오브젝트가 존재하든 존재하지 않든 apply 명령어는 사용 가능한 반면 create 명령어는 오브젝트 첫 생성시에만 사용 가능합니다.

잘 생성되었다면 ${name} created 문구가 뜹니다. kubectl get po 명령어로 생성된 pod를 확인할 수 있습니다.

Running status의 pod를 확인했다면 exec 명령어로 Pod내 컨테이너에 접근해볼 수 있습니다. docker exec -it 명령어와 유사합니다.

kubectl exec -it pods101 -- /bin/bash

 

3. 여러 컨테이너를 가진 Pod 배포해보기

앞서 말했듯 하나의 Pod에는 여러 컨테이너가 포함될 수 있습니다. 각 고유한 name의 컨테이너들 스펙을 적어줍니다. 여기서는 기존에 올렸던 nginx 이미지 외에 watcher (로깅 목적의 이미지) 이미지를 추가로 올려줍니다.

# pods02.yaml

apiVersion: v1
kind: Pod
metadata:
  name: hello-pod
spec:
  containers:
    - name: hello-pod
      image: nginx:latest
      ports:
        - containerPort: 80
    - name: webwatcher
      image: afakharany/watcher:latest

 

이번에도 apply 명령어 사용뒤 pod를 확인해보면 처음 배포했던 것과 다르게 컨테이너 수가 2개가 뜬 것을 확인할 수 있습니다.

 

GCP 콘솔에서도 컨테이너 두 개가 떠 있는 것을 확인할 수 있습니다.

 

kubectl exec -it hello-pod -c webwatcher -- /bin/bash

이제 컨테이너 내부로 접근하는 방식도 달라집니다. exec 명령어에 -c 옵션으로 접근하려는 컨테이너를 지정해줘야 합니다. 만일 컨테이너를 지정해주지 않는다면 디폴트 컨테이너로 접근합니다.

 

컨테이너를 지정해주지 않으면 디폴트 컨테이너로 접근됨

 

3. 볼륨쉐어링

컨테이너들은 하나의 Pod 안에서 같은 볼륨(저장 공간)을 공유할 수 있습니다.

아래 yaml 파일은 여러 컨테이너들이 어떻게 하나의 저장 공간을 공유하는지 알아보기 위한 내용입니다. spec 안에 containers 외에 volumes라는 설정이 추가되었습니다. 여기서는 `html` 이라는 이름의 emptyDir 볼륨 유형을 정의하였습니다.

# pods03.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mc1
spec:
  volumes:
  - name: html
    emptyDir: {}
  containers:
  - name: 1st
    image: nginx
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  - name: 2nd
    image: debian
    volumeMounts:
    - name: html
      mountPath: /html
    command: ["/bin/sh", "-c"]
    args:
      - while true; do
          date >> /html/index.html;
          sleep 1;
        done

파일 내용 들여다보기

emptyDir 볼륨 유형

emptyDir 볼륨 유형은 컨테이너가 노드에 할당될 때 비어있는 상태로 할당됩니다. 해당 볼륨 내 데이터들은 Pod가 삭제될때 함께 제거됩니다. 따라서 Pod 자체를 삭제하지 않는 이상 컨테이너를 재시작하여도 기존에 사용하던 데이터는 그대로 보존됩니다. (컨테이너 crash는 예외)

 

컨테이너 볼륨 마운트

그 다음 컨테이너 두 개를 추가합니다. 간단하게 1st, 2nd 라는 name의 컨테이너들입니다. 1st 컨테이너는 html 볼륨을 /usr/share/nginx/html 이라는 경로에 마운트하고, 2nd 컨테이너는 html 볼륨을 /html 경로로 마운트하도록 했습니다.

그리고 해당 /html 경로에 있는 index.html 파일에 1초마다 날짜를 찍는 명령어를 설정해두었습니다.

 

 

이제 각 컨테이너에서 각자 마운팅한 경로의 index.html 파일 내용을 확인해보면 동일한 파일내용을 읽어올 수 있습니다.

 

 

관련글 더보기

댓글 영역