從0到1使用Kubernetes系列(八):Kubernetes安全

本文是從 0 到 1 使用 Kubernetes 系列第八篇,上一篇從0到1使用Kubernetes系列(七):網路介紹了 K8S 網路相關的內容,本文將帶你了解 K8S 的安全問題。

Kubernetes 的安全是一個相當廣泛的主題,涉及很多高度相關的內容。和探討大部分安全性相關的問題一樣,首先需要考慮威脅模型——誰可能攻擊你的系統,以及他們如何做到這一點。這可以幫你確定安全工作的優先順序。對於大多數 Kubernetes 應用有三類主要的攻擊者:

  1. 外部攻擊者:當你在內部或雲上部署應用時,你可能面臨來自集群外的攻擊。這類攻擊者沒有系統許可權,所以會專註於公開的服務,會嘗試獲取訪問許可權並提升許可權。
  2. 泄露的容器:Kubernetes 集群通常運行著各種工作負載。攻擊者也可能利用集群中運行的容器的漏洞進行攻擊,在這種時候,要最大程度降低漏洞攻擊影響到整個集群的風險。攻擊者可以訪問單個容器的資源,因此限制容器許可權至關重要。
  3. 惡意用戶:Kubernetes 是一個多用戶系統。攻擊者可能擁有某用戶的賬戶,並企圖獲得更多許可權,這種情況比較複雜,要具體分析,需要限制不同用戶的訪問許可權。

圍繞雲原生基礎概念構建的模型可以幫你建立對 Kubernetes 安全的總體認識。下圖將安全劃分為四個層級,被稱為雲原生安全的4C模型。管理員將在不同的層次上應對三類攻擊者。

1.png

4C 指的是雲(Cloud)、集群(Cluster),容器(Containers)和程式碼(Code)

正如你在圖中所看見的,4C 模型中每部分的安全性都是相互包含的。只依靠增強程式碼層次安全來預防雲、集群和容器中安全漏洞是幾乎不可能的。適當提高其他層的安全能力,就已經為你的程式碼提供強大的基礎安全保障。下面將詳細介紹這四部分內容。

Cloud

大多數情況下,云為 Kubernetes 集群提供可信的計算資源。如果雲的基礎設置是不可靠的(或以易受到攻擊的方式配置),那就沒有辦法保證在這個基礎上構建的 Kubernetes 集群的安全性。每一個雲服務提供商都向他們的客戶提供大量如何在其環境安全運行負載的建議。下面提供常用雲服務廠商的安全文檔鏈接,並且提供了構建安全 Kubernetes 集群的建議。

雲服務提供商安全文檔列表

雲服務廠商 鏈接
阿里雲 //www.alibabacloud.com/trust-center
AWS //aws.amazon.com/security/
Google Cloud Platform //cloud.google.com/security/
Microsoft Azure //docs.microsoft.com/en-us/azure/security/azure-security

如果你運行在自己的硬體上或者其他雲服務提供商,請查閱文檔獲取最佳安全實踐。

通用的安全建議

  • 理想情況下,不開放 Kubernetes Master 節點公網訪問,並且限制能夠訪問集群 Master 節點的 IP 地址。

  • 通過網路安全組等配置工作節點只接受 Master 節點上指定埠的連接,並且接受 Kubernetes 中服務類型為 NodePort 和 LoadBalancer 的連接。如果可能,這些節點也不應該暴露在公網中。

  • Kubernetes 訪問雲服務提供商的 API,每一個雲服務提供商都賦予 Kubernetes 的 Master 和 Node 不同的許可權。該訪問許可權遵循其管理資源所需資源的最小許可權原則。

  • 訪問 etcd, 只有在 master 節點中通過 TLS 可以訪問 etcd。

  • 在所有可能情況下,對停用狀態的的驅動設備加密。ectd 擁有整個集群的狀態(包括密鑰資訊),因此對其磁碟要在其停用的時候加密。

Cluster

Kubernetes 是一個複雜的系統,下圖展示了一個集群不同的組成部分,為了保證集群整體的安全,需要仔細保護每一個組件。

2.png

將需要注意保護的集群組件劃分成兩個部分:

  1. 保護組成集群的可配置組件
  2. 保護運行在集群中的應用

集群的組件

  1. 控制對 Kubernetes API 的訪問

    使用 TLS 進行安全通訊。Kubernetes 期望默認情況下使用 TLS 對集群中所有 API 通訊進行加密,大多數安裝方式都會創建必要的證書並分發給集群組件。

    API 認證。在安裝集群時,為API伺服器選擇與通用訪問模式匹配的身份驗證機制。例如,小型單用戶集群可能希望使用簡單的證書或靜態Bearer令牌方法。較大的群集可能希望集成現有的OIDC或LDAP伺服器,以將用戶細分為多個組。更多有資訊請參考認證

    API 授權。一旦通過身份驗證,每個API調用也都有望通過授權檢查。Kubernetes 附帶了一個集成的基於角色的訪問控制(RBAC)組件,該組件將傳入的用戶或組與捆綁到角色中的一組許可權進行匹配。這些許可權將動詞(get,create,delete)與資源(pods,service,nodes)結合在一起,並且可以是命名空間或集群作用域。提供了一組現成的角色,這些角色根據客戶端可能要執行的操作提供合理的默認責任分離。更多有關資訊請參考授權

  2. 控制對 Kubelet 的訪問。

    Kubelet 在埠10250和10255上提供小型 REST API。埠10250是讀/寫埠,而10255是具有API端點子集的只讀埠。這些端點授予對節點和容器的強大控制權。默認情況下,Kubelets允許未經身份驗證對此API進行訪問。生產集群應啟用 Kubelet 身份驗證和授權,可以通過設置 --read-only-port=0 來禁用只讀埠,但是10250 埠用於系統指標收集和其他重要功能,所以開發者必須仔細控制對此埠的訪問。更多有關資訊請參考Kubelet身份驗證/授權

  3. 保護集群組件不受損壞

    • 限制對 etcd 的訪問。對API的etcd後端的寫入訪問權等同於在整個集群上獲得root許可權,而讀取訪問權也可以獲取集群資訊。管理員應始終使用從API伺服器到etcd伺服器的強憑據,例如通過TLS客戶端證書的相互身份驗證,通常建議 etcd伺服器隔離在僅API伺服器可以訪問的防火牆後面。
    • 限制對Alpha或Beta功能的訪問。Alpha和Beta Kubernetes功能正在積極開發中,並且可能會存在限制或錯誤,從而導致安全漏洞。始終評估Alpha或Beta功能可能提供的價值,以防對您的安全狀況造成潛在風險。如有疑問,請禁用不使用的功能。
    • 啟用審核日誌記錄。審核記錄器是一項Beta版功能,可記錄API的行為,在出現問題後提供分析依據。
    • 經常輪換基礎設施憑證。密鑰和憑證生存周期越短,就越難被攻擊者利用。
    • 在啟用第三方集成之前,請先進行審查。
    • 停用時加密 ectd。etcd資料庫將包含可通過Kubernetes API訪問的所有資訊,可能使攻擊者深入了解群集的狀態。
    • 接收有關安全更新和報告漏洞的警報。

集群中的應用

根據應用程式受到的攻擊,關注安全的特定方面。例如,運行中的服務 A 對於其他應用非常重要,而服務 B 容易受到資源耗盡攻擊,如果不設置服務 B 的資源限制,就會因為服務 B 耗盡資源導致服務 A 不可用。所以需要注意下面幾個常見安全措施:

  • 定義資源限制

    默認情況下,Kubernetes 集群中對所有資源沒有對 CPU 、記憶體和磁碟的使用限制。可以通過創建資源配額策略,並附加到 namespace 中來限制資源的使用。

    下面的例子將限制命名空間中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
        requests.nvidia.com/gpu: 4
    

    分配資源配額到命名空間:

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

    查看 namespace 資源使用情況:

    [root@localhost ~]# kubectl describe quota compute-resources --namespace=myspace
    Name:                    compute-resources
    Namespace:               myspace
    Resource                 Used  Hard
    --------                 ----  ----
    limits.cpu               0     2
    limits.memory            0     2Gi
    pods                     0     4
    requests.cpu             0     1
    requests.memory          0     1Gi
    requests.nvidia.com/gpu  0     4
    

    也可以為 Pod 添加資源限制,設置記憶體請求為 256MiB,記憶體限制為512MiB

    “`yaml apiVersion: v1 kind: Pod metadata: name: default-mem-demo spec: containers:

    • name: default-mem-demo-ctr image: nginx resources: limits: memory: 512Mi requests: memory: 256Mi “`
  • Pod 安全策略

    作為 Pod 的組成部分,容器通常配置有非常實用的安全默認值,這些默認值適用於大多數情況。但是,有時 Pod 可能需要其他許可權才能執行其預期任務,在這種情況下,我們需要增強 Pod 的默認許可權。安全上下文定義了 Pod 或容器的特權和訪問控制,安全上下文設置有:

    1. 委託訪問:基於用戶ID 和用戶組ID 許可權去訪問資源對象(如文件)。
    2. SELinux:為對象分配安全標籤
    3. 以特權或非特權用戶運行
    4. Linux 功能:為進程提供一些特權,而不去賦予它root用戶的所有特權
    5. AppArmor:使用程式配置文件來限制單個程式的功能。
    6. Seccomp:過濾進程的系統調用
    7. 允許提升許可權(AllowPrivilegeEscalation):子進程能否獲得父進程更多的許可權。這個布爾值直接控制是否在容器進程上設置了 no_new_privs 標誌。在以下情況下 AllowPrivilegeEscalation 始終為 true——一是,以特權OR運行;二是,具有 CAP_SYS_ADMIN

    在 securityContext 欄位下配置安全策略,在 Pod 中指定的安全策略將被應用於所有容器,容器中指定的安全策略應用於單個容器,當它們重複時,容器級會覆蓋 Pod 級的的安全策略。

    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: [ "sh", "-c", "sleep 1h" ]
        volumeMounts:
        - name: sec-ctx-vol
          mountPath: /data/demo
        securityContext:
          runAsUser: 2000
          allowPrivilegeEscalation: false
    

    更多有關資訊請參考Pod 安全策略

  • 網路規則

    Kubernetes允許來自集群中任何容器的所有網路流量發送到集群中的任何其他容器並由其接收。當嘗試隔離工作負載時,這種開放式方法沒有幫助,因此需要應用網路策略來幫助開發者實現所需的隔離。Kubernetes NetworkPolicy API使開發者能夠將入口和出口規則應用於選定的Pod,用於第3層和第4層流量,並依賴於實現容器網路介面(CNI)的兼容網路插件的部署。

    網路策略是 namespace 作用域,並根據匹配標籤(例如,tier:backend)的選擇應用於Pod。當NetworkPolicy對象的Pod選擇器與Pod匹配時,根據策略中定義的入口和出口規則來管理進出Pod的流量。 所有來自或發往該Pod的流量都會被拒絕,除非有允許它的規則。

    要在Kubernetes集群中正確隔離網路和傳輸層的應用程式,網路策略應以「拒絕所有」的默認前提開始。然後,應將每個應用程式組件及其所需源和目標的規則逐個列入白名單,並進行測試以確保流量模式按預期工作。

  • 密鑰管理

    Kubernetes 使用 Secrets 保護應用程式需要訪問敏感資訊——密碼、X.509證書、SSH密鑰或OAuth令牌等。它通過卷裝入,對它的訪問嚴格限於那些需要使用它的實體(用戶和Pod),且當存儲在磁碟上時(靜止狀態)它是不可訪問或只讀的。

需要考慮的全部安全問題如下:

需要關注的安全領域 建議
RBAC 授權 //kubernetes.io/docs/reference/access-authn-authz/rbac/
認證方式 //kubernetes.io/docs/reference/access-authn-authz/controlling-access/
密鑰管理 //kubernetes.io/docs/concepts/configuration/secret/ //kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
Pod 安全規則 //kubernetes.io/docs/concepts/policy/pod-security-policy/
服務品質 //kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/
網路規則 //kubernetes.io/docs/concepts/services-networking/network-policies/
ingress 的 TLS //kubernetes.io/docs/concepts/services-networking/ingress/#tls

Contanier

為了在 Kunernetes 中運行軟體,必須將它打包成容器。需要考慮下面的注意事項,來保證容器符合 Kubernetes 安全配置。

  • 最小化鏡像

    理想情況下,使用應用程式二進位文件和二進位文件所依賴的的任何相關項來創建鏡像。事實上,沒有什麼阻止開發者將 scratch 作為基礎鏡像,並將靜態鏈接的二進位文件複製到鏡像中。它沒有其他依賴,鏡像中包含單個文件,以及一些描述容器如何運行的元數據。最小化鏡像加快鏡像的分發速度,並且顯著減少容器內部的受攻擊面。

  • 基礎鏡像

    但是這並不總是可行的,因此需要慎重選擇基礎鏡像。最佳的方法是使用作業系統供應商支援的鏡像,或者是 docker hub 上官方支援的鏡像。不要盲目使用之前未經過審查的不受信任來源的鏡像,尤其是在生產環境中。

  • 鏡像掃描

    鏡像掃描對於保障容器應用的安全至關重要,確保您的鏡像定期通過信譽良好的工具進行掃描,可以使用 CoreOS 的 Clair 之類的工具掃描容器中的已知漏洞,它是容器鏡像的靜態漏洞分析器。

  • 鏡像的簽名和執行

    使用 CNCF 項目的的 TUF 和 Notary 對容器進行簽名,在執行前驗證簽名,確保鏡像的正確沒有被篡改。

  • 禁止特權用戶

    在構建鏡像時,創建最低作業系統許可權的用戶完成容器的運行。

Code

最後是程式碼級別,這是程式設計師能掌控的被攻擊面,但不在 Kubernetes 的安全保護範圍,提供如下建議:

  • 僅通過 TLS 訪問

    如果您的程式碼需要通過TCP進行通訊,則理想情況下,它將提前與客戶端執行TLS握手。除少數情況外,默認行為應是對傳輸中的所有內容進行加密。

  • 限制通訊範圍

    無論什麼情況下,程式只應該公開必要的埠。

  • 第三方依賴安全性

    確保第三方依賴是安全的。

  • 靜態程式碼分析

    大多數語言都提供了靜態程式碼分析,可以分析程式碼中是否存在潛在的不安全編碼實踐。

  • 動態探測攻擊

    自動化工具可以針對您的服務嘗試會破壞服務的攻擊。這些包括SQL注入,CSRF和XSS。最受歡迎的動態分析工具之一是OWASP Zed Attack代理。


本文由豬齒魚技術團隊原創,轉載請註明出處