▶ 지난 포스팅
Kubernetes Object [Part 01] — 하늘을 나는 펭귄
Kubernetes Object [Part 01]
01. Kubernetes 오브젝트kubernetes 시스템 내에서 영속성을 가지는 오브젝트클러스터의 의도한 상태를 나타내기 위해 오브젝트를 이용status 필드는 kubernetes 시스템과 컴포넌트에 의해 오브젝트의 현
ssunghwan.tistory.com
01. Container Object
💁♂️ Pod란?
- 최소단위 쿠버네티스 객체
- docker container와는 조금 다르게 pod는 하나 이상의 컨테이너를 포함 가능
- 애플리케이션 컨테이너(하나 또는 다수), 스토리지, 네트워크 등의 정보를 포함한다.
즉, 사실상 Pods는 다수의 Container를 담고있는 가상머신!!
- Pod 안에 있는 모든 컨테이너는 항상 같은 host에 스케줄링이 된다.
- filesystem, networking, namespace 등 모두 공유하게 된다!
■ Pods 디자인 패턴

1. Sidecar 방식 : 메인 컨테이너의 기능을 추가해주는 시나리오에서 많이 사용
로깅을 하는 전용 컨테이너를 띄울 때 자주 사용한다.
하나의 Pod 안에서 Container는 파일 시스템을 공유하기 때문에 메인 컨테이너가 발생시킨 로그를 sidecar container가
처리하는 로그 라우터 역할
2. Adapter 방식 : 외부 접속을 위한 인터페이스를 제공해주기 위해 구성
메인 컨테이너의 어느 데이터 형식을 변환해주는 역할을 Adapter가 한다.
예를 들어, 외부에 prometheus 같은 모니터링 소프트웨어에서는 정의된 형식으로만 메트릭 수집을 해야되는데 만약 메인
컨테이너가 규칙에 어긋나 있으면 Adapter가 그 데이터를 반환해주는 역할을 대신 한다.
3. Ambassador 방식
메인 컨테이너를 대신해서 외부 시스템과 통신을 중제 해주는 역할을 해주는 서브 컨테이너가 필요할 때 사용
■ Pod yaml 구조
apiVersion: v1
kind: Pod
metadata:
name: myapp-prod
namespace: app
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx:1.14
ports:
- containerports: 8080
- name: redis-container
image: redis:3.2
- 대표적으로 참조하는 Lables 추가, ports 할당 및 multi container를 구성하여 사용한다.
■ Pod에 resource requirement 정의
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: nginx
image: nginx:1.14
resources:
requests:
memory: "1Gi"
cpu: "1000m"
limits:
memory: "2Gi"
cpu: "3000m"
- resource 정의가 없는 경우 제한없이 cpu / memory 사용할 수 있지만, 아래와 같은 상황이 발생한다.
limit을 넘을 경우 kubernetes는 cpu throttle을 하고, memory의 경우 limit을 넘어 쓸 수는 있지만
결국에는 terminate 시켜버린다.
■ Pod 생성
역시 명령을 직접 내려서 생성할 수 있지만, yaml 형식으로 배포 가능하며 이를 습관화 하도록 하자.
kubectl run [pod name] --image=nginx
kubectl run [pod name] --image=nginx --dry-run=client -o yaml > pod.yaml
kubectl apply -f pod.yaml
02. Pods를 관리하는 Resource 종류
2-1. ReplicaSet
Pods에 대해 간략하게 설명 드렸지만 다수의 Container를 관리하는 친구입니다.
하지만, 하나의 Pod에 Application을 배포하였다고 가정하였을때 오류가 생긴다면 Application은 어떻게 사용할까?
대규모 환경에서는 Cluster 위에 여러 개의 동일한 Pods를 실행하여 Traffic을 분산시키고 혹시 모를
오류 상황에도 여러 동일한 Pods들 덕분에 서비스가 중지되지 않는 것 입니다.
💁♂️ ReplicaSet이란?
여러 복제된 Pods들을 그룹 단위로 묶어 App의 안정성, 가용성을 목적으로 둔 Kubernetes 워크로드.
- 사용자가 지정한 Pods의 개수를 항상 유지하며 삭제되거나 장애 발생 시 ReplicaSet이 새로운 Pods 생성.
- 여러 Pods를 생성하여 외부 Traffic을 분산하여 MSA 구조에 효과적이다.
- 동일한 Pods를 하나하나 정의할 필요 없이 사용자의 요구 사항에 맞춰 원하는 수 만큼 쉽게 관리.
■ ReplicaSet의 기본 Yaml 구조

ReplicaSet의 강점 중 하나가 Selector기반 관리 입니다.
- Pod를 모니터링 하면서 selector에 정의한 label과 동일한 label을 갖고 있는 Pod의 개수를 계산하게 되며 이러한 메커니즘을 통해서 레플리카셋을 생성하기 이전에 생성한 Pod를 고려할 수 있도록 설계.
- label이 변경되어 Selector와 일치하지 않으면 해당 Pod는 관리 대상에서 벗어나고 ReplicaSet은 부족한 만큼 Pod를 생성,
■ ReplicaSet 생성, 확인
yaml 파일로 생성된 ReplicaSet을 실행, 확인하고 labels 까지 확인해보자.
kubectl apply -f replicaset.yaml
kubectl get replicaset
kubectl get replicaset -o wide
kubectl get pod -l type=front-end --show-labels

■ ReplicaSet 자동복구(Self-healing) 확인
임의로 하나의 Pod를 삭제한 후 확인해보자.

■ ReplicaSet Scale in/out
스케일링하여 pods 갯수를 조정하고 확인.
kubectl scale replicaset myapp-replicaset --replicas 6
kubectl get replicaset

이렇게 cli 명령을 활용하여 스케일링 하는것 보다 Yaml 파일로 관리하는 것이 운영 측에서 더 용이하다.
vi replicaset.yaml
replicas: 6 [수정]
kubectl apply -f replicaset.yaml
kubectl get replicaset
2-2. Deployment
쉽게 말해서 RepliaSet의 상위 개념이며, 아래와 같은 기능을 지원한다.
- Rolling Update / RollBack : 버전 관리 기능이며, 해당 Pods들 내부 Container의 버전을 쉽게 관리한다.
- 복제된(Replicated) 애플리케이션(Pod)를 관리하는 Object.
💁♂️ Deployment란?
Pods 내부에서 실행되고 있는 Container의 버전 변화에 따른 Pod 집합의 안정적인 배포와 업데이트를 관리.
■ Deployment의 기본 Yaml 구조

■ Deployment의 배포 전략
1. recreate : 모든 Pod를 한번 삭제하고 다시 생성하는 옵션.
- 장점 : downtime이 발생하며, 정해진 Pod 갯수 이외에 추가 리소스를 사용하지 않으므로 전환이 빠르고 비용이 효율적.
- 단점 : downtime이 발생하기 때문에 운영환경에 적합하지 않다.
2. rolling update : 하나씩 혹은 몇개씩 롤링을 하면서 버전을 바꿔주는 전략.
Downtime이 없어서 일반적으로 사용되며, 동시에 두개의 버전을 서비스 하게 되는 상황이 발생.
- maxUnavailable : 업데이트 중 동시에 정지가 가능한 최대의 Pod 수를 지정
- maxSurge : 업데이트 중 동시에 생성할 수 있는 최대의 Pod 수를 지정
번외로, Blue green 배포나 카나리 배포를 원하게 될 경우에는 ArgoCD 같은 배포 툴을 활용해서
운영 환경에 맞게 업데이트 진행 !!!
■ Deployment 생성, 확인
yaml 파일로 deployment를 생성하고 deep하게 확인하며 ReplicaSet 및 pod를 확인하는 명령어.
kubectl apply -f test-deploy.yaml --record
kubectl get deployment
kubectl describe deployment myapp-deployment
kubectl get replicaset
kubectl get pod
■ Rolling Update & Roll Back
# Rolling update
$ kubectl set image deployment myapp-deployment nginx-container=nginx:1.23 --record
# 변경사항 확인
$ kubectl rollout history deployment myapp-deployment
# Rollback (history 기준 revision 넘버로 롤백)
$ kubectl rollout undo deployment myapp-deployment --to-revision 1
2-3. DaemonSet
Cluster의 각 Node에 Pod를 하나씩 실행시킬때 사용하는 Object.
- 로그수집기를 실행하거나 노드를 모니터링 하는 용도의 데몬 등 클러스터 전체에 항상 실행시켜 둬야하는 Pod를 실행하는데 사용한다.
- 가장 대표적인 예시: kube-proxy, fluent-bit, weave-net 등 네트워크 플러그인 등등 ...
💁♂️ DaemonSet란?
Cluster의 안정성과 효율성을 높이는데 필수적인 도구, 특정 기능을 모든 Node에 일관되게 배포하고 관리할때 사용
■ DaemonSet의 기본 Yaml 구조

■ DaemonSet 재시작
1. 동작 : DaemonSet에 의해 배포된 Pod 내부의 Container는 기본적으로 restartPolicy: Always로 설정된다.
- Container가 어떤 이유로든 종료되거나 장애가 발생하더라도 Pod내에서 Container를 재시작
- Kubelet은 Pod의 이 설정을 기반으로 Container 상태를 모니터링, 필요에 따라 재시작 합니다.
2. 결과 : Pod 자체는 재시작 되지 않고 유지되며, Container만 재시작되어 서비스의 연속성을 유지합니다.
그렇다면, 사용자가 수동으로 삭제할 경우는?
- 사용자가 'kubectl delete pod [pod name]' 명령을 통해 특정 Node의 DaemonSet Pod를 삭제할 경우
DaemonSet Controller는 해당 Node에 지정된 Pod가 없다는 것을 감지하였지만
각 Node에 하나의 DaemonSet Pod를 유지해야 한다는 목표를 가지고 있어 삭제된 Pod를 해당 Node에 스케줄링.
■ DaemonSet 업데이트
yaml 파일에서 pod 템플릿을 변경하거나, 수동 명령으로 version update를 진행하여도 DaemonSet은 기본적으로
Rolling update 업데이트 전략을 사용하여 Pod를 점진적으로 Update 한다.
즉, 기존 Pod가 종료되고 새로운 대체Pod가 생성된다.