파드 및 엔드포인트 간 트래픽 흐름(Ingress/Egress)을 제어하기 위한 리소스
보안이나 서비스 격리를 위해 특정 파드, 네임스페이스 간 통신을 차단하거나 허용하는 정책
NetworkPolicy 리소스를 지원하는 CNI가 설치되어 있어야 실제 동작Flannel은 지원 X
비유하면 인터넷 방화벽과 유사한 기능을 한다.
- 다만 방화벽은 외부에서 들어오는 트래픽을 제어하고,
- 쿠버네티스 네트워크 정책은 파드 간 트래픽도 제어한다는 범위와 대상 관점의 차이가 존재
All Allow
NetworkPolicy가 어떤 파드에 적용될 지 결정하는 필드
label기반 선택자 사용(e.g app=nginx)
app=nginx 라벨이 적용된 파드에 대한 ingress 제한 예시
deny-all-to-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-to-nginx
namespace: default
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- {} # Deny All Ingress
kubectl run nginx --image=nginx --labels="app=nginx" --port=80
kubectl run client --image=busybox:1.28 --restart=Never -it --rm --sh
# curl http://nginx -> 성공
kubectl apply -f deny-all-to-nginx.yaml
kubectl run client --image=busybox:1.28 --restart=Never -it --rm --sh
# curl http://nginx -> 실패
kubectl delete networkpolicy --all
🤔 쿠버네티스 네트워크 보안 모델의 기본 트래픽 방침은
All Allow라고 했는데, ingress 설정이 의미가 있을까?
기본적으로 모든 인바운드/아웃바운드를 허용하지만, ingress 설정을 지정하면 해당 설정이 적용되고 All Deny 설정으로 변경된다.
allow-from-frontend-ns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend-ns
namespace: default
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
team: frontend
kubectl create ns frontend # frontend라는 이름의 네임스페이스 생성
kubectl create ns dev # dev라는 이름의 네임스페이스 생성
kubectl run nginx --image=nginx --labels="app=nginx" --port=80 --expose -n deafult # nginx라는 이름의 컨테이너를 생성 -> default 네임스페이스
kubectl run client --image=busybox:1.28 --restart=Never -it --labels="team=frontend" -n frontend --sh # client 라는 이름의 컨테이너 실행 -> team=frontend 라벨을 갖고 네임스페이스는 frontend
kubectl label ns frontend team=frontend # frontend라는 네임스페이스에 team=frontend라는 라벨 추가
kubectl apply -f allow-from-frontend-ns.yaml
kubectl run cliend --image=busybox:1.28 --restart=Never -it --rm -n frontend --sh # curl http://nginx -> 성공
kubectl run client --image=busybox:1.28 --restart=Never -it -n dev --sh # curl http://nginx -> 실패
kubectl delete networkpolicy --all
podSelector에서 네트워크 정책을 적용할 pod label을 선택한 뒤에, namespaceSelector로 선택한 네임 스페이스로부터의 요청만 허용하는 설정
allow-egress-to-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-to-nginx
spec:
podSelector:
matchLabels:
run: client
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app:nginx
ports:
- protocol: TCP
port: 80
kubectl run nginx --image=nginx --labels="app=nginx" --port=80
kubectl run client --image=busybox:1.28 --restart=Never -it --rm -- sh
# curl http://nginx -> 성공
kubectl apply -f allow-egress-to-nginx.yaml
kubectl run client --image=busybox:1.28 --restart=Never -it --labels="run=client" --rm – sh
# curl http://nginx -> 성공 ingress 제한 없음
# ping 8.8.8.8 # 실패 egress 정책 적용
# wget http://google.com # 실패
kubectl delete networkpolicy --all
allow-cidr-access.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-cidr-access
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 192.168.xx.xx/8
except:
- 192.168.xx.xx/32
kubectl run nginx --image=nginx --labels="app=nginx" --port=80
kubectl apply -f allow-cidr-access.yaml
kubectl run client --image=busybox:1.28 --restart=Never -it --rm --sh
#curl http://nginx
kubectl get pod client -o wide # 파드 IP 확인
kubectl delete networkpolicy --all
1. Selector -> 정책이 적용될 대상
2. ingress/egress -> 허용 트래픽 방향
3. from/to -> 어디서 오는지/ 가는지 지정
4. ports -> 허용할 프로토콜/ 포트 지정
