
쿠버네티스에서는 사용하고자 하는 컨테이너를 Pod
라는 단위를 이용하여 관리하고 배포한다.
쿠버네티스 컨트롤러는 이러한 Pod
를 다양한 형태로 손쉽게 배포할 수 있도록 도와준다.
컨트롤러에 대해 알아보기 전에 먼저 Pod
에 대해 알아보자.
Pod란?
쿠버네티스에서 다루는 가장 작은 배포 단위이며, 하나 혹은 둘 이상의 컨테이너를 배포하기 위한 환경을 제공한다.
단일 컨테이너(Docker, Containerd 등) 배포와 쿠버네티스 Pod
배포를 비교하면 아래와 같은 장점들이 있다.
- 여러 개의 컨테이너를 하나의 컨테이너처럼 관리하고 배포할 수 있다
- 사용량에 따라 유동적으로 스케일 조정이 가능하다
- 서로 다른 컨테이너들을 하나의 네트워크에서 동작시킬 수 있다
- 설정에 따라 컨테이너 간 동일한 볼륨을 공유하도록 할 수 있다
위와 같은 특징들을 통해 단일 컨테이너 환경에서는 불가능했던 다양한 배포 환경을 구성할 수 있다.(sidecar 형태를 이용한 상태 모니터링, 다른 컨테이너의 파일 추출 등)
컨트롤러란?
컨트롤러는 위와 같은 Pod
를 다양한 형태로 배포할 수 있도록 여러 가지 옵션들을 지원한다.
주로 배포 형태를 나누는 기준은 Pod의 목적에 따라 달라진다.
- 상태 저장이 필요없는
Pod
(ReplicaSet, Deployment, Daemonset) - 상태 저장이 필요한
Pod
(Statefulset) - 일회성 혹은 반복성 작업을 진행하는
Pod
(Job, CronJob)
여기서 말하는 상태 저장이란 Pod
가 종료 후 재시작되어도 이전의 상태를 고유하게 유지해야 할 필요성이 있음을 의미한다.(볼륨 연결, 컨테이너 구성 정보 등)
Replicaset
Pod
가 배포되기 위한 최소한의 상태정보를 관리하는 컨트롤러로 컨테이너 이미지, 포트, Replicas 수 등이 있다.
Replicaset
은 단순히 Pod
만 배포되는것과는 다르게 설정해 둔 상태를 유지하려는 특성을 가지고 있어서 현재 상태와 설정해 둔 상태가 다르다면 다시 설정해 둔 상태로 복구하는 Self-healing
기능을 가지고 있다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
예를들어 위 yaml에서는 replicas
를 3
으로 설정해두었는데 현재 2개의 Pod
만 돌고있다면 Replicaset
이 자동으로 1개의 Pod
를 추가로 생성한다.
Deployment
Replicaset
의 상위 개념으로 여러 관리 기능들을 추가로 지원하기 때문에 주로 Replicaset
보다는 Deployment
를 이용하여 Pod
를 배포한다. Replicas
와 기본 배포 구성은 같으나 추가로 Pod
의 Update 방식을 지정하거나 각 Replicaset
의 버전정보를 이용하여 Rollback 할 수 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
Replicaset
과 다르게 strategy
라는 옵션을 추가로 사용할 수 있는데 Pod
가 새로 배포될 때 어떤 방식으로 기존의 Pod
를 대체할건지를 정할 수 있다.
아래는 Deployment
를 통해 Pod
를 배포했을 때 구조 도이다.
만약 새로 배포한 Version 2
의 nginx가 문제가 발생하여 이전 버전으로 되돌려야 한다면 Version 1
의 revision 번호를 Deployment에 명시만 해주면 빠르게 Rollback이 가능하다.
Daemonset
기존에 Pod
가 배포될 때는 kube-scheduler
에 의해 노드들의 리소스와 스펙들을 고려하여 자동으로 알맞은 노드에 배치가 된다. 하지만 Daemonset
으로 Pod
를 배포하면 각 노드별로 1개의 Pod
가 무조건 스케줄링되도록 보장된 채로 배포가 진행된다. 주로 각 노드들에 배치되어 상태를 확인해야 하는 로깅이나 메트릭 모니터링 시스템 배포에 사용된다.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit-daemonset
namespace: logging
labels:
k8s-app: fluent-bit-logging
spec:
selector:
matchLabels:
name: fluent-bit
template:
metadata:
labels:
name: fluent-bit
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluent-bit
image: fluent/fluent-bit:2.1.10
resources:
limits:
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- mountPath: /fluent-bit/etc/conf
name: config
- mountPath: /var/log
name: varlog
- mountPath: /var/lib/docker/containers
name: varlibdockercontainers
readOnly: true
volumes:
- name: config
configMap:
defaultMode: 420
name: fluent-bit
- name: varlog
hostPath:
path: /var/log
type: ""
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
type: ""
예시에 사용된 fluent-bit
는 각 노드별로 배치되어 해당 노드에서 실행 중인 Pod
들의 로그를 수집하는 역할을 수행한다.
Statefulset
이전 상태를 계속 유지해야 하는 Pod
들을 배포할 때 사용되며 상태정보 및 데이터를 안전하게 유지할 수 있다는 장점이 있어 주로 DB를 배포할 때 사용된다. 또한 배포할 때마다 뒤에 무작위로 문자들이 부여되는 다른 리소스들과 다르게 Statefulset
은 각 Pod
가 재기동되어도 고유한 상태를 지속할 수 있도록 이름 뒤에 순번을 지정하여 관리한다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-statefulset
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "root_password"
- name: MYSQL_DATABASE
value: "database"
- name: MYSQL_USER
value: "username"
- name: MYSQL_PASSWORD
value: "password"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-volume
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
예시는 MySQL8 버전을 배포하는 yaml로써 실제 배포 시 Pod
의 이름은 mysql-0
, mysql-1
, mysql-2
로 설정된다.
또한 아랫부분에 영구볼륨을 지정하고 있는데 이 또한 각 Pod
마다 고유한 볼륨을 가지도록 3개의 볼륨이 생성된다.
실제 배포되는 구조도를 그리면 아래와 같다.
각 Pod
이름 뒤에 고유한 번호가 붙게 되고 해당 Pod
의 이름으로 영구 볼륨이 매칭되는 것을 볼 수 있다.
Job
일반적인 Pod
처럼 계속해서 구동되는 것이 아닌 목표를 달성하고 종료되는 일회성 Pod
를 배포할 때 사용된다.
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
template:
metadata:
name: example-job
spec:
restartPolicy: OnFailure
containers:
- name: example-container
image: busybox:latest
command: ["echo", "Hello, Kubernetes!"]
backoffLimit: 4
위 Job Pod
는 busybox
이미지에서 Hello Kubernetes!
라는 텍스트를 출력하는 명령을 수행하고 종료된다.
만약 해당 명령어가 실패 시 backoffLimit
옵션을 통해 최대 4회까지 재시도한다.
PS C:\Users\Home>kubectl logs example-job-jf4zm
Hello, Kubernetes!
PS C:\Users\Home>kubectl get pod
NAME READY STATUS RESTARTS AGE
example-job-jf4zm 0/1 Completed 0 2m6s
실제 위 yaml을 배포 후 확인해 보면 Hello Kubernetes!
라는 텍스트 출력 후 컨테이너가 Completed
상태로 종료된 걸 볼 수 있다.
Cronjob
Job
이 목표를 달성하고 종료되는 일회성 Pod
라면 Cronjob
은 주기적으로 반복 작업을 진행하는 Pod
를 배포할 때 사용된다.
리눅스 Crontab과 유사하게 크론 표현식을 통해 주기를 설정할 수 있다.
아래는 1분마다 Hello Kubernetes!
텍스트를 출력하는 예시 yaml이다.
apiVersion: batch/v1
kind: CronJob
metadata:
name: example-cronjob
spec:
schedule: "1 * * * *"
jobTemplate:
spec:
template:
metadata:
labels:
app: example-cronjob
spec:
restartPolicy: OnFailure
containers:
- name: example-container
image: busybox:latest
command:
- /bin/sh
- -c
- date; echo "Hello, Kubernetes!"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
하단에 successfulJobsHistoryLimit
및 failedJobsHistoryLimit
옵션은 각각 성공 및 실패한 Job
의 이력을 관리하는 데 사용된다.
배포 후 실제 Job
이 설정한 대로 1분마다 실행되는지 확인해 본다.
PS C:\Users\Home>kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
example-cronjob 1 * * * * False 0 17s 2m48s
PS C:\Users\Home>kubectl get pod
NAME READY STATUS RESTARTS AGE
example-cronjob-28379823-sl2hf 0/1 Completed 0 2m13s
example-cronjob-28379824-c4hg9 0/1 Completed 0 73s
example-cronjob-28379825-2bxsl 0/1 Completed 0 13s
Cronjob
을 배포한 지 3분 정도 되었고 실제 Job
을 실행하는 Pod
가 3개 실행되어 Completed
상태로 종료된 걸 볼 수 있다.
참고자료
워크로드 리소스
운영 수준의 컨테이너 오케스트레이션
kubernetes.io
'Kubernetes' 카테고리의 다른 글
Ingress를 활용하여 웹 트래픽 제어하기 (0) | 2024.01.06 |
---|---|
Helm 알아보기 (0) | 2023.12.31 |
AKS를 사용하여 쿠버네티스 구성하기 (0) | 2023.12.10 |
관리형 쿠버네티스 알아보기 (0) | 2023.12.03 |
Minikube로 쿠버네티스 설치하기 (1) | 2023.11.26 |