이전 글 : https://sundlscha.tistory.com/13
Kubernetes Network Policy 공부하기 (1)
1. Network Policy란? Kubernetes Cluster 내부에서 pod 간 통신 시 트래픽 규칙을 규정하는 역할을 하는 object입니다. 기본적으로 Network Policy를 사용하지 않는 경우 Kubernetes Cluster 내부의 모든 pod는 서로 통
sundlscha.tistory.com
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-라는 문자열과 일치하는 것이 있는지 확인하기 위한 패턴입니다.
- awk 명령어는 사용자로부터 직접 입력을 받거나, 파일을 지정하여 데이터를 가공하고 처리하는 명령어입니다.
- kubectl 명령어 외 파이프라인 뒤 명령어의 경우 하기 내용을 확인해 주세요!
- kubectl get ns | awk ‘NR==1 || /ns-/' ← 이 명령어는 첫 번째 행 또는 ns-라는 문자열이 포함된 행을 출력하라는 의미입니다.
- namespace에 label을 지정해 줍니다.
- kubectl label namespace ns-01 ns=ns-01
- 지정된 label을 확인하기 위해 하기와 같은 명령어를 입력합니다.
- kubectl get ns ns-01 --show-labels
- 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
- 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
- kubectl get po -o wide -n ns-02
3. Network Policy 생성 1 - podSelector
3.1 Test Architecture
※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.
![](https://blog.kakaocdn.net/dn/vHmxh/btsF3fVWQRo/pXX0kH1cU07WHILdtqKglk/img.png)
- Public IP가 붙은 Hub 대역의 VM에서 Spoke 대역의 VM에 접근합니다. (Spoke 대역의 VM에는 Public IP를 붙이지 않았기 때문입니다.)
- ns-01의 모든 pod들에 대해 ingress/egress 트래픽을 차단하는 Network Policy를 생성합니다.
- 테스트 시나리오는 다음과 같습니다.
- Kubernetes Cluster 외부
- Spoke VM에서 ns-01의 pod로 curl 명령어를 날립니다.
- Spoke VM에서 ns-01의 pod로 curl 명령어를 날립니다.
- Kubernetes Cluster 내부
- ns-01의 임의의 pod에서 ns-02의 임의의 pod로 curl 명령어 실행
- ns-02의 임의의 pod에서 ns-01의 임의의 pod로 curl 명령어 실행
- Kubernetes Cluster 외부
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
- 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
- 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
- kubectl exec -it deployment-test-f8dbf68bd-9vr78 -- curl --connect-timeout 5 10.10.144.23
- Network Policy의 적용을 받은 pod 중 하나를 실행하여 namespace 2의 pod에게 curl 명령어를 날립니다.
4. Network Policy 생성 2 - namespaceSelector
4.1 Test Architecture
※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.
![](https://blog.kakaocdn.net/dn/BgRtX/btsF2M7x3SJ/roPBbOO8tOnGp3LysW9qVK/img.png)
- Public IP가 붙은 Hub 대역의 VM에서 Spoke 대역의 VM에 접근합니다.
- ns-01에 생성했던 network policy를 제거합니다.
- ns-01 namespace에 ns: ns-01이라는 Label이 붙어 있는 것을 다시 확인합니다.
- ns-02의 모든 pod들에 대해 ingress/egress 트래픽을 차단하는 Network Policy를 생성합니다.
- ns-02의 배포된 pod들 중 app: test Label을 가지는 pod들에 대해 egress 트래픽을 허용하는 Network Policy를 생성합니다.
- 테스트 시나리오는 다음과 같습니다.
- Kubernetes Cluster 내부
- ns-02에 배포된 pod들 중 app: test Label을 가지는 pod에서 ns-01의 임의의 pod로 curl 명령어 실행
- ns-02에 배포된 pod들 중 app: hyein Label을 가지는 pod에서 ns-01의 임의의 pod로 curl 명령어 실행
- Kubernetes Cluster 내부
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
- kubectl apply -f np4.yaml
- ns-02 namespace에 있는 Deployment 및 Label를 조회하기 위한 명령어는 하기와 같습니다.
- kubectl get deploy -n ns-02 --show-labels
- 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
- 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
- kubectl exec -it deployment-hyein-87b66c554-2dsdb -- curl --connect-timeout 5 10.10.144.5
- deployment-test의 pod에서 ns-01에 있는 pod 중 임의의 pod로 curl 명령어 날립니다.
5. Network Policy 생성 3 - ipBlock
5.1 Test Architecture
※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.
※ ns-02의 Deployment 및 Network Policy는 5. Network Policy 생성 3 - ipBlock에서 사용하지 않아 표기를 생략한 점 참고 부탁드립니다.
![](https://blog.kakaocdn.net/dn/bxx5GD/btsFZWK7hxk/BvIyxKwrmeHBKP61ylKwp1/img.png)
- Public IP가 붙은 Hub 대역의 VM에서 Spoke 대역의 VM에 접근합니다.
- 2개의 Spoke VM에 각각 접근합니다.
- 2개의 Spoke VM에 각각 접근합니다.
- ns-01에 ingres/egress를 모두 차단하는 network policy를 생성합니다.
- app: test Label을 가지는 pod들에 대해 특정 ip 대역에서 들어오는 ingress 트래픽을 허용하는 Network Policy를 생성합니다.
- 테스트 시나리오는 다음과 같습니다.
- Kubernetes Cluster 외부
- 10.10.128.4의 ip 주소를 가지는 Spoke VM에서 curl 명령어 실행
- 10.10.128.5의 ip 주소를 가지는 Spoke VM에서 curl 명령어 실행
- Kubernetes Cluster 외부
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
- 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 명령어를 실행하면 하기 빨간 박스와 같이 통신이 가능한 것을 확인할 수 있습니다.
- pod 중 하나로 curl 명령어를 실행하면 하기 빨간 박스와 같이 통신이 가능한 것을 확인할 수 있습니다.
- vm-02 (10.10.128.5)
- pod 중 하나로 curl 명령어를 실행하면 하기 빨간 박스와 같이 통신이 불가한 것을 확인할 수 있습니다.
- pod 중 하나로 curl 명령어를 실행하면 하기 빨간 박스와 같이 통신이 불가한 것을 확인할 수 있습니다.
- vm-01 (10.10.128.4)
6. Network Policy 생성 4 - ipBlock
6.1 Test Architecture
※ pod는 Deployment를 통해 배포되었지만, pod 간 트래픽 흐름을 나타내기 위해 Deployment 표기는 생략한 점 참고 부탁드립니다.
※ ns-02의 Deployment 및 Network Policy는 6. Network Policy 생성 4 - ipBlock에서 사용하지 않아 표기를 생략한 점 참고 부탁드립니다.
![](https://blog.kakaocdn.net/dn/bH09Cr/btsF0FWnkJg/sOjQsc7OrWekisU5yk0DRK/img.png)
- Public IP가 붙은 Hub 대역의 VM에서 테스트 수행합니다.
- ns-01에 ingres/egress를 모두 차단하는 network policy를 생성합니다.
- Node ip 대역에서 들어오는 ingress 트래픽을 허용하는 network policy를 생성합니다.
- 테스트 시나리오는 다음과 같습니다.
- Kubernetes Cluster 외부
- Hub 대역의 VM에서 Internal Load Balancer의 ip를 통해 Application에 접근할 수 있는지 확인합니다.
- Kubernetes Cluster 외부
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
- kubectl apply -f svc1.yaml
- Service의 External IP를 확인하기 위해 하기 명령어를 실행합니다.
- kubectl get svc
- 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
- kubectl apply -f np5.yaml
- ns-01에 배포된 Network Policy를 조회하기 위해 하기와 같은 명령어를 입력합니다.
- kubectl get netpol
- kubectl get netpol
- Internal Load Balancer의 External IP를 통해 Appilcation에 다시 한번 접근해 봅니다.
와! 이번에는 접속이 가능하군요!
- ClientIP에 10.10.144.11 (node ip 중 하나)가 찍힌 것을 통해 정상적으로 network policy가 적용된 것을 확인할 수 있습니다.
'Kubernetes' 카테고리의 다른 글
Encrypting Secret Data at Rest in ETCD (0) | 2024.03.22 |
---|---|
Virtual Machine으로 Kubernetes Cluster 구성하기 (2) (0) | 2024.03.22 |
Virtual Machine으로 Kubernetes Cluster 구성하기 (1) (0) | 2024.03.22 |
Kubernetes Network Policy 공부하기 (1) (0) | 2024.03.22 |
Kubernetes Namespace 간 Ingress 트래픽 라우팅 하기 (0) | 2024.03.22 |
댓글