HomeAbout
[Kubernetes] Kubernetes Pod 이해하기 : 기본 개념과 YAML 설정 예제
Docker & Kubernetes
[Kubernetes] Kubernetes Pod 이해하기 : 기본 개념과 YAML 설정 예제
NASA1515
NASA1515
June 22, 2021
3 min

목차

01
✔ POD?!
02
✌ POD 생성 실습
03
🤦‍♂️ 컨테이너 두개 이상을 포함한 pod 만들기

✔ POD?!

Pod는 Kubernetes에서 애플리케이션의 기본 실행 단위로, 가장 작은 배포 단위입니다.
POD는 하나 이상의 ‘동작중인’ 컨테이너를 포함하고 있는 Object이고 하나의 POD에는 하나의 컨테이너를 배치하는 게 기본입니다.
또한, 이 컨테이너들은 네트워크와 저장소를 공유합니다.
클러스터 내에서 POD는 주로 두 가지 방법으로 사용되죠.

스크린샷, 2020-09-16 15-29-48


Pod 모델 종류


1. 1개 컨테이너 - 단일 POD 모델

“one-container-per-Pod”은 쿠버네티스에서 가장 널리 쓰이는 케이스 입니다.
한개의 pod가 1개의 container을 감싸고 있으며, 쿠버네티스에서 해당 pod을 관리합니다.


2. 2개 이상 컨테이너 - 다중 POD 모델

2개 이상의 container가 리소스를 밀접하게 공유해야하는 상황에 쓰입니다.
하나의 컨테이너가 file을 제공해주면 “sidecar” 역할을 하는 컨테이너가 해당 file에 접근하는 개념입니다.
즉 쉽게 말해 서로 의존성이 있는 다중 컨테이너가 동작 중인 POD. 리소스 공유가 필요한 결합 서비스 단위인 경우입니다.


부가 설명

기본적으로 하나의 컨테이너에는 최소한의 필요한 기능 즉 하나의 컨테이너는 하나의 기능만 하는 것이 기본입니다.
그런데 VM에 익숙해지면 착각하는 것이 하나의 컨테이너에 여러 개의 어플리케이션을 돌리면 효율적이지 않겠냐는 의문 들기 시작합니다.
하지만 Dockerfile의 메커니즘 자체가 그렇듯 하나의 컨테이너는 하나의 어플리케이션만 띄울 수 있도록 설계되어 있습니다.
쉘 스크립트나 docker-compose를 이용해서 동시에 여러 동작을 유발할 수는 있지만 원칙은 그렇습니다.

다만, 컨테이너는 유연하게 확장/축소가 가능하다는 것이 장점입니다.
만약 하나의 컨테이너에 웹, DB, APP를 실행시키는 것은 가장 기본적인 목적인 'APP 격리'에 위배됩니다.
POD가 사용되는 방식 중 하나인 '다중 컨테이너의 동작''멀티 컨테이너'이지 여러 개를 실행하는 것과는 다르다는 것 입니다.
또한 POD의 컨테이너는 같은 노드에서만 동작하고, 하나의 POD에 있는 다중 컨테이너는 저장소, 네트워크 IP 등을 공유합니다.

요약하자면 아래와 같은 특성들을 가지고 있는 것이죠.

Pod의 특징

  • 격리: 각 컨테이너는 독립적으로 실행되며, 격리된 환경에서 운영됩니다. 이는 애플리케이션의 안정성과 보안을 높입니다.
  • 자원 공유: 같은 Pod 내의 컨테이너들은 저장소와 네트워크를 공유하여 효율적인 자원 사용을 가능하게 합니다.

POD는 어떻게 다중 컨테이너를 관리할까?

POD는 애초에 결합성이 있는 서비스를 위해 다중 컨테이너를 지원하도록 디자인 되었습니다.
Volume 내부의 웹 역할을 하는 컨테이너와 원격 소스로부터 그 파일들을 업데이트하는 분리된 “사이드카” 컨테이너가 있는 경우 아래와 같습니다.

스크린샷, 2020-09-16 15-49-34

  • web server가 추가로 필요하게 되면 file puller도 같이 하나가 POD단위로 증가하게 되는데 이러한 패턴을 '사이드 카' 패턴이라고 합니다.
    Kubernetes에서는 결합성이 강한 경우만 사용하도록 권고하고 있습니다. 이 때, POD는 POD 안에 속해 있는 Container 사이에 두 가지의 공유 리소스를 제공합니다.

바로 네트워킹저장소인 경우 입니다.


네트워킹

  • 각 POD는 고유한 IP를 할당 받고, 한 POD 안에 있는 모든 Container는 Network NameSpace와 IP주소, Port를 공유합니다.
    POD끼리는 localhost를 이용해서 내부적으로 통신이 가능하고, 밖의 요소와 통신을 위해선 같은 네트워크 리소스 사용 상태를 서로 공유하고 있어야 합니다.

저장소

  • POD 내부의 모든 컨테이너는 공유 볼륨에 접근할 수 있고 그 컨테이너끼리 데이터를 공유할 수 있습니다.
    또한 볼륨은 컨테이너가 재시작 되더라도 POD 안의 데이터를 영구적으로 유지할 수 있게 합니다.


POD의 Lifecycle

  • 일단 POD가 생성되면 POD에는 고유한 ID가 할당되고, 노드에 스케줄링 됩니다.
    해당 노드가 종료되면 해당 노드에 스케줄링 되어있던 POD는 일정 시간이 지난 후 삭제되게 되고
    노드가 삭제된다고 해서 소속되어있던 POD가 리스케줄링 되지 않으며 필요시 완전히 새로운 POD를 다시 생성하는 방식입니다.
    같은 이유로 POD는 문제가 발생하더라도 자가 복구를 하지 않습니다. 만약 POD의 동작이 실패하는 경우 POD는 그대로 삭제 될 뿐 입니다.
    이와 같이 POD Instance를 Management하는 과정에서 컨트롤러가 사용 됩니다.

즉, POD는 사용자나 컨트롤러가 명시적으로 삭제하기 전까지는 남아 있게 됩니다.


POD의 종료


절차

  • POD가 더 이상 필요하지 않을 때에는 종료시켜야 합니다 사용자는 삭제를 요청할 수 있어야 하고, 프로세스가 종료되는 것, 삭제된 것을 확인 할 수 있어야 합니다.
    POD 삭제 요청을 하면 시스템은 POD가 종료 되기 전 정리를 위한 유예 기간을 두었다가, KILL 시그널이 해당 프로세스로 전송되면 POD가 API 서버에서 삭제됩니다.
  • 사용자의 삭제 명령(default 유예기간: 30초)
  • 유예기간이 지난 POD 정보가 갱신
  • 이 POD는 조회시 Terminating이라는 문구 출력
  • Terminating으로 표시되는 것을 확인하면 kubelet은 종료 작업 시작
  • 종료한 POD는 엔드포인트 리스트에서 제거되며, 레플리케이션 컨트롤러의 관리 대상에서 제외
  • 만약 도중에 유예 기간이 만료되면 POD에서 실행중이던 모든 프로세스에 SIGKILL이 떨어짐
  • kubelet은 유예기간을 0으로 세팅해서 API 서버로부터 POD를 즉시 삭제할 수 있음. 이제 POD는 더이상 보이지 않음.

강제 삭제

  • 기본적으로 삭제 작업은 30초 이내에 끝납니다. kubectl delete 명령은 —grace-period={second} 옵션을 지원하는데,
    이 옵션은 기본 설정된 값을 사용자가 정의할 수 있도록 하는 옵션으로, 0이 되면 POD는 즉시 삭제됩니다.
    kubectl 1.5버전 이상에서는 강제 삭제를 위해서 반드시 --grace-period=<second>와 함께 --force를 같이 사용해야 합니다.
    POD를 강제 삭제하면 API서버는 kubelet으로부터 실행중이던 POD가 종료되었다는 통지를 기다리지 않고 API단에서 POD를 즉시 제거해버리기 때문에 동일한 이름으로 새 POD를 만들 수도 있습니다.

✌ POD 생성 실습


kubectl explain 명령으로 POD 리소스의 필드를 확인 해보죠

[root@nasa-master ~]# kubectl explain pod.spec.containers
KIND:     Pod
VERSION:  v1

RESOURCE: containers <[]Object>

DESCRIPTION:
    List of containers belonging to the pod. Containers cannot currently be
    added or removed. There must be at least one container in a Pod. Cannot be
    updated.

    A single application container that you want to run within a pod.

FIELDS:
image   <string>
    Docker image name. More info:
    https://kubernetes.io/dojs/concepts/containers/images This field is
    optional to allow higher level config management to default or override
    container images in workload controllers like Deployments and StatefulSets.
...


이제 연습삼아 POD를 정의하는 yaml파일을 만들어보겠습니다.

apiVersion: v1 
kind: Pod 
metadata: 
name: nasa-nginx-pod 
spec: 
containers: 
- name: nasa-nginx-container 
    image: nginx:latest 
    ports: 
    - containerPort: 80 
        protocol: TCP

위 yaml 파일을 세부적으로 설명해보겠습니다.

  • apiVersion : YAML 파일에서 정의한 오브젝트의 API 버전을 나타냅니다.
  • kind : 이 리소스의 종류를 나타냅니다. 위에선 pod로 생성하기 때문에 pod 다른 오브젝트의 종류는 kubectl api-resources 명령어를 통해 확인할 수 있습니다.
  • metadata: 라벨, 주석, 이름과 같은 리소스의 부가 정보들을 입력합니다.
  • spec: 리소스를 생성하기 위한 자세한 정보를 입력합니다. 생성되는 container의 이름, 이미지, 포트 등을 설정할 수 있습니다.
pod.spec.containers : 컨테이너 정의
pod.spec.containers.image: 컨테이너에 사용할 이미지
pod.spec.containers.name: 컨테이너 이름
pod.spec.containers.ports: 노출할 포트 정의
pod.spec.containers.ports.containerPort: 노출할 컨테이너 포트번호
pod.spec.containers.ports.protocol: 노출할 컨테이너 포트의 기본 프로토콜

작성한 YAML파일을 기반으로 POD를 생성해보겠습니다

kubectl apply -f yaml 파일이름
[root@nasa-master nasa]# kubectl apply -f nasa.yml 
pod/nasa-nginx-pod created

POD 동작상태 확인

[root@nasa-master nasa]# kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nasa-nginx-pod   1/1     Running   0          64s

실행중인 POD 정의 확인

  • -o 옵션에는 yaml과 json 중 하나를 선택할 수 있습니다.
[root@nasa-master nasa]# kubectl get pods nasa-nginx-pod -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
    {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nasa-nginx-pod","nam
espace":"default"},"spec":{"containers":[{"image":"nginx:latest","name":"nasa-nginx-container",
"ports":[{"containerPort":80,"protocol":"TCP"}]}]}}
creationTimestamp: "2020-09-16T07:26:45Z"
name: nasa-nginx-pod
namespace: default
resourceVersion: "39554"
selfLink: /api/v1/namespaces/default/pods/nasa-nginx-pod
uid: 148bfb1a-73ad-4c44-805d-300cb5be8af8
spec:
containers:
- image: nginx:latest
    imagePullPolicy: Always
    name: nasa-nginx-container
    ports:
    - containerPort: 80
    protocol: TCP
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
    name: default-token-556xc
    readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: nasa-node3
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300

POD의 describe 확인

[root@nasa-master nasa]# kubectl describe pods nasa-nginx-pod
Name:         nasa-nginx-pod
Namespace:    default
Priority:     0
Node:         nasa-node3/10.146.0.9
Start Time:   Wed, 16 Sep 2020 07:26:45 +0000
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nasa-nginx
-pod","namespace":"default"},"spec":{"containers":[{"image"...
Status:       Running
...

pod도 container와 같이 kubectl exec를 통해 명령어를 실행시킬 수 있습니다.

kubectl exec -it nasa-nginx-pod bash
[root@nasa-master nasa]# kubectl exec -it nasa-nginx-pod bash
root@nasa-nginx-pod:/# 
root@nasa-nginx-pod:/# ls     
bin   dev                  docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc                   lib   media  opt  root  sbin  sys  usr

또 도커와 같이 kubectl logs를 통해 포드의 로그를 확인할 수 있습니다.

kubectl logs nasa-nginx-pod
[root@nasa-master nasa]#  kubectl logs nasa-nginx-pod
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuratio
n
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up

오브젝트는 kubectl delete -f 명령어로 삭제할 수 있습니다.

[root@nasa-master nasa]# kubectl delete -f nasa.yml 
pod "nasa-nginx-pod" deleted
[root@nasa-master nasa]# 
[root@nasa-master nasa]# kubectl get po
No resources found.

🤦‍♂️ 컨테이너 두개 이상을 포함한 pod 만들기


YAML 파일

apiVersion: v1
kind: Pod 
metadata: 
name: nasa-nginx-pod 
spec: 
containers: 
    - name: nasa-nginx-container 
    image: nginx:latest 
    ports: 
        - containerPort: 80 
          protocol: TCP 
    - name: sidecar 
    image: ubuntu:14.04 
    command: ["echo", "hello"] 
    args: ["ubuntu"]

다음과 같이 두개가 생성되었고 한개만 실행하고 있는 것을 확인할 수 있습니다.

[root@nasa-master nasa]# kubectl get po
NAME             READY   STATUS             RESTARTS   AGE
nasa-nginx-pod   1/2     CrashLoopBackOff   1          32s

-c 옵션을 사용해 어떤 컨테이너에 접속 할지 확인 가능합니다

kubectl exec -it nasa-nginx-pod -c sidecar bash
[root@nasa-master nasa]# kubectl exec -it nasa-nginx-pod -c nasa-nginx-container bash
root@nasa-nginx-pod:/# ls
bin   dev                  docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc                   lib   media  opt  root  sbin  sys  usr

Tags

#Kubernetes
NASA1515

NASA1515

Data Engineer

Hello I'M Wonseok aka NASA1515

Expertise

Public Cloud
k8s/Docker
Python

Social Media

instagramwebsitelinkedingithub

Related Posts

[Kubernetes] VSCode (VisualStudio Code)로 Kubernetes 클러스터 관리 : 초보자를 위한 완벽 가이드
[Kubernetes] VSCode (VisualStudio Code)로 Kubernetes 클러스터 관리 : 초보자를 위한 완벽 가이드
2021-08-19
2 min

Topics

CloudDevelop

Social Media