[Kubernetes] Pod

pingping·2021년 2월 13일
0

Kubernetes

목록 보기
4/10
post-thumbnail

Pod

  • 쿠버네티스 입문 책과 쿠버네티스 공식 Docs를 참고하여 정리하였습니다.
  • 개인 공부 용이므로 개념 위주로 정리하였습니다.

Concept

  • 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 단위

    ⇒ 하나 이상의 컨테이너의 그룹

  • Docker 개념 측면에서 Pod는 공유 네임스페이스와 공유 파일시스템 볼륨이 있는 Docker Container Group과 비슷하다.

개념 정리
cgroup : Control Group의 약자, 하드웨어 자원을 배분하는 기능
( CPU, RAM, .. 의 자원을 사용자가 원하는 만큼 격리된 프로세스에 할당해 줄 수 있음 )

Namespace : Process를 독립시켜주는 가상화 기술
( 독립된 프로세스는 PID, IPC, Network, UID, Mount, UTS 가 독립적으로 존재할 수 있다. )

Lifecycle

  • Pod는 생성부터 삭제까지의 과정에 생명 주기(Lifecycle)가 있다.

    • Pending : 쿠버네티스 시스템에 파드를 생성중임을 뜻한다.

    • Running : Pod 안 모든 컨테이너가 실행 중인 상태

    • Succeeded : Pod 안 모든 컨테이너가 정상 실행 종료된 상태로 재시작되지 않는다.

    • Failed : Pod 안 모든 컨테이너 중 정상적으로 실행 종료되지 않은 컨테이너가 있는 상태

      ( 컨테이너 종료 코드가 0이 아니면 비정상 종료이거나 시스템이 직접 종료한 것 )

    • Unknown : 파드의 상태를 확인할 수 없는 상태이다.


  • Pod의 생명 주기는 kubectl describe pods <<파드 이름>> 명령을 실행한 후

    Status 항목을 살펴보면 확인할 수 있다.

livenessProbe, readinessProbe

  • 컨테이너가 실행된 이후 각 Node의 Kubelet이 컨테이너를 주기적으로 진단한다. 여기서 중요한 개념이 2가지가 나온다. 바로 livenessProbe, readinessProbe이다.

livenessProbed와 readinessProbe

1) livenessProbe

: 컨테이너가 실행되었는지 확인한다. 이 진단에 실패하면 Kubelet은 컨테이너를 종료시키고, 재시작 정책에 따라서 컨테이너를 재시작한다.

( 컨테이너에 livenessProbe를 어떻게 할지 명시하지 않았다면 기본값은 Success이다. )

2) readinessProbe

: 컨테이너가 실행된 후 실제로 서비스 요청에 응답할 수 있는지를 진단한다.

이 진단에 실패하면 Endpoint controller는 해당 파드에 연결된 모든 서비스를 대상으로 엔드포인트 정보를 제거한다. 첫 번째 readinessProbe를 하기 전까지의 기본 상태 값은 Failure이다.

( readinessProbe를 지원하지 않는 컨테이너라면 기본 상태 값은 Success이다. )


  • 이런 개념 덕분에 해당 파드는 실제 트래픽을 받을 준비가 되었음을 확인한 후 트래픽을 받을 수 있으며 Java Application처럼 프로세스가 시작된 후 앱이 초기화될 때까지 시간이 걸리는 상황에 유용하다.
  • 그 뿐만 아니라 앱을 실행할 때 대용량 데이터를 불러와야 하거나, 컨테이너 실행은 시작됐지만 앱의 환경 설정 실수로 앱이 실행되지 않는 상황 등에 대비할 수 있다.

3) Handler

  • 컨테이너 진단은 컨테이너가 구현한 핸들러를 Kubelet이 호출하여 실행한다. 총 3가지가 있음

    • ExecAction

      : 컨테이너 안에 지정된 명령을 실행하고 종료 코드가 0일때 Success라고 진단한다.

    • TCPSocketAction

      : 컨테이너 안에 지정된 IP와 포트로 TCP 상태를 확인하고 포트가 열려있으면 Success라고 진단한다.

    • HTTPGetAction

      : 컨테이너 안에 지정된 IP, Port, 경로로 HTTP Get 요청을 보낸다.

      ( 응답 상태 코드가 200 ~ 400 사이면 Success라고 진단한다. )

Init Container

  • Init Container ?

    : App Container가 실행되기 전 Pod를 초기화한다. 보안상 이유로 App Container 이미지와 같이 두면 안되는 App의 소스 코드를 별도로 관리할 때 유용하다.

특징

  • 여러 개를 구성할 수 있으며 여러 개 있다면 YAML 파드 템플릿에 명시된 순서대로 초기화 컨테이너가 실행된다.

  • 초기화 컨테이너 실행이 실패한다면 성공할 때까지 재시작한다.

    ⇒ 선언적(Declarative) 특징에서 벗어날 수 있으며 필요한 명령들을 순서대로 실행하는 데 이용할 수 있다.

  • 초기화 컨테이너가 모두 실행된 후 App Container가 실행된다.

  • readinessProbe를 지원하지 않는다.


초기화 컨테이너 예시

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:
      image: arisu1000/simple-container-app:latest
      command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  • 리소스 생성
    • Init Container가 생성된 이후 contaier가 생성되는 것을 확인할 수 있다.
    • pod는 instance-5 ( 2번째 worker node )에 떠있음
root@instance-1:~/kubernetes-sample/pod# kubectl get pods -w
NAME                    READY   STATUS     RESTARTS   AGE
kubernetes-simple-pod   0/1     Init:1/2   0          10s
kubernetes-simple-pod   0/1     PodInitializing   0          11s
kubernetes-simple-pod   1/1     Running           0          12s

# kubectl describe pods kubernetes-simple-pod
..
..
Init Containers:
  init-myservice:
    Container ID:  docker://f106ff7109d2118802f8d60e728748b6b5a131495dfc58a79a642a39972ed856
..
..
init-mydb:
    Container ID:  docker://4fed60d740bcb412a8a51f97b76cdf9df30b90951bbb48bf6e37d7f143eb224f
    Image:         arisu1000/simple-container-app:latest
..
..
Containers:
  kubernetes-simple-pod:
    Container ID:  docker://c6c6f449a0077fc3719e836573e0452700ab8719c0d6d1acc53aec923569dcf6
    Image:         arisu1000/simple-container-app:latest
..
..
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  47s   default-scheduler  Successfully assigned default/kubernetes-simple-pod to instance-5
  Normal  Pulling    46s   kubelet            Pulling image "arisu1000/simple-container-app:latest"
  Normal  Pulled     43s   kubelet            Successfully pulled image "arisu1000/simple-container-app:latest" in 2.6273271s
  Normal  Created    43s   kubelet            Created container init-myservice
  Normal  Started    43s   kubelet            Started container init-myservice
  Normal  Pulling    40s   kubelet            Pulling image "arisu1000/simple-container-app:latest"
  Normal  Pulled     39s   kubelet            Successfully pulled image "arisu1000/simple-container-app:latest" in 349.05471ms
  Normal  Created    39s   kubelet            Created container init-mydb
  Normal  Started    39s   kubelet            Started container init-mydb
  Normal  Pulling    37s   kubelet            Pulling image "arisu1000/simple-container-app:latest"
  Normal  Pulled     36s   kubelet            Successfully pulled image "arisu1000/simple-container-app:latest" in 266.076585ms
  Normal  Created    36s   kubelet            Created container kubernetes-simple-pod
  Normal  Started    36s   kubelet            Started container kubernetes-simple-pod

Pod Infra Container

  • Pod infra Container

    Kubernetes에는 모든 Pod에서 항상 실행되는 Pause라는 컨테이너가 있다.

  • pause는 파드 안 기본 네트워크로 실행되며, PID가 1로 설정되므로 다른 컨테이너의 부모 컨테이너 역할을 한다. 파드 안 다른 컨테이너는 pause 컨테이너가 제공하는 네트워크를 공유하여 사용한다. 그래서 파드 안 다른 컨테이너가 재시작되었을 때는 파드의 IP를 유지하지만, pause 컨테이너가 재시작되면 파드 안 모든 컨테이너도 재시작한다.

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

  • 관련되는 개념 : namespace, cgroups, PID, Zombie process, fork, exec, systemcall

Static Pod

  • Static Pod

    : kube-apiserver를 통하지 않고 해당 Node의 Kubelet이 직접 실행하는 Pod

  • kubelet 설정의 - -pod-manifest-path라는 옵션에 지정한 디렉터리에 스태틱 파드를 실행하려는 YAML 템플릿 파일을 넣어두면 Kubelet이 그것을 감지하여 Pod로 실행한다.

  • 보통 Static Pod는 Kube-apiserver 혹은 etcd 같은 시스템 파드를 실행하는 용도로 많이 사용한다. 쿠버네티스에서 Pod를 실행하려면 kube-apiserver가 필요한데 kube-apiserver 자체를 처음 실행하는 별도의 수단으로 스태틱 파드를 이용하는 것이다.

Pod에 CPU, Memory 할당

  • Pod에 CPU나 Memory 설정을 해주지 않는다면 어떤 Node에는 CPU나 Memory 자원이 남고 어떤 Node에는 부족한 현상이 발생할 수 있다.
  • 이러한 현상을 방지하는 방법 중 가장 기초적인 방법이 CPU와 Memory의 Request, Limit을 지정해주는 것이다.
  • 4개의 필드
    • .sepc.containers[].resources.limits.cpu
    • .sepc.containers[].resources.limits.memory
    • .sepc.containers[].resources.requests.cpu
    • .sepc.containers[].resources.requests.memory
containers:
..
..
	resources:
	      requests:
	        cpu: 0.1
	        memory: 200M
	      limits:
	        cpu: 0.5
	        memory: 1G
  • CPU

    0.1로 설정 시 연산량을 100이라고 가정했을 때 최소 10%는 확보해놓고 있겠다는 뜻

    0.5 : 최대 50% 사용하겠다는 것을 명시

  • Memory

    최소 200M의 메모리 공간을 미리 확보

    최대 1G의 메모리 공간을 사용

Pod에 Environment Value 설정

containers:
..
..
	env:
		#### 1
		#### 가장 기초적인 방법으로 직접 name과 value를 지정해줄 수 있다.
	    - name: TESTENV01
	      value: "testvalue01"
		#### 2
		#### valueFrom : 어딘가로부터 key, value를 참조하겠음을 의미
		#### fieldRef : 파드의 현재 설정 내용을 값으로 설정하겠다는 뜻
		#### fieldPath : 값을 참조하려는 항목의 위치를 지정해준다.
	    - name: HOSTNAME
	      valueFrom:
	        fieldRef:
	          fieldPath: spec.nodeName
		#### 3
	    - name: POD_NAME
	      valueFrom:
	        fieldRef:
	          fieldPath: metadata.name
		#### 4
	    - name: POD_IP
	      valueFrom:
	        fieldRef:
	          fieldPath: status.podIP
		#### 5
		#### 컨테이너에 CPU, Memory 사용량을 얼마나 할당했는지에 관한 정보이다.
	    - name: CPU_REQUEST
	      valueFrom:
	        resourceFieldRef:
	          containerName: kubernetes-simple-pod
	          resource: requests.cpu
		#### 6
	    - name: CPU_LIMIT
	      valueFrom:
	        resourceFieldRef:
	          containerName: kubernetes-simple-pod
	          resource: limits.cpu
  • 확인

    제대로 환경 변수가 설정되었는지 확인하기 위해 kubectl exec 명령어로 직접 컨테이너 내부로 접속하여 확인하였다.

root@instance-1:~/kubernetes-sample/pod# kubectl exec -it kubernetes-simple-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
~ # 
~ # env
POD_IP=10.233.118.7
KUBERNETES_PORT=tcp://10.233.0.1:443
KUBERNETES_SERVICE_PORT=443
CPU_REQUEST=0
HOSTNAME=instance-5
TESTENV01=testvalue01
SHLVL=1
HOME=/root
TERM=xterm
POD_NAME=kubernetes-simple-pod
KUBERNETES_PORT_443_TCP_ADDR=10.233.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
CPU_LIMIT=2
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.233.0.1:443
KUBERNETES_SERVICE_HOST=10.233.0.1
PWD=/root

## kubectl describe pods <<POD_NAME>> 으로도 확인할 수 있다.
..
..
Environment:
      TESTENV01:    testvalue01
      HOSTNAME:      (v1:spec.nodeName)
      POD_NAME:     kubernetes-simple-pod (v1:metadata.name)
      POD_IP:        (v1:status.podIP)
      CPU_REQUEST:  0 (requests.cpu)
      CPU_LIMIT:    node allocatable (limits.cpu)
..
..
profile
Cloud Infra Engineer & interested in python, IaC, k8s

0개의 댓글