5장. 파드
파드의 필요성
서비스 레벨에 차이가 있으면서 한 머신에 있어야 할 공생 관계를 가진 경우를 컨트롤 하기 위해서
local filesystem을 공유하는 git 동기화 컨테이너와 웹 서빙 컨테이너
MSA에서 각 어플리케이션과 해당 어플리케이션의 정보 및 네트워크를 컨트롤하는 사이드카
쿠버네티스에서의 파드
쿠버네티스 컨테이너의 배포 단위로 같은 파드에 속한 컨테이너 들은 모두 같은 머신 혹은 node에 속한다.
동일 파드
동일 ip
포트
네트워크 네임스페이스
호스트 명(UTS 네임스페이스)
UTS 네임스페이스 - 리눅스 커널의 네임스페이스 중 하나로 시스템의 호스트명과 도메인 이름을 격리하는 역할을 함, kubernetes에서 pod안의 모든 컨테이너들은 동일한 uts네임스페이스를 공유하고 그 결과 pod내의 모든 컨테이너들은 동일한 호스트명을 가짐. 이를 통해 하나의 pod내에서 실행 중인 여러 컨테이너들은 같은 호스트를 사용할 수 있게 되고 이것이 네트워크 상호작용을 간단하게 만드는 효과를 만든다고 한다.
프로세스 간 통신 채널로 동일 파드에 속하는 컨테이너는 서로 소통 가능
파드에 대한 생각
파드 안의 존재들은 모두 같은 스케일링 전략을 가져야 한다.
각기 다른 머신에 존재하여도 문제없이 실행될 수 있다면 같은 pod에 놓는 것은 좋지 못한 선택일 수 있다.
ex) database와 웹서버
파드 매니페스트
정의: 쿠버네티스 api 객체를 단순히 텍스트 파일 형태로 표현한 것
declarative configuration
상태를 지정하고 해당 상태를 유지하도록 조치를 취하는 서비스로 제출하는 것
처리과정
매니페스트 파일을 API 서버에 제출
매니페스트 검증 및 수락 + 처리
영구 저장소(etcd)에 저장
etcd: Kubernetes의 분산 키-값 저장소로, 클러스터의 상태 정보를 모두 저장합니다. 이에는 파드 매니페스트를 비롯한 클러스터 내의 모든 오브젝트의 상태(예: 파드, 서비스, 컨피그맵, 시크릿, 노드 정보 등)가 포함됩니다.(gpt)
스케줄러가 노드에 파드를 배치
kubelet에 의해 파드 실행
매니페스트 파일에 기반하여 실제 객체를 지속적으로 관리
파드 생성
kubectl run
user@AL02502768 kind % kubectl run kuard --generator=run-pod/v1 \ --image=gcr.io/kuar-demo/kuard-amd64:blue pod/kuard created
—generator 옵션
종류
run-pod/v1
: Pod를 생성하기 위한 생성기.deployment/apps.v1
: Deployment를 생성하기 위한 생성기.
구 버전에서 쓰이는 방식이고 현재는 다음과 같은 방식으로 대체되었다고 한다.
kubectl run <pod-name> --image=<image-name> --restart=Never
생성된 pods 확인
user@AL02502768 kind % kubectl get pods NAME READY STATUS RESTARTS AGE kuard 1/1 Running 0 15m
특정 파드 삭제
user@AL02502768 kind % kubectl delete pods/kuard pod "kuard" deleted
파드 매니페스트 생성
yaml이나 json으로 생성 가능하지만 주로 yaml 사용(comment)
key-value 스타일
metadata vs spec section
metadata section: 파드와 그 라벨에 대한 설명
spec: 컨테이너 목록 설명
예시코드:
apiVersion: v1 kind: Pod metadata: name: kuard spec: containers: - image: gcr.io/kuar-demo/kuard-amd64:blue name: kuard ports: - containerPort: 8080 name: http protocol: TCP
파드 실행
apply 명령 사용
user@AL02502768 kind % kubectl apply -f kuard-pod.yaml pod/kuard created
파드 조회
get 명령 사용
user@AL02502768 kind % kubectl get pods NAME READY STATUS RESTARTS AGE kuard 1/1 Running 0 20s
파드 세부 사항
describe 명령어 사용
user@AL02502768 kind % kubectl describe pods kuard
# 파드에 대한 기본적인 정보
Name: kuard
Namespace: default
Priority: 0
Node: kind-control-plane/10.89.1.4
Start Time: Mon, 02 Sep 2024 01:28:18 +0900
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
""{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"kuard","namespace":"default"},"spec":{"containers":[{"image":"gcr.io/..."
Status: Running
IP: 10.244.0.6
IPs:
IP: 10.244.0.6
## 파드 내 컨테이너에 대한 설명
Containers:
kuard:
Container ID: containerd://33deba34b9f3e27905b686f25d97bd5b46e4af1d184231f74e7bcd183187e2a7
Image: gcr.io/kuar-demo/kuard-amd64:blue
Image ID: gcr.io/kuar-demo/kuard-amd64@sha256:1ecc9fb2c871302fdb57a25e0c076311b7b352b0a9246d442940ca8fb4efe229
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 02 Sep 2024 01:28:18 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-5btk2 (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-5btk2:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
## 이벤트 정보
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 8m58s default-scheduler Successfully assigned default/kuard to kind-control-plane
Normal Pulled 8m58s kubelet, kind-control-plane Container image "gcr.io/kuar-demo/kuard-amd64:blue" already present on machine
Normal Created 8m58s kubelet, kind-control-plane Created container kuard
Normal Started 8m58s kubelet, kind-control-plane Started container kuard
man page
user@AL02502768 kind % kubectl describe --help Show details of a specific resource or group of resources Print a detailed description of the selected resources, including related resources such as events or controllers. You may select a single object by name, all objects of that type, provide a name prefix, or label selector. For example: $ kubectl describe TYPE NAME_PREFIX will first check for an exact match on TYPE and NAME_PREFIX. If no such resource exists, it will output details for every resource that has a name prefixed with NAME_PREFIX. Use "kubectl api-resources" for a complete list of supported resources. Examples: # Describe a node kubectl describe nodes kubernetes-node-emt8.c.myproject.internal # Describe a pod kubectl describe pods/nginx # Describe a pod identified by type and name in "pod.json" kubectl describe -f pod.json # Describe all pods kubectl describe pods # Describe pods by label name=myLabel kubectl describe po -l name=myLabel # Describe all pods managed by the 'frontend' replication controller (rc-created pods # get the name of the rc as a prefix in the pod the name). kubectl describe pods frontend Options: -A, --all-namespaces=false: If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace. -f, --filename=[]: Filename, directory, or URL to files containing the resource to describe -k, --kustomize='': Process the kustomization directory. This flag can't be used together with -f or -R. -R, --recursive=false: Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory. -l, --selector='': Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2) --show-events=true: If true, display events related to the described object. Usage: kubectl describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME) [options] Use "kubectl options" for a list of global command-line options (applies to all commands).
관련 설명 필요
파드 삭제
user@AL02502768 kind % kubectl delete pods/kuard
pod "kuard" deleted
파드에 접근
로그를 통해 더 많은 정보 얻기
logs 명령어 사용
user@AL02502768 kind % kubectl logs kuard 2024/09/01 16:45:52 Starting kuard version: v0.10.0-blue 2024/09/01 16:45:52 ********************************************************************** 2024/09/01 16:45:52 * WARNING: This server may expose sensitive 2024/09/01 16:45:52 * and secret information. Be careful. 2024/09/01 16:45:52 ********************************************************************** 2024/09/01 16:45:52 Config: { "address": ":8080", "debug": false, "debug-sitedata-dir": "./sitedata", "keygen": { "enable": false, "exit-code": 0, "exit-on-complete": false, "memq-queue": "", "memq-server": "", "num-to-gen": 0, "time-to-run": 0 }, "liveness": { "fail-next": 0 }, "readiness": { "fail-next": 0 }, "tls-address": ":8443", "tls-dir": "/tls" } 2024/09/01 16:45:52 Could not find certificates to serve TLS 2024/09/01 16:45:52 Serving on HTTP on :8080
exec을 사용해 컨테이너에서 명령 실행
user@AL02502768 kind % kubectl exec -it kuard -- ash
~ $ exit
참고사항: bash는 없음
user@AL02502768 kind % kubectl exec -it kuard -- bash error: Internal error occurred: error executing command in container: failed to exec in container: failed to start exec "56fbf70a8f69023e46ca86000a3415fa23e0d3302d0e5598aa361169953148ba": OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
컨테이너 내외부로 파일 복사
안티패턴이지만 장애를 빠르게 해결하는 방안으로는 사용 가능
단 사용 후 이미지에 반영하여야 함
상태 검사
프로세스 상태 검사 → 파드를 항상 살아 있는 상태로 유지할 수 있음
검사 실패 시 프로세스 재시작
그러나 주요 프로세스를 항상 실행하게 하는 단순한 방식이어서 데드락 같은 상황을 처리할 수 없음
각 어플리케이션 별로 특화된 상태 검사가 필요
프로브라고 불리며 매니페스트에 정리
활성 프로브
활성 프로브를 추가한 매니페스트
apiVersion: v1 kind: Pod metadata: name: kuard spec: containers: - image: gcr.io/kuar-demo/kuard-amd64:blue name: kuard livenessProbe: httpGet: path: /healthy port: 8080 initialDelaySeconds: 5 periodSeconds: 1 failureThreshold: 3 ports: - containerPort: 8080 name: http protocol: TCP
강제 실패 시:
87s Normal Created pod/kuard Created container kuard 87s Normal Started pod/kuard Started container kuard 87s Warning Unhealthy pod/kuard Liveness probe failed: HTTP probe failed with statuscode: 500 87s Normal Killing pod/kuard Container kuard failed liveness probe, will be restarted
준비 프로브
사용자 요청을 받을 수 있는 상태인지에 대한 체크
실패시 성공할 때까지 로드밸런서에서 제외, 주기적으로 시도하여 성공시 다시 트래픽 받음
시작 프로브
컨테이너가 시작될 때 한 번 실행됨. 이 프로브가 성공할 때까지 쿠버네티스는 컨테이너가 정상적으로 시작되고 있다고 가정하며, 성공하면 준비 및 라이브니스 프로브가 활성화됨
만약 시작 프로브가 실패하면, 컨테이너는 재시작되거나 실패 상태로 간주될 수 있음.
상태 검사의 기타 기입
tcp와 exec 프로브 존재
apiVersion: v1
kind: Pod
metadata:
name: kuard
spec:
containers:
- image: gcr.io/kuar-demo/kuard-amd64:blue
name: kuard
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 1
livenessProbe:
httpGet:
path: /healthy
port: 8080
initialDelaySeconds: 5
periodSeconds: 1
failureThreshold: 3
ports:
- containerPort: 8080
name: http
protocol: TCP
리소스 관리
리소스 관리가 필요한 이유
컴퓨트 노드의 전체 사용률을 높여서 비용 효율성을 높이기 위해
이를 위해서는 각 컨테이너가 필요한 리소스를 쿠버네티스에 알려주어야 할 필요성이 있음
기호 표기 방법
literals:
메모리 자원을 설정할 때 사용하는 표기 방식으로 기본 단위는 byte
MB/GB/PB와 MiB/GiB/PiB의 차이 비교
1 MB = 1000KB
1 MIM = 1024KIB
millicores:
CPU 리소스를 설정할 때 사용하는 단위
1 core == 1000m
리소스 요청
개념: 해당 어플리케이션이 보장받아야 하는 최소 리소스 량
예시코드
apiVersion: v1 kind: Pod metadata: name: kuard spec: containers: - image: gcr.io/kuar-demo/kuard-amd64:blue name: kuard resources: requests: cpu: "500m" memory: "128Mi" ports: - containerPort: 8080 name: http protocol: TCP
리눅스 커널 cpu-shares:
리소스 제한
개념: 해당 어플리케이션이 받을 수 있는 최대 리소스 량
예시코드
apiVersion: v1 kind: Pod metadata: name: kuard spec: containers: - image: gcr.io/kuar-demo/kuard-amd64:blue name: kuard resources: requests: cpu: "500m" memory: "128Mi" limits: cpu: "800m" memory: "256Mi" ports: - containerPort: 8080 name: http protocol: TCP
볼륨을 통한 데이터 보존
파드에서 볼륨 사용
해당 파드 매니페스트에서 컨테이너가 접근할 수 있는 모든 볼륨을 정의
예시
apiVersion: v1 kind: Pod metadata: name: kuard spec: volumes: - name: "kuard-data" hostPath: #워커 노드 임의의 위치를 컨테이너에 마운트 할 수 있는 예약 볼륨 path: "/var/lib/kuard"
컨테이너에서 볼륨 사용
특정 컨테이너에 마운트될 볼륨과 각 볼륨들이 마운트될 경로 정의
예시
apiVersion: v1 kind: Pod metadata: name: kuard spec: volumes: - name: "kuard-data" hostPath: #워커 노드 임의의 위치를 컨테이너에 마운트 할 수 있는 예약 볼륨 path: "/var/lib/kuard" containers: - image: gcr.io/kuar-demo/kuard-amd64:blue name: kuard volumeMounts: - mountPath: "/data" name: "kuard-data" ports: - containerPort: 8080 name: http protocol: TCP
파드에서 볼륨을 사용하는 다양한 방법
통신/동기화
두 컨테이너 사이의 볼륨 공유
apiVersion: v1
kind: Pod
metadata:
name: shared-volume-pod
spec:
volumes:
- name: shared-data
emptyDir: {} # 이 예제에서는 emptyDir을 사용합니다. Pod의 수명 동안만 데이터를 저장합니다.
containers:
- name: container-1
image: nginx
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html # 첫 번째 컨테이너에서의 마운트 경로
- name: container-2
image: busybox
command: [ "sh", "-c", "echo 'Hello from container-2' > /shared-data/message.txt && sleep 3600" ]
volumeMounts:
- name: shared-data
mountPath: /shared-data
캐시
emptyDir 볼륨 공유
apiVersion: v1
kind: Pod
metadata:
name: empty-dir-example
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- mountPath: /tmp/emptydir
name: temp-storage
volumes:
- name: temp-storage
emptyDir: {}
emptydir
pod가 생성될 때 자동으로 만들어지며, Pod가 삭제되면 함께 삭제됩
일반적으로는 로컬 디스크에 데이터를 저장하지만 메모리를 기반으로 저장할 수도 있음
volumes: - name: temp-storage emptyDir: medium: Memory
영구데이터
클라우드 같은 원격 네트워크 스토리지 볼륨 사용
호스트 파일 시스템 필요시
hostPath라는 볼륨을 사용
apiVersion: v1
kind: Pod
metadata:
name: hostpath-example
spec:
containers:
- name: hostpath-container
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: hostpath-volume
volumes:
- name: hostpath-volume
hostPath:
path: /data/nginx
type: Directory