Infra/Kubernetes

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

에드박 2023. 1. 12. 02:52

파드 개념

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

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

 

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

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

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

 

파드 하나 안에 컨테이너들이 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_ 인 환경변수들은 쿠버네티스 안에서 현재 사용중인 자원 관련 정보

 


파드 구성 패턴

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

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