Tìm hiểu Kurbernetes NetworkPolicy

Tại sao chúng ta phải dùng NetworkPolicy: Allow đến mức pod gọi pod, giới hạn pod gọi internet. Tránh trường hợp 1 pod bị chiếm quyền tấn công loạn xạ toàn bộ hệ thống k8s. Để hiểu cơ bản về việc các pod gọi nhau trong k8s, ta sẽ đi P1 và P2 khi chưa

Tại sao chúng ta phải dùng NetworkPolicy:

  • Allow đến mức pod gọi pod, giới hạn pod gọi internet. Tránh trường hợp 1 pod bị chiếm quyền tấn công loạn xạ toàn bộ hệ thống k8s.

Để hiểu cơ bản về việc các pod gọi nhau trong k8s, ta sẽ đi P1 và P2 khi chưa có chặn networkpolicies. Và P3,P4 sẽ thực hiện chặn lại.

Phần 1: Pod gọi Pod – cùng Namespace:

Phần này ta tạo 2 pod nằm trong cùng 1 NS, sau đó thực hiện gọi nhau thông qua service_name

# kubectl create ns tuanda0
# kubectl -n tuanda0 run --image=nginx web01
# kubectl -n tuanda0 expose pod web01 --port=80
# kubectl -n tuanda0 run busybox --image=busybox --restart=Never -- /bin/sh -c 'echo hello;sleep 36000'
Thực hiện kiểm tra bằng việc truy cập busybox và gọi service_name nginx
# kubectl -n tuanda0 exec -it busybox -- /bin/sh
> wget web01
    Hello World

Phần 2: Pod gọi Pod – khác Namespace

Phần này ta tạo 2 pod nằm khác NS, Để gọi chéo ta thêm tiền tố namespace sau service_name :

<svcname>.<namespace>.svc.cluster.local hoặc rút gọn: <svcname>.<namespace>

kubectl create ns tuanda1
kubectl create ns tuanda2
kubectl -n tuanda1 run --image=nginx web01
kubectl -n tuanda1 expose pod web01 --port=80
kubectl -n tuanda2 run busybox --image=busybox --restart=Never -- /bin/sh -c 'echo hello;sleep 36000'
# Ta thực hiện vào pod2 (ns: tuanda2) để kiểm tra thông với pod1 ở ns tuanda1
kubectl -n tuanda2 exec -it busybox -- /bin/sh
> nslookup web01.tuanda1.svc.cluster.local   [OK]
> wget web01.tuanda1.svc.cluster.local
    Hello World

Phần 3: Pod gọi nhau sử dụng Networkpolicies Deny all – cùng NameSpace

Chuẩn bị pod và ns để test:

kubectl create ns frontend
kubectl label namespaces frontend role=frontend --overwrite=true
kubectl -n frontend run --image=nginx --labels="app=web_frontend" nginx
kubectl -n frontend expose pod nginx --port=80
kubectl -n frontend run busybox --image=busybox --restart=Never -- /bin/sh -c 'echo hello;sleep 36000'

Step1: DENY ALL

Việc đầu tiên phải làm là ta cần deny all và mở những rule cần thiết ở các VD tiếp.

# vim 01.deny-frontend.yaml
    
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: frontend
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Kết quả:

Case1 : Allow Egress (outbound)

Trong case này, ta giả lập cần mở cho busybox gọi ra ngoài web google, api sendmail, api sms….

# kubectl get ns --show-labels (để lấy label của namespace)
# kubectl get all -n frontend --show-labels (để lấy label của pod)
# vim 02.allow-http-dns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-http-dns
  namespace: frontend
spec:
  policyTypes:
  - Egress
  podSelector: {} 
  egress:
  - ports:
    - port: 53
      protocol: UDP
    - port: 80
      protocol: TCP
    - port: 443
      protocol: TCP
    
Vào pod busybox thực hiện wget google.com KQ: [return 200]. Với trường hợp ta chỉ định pod nhất định > thì có thể sửa podSelector:
  podSelector:
    matchLabels:
      role: db
Ngoài ra có thể giới hạn chính xác IP được gọi, chứ ko mở all 80/443 ra ngoài như sau:
  egress:   
  - to:     
    - ipBlock:         
        cidr: 123.123.68.68/32
    ports:     
    - protocol: TCP       
      port: 8080

Case2: Allow Ingress (Inbound)

Vậy với trường hợp Pod gọi Pod khi bị DenyAll, ta thực hiện như sau

# kubectl get ns --show-labels (để lấy label của namespace)
# kubectl get all -n frontend --show-labels (để lấy label của pod)

# vim 03.allow-http-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: 03-allow-http-ingress
  namespace: frontend
spec:
  podSelector:
    matchLabels:
      app: web_frontend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          role: frontend
      podSelector:
        matchLabels:
          run: busybox
    ports:
    - protocol: TCP
      port: 80

# kubectl apply  -f 03.allow-http-ingress.yaml
# kubectl -n frontend exec -it busybox -- sh  (vào pod busybox để kiểm tra)
> wget nginx 
Hello World
    

Phần 4: Pod gọi nhau sử dụng Networkpolicies Deny all – khác NameSpace

Xóa ns để tạo lại môi trường giả lập

kubectl delete ns frontend
kubectl delete ns backend

kubectl create ns frontend
kubectl label namespaces frontend role=frontend --overwrite=true
kubectl -n frontend run --image=nginx --labels="app=web_frontend" nginx
kubectl -n frontend expose pod nginx --port=80
kubectl -n frontend run busybox --image=busybox --restart=Never -- /bin/sh -c 'echo hello;sleep 36000'

kubectl create ns backend
kubectl label namespaces backend role=backend --overwrite=true
kubectl -n backend run --image=nginx --labels="app=web_backend" nginx
kubectl -n backend expose pod nginx --port=80
kubectl -n backend run busybox --image=busybox --restart=Never -- /bin/sh -c 'echo hello;sleep 36000'

Sơ đồ

B1: Chặn Ingress/Exgress 2 NS

#vim  01.deny-frontend.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: 01-default-deny-all-frontend
  namespace: frontend
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

# vim 01.deny-backend.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: 01-default-deny-all-backend
  namespace: backend
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
# kubectl apply  -f 01.deny-backend.yaml 
# kubectl apply  -f 01.deny-frontend.yaml 

B2: Busybox frontend gọi nginx backend

(1, ====Vì busybox cần biết IP của service_backend là bao nhiêu, nên ta cần mở DNS 53====)
#  vim 05.exgress-frontend-allow-dns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: exgress-frontend-allow-dns
  namespace: frontend
spec:
  podSelector:
    matchLabels:
      run: busybox
  policyTypes:
  - Egress
  egress:
  - ports:
    - port: 53
      protocol: UDP
    
(====================2, Mở Egress cho Frontend ====================)
# vim 06.exgress-frontend-allow-http.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: exgress-frontend-allow-http
  namespace: frontend
spec:
  podSelector:
    matchLabels:
      run: busybox
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          role: backend
      podSelector:
        matchLabels:
          app: web_backend
    
(====================3, Mở Ingress cho Backend ====================)
07.ingress-backend-allow-http.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ingress-backend-allow-http
  namespace: backend
spec:
  podSelector:
    matchLabels:
      app: web_backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          role: frontend
      podSelector:
        matchLabels:
          run: busybox
    ports:
    - protocol: TCP
      port: 80

(====================Test ====================)    
kubectl -n frontend exec -it busybox -- sh
> wget nginx.backend
    HelloWorld

Tổng kết:

Nguồn tham khảo:

https://kubernetes.io/docs/concepts/services-networking/network-policies/

https://faun.pub/debugging-networkpolicy-part-1-249921cdba37

https://pauldally.medium.com/debugging-networkpolicy-part-2-2d5c42d8465c

https://docs.giantswarm.io/getting-started/network-policies/

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ