소프트웨어 개발 분야에서 일하고 있다면 Kubernetes에 대해 들어보셨을 것입니다. 하지만 정확히 무엇이며, 왜 컨테이너화된 애플리케이션을 관리하기 위한 사실상의 표준이 되었을까요? 이 가이드는 기초부터 핵심 개념까지, 실용적인 예제와 다이어그램을 통해 안내합니다.
Kubernetes 이전: 약간의 역사
Kubernetes가 왜 혁명적인지 이해하기 위해 한 발 뒤로 물러서 봅시다.
- 전통적인 배포: 처음에는 애플리케이션이 물리 서버에서 실행되었습니다. 이 접근 방식은 비용이 많이 들고, 확장이 어려우며, 리소스 충돌이 발생하기 쉬웠습니다.
- 가상화된 배포: 그 다음에 가상 머신(VM)이 등장했습니다. VM은 동일한 하드웨어에서 여러 격리된 애플리케이션을 실행할 수 있게 하여 리소스 활용과 보안을 개선했습니다. 그러나 각 VM은 전체 운영 체제를 실행하여 많은 리소스를 소비합니다.
- 컨테이너화된 배포: 컨테이너(Docker 등)는 다음 진화 단계입니다. 동일한 호스트 운영 체제를 공유하지만 격리된 프로세스를 실행합니다. 가볍고, 빠르게 시작되며, 이식성이 좋습니다.
컨테이너는 이식성 문제를 해결했지만 또 다른 문제를 만들었습니다: 프로덕션 환경에서 수백(또는 수천) 개의 컨테이너를 어떻게 관리할까요? 항상 실행 중이고, 서로 통신할 수 있으며, 부하에 따라 확장되도록 어떻게 보장할까요?
여기서 Kubernetes가 등장합니다.
Kubernetes란 무엇인가?
Kubernetes(흔히 K8s로 줄여서)는 컨테이너 오케스트레이션을 위한 오픈소스 플랫폼입니다. 간단히 말해, 컨테이너화된 애플리케이션의 배포, 스케일링, 관리를 자동화합니다. Google이 만들고 현재 Cloud Native Computing Foundation (CNCF)이 유지 관리하는 Kubernetes는 대규모 마이크로서비스를 다루는 모든 사람의 필수 도구가 되었습니다.
Kubernetes 클러스터의 아키텍처
Kubernetes 환경은 클러스터라고 합니다. 클러스터는 애플리케이션을 실행하는 노드라고 하는 머신 세트로 구성됩니다. 아키텍처는 Control Plane과 Worker Nodes의 두 주요 부분으로 나뉩니다.
Control Plane
Control Plane은 클러스터의 "두뇌"입니다. 전역 결정(스케줄링 등)을 내리고 클러스터 이벤트를 감지하고 대응합니다. 주요 구성 요소는 다음과 같습니다:
- API Server (
kube-apiserver): 클러스터의 게이트웨이입니다. 사용자(kubectl통해), 클러스터 구성 요소, 외부 도구가 통신하는 데 사용하는 Kubernetes API를 노출합니다. - etcd: 일관되고 고가용성을 갖춘 키-값 데이터베이스입니다. 시스템의 원하는 상태와 현재 상태를 나타내는 모든 클러스터 데이터를 저장합니다.
- Scheduler (
kube-scheduler): 리소스 요구 사항, 정책 및 기타 제약 조건을 고려하여 새로 생성된 Pods를 사용 가능한 Worker Node에 할당합니다. - Controller Manager (
kube-controller-manager): 클러스터의 상태를 감시하고 원하는 상태로 가져오기 위해 작동하는 제어 루프인 컨트롤러를 실행합니다. 예를 들어Node Controller는 노드를 관리하고,Replication Controller는 올바른 수의 Pods가 실행 중인지 확인합니다.
Worker Node
Worker Nodes는 애플리케이션이 실제로 실행되는 머신(물리적 또는 가상)입니다. 각 노드는 Control Plane에 의해 관리되며 다음 구성 요소를 포함합니다:
- Kubelet: 각 노드에서 실행되는 에이전트입니다. Pods에 설명된 컨테이너가 실행 중이고 정상인지 확인합니다.
- Kube-proxy: 노드의 네트워크 규칙을 관리하는 네트워크 프록시입니다. 클러스터 내부 또는 외부 네트워크 세션에서 Pods로의 네트워크 통신을 가능하게 합니다.
- Container Runtime: 컨테이너를 실행하는 소프트웨어입니다. Docker가 가장 유명하지만, Kubernetes는
containerd와CRI-O같은 다른 런타임도 지원합니다.
Kubernetes의 기본 오브젝트
Kubernetes에서 모든 것은 오브젝트로 표현됩니다. 이 오브젝트들은 "의도의 기록"입니다: 오브젝트를 생성하면 Kubernetes는 지속적으로 그것이 존재하고 원하는 상태와 일치하도록 작업합니다.
가장 중요한 것들은 다음과 같습니다:
Pod
Pod는 Kubernetes에서 가장 작은 실행 단위입니다. 동일한 노드에서 함께 실행되는 하나 이상의 컨테이너를 나타내며, 네트워크와 스토리지 같은 리소스를 공유합니다.
일반적으로 Pod당 하나의 컨테이너만 실행하지만, 고급 시나리오(로깅이나 모니터링을 위한 "sidecar containers" 등)에서는 더 많을 수 있습니다.
Pods를 직접 생성하는 경우는 거의 없습니다. Deployments 같은 상위 수준 추상화를 사용합니다.
Deployment
Deployment는 가장 자주 사용하게 될 오브젝트입니다. 동일한 Pods 그룹의 원하는 상태를 설명합니다. Deployment 컨트롤러는 다음을 담당합니다:
- ReplicaSet 생성 및 관리 (Pod의 특정 수의 복제본이 항상 실행되도록 보장하는 또 다른 오브젝트).
- Pods 수를 늘리거나 줄이는 스케일링.
- 다운타임 없이 제어된 방식으로 애플리케이션 업데이트 관리 (예: Rolling Update).
NGINX 서버의 3개 복제본을 실행하는 Deployment를 위한 YAML 파일 예시:
# nginx-deployment.yaml 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:1.14.2 ports: - containerPort: 80
Service
Kubernetes의 Pods는 일시적입니다: 언제든지 생성되고 삭제될 수 있습니다. 각 Pod는 자체 IP 주소를 가지지만, 이 IP는 안정적이지 않습니다. 그렇다면 어떻게 애플리케이션을 안정적으로 노출할까요?
Service를 사용합니다. Service는 Pods의 논리적 세트와 접근 정책을 정의하는 추상화입니다. Pods 그룹에 대한 안정적인 접근 포인트 (가상 IP 주소와 DNS 이름)를 제공합니다.
Service는 labels 기반의 selector를 사용하여 트래픽을 전달할 Pods를 찾습니다.
NGINX Deployment를 위한 Service 생성 방법:
# nginx-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIP # Default - exposes the service only within the cluster
다양한 유형의 Services가 있습니다:
ClusterIP: 클러스터 내부 IP에서 서비스를 노출합니다 (기본값).NodePort: 각 Worker Node의 정적 포트에서 서비스를 노출합니다.LoadBalancer: 클라우드 공급자(예: AWS, GCP)에 외부 로드 밸런서를 생성하고 서비스에 공개 IP를 할당합니다.
Ingress
LoadBalancer Service는 훌륭하지만, 각 서비스마다 하나씩 만드는 것은 비용이 많이 들 수 있습니다. 여러 HTTP/HTTPS 서비스를 외부에 노출하려면 Ingress를 사용합니다.
Ingress는 외부 트래픽을 위한 "지능형 라우터" 역할을 합니다. 호스트(예: api.mysite.com) 또는 경로(예: mysite.com/api)를 기반으로 라우팅 규칙을 정의할 수 있습니다.
Ingress 예시:
# example-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - host: mysite.com http: paths: - path: /api pathType: Prefix backend: service: name: api-service port: number: 8080 - path: /ui pathType: Prefix backend: service: name: ui-service port: number: 3000
기타 유용한 오브젝트
- Namespace: 물리적 클러스터 내에 "가상 클러스터"를 만들 수 있습니다. 환경(예:
development,staging,production) 또는 팀을 격리하는 데 유용합니다. - ConfigMap과 Secret: 컨테이너 이미지와 분리된 구성 데이터와 시크릿(비밀번호나 API 키 등)을 관리합니다.
- StatefulSet: Deployment와 유사하지만, 안정적인 네트워크 ID와 영구 스토리지가 필요한 상태 저장 애플리케이션(데이터베이스 등)에 특화되어 있습니다.
- PersistentVolume (PV)과 PersistentVolumeClaim (PVC): 클러스터의 영구 스토리지를 관리합니다.
결론
Kubernetes는 놀랍도록 강력한 도구이지만, 학습 곡선이 가파를 수 있습니다. 이 가이드는 표면만 훑었지만, 기본 개념에 대한 탄탄한 이해를 제공했기를 바랍니다.
이제 무엇을 할까요?
- 로컬에서 실험하세요: 컴퓨터에 Kubernetes 클러스터를 만들기 위해 Minikube 또는 Kind를 설치하세요.
kubectl사용하기: 클러스터와 상호작용하는 주요 도구인kubectl명령에 익숙해지세요. 이 글의 NGINX Deployment와 Service를 만들어 보세요.- 공식 튜토리얼 탐색하기: Kubernetes 문서는 예제가 가득한 훌륭한 리소스입니다.
컨테이너 오케스트레이션은 클라우드 네이티브 세계에서 필수적인 기술이며, Kubernetes를 마스터하면 무한한 가능성이 열릴 것입니다. 즐기세요!