返回文章列表

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

本文探討 Kubernetes 網路安全機制,涵蓋 Pod、服務、Ingress 的運作方式,並提供網路策略設定與服務網格最佳實踐。同時,文章也詳細說明 Pod 安全准入控制器、RuntimeClass 的應用,以及如何透過 Gatekeeper 等工具強化叢集政策與治理,確保容器安全與合規性。

網路安全 容器技術

Kubernetes 網路模型複雜且重要,從 Pod 的 IP 分配到服務的建立,再到 Ingress 的流量路由,每個環節都攸關應用程式的穩定性和安全性。透過網路策略,我們可以精細地控制 Pod 間的通訊,限制非必要的流量,提升整體安全性。服務網格則提供更進階的流量管理和監控能力,讓微服務架構下的應用程式更具彈性。除了網路層級的防護,Pod 本身的安全性也至關重要。Pod Security Admission 控制器提供簡化的安全策略設定,而 RuntimeClass 則允許我們選擇更安全的容器執行環境,進一步提升隔離性和安全性。最後,透過 Gatekeeper 等政策治理工具,我們可以將安全策略自動化,確保叢集符合規範,降低人為錯誤的風險。

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

Kubernetes 不僅提供應用程式管理,還提供將不同應用程式元件連結起來的能力。在本章中,我們探討了 Kubernetes 的運作細節,包括 Pod 如何透過 CNI 外掛程式取得 IP 位址、如何將這些 IP 位址分組形成服務,以及如何透過 Ingress 資源實作更複雜的應用程式或第七層路由。此外,我們還討論瞭如何使用網路策略限制流量並保護網路安全,以及服務網格技術如何改變人們連線和監控服務之間連線的方式。

服務網格規範與最佳實踐

服務網格社群不斷發展壯大,隨著越來越多的企業參與定義其需求,服務網格生態系統將發生巨大變化。以下是一些根據目前服務網格試圖解決的常見問題的最佳實踐:

  • 評估服務網格所提供的主要功能的優先順序,並確定哪些現有的產品以最少的開銷提供最重要的功能。
  • 判斷是否需要跨系統的服務網格,例如多雲或混合雲場景。
  • 許多服務網格產品是開源社群專案,如果管理環境的團隊對服務網格不熟悉,商業支援的產品可能是更好的選擇。

Pod 與容器安全

在 Kubernetes 中,Pod 安全性可以透過 Pod Security Admission 和 RuntimeClass 兩種主要方式進行控制。本章將回顧這兩種 API 的用途和使用方法,並提供最佳實踐建議。

Pod Security Admission 控制器

Pod Security Admission 控制器提供了一個簡化的 API 用於保護 Pod,但它並未提供與 PodSecurityPolicy 完全相同的功能。如果需要更完整的功能,可以安裝像 Gatekeeper 這樣的策略解決方案。

  • Pod Security Admission 控制器簡化了安全性組態,提供了三種不同的策略級別供管理員選擇。
  • 這三種級別分別是:privileged、baseline 和 restricted。
  • 在啟用 Pod Security Admission 控制器時,需要謹慎操作,以避免對現有的工作負載造成影響。

程式碼範例與解析

以下是一個 Kubernetes Pod 的 YAML 設定檔範例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: example-image
    securityContext:
      runAsUser: 1000
      fsGroup: 1000

內容解密:

  • apiVersionkind 分別指定了 Kubernetes 資源的 API 版本和型別。
  • metadata 部分定義了 Pod 的中繼資料,包括名稱。
  • spec 部分定義了 Pod 的規格,包括容器列表。
  • securityContext 部分定義了容器的安全性上下文,包括執行使用者和檔案系統群組。

Kubernetes 網路模型

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

title 內容解密:

rectangle "CNI" as node1
rectangle "Service" as node2
rectangle "Ingress" as node3
rectangle "流量管理" as node4

node1 --> node2
node2 --> node3
node3 --> node4

@enduml

圖表翻譯:

此圖示呈現了 Kubernetes 的網路模型。Pod 透過 CNI 外掛程式取得 IP 位址,然後這些 IP 位址被分組形成服務。服務再透過 Ingress 資源實作更複雜的路由和流量管理。

Pod 安全准入控制器的三種執行層級

除了安全級別之外,Pod 安全准入控制器還提供了三種策略執行層級。enforce 層級會主動阻止不符合安全級別的 Pod 被建立。warn 層級會向使用者發出警告,指出其 Pod 違反了策略,但不會阻止其被建立。audit 層級會記錄策略違規行為,但不會向使用者提供反饋。

安全級別版本控制

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

使用名稱空間標籤啟用 Pod 安全

Pod 安全的啟用是透過在名稱空間上新增標籤來實作的。您可以透過在名稱空間 YAML 中新增標籤來實作,如下例所示。首先,我們將從一個簡單地在基準安全級別上稽核現有使用的組態開始:

metadata:
  labels:
    # 首先設定 enforce 和 warn 為 unrestricted,以避免幹擾現有使用者
    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

內容解密:

此 YAML 組態片段展示瞭如何透過名稱空間標籤來啟用 Pod 安全准入控制器的不同執行層級。其中:

  • pod-security.kubernetes.io/enforce: privileged 指定了強制執行的安全級別為 privileged
  • pod-security.kubernetes.io/enforce-version: v1.25 指定了強制執行的安全級別版本為 v1.25
  • pod-security.kubernetes.io/warn: privilegedpod-security.kubernetes.io/warn-version: v1.25 分別設定了警告級別和版本。
  • pod-security.kubernetes.io/audit: baselinepod-security.kubernetes.io/audit-version: v1.25 則開啟了基準安全級別的稽核日誌記錄。

工作負載隔離與 RuntimeClass

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

RuntimeClass 的使用

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

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

內容解密:

此 YAML 組態片段展示瞭如何透過指定 runtimeClassName 來選擇特定的容器執行時。在這個例子中,Pod 名稱為 nginx,並且指定了使用名為 firecracker 的 RuntimeClass。這允許您根據工作負載的需求選擇不同的容器執行時,從而實作不同程度的隔離。

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 如何使用 RuntimeClass 啟動 Pod 的流程。首先,Kubelet 接收 Pod 的規格(Spec),然後根據指定的 RuntimeClass 確定要使用的 RuntimeHandler。接著,RuntimeHandler 被傳遞給 Container Runtime Interface(CRI),由 CRI 負責與具體的容器執行時互動,最終啟動容器。

開源容器執行時實作

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

  • Kata containers
  • gVisor
  • Firecracker
  • WebAssembly (WASM) based containers supported by containerd

這些專案提供了不同的隔離機制,例如巢狀虛擬化、系統呼叫過濾等,以滿足不同工作負載的安全需求。

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

在企業環境中,Kubernetes 叢集的管理需要嚴格的策略與治理機制,以確保叢集的安全性和合規性。本章將探討 Kubernetes 中的策略與治理工具,幫助您維護叢集的穩定性和安全性。

為什麼策略與治理至關重要

在醫療保健或金融服務等高度監管的行業中,企業必須遵守嚴格的法規要求。即使在非監管環境中,制定和實施公司內部策略也是確保叢集安全和穩定的關鍵。這些策略可能涉及合規性要求或最佳實踐的實施。

Kubernetes 中的策略

Kubernetes 中的策略無處不在,從網路策略到 Pod 安全策略。這些策略定義了資源的預期狀態,並確保 Kubernetes 資源規格的宣告得到正確實施。網路策略和 Pod 安全策略是兩個典型的例子,它們在各自的領域內發揮著至關重要的作用。

網路策略

網路策略(Network Policy)允許您控制 Pod 之間的流量,從而提高叢集的安全性。透過定義允許或拒絕流量的規則,您可以防止未經授權的存取並減少潛在的安全風險。

Pod 安全策略

Pod 安全策略(Pod Security Policy)則關注於 Pod 的安全組態。它們定義了 Pod 可以執行的操作、可以存取的資源等,從而防止惡意或組態錯誤的 Pod 對叢集造成威脅。

實施策略與治理的工具

有多種工具可用於實施 Kubernetes 中的策略與治理。以下是一些值得注意的工具:

  • Open Policy Agent (OPA):OPA 是一個通用策略引擎,可以與 Kubernetes 整合,提供細粒度的策略控制。它允許您定義和實施跨多個 Kubernetes 資源的策略。
  • Kyverno:Kyverno 是另一個流行的策略管理工具,它提供了更簡單的方式來定義和管理 Kubernetes 中的策略。它支援多種策略型別,包括驗證、變異和生成策略。

最佳實踐

在實施策略與治理時,以下最佳實踐值得參考:

  • 明確定義策略:確保您的策略清晰、明確,並與企業目標保持一致。
  • 使用自動化工具:利用自動化工具來實施和監控策略,減少人為錯誤並提高效率。
  • 持續監控和改進:定期審查和更新您的策略,以確保它們仍然有效並符合不斷變化的需求。
內容解密:

本章節主要闡述了 Kubernetes 中關於容器執行時(Container Runtime)的選擇與使用,以及如何透過不同的執行時實作工作負載隔離(Workload Isolation)。文中提到了多種容器執行時,例如 CRI containerdcri-oFirecrackergVisorKata Containers 等,每一種都有其特定的設計目標和應用場景。這些容器執行時在安全性和隔離性方面有不同的實作方式,例如 gVisor 透過使用者空間核心提供隔離,而 Kata Containers 則利用輕量級虛擬機器實作類別似容器的使用體驗。

此外,文中還討論了使用 RuntimeClass 進行工作負載隔離的最佳實踐,包括避免因使用多種容器執行時而導致的維運複雜性,以及理解不同執行時之間的特性差異。同時,文中強調了工作負載隔離並不等同於安全的多租戶(Secure Multitenancy),需要綜合考慮 Kubernetes 叢集和 API 的整體安全性。

最後,本章節還提到了其他與 Pod 和容器安全相關的工具和技術,例如入侵檢測和異常檢測工具(如 Falco),以及如何利用這些工具來增強容器的安全性和可觀察性。整體而言,本章節為讀者提供了關於 Kubernetes 容器安全和隔離性的全面概述,並介紹了相關的最佳實踐和工具。

Kubernetes 叢集的政策與治理

在 Kubernetes 環境中,資源規範的欄位值限制是由政策和治理來管理的。與其在執行階段實施政策,不如在治理的背景下,透過評估政策來限制 Kubernetes 資源的欄位組態方式。只有符合政策評估的 Kubernetes 資源規範才被允許並提交到叢集狀態。

Cloud Native Policy Engine

為了評估哪些資源符合規範,我們需要一個足夠靈活的政策引擎來滿足各種需求。Open Policy Agent(OPA)是一個開源、靈活、輕量級的政策引擎,在雲原生生態系統中越來越受歡迎。OPA 的出現使得許多不同的 Kubernetes 治理工具得以實作。其中一個受到社群關注的 Kubernetes 政策和治理專案是 Gatekeeper。在本章的其餘部分,我們將使用 Gatekeeper 作為典型範例來說明如何實作叢集的政策和治理。

介紹 Gatekeeper

Gatekeeper 是一個開源、可自定義的 Kubernetes 准入 Webhook,用於叢集政策和治理。Gatekeeper 利用 OPA 約束框架來強制執行根據自定義資源定義(CRD)的政策。使用 CRD 可以提供整合的 Kubernetes 使用體驗,將政策編寫與實作分離。政策範本被稱為約束範本,可以在叢集之間共用和重複使用。Gatekeeper 提供了資源驗證和稽核功能。Gatekeeper 的一大優點是其可移植性,這意味著您可以在任何 Kubernetes 叢集上實作它。

範例政策

在探討如何組態 Gatekeeper 之前,保持對我們試圖解決的問題的關注非常重要。雖然每個組織/團隊都需要根據自己的需求最佳化政策,但有一些相當普遍的政策可以作為最佳實踐。讓我們來看看一些解決最常見的合規問題的政策:

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

Gatekeeper 術語

Gatekeeper 採用了與 OPA 相同的術語。瞭解這些術語對於理解 Gatekeeper 的運作非常重要。Gatekeeper 使用 OPA 約束框架,引入了三個新的術語:

  • 約束(Constraint)
  • Rego
  • 約束範本(Constraint template)

約束

約束可以被視為對 Kubernetes 資源規範的特定欄位和值所施加的限制。可以把它想成是一種政策。當定義約束時,您實際上是在宣告您不希望允許某些事情。這種方法的含義是,資源在沒有約束發出拒絕的情況下是隱含允許的。

Rego

Rego 是 OPA 原生的查詢語言。Rego 查詢是對儲存在 OPA 中的資料的斷言。Gatekeeper 將 Rego 儲存在約束範本中。

約束範本

約束範本可以被視為一種政策範本。它是可移植和可重複使用的。約束範本由型別引數和目標 Rego 組成,後者被引數化以便重複使用。

定義約束範本

約束範本是一種自定義資源定義(CRD),提供了一種範本化政策的方法,以便共用或重複使用。此外,還可以驗證政策的引數。讓我們來看看來自上游 Gatekeeper 政策函式庫的約束範本,在前面範例的背景下。在下面的範例中,我們共用了一個約束範本,提供「只允許來自受信任的容器登入檔的容器」的政策:

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[_]

內容解密:

上述 YAML 程式碼定義了一個名為 k8sallowedrepos 的約束範本,用於限制容器映像檔的字首必須來自指定的清單。

  • apiVersionkind 指定了這個資源的型別是 ConstraintTemplate
  • metadata 部分包含了這個約束範本的中繼資料,如名稱、標題和版本。
  • spec 部分定義了這個約束範本的具體內容,包括 CRD 的定義和 Rego 查詢。
  • crd.spec.names.kind 指定了這個約束範本所對應的 CRD 的種類別。
  • validation 部分定義了 parameters 欄位的結構描述。
  • targets 部分指定了這個約束範本所針對的目標,在這裡是 admission.k8s.gatekeeper.sh
  • rego 部分定義了 Rego 查詢,用於檢查容器映像檔的字首是否符合指定的清單。

這個約束範本可以用於檢查叢集中的容器映像檔是否來自受信任的登入檔。如果容器映像檔的字首不在指定的清單中,則會觸發違規並顯示錯誤訊息。