Chiến lược bảo mật cho Node và Network trong Kubernetes

Sử dụng Namespace của Host cho Pod

Trong một số trường hợp đặc biệt, Pod cần truy cập trực tiếp vào các tài nguyên hệ thống của Node (máy chủ vật lý hoặc máy ảo). Kubernetes cung cấp các tùy chọn để chia sẻ không gian tên (namespace) của máy chủ với container.

Sử dụng Network Namespace của Node

Khi kích hoạt hostNetwork: true, Pod sẽ không nhận được địa chỉ IP riêng từ mạng của cụm (cluster network) mà sử dụng trực tiếp giao diện mạng của Node. Điều này thường được dùng cho các thành phần quản trị hệ thống hoặc monitoring.

apiVersion: v1
kind: Pod
metadata:
  name: k8s-node-net-pod
spec:
  hostNetwork: true
  containers:
  - name: inspector
    image: busybox
    command: ["sh", "-c", "sleep 1h"]

Ràng buộc cổng trực tiếp trên Host (hostPort)

Khác với hostNetwork, hostPort cho phép container giữ Network Namespace riêng nhưng ánh xạ một cổng cụ thể từ Node vào container. Lưu ý rằng mỗi cổng trên Node chỉ có thể được sử dụng bởi một Pod tại một thời điểm.

apiVersion: v1
kind: Pod
metadata:
  name: web-direct-port
spec:
  containers:
  - name: nginx-server
    image: nginx:alpine
    ports:
    - containerPort: 80
      hostPort: 8888

Chia sẻ không gian tên PID và IPC

Sử dụng hostPID cho phép container nhìn thấy tất cả các tiến trình đang chạy trên Node. Trong khi đó, hostIPC cho phép container giao tiếp với các tiến trình trên Node thông qua cơ chế Inter-Process Communication.

apiVersion: v1
kind: Pod
metadata:
  name: system-monitor-pod
spec:
  hostPID: true
  hostIPC: true
  containers:
  - name: monitor
    image: alpine
    command: ["sleep", "3600"]

Cấu hình Security Context cho Container

Security Context xác định các đặc quyền và quyền hạn truy cập cho một Pod hoặc Container, giúp giảm thiểu rủi ro nếu container bị tấn công.

Chạy với User ID cụ thể

Thay vì chạy dưới quyền root (UID 0), bạn có thể chỉ định một User ID cụ thể để hạn chế quyền truy cập vào file hệ thống.

apiVersion: v1
kind: Pod
metadata:
  name: uid-restricted-pod
spec:
  containers:
  - name: app-worker
    image: alpine
    command: ["sleep", "1h"]
    securityContext:
      runAsUser: 1001

Ngăn chặn chạy dưới quyền Root

Thiết lập runAsNonRoot: true sẽ khiến Pod thất bại khi khởi tạo nếu image được build để chạy mặc định bằng quyền root.

spec:
  containers:
  - name: secure-app
    image: alpine
    securityContext:
      runAsNonRoot: true

Chế độ đặc quyền (Privileged Mode)

Khi một container chạy ở chế độ privileged, nó có quyền truy cập gần như tương đương với các tiến trình chạy trực tiếp trên host, bao gồm cả việc can thiệp vào kernel.

securityContext:
  privileged: true

Quản lý Kernel Capabilities

Thay vì cấp toàn bộ đặc quyền, bạn có thể thêm hoặc bớt các quyền cụ thể của kernel (capabilities) để tối ưu hóa bảo mật theo nguyên tắc đặc quyền tối thiểu.

securityContext:
  capabilities:
    add: ["SYS_TIME"]
    drop: ["CHOWN"]

Sử dụng File System chỉ đọc

Để ngăn chặn việc ghi mã độc vào container, bạn có thể chuyển root filesystem sang chế độ chỉ đọc và chỉ cho phép ghi vào các Volume được chỉ định.

spec:
  containers:
  - name: static-app
    image: alpine
    securityContext:
      readOnlyRootFilesystem: true
    volumeMounts:
    - name: data-storage
      mountPath: /data
  volumes:
  - name: data-storage
    emptyDir: {}

Chính sách bảo mật Pod (PodSecurityPolicy)

PodSecurityPolicy (PSP) là một tài nguyên cấp Cluster dùng để kiểm soát các khía cạnh bảo mật mà Pod phải tuân thủ trước khi được khởi tạo.

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restrictive-policy
spec:
  privileged: false
  hostNetwork: false
  allowPrivilegeEscalation: false
  runAsUser:
    rule: MustRunAsNonRoot
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
  - 'configMap'
  - 'secret'
  - 'persistentVolumeClaim'

Để áp dụng chính sách này cho người dùng cụ thể, cần sử dụng RBAC để liên kết (bind) quyền use đối với tài nguyên PSP này thông qua ClusterRole và ClusterRoleBinding.

Cô lập lưu lượng mạng với NetworkPolicy

Mặc định trong Kubernetes, mọi Pod đều có thể giao tiếp với nhau. NetworkPolicy cho phép bạn thiết lập các quy tắc tường lửa để kiểm soát luồng dữ liệu.

Chặn toàn bộ lưu lượng vào (Default Deny)

Chính sách này thường được dùng làm nền tảng để khóa chặt một Namespace, sau đó mới mở dần các cổng cần thiết.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Cho phép truy cập dựa trên Label và Port

Ví dụ dưới đây chỉ cho phép các Pod có nhãn role: frontend truy cập vào cổng 3306 của các Pod có nhãn role: db.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-access
spec:
  podSelector:
    matchLabels:
      role: db
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 3306

Giới hạn truy cập theo dải IP (CIDR)

Có thể giới hạn truy cập từ các dải mạng bên ngoài hoặc các phân vùng mạng cụ thể.

ingress:
- from:
  - ipBlock:
      cidr: 10.0.0.0/16
      except:
      - 10.0.1.0/24

Kiểm soát lưu lượng ra (Egress)

Để ngăn chặn việc rò rỉ dữ liệu hoặc kết nối đến các máy chủ điều khiển độc hại, bạn có thể cấu hình Egress để chỉ cho phép Pod kết nối đến các dịch vụ hợp lệ.

spec:
  podSelector:
    matchLabels:
      app: my-service
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: internal-api
  policyTypes:
  - Egress

Thẻ: Kubernetes k8s-security networkpolicy podsecuritypolicy DevOps

Đăng vào ngày 2 tháng 11 lúc 20:54