마루옵스서버 · 네트워크 · AI 기술 노트

소개문의

[쿠버네티스 학습 06] Service·DNS와 Windows에서의 접속 경로

두 개의 케이블이 연결된 소형 네트워크 스위치

참고 사진 · 두 개의 케이블이 연결된 소형 네트워크 스위치 · 사진: Simon A. Eugster / 원본 / CC BY-SA 3.0 · 목록용 크기 조정

전체 연재 안내 · 실습 파일 ZIP

Windows 11 · VMware · Rocky Linux Kubernetes 연재 06/10

Pod가 교체돼도 같은 주소로 웹 서버에 접속하려면 Service가 필요합니다. Windows에서 받은 요청이 어느 포트를 거쳐 Pod까지 가는지 따라가 볼게요. 이 예제의 경로는 Windows → 노드:30080 → Service → 준비된 Pod:8080입니다.

1. Service selector와 포트

cp01의 ~/k8s-lab/app에 web-service.yaml로 저장합니다. Service selector와 앞서 만든 Pod 레이블이 같은 app: web인지 확인합니다.

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: lab
spec:
  type: NodePort
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: http
      nodePort: 30080
kubectl apply -f web-service.yaml
kubectl -n lab get service web
kubectl -n lab get endpointslice -l kubernetes.io/service-name=web -o wide

Service의 port: 80, Pod의 이름 있는 포트를 가리키는 targetPort: http, 노드의 nodePort: 30080을 나눠 봅니다. targetPort가 가리키는 Pod 포트는 8080입니다. containerPort만 선언해서는 Service나 호스트 포트가 자동으로 열리지 않습니다.

2. Windows·Pod에서 접속

Test-NetConnection 192.168.80.11 -Port 30080
curl.exe http://192.168.80.11:30080/

Windows에서 http://192.168.80.11:30080/을 열어 기본 페이지를 확인합니다. VMnet8 어댑터로 노드에 직접 접근하는 경로예요. 기본 NodePort 동작에서는 wk01에 들어온 요청도 준비된 다른 워커의 Pod로 전달될 수 있습니다. 노드와 네트워크, 전달 대상이 모두 정상이어야 합니다.

kubectl -n lab run netcheck --image=busybox:1.37.0 \
  --restart=Never --command -- sleep 3600
kubectl -n lab wait --for=condition=Ready pod/netcheck --timeout=120s
kubectl -n lab exec netcheck -- nslookup web.lab.svc.cluster.local
kubectl -n lab exec netcheck -- wget -qO- http://web.lab.svc.cluster.local/

Pod의 DNS 질의는 CoreDNS를 거쳐 보통 Service의 ClusterIP를 얻습니다. ClusterIP를 물리 NIC의 일반 IP처럼 생각하면 경로가 헷갈릴 수 있어요. 이번 iptables 모드에서는 kube-proxy가 만든 커널 규칙과 연결 추적이 전달을 처리합니다. 같은 TCP 연결이 같은 백엔드에 유지될 수 있으므로 요청마다 두 Pod가 엄격히 번갈아 응답한다고 보장하지 않습니다.

3. ConfigMap 볼륨

cd ~/k8s-lab/app
cat > index.html <<'EOF'
<!doctype html>
<html lang="ko"><meta charset="utf-8">
<title>MaruOps Kubernetes Lab</title>
<h1>Windows에서 Kubernetes Pod까지 연결됐습니다.</h1>
<p>이 페이지는 ConfigMap 볼륨에서 읽습니다.</p></html>
EOF
kubectl -n lab create configmap web-content --from-file=index.html \
  --dry-run=client -o yaml > web-configmap.yaml
kubectl apply -f web-configmap.yaml

기존 web-deployment.yaml에 아래 조각을 합칩니다. containers와 같은 깊이의 spec.template.spec에 volumes를, nginx 컨테이너 안에 volumeMounts를 추가합니다. 이 조각만 따로 리소스로 apply하지 않습니다.

# spec.template.spec 아래
volumes:
  - name: web-content
    configMap:
      name: web-content
# nginx 컨테이너 항목 아래, resources와 같은 깊이
volumeMounts:
  - name: web-content
    mountPath: /usr/share/nginx/html
    readOnly: true
kubectl apply --dry-run=server -f web-deployment.yaml
kubectl apply -f web-deployment.yaml
kubectl -n lab rollout status deployment/web --timeout=180s
kubectl -n lab exec netcheck -- wget -qO- http://web/

ConfigMap을 바꾸면 생성·apply 명령을 다시 실행합니다. 디렉터리 마운트의 갱신에는 kubelet 동기화 시간이 걸릴 수 있습니다. subPath 마운트는 같은 자동 갱신을 기대할 수 없고 환경변수도 실행 중 프로세스에 새로 주입되지 않습니다. 앱이 파일을 언제 읽는지에 따라 재시작 필요 여부도 확인합니다.

4. Secret의 보호 범위

일반 설정은 ConfigMap, 접근을 제한할 자격증명은 Secret으로 구분합니다. Secret의 base64는 암호화가 아니므로 RBAC와 etcd 저장 암호화, 백업 권한도 필요합니다. 예제에서는 실제 비밀번호를 사용하지 않습니다. Secret을 NGINX의 HTML 디렉터리에 마운트하면 웹에 노출될 수 있으니 그 위치에 두지 않습니다.

5. 요청 경로별 장애 확인

증상다음에 볼 것
Windows에서 노드 IP도 안 됨VMnet8 연결·Windows 경로·게스트 IP
NodePort 연결 실패Service 타입·포트 충돌·호스트 경로
Service는 있지만 응답 안 옴EndpointSlice에 준비된 주소가 있는지
Pod IP로는 되는데 Service로 안 됨kube-proxy·규칙·Service 포트
IP는 되는데 이름이 안 풀림CoreDNS·Pod resolv.conf·DNS 통신
kubectl -n lab get pods --show-labels
kubectl -n lab describe service web
kubectl -n lab get endpointslice -l kubernetes.io/service-name=web -o yaml
kubectl -n lab delete pod netcheck

ConfigMap은 배포할 설정을 전달하는 데 사용합니다. 사용자가 쓴 데이터를 남기는 일은 볼륨의 역할이에요. 다음 글에서 Pod를 다시 만든 뒤에도 같은 파일을 읽는 구성을 다룹니다.

참고 자료

공식 문서와 배포 파일 확인 기준: 2026년 10월 18일. 출력은 완료 여부를 판단하기 위한 예시이며 환경별로 달라질 수 있습니다.


← 05편 · 07편 →

전체 10편 목차 펼치기

전체 연재 안내와 실습 기준

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

닉네임·이메일·댓글 내용·IP 주소·브라우저 정보는 댓글 게시 및 관리에 사용됩니다. 이메일과 접속 정보는 공개 댓글에 표시하지 않습니다. 개인정보 요청은 운영자 이메일로 보내 주세요. 개인정보처리방침