본문 바로가기
Infra/Kubernetes

[쿠버네티스 입문] 5-1. 파드

by 에드박 2023. 1. 12.

파드 개념

쿠버네티스는 파드라는 단위로 컨테이너를 묶어서 관리

보통 파드 안에 컨테이너 하나가 아닌 여러 개의 컨테이너로 구성됨

 

파드로 컨테이너 여러 개를 한꺼번에 관리할 때는 컨테이너마다 역할을 부여할 수 있음

파드 하나에 속한 컨테이너들은 모두 노드 하나 안에서 실행 (노드란?)

-> 파드의 역할 중 하나가 컨테이너들이 같은 목적으로 자원을 공유하는 것이므로 가능

 

파드 하나 안에 컨테이너들이 IP 하나를 공유함

파드에 192.168.10.10 이라는 IP 로 접근하며, 파드안 컨테이너와 통신할 때는 컨테이너마다 다르게 설정한 포트(Port)를 사용함

파드 안 여러개 컨테이너 구성 예시


파드 사용하기

# pod-sample.yaml

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    ports:
    - containerPort: 8080
  • .metadata.name : 파드 이름을 설정
  • .metadata.labels.app : 오브젝트를 식별하는 레이블을 설정. 여기서는 해당 파드가 앱 컨테이너
  • .spec.containers[].name : 컨테이너 이름을 설정
  • .spec.containers[].image : 컨테이너에서 사용할 이미지 지정
  • .spec.containers[].ports[].containerPort : 해당 컨테이너에 접속할 포트 번호를 설정

작성한 템플릿으로 Pod 생성

$ kubectl apply -f pod-sample.yaml

# 생성된 Pod 확인

$ kubectl get pods


파드 생명 주기

파드 생명주기 공식 문서 : https://kubernetes.io/ko/docs/concepts/workloads/pods/pod-lifecycle/

파드는 생성부터 삭제까지의 과정에 생명 주기가 존재

아래는 pod 의 status 목록이다.

  • Pending: 쿠버네티스 시스템에 파드를 생성하는 중인 상태
    • 컨테이너 이미지 다운로드 후, 전체 컨테이너 실행하는 중
  • Running: 파드 안 모든 컨테이너가 실행 중인 상태.
    • 1개 이상의 컨테이너가 실행 중 이거나 시작 또는 재시작 상태일 수 있습니다.
  • Succeeded: 파드 안 모든 컨테이너가 정상 실행 종료된 상태.
  • Failed: 파드 안 모든 컨테이너 중 정상적으로 실행 종료되지 않은 컨테이너가 있는 상태
    • 컨테이너 종료 코드가 0이 아니면 비정상 종료이거나 시스템이 직접 컨테이너를 종료한 것
  • Unknown: 파드의 상태를 확인할 수 없는 상태
    • 보통 파드가 있는 노드와 통신할 수 없을 때

현재 파드 생명 주기 확인

$ kubectl describe pods {파드 이름}

# 명령어 실행 후 Status 항목 확인

Conditions 항목은 파드의 현재 상태 정보를 나타냄

Conditions 의 Type 의미

  • Initialized: 모든 초기화 컨테이너가 성공적으로 시작 완료되었다는 뜻
  • Ready: 파드는 요청들을 실행할 수 있고 연결된 모든 서비스의 로드밸런싱 풀에 추가되어야 한다는 뜻
  • ContainersReady: 파드 안 모든 컨테이너가 준비 상태라는 뜻
  • PodScheduled: 파드가 하나의 노드로 스케줄을 완료했다는 뜻
  • Unscheduleable: 스케줄러가 자원의 부족이나 다른 제약 등으로 지금 당장 파드를 스케줄 할 수 없다는 뜻

Conditions 의 Status 는 

  • True: 상태 활성화
  • False: 상태 비활성화
  • Unknown: 상태 알 수 없음

kubelet 으로 컨테이너 진단하기

컨테이너 실행된 후 kubelet 이 컨테이너를 주기적으로 진단함

( kubelet 공식 문서 : https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ )

이때 Probe라는 개념이 등장하는데, kubelet 에 의해 컨테이너의 상태를 주기적 진단을 의미한다.

  • livenessProbe: 컨테이너가 실행됐는지 확인
    • livenessProbe 실패 시, 컨테이너를 종료시키고, 재시작 정책에 따라 컨테이너를 재시작함
    • 기본 상태값은 Success
  • readinessProbe: 컨테이너가 실행된 후 실제로 서비스 요청에 응답할 수 있는지 진단
    • 진단 실패 시, endpoint controller 는 해당 파드에 연결된 모든 서비스를 대상으로 엔드포인트에서 파드의 IP 정보를 제거함
    • 첫 번째 readinessProbe를 하기 전까지 기본 상태 값은 Failure
    • readinessProbe 를 지원하지 않는 컨테이너라면 기본 상태값은 Success 이다.
  • startupProbe: 컨테이너 안 애플리케이션이 시작되었는지 나타냄.
    • stageupProbe 진단이 성공할 때까지 나머지 브로브는 활성화되지 않음
    • 진단이 실패하면 kubelet이 컨테이너를 종료시키고, 컨테이너 재시작 정책에 따라 처리함
    • startupProbe 가 없는 컨테이너라면 기본 상태값은 Success 이다.

readinessProbe를 지원하는 컨테이너는 실행직후 바로 트래픽을 받지 않음.

실제 트래픽을 받을 준비가 됐음을 확인 후 트래픽을 받을 수 있음

자바 애플리케이션처럼 프로세스가 시작된 후 앱이 초기화될 때까지 시간이 걸리는 상황에 유용

 

# Probe 설정 예시

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    ports:
    - containerPort: 8080
    # readinessProbe 설정
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    # livenessProbe 설정
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

 

 

컨테이너 진단은 컨테이너가 구현한 핸들러(handler)를 kubelet이 호출해서 실행

핸들러에는 3가지가 존재

  • ExecAction: 컨테이너 안에 지정된 명령을 실행하고 종료 코드가 0일때 Success라고 진단
  • TCPSocketAction: 컨테이너 안에 지정된 IP와 포트로 TCP 상태를 확인하고 포트가 열려있으면 Success라고 진단
  • HTTPGetAction: 컨테이너 안에 지정된 IP, 포트, 경로로 HTTP GET 요청을 보냄. 응답 상태 코드가 200 ~ 400 사이면 Success 로 진단

진단 결과도 세 가지

  • Success: 컨테이너 진단에 성공
  • Failure: 컨테이너가 진단에 실패
  • Unknown: 진단 자체가 실패해서 컨테이너 상태를 알 수 없음

초기화 컨테이너

초기화 컨테이너는 앱 컨테이너가 실행되기 전 파드를 초기화하는 용도로 사용

보안상 이유로 앱 컨테이너 이미지와 같이 두면 안 되는 앱의 소스코드를 별도로 관리할 때 유용

  • 초기화 컨테이너는 여러 개 구성 가능 (여러개 라면 템플릿에 명시한 순서대로 초기화 컨테이너가 실행됨)
  • 초기화 컨테이너 실행이 실패하면 성공할 때까지 재시작함
  • 초기화 컨테이너가 모두 실행된 후 앱 컨테이너 실행이 시작됨

초기화 컨테이너의 특징을 활용하면, 파드 실행 시 앱 컨테이너가 외부의 특정 조건을 만족할 때까지 대기했다가 실행하도록 만들 수 있음

초기화 컨테이너는 이전에 소개한 Probe 는 지원하지 않음 (파드가 모두 준비되기 전에 실행한 후 종료되는 컨테이너이기 때문)

 

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  initContainers:
  - name: init-myservice
    image: arisu1000/simple-container-app:latest
    command: ['sh', '-c', 'sleep 2; echo helloworld01;']
  - name: init-mydb
    image: arisu1000/simple-container-app:latest
    command: ['sh', '-c', 'sleep 2; echo helloworld02;']
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

 

kubernetes-simple-pod 라는 파드를 생성하기 전 초기화 컨테이너로 init-service 와 init-mydb를 실행

 


파드 인프라 컨테이너

모든 파드에서 항상 실행되는 pause 라는 파드 인프라 컨테이너가 존재

 

pause 는 파드 안 기본 네트워크로 실행, 프로세스 식별자가 1(PID 1)로 설정됨.

다른 컨테이너의 부모 역할. 파드 안 다른 컨테이너는 pause 가 제공하는 네트워크를 공유해서 사용함

pause 외 다른 컨테이너가 재시작되면 파드의 IP는 유지되지만, pause 컨테이너 재시작 시 파드 안 모든 컨테이너가 재시작됨

 

kubelet 명령 옵션으로 --pod-infra-container-image 가 있는데, 이는 pause 가 아닌 다른 컨테이너를 파드 인프라 컨테이너로 지정할 때 사용함.

 


스태틱 파드

kube-apiserver를 통하지 않고, kubelet이 직접 실행하는 파드

 

kubelet 설정의 --pod-manifest-path라는 옵션에 지정한 디렉터리에 실행하려는 스태틱 파드들을 넣어두면 kubelet이 감지하여 파드로 실행함

 

kube-apiserver로 스태틱파드를 조회할 수 있지만, 스태틱 파드에 어떤 명령을 실행할 수는 없다.

 

보통 스태틱 파드는 kube-apiserver 라던가 etcd 같은 시스템 파드를 실행하는 용도로 많이 사용됨

 

아래는 도커 데스크탑의 가상머신 내부로 들어가 스태틱 파드 정보를 조회한 결과

  • etcd.yaml / kube-apiserver.yaml / kube-controller-manager.yaml / kube-scheduler.yaml 을 확인할 수 있음

 


파드에 CPU 와 메모리 자원 할당

노드 하나에 여러 개 파드를 실행하는 일이 있을 때, 노드 하나에 자원 사용량이 많은 파드가 모여있다면 파드들의 성능이 나빠질 수 있다.

 

전체 클러스터의 자원 사용 효율도 낮으므로 조정이 필요함

어떤 노드는 파드가 없어서 CPU나 메모리같은 자원이 남지만, 어떤 노드에는 파드들이 많아서 사용해야하는 자원이 부족할 수 있다.

 

쿠버네티스에는 이런 상황을 막는 여러 방법이 있다.

가장 기본적인 방법으로는 파드를 설정할 때 파드 안 각 컨테이너가 CPU나 메모리를 얼마나 사용할 수 있을지 조건을 지정하는 것

 

아래 4개 필드 값을 통해 조절 가능

  • spec.containers[].resource.limits.cpu : 최대 cpu 허용량
  • spec.containers[].resource.limits.memory : 최대 메모리 허용량
  • spec.containers[].resource.requests.cpu : 최소 cpu 할당량
  • spec.containers[].resource.requests.memory : 최대 메모리 할당량

cpu 는 CPU 코어 하나의 연산 능력 기준 단위. 1이면 코어 하나의 연산 능력  단위 ex) 1.5, 0.1, 1.1

memory 는 바이트 단위 용량 ex) 100M, 1G

# pod-resource.yaml

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    resources:
      requests:
        cpu: 0.1
        memory: 200M
      limits:
        cpu: 0.5
        memory: 1G
    ports:
    - containerPort: 8080

파드에 환경변수 설정

.spec.containers[].env[] 하위 필드를 확인

# 파드 환경변수 설정 예시

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    ports:
    - containerPort: 8080
    # 환경변수 나열
    env:
    - name: TESTENV01
      value: "testvalue01"
    - name: HOSTNAME
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP
    - name: CPU_REQUEST
      valueFrom:
        resourceFieldRef:
          containerName: kubernetes-simple-pod
          resource: requests.cpu
    - name: CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          containerName: kubernetes-simple-pod
          resource: limits.cpu

value 와 valueFrom 의 차이를 잘 보자

  • name: 사용할 환경변수의 이름을 설정
  • value: 문자열이나 숫자 형식의 값을 설정
  • valueFrom: 값을 직접 할당하는 것이 아닌 다른 곳에서 참조하는 값을 설정
  • fieldRef: 파드의 현재 설정 내용을 값으로 설정
  • fieldPath: .fieldRef 에서 어디서 값을 가져올 것인지 지정. 값을 참조하려는 항목의 위치
  • resourceFieldRef: 컨테이너에 CPU, 메모리 사용량을 얼마나 할당했는지에 관한 정보를 가져옴
    • containerName: 환경 변수 설정을 가져올 컨테이너 이름을 설정
    • resource: 어떤 자원의 정보를 가져올지 설정

 

# 파드 환경 변수 설정 내용 확인하기

$ kubectl apply -f pod-env.yaml

# pod 내부 터미널로 이동
$ kubectl exec -it kubenetes-simple-pod -- sh

# env 입력으로 환경변수 확인
~ # env

# 특정 env 검색
~ # env | grep {검색할 환경변수 이름}

 

prefix 가 KUBERNETES_ 인 환경변수들은 쿠버네티스 안에서 현재 사용중인 자원 관련 정보

 


파드 구성 패턴

파드로 여러개의 컨테이너를 묶어서 구성, 실행할 때 몇가지 패턴

  • 사이드카 패턴 : 기본 컨테이너는 원래 목적의 기능에 집중하도록 구성하고, 나머지 부가 기능들은 사이드카 컨테이너를 추가해서 사용
  • 앰배서더 패턴 : 파드 안에서 프록시 역할을 하는 컨테이너 추가하는 패턴. 파드 안에서 외부서버에 접근할 때는 프록시 컨테이너를 통하도록 구성할 수 있음
  • 어댑터 패턴 : 파드 외부로 노출되는 정보를 표준화하는 어댑터 컨테이너를 사용한다는 뜻

댓글