Kubernetes的原生多租戶解決方案


Kubernetes的原生多租戶解決方案

Kubernetes提供一系列原生Kubernetes API與資源,用於幫助在單一集群內建立起多租戶體系。下面,我們將介紹如何在計算、網絡以及存儲方面實現多租戶資源隔離。

計算隔離

Kubernetes說明文檔中將命名空間定義為“一種在多個用戶之間分配集群資源的方法”,這也使其成為多租戶機制的基礎。大多數Kubernetes資源對象都屬於一個命名空間。在下圖中,我們定義了兩個命名空間,每個命名空間各自運行一組彼此隔離的資源對象。

雖然K8S中並沒有租戶這樣的概念,命名空間本身也不提供工作負載或用戶的隔離,但是K8S除了以命名空間作為基礎的資源隔離單位,還提供了基於 RBAC 的權限管理方式:RBAC用於定義誰能夠在Kubernetes API上執行的操作。這種授權機制可以通過ClusterRole作用於整個集群,也可以通過Role作用於某個命名空間。例如,我們可以定義一個名為namespace1-admin的角色,該角色負責為管理員提供對namespace1命名空間的訪問權限,同時將其與名為admin-ns1的組關聯起來,具體操作代碼如下:

kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: namespace1-admin namespace: namespace1 rules: - apiGroups: ["", "extensions", "apps"] resources: ["*"] verbs: ["*"] - apiGroups: ["batch"] resources: - jobs - cronjobs verbs: ["*"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: admins-ns1-rb namespace: namespace1 subjects: - kind: Group name: admins-ns1 apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: namespace1-admin apiGroup: rbac.authorization.k8s.io

Amazon EKS通過AWS IAM Authenticator for Kubernetes提供RBAC與IAM的集成功能,可以將IAM用戶與角色映射至RBAC組。RBAC是Kubernetes的核心組件,負責控制其他隔離層的權限。我們將在后文中詳細討論。

Kubernetes允許用戶對Pod的CPU與內存資源配額做出定義與限制。為了避免節點上發生資源爭用,同時改善調度程序的資源分配,開發人員應始終設置資源配額。ResourceQuota資源配額允許用戶定義和限制一個命名空間中可以使用的Kubernetes資源或對象的數量。從計算資源的角度來看,用戶可以通過資源配額以原生方式定義CPU與內存限制,示例如下:

apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu-demo namespace: namespace1 spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi

使用資源配額,可以為工作負載分配有限的資源,防止租戶之間相互干擾。我們還可以通過Limit Ranges定義每個Pod甚至是容器的默認、最小與最大請求及其限制條件。

租戶資源也應該保證與基礎設施節點實例之間的隔離。Kubernetes Pod安全策略(PSP)是集群級的Pod安全策略,自動為集群內的Pod和Volume設置Security Context。Pod Security Policy定義了一系列Pod在系統中運行必須滿足的約束條件,以及一些默認的約束值。這要求負責構建多租戶集群的管理員通過PSP的Privileged確定Pod中是否可以啟用特權模式。通過HostNetwork控制容器是否可以使用所在節點的網絡名稱空間,防止Pod訪問回環設備和潛在的監聽網絡鄰居的活動。自1.13版本起,Amazon EKS正式支持PSP,關於更多詳細信息,請參閱AWS開源博客

Kubernetes還提供多種Pod調度方案,在調度的時候考慮Pod與Pod之間的關系,而不只是Pod與Node的關系。例如,Pod Anti-Affinity允許用戶使用以下設置保證帶有特定標簽的Pod不會被部署在同一節點之上:

apiVersion: v1 kind: Pod metadata: namespace: namespace1 name: workload-1 labels: team: "team-1" spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: "kubernetes.io/hostname" namespaces: - shared-services labelSelector: matchExpressions: - key: "type" operator: In values: ["monitoring"]

在這里,namespace1中帶有team: team-1標簽的各Pod不會與在shared-services命名空間中擁有monitoring標簽類型的Pod被部署在同一節點之上,這是為了防止業務應用與監控應用之間發生干擾。這里還有幾點需要注意。首先,為了實現這項功能,我們需要保證在適當的工作負載上應用適當的標簽。第二,這類配置可能提高大規模維護工作的難度,因為隨着要求的增加與Pod量的提升,過度復雜的調度要求可能導致某些Pod找不到合適的部署節點。最后,Pod親和性與反親和性設定會給控制平面帶來更高的工作壓力,這里不建議大家在包含數百個節點甚至規模更大的集群當中使用。與此類似,我們可以使用nodeSelectors與nodeAffinity將Pod分配給特定節點。

但如果我們希望在調度Pod的時候排除某些節點,讓這些節點只在特殊指定時使用,又該怎么辦?這種情況就需要使用“污點(taint)和容忍(toleration)”的功能。在示例中,集群管理員可以使用以下節點組配置文件在EKS上創建專有的工作節點組,用於監控及管理工作負載:

apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: dev-cluster region: eu-west-1 nodeGroups: - name: ng-monitoring instanceType: c5.8xlarge desiredCapacity: 2 taints: monitoring: "true:NoSchedule"

通過使用污點,Kubernetes調度系統會避免調度不容忍這種污點的Pod到帶有此污點標記的節點上。

另一種方式則是在EKS上使用AWS Fargate。Fargate在VM隔離的環境中運行每個Pod,而無需與其他Pod共享資源。從而消除了創建或管理EC2實例節點的需求。

網絡隔離

在默認情況下,Pod可以在同一集群的網絡上跨不同的命名空間實現通信。Kubernetes提供相應的網絡策略,允許用戶以細粒度方式定義並控制Pod之間的通信。網絡策略的具體實現,由網絡插件負責完成。在默認EKS集群當中,Pod到Pod間網絡則被委派給Amazon VPC CNI插件實現,VPC CNI插件通過支持Calico來實現Kubernetes的網絡策略。假設我們需要根據命名空間對各個租戶進行隔離,則可以使用以下網絡策略確保各租戶只能在所在命名空間namespace1之內進行網絡通信(換句話說,拒絕該集群之內不同命名空間之間的相互通信):

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-np-ns1 namespace: namespace1 spec: podSelector: {} policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: nsname: namespace1 egress: - to: - namespaceSelector: matchLabels: nsname: namespace1

網絡策略還提供更多高級配置,可用於限制多租戶集群上的通信。關於更多快速入門以及環境設置指南,請參閱Amazon EKS說明文檔中的相關內容。

我們還可以通過服務網格定義更多的保護機制,甚至可以將保護機制擴展到單一EKS集群之外。Istio是一個非常流行的開源服務網格技術,可提供流量管理、安全保護與可觀察性等多種功能。Istio團隊在相關博文中討論了如何在多租戶集群中部署Istio的詳細信息。EKS Workshop還提供關於在EKS上設置Istio的快速入門教程。用戶可以使用Istio在不同的網絡層內實施對應的身份驗證與授權策略。例如,大家可以將用於控制L3/L4網絡流量的網絡策略與L7層上基於JWT的令牌身份驗證結合起來,更好地控制來自不同租戶的服務間的通信方式。

AWS App Mesh是一種AWS提供的全托管服務網格,AWS App Mesh以Envoy為基礎,實現了服務網格控制平面的全面托管,為客戶提供了運行在AWS中應用程序的各項服務之間統一的可見性和網絡流量控制的能力。關於App Mesh的實際效果,大家可以參考Amazon EKS快速入門中的相關測試

存儲隔離

在使用共享集群時,不同的租戶可能需要不同的存儲資源類型。Kubernetes提供不同的工具用於管理存儲資源。其中最重要的當數Volume,它能夠以持久性形式將存儲資源接入Pod並管理存儲資源的整個生命周期。正如前文“計算”部分所述,這里我們不建議直接掛載由節點提供的存儲卷(大家最好在配合PSP的多租戶設計中直接禁用掉對本地存儲卷的訪問)。下面,我們將向大家介紹PersistentVolume(PV)子系統的一些關鍵功能及其與PersistentVolumeClaim (PVC)的關系。

PersistentVolume(PV)是集群中由管理員配置的網絡存儲。它是集群中的資源,

,StorageClass也是如此。集群管理員實際上是以集中方式對可用的存儲驅動程序、配置以及操作方式做出定義。在Amazon EKS中提供了不同的開箱即用的Storage Classes實現,具體包括Amazon EBS(既作為樹內插件,又可作為CSI插件)、Amazon EFS以及FSx for Lustre。而PVC則允許用戶根據存儲類中的要求為Pod請求存儲卷。PVC被定義為一個命名空間資源,並由此對租戶的存儲訪問操作進行控制。管理員可以使用存儲資源配額定義屬於特定命名空間的存儲類。例如,要在命名空間namespace1當中禁用對storagens2存儲類的使用,則可按照以下方式使用ResourceQuota:

apiVersion: v1 kind: ResourceQuota metadata: name: storage-ns1 namespace: namespace1 spec: hard: storagens2.storageclass.storage.k8s.io/requests.storage: 0

多集群間隔離

在實現多租戶方面,另外一種可行的選項是使用多個只包含單一租戶的Amazon EKS集群。通過這種策略,每個租戶都可以在共享AWS賬戶(或者專供大型企業使用的專有賬戶)之內擁有只屬於自己的Kubernetes集群。

每個集群既可以自行配置,也可以由運維管理團隊統一提供,並部署標准化配置。如果選擇后一種方法,那么運維管理團隊需要高度關注兩個問題:集群配置和多集群監控。

客戶在使用Amazon EKS托管的控制平面的同時,可能還希望在新建集群上采用統一的配置標准。在這種情況下,Terraform可以與Kubernetes Provider一起配合使用,保證以自動化方式部署前文提到的PSP或網絡策略。注意:EKS在每個區域內單一賬戶中設定了100個EKS集群的配額上限,但大家也可以根據需求進行更改。

在集群部署完成之后,我們可能還需要對所有已部署的多個集群進行審查,監控各租戶運行狀況、保證目前運行的EKS控制平面為最新版本且運行情況良好。Rancher是一款流行的開源工具,可用於管理多Kubernetes集群,這里建議大家參考開源博客上的講解文章以了解Rancher部署與使用方面的詳細信息。

總結

 

聊聊 Amazon EKS 集群上的多租戶設計注意事項

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM