返回文章列表

Kubernetes 網路安全策略與服務網格最佳實踐

本文探討 Kubernetes 網路安全最佳實踐,涵蓋網路策略、服務網格、Pod 安全及策略治理等導向。文章首先介紹網路策略的最佳實踐和與服務網格的整合,接著深入 Pod 安全,探討 Pod Security Admission 和 RuntimeClass 的應用。最後,文章討論策略與治理的重要性,並介紹 OPA

網路安全 Kubernetes

Kubernetes 網路策略提供更細緻的應用程式流量控管機制,本文將探討如何有效運用網路策略及服務網格提升叢集安全性。實務上建議從 Pod 的入口流量開始設定網路策略,待流量符合預期後再設定出口規則,避免追蹤困難。選擇合適的網路外掛並建立預設拒絕策略,確保即使刪除其他策略也不會意外暴露 Pod。隨著服務規模擴大,服務網格提供負載平衡、服務發現、可觀察性、安全性和彈性等關鍵功能,有效簡化服務間通訊的管理和安全控制。選擇服務網格時,需考量團隊技術能力、基礎設施資源和跨系統網格需求,並評估開源或商業支援方案。

網路安全最佳實踐與服務網格

在企業系統中,網路流量的安全管理曾經是複雜的硬體裝置和網路規則集的專屬領域。如今,Kubernetes 網路策略(Network Policy)提供了一種更以應用程式為中心的方法,用於區隔和控制在 Kubernetes 中託管的應用程式的流量。無論使用哪種策略外掛,以下是一些常見的最佳實踐:

網路策略最佳實踐

  • 從小處著手,先專注於 Pod 的入口流量(ingress)。同時設定入口和出口規則可能會使網路追蹤變得困難。一旦流量如預期般流動,就可以開始查看出口規則,以進一步控制對敏感工作負載的流量。Kubernetes 網路策略的規範預設偏好入口規則,即使入口規則列表中沒有輸入任何內容。
  • 確保所使用的網路外掛具有與 NetworkPolicy API 的介面,或支援其他知名外掛。例如,Calico、Cilium、Kube-router、Romana 和 Weave Net 等都是常見的網路外掛。
  • 如果網路團隊習慣使用「預設拒絕」(default-deny)策略,請為叢集中的每個名稱空間建立一個網路策略,以保護工作負載。這樣可以確保即使刪除另一個網路策略,也不會意外地「暴露」任何 Pod。

預設拒絕所有流量的網路策略範例

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

內容解密:

此網路策略範例定義了一個名為 default-deny-all 的策略,它預設拒絕所有入口流量。podSelector 為空物件 {} 表示選取所有 Pod,而 policyTypes 指定了該策略適用於入口流量。

網路策略與服務網格

當叢集託管數百個服務,並跨越數千個端點進行負載平衡時,管理和保護這些服務之間的通訊變得非常困難。服務網格(Service Mesh)提供了一種控制這些服務之間連線和安全性的解決方案。

服務網格的主要功能

  • 負載平衡和流量控制:服務網格提供細粒度的流量控制和負載平衡功能。
  • 服務發現:服務網格允許服務成員之間進行服務發現,無論是在叢集內還是跨叢集。
  • 可觀察性:服務網格提供了對流量和服務的可觀察性,包括使用 Jaeger 或 Zipkin 等追蹤系統進行分散式追蹤。
  • 安全性:服務網格使用相互驗證來保護網格中的流量,同時也可以提供 Ingress 控制器來實作南北向的安全性和控制。
  • 彈性和健康檢查:服務網格提供了彈性和健康檢查功能,例如電路斷路器、重試和截止日期等。

服務網格的實作

大多數服務網格使用 Sidecar 代理來實作其功能。例如,Istio 使用 Envoy 作為其資料平面代理,而 Linkerd2 則使用自己的資料平面代理。HashiCorp 的 Consul 也提供了服務網格功能,並支援使用 Envoy 或自己的代理。

Pod 與容器安全性

在透過 Kubernetes API 實作 Pod 安全性的過程中,您主要有兩個選項:Pod Security Admission 和 RuntimeClass。本章將檢視每個 API 的目的和用法,並提供最佳實踐建議。

Pod Security Admission Controller

此叢集級別的資源提供了一個單一的位置,用於定義和管理 Pod 規格中所有與安全相關的欄位。在 Pod Security Admission 資源出現之前,叢集管理員和/或使用者使用 PodSecurityPolicy,但該方法複雜且難以正確設定。在 PodSecurityPolicy 出現之前,使用者需要為每個 Pod 或 Deployment 獨立定義個別的 SecurityContext 設定,或在叢集上啟用自定義的准入控制器來強制執行某些 Pod 安全導向。

啟用 Pod Security Admission

如果您的叢集版本為 Kubernetes 1.22 或更新,則可能已啟用 Pod Security Admission。您可以使用 kubectl version 命令檢查叢集版本。如果您正在執行較舊版本的 Kubernetes,建議進行更新,因為較舊版本已不再受到 Kubernetes 專案的積極支援,這使您面臨未修補的安全漏洞風險。

在現有叢集上啟用 Pod Security Admission 控制時,請謹慎行事,因為如果沒有在開始時做好充分準備,則可能會阻礙工作負載。建議先使用警告和稽核執行模式,以確保您的政策按預期運作。

Pod 安全級別

Pod Security Admission 控制器透過實施三種不同的政策級別來簡化安全組態,管理員可以從中選擇。每個安全級別都包含一系列用於限制 Pod 組態的規則。這些安全級別的詳細資訊可以在 Kubernetes 檔案中找到。

三種 Pod 安全標準級別分別是:

  1. privileged:實際上沒有任何限制。它與未啟用 Pod 安全性的 Kubernetes 叢集的預設行為相比對。
  2. baseline:防範已知的許可權提升和其他安全問題。
  3. restricted:目前社群對於 Pod 安全性的最佳實踐。

在開始使用政策時,可能會立即嘗試對所有名稱空間強制執行受限級別,但需要注意的是,叢集中預先存在的組態可能會中斷,且其他第三方提供的社群解決方案或軟體可能無法正常運作。

最佳實踐

  1. 評估服務網格關鍵功能的優先順序:確定哪些當前的服務網格產品以最小的負擔提供最重要的功能。這裡的負擔指的是人力技術負債和基礎設施資源負債。
  2. 考量跨系統網格的需求:並非所有的服務網格都提供跨多雲或混合場景的能力。如果需要此功能,則需要仔細評估相關的服務網格產品。
  3. 評估開源與商業支援的服務網格:許多服務網格產品是根據開源社群的專案。如果團隊對服務網格不熟悉,商業支援的產品可能是更好的選擇。

程式碼範例與說明

以下是一個簡單的 YAML 組態檔案,用於演示如何為一個 Pod 設定基本的 SecurityContext:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: ["sleep", "1h"]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false

內容解密:

  1. securityContext: 定義了 Pod 的安全上下文,包括執行 Pod 的使用者和群組 ID。
  2. runAsUserrunAsGroup: 指定容器內程式執行的使用者和群組 ID。
  3. fsGroup: 指定擁有該卷的所有程式的群組 ID。
  4. allowPrivilegeEscalation: 設定為 false 以防止容器內程式提升其許可權。 這個組態範例展示瞭如何在 Kubernetes 中為 Pod 和容器設定基本的安全上下文,以增強容器的安全性。

Pod Security Admission 控制器與工作負載隔離

Pod Security Admission 控制器提供了三種策略執行層級,分別為 enforcewarnauditenforce 層級會主動阻止不符合安全層級的 Pod 被建立;warn 層級會向使用者發出警告,但不會阻止 Pod 被建立;audit 層級則會記錄策略違規,但不會向使用者提供反饋。

每個安全層級都與特定的 Kubernetes 版本相關聯(例如 v1.25)。雖然安全層級與 Kubernetes 版本相關聯,但它在其他 Kubernetes 版本中仍然可用。版本遵循與其他 Kubernetes 元件相同的三版本棄用策略。此外,還有一個 latest 版本,追蹤最新的策略。然而,與使用容器映像中的 latest 標籤一樣,不建議使用 latest 版本,因為叢集升級時,安全策略會發生變化,這可能會導致叢集意外中斷。相反,在叢集升級後逐步升級安全策略是一種最佳實踐。

使用名稱空間標籤啟用 Pod Security

Pod Security 的啟用是透過在名稱空間中新增標籤來實作的。可以在名稱空間 YAML 中新增標籤,如下所示:

metadata:
  labels:
    # 初始設定為不幹擾現有使用者
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/enforce-version: v1.25
    pod-security.kubernetes.io/warn: privileged
    pod-security.kubernetes.io/warn-version: v1.25
    # 開啟基準稽核
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/audit-version: v1.25

一旦將此組態應用於所有名稱空間,就可以在叢集稽核日誌中看到稽核資訊。這將使您瞭解叢集的合規性。如果叢集的合規性很差,您可能需要識別各種工作負載的所有者,並與他們合作,使其工作負載符合規範。由於執行是按名稱空間進行的,因此可以與團隊個別合作,並在工作負載符合規範後轉為執行。

內容解密:

此段落說明瞭如何使用名稱空間標籤啟用 Pod Security,並提供了示例組態。組態中設定了 enforcewarnaudit 層級,分別對應不同的安全檢查。

工作負載隔離與 RuntimeClass

容器執行時仍被視為不安全的工作負載隔離邊界。目前尚不清楚今天最常見的執行時是否會被視為安全。Kubernetes 的發展勢頭和行業中的興趣導致了不同容器執行時的開發,這些執行時提供了不同程度的隔離。一些是根據熟悉和可信賴的技術堆積疊,而另一些則是完全新的嘗試,旨在解決這個問題。開源專案如 Kata containers、gVisor 和 Firecracker 都提供了更強大的工作負載隔離。這些專案要麼根據巢狀虛擬化(在虛擬機器中執行超輕量級虛擬機器),要麼根據系統呼叫過濾和服務。

RuntimeClass 被引入 Kubernetes 作為 API,以允許容器執行時的選擇。它用於表示叢集中受支援的容器執行時之一,由叢集管理員組態。作為 Kubernetes 使用者,可以在 Pod 規範中使用 RuntimeClassName 定義特定的執行時類別。

RuntimeClass 的使用

如果叢集管理員設定了不同的 RuntimeClass,可以透過在 Pod 規範中指定 runtimeClassName 來使用它們。例如:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  runtimeClassName: firecracker

內容解密:

此段落說明瞭如何使用 RuntimeClass,並提供了示例組態。組態中指定了 runtimeClassNamefirecracker,表示使用 Firecracker 執行時。

RuntimeClass 流程圖

下圖示範了 kubelet 如何在啟動 Pod 時使用 RuntimeClass。

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title RuntimeClass 流程圖

rectangle "Pod Spec" as n1
rectangle "RuntimeHandler" as n2
rectangle "Container Runtime" as n3

n1 --> n2
n2 --> n3

@enduml

此圖示說明瞭 kubelet 如何根據 Pod 規範中的 RuntimeClassName 選擇合適的容器執行時。

內容解密:

此段落說明瞭 RuntimeClass 的流程,並提供了 Plantuml 圖表。圖表展示了 kubelet 如何使用 RuntimeClass 選擇容器執行時。

開源容器執行時實作

以下是一些開源容器執行時實作,它們提供了不同程度的安全性和隔離:

  • Kata containers
  • gVisor
  • Firecracker
  • WebAssembly (WASM)

這些專案提供了不同的隔離機制,例如巢狀虛擬化和系統呼叫過濾。containerd 專案現在支援根據 WebAssembly 的容器。

內容解密:

此段落介紹了一些開源容器執行時實作,並說明瞭它們提供的隔離機制。這些專案為使用者提供了不同的選擇,以滿足其安全性和隔離需求。

策略與治理:確保叢集合規性

在企業環境中,Kubernetes 叢集的管理面臨諸多挑戰。如何確保所有容器僅來自受信任的容器登入檔?如何實施安全團隊制定的網路存取策略?本章將探討 Kubernetes 中的策略與治理工具,幫助您建立合規且安全的叢集環境。

為何策略與治理至關重要

在醫療保健、金融服務等高度監管的行業中,企業必須遵守嚴格的法規要求。即使在一般企業環境中,建立對叢集的控制機制也是必要的。定義公司特定的政策並確保叢集符合這些政策是維持系統安全和穩定的基礎。

策略實施的挑戰

  1. 合規性需求:不同行業有不同的法規要求,需要相應的策略來滿足這些要求。
  2. 最佳實踐:除了合規性,還需要實施最佳實踐以確保系統的穩定性和安全性。
  3. 開發者敏捷性:在實施策略時,不能犧牲開發者的敏捷性和自助服務能力。

Kubernetes 中的策略

Kubernetes 中的策略無處不在,從網路策略到 Pod 安全策略,都體現了策略的重要性。我們信任在 Kubernetes 資源規格中宣告的內容能夠按照策略定義實作。然而,不同型別的策略有不同的實施方式和關注點。

網路策略與 Pod 安全策略

  • 網路策略:控制 Pod 之間的網路流量,限制哪些 Pod 可以相互通訊。
  • Pod 安全策略:定義 Pod 的安全組態,例如是否允許特權模式、是否允許使用主機網路等。

策略管理的最佳實踐

為了有效管理 Kubernetes 中的策略,企業需要採取以下最佳實踐:

  1. 明確策略定義:清晰定義需要實施的策略,包括合規性要求和最佳實踐。
  2. 選擇合適的工具:利用 Kubernetes 生態系統中的工具來實施和管理策略。
  3. 持續監控和稽核:定期檢查叢集狀態,確保符合定義的策略。

內容解密:

本章節主要闡述了 Kubernetes 中策略與治理的概念及其重要性。首先介紹了為何需要策略與治理,接著討論了 Kubernetes 中不同型別的策略,包括網路策略和 Pod 安全策略。最後提出了一些最佳實踐,幫助企業有效管理 Kubernetes 叢集中的策略。透過這些內容,讀者可以瞭解如何在 Kubernetes 環境中建立合規且安全的叢集。

策略與治理:Kubernetes叢集的合規性管理

在管理Kubernetes叢集時,我們需要確保資源組態符合組織的政策和最佳實踐。Open Policy Agent(OPA)和Gatekeeper是兩個流行的工具,幫助我們實作這一目標。

Gatekeeper簡介

Gatekeeper是一個可自定義的Kubernetes准入Webhook,用於實施叢集政策和治理。它利用OPA的約束框架來強制執行根據自定義資源定義(CRD)的政策。Gatekeeper允許資源驗證和稽核功能,並且具有可移植性,可以在任何Kubernetes叢集上實施。

Gatekeeper術語

Gatekeeper採用了許多與OPA相同的術語,包括:

  • 約束(Constraint):對Kubernetes資源規格的特定欄位和值施加的限制。
  • Rego:OPA原生查詢語言,用於對儲存在OPA中的資料進行斷言。
  • 約束範本(Constraint Template):可移植和重用的政策範本,由型別引數和目標Rego組成。

定義約束範本

約束範本是一種自定義資源定義(CRD),提供了一種範本化政策的方法,以便分享或重用。讓我們看一個約束範本的例子,它實作了「只允許來自受信任容器註冊中心的容器」這一政策:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sallowedrepos
  annotations:
    metadata.gatekeeper.sh/title: "Allowed Repositories"
    metadata.gatekeeper.sh/version: 1.0.0
description: >-
  Requires container images to begin with a string from the specified list.
spec:
  crd:
    spec:
      names:
        kind: K8sAllowedRepos
  validation:
    # Schema for the `parameters` field
    openAPIV3Schema:
      type: object
      properties:
        repos:
          description: The list of prefixes a container image is allowed to have.
          type: array
          items:
            type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sallowedrepos
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)]
          not any(satisfied)
          msg := sprintf("container <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos])
        }
        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]

內容解密:

  • apiVersionkind 指定了約束範本的API版本和型別。
  • metadata 包含了約束範本的後設資料,如名稱、標題和版本。
  • spec.crd.spec.names.kind 定義了約束範本的自定義資源型別。
  • spec.validation.openAPIV3Schema 定義了引數欄位的結構描述。
  • spec.targets 指定了約束範本的目標,包括目標型別和Rego程式碼。
  • Rego程式碼定義了違反約束的條件和錯誤訊息。

常見政策範例

以下是一些常見的政策範例,用於解決Kubernetes叢集中的合規性問題:

  • 服務不得公開暴露在網際網路上。
  • 只允許來自受信任容器註冊中心的容器。
  • 所有容器都必須具有資源限制。
  • Ingress主機名稱不得重疊。
  • Ingress必須只使用HTTPS。