全部產品
Search
文件中心

Container Service for Kubernetes:Pod安全

更新時間:Jun 19, 2024

Container Service for Kubernetes中,您可以通過限制容器以特權模式運行、限制應用程式進程以root身份運行以及禁用Service Account令牌自動掛載等方式,防止容器中啟動並執行進程逃離容器的隔離邊界並獲得對宿主機的存取權限。通過正確配置Pod安全性原則以加固叢集的安全性,防止叢集成為攻擊者利用的目標。

防止進程逃離容器邊界並獲得許可權

作為使用Kubernetes的開發或者營運人員,您需要重點關注如何防止在容器中啟動並執行進程逃離容器的隔離邊界並獲得對宿主機的存取權限。這樣做主要有兩個原因:

  • 首先,容器內啟動並執行進程預設在[Linux] root使用者的上下文中運行。儘管root在容器中的操作部分受到Docker分配給容器的Linux capabilities的限制,但這些預設許可權可能允許攻擊者提權或者訪問到宿主機的敏感資訊,包括SecretsConfigMap等敏感資源。下面是分配給Docker容器的預設capabilities列表。更多資訊,請參見capabilities(7) — Linux manual page

    cap_chown, cap_dac_override, cap_fowner, cap_fsetid, cap_kill, cap_setgid, cap_setuid, cap_setpcap, cap_net_bind_service, cap_net_raw, cap_sys_chroot, cap_mknod, cap_audit_write, cap_setfcap.

    應儘可能避免使用以特權身份(privileged)運行Pod,因為其擁有與宿主機上root關聯的所有Linuxcapabilities

  • 其次,所有Kubernetes工作節點都使用一種稱為節點授權者的授權模式。節點授權者授權所有源自Kubelet的API請求,並允許節點執行以下操作:

    讀操作:

    • Services

    • Endpoints

    • Nodes

    • Pods

    • 與綁定到Kubelet節點的Pod相關的Secrets、Configmaps、PV和PVC

    寫操作:

    • 節點和節點狀態(啟用NodeRestriction准入外掛程式以限制Kubelet修改自己的節點)

    • Pods和Pod狀態(啟用NodeRestriction准入外掛程式以限制Kubelet修改綁定到自身的Pod)

    • Events

    Auth相關操作:

    • 對用於TLS引導的CertificateSigningRequest (CSR) API的讀/寫存取權限

    • 能夠為委託的身份認證/授權檢查建立TokenReviewSubjectAccessReview

ACK叢集預設使用節點限制准入控制器。該控制器僅允許節點修改綁定到節點的一組有限節點屬性和Pod對象,但是設法訪問主機的攻擊者仍然能夠從Kubernetes API搜集環境中的敏感資訊。更多資訊,請參見節點限制准入控制器

Pod安全配置建議

  • 限制容器以特權模式運行

    如前所述,以特權身份啟動並執行容器繼承了分配給主機上root的所有Linux capabilities。大多數情境下,容器並不是必須擁有這些許可權才能保證業務運行。您可以通過建立Pod安全性原則來拒絕容器配置為以特權模式啟動並執行Pod。您可以將Pod安全性原則視為Pod在建立之前必須滿足的一組安全約束。ACK提供了基於OPA和gatekeeper的容器安全性原則能力,可以驗證在叢集上建立和更新Pod的請求,該請求基於使用者配置的安全規則。如果建立或更新Pod的請求不符合定義的規則,系統將拒絕該請求並返回錯誤。同樣,您可以通過部署ACKPSPPrivilegedContainer策略限制,在叢集指定範圍的命名空間中部署privileged特權容器。

  • 限制應用程式進程以root身份運行

    預設情況下,容器都以root身份運行。如果攻擊者能夠利用應用程式中的漏洞並獲得正在啟動並執行容器的Shell存取權限,這可能會出現安全問題。您可以通過多種方式緩解此類風險。一種方式是,通過從容器鏡像中刪除Shell。另一種方式是,將USER指令添加到您的Dockerfile或以非root使用者身份在Pod中運行容器。Kubernetes podSpec在spec.securityContext下包含runAsUserrunAsGroup兩個欄位,允許您指定運行應用程式的使用者和組。您可以通過建立ACKPSPAllowedUsers策略來限制。

  • 禁止以Docker in Docker的方式運行容器或者在容器中掛載Docker.sock

    使用嵌套容器或者掛載Docker.sock的方式可以方便地在Docker容器中構建/運行容器鏡像,但您將節點的控制權交給了在容器中啟動並執行進程。關於在Kubernetes上構建容器鏡像,請參見使用企業版執行個體構建鏡像Kanikoimg

  • 限制使用HostPath,如果需要使用HostPath,限制只可以掛載指定首碼的目錄並將卷配置為唯讀

    使用HostPath可以直接將宿主機的目錄掛載到容器中。很少有業務情境的Pod用到此功能特性。但如果確實有業務需要,您需要瞭解其中的風險。預設情況下,以root身份啟動並執行Pod將擁有對HostPath暴露的檔案系統的寫存取權限。這可能允許攻擊者修改Kubelet設定,建立指向未直接通過HostPath暴露的目錄或檔案的符號連結,例如/etc/shadow、安裝Ssh密鑰、讀取掛載到主機的密鑰以及進行惡意操作。為了降低使用HostPath的風險,請將spec.containers.volumeMounts 配置為唯讀,例如:

    volumeMounts:
    - name: hostPath-volume
        readOnly: true
        mountPath: /host-path

    同樣,您可以通過部署ACKPSPHostFilesystem策略執行個體,限制在叢集指定命名空間範圍內部署的Pod允許掛載的主機Host目錄範圍。

  • 為每個容器佈建要求和資源限制,避免資源爭奪或DoS攻擊

    沒有請求或資源限制的Pod理論上可以消耗掉主機上的所有可用資源。當有Pod被調度到此節點上時,該節點可能會遭遇CPU或記憶體不足的情況,這可能導致Kubelet崩潰或從節點驅逐Pod。雖然無法完全避免這種情況的發生,但佈建要求和資源限制將有助於最大程度地減少資源爭奪,並降低應用程式編寫不當導致資源消耗過多所帶來的風險。

    PodSpec允許您限制CPU和記憶體的使用。您可以通過在命名空間上設定Resource Quota或建立Limit Range來強制對請求和資源進行限制。資源配額允許您指定分配給命名空間的資源總量,例如CPU和RAM。當應用於命名空間時,會強制您為部署到該命名空間中的所有容器指定請求和資源的限制。相比之下,限制範圍可讓您更精細地控制資源分派。通過限制範圍,您可以為命名空間內的每個Pod或每個容器的CPU和記憶體資源設定最小值/最大值。如果沒有提供,您還可以設定預設請求/限制值。更多資訊,請參見Managing Resources for Containers

    同樣,您可以通過部署ACKContainerLimits策略執行個體,要求在叢集指定命名空間範圍內部署的應用Pod必須配置的資源限制。

  • 禁止使用權限提高配置

    權限提高允許進程更改其運行所在的安全上下文。例如sudo,帶有SUIDSGID位的二進位檔案也是如此。特權升級基本上是使用者以另一個使用者或組的許可權執行檔案的一種方式。您可以將allowPriviledgedEscalation設定為falsepod安全性原則或通過在podSpec中設定securityContext.allowPrivilegedEscalation來阻止容器進行權限提高。

    同樣,您可以通過部署ACKPSPAllowPrivilegeEscalationContainer策略執行個體,強制要求在叢集指定命名空間範圍內部署的Pod配置allowPrivilegeEscalation參數。

  • 禁用Service Account令牌自動掛載

    對於不需要訪問Kubernetes API的Pod,您可以在PodSpec上禁止自動掛載ServiceAccount令牌,或禁用所有使用特定ServiceAccount的Pod。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-no-automount
    spec:
      automountServiceAccountToken: false

    禁用ServiceAccount自動掛載不會阻止Pod對Kubernetes API的網路訪問。為阻止Pod對Kubernetes API進行網路訪問,您需要修改ACK叢集Endpoint訪問並使用網路原則Network Policy來阻止Pod對Kubernetes API進行網路訪問。具體操作,請參見在ACK叢集使用網路原則

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sa-no-automount
    automountServiceAccountToken: false

    同樣,您可以通過部署ACKBlockAutomountToken策略執行個體,要求在應用Pod中設定automountServiceAccountToken: false欄位,以防止自動掛載Service Account。

  • 禁用服務發現

    對於不需要尋找或調用叢集服務的Pod,您可以減少提供給Pod的資訊量。您可以將Pod的DNS原則設定為不使用CoreDNS,並且不將命名空間中的Service暴露為Pod中的環境變數。更多資訊,請參見Environment variables

    Pod的DNS策略的預設值是ClusterFirst,使用叢集內DNS,而非預設值Default使用底層節點的DNS解析。更多資訊,請參見Kubernetes docs on Pod DNS policy

    禁用服務鏈結接和更改Pod的DNS策略不會阻止Pod對叢集內DNS服務進行網路訪問。攻擊者仍然可以通過訪問叢集內DNS服務來枚舉叢集中的服務(例如:dig SRV *.*.svc.cluster.local @$CLUSTER_DNS_IP)。關於阻止叢集內服務發現,請參見在ACK叢集使用網路原則

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-no-service-info
    spec:
        dnsPolicy: Default # “預設值”不是真正的預設值。
        enableServiceLinks: false
  • 配置鏡像為唯讀檔案系統

    將您的鏡像配置為唯讀檔案系統可防止攻擊者覆蓋您的應用程式使用的檔案系統上的檔案。如果您的應用程式必須寫入檔案系統,請考慮寫入臨時目錄或掛載附加卷。您可以通過如下設定Pod的SecurityContext來強制執行此操作:

    ...
    securityContext:
      readOnlyRootFilesystem: true
    ...

    同樣,您可以通過部署ACKPSPReadOnlyRootFilesystem策略執行個體,限制在叢集指定命名空間範圍內部署的Pod只能使用唯讀根檔案系統。