CKAD — 쿠버네티스 애플리케이션 개발자 · 서비스와 네트워킹 · 실습
Service, Ingress, NetworkPolicy
목표
Service 의 포트 세 종류를 구분해서 지정하고, named port·헤드리스·StatefulSet DNS·Ingress 라우팅·NetworkPolicy 화이트리스트를 매니페스트로 작성할 수 있게 된다.
왜 중요한가
Service 에서 나오는 실수는 거의 전부 두 가지다. 셀렉터가 파드 라벨과 다른 것과 포트 세 개를 헷갈리는 것. 셀렉터가 어긋나면 오류 없이 엔드포인트가 비고, 클라이언트는 연결 거부만 본다. kubectl get endpoints 가 비어 있는지 확인하는 습관 하나로 대부분의 시간을 아낀다.
포트는 방향으로 외우면 헷갈리지 않는다. port 는 들어오는 쪽(클라이언트가 Service 에 붙는 포트), targetPort 는 나가는 쪽(Service 가 파드에 붙는 포트), nodePort 는 바깥에서 들어오는 쪽(노드에서 여는 포트)이다.
헤드리스 Service 는 로드밸런싱을 포기하는 선택이다. 가상 IP 를 만들지 않고 DNS 가 파드 IP 목록을 그대로 돌려주며, StatefulSet 과 짝지으면 파드마다 고유 이름이 생긴다. 클라이언트가 특정 인스턴스를 지목해야 하는 워크로드(DB 프라이머리, 샤드)에 쓴다.
NetworkPolicy 는 기본 허용, 정책이 붙으면 화이트리스트라는 두 문장으로 요약된다. 그래서 실무에서는 먼저 네임스페이스 전체에 기본 차단을 걸고 필요한 통신만 열어 준다. 정책들은 서로를 덮어쓰지 않고 합집합으로 더해진다는 점도 기억한다.
단계
1. 네임스페이스 ckad-net 을 만든다. Deployment frontend(레플리카 2, 라벨 app=frontend, 이미지 nginx:1.27, 컨테이너 포트 80 에 이름 http)와 Service frontend(ClusterIP, port: 80, targetPort: 80, 셀렉터 app=frontend)를 만든다.
2. Deployment backend(레플리카 2, 라벨 app=backend, 이미지 nginx:1.27, 컨테이너 포트 8080 에 이름 api)와 Service backend(ClusterIP, port: 80, targetPort: api — 이름으로, 셀렉터 app=backend)를 만든다.
3. Service frontend-np 를 만든다. 타입 NodePort, port: 80, targetPort: 80, nodePort: 30080, 셀렉터 app=frontend.
4. 헤드리스 Service cache-hs(clusterIP: None, port: 6379, 셀렉터 app=cache)와 StatefulSet cache(레플리카 3, serviceName: cache-hs, 라벨 app=cache, 이미지 nginx:1.27)를 만든다. 그리고 0번 파드의 완전한 DNS 이름을 /root/ckad-net/dns.txt 에 한 줄로 적는다.
5. Ingress shop 을 만든다. ingressClassName: nginx, 호스트 shop.ckad.local, 경로 / (pathType Prefix) → Service frontend 포트 80, 경로 /api (pathType Prefix) → Service backend 포트 80.
6. NetworkPolicy backend-allow-frontend 를 만든다. 대상은 app=backend 파드, policyTypes: [Ingress], 허용 출발지는 app=frontend 파드, 포트는 TCP 8080.
7. NetworkPolicy default-deny-ingress 를 만든다. podSelector: {} (네임스페이스 전체), policyTypes: [Ingress], ingress 규칙은 비워 둔다. 이 시점에 Service backend 의 셀렉터가 실제로 파드 2개 이상을 고르는지 kubectl get pods -n ckad-net -l app=backend 로 확인한다.
참고
kubectl create deployment frontend --image=nginx:1.27 --replicas=2 -n ckad-net --dry-run=client -o yaml로 뼈대를 뽑고ports에 이름을 붙인다.kubectl expose deployment frontend --port=80 --target-port=80 -n ckad-net은 셀렉터를 자동으로 채워 준다.- 4단계 DNS 이름 형식:
<파드이름>.<서비스이름>.<네임스페이스>.svc.cluster.local - 흔한 실수 1: NetworkPolicy 에서
podSelector(적용 대상)와from[].podSelector(허용 출발지)를 바꿔 쓰는 것. - 흔한 실수 2:
nodePort를 30000 미만으로 지정하는 것. 기본 허용 범위는 30000~32767 이다. - 흔한 실수 3:
targetPort에 이름을 쓸 때 Service 가 아니라 컨테이너의 포트 이름을 써야 한다는 것. - 이 환경에는 Ingress 컨트롤러와 실제 CNI 데이터플레인이 없으므로 라우팅과 정책이 실제로 동작하는지는 확인할 수 없다. 오브젝트를 정확히 쓰는 것이 목표다.
단계 7개
- Deployment 와 ClusterIP Service
- named port 로 targetPort 연결
- NodePort 로 바깥에 열기
- 헤드리스 Service 와 StatefulSet
- Ingress 로 호스트와 경로 라우팅
- NetworkPolicy 로 프런트엔드만 허용
- 기본 차단 정책과 셀렉터 점검 (종합)