LabHub
배우기 러닝패스 코스

Kubernetes Operations

Policy Design Starting From Default Deny

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

네임스페이스의 통신 기본값을 거부로 뒤집고, 필요한 경로만 라벨로 골라 여는 정책 세트를 직접 작성합니다.

왜 중요한가

NetworkPolicy 에서 가장 많이 틀리는 것은 문법이 아니라 방향과 결합 방식입니다. 정책은 트래픽을 보내는 쪽이 아니라 받는 쪽에 붙습니다. web 에서 api 로 가는 통신을 허용하려면 정책의 podSelector 가 api 여야 하고, web 은 ingress.from 안에 등장합니다. 또 from 배열의 항목끼리는 OR 이고 한 항목 안의 namespaceSelectorpodSelector 는 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 는 빈 객체 {} 이고 policyTypesIngress 하나만이며 ingress 규칙은 하나도 없어야 합니다.
  3. NetworkPolicy allow-web-to-api 를 만드세요. podSelector.matchLabels.appapi, ingress[0].from[0]podSelector.matchLabels.app: web 하나만 갖습니다(같은 항목에 namespaceSelector 를 넣지 마세요). 허용 포트는 TCP 8080 입니다.
  4. NetworkPolicy default-deny-egress 를 만드세요. policyTypesEgress 하나만입니다. 이어서 allow-dns-egress 를 만들되 egress[0].to[0].namespaceSelector.matchLabelskubernetes.io/metadata.name: kube-system 을 쓰고, egress[0].ports 에는 포트 53UDP 와 TCP 두 항목으로 넣으세요.
  5. 네임스페이스 monitoring 을 만들고 라벨 purpose=monitoring 을 붙이세요. 그다음 netpol-lab 에 NetworkPolicy allow-from-monitoring 을 만드세요. podSelector.matchLabels.appapi, ingress[0].from[0].namespaceSelector.matchLabels.purposemonitoring, 허용 포트는 9090 입니다.
  6. NetworkPolicy allow-office-cidr 을 만드세요. podSelector.matchLabels.appweb 이고, ingress[0].from[0].ipBlock.cidr10.0.0.0/16, except10.0.5.0/24 하나입니다.
  7. NetworkPolicy api-full 을 만드세요. podSelector.matchLabels.appapi, policyTypesIngressEgress 둘 다입니다. 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-apiapi 에만 들어가야 합니다(web 이나 db 에 넣으면 안 됩니다). allow-office-cidrweb 에, api-fullapi 에 들어갑니다. 최종적으로 netpol-lab 의 NetworkPolicy 는 6개 이상이어야 합니다.

참고

실습용 네임스페이스와 라벨 붙은 파드 만들기

네임스페이스 netpol-lab 을 만들고 /opt/lab/fixtures/k8s/workloads.yaml 을 그 안에 적용하세요. 결과로 web, api, db 세 파드가 각각 자기 이름과 같은 app 라벨을 갖고, api 파드는 추가로 tier=backend 라벨을 가져야 합니다.

정책은 라벨로만 대상을 고릅니다. 픽스처에 세 파드가 준비돼 있으니 그대로 올리되, 어느 네임스페이스에 올리는지를 확인하세요.

인그레스 기본 거부 정책 만들기

netpol-lab 에 NetworkPolicy default-deny-ingress 를 만드세요. podSelector 는 빈 객체 {} 이고 policyTypesIngress 하나만이며 ingress 규칙은 하나도 없어야 합니다.

네임스페이스 전체를 고르는 셀렉터는 비어 있는 셀렉터입니다. 전부 거부한다는 뜻은 허용 규칙을 하나도 쓰지 않는 것입니다.

web 에서 api 로 가는 포트만 열기

NetworkPolicy allow-web-to-api 를 만드세요. podSelector.matchLabels.appapi, ingress[0].from[0]podSelector.matchLabels.app: web 하나만 갖습니다(같은 항목에 namespaceSelector 를 넣지 마세요). 허용 포트는 TCP 8080 입니다.

정책은 보내는 쪽이 아니라 받는 쪽에 붙습니다. 같은 네임스페이스 안이므로 상대를 고를 때 네임스페이스 셀렉터를 섞지 마세요.

이그레스 기본 거부와 DNS 예외

NetworkPolicy default-deny-egress 를 만드세요. policyTypesEgress 하나만입니다. 이어서 allow-dns-egress 를 만들되 egress[0].to[0].namespaceSelector.matchLabelskubernetes.io/metadata.name: kube-system 을 쓰고, egress[0].ports 에는 포트 53UDP 와 TCP 두 항목으로 넣으세요.

이그레스를 막으면 이름 해석부터 죽습니다. DNS 는 UDP 만으로 끝나지 않는다는 점과, 대상 네임스페이스를 고르는 표준 라벨이 무엇인지 확인하세요.

다른 네임스페이스에서 오는 트래픽 허용하기

네임스페이스 monitoring 을 만들고 라벨 purpose=monitoring 을 붙이세요. 그다음 netpol-lab 에 NetworkPolicy allow-from-monitoring 을 만드세요. podSelector.matchLabels.appapi, ingress[0].from[0].namespaceSelector.matchLabels.purposemonitoring, 허용 포트는 9090 입니다.

네임스페이스를 고르려면 그 네임스페이스에 라벨이 실제로 붙어 있어야 합니다. 셀렉터가 고를 대상이 없으면 정책은 아무 의미가 없습니다.

IP 대역 허용과 예외 지정하기

NetworkPolicy allow-office-cidr 을 만드세요. podSelector.matchLabels.appweb 이고, ingress[0].from[0].ipBlock.cidr10.0.0.0/16, except10.0.5.0/24 하나입니다.

ipBlock 은 넓게 열고 좁게 빼는 방식으로 씁니다. 제외 대역은 반드시 허용 대역 안에 들어 있어야 합니다.

인그레스와 이그레스를 한 정책에 담기

NetworkPolicy api-full 을 만드세요. podSelector.matchLabels.appapi, policyTypesIngressEgress 둘 다입니다. ingress[0].from 에는 항목이 2개 이상(예: web 파드와 monitoring 네임스페이스) 들어가야 하고, egress[0].to[0]podSelector.matchLabels.app: db, 허용 포트는 5432 입니다.

from 배열의 항목끼리는 OR 입니다. 두 종류의 출처를 허용하려면 항목을 두 개로 나누세요. 나가는 쪽은 데이터베이스 포트만 열립니다.

파드별 적용 정책 지도 만들기

/root/ops/netpol/out/policy-map.json 을 만드세요. 최상위 키는 web, api, db 세 개이고 각 값은 그 파드를 고르는 정책 이름의 배열입니다. 빈 셀렉터를 가진 정책은 세 파드 모두에 들어가야 하고, allow-web-to-apiapi 에만 들어가야 합니다(web 이나 db 에 넣으면 안 됩니다). allow-office-cidrweb 에, api-fullapi 에 들어갑니다. 최종적으로 netpol-lab 의 NetworkPolicy 는 6개 이상이어야 합니다.

빈 셀렉터를 가진 정책은 모든 파드에 적용됩니다. 정책이 고르는 것은 받는 쪽이라는 점을 지도에 반영하세요.