ネットワークポリシーで通路を狭める
한국어 원문으로 표시합니다.
목표
NetworkPolicy 를 기본 거부에서 시작해 여섯 가지 형태로 좁혀 가며, 특히 from 항목의 AND/OR 구조를 손으로 구분합니다.
왜 중요한가
먼저 분명히 해 둡니다. 이 실습 환경에는 정책을 집행할 CNI 데이터플레인이 없습니다. 그래서 실제로 트래픽이 막히는지는 확인할 수 없고, 채점은 오브젝트 스펙만 봅니다. 이 제약은 오히려 시험과 닮았습니다. CKA 에서도 대부분 매니페스트가 정확한지를 봅니다.
NetworkPolicy 의 사고 방식은 방화벽과 다릅니다. 정책이 하나라도 어떤 파드를 고르는 순간, 그 파드의 해당 방향(Ingress/Egress) 트래픽은 기본 거부로 바뀌고 정책들이 허용한 것만 통과합니다. 정책은 서로 더해질 뿐 거부 규칙은 존재하지 않습니다. 그래서 "기본 거부 정책 하나 + 필요한 만큼의 허용 정책" 이 표준 패턴입니다.
egress 를 막을 때 DNS 를 함께 막아 버리는 사고도 흔합니다. 파드가 서비스 이름을 못 풀면 증상이 네트워크 차단이 아니라 애플리케이션 타임아웃으로 나타나 진단이 오래 걸립니다.
단계
- 네임스페이스
cka-netpol(라벨tier=app)과cka-netpol-client(라벨tier=client)를 만든다.cka-netpol에 Deploymentweb(레플리카 2, 이미지nginx:1.27, 파드 라벨app=web)을 만든다. cka-netpol에 NetworkPolicydefault-deny-ingress를 만든다. podSelector 는 빈 오브젝트, policyTypes 는[Ingress], ingress 규칙은 없다.- NetworkPolicy
allow-frontend를 만든다. podSelectorapp=web, ingress 의 from 은 podSelectorapp=frontend하나만, 포트는 TCP 80. - NetworkPolicy
allow-client-ns를 만든다. podSelectorapp=web, ingress 의 from 은 namespaceSelectortier=client하나만 (podSelector 를 함께 넣지 않는다). - NetworkPolicy
egress-dns-only를 만든다. podSelectorapp=web, policyTypes 는[Egress], egress 의 to 는 namespaceSelectorkubernetes.io/metadata.name=kube-system, 포트는 UDP 53 과 TCP 53 두 개. - NetworkPolicy
allow-cidr을 만든다. podSelectorapp=web, ingress 의 from 은 ipBlock cidr10.0.0.0/16이고 except 에10.0.5.0/24. - NetworkPolicy
web-final을 만든다. podSelectorapp=web, policyTypes 는[Ingress, Egress]. ingress 의 from 은 항목 하나 안에 namespaceSelectortier=client와 podSelectorapp=frontend를 함께 두고 포트는 TCP 8080. egress 의 to 는 ipBlock cidr0.0.0.0/0에 except169.254.169.254/32, 포트는 TCP 443.
참고
- 모든 네임스페이스에는
kubernetes.io/metadata.name라벨이 자동으로 붙습니다. kube-system 을 고를 때 유용합니다. kubectl get netpol <이름> -n cka-netpol -o yaml로 저장된 형태를 다시 읽어 보면 AND/OR 구조가 눈에 들어옵니다.- 흔한 실수 1: 7단계에서 from 을 두 항목으로 나누는 것. 그러면 OR 이 되어 client 네임스페이스의 모든 파드가 뚫립니다.
- 흔한 실수 2:
169.254.169.254/32를 except 가 아니라 별도 to 항목으로 적는 것. except 는 ipBlock 안에 들어갑니다.
대상과 출발지 준비하기
네임스페이스 cka-netpol (라벨 tier=app)과 cka-netpol-client (라벨 tier=client)를 만든다. cka-netpol 에 Deployment web (레플리카 2, 이미지 nginx:1.27, 파드 라벨 app=web)을 만든다.
네임스페이스 라벨은 나중에 namespaceSelector 가 고를 열쇠입니다. 파드 라벨도 정확히 맞춰 두세요.
기본 거부 정책
cka-netpol 에 NetworkPolicy default-deny-ingress 를 만든다. podSelector 는 빈 오브젝트, policyTypes 는 [Ingress], ingress 규칙은 없다.
podSelector 를 빈 오브젝트로 두면 그 네임스페이스의 모든 파드가 대상입니다. 규칙을 하나도 쓰지 않으면 전부 거부라는 뜻이 됩니다.
같은 네임스페이스의 파드만 허용
NetworkPolicy allow-frontend 를 만든다. podSelector app=web, ingress 의 from 은 podSelector app=frontend 하나만, 포트는 TCP 80.
from 항목에 podSelector 만 쓰면 정책이 있는 네임스페이스 안으로 범위가 한정됩니다. 포트도 지정해야 합니다.
다른 네임스페이스 전체 허용
NetworkPolicy allow-client-ns 를 만든다. podSelector app=web, ingress 의 from 은 namespaceSelector tier=client 하나만 (podSelector 를 함께 넣지 않는다).
namespaceSelector 는 네임스페이스에 붙은 라벨을 봅니다. 이번에는 그 네임스페이스 전체를 허용해야 하므로 podSelector 를 함께 넣지 마세요.
나가는 트래픽을 DNS 만 남기고 막기
NetworkPolicy egress-dns-only 를 만든다. podSelector app=web, policyTypes 는 [Egress], egress 의 to 는 namespaceSelector kubernetes.io/metadata.name=kube-system, 포트는 UDP 53 과 TCP 53 두 개.
모든 네임스페이스에는 이름과 같은 값의 라벨이 자동으로 붙습니다. DNS 는 UDP 만으로 충분하지 않은 경우가 있습니다.
CIDR 로 허용하고 일부 대역만 빼기
NetworkPolicy allow-cidr 을 만든다. podSelector app=web, ingress 의 from 은 ipBlock cidr 10.0.0.0/16 이고 except 에 10.0.5.0/24.
ipBlock 은 cidr 과 except 를 갖습니다. except 의 대역은 반드시 cidr 안에 포함돼야 합니다.
종합: AND 조건과 메타데이터 대역 차단
NetworkPolicy web-final 을 만든다. podSelector app=web, policyTypes 는 [Ingress, Egress]. ingress 의 from 은 항목 하나 안에 namespaceSelector tier=client 와 podSelector app=frontend 를 함께 두고 포트는 TCP 8080. egress 의 to 는 ipBlock cidr 0.0.0.0/0 에 except 169.254.169.254/32, 포트는 TCP 443.
from 항목을 두 개로 나누면 OR, 한 항목 안에 두 셀렉터를 함께 쓰면 AND 입니다. 대시 위치 하나가 의미를 바꿉니다.