Kubernetes는 컨테이너회된 애플리케이션의 배포, 관리 및 확장을 자동화하는 오픈소스 플랫폼이다. Kubernetes 클러스터의 주요 구성 요소들을 하나씩 확인해보고, 애플리케이션 배포부터 워크로드 관리, 라우팅, 설정 관리 그리고 논리적 분리까지 전반적인 과정을 알아본다
Pod: 애플리케이션의 최소 배포 단위
Kubernetes에서 가장 기본적인 배포 단위는 Pod이다. Pod는 하나 이상의 컨테이너(일반적으로 하나의 컨테이너)를 포함하며, 이 컨테이너 안에서 Spring 서버와 같은 실제 애플리케이션이 실행된다. Pod는 실제 워커 노드(물리적 또는 가상 서버)에서 실행되는 유일한 물리적 서버 공간이다
Deployment: Pod의 선언적 관리 및 무중단 배포
Pod를 개별적으로 관리하는 것은 비효율적이며, 서비스의 안정성을 보장하기 어렵다. Deployment는 Pod를 선언적으로 관리하고 무중단 배포를 가능하게 하는 Kubernetes 리소스이다
- 선언적 관리: Deployment는 특정 개수의 Pod 복제본을 항상 유지하도록 선언할 수 있다. 예를 들어, Pod 3개를 지정하면 Kubernetes는 항상 3개의 Pod가 실행되도록 보장한다
- 자동 복구: 만약 Pod가 어떤 이유로든 중단되거나 삭제되면, Deployment는 이를 감지하고 자동으로 새로운 Pod를 생성하여 선언된 개수를 유지한다. 이는 서비스의 안정성을 크게 높여준다
- 롤링 업데이트 (무중단 배포): 새로운 버전의 애플리케이션을 배포할 때, Deployment는 기존 서비스를 중단시키지 않고 업데이트를 수행하는 롤링 업데이트 기능을 제공한다. 새로운 Pod를 먼저 띄워 정상 작동을 확인한 후, 기존 Pod의 트래픽을 전환하고 점진적으로 종료하여 사용자 입장에서는 서비스 중단을 전혀 느끼지 못하게 한다
- 롤백: 새로운 버전 배포 후 문제가 발생했을 경우, Deployment는 빠르고 쉽게 이전 버전을 되돌릴 수 있는 롤백 기능을 지원한다
- 오토스케일링: Deployment는 Horizontal Pod Autoscaler(HPA)와 연동하여 Pod의 CPU, 메모리 사용량 등의 메트릭을 모니터링하고 부하 상황에 따라 Pod의 수를 자동으로 증설하거나 감소시킬 수 있다
Deployment의 핵심 기능은 ReplicaSet에 기반하며, ReplicaSet은 지정된 수의 Pod 복제본이 항상 실행되도록 보장하는 역할을 한다. Deployment는 ReplicaSet 위에 롤링 업데이트, 롤백, 오토스케일링과 같은 고급 기능을 추가로 제공한다
Service: 내부 트래픽 라우팅 및 로드 밸런싱 (서비스 디스커버리)
사용자나 다른 애플리케이션이 여러 Pod로 구성된 애플리케이션에 접근할 때, 개별 Pod의 IP 주소와 포트를 직접 바라보는 것은 비효율적이다. Service는 이러한 문제를 해결하기 위해 Pod 그룹에 대한 단일하고 안정적인 엔드포인트를 제공하며, 라우팅 및 로드 밸런싱 역할을 수행한다
- 서비스 디스커버리: Service는 클러스터 내부에서 다른 Pod들이 특정 애플리케이션(예: 주문 서비스)의 위치를 “발견”할 수 있도록 해주는 기능을 제공한다. 예를 들어, 회원 서비스가 주문 서비스로 요청을 보낼 때, 주문 Service의 이름을 통해 주문 서버에 접근할 수 있다
- 로드 밸런싱: 사용자 또는 다른 Pod로부터 요청이 들어오면, Service는 자신이 관리하는 여러 Pod 중 하나로 요청을 분산하여 부하를 고르게 나눠준다
- Service 타입
- Cluster IP (기본): 클러스터 내부에서만 접근 가능한 IP를 할당하여 주로 내부 통신(서버 간 통신)에 사용된다. 보안 및 자원 효율성을 위해 이 타입을 사용하는 것이 권장된다
- NodePort, LoadBalancer: 외부에서 Service로 직접 접근할 수 있도록 해주는 타입으로 AWS Load Balancer와 같은 클라우드 자원과의 연동이 필요할 수 있다
Ingress: 외부 요청을 클러스터 내부 Service로 라우팅
Service가 주로 클러스터 내부 통신을 위해 설계된다면, Ingress는 클러스터 외부에서 들어오는 HTTP/HTTPS 요청을 클러스터 내부의 Service로 라우팅하는 역할을 한다
- 단일 진입점: Ingress는 클러스터의 단일 외부 진입점을 제공하고 URL 경로(예: /order-service, /member-service) 또는 호스트(서브 도메인) 규칙을 기반으로 요청을 적절한 Service로 라우팅한다
- 로그 밸런서 통합: Ingress 자체는 엔드포인트를 만들지 못하며, AWS Load Balancer와 같은 외부 로드 밸런서와 연동하여 단일 로드 밸런서를 통해 여러 Service로 트래픽을 분산한다. 이를 통해 각 Service마다 별도의 로드 밸런서를 생성하는 비효율을 방지하고 비용을 절감할 수 있다
ConfigMap & Secret: 환경 설정 및 민감 정보 관리
애플리케이션이 실행되는 데 필요한 설정 정보나 민감한 데이터(예: 데이터베이스 비밀번호, API 키)는 소스코드에 직접 포함하지 않고 Kubernetes 내부에 안전하게 저장하고 관리해야 한다
- ConfigMap: 민감하지 않은 일반 설정 정보(key-value)를 저장하는 데 사용된다
- Secret: 데이터베이스 비밀번호, API 토큰, 인증서와 같은 민감한 정보를 저장하는 데 사용된다. Secret에 저장된 데이터는 자동으로 Base64로 인코딩되어 저장되며, Pod에 마운트되거나 환경 변수로 주입될 수 있다. 이를 통해 소스코드 노출 없이 안전하게 정보를 관리할 수 있다
Namespace: 클러스터 리소스의 논리적 구분
Namespace는 Kubernetes 클러스터 내의 리소스를 논리적으로 분리하는 단위이다
- 논리적 구분: 하나의 물리적 클러스터 내에서 개발(dev), 운영(prod), 테스트(test)와 같은 여러 환경을 논리적으로 분리하여 관리할 수 있다
- 자원 격리: 각 Namespace는 독립적은 리소스 집합을 가지므로, 서로 다른 환경의 Pod, Service 등이 출동하지 않도록 격리된다
- 워커 노드와 독립적: Namespace는 워커 노드의 물리적 구분을 의미하는 것이 아니다. 예를 들어, 두 개의 워커 노드에 dev 및 prod Namespaced의 Pod가 모두 배포될 수 있으며, Kubernetes는 Namespace에 선언된 Pod들을 적절한 워커 노드에 분산하여 배포한다
Kubernetes 리소스의 위치 (컨트롤 플레인 vs 워커 노드)
Namespace 클러스터는 크게 컨트롤 플레인과 워커 노드로 구성된다
- 컨트롤 플레인: Namespace 클러스터를 관리하고 제어하는 두외 역할을 한다. Deployment, Service, Ingress, ConfigMap, Secret, Namespace와 같은 Kubernetes 자원들은 컨트롤 플레인에 정의되고 관리된다. 이들 리소스는 특정 워커 노드에 종속되지 않고 클러스터 전체에 적용되는 개념이다
- 워커 노드: 실제 애플리케이션 컨테이너(Pod)가 실행되는 물리적 또는 가상 머신이다. Pod는 워커 노드에서 실행되는 유일한 물리적인 서버 공간이다
장점: 워커 노드가 삭제되더라도 컨트롤 플레인에 정의된 Deployment, Service 등의 리소스는 그대로 유지된다. 따라서 새로운 워커 노드를 추가하기만 하면 Deployment가 자동으로 Pod를 재생성하고, Service가 다시 라우팅을 설정하는 등 클러스터를 쉽게 복구하고 유연하게 확장할 수 있다
Kubernetes의 특징 및 장점 요약
- 자동 복구: 중단된 컨테이너(Pod)를 자동으로 재시작한다
- 서비스 디스커버리 및 로드 밸런싱: Service를 통해 애플리케이션 간 통신 및 외부 트래픽 분산을 용이하게 한다
- 멀티 환경 지원 (네임스페이스): 개발, 운영, 테스트 환경을 논리적으로 분리하여 효율적으로 관리를 가능하게 한다
- 오토스케일링
- Horizontal Pod Autoscaler (HPA): Pod의 자원 사용량(CPU, 메모리)에 따라 Pod 수를 자동으로 증설 / 감소시킨다
- Cluster Autoscaler: 노드의 자원이 부족해지면 자동으로 인스턴스(워커 노드)를 증설 / 감소시킨다
- 자동화된 롤아웃/롤백 (무중단 배포): Deployment를 통해 서비스 중단 없이 애플리케이션을 업데이트하고 문제가 발생 시 이전 버전으로 쉽게 되돌릴 수 있다
- 자원 제한: Pod 별로 CPU, 메모리 등의 자원 사용량을 제한하여 안정적인 운영을 보장한다