쿠버네티스는 어떻게 컨테이너를 실행하고 관리하는가 — Pod컨트롤러 객체와 함께 파드 실행하기애플리케이션 매니페스트에 배포 정의하기디플로이먼트와 파드의 정의(deployment.yaml)파드에서 실행중인 애플리케이션에 접근하기로컬컴퓨터와 파드 사이에 파일 주고받기파드 삭제, 디플로이먼트 삭제
쿠버네티스는 어떻게 컨테이너를 실행하고 관리하는가 — Pod
컨테이너
는 일반적으로 애플리케이션 구성 요소 하나를 실행하는 가상화된 환경을 가리킨다.
- 쿠버네티스는 이
컨테이너
를 또 다른 가상 환경인파드
로 감싼다.
파드
는 컴퓨팅의 단위로,클러스터
를 이루는노드
중 하나에서 실행된다.파드
는 쿠버네티스로 관리되는 자신만의 가상 IP 주소를 가지며 이 주소로 가상 네트워크에 접속된 다른 파드, 심지어 다른 노드에서 실행되는 파드라도 통신을 주고받을 수 있다.파드 하나
는 대개컨테이너 하나
를 포함하는데, 설정에 따라 파드 하나가 여러 개의 컨테이너를 포함할 수도 있다. (대부분의 파드는 하나의 컨테이너만 실행함. 고급 옵션을 건드리지 않았다면) → 따라서 파드를 쿠버네티스가 컨테이너를 실행하는 수단 으로 생각해도 크게 틀리지 않다.- 쿠버네티스가 직접 컨테이너를 실행하지는 않고, 컨테이너를 생성할 책임을 해당 노드에 설치된 컨테이너 런타임에 맡기는 형태임
- 파드에 포함된 모든 컨테이너는 같은 가상 환경에 포함된다. 따라서 네트워크를 공유(같은 IP 주소)하며 localhost로 서로 통신할 수도 있다.

kubectl get pods
: 현재 클러스터에 있는 모든 파드의 목록을 출력. READY 항목은 파드에서 실행 중인 컨테이너 개수와 그중 현재 준비(Ready) 상태인 컨테이너 개수를 나타낸다. hymn_fly 🐵 kubectl get pods NAME READY STATUS RESTARTS AGE hello-kiamol 1/1 Running 0 6m # get pods 계속 보기 kubectl get pods -w # kubectl pod 정보 모두 보기 kubectl get pods -A -o wide # localhost로 들어온 요청을 pod 에 포트포워딩하기 hymn_fly 🐵 ~ kubectl port-forward pod/hello-kiamol 8080:80 # pod 에 대한 상세내용 # 이때 containerId에 container 를 관리하는 컨테이너 런타임이 같이 포함되어 프린트됨 kubectl describe pod <pod-name>
파드는 쿠버네티스에서 컴퓨팅의 최소 단위다.
파드는 원시 타입 리소스이므로 일반적으로 파드를 직접 실행할 일은 없고 대개 파드를 관리할 컨트롤러 객체를 따로 만들게 됨
컨트롤러 객체와 함께 파드 실행하기
파드는 직접 사용하기에는 너무 단순한 객체다. 파드는 고립된 한 벌의 애플리케이션이며, 각 파드는 서로 다른 노드에 배정된다. 어떤 노드가 고장을 일으킨다면 파드는 유실되며, 쿠버네티스는 유실된 파드를 새 파드로 대체하지 않는다.
여러 파드를 실행하며, 고가용성을 확보하려 해도 모든 파드가 다른 노드에 흩어져서 실행된다는 보장이 없다. 억지로 서로 다른 노드에 실행되도록 사람이 직접 관리해야 한다면 오케스트레이션 도구를 사용하는 의미가 없다.
컨트롤러 객체가 바로 이런 불편함을 해결해 준다. 컨트롤러 객체는 다른 리소스를 관리하는 쿠버네티스 리소스다.
컨트롤러는 쿠버네티스 API와 연동하며 시스템의 현재 상태를 감시하다가 ‘바람직한 상태’와 차이가 생기면 필요에 따라 그 차이를 바로잡는다. 쿠버네티스에는 여러 가지
컨트롤러
객체가 있는데 그 중에서도 파드를 주로 관리하는 컨트롤러 객체는 디플로이먼트
다.어떤 노드가 고장을 일으켜
파드
가 유실되면 디플로이먼트
가 대체 파드를 다른 노드에 실행한다.디플로이먼트를 스케일링하고 싶다면 필요한 파드 수를 지정하면 된다. 그러면 디플로이먼트가 여러 노드에 걸쳐 필요한 수만큼 파드를 실행함

# 디플로이먼트 생성 kubectl create deployment hello-kiamol-2 --image=kiamol/ch02-hello-kiamol # 디플로이먼트 조회 kubectl get deploy hello-kiamol-2 NAME READY UP-TO-DATE AVAILABLE AGE hello-kiamol-2 1/1 1 1 8s kubectl get deploy hello-kiamol-2 -o jsonpath='{.spec.template.metadata.labels}' {"app":"hello-kiamol-2"} # 디플로이먼트 구성정보를 yaml 로 내보내기 kubectl get deploy <deploy-name> -o yaml > filename.yaml # 라벨중 app=hello-kiamol-2 인 pod를 모두 조회 kubectl get pods -l app=hello-kiamol-2
레이블을 이용하여 리소스 간 관계를 파악하는 것은 쿠버네티스에서 매우 자주 쓰는 중요한 패턴이다. 리소스는 생애 주기를 거치며 생성이나 수정 삭제와 함께 레이블을 부여받는다.

# 모든 파드의 이름과 라벨 확인 kubectl get pods -o custom-columns=NAME:metadata.name,LABELS:metadata.labels # 디플로이먼트가 생성한 파드의 app 레이블 수정 kubectl label pods -l app=hello-kiamol-2 --overwrite app=hello-kiamol-x # 디플로이먼트 포트포워딩 kubectl port-forward deploy/hello-kiamol-2 8080:80
디플로이먼트 입장에서는 레이블 셀렉터와 일치하는 파드가 사라졌기 때문에 새로운 파드를 만듦
이 방법은 디버깅에 유용한다, 원하는 파드를 컨트롤러 객체의 관리에서 제외하고 직접 접속해서 문제가 무엇인지 확인할 수 있기 때문임
애플리케이션 매니페스트에 배포 정의하기
매니페스트는 JSON 또는 YAML 포맷으로 작성할 수 있고 쿠버네티스 API의 정식 스크립트 포맷은 JSON 이지만, 매니페스트를 작성할 때는 가독성이 더 뛰어나고 파일 하나에 더 많은 리소스를 정의할 수 있는 YAML을 많이 쓴다.
# 매니페스트 스크립트는 쿠버네티스 api의 버전과 정의하려는 리소스의 유형을 밝히며 시작 apiVersion: v1 kind: Pod # 리소스의 메타데이터에는 이름(필수 요소)와 레이블(비필수 요소)이 있다. metadata: name: hello-kiamol-3 # 스펙은 리소스의 실제 정의 내용이다. # 파드의 경우 실행할 컨테이너를 정의해야 하고, 컨테이너는 이름과 이미지로 정의됨 spec: containers: - name: web image: kiamol/ch02-hello-kiamol
# 매니페스트 파일로 애플리케이션 배포 kubectl apply -f pod.yaml # 링크로도 애플리케이션 배포 가능 kubectl apply -f https://raw.githubusercontent.com/sixeyed/kiamol/master/ch02/pod.yaml
매니페스트 파일에 정의된 리소스 상태가 현재 클러스터에 실행중인 파드와 일치하면 더 이상 수정할 것이 없다는 로깅이 출력됨
디플로이먼트와 파드의 정의(deployment.yaml)
# 디플로이먼트는 API 버전 1에 속한다. apiVersion: apps/v1 kind: Deployment # 디플로이먼트의 이름 metadata: name: hello-kiamol-4 # 디플로이먼트가 자신의 관리 대상을 결정하는 레이블 셀렉터가 정의됨 # 여기서는 app 레이블을 사용하는데, 레이블은 임의의 키-값 쌍임 spec: selector: matchLabels: app: hello-kiamol-4 # 이 템플릿은 디플로이먼트가 파드를 만들 때 쓰인다 # 디플로이먼트 정의 속 파드의 정의에는 이름이 없다 # 그 대신 레이블 셀렉터와 일치하는 레이블을 지정해야 함 template: metadata: labels: app: hello-kiamol-4 # 파드 정의에는 컨테이너 이름과 이미지 이름 지정 spec: containers: - name: web image: kiamol/ch02-hello-kiamol
애플리케이션이 복잡해짐에 따라 복제본을 몇 개나 둘지, CPU와 메모리의 사용 상한은 어느 정도를 적용할지, 애플리케이션의 상태 체크는 어떤 방식으로 할지, 애플리케이션에서 사용할 설정값은 어디서 읽어 들이고 데이터는 어디다 저장할지 등 어떤 설정이든 YAML 파일에 추가하면 됨
파드에서 실행중인 애플리케이션에 접근하기
실제 어플리케이션은 컨테이너 속에서 동작. 컨테이너 런타임(매니지드 쿠버네티스 클러스터에서는 도커 또는 containerd에 직접 접근할 수 없음)에 따라 직접적인 컨테이너 접근을 허용하지 않을 수 있음
# 파드 내부와 연결할 대화형 쉘 실행 kubectl exec -it hello-kiamol -- sh # kubectl exec [POD] -- [COMMAND] # 쿠버네티스를 통해 컨테이너의 최근 로그를 출력 kubectl logs --tail=2 hello-kiamol # 컨트롤러 객체가 생성한 파드 이름에는 무작위 문자열이 포함되기에, 이름을 직접 참조하지 않고 # 컨트롤러 객체나 그 레이블로 파드를 참조하면 됨 kubectl logs --tail=1 deploy/hello-kiamol-4 kubectl logs --tail=1 -l app=hello-kiamol-4
로컬컴퓨터와 파드 사이에 파일 주고받기
# 파드 속에서 웹 페이지를 로컬 컴퓨터로 복사 kubectl cp hello-kiamol:/usr/share/nginx/html/index.html /tmp/kiamol/ch02/index.html
파드 삭제, 디플로이먼트 삭제
# 모든 파드 삭제 kubectl delete pods --all # 디플로이먼트 목록 확인 kubectl get deploy # 디플로이먼트 모두 삭제 kubectl delete deploy --all # 파드 목록 확인 kubectl get pods # 모든 리소스 목록 확인 kubectl get all