stamper

NetworkPolicy egress 격리 후 DNS만 허용하는 실습

stamper1일 전조회 1추천 0

문제 상황

egress 정책을 적용한 직후 앱이 Could not resolve host를 보고한다. DNS 통신 차단이 원인 후보이므로 정책 적용 전후를 비교해 확인한다. 새 네임스페이스에서 재현하고 DNS만 열어 본다.

전제

  • CNI가 NetworkPolicy egress를 지원해야 함(미지원 CNI는 정책이 무시됨)
  • dev 클러스터에서 새 실습 네임스페이스 np-lab만 사용한다. 같은 이름의 기존 namespace가 있으면 중단하고 고유한 이름으로 모든 예제를 바꾼다.
  • np-labtest라는 Deployment를 미리 준비한다. 조직에서 허용한 진단 이미지를 사용하고 nslookupwget이 있는지 확인한다. 정책 적용 전 DNS 조회가 성공해야 비교가 가능하다.
kubectl config current-context
kubectl create namespace np-lab
# 이제 test Deployment를 준비한 뒤, 차단 전 기준값을 확인한다.
kubectl -n np-lab exec deploy/test -- nslookup kubernetes.default

1) egress 전면 차단 재현

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-egress
  namespace: np-lab
spec:
  podSelector: {}
  policyTypes: [Egress]

위 YAML을 deny-egress.yaml로 저장하고 kubectl apply -f deny-egress.yaml로 적용한다. 다른 허용 정책이 없는 일반 Pod 네트워크에서는 선택된 Pod의 나가는 트래픽이 격리된다. 잠시 뒤 같은 Pod에서 실행한다:

kubectl -n np-lab exec deploy/test -- nslookup kubernetes.default

→ DNS 실패를 관찰(재현 성공).

2) DNS만 허용

kube-dns pod의 라벨을 실제로 확인한다:

kubectl -n kube-system get pod -l k8s-app=kube-dns

namespace 라벨도 kubectl get namespace kube-system --show-labels로 확인한다. 아래 YAML을 allow-dns.yaml로 저장한다:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: np-lab
spec:
  podSelector: {}
  policyTypes: [Egress]
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

핵심: namespaceSelectorpodSelector같은 to 항목 안에 두어 AND(= kube-system 안의 kube-dns pod)로 만든다. 둘을 별도 to 항목으로 나누면 OR가 되어 의도보다 넓게 열린다. UDP/TCP 53 둘 다 필요하다.

다음 순서로 문법·서버 수용 여부와 DNS 회복을 확인한다.

kubectl apply --dry-run=server -f allow-dns.yaml
kubectl apply -f allow-dns.yaml
kubectl -n np-lab exec deploy/test -- nslookup kubernetes.default
kubectl -n np-lab exec deploy/test -- wget -T 5 -O /dev/null https://example.com

DNS 응답에 주소가 나오고, 외부 HTTP 요청은 연결에 실패하는 것이 이 실습의 기대 결과다. 도구 미설치·TLS 인증서 오류는 네트워크 정책 차단의 증거가 아니므로 출력 내용을 구분한다.

정책 합집합

같은 pod에 여러 NetworkPolicy가 붙으면 규칙은 **합집합(union)**이다. deny-egressallow-dns가 함께 있으면 DNS는 열린다. 하지만 외부 HTTP(443 등)는 여전히 막혀 있다 — DNS 해결과 외부 HTTP 허용은 별개다. 또한 이 정책은 egress만 다룬다. ingress 제한이 필요하면 별도 policyType이 필요하다.

검증 / 실패 판정

  • allow-dns 적용 후 nslookup이 성공하면 OK.
  • 그래도 실패하면 NodeLocal DNS/hostNetwork 경로, 라벨 불일치, DNS 서버 상태를 조사한다. 반대로 차단 정책 적용 후에도 계속 통신되면 CNI 미지원이나 다른 허용 정책을 의심한다. 이 예제는 CNI별 DNS 경로 차이로 그대로 적용되지 않을 수 있음을 전제한다.

되돌리기

kubectl delete namespace np-lab

np-lab을 이번 실습에서 새로 만들었고 그 안에 실습 리소스만 있는지 먼저 확인한다. 삭제는 namespace 안의 모든 리소스를 제거한다. 기존 공유 namespace에 그대로 실행하면 안 된다.

출처

댓글 0

아직 댓글이 없습니다.