( 참고 : [교재] 핵심만 콕! 쿠버네티스 )

쿠버네티스 Pod


1. Pod 소개

Pod = 쿠버네티스의 최소 실행단위

( Pod를 통해 기본 가상환경을 제공함 )


가상환경 플랫폼 실행 단위

  • 가상머신 : Instance
  • 도커 : Container
  • 쿠버네티스 : Pod


Pod의 특징

[1] 1개 이상의 container 실행

  • 상황에 따라 2~3개의 컨테이너를 실행


[2] 동일 Node에 할당

  • Pod 내에 실행되는 container들은, 반드시 동일한 node에 할당되며, 동일한 생명 주기를 가진다
  • Pod가 삭제되면, Pod 내의 모든 container들이 삭제됨


[3] 고유의 Pod IP

  • Pod 리소스는 cluster내에서 접근가능한 고유의 IP를 가진다
  • NAT 통신 없이도, Pod의 고유 IP를 통해 접근 가능


[4] IP 공유

  • Pod내에 있는 “container들은 서로 IP를 공유”

    ( 따라서, 포트를 이용하여 구분함)


[5] Volume 공유

  • Pod내에 있는 컨테이너들은, 동일한 Volume과 연결이 가능


구조 도식화

Node (192.168.0.6)

  • Pod 1 (10.10.0.4)
    • Container 1-1
    • Container 1-2
  • Pod 2 (10.10.0.5)
    • Container 2-1
    • Container 2-2


YAML

  • 쿠버네티스의 모든 리소스는 YAML 형태의 “선언형 명령 정의서”로 표현 가능
  • ex) Pod의 YAML 정의서 파일 만들기 ( mynginx.yaml )
    • --dry-run & -o yaml을 조합하면, Pod를 실제로 생성하지 않고도 템플릿 파일 생성 가능
kubectl run mynginx --image nginx --dry-run=client -o yaml > mynginx.yaml


이렇게 해서 생성된 mynginx.yaml :

# mynginx.yaml
apiVersion : v1
kind : Pod
metadata :
	labels :
	   run : mynginx
	name : mynbinx
spec :
	containers :
	- image : nginx
	  name : mynginx
	restartPolicy : Never


Pod를 구성하기 위한 최소 property

  • apiVersion : 리소스 동일 이름 충돌 피하기 위한 목적 ( 리소스의 scope를 정의 )
    • ex) V1
  • kind : 리소스 타입
    • ex) Pod
  • metadata : 리소스의 meta 정보
    • labels : 리소스의 label 정보
    • name : 리소스의 name 정보
  • spec : 리소스의 스펙 정보
    • containers : 1개 이상의 container 정의
      • name : container의 이름
      • image : container의 이미지 주소


위에서 생성된 YAML파일를 사용하여, Pod를 생성하기

kubectl apply -f mynginx.yaml

생성 순서

  • step 1) 사용자가 kubectl 명령어를 통해, Pod 정의를 Master에 전달

  • step 2) Master는 YAML 정의의 유효성을 체크 &

    특정 노드에 (사용자의 요청에 따라) container를 실행하도록 명령 내림

  • step 3) 명령 받은 node는 (요청사항에 따라) 컨테이너를 node에 실행


2. 라벨링 시스템

라벨 = 단순히 key,value 형태의 문자열

라벨링 시스템의 목적 :

  • 특정 리소스를 참조하기 위해!

  • Pod에 트래픽을 전달하기 위해


Pod에 라벨을 부여한다

= (key,value) 형태의 문자열을 Pod의 meta data property에 추가한다


(1) 라벨 정보 부여

방법 1) kubectl label

kubectl label pod <NAME> <KEY>=<VALUE>


example )

  • mynginx 이름의 pod에 hello(key) = world(value) 라벨을 추가
kubectl label pod mynginx hello=world


방법 2) 선언형 명령

  • 애초에 YAML 정의서를 작성할 때, metadata property에 “직접 라벨 추가”


(2) 라벨 정보 확인

Pod에 부여된 라벨을 확인하기 위해, -L 옵션 사용

example) run이라는 key에 대한 value를 확인하려면?

kubectl get pod mynginx -L run


특정 라벨이 아닌, 전체 라벨을 확인하려면, --show-labels 옵션 사용

kubectl get pod mynginx --show-labels


(3) 라벨을 이용한 조건 필터링

특정한 라벨을 가진 Pod만 확인하려면, -l 옵션 사용


example) key가 run인 Pod 출력

kubectl get pod -l run


example) key가 run & value가 mynginx인 Pod 출력

kubectl get pod -l run=mynginx


(4) nodeSelector를 이용한 노드 선택

  • Pod가 특정 Node에 할당되도록 스케줄링
  • (default) Master가 알아서 어떤 Node에서 실행할지 스스로 판단하여 스케줄링
  • (명시적) nodeSelector 통해서, Node 선택 가능


node들에게 달린 라벨 확인하기

kubectl get node --show-labels


라벨 추가하기 ( disktype )

  • Master 노드에 disktype=ssd 라벨을 부여
  • Worker 노드에 disktype=hdd 라벨을 부여

( pod와 마찬가지로, 동일하게 label 명령어 사용하면 됨 )

kubectl label node master disktype=ssd
kubectl label node worker disktype=hdd


노드의 라벨 확인하기

  • 필터 : disktype 라벨을 가진 노드의 라벨 정보만
kubectl get node --show-labels | grep distkype


실행하고자 하는 Pod의 YAML 정의서에, nodeSelector property 추가하기

example) node-selector.yaml

apiVersion :v1
kind : Pod
...
..
spec :
	...
	
	nodeSelector :
		disktype : ssd

그런 뒤, 해당 YAML 파일을 선언하여 Pod 생성

kubectl apply -f node-selector.yaml


방금 생성한 Pod가 어느 node에서 생성되는지 확인

( 잘 되었다면, 우리가 지정한 Master node에서 생성되어야 함! )

kubectl get pod node-selector -o wide


노드 그룹

만약 2개 이상의 node에 동일한 라벨이 붙어있는 경우?

\(\rightarrow\) 노드의 상태에 따라 자동으로 “최적의 node”를 선택하여 할당함


3. 실행 명령 & 파라미터 지정

Pod 생성 시,실행 명령 &파라미터를 전달할 수 있음

ex) cmd.yaml

apiVersion : v1
...
spec :
	restartPolicy : OnFailure
	containers :
	- name : nginx
	  image : nginx
	  command : ["/bin/echo"]
	  args : ["hello"]
  • command : 컨테이너의 시작 실행 명령

    ( = 도커의 ENTRYPOINT )

  • args : 실행 명령에 넘겨줄 parameter

    ( = 도커의 CMD )

  • restartPolicy : Pod의 재시작 정책

    • Always : Pod 종료 시, 항상 재시작 시도 ( default )
    • Never : 재시작 시도 X
    • OnFailure : 실패 시에만!


이대로 실행하기~

kubectl apply -f cmd.yaml


4. 환경 변수 설정

Pod에 환경변수를 전달(설정)하는 방법

\(\rightarrow\) env property 활용하기


ex) env.yaml

# env.yaml
apiVersion : v1
...
spec :
	containers :
	- name : nginx
	  image : nginx
	  env :
	  - name : hello
	    value : "world!"
  • env 환경변수를 설정하는 property를 선언함
    • name : 환경변수의 key
    • value : 환경변수의 value


위와 같은 환경변수를 가진 pod를 생성함

kubectl apply -f env.yaml


pod 생성 이후, exec 명령으로 env Pod에 printenv 명령 전달

  • example) hello라는 key를 가진 환경변수 출력하기!
kubectl exec env -- printenv | grep hello


5. 볼륨 연결

Pod 내부 스토리지의 생명 주기 = Pod와 동일

( \(\therefore\) Pod 삭제 시, 저장된 데이터도 함께 삭제 )


따라서, 지속적으로 저장하고 싶다면, 볼륨을 따로 연결해야 함

  • 여러 형태의 volume 존재

  • 가장 기본이 되는 것은 “host Volume”

    ( 도커 -v 옵션과 유사하게, host 서버의 볼륨공간에 pod가 데이터를 저장 )


# volume.yaml
apiVersion : v1
..
spec :
	containers :
	- name :
	  ...
	  volumeMounts:
	  - mountPath : /container-volume
	    name : my-volume
	    
	volumes :
	- name : my-volume
	  hostPath :
	     path : /home
  • volumeMounts : 컨테이너 내부에 사용될 볼륨 선언
  • volumes : Pod에서 사용할 volume 지정


위와 같이 volume이 연결된 pod를 실행하기

kubectl apply -f volume.yaml


volume 확인하기

\(\rightarrow\) 호스트 서버의 /home 디렉터리와 동일함을 확인함

kubectl exec volume --ls /container-volume
# ubuntu
ls /home
# ubuntu


6. 리소스 관리

여기서 말하는 리소스는..

  • 쿠버네티스의 리소스 (X)
  • 컴퓨팅 자원관리 (O)


container 실행에 필요한 리소스를 제약할 수 있음

( resources라는 property를 활용하여 )

  • 최소 resource : requests
  • 최대 resource : limits property


(1) requests : 최소 사용량

pod가 보장받을 수 있는 “최소 사용량”


ex) requests.yaml

# requests.yaml
apiVersion : v1
...
spec :
	containers :
	- name : nginx
	  image : nginx
	  resources :
	  	requests :
	  	  cpu : "250m"
	  	  memory : "500Mi"


(2) limits : 최대 사용량

pod가 사용할 수 있는 “최대 사용량”


ex) limits.yaml

# limits.yaml
apiVersion : v1
...
spec :
	containers :
	- name : nginx
	  image : nginx
	  resources :
	  	limits :
	  	  cpu : "500m"
	  	  memory : "1Gi"


최대 리소스 사용량을 넘어가면…

  • CPU : throttling
  • 메모리 : Out of Memory


무한 메모리 리소스를 반복하도록 하는 python script를 실행한 뒤 지켜보자

kubectl apply -f limits.yaml

watch kubectl get pod


7. 상태 확인

Pod가 정상적으로 동작하고 있는지 확인 ( health check )


(1) livenessProbe

컨테이너가 잘 살아있는지 확인

( + 자가치유를 위한 판단 기준으로 사용 )


ex) liveness.yaml

# liveness.yaml
apiVersion : v1
...
spec :
	containers :
	- name : nginx
	  image : nginx
	  livenessProbe :
	  	httpGet :
	  		path: /live
	  		port: 80

해석 :

  • Pod의 상태를 확인하기 위해, HTTP 프로토콜의 GET method를 사용하여,

    /live 위치의 80포트를 지속적으로 호출

  • 리턴값이

    • 200~300번대이면 : 정상

    • 그 외 : 비정상

      \(\rightarrow\) 종료 & 재시작


실행 후 확인하기

kubectl apply -f liveness.yaml

watch kubectl get pod liveness
# NAME READY STATUS RESTARTS AGE
# ...
  • 계속해서 지켜 보면, RESTARTS값이 계속 증가하는 것을 확인할 수 있음

    ( 이유 : /live 호출에서 404error을 받기 때문에, Pod가 강제로 재시작(자가치유) 되고 있으므로 )


(2) readinessProbe

Pod가 생성 직후, 트래픽을 받을 준비가 되었는지 확인


ex) readiness.yaml

# readiness.yaml
apiVersion : v1
...
spec :
	containers :
	- name : nginx
	  image : nginx
	  readinessProbe :
	  	httpGet :
	  		path: /ready
	  		port: 80


실행 후 확인하기

kubectl apply -f liveness.yaml

kubectl get pod
# NAME READY STATUS RESTARTS AGE
# ...  0/1

# /ready URL 생성
kubectl exec readiness --touch /usr/share/nginx/html/ready

kubectl get pod
# NAME READY STATUS RESTARTS AGE
# ...  1/1
  • READY 칼럼의 0/1 표시를 통해 확인 가능
    • 0/1 : 준비 X
    • 1/1 : 준비 O


(3) livenessProbe & readinessProbe

위 둘 다, HTTP 통신뿐만 아니라, 명령 실행을 통해서도 잘 작동하는지 확인 가능


ex) readiness-cmd.yaml

# readiness-cmd.yaml
apiVersion : v1
...
spec :
	containers :
	- name : nginx
	  image : nginx
	  readinessProbe :
	  	exec :
	  		command :
	  		- cat
	  		- /tmp/ready
  • exec : 아래의 명령 실행
    • command : 사용자가 실행할 명령 지정


실행 후 확인하기

kubectl apply -f readiness-cmd.yaml

kubectl get pod
# NAME READY STATUS RESTARTS AGE
# ...  0/1

# /tmp/ready 파일 생성
kubectl exec readiness-cmd --touch /tmp/ready

kubectl get pod
# NAME READY STATUS RESTARTS AGE
# ...  1/1
  • READY 칼럼의 0/1 표시를 통해 확인 가능
    • 0/1 : 준비 X
    • 1/1 : 준비 O


8. 2개 컨테이너 실행

Pod = 1개 이상의 컨테이너를 가질 수 있는 최소 실행 단위

\(\rightarrow\) 이번에는, 2개의 서로 다른 컨테이너를 실행해볼 것


ex) second.yaml

# second.yaml
apiVersion : v1
kind : Pod
metadata :
	name : second
spec :
	containers :
	- name : nginx
	  image : nginx
	- name : curl
	  image : curlimages/curl
	  command : ["/bin/sh"]
	  args : ["-c", "while true; do sleep 5; curl localhost; done"]
  • 1번째 container : NGINX 웹서버
  • 2번째 container : 쉘 스크립트를 실행하는 컨테이너
    • 역할 : loop를 돌면서, 5초 간 대기 후 local host로 호출


실행 후 확인하기

kubctl apply -f second.yaml

kubectl logs second

\(\rightarrow\) log 확인하려 할 때, 에러 발생

( \(\because\) 2개 이상의 container이므로, “명시적으로 지정” 해줘야 )

kubectl logs second -c nginx


9. 초기화 컨테이너

container끼리는 실행 순서 보장 X

but, 명시적으로 지정해서 초기화 작업을 수행해야하는 경우에는?

\(\rightarrow\) initContainers property를 이용


# init-container.yaml
apiVersion : v1
kind : Pod
metadata :
	name : init-container
spec :
	restartPolicy : OnFailure
	
	containers :
	- name : busybox
	  image : k8s.gcr.io/busybox
	  command : ["ls"]
	  args : ["/tmp/moby"]
	  volumeMounts:
	  - name : workdir
	    mountPath : /tmp
	    
	initContainers :
	- name : git
	  image : alpine/git
	  command : ["sh"]
	  args :
	  - "-c"
	  - "git clone https://github.com/moby/moby.git /tmp/moby"
	  volumeMounts :
	  - name : workdir
	    mountPath : "/tmp"
	
	volumes :
	- name : workdir
	  emptyDir : {}

ex) main container 실행 전에, 먼저 git repository에서 받아야 한다면?

  • 초기화 container에서 미리 git pull을 받아서, container 끼리의 공유 공간인 “emptyDir” volume을 통해 gir repository 전달


실행 후 확인하기

kubctl apply -f init-container.yaml

kubectl get pod

# 1) initContainer의 log 확인
kubectl logs init-container -c git -f

# 2) main Container(=busybox)의 log 확인
kubectl logs init-container

\(\rightarrow\) log 확인하려 할 때, 에러 발생

( \(\because\) 2개 이상의 container이므로, “명


10. Config 설정

설정값들을 따로 모아두고, 필요할 떄 꺼내 쓰자!

\(\rightarrow\) 설정값들 모아놓은 통 = ConfigMap


ConfigMap에서 설정값들을 불러와서 Pod에 전달하자!


(1) ConfigMap 리소스 생성

ConfigMap 리소스

  • 메타데이터(설정값)을 저장하는 리소스

    ( 지금까지는 Pod에서 “직접” 설정값들을 지정했었음 )


ConfigMap 생성하기

kubectl create configmap <key> <data-source>


방법 1 : --from-file

  • (1) 설정파일 작성하기

    # game.properties
    weapon = gun
    health = 3
    potion = 5
    
  • (2) ConfigMap 만들기

    ( ConfigMap의 이름은 “game-config”로 지정 )

    kubectl create configmap game-config --from-file=game.properties
    
  • (3) 생성된 ConfigMap (cm) 조회하기

    kubectl get cm game-config -o yaml
    kubectl get configmaps game-config -o yaml
    


방법 2 : --from-literal

--from-literal을 사용해서도 Configmap 생성 가능

( --from-file과는 다르게, 파일 사용 없이 직접! )

kubectl create configmap special-config\
			--from--literal=special.power=10
			--from--literal=special.strength=20


방법 3 : YAML 정의서

직접 ConfigMap 리소스를 YAML 정의서로 작성하여 생성 가능


# monster-config.yaml
apiVersion : v1
kind : ConfigMap
metadata :
	name : monster-config
	namespace : default
data :
	monsterType : fire
	monsterNum : "5"
	monsterLife : "3"


실행 후 확인하기

kubctl apply -f monster-config.yaml

kubectl get cm monster-config -o yaml


(2) ConfigMap 활용

1) 볼륨 연결

ConfigMap을 볼륨으로 mount하여 파일처럼 사용 가능


ex) game-volume.yaml

# game-volume.yaml
apiVersion : v1
kind : Pod
metadata :
	name : game-volume
spec :
	restartPolicy : OnFailure
	containers :
	...
	volumes :
	- name : game-volume
	  configMap :
	    name : game-config
  • volumes : Pod에서 사용할 볼륨 선언
    • configMap :
      • (기존) hostPath, emptyDir
      • (신규) configMap라는 볼륨 사용 가능


실행 후 확인하기

kubctl apply -f game-volume.yaml

kubectl logs game-volume


2) 환경변수 - valueFrom

  • 생략


3) 환경변수 - envFrom

  • 생략