Google Kubernetes Engine: NetworkPolicy cho phép đi ra k8s-metadata-proxy
Bối cảnh
Tôi có một cụm Google Kubernetes Engine (GKE) với Nhận dạng khối lượng công việc được bật. Là một phần của Workload Identity, DaemonSet k8s-metadata-proxy chạy trên cụm. Tôi có một không gian tên my-namespacevà muốn từ chối tất cả lưu lượng đi ra của các nhóm trong không gian tên ngoại trừ việc đi ra DaemonSet k8s-metadata-proxy. Như vậy, tôi có NetworkPolicy sau:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: my-namespace
spec:
# Apply to all pods.
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
# This is needed to whitelist k8s-metadata-proxy. See https://github.com/GoogleCloudPlatform/k8s-metadata-proxy
- protocol: TCP
port: 988
Vấn đề
NetworkPolicy quá rộng vì nó cho phép đi ra lưu lượng TCP tới bất kỳ máy chủ nào trên cổng 988 thay vì chỉ đi ra DaemonSet k8s-metadata-proxy, nhưng tôi dường như không thể tìm ra cách chỉ định .spec.egress[0].tođể đạt được mức độ chi tiết mà tôi muốn.
Tôi đã thử các cách sau to:
egress:
- to:
- namespaceSelector:
matchLabels:
namespace: kube-system
ports:
- protocol: TCP
port: 988
- to:
- ipBlock:
cidr: <cidr of pod IP range>
- ipBlock:
cidr: <cidr of services IP range>
ports:
- protocol: TCP
port: 988
nhưng các quy tắc này dẫn đến lưu lượng truy cập đến k8s-metadata-proxy bị chặn.
Câu hỏi
Làm cách nào tôi có thể chọn DaemonSet k8s-metadata-proxy trong tophần của quy tắc đầu ra trong a networking.k8s.io/v1/NetworkPolicy?
Trả lời
Như tôi đã nói trong bình luận:
Xin chào. Bạn có thể thêm vào podSelector.matchLabels của định nghĩa Egress để cho phép nhóm của bạn chỉ kết nối với các Nhóm có nhãn cụ thể. Bạn có thể đọc thêm về nó tại đây: cloud.google.com/kubernetes-engine/docs/tutorials/…
Nhận xét này có thể gây hiểu lầm vì giao tiếp với gke-metadata-serverđược mô tả trong tài liệu chính thức:
- Cloud.google.com: Kubernetes Engine: Nhận dạng khối lượng công việc: GKE-MDS
Tập trung vào phần của tài liệu trên:
Hiểu máy chủ siêu dữ liệu GKE
Máy chủ siêu dữ liệu GKE là một máy chủ siêu dữ liệu mới được thiết kế để sử dụng với Kubernetes. Nó chạy như một bộ daemonset , với một Pod trên mỗi nút cụm. Máy chủ siêu dữ liệu chặn các yêu cầu HTTP đểhttp://metadata.google.internal(
169.254.169.254:80), bao gồm các yêu cầu nhưGET /computeMetadata/v1/instance/service-accounts/default/tokentruy xuất mã thông báo cho tài khoản dịch vụ của Google mà Pod được định cấu hình để hoạt động. Lưu lượng truy cập vào máy chủ siêu dữ liệu không bao giờ rời khỏi phiên bản VM lưu trữ Pod.Lưu ý : Nếu bạn có chính sách mạng cụm nghiêm ngặt , bạn phải cho phép đi ra 127.0.0.1/32 trên cổng 988 để Pod của bạn có thể giao tiếp với máy chủ siêu dữ liệu GKE.
Quy tắc chỉ cho phép lưu lượng truy cập GKE Metadata serverđược mô tả trong đoạn cuối của trích dẫn trên. Các YAMLđịnh nghĩa nên trông giống như dưới đây:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: egress-rule
namespace: restricted-namespace # <- namespace your pod is in
spec:
policyTypes:
- Egress
podSelector:
matchLabels:
app: nginx # <- label used by pods trying to communicate with metadata server
egress:
- to:
- ipBlock:
cidr: 127.0.0.1/32 # <- allow communication with metadata server #1
- ports:
- protocol: TCP
port: 988 # <- allow communication with metadata server #2
Giả sử rằng:
- Bạn có một cụm Kubernetes với:
Network Policyđược kích hoạtWorkload Identityđược kích hoạt
- Bạn
Podsđang cố gắng giao tiếp từrestricted-namespacekhông gian tên
Đầu ra để mô tả cần thiết NetworkPolicy:
$ kubectl describe networkpolicy -n restricted-namespace egress-rule
Name: egress-rule
Namespace: restricted-namespace
Created on: 2020-10-04 18:31:10 +0200 CEST
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"networking.k8s.io/v1","kind":"NetworkPolicy","metadata":{"annotations":{},"name":"egress-rule","namespace":"restricted-name...
Spec:
PodSelector: app=nginx
Allowing ingress traffic:
<none> (Selected pods are isolated for ingress connectivity)
Allowing egress traffic:
To Port: <any> (traffic allowed to all ports)
To:
IPBlock:
CIDR: 127.0.0.1/32
Except:
----------
To Port: 988/TCP
To: <any> (traffic not restricted by source)
Policy Types: Egress
Khước từ!
Việc áp dụng các quy tắc đó sẽ từ chối tất cả lưu lượng truy cập từ các nhóm có
app=nginxnhãn không được gửi đến máy chủ siêu dữ liệu!
Bạn có thể tạo và execđưa vào nhóm có nhãn app=nginxbằng cách:
kubectl run -it --rm nginx \
--image=nginx \
--labels="app=nginx" \
--namespace=restricted-namespace \
-- /bin/bash
Tiền boa!
Hình ảnh
nginxđược sử dụng vì nó đãcurlđược cài đặt theo mặc định!
Bằng ví dụ này, bạn sẽ không thể giao tiếp với máy chủ DNS. Bạn có thể:
- cho phép các nhóm của bạn giao tiếp với máy chủ DNS
- đặt
envbiến cho máy chủ siêu dữ liệu (169.254.169.254)
Ví dụ về giao tiếp với GKE Metadata Server:
$ curl 169.254.169.254/computeMetadata/v1/instance/ -H 'Metadata-Flavor: Google'
attributes/
hostname
id
service-accounts/
zone
Các nguồn bổ sung:
- Cloud.google.com: Compute: Lưu trữ siêu dữ liệu đang truy xuất
Để cho phép các nhóm cụ thể chỉ gửi lưu lượng đến các nhóm cụ thể trên các cổng cụ thể, bạn có thể sử dụng chính sách sau:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: egress-rule
namespace: restricted-namespace # <- namespace of "source" pod
spec:
policyTypes:
- Egress
podSelector:
matchLabels:
app: ubuntu # <- label for "source" pod
egress:
- to:
- podSelector:
matchLabels:
app: nginx # <- label for "destination" pod
- ports:
- protocol: TCP
port: 80 # <- allow only port 80