TOPIC/Infra

Kubernetes Network Policy 공부하기 (2)

H-Y-E-N 2024. 1. 12. 21:40

안녕하세요. HYEN입니다.

이전 글에서 Network Policy에 대해서 공부해 보았는데요. 

이번에는 실제로 Network Policy에 대해 테스트한 내용에 대해 다뤄보도록 하겠습니다. 😝

 

Network Policy에 대한 이론을 정리한 글은 아래 링크를 참고해 주세요!

https://with-cloud.tistory.com/17


 

1. Namespace 생성 및 Label 지정

  • 테스트에 사용할 namespace를 생성합니다.
    • kubectl create ns ns-01
    • kubectl create ns ns-02

 

  • 생성된 namespace 확인하기 위해 하기 명령어를 입력합니다. 
    • kubectl get ns | awk ‘NR==1 || /ns-/' ← 이 명령어는 첫 번째 행 또는 ns-라는 문자열이 포함된 행을 출력하라는 의미입니다.
      • kubectl 명령어 외 파이프라인 뒤 명령어의 경우 하기 내용을 확인해 주세요! 
        • awk 명령어는 사용자로부터 직접 입력을 받거나, 파일을 지정하여 데이터를 가공하고 처리하는 명령어입니다. 

        • NR은 현재 레코드의 번호를 의미합니다. 예를 들어, NR==1은 첫 번째 행을 의미하죠. 

        • / /은 정규식 패턴을 의미합니다. 예를 들어, /ns-/는 ns-라는 문자열과 일치하는 것이 있는지 확인하기 위한 패턴입니다.

 

  • namespace에 label을 지정해 줍니다.
    • kubectl label namespace ns-01 ns=ns-01

 

  • 지정된 label을 확인하기 위해 하기와 같은 명령어를 입력합니다. 
    • kubectl get ns ns-01 --show-labels

 

2. Deployment 생성

  • ns-01 namespace에 Deployment를 생성합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: amsy810/echo-nginx:v2.0
        ports:
        - containerPort: 80
  • kubectl apply -f deploy.yaml

    image“쿠버네티스 완벽 가이드” 책의 image를 참고하였습니다. (curl 등 network 통신 테스트가 목적이기 때문입니다.)

 

  • pod ip를 조회합니다. (AKS를 종료한 후 재시작 할 경우, pod의 ip는 변경된다는 점, 잊지 마세요!)
    • kubectl get po -o wide

 

  • 해당 ip 중 하나로 curl 명령어를 날립니다. (AKS에 접근할 수 있는 Spoke 대역의 VM에서 명령어를 입력해야 합니다.)



    정상적으로 nginx의 default page가 보이는 것을 확인할 수 있습니다. 

 

  • ns-02 namespace에 Deployment를 생성합니다. 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-test
  namespace: ns-02
  labels:
    app: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - name: test
        image: amsy810/echo-nginx:v2.0
        ports:
        - containerPort: 80

 

  • kubectl apply -f deploy1.yaml

 

  • pod ip를 조회합니다.(AKS를 종료한 후 재시작 할 경우, pod의 ip는 변경된다는 점, 잊지 마세요!)
    • kubectl get po -o wide -n ns-02

 

3. Network Policy 생성 1 - podSelector

3.1 Test Architecture

※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.

  1. Public IP가 붙은 Hub 대역의 VM에서 Spoke 대역의 VM에 접근합니다. (Spoke 대역의 VM에는 Public IP를 붙이지 않았기 때문입니다.)
  2. ns-01의 모든 pod들에 대해 ingress/egress 트래픽을 차단하는 Network Policy를 생성합니다. 
  3. 테스트 시나리오는 다음과 같습니다. 
    • Kubernetes Cluster 외부
      • Spoke VM에서 ns-01의 pod로 curl 명령어를 날립니다.

    • Kubernetes Cluster 내부
      • ns-01의 임의의 pod에서 ns-02의 임의의 pod로 curl 명령어 실행
      • ns-02의 임의의 pod에서 ns-01의 임의의 pod로 curl 명령어 실행  

 

3.2 Test 

  • ns-01 namespace 내 모든 pod들에 대해 ingress/egress 트래픽을 모두 차단하는 Network Policy를 생성합니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-deny-all
  namespace: ns-01
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
  • Network Policy를 생성하기 위해 하기와 같은 명령어를 입력합니다. 
    • kubectl apply -f np.yaml

 

  • Kubernetes Cluster 외부에서 들어오는 트래픽에 대한 테스트를 하기 위해 curl 명령어를 사용합니다.
    • Network Policy를 적용한 후에는 aks와 같은 VNet 대역에 있는 VM에서 curl 명령어를 해당 pod의 ip로 날려도 통신이 되지 않는 것을 확인할 수 있습니다. 

 

  • Kubernetes Cluster 내부에서의 pod 간 통신을 테스트하기 위해 pod 내 container에 접근하여 curl 명령어를 날립니다. 
    • Network Policy의 적용을 받은 pod 중 하나를 실행하여 namespace 2의 pod에게 curl 명령어를 날립니다.
      ➡️ egress가 차단 되어 curl: (28) Connection timed out after 5001 milliseconds라는 메시지가 출력되는 것을 확인할 수 있습니다.
      • kubectl exec -it nginx-deployment-799744886-4nvls -- curl --connect-timeout 5 10.10.144.28

         
    • namespace 2에 pod를 하나 생성하여 Network Policy의 적용을 받은 pod 중 하나로 curl 명령어를 날립니다.
      ➡️ ingress가 차단되어 curl: (28) Connection timed out after 5001 milliseconds라는 메시지가 출력되는 것을 확인할 수 있습니다.
      • kubectl exec -it deployment-test-f8dbf68bd-9vr78 -- curl --connect-timeout 5 10.10.144.23

 

4. Network Policy 생성 2 - namespaceSelector

4.1 Test Architecture

※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.

  1. Public IP가 붙은 Hub 대역의 VM에서 Spoke 대역의 VM에 접근합니다.
  2. ns-01에 생성했던 network policy를 제거합니다.
  3. ns-01 namespace에 ns: ns-01이라는 Label이 붙어 있는 것을 다시 확인합니다.
  4. ns-02의 모든 pod들에 대해 ingress/egress 트래픽을 차단하는 Network Policy를 생성합니다. 
  5. ns-02의 배포된 pod들 중 app: test Label을 가지는 pod들에 대해 egress 트래픽을 허용하는 Network Policy를 생성합니다.
  6. 테스트 시나리오는 다음과 같습니다. 
    • Kubernetes Cluster 내부
      • ns-02에 배포된 pod들 중 app: test Label을 가지는 pod에서 ns-01의 임의의 pod로 curl 명령어 실행 
      • ns-02에 배포된 pod들 중 app: hyein Label을 가지는 pod에서 ns-01의 임의의 pod로 curl 명령어 실행 

 

4.2 Test

  • namespace 2의 모든 pod들에 대한 ingress/egress를 차단하기 위한 network policy를 생성합니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-deny-all
  namespace: ns-02
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

 

  • namespace 2의 pod 중 app: test라는 Label을 가진 pod에 대해서만 namespace 1에 있는 모든 pod로 Egress 트래픽을 보내는 것을 허용하기 위해 namespaceSelector 옵션을 사용합니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-deny-egress-to-ns-01
  namespace: ns-02
spec:
  podSelector:
    matchLabels:
      app: test
  policyTypes:
    - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          ns: ns-01
    ports:
    - protocol: TCP
      port: 80

 

  • Network Policy를 생성하기 위해 하기와 같은 명령어를 실행합니다. 
    • kubectl apply -f np4.yaml

    • kubectl apply -f np2.yaml

 

  • ns-02 namespace에 있는 Deployment 및 Label를 조회하기 위한 명령어는 하기와 같습니다.
    • kubectl get deploy -n ns-02 --show-labels

 

➡️ deployment-test에서 ns-01 namespace로 보내는 egress 트래픽은 차단단되어야 하고
     deployment-hyein에서 ns-01 namespace로 보내는 egress 트래픽은 허용되어야 합니다. 

 

  • 그렇다면 테스트 결과를 확인해 보겠습니다! 
    • deployment-test의 pod에서 ns-01에 있는 pod 중 임의의 pod로 curl 명령어 날립니다.
      • kubectl exec -it deployment-test-f8dbf68bd-9vr78 -- curl --connect-timeout 5 10.10.144.5
    • deployment-hyein의 pod에서 ns-01에 있는 pod 중 임의의 pod로 curl 명령어를 날립니다.
      • kubectl exec -it deployment-hyein-87b66c554-2dsdb -- curl --connect-timeout 5 10.10.144.5

 

5. Network Policy 생성 3 - ipBlock

5.1 Test Architecture

※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.

※ ns-02의 Deployment 및 Network Policy는 5. Network Policy 생성 3 - ipBlock에서 사용하지 않아 표기를 생략한 점 참고 부탁드립니다. 

  1. Public IP가 붙은 Hub 대역의 VM에서 Spoke 대역의 VM에 접근합니다.
    • 2개의 Spoke VM에 각각 접근합니다. 

  2. ns-01에 ingres/egress를 모두 차단하는 network policy를 생성합니다.
  3. app: test Label을 가지는 pod들에 대해 특정 ip 대역에서 들어오는 ingress 트래픽을 허용하는 Network Policy를 생성합니다.
  4. 테스트 시나리오는 다음과 같습니다. 
    • Kubernetes Cluster 외부
      • 10.10.128.4의 ip 주소를 가지는 Spoke VM에서 curl 명령어 실행
      • 10.10.128.5의 ip 주소를 가지는 Spoke VM에서 curl 명령어 실행 

 

5.2 Test - spoke-vm 대역에서 pod로 직접 통신

  • ns-01 namespace 내 app: nginx라는 Label Selector을 가지고 있는 pod들에 대해 snet-vm(10.10.128.0/27) 대역에서 들어오는 ingress 트래픽을 허용하되, except field를 사용하여 10.10.128.5 ip 주소를 가지는 source에서 들어오는 ingress 트래픽은 차단하는 Network Policy를 생성합니다. 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-with-ipblock
  namespace: ns-01
spec:
  podSelector:
    matchLabels:
      app: nginx
  policyTypes:
    - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 10.10.128.0/27
        except:
        - 10.10.128.5/32
    ports:
    - protocol: TCP
      port: 80
  • Network Policy를 생성하기 위해 하기 명령어를 실행합니다.
    • kubectl apply -f np1.yaml

 

✅ 현재 ns-01 namespace에는 모든 ingress/egress 트래픽을 차단하는 np-deny-all이라는 network policy와 특정 subnet 대역에서 들어오는 트래픽만 허용하는 np-with-ipblock 이라는 network policy가 배포되어 있습니다.

Network Policy는 합집합입니다.

➡️ 특정 subnet 대역에서 Service의 External IP로 접속을 시도해도 통신이 불가합니다.

 

  • snet-vm 대역에 생성한 2개의 VM에 접속하여 테스트를 진행합니다.
    • vm-01 (10.10.128.4)
      • pod 중 하나로 curl 명령어를 실행하면 하기 빨간 박스와 같이 통신이 가능한 것을 확인할 수 있습니다.
    • vm-02 (10.10.128.5)
      • pod 중 하나로 curl 명령어를 실행하면 하기 빨간 박스와 같이 통신이 불가한 것을 확인할 수 있습니다.

 

6. Network Policy 생성 4 - ipBlock

6.1 Test Architecture

※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.

※ ns-02의 Deployment 및 Network Policy는 6. Network Policy 생성 4 - ipBlock에서 사용하지 않아 표기를 생략한 점 참고 부탁드립니다.

  1. Public IP가 붙은 Hub 대역의 VM에서 테스트 수행합니다. 
  2. ns-01에 ingres/egress를 모두 차단하는 network policy를 생성합니다.
  3. Node ip 대역에서 들어오는 ingress 트래픽을 허용하는 network policy를 생성합니다.
  4. 테스트 시나리오는 다음과 같습니다. 
    • Kubernetes Cluster 외부
      • Hub 대역의 VM에서 Internal Load Balancer의 ip를 통해 Application에 접근할 수 있는지 확인합니다.

 

6.2 Test - Hub VM - Service - Deployment - Pod로의 Ingerss 통신 제어

  • ns-01 namespace 내 nginx-deployment 앞단에 LoadBalancer Type의 Service를 배포합니다.
apiVersion: v1
kind: Service
metadata:
  name: svc-deploy-nginx
  namespace: ns-01
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    service.beta.kubernetes.io/azure-load-balancer-internal-subnet: "snet-lb"
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
  type: LoadBalancer
  • Service를 배포하기 위해 하기 명령어를 실행합니다.
    • kubectl apply -f svc1.yaml

 

  • Service의 External IP를 확인하기 위해 하기 명령어를 실행합니다.
    • kubectl get svc

 

  • Internal Load Balancer의 External IP를 통해 Appilcation에 접근해 봅니다.
    • 접근이 불가한 것을 확인할 수 있습니다.

 

왜 접근이 불가능할까요

 

✅ 현재 ns-01 namespace에는 모든 ingress/egress 트래픽을 차단하는 np-deny-all이라는 network policy와 특정 subnet 대역에서 들어오는 트래픽만 허용하는 np-with-ipblock 이라는 network policy가 배포되어 있습니다.
✅ Network Policy는 합집합입니다.

➡️ Hub VM에서 Service의 External IP로 접속을 시도해도 통신이 불가합니다.

 

  • Load Balancer를 타고 들어온 트래픽이 Node를 거쳐 pod로 흐를 수 있도록 node들의 ip를 허용해 주는 network policy를 생성해야 합니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: np-with-ipblock-for-node
  namespace: ns-01
spec:
  podSelector:
  policyTypes:
    - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 10.10.144.0/20
    ports:
    - protocol: TCP
      port: 80
  • AKS의 node들이 배포되어 있는 subnet 대역을 cidr로 지정해 줍니다.

  • Network Policy를 생성하기 위해 하기와 같은 명령어를 입력합니다.
    • kubectl apply -f np5.yaml

 

  • ns-01에 배포된 Network Policy를 조회하기 위해 하기와 같은 명령어를 입력합니다.
    • kubectl get netpol

 

  • Internal Load Balancer의 External IP를 통해 Appilcation에 다시 한번 접근해 봅니다.

와! 이번에는 접속이 가능하군요! 

 

  • ClientIP에 10.10.144.11 (node ip 중 하나)가 찍힌 것을 통해 정상적으로 network policy가 적용된 것을 확인할 수 있습니다.

 


이상으로 Network Policy에 대한 테스트를 마치도록 하겠습니다. 

감사합니다! 

728x90
320x100
SMALL