本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 部署的安全最佳實務

注意:此文章中的某些建議已不再適用。目前的叢集強化選項已在本文件中說明。

編者註:今天的文章由 Aqua Security 的 Amir Jerbi 和 Michael Cherny 撰寫,內容描述 Kubernetes 部署的安全最佳實務,根據他們從內部部署和雲端部署中看到的各種使用案例收集的資料。

Kubernetes 提供了許多控制項,可以大幅提升您的應用程式安全性。設定這些控制項需要深入了解 Kubernetes 和部署的安全需求。我們在此強調的最佳實務與容器生命週期一致:建置、交付和執行,並且專門針對 Kubernetes 部署量身定制。我們在 我們自己的 SaaS 部署中採用了這些最佳實務,該部署在 Google Cloud Platform 上執行 Kubernetes。

以下是我們針對部署安全 Kubernetes 應用程式的建議

**確保映像檔沒有漏洞 **
執行具有漏洞的容器會使您的環境容易受到危害的風險。許多攻擊可以透過簡單地確保沒有具有已知漏洞的軟體組件來緩解。

  • 實作持續安全漏洞掃描 -- 容器可能包含具有已知漏洞 (CVE) 的過時套件。這不能是「一次性」的流程,因為每天都會發布新的漏洞。持續評估映像檔的持續性流程對於確保所需的安全態勢至關重要。

  • 定期將安全更新套用至您的環境 -- 一旦在執行中的容器中發現漏洞,您應始終更新來源映像檔並重新部署容器。盡量避免直接更新 (例如,對執行中的容器進行「apt-update」),因為這可能會破壞映像檔與容器之間的關係。使用 Kubernetes 滾動更新功能升級容器非常容易 - 這允許透過將執行中的應用程式的映像檔升級到最新版本來逐步更新應用程式。

確保您的環境中僅使用授權的映像檔
如果沒有確保僅允許執行符合組織策略的映像檔的流程,則組織將面臨執行易受攻擊甚至惡意容器的風險。從不明來源下載和執行映像檔是危險的。這相當於在生產伺服器上執行來自不明供應商的軟體。請勿這樣做。

使用私有登錄檔儲存您核准的映像檔 - 確保您僅將核准的映像檔推送至這些登錄檔。僅此一項就已經縮小了範圍,將進入您管道的潛在映像檔數量減少到數十萬個公開可用映像檔的一小部分。建置整合安全評估(如漏洞掃描)的 CI 管道,使其成為建置流程的一部分。

CI 管道應確保僅使用經過審查的程式碼(已核准用於生產環境)來建置映像檔。一旦建置映像檔,就應掃描其安全漏洞,並且僅在未發現問題的情況下,才將映像檔推送至私有登錄檔,然後從該登錄檔部署到生產環境。安全評估中的失敗應在管道中產生失敗,防止安全品質不良的映像檔被推送至映像檔登錄檔。

Kubernetes 中正在進行映像檔授權外掛程式的工作(預計在 Kubernetes 1.4 中推出),這將允許防止交付未經授權的映像檔。如需更多資訊,請參閱此 提取請求

限制對 Kubernetes 節點的直接存取
您應限制對 Kubernetes 節點的 SSH 存取,以降低未經授權存取主機資源的風險。相反,您應要求使用者使用「kubectl exec」,這將提供對容器環境的直接存取,而無法存取主機。

您可以使用 Kubernetes 授權外掛程式進一步控制使用者對資源的存取權限。這允許為特定命名空間、容器和操作定義精細的存取控制規則。

在資源之間建立管理邊界
限制使用者權限的範圍可以減少錯誤或惡意活動的影響。Kubernetes 命名空間允許您將建立的資源劃分為邏輯命名的群組。在一個命名空間中建立的資源可以對其他命名空間隱藏。預設情況下,Kubernetes 叢集中使用者建立的每個資源都在名為 default 的預設命名空間中執行。您可以建立其他命名空間,並將資源和使用者附加到這些命名空間。您可以使用 Kubernetes 授權外掛程式來建立策略,以隔離不同使用者對命名空間資源的存取權限。

例如:以下策略將允許「alice」從命名空間「fronto」讀取 Pod。

{

  "apiVersion": "abac.authorization.kubernetes.io/v1beta1",

  "kind": "Policy",

  "spec": {

    "user": "alice",

    "namespace": "fronto",

    "resource": "pods",

    "readonly": true

  }

}

定義資源配額
執行資源不受限制的容器選項會使您的系統面臨 DoS 或「吵雜鄰居」情境的風險。為了預防和最大限度地降低這些風險,您應定義資源配額。預設情況下,Kubernetes 叢集中的所有資源都是使用不受限制的 CPU 和記憶體請求/限制建立的。您可以建立附加到 Kubernetes 命名空間的資源配額策略,以限制 Pod 允許消耗的 CPU 和記憶體。

以下是命名空間資源配額定義的範例,它將命名空間中 Pod 的數量限制為 4 個,將其 CPU 請求限制在 1 到 2 之間,並將記憶體請求限制在 1GB 到 2GB 之間。

compute-resources.yaml

apiVersion: v1  
kind: ResourceQuota  
metadata:  
  name: compute-resources  
spec:  
  hard:  
    pods: "4"  
    requests.cpu: "1"  
    requests.memory: 1Gi  
    limits.cpu: "2"  
    limits.memory: 2Gi

將資源配額分配給命名空間

kubectl create -f ./compute-resources.yaml --namespace=myspace

實作網路分段

在同一個 Kubernetes 叢集上執行不同的應用程式會產生一個風險,即一個受損的應用程式攻擊相鄰的應用程式。網路分段對於確保容器只能與它們應該通訊的對象通訊非常重要。

Kubernetes 部署中的挑戰之一是在 Pod、服務和容器之間建立網路分段。由於容器網路身分 (IP) 的「動態」性質,以及容器可以在同一個節點內部或節點之間通訊的事實,這是一個挑戰。

Google Cloud Platform 的使用者可以受益於自動防火牆規則,防止跨叢集通訊。可以使用網路防火牆或 SDN 解決方案在內部部署類似的實作。Kubernetes 網路 SIG 正在這個領域進行工作,這將大大改進 Pod 到 Pod 的通訊策略。新的網路策略 API 應解決圍繞 Pod 建立防火牆規則的需求,限制容器化可以擁有的網路存取權限。

以下是一個網路策略的範例,該策略控制「後端」Pod 的網路,僅允許來自「前端」Pod 的入站網路存取

POST /apis/net.alpha.kubernetes.io/v1alpha1/namespaces/tenant-a/networkpolicys  
{  
  "kind": "NetworkPolicy",

  "metadata": {

    "name": "pol1"

  },

  "spec": {

    "allowIncoming": {

      "from": [{

        "pods": { "segment": "frontend" }

      }],

      "toPorts": [{

        "port": 80,

        "protocol": "TCP"

      }]

    },

    "podSelector": {

      "segment": "backend"

    }

  }

}

在此處閱讀有關網路策略的更多資訊 這裡

將安全上下文套用至您的 Pod 和容器

在設計容器和 Pod 時,請確保為您的 Pod、容器和磁碟區配置安全上下文。安全上下文是在部署 yaml 中定義的屬性。它控制將分配給 Pod/容器/磁碟區的安全參數。一些重要的參數是

安全上下文設定描述
SecurityContext->runAsNonRoot指示容器應以非 root 使用者身分執行
SecurityContext->Capabilities控制分配給容器的 Linux 功能。
SecurityContext->readOnlyRootFilesystem控制容器是否能夠寫入根檔案系統。
PodSecurityContext->runAsNonRoot防止以「root」使用者身分執行容器作為 Pod 的一部分

以下是具有安全上下文參數的 Pod 定義範例

apiVersion: v1  
kind: Pod  
metadata:  
  name: hello-world  
spec:  
  containers:  
  # specification of the pod’s containers  
  # ...  
  securityContext:  
    readOnlyRootFilesystem: true  
    runAsNonRoot: true

參考 這裡

如果您正在執行具有提升權限的容器 (--privileged),則應考慮使用「DenyEscalatingExec」准入控制。此控制拒絕對以允許主機存取的提升權限執行的 Pod 執行 exec 和 attach 命令。這包括以特權模式執行的 Pod、有權存取主機 IPC 命名空間以及有權存取主機 PID 命名空間的 Pod。有關准入控制的更多詳細資訊,請參閱 Kubernetes 文件

記錄一切

Kubernetes 提供基於叢集的日誌記錄,允許將容器活動記錄到中央日誌中心。建立叢集後,可以使用在每個節點上執行的 Fluentd 代理將每個容器的標準輸出和標準錯誤輸出擷取到 Google Stackdriver Logging 或 Elasticsearch 中,並使用 Kibana 檢視。

摘要

Kubernetes 提供了許多選項來建立安全的部署。沒有一種適用於所有地方的通用解決方案,因此需要對這些選項有一定的熟悉程度,並了解它們如何增強您的應用程式安全性。

我們建議實作本部落格中強調的最佳實務,並使用 Kubernetes 彈性配置功能將安全流程整合到持續整合管道中,以安全地「嵌入」安全性來自動化整個流程。