처음에 쿠버네티스를 시작하면 파드를 생성하는 방법이 두 가지나 있어서 혼란스러웠습니다.하...
kubectl run
과 kubectl create deployment
둘 다 파드를 만드는 명령어인데, 도대체 언제 무엇을 써야 할까요?...???
파드(Pod) 쿠버네티스에서 컨테이너를 실행하는 가장 기본적인 단위입니다. 하나 이상의 컨테이너를 포함할 수 있으며, 네트워크와 스토리지 등의 리소스를 공유합니다.
kubectl run
vs kubectl create deployment
명령어 | 특징 | 사용 시기 |
---|---|---|
kubectl run | 단일 파드만 생성 | 빠른 테스트, 개발 환경 |
kubectl create deployment | 디플로이먼트 객체를 통한 파드 관리 | 실제 서비스, 운영 환경 |
# 단일 파드 생성
kubectl run nginx-pod --image=nginx
# 디플로이먼트를 통한 파드 생성
kubectl create deployment nginx-deployment --image=nginx
run
명령어로 만든 파드가 죽으면 그대로 죽은 상태로 남아있지만, create deployment
로 만든 파드가 죽으면 자동으로 새 파드가 생성됩니다. 이것은 디플로이먼트가 파드의 상태를 지속적으로 모니터링하고 관리하기 때문입니다.
단순히 테스트하거나 일회성 작업을 위한 파드는 kubectl run
을 사용하고, 실제 서비스를 배포할 때는 kubectl create deployment
를 사용하는 것이 좋습니다.
쿠버네티스 오브젝트는 클러스터의 '상태'를 나타내는 단위입니다. 각 오브젝트는 특정 역할을 수행합니다:
처음에는 파드와 컨테이너의 관계를 이해하기 어려울 수 있습니다. 파드는 하나 이상의 컨테이너를 포함하는 '래퍼(wrapper)'라고 생각하면 됩니다. 파드 내의 컨테이너들은 네트워크와 스토리지 리소스를 공유합니다.
각 오브젝트는 서로 다른 역할을 수행하면서도 유기적으로 연결되어 있습니다:
default
, kube-system
, metallb-system
등이 있습니다.실제 서비스를 운영하다 보면 단일 파드만으로는 한계가 있습니다. 부하가 증가하면 파드 수를 늘려야 하고, 줄어들면 파드 수를 줄여야 합니다. 이런 상황에서 레플리카셋이 필요합니다.
레플리카셋은 지정한 수의 파드 복제본을 유지하는 오브젝트입니다. 파드가 죽으면 자동으로 새 파드를 생성하여 지정된 수를 유지합니다.
# 디플로이먼트의 파드 수 조정
kubectl scale deployment dpy-nginx --replicas=3
저기 명령어는 dpy-nginx
디플로이먼트의 파드 수를 3개로 조정합니다. 레플리카셋은 이 명령에 따라 자동으로 파드 수를 3개로 유지합니다.
레플리카셋은 파드 수만 관리하는 반면, 디플로이먼트는 레플리카셋을 관리하면서 추가로 롤링 업데이트와 롤백 기능을 제공합니다. 실무에서는 대부분 디플로이먼트를 사용하는 것이 좋습니다.
레플리카셋이 수행하는 주요 기능은 다음과 같습니다
디플로이먼트는 이러한 레플리카셋의 기능을 포함하면서 추가적인 기능을 제공합니다:
# 디플로이먼트 예시
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3 # 파드 3개 유지
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
여러 명령어들을 배울수록 헷갈리는 부분이 많아서 일관된 방식으로 오브젝트를 관리하고 싶었습니다. 그때 알게 된 것이 kubectl apply
명령어입니다.
명령어 | 특징 | 사용 시기 |
---|---|---|
kubectl create | 일회성 생성 | 처음 생성 시 |
kubectl apply | 생성 및 변경사항 적용 | 지속적인 관리 |
kubectl apply
는 YAML 파일을 이용해 오브젝트를 생성하고 관리합니다. 이 방식의 장점은 코드로 인프라를 관리할 수 있다는 것입니다(Infrastructure as Code).
# YAML 파일을 이용한 오브젝트 생성/수정
kubectl apply -f my-deployment.yaml
YAML 파일을 수정한 후 다시 apply
명령어를 실행하면, 쿠버네티스는 변경된 부분만 업데이트합니다. 이는 오브젝트의 이력을 추적하고 관리하는 데 매우 유용합니다.
YAML 파일을 Git과 같은 버전 관리 시스템에 저장하면, 인프라 변경 이력을 추적하고 협업할 수 있으며, 필요시 이전 상태로 되돌릴 수도 있습니다.
쿠버네티스의 가장 강력한 기능 중 하나는 셀프 힐링(Self-Healing) 입니다. 파드가 죽거나 노드에 문제가 생겨도 시스템은 계속 실행됩니다.
디플로이먼트는 이러한 셀프 힐링 기능을 기본적으로 제공합니다. 디플로이먼트에 속한 파드가 삭제되면 자동으로 새로운 파드가 생성됩니다.
# 디플로이먼트의 파드 수 확인
kubectl get pods -l app=nginx
# 파드 하나 삭제
kubectl delete pod nginx-deployment-6b474476c4-abcd1
# 잠시 후 다시 파드 수 확인
kubectl get pods -l app=nginx
# 새로운 파드가 자동으로 생성된 것을 확인할 수 있습니다
파드가 삭제되면 디플로이먼트 컨트롤러가 이를 감지하고, 레플리카셋에게 새로운 파드를 생성하도록 지시합니다. 레플리카셋은 스케줄러에게 파드 생성을 요청하고, 스케줄러는 적절한 노드를 선택하여 파드를 배치합니다.
클러스터의 노드 중 하나에 유지보수가 필요할 때, 해당 노드에 새로운 파드가 스케줄링되지 않도록 해야 합니다. 이때 사용하는 것이 cordon
명령어입니다.
# 노드에 새로운 파드 스케줄링 중지
kubectl cordon w3-k8s
# 노드 상태 확인
kubectl get nodes
# SchedulingDisabled 상태가 표시됩니다
# 스케줄링 다시 활성화
kubectl uncordon w3-k8s
cordon
명령어는 노드를 '통제(cordon off)'하여 새로운 파드가 배치되지 않도록 합니다. 이미 실행 중인 파드는 계속 실행됩니다.
cordon은 새로운 파드의 스케줄링만 방지하고, 이미 실행 중인 파드에는 영향을 주지 않습니다. 실행 중인 파드를 다른 노드로 이동시키려면 drain
명령어를 사용해야 합니다.
노드의 하드웨어 업그레이드나 OS 패치 적용과 같은 유지보수 작업을 위해 노드의 모든 파드를 다른 노드로 이동시켜야 할 때가 있습니다. 이럴 때 사용하는 것이 drain
명령어입니다.
# 노드의 파드를 다른 노드로 이동
kubectl drain w3-k8s --ignore-daemonsets
# 유지보수 완료 후 노드 복구
kubectl uncordon w3-k8s
--ignore-daemonsets
옵션은 DaemonSet에 의해 관리되는 파드를 무시하도록 지시합니다. DaemonSet 파드는 모든 노드에 실행되어야 하는 특수한 파드로, 노드 단위 모니터링이나 로깅에 사용됩니다.
애플리케이션을 새 버전으로 업데이트하거나, 문제가 생겼을 때 이전 버전으로 롤백하는 것은 운영에서 매우 중요한 작업입니다. 쿠버네티스는 이러한 작업을 손쉽게 수행할 수 있는 명령어들을 제공합니다.
명령어 | 기능 | 사용 예시 |
---|---|---|
kubectl rollout history | 배포 히스토리 확인 | kubectl rollout history deployment nginx-app |
kubectl set image | 파드 이미지 업데이트 | kubectl set image deployment nginx-app nginx=nginx:1.16.0 --record |
kubectl rollout undo | 이전 버전으로 롤백 | kubectl rollout undo deployment nginx-app --to-revision=1 |
이미지 업데이트 시 --record
옵션을 사용하면 변경 사항이 히스토리에 기록되어 나중에 특정 버전으로 롤백할 때 유용합니다.
# 배포 히스토리 확인
kubectl rollout history deployment rollout-nginx
# 이미지 업데이트
kubectl set image deployment rollout-nginx nginx=nginx:1.16.0 --record
# 특정 버전으로 롤백
kubectl rollout undo deployment rollout-nginx --to-revision=1
롤링 업데이트는 모든 파드를 동시에 교체하지 않고 점진적으로 교체하기 때문에 서비스 중단 없이 업데이트할 수 있습니다. 또한 문제 발생 시 즉시 롤백할 수 있어 안전합니다.
하 머리아프고 손가락도 뻐근하네요
쿠버네티스에서 서비스(Service)라는 용어는 일반적인 의미와 조금 다릅니다. 쿠버네티스의 서비스는 파드에 접근하기 위한 안정적인 엔드포인트를 제공하는 오브젝트입니다.
파드는 일시적(ephemeral)입니다. 언제든지 생성, 삭제될 수 있고 IP 주소도 변경됩니다. 이런 상황에서 안정적으로 파드에 접근하려면 서비스가 필요합니다.
서비스는 라벨 셀렉터(Label Selector)를 사용하여 어떤 파드에 트래픽을 전달할지 결정합니다. 예를 들어, app: nginx
라벨이 있는 모든 파드에 트래픽을 분산할 수 있습니다.
쿠버네티스는 다양한 서비스 유형을 제공합니다
# 서비스 생성 예시
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- port: 80 # 서비스 포트
targetPort: 8080 # 파드 포트
type: LoadBalancer # 서비스 유형
위 예시는 app: my-app
라벨이 있는 파드들에 트래픽을 분산하는 LoadBalancer 유형의 서비스를 생성합니다. 외부에서는 서비스의 80번 포트로 접근하면 파드의 8080번 포트로 트래픽이 전달됩니다.
서비스를 생성하고 활용하는 방법에는 여러 가지가 있습니다. 가장 일반적인 방법은 YAML 파일을 사용하는 것입니다.
# YAML 파일로 서비스 생성
kubectl apply -f my-service.yaml
# 명령어로 서비스 생성 (NodePort 유형)
kubectl expose deployment nginx-deployment --port=80 --type=NodePort
# 서비스 목록 확인
kubectl get services
# 서비스 상세 정보 확인
kubectl describe service my-service
서비스 유형에 따라 접근 방법이 다릅니다. ClusterIP는 클러스터 내부에서만, NodePort는 <노드IP>:<노드포트>로, LoadBalancer는 할당된 외부 IP로 접근합니다.
서비스를 활용하는 시나리오를 살펴보면
서비스는 쿠버네티스에서 가장 중요한 개념 중 하나이며, 이를 올바르게 활용하면 안정적이고 확장 가능한 애플리케이션을 구축할 수 있습니다.