소개
Pod 는 일시적인 존재입니다. Deployment 는 롤아웃, 재시작 또는 스케일링 과정에서 Pod 를 교체할 수 있으므로, 클라이언트는 개별 Pod 의 IP 에 직접 연결해서는 안 됩니다. Service 는 클라이언트에게 안정적인 이름과 가상 IP 를 제공하며, 레이블을 사용하여 트래픽을 현재 일치하는 Pod 로 라우팅합니다.
이 실습에서는 간단한 웹 Deployment 를 생성하고, ClusterIP Service 로 노출하며, Service 가 백엔드 Pod 를 선택하는 방식을 확인하고, 클라이언트 Pod 에서 Service 를 테스트한 뒤, Deployment 를 스케일링하여 Service 엔드포인트가 업데이트되는 과정을 살펴봅니다.
웹 Deployment 생성
이 단계에서는 네임스페이스를 준비하고, 나중에 Service 로 노출할 수 있는 Deployment 를 생성합니다.
/home/labex/project에서 시작합니다:
mkdir -p /home/labex/project
cd /home/labex/project
Kubernetes API 서버에 연결할 수 있는지 확인합니다. VM 이 막 시작되어 노드가 아직 준비되지 않았다면, 몇 초 기다린 후 명령어를 다시 실행하세요.
kubectl get nodes --request-timeout=5s
예상 출력은 다음과 같습니다:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
클러스터 네트워킹 Pod 가 준비 (Ready) 상태가 될 때까지 기다립니다. 이 실습에서는 Service 를 통해 Pod 간 트래픽을 전송하므로, 접근을 테스트하기 전에 클러스터 네트워킹이 정상 상태여야 합니다.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
예상 출력:
pod/calico-node-... condition met
ckad-prep-service라는 이름의 네임스페이스를 생성하고 현재 네임스페이스로 설정합니다:
kubectl create namespace ckad-prep-service
kubectl config set-context --current --namespace=ckad-prep-service
하나의 NGINX Pod 를 포함하는 web-front라는 이름의 Deployment 를 생성합니다. --port=80 플래그는 Pod 템플릿에 컨테이너 포트를 기록하는 역할을 합니다. 이 명령어 자체가 Service 를 생성하지는 않습니다.
kubectl create deployment web-front --image=nginx:1.25 --port=80
Deployment 가 사용 가능해질 때까지 기다린 후, Pod 레이블을 확인합니다. app=web-front 레이블은 Service 가 백엔드 Pod 를 찾는 데 사용되므로 중요합니다.
kubectl rollout status deployment/web-front --timeout=120s
kubectl get pods -l app=web-front --show-labels
예상 출력은 다음과 같습니다:
deployment "web-front" successfully rolled out
NAME READY STATUS RESTARTS AGE LABELS
web-front-... 1/1 Running 0 ... app=web-front,...
ClusterIP Service 로 Deployment 노출
이 단계에서는 Deployment 를 위한 Service 를 생성하고, Service 와 Pod 를 연결하는 필드들을 확인합니다.
kubectl expose deployment를 사용하여 ClusterIP Service 를 생성합니다. Service 포트는 80이며, --target-port=80은 일치하는 Pod 의 80번 포트로 트래픽을 전달하도록 Service 에 지시합니다.
kubectl expose deployment web-front --name=web-front --port=80 --target-port=80
예상 출력:
service/web-front exposed
Service 를 확인합니다:
kubectl get service web-front
예상 출력은 다음과 같습니다:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web-front ClusterIP ... <none> 80/TCP ...
이제 Service 셀렉터와 포트 매핑을 확인합니다. 셀렉터는 Service 가 Pod 를 찾는 방법이며, 포트 매핑은 클라이언트 트래픽이 컨테이너에 도달하는 방법입니다.
kubectl get service web-front -o jsonpath='{.spec.selector.app}{" "}{.spec.ports[0].port}{":"}{.spec.ports[0].targetPort}{"\n"}'
예상 출력:
web-front 80:80
Kubernetes 는 선택된 백엔드 주소를 EndpointSlice 에 저장합니다. 이 Service 를 위해 생성된 EndpointSlice 를 나열합니다:
kubectl get endpointslice -l kubernetes.io/service-name=web-front
예상 출력은 다음과 같습니다:
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
web-front-... IPv4 80 ... ...
클러스터 내부에서 Service 테스트
이 단계에서는 임시 클라이언트 Pod 를 생성하고 Service 에 HTTP 요청을 보냅니다. ClusterIP Service 는 클러스터 내부 접근을 위한 것이므로, 다른 Pod 에서 테스트하는 것이 가장 직접적인 검증 방법입니다.
실행 상태를 유지하는 클라이언트 Pod 를 생성합니다:
kubectl run service-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
클라이언트 Pod 가 준비될 때까지 기다립니다:
kubectl wait --for=condition=Ready pod/service-client --timeout=120s
예상 출력:
pod/service-client condition met
클라이언트 Pod 내부에서 wget을 사용하여 http://web-front에 요청을 보냅니다. web-front라는 이름은 네임스페이스 내부에서 Service 로 해석됩니다.
kubectl exec service-client -- wget -qO- http://web-front | head -n 5
예상 출력에는 기본 NGINX 페이지의 시작 부분이 포함됩니다:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
이는 클라이언트가 안정적인 Service 이름에 도달했으며, Service 가 트래픽을 현재 백엔드 Pod 로 성공적으로 전달했음을 증명합니다.
백엔드 스케일링 및 엔드포인트 재확인
이 단계에서는 Deployment 를 스케일링하고, 백엔드 엔드포인트가 변경되어도 Service 는 동일한 안정적인 진입점을 유지하는지 확인합니다.
Deployment 를 2 개의 레플리카로 스케일링합니다:
kubectl scale deployment web-front --replicas=2
kubectl rollout status deployment/web-front --timeout=120s
예상 출력은 다음과 같습니다:
deployment.apps/web-front scaled
deployment "web-front" successfully rolled out
Pod 를 나열합니다. 이제 동일한 app=web-front 레이블을 가진 2 개의 실행 중인 백엔드 Pod 가 있어야 합니다.
kubectl get pods -l app=web-front
예상 출력에는 2 개의 Pod 가 포함됩니다:
NAME READY STATUS RESTARTS AGE
web-front-... 1/1 Running 0 ...
web-front-... 1/1 Running 0 ...
Service 뒤에 있는 엔드포인트 개수를 셉니다. 이 명령어는 각 엔드포인트 주소마다 한 줄씩 출력한 뒤 줄 수를 셉니다.
kubectl get endpointslice -l kubernetes.io/service-name=web-front -o jsonpath='{range .items[*].endpoints[*]}{.addresses[0]}{"\n"}{end}' | wc -l
예상 출력:
2
동일한 클라이언트 Pod 에서 Service 에 다시 요청을 보냅니다:
kubectl exec service-client -- wget -qO- http://web-front | grep '<title>Welcome to nginx'
예상 출력:
<title>Welcome to nginx!</title>
요약
ClusterIP Service 를 사용하여 Deployment 를 노출하고 전체 클러스터 내부 접근 경로를 검증했습니다. 백엔드 Deployment 를 생성하고, 셀렉터와 포트 매핑이 포함된 Service 를 만들었으며, Service 를 위해 생성된 EndpointSlice 를 확인하고, 클라이언트 Pod 에서 접근을 테스트한 뒤, Deployment 를 스케일링하여 Service 가 업데이트된 백엔드 세트로 계속 라우팅하는 것을 확인했습니다.


