개요
- Killer Shell CKA - NetworkPolicy Namespace Selector
- https://killercoda.com/killer-shell-cka/scenario/networkpolicy-namespace-communication
- 요구사항
- Namespace space1의 모든 파드가 오직 Namespace space2의 파드로만 아웃바운드 통신(Egress) 가능하도록 제한하되, DNS(53/TCP, 53/UDP) 아웃바운드는 허용
- Namespace space2의 모든 파드가 오직 Namespace space1의 파드로부터만 인바운드 통신(Ingress) 가능하도록 제한
- Ingress/Egress 방향 중 명시되지 않은 방향은 제한하지 않음
사전 확인
- namespaceSelector는 네임스페이스 레이블로 매칭된다. 기본적으로 kubeadm 클러스터는 kubernetes.io/metadata.name 레이블이 존재한다.
controlplane:~$ k get ns --show-labels
NAME STATUS AGE LABELS
default Active 4d9h kubernetes.io/metadata.name=default
kube-node-lease Active 4d9h kubernetes.io/metadata.name=kube-node-lease
kube-public Active 4d9h kubernetes.io/metadata.name=kube-public
kube-system Active 4d9h kubernetes.io/metadata.name=kube-system
local-path-storage Active 4d9h kubernetes.io/metadata.name=local-path-storage
space1 Active 38s kubernetes.io/metadata.name=space1
space2 Active 38s kubernetes.io/metadata.name=space2
해결: NetworkPolicy 생성
1) space1: 모든 파드의 Egress를 space2로만 허용, 추가로 DNS(53/TCP,UDP) 아웃바운드 허용
$ vim np-space1.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: np
namespace: space1
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: space2
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
$ k apply -f np-space1.yaml
networkpolicy.networking.k8s.io/np created
2) space2: 모든 파드의 Ingress를 space1로부터만 허용
$ vim np-space2.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: np
namespace: space2
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: space1
$ k apply -f np-space2.yaml
networkpolicy.networking.k8s.io/np created
검증
- 동작해야 하는 요청
$ k -n space1 exec app1-0 -- curl -m 1 microservice1.space2.svc.cluster.local
...</html>
$ k -n space1 exec app1-0 -- curl -m 1 microservice2.space2.svc.cluster.local
...</html>
$ k -n space1 exec app1-0 -- nslookup tester.default.svc.cluster.local
...</html>
$ k -n kube-system exec -it validate-checker-pod -- curl -m 1 app1.space1.svc.cluster.local
...</html>
- 차단되어야 하는 요청
$ k -n space1 exec app1-0 -- curl -m 1 tester.default.svc.cluster.local
...curl: (28) Connection timed out after 1001 milliseconds
$ k -n kube-system exec -it validate-checker-pod -- curl -m 1 microservice1.space2.svc.cluster.local
...curl: (28) Connection timed out after 1001 milliseconds
$ k -n kube-system exec -it validate-checker-pod -- curl -m 1 microservice2.space2.svc.cluster.local
...curl: (28) Connection timed out after 1001 milliseconds
$ k -n default run nginx --image=nginx:1.21.5-alpine --restart=Never -i --rm -- curl -m 1 microservice1.space2.svc.cluster.local
...curl: (28) Connection timed out after 1001 milliseconds
참고/주의
- NetworkPolicy는 선택된 파드와 지정된 방향에 대해서만 제한이 적용된다.
- space1의 정책은 Egress만 제한하므로 Ingress는 영향을 받지 않는다.
- space2의 정책은 Ingress만 제한하므로 Egress는 영향을 받지 않는다.
- DNS 허용 규칙은 목적지 제한 없이 53/TCP,53/UDP로의 아웃바운드를 허용한다. 특정 CNI 환경에서 DNS를 더 엄격히 제한하려면 kube-system 네임스페이스의 CoreDNS 파드로의 트래픽만 허용하도록 namespaceSelector와 podSelector를 조합할 수 있다.
- 네트워크 플러그인(Calico, Cilium 등)에서 NetworkPolicy 지원이 활성화되어 있어야 한다.