쿠버네티스 운영 실무 · NetworkPolicy 적용 · 실습
기본 거부에서 시작하는 정책 설계
목표
네임스페이스의 통신 기본값을 거부로 뒤집고, 필요한 경로만 라벨로 골라 여는 정책 세트를 직접 작성합니다.
왜 중요한가
NetworkPolicy 에서 가장 많이 틀리는 것은 문법이 아니라 방향과 결합 방식입니다. 정책은 트래픽을 보내는 쪽이 아니라 받는 쪽에 붙습니다. web 에서 api 로 가는 통신을 허용하려면 정책의 podSelector 가 api 여야 하고, web 은 ingress.from 안에 등장합니다. 또 from 배열의 항목끼리는 OR 이고 한 항목 안의 namespaceSelector 와 podSelector 는 AND 입니다. 하이픈 위치 하나로 "특정 네임스페이스의 특정 파드"가 "그 네임스페이스의 모든 파드 또는 아무 데나 있는 그 파드"로 바뀝니다. 그리고 이그레스를 막을 때는 DNS 예외를 반드시 짝으로 넣으세요. 실제 프로덕션에서 기본 거부만 먼저 넣었다가 이름 해석이 죽어 전체 서비스가 연쇄로 멈춘 사례가 반복해서 보고됩니다. 이 랩의 클러스터는 파드 간 실제 패킷이 흐르지 않으므로 채점은 정책 오브젝트의 내용과 셀렉터 의미로 이루어집니다. 문법과 사고방식을 여기서 굳히고, 실제 차단 확인은 CNI 가 있는 환경에서 하면 됩니다.
단계
1. 네임스페이스 netpol-lab 을 만들고 /opt/lab/fixtures/k8s/workloads.yaml 을 그 안에 적용하세요. 결과로 web, api, db 세 파드가 각각 자기 이름과 같은 app 라벨을 갖고, api 파드는 추가로 tier=backend 라벨을 가져야 합니다.
2. netpol-lab 에 NetworkPolicy default-deny-ingress 를 만드세요. podSelector 는 빈 객체 {} 이고 policyTypes 는 Ingress 하나만이며 ingress 규칙은 하나도 없어야 합니다.
3. NetworkPolicy allow-web-to-api 를 만드세요. podSelector.matchLabels.app 은 api, ingress[0].from[0] 은 podSelector.matchLabels.app: web 하나만 갖습니다(같은 항목에 namespaceSelector 를 넣지 마세요). 허용 포트는 TCP 8080 입니다.
4. NetworkPolicy default-deny-egress 를 만드세요. policyTypes 는 Egress 하나만입니다. 이어서 allow-dns-egress 를 만들되 egress[0].to[0].namespaceSelector.matchLabels 에 kubernetes.io/metadata.name: kube-system 을 쓰고, egress[0].ports 에는 포트 53 을 UDP 와 TCP 두 항목으로 넣으세요.
5. 네임스페이스 monitoring 을 만들고 라벨 purpose=monitoring 을 붙이세요. 그다음 netpol-lab 에 NetworkPolicy allow-from-monitoring 을 만드세요. podSelector.matchLabels.app 은 api, ingress[0].from[0].namespaceSelector.matchLabels.purpose 는 monitoring, 허용 포트는 9090 입니다.
6. NetworkPolicy allow-office-cidr 을 만드세요. podSelector.matchLabels.app 은 web 이고, ingress[0].from[0].ipBlock.cidr 은 10.0.0.0/16, except 는 10.0.5.0/24 하나입니다.
7. NetworkPolicy api-full 을 만드세요. podSelector.matchLabels.app 은 api, policyTypes 는 Ingress 와 Egress 둘 다입니다. ingress[0].from 에는 항목이 2개 이상(예: web 파드와 monitoring 네임스페이스) 들어가야 하고, egress[0].to[0] 은 podSelector.matchLabels.app: db, 허용 포트는 5432 입니다.
8. /root/ops/netpol/out/policy-map.json 을 만드세요. 최상위 키는 web, api, db 세 개이고 각 값은 그 파드를 고르는 정책 이름의 배열입니다. 빈 셀렉터를 가진 정책은 세 파드 모두에 들어가야 하고, allow-web-to-api 는 api 에만 들어가야 합니다(web 이나 db 에 넣으면 안 됩니다). allow-office-cidr 은 web 에, api-full 은 api 에 들어갑니다. 최종적으로 netpol-lab 의 NetworkPolicy 는 6개 이상이어야 합니다.
참고
- 픽스처는
kubectl apply -f /opt/lab/fixtures/k8s/workloads.yaml -n netpol-lab으로 올립니다. 픽스처 파일 자체를 고치지 마세요. kubernetes.io/metadata.name은 쿠버네티스가 모든 네임스페이스에 자동으로 붙여 주는 라벨이라 별도 라벨링 없이 네임스페이스를 고를 수 있습니다. 반대로purpose=monitoring처럼 직접 정한 라벨은 네임스페이스에 실제로 붙여야 합니다.- 정책 내용 확인은
kubectl get netpol <이름> -n netpol-lab -o yaml이 가장 빠릅니다.kubectl apply --dry-run=client로 오타를 미리 거르세요. - 흔한 실수 1: 3번에서
podSelector를 web 으로 잡는 것. 정책은 받는 쪽에 붙습니다. - 흔한 실수 2: 4번에서 DNS 를 UDP 만 여는 것. 응답이 크면 TCP 53 으로 넘어갑니다.
- 흔한 실수 3: 7번에서
from항목 하나 안에 두 셀렉터를 넣는 것. 그것은 OR 이 아니라 AND 가 되어 훨씬 좁은 규칙이 됩니다. - 실습 파드는 실습마다 새로 뜨므로 앞 실습에서 만든 클러스터 상태는 남아 있지 않습니다. 네임스페이스와 파드는 이 실습 안에서 직접 만드세요. 운영 절차를 기억이 아니라 런북과 매니페스트로 남겨야 하는 이유가 바로 이것입니다.
단계 8개
- 실습용 네임스페이스와 라벨 붙은 파드 만들기
- 인그레스 기본 거부 정책 만들기
- web 에서 api 로 가는 포트만 열기
- 이그레스 기본 거부와 DNS 예외
- 다른 네임스페이스에서 오는 트래픽 허용하기
- IP 대역 허용과 예외 지정하기
- 인그레스와 이그레스를 한 정책에 담기
- 파드별 적용 정책 지도 만들기