해당 포스팅은 "쿠버네티스 인 액션"을 공부하고 정리한 글입니다. 모든 내용은 해당 도서를 기준으로 합니다.
⬛ 3장 파드 쿠버네티스에서 컨테이너 실행
◾ 3.1 파드 소개
파드는 함께 배치된 컨테이너 그룹으로 쿠버네티스가 컨테이너를 가진 파드를 배포하고 운영함.
일반적으로 파드는 하나의 컨테이너만 포함하지만 파드가 여러 컨테이너를 가지고 있을 때 모든 컨테이너는 항상 하나의 워커 노드에서 실행됨.
▪️ 3.1.1 파드가 필요한 이유
컨테이너는 단일 프로세스를 실행하는 것을 목적으로 설계함.
그렇지 않으면 모든 프로세스를 실행하고 로그를 관리하는 건 모두 사용자 책임이다. 또, 어떤 프로세스가 남긴 로그인지 파악이 힘들기 때문에 각 프로세스를 자체의 개별 컨테이너로 실행해야 함.
여러 프로세스를 단일 컨테이너로 묶지 않기 때문에 컨테이너를 함께 묶고 하나의 단위로 관리할 수 있는 또 다른 상위 구조가 필요하게 되는데 이게 파드가 필요한 이유임.
▪️ 3.1.2. 파드 이해하기
pod를 사용하면
- 밀접하게 연관된 프로세스를 함께 실행하고 단일 컨테이너 안에서 모두 함께 실행되는 것처럼 동일한 환경을 제공할 수 있으며 이들을 격리된 상태로 유지할 수 있음.
같은 파드에서 컨테이너 간 부분 격리
- 쿠버네티스는 파드 안에 있는 모든 컨테이너가 자체 네임스페이스가 아닌 동일한 리눅스 네임스페이스를 공유하도록 도커를 설정함.
- 모든 컨테이너는 같은 호스트 이름과 네트워크 인터페이스를 공유함.
- 하지만 파일시스템에 한해서는 좀 다름.
- 컨테이너 파일 시스템은 컨테이너 이미지에서 나오기 때문에 파일시스템은 다른 컨테이너와 완전히 분리됨.
컨테이너가 동일한 IP와 포트 공간을 공유하는 방법
파드 안의 컨테이너가 동일한 네트워크 네임스페이스에서 실행되기 때문에 동일한 IP 주소와 포트 공간을 공유함.
- 이는 동일한 파드 안 컨테이너에서 실행 중인 프로세스가 같은 포트 번호를 사용하지 않도록 주의해야 함. (동일 파드일 때만 해당)
파드 간 플랫 네트워크 소개
- 클러스터의 모든 파드는 하나의 플랫한 공유 네트워크 주소 공간에 상주함.
- 모든 파드는 다른 파드의 IP 주소를 사용해 접근하는 것이 가능함.
- 둘 사이에는 어떠한 NAT(Network Address Translation)가 존재하지 않음.
- 파드는 논리적인 호스트로서 컨테이너가 아닌 환경에서의 물리적 호스트 혹슨 VM과 매우 유사하게 동작함.
◼️ 3.1.3 파드에서 컨테이너의 적절한 구성
파드는 특정한 애플리케이션만을 호스팅 함.
모든 것을 파드 하나에 넣는 대신 애플리케이션을 여러 파드로 구성하고 각 파드에는 밀접하게 관련 있는 구성 요소나 프로세스만 포함해야 함.
스케일링
- 파드는 스케일링의 기본 단위임.
- 쿠버네티스는 개별 컨테이너를 수평으로 확장할 수 없음. 대신 전체 파드를 수평으로 확장함.
- 컨테이너를 개별적으로 스케일링 하는 것이 필요하다면 별도 파드에 배포 해야 함.
파드에서 여러 컨테이너를 사용하는 경우
- 애플리케이션이 하나의 주요 프로세스와 하나 이상의 보완 프로세스로 구성된 경우.
- 추가 컨테이너는 사이드카 컨테이너라고 부름.
- 컨테이너를 함께 실행해야 하는지, 혹은 서로 다른 호스트에서 실행할 수 있는지?
- 여러 컨테이너가 모여 하나의 구성 요소를 나타내는지? 혹은 개별적인 구성 요소인지?
- 컨테이너가 함께, 혹은 개별적으로 스케일링 돼야 하는지?
◼️ 3.2 YAML 또는 JSON 디스크립터로 파드 생성
쿠버네티스 리소스는 일반적으로 쿠버네티스 REST API 앤드포인트에 JSON 혹은 YAML 매니페스트를 전송해 생성함.
YAML 파일에 모든 쿠버네티스 오브젝트를 정의하면 버전 관리 시스템에 넣는 것이 가능해져 그에 따른 모든 이점을 누릴 수 있음.
▪️ 3.2.1 기존 파드의 YAML 디스크립터 살펴보기
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox:1.28
ports:
- containerPort: 8080
protocl: TCP
command: ['sh', '-c', 'echo "The app is running!" && tail -f /dev/null']
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log_level.conf
- metadata : 이름, 네임스페이스, 레이블 및 파드에 관한 기타 정보 포함.
- spec : 파드 컨테이너, 볼륨, 기타 데이터 등 파드 자체에 관한 실제 명세 가짐.
- status : 파드 상태, 각 컨테이너 설명과 상태, 파드 내부 IP, 기타 현재 기본 정보 포함.
- port : 컨테이너가 0.0.0.0 주소에 열어 둔 포트를 통해 접속을 허용할 경우 파드 스펙에 포트를 명시적으로 나열하지 않아도 다른 파드에서 항상 해당 파드에 접속할 수 있음.
- 클러스터를 사용하는 모든 사람이 파드에서 노출한 포트를 빠르게 볼 수 있음.
- 포트에 이름을 지정해 편리하게 사용할 수 있음.
- → 포트를 명시적으로 정의하면
- 클러스터를 사용하는 모든 사람이 파드에서 노출한 포트를 빠르게 볼 수 있음.
- 포트에 이름을 지정해 편리하게 사용할 수 있음.
▪️ 3.2.3 kubectl create 명령으로 파드 만들기
kubectl create
kubectl create -f pod_name.yaml
실행 중인 파드의 전체 정의 가져오기
kubectl get pod pod_name -o yaml
kubectl get pod pod_name -o json
▪️ 3.2.4 애플리케이션 로그 보기
컨테이너화 된 애플리케이션은 로그를 파일에 쓰기보다는 표준 출력과 표준 에러에 로그를 남기는 게 일반적임.
- 컨타이너 런타임은 이러한 스트림을 파일로 전달.
- 다음 명령을 이용해 컨테이너 로그를 가져옴.
kubectl logs pod_name
▪️ 3.2.5 파드에 요청 보내기
포트 포워딩
- 파드에 테스트와 디버깅 목적으로 연결할 수 있는 다른 방법
kubectl port-forward pod_name 8888:8080
→ 다른 터미널에서 curl을 이용해 localhost:8888에서 실행되고 있는 kubectl port-forward 프록시를 통해 HTTP 요청을 해당 파드에 보낼 수 있음.
- 포드 포워딩을 사용해 개별 파드를 효과적으로 테스트할 수 있음.
◼️ 3.3 레이블을 이용한 파드 구성
파드 수가 증가함에 따라 파드를 부분 집합으로 분류할 필요가 있음.
레이블
- 파드와 기타 다른 쿠버네티스 오브젝트의 조직화가 이뤄짐.
- 파드와 모든 다른 쿠버네티스 리소스를 조직화할 수 있는 단순하면서 강력한 쿠버네티스 기능.
- 레이블 셀렉터를 사용해 리소스를 선택할 때 활용됨.
- app : 파드가 속한 애플리케이션. 구송 요소 혹은 마이크로서비스를 지정
- rel : 파드에서 실행 중인 애플리케이션이 안전, 베타 혹은 카나리 릴리스인지 보여줌.
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels:
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
기존 파드 레이블 수정
kubectl label pod pod_name app=nginx --overwrite
◼️ 3.4 레이블 셀렉터를 이용한 파드 부분 집합 나열
레이블 셀렉터
- 특정 레이블로 태그 된 파드의 부분 집합을 선택해 원하는 작업을 수행함.
- 특정 값과 레이블을 갖는지 여부에 따라 리소스를 필터링하는 기준이 됨.
- 리소스 선택 기준
- 특정한 키를 포함하거나 포함하지 않는 레이블
- 특정한 키와 값을 가진 레이블
- 특정한 키를 갖고 있지만 다른 값을 가진 레이블
레이블 셀렉터를 사용해 파드 나열
kubectl get pod -l app=nginx
◼️ 3.5 레이블과 셀렉터를 이용해 파드 스케줄링 제한
쿠버네티스는 모든 노드를 하나의 대규모 배포 플랫폼으로 노출하기 때문에 파드가 어느 노드에 스케줄링 됐느냐는 중요하지 않음.
- 각 파드는 요청한 만큼 정확한 컴퓨팅 리소스를 할당 받음.
- 다른 파드에서 해당 파드로 접근하는 것은 파드가 스케줄링 된 노드에 아무런 영향을 받지 않음.
- 쿠버네티스에게 파드를 어디에 스케줄링할지 알려줄 필요가 없음.
노드 셀렉터를 사용해서
- 정확한 노드를 지정하는 대신 필요한 노드 요구 사항을 기술하고 쿠버네티스가 요구 사항을 만족하는 노드를 선택하도록 함.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
→ nodeSelector에 실제 호스트 이름을 지정할 경우에 해당 노드가 오프라인 상태인 경우 파드가 스케줄링 되지 않을 수 있음.
◼️ 3.6 파드에 어노테이션 달기
어노테이션
- 파드 및 다른 오브젝트는 레이블 외에 어노테이션을 가질 수 있음.
- 키-값 쌍으로 레이블가 비슷하지만 식별 정보를 가지지 않음.
- 어노테이션 셀렉터와 같은 건 없음.
- 쿠버네티스에 새로운 기능을 추가할 때 흔히 사용.
- 파드나 다른 API 오브젝트에 설명을 추가 해 둘 때 유용하게 사용.
- 레이블에는 짧은 데이터를 넣지만 어노테이션에는 상대적으로 큰 데이터를 넣을 수 있음(256KB).
apiVersion: v1
kind: Pod
metadata:
name: annotations-demo
annotations:
imageregistry: "<https://hub.docker.com/>"
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
◼️ 3.7 네임스페이스를 사용한 리소스 그룹화
오브젝트를 겹치지 않는 그룹으로 분할하고자 할 때
- 오브젝트를 네임스페이스로 그룹화.
- 네임스페이스는 오브젝트 이름의 범위를 제공.
네임스페이스
- 모든 리소스를 하나의 단일 네임스페이스에 두는 대신 여러 네임스페이스로 분할 가능.
- 분리된 네임스페이스는 같은 리소스 이름을 다른 네임스페이스에 걸쳐 여러번 사용할 수 있게 해줌.
- 많은 구성 요소를 가진 복잡한 시스템을 좀 더 작은 개별 그룹으로 분리할 수 있음.
- 실행 중인 오브젝트에 대한 격리는 제공하지 않음.
- 리소스 이름은 네임스페이스 안에서만 고유하면 됨.
네임스페이스 생성
kubectl create namespace <namespace name>
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
name: development
네임스페이스 나열
kubectl get namespace
특정 네임스페이스 내 파드 나열
kubectl get pod --namespace <namespace name>
◼️ 3.8 파드 중지와 제거
파드 제거
kubectl delete pod <pod name>
레이블 셀렉터를 이용한 파드 제거
kubectl delete pod -l app=nginx
네임스페이스를 이용한 파드 제거
kubectl delete namespace <namespace name>
네임스페이스를 유지하면서 안에 있는 모든 파드 삭제
kubectl delete pod -all
네임스페이스에서 모든 리소스 삭제
kubectl delete all --all