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

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 建立防火牆規則的需求,限制容器化應用程式可以擁有的網路訪問許可權。

以下是一個網路策略的示例,它控制“backend”Pod 的網路,只允許來自“frontend”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防止容器在 Pod 中以 'root' 使用者身份執行

以下是帶有安全上下文引數的 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 命令。這包括以特權身份執行、有權訪問主機 IPC 名稱空間和有權訪問主機 PID 名稱空間的 Pod。有關准入控制的更多詳細資訊,請參閱 Kubernetes 文件

記錄一切

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

總結

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

我們建議實施本部落格中強調的最佳實踐,並利用 Kubernetes 靈活的配置功能將安全流程整合到持續整合管道中,透過安全“無縫嵌入”來自動化整個過程。