Kubernetes 資料平面 - Amazon EKS

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

Kubernetes 資料平面

選取 EC2 執行個體類型可能是客戶面臨的最困難決策之一,因為在具有多個工作負載的叢集中。沒有one-size-fits解決方案。以下是一些秘訣,可協助您避免擴展運算的常見陷阱。

自動節點自動擴展

我們建議您使用節點自動調整規模,以減少混音並與 Kubernetes 深度整合。建議大規模叢集使用受管節點群組Karpenter

受管節點群組將為您提供 Amazon EC2 Auto Scaling 群組的彈性,並為受管升級和組態提供額外優勢。它可以使用 Kubernetes Cluster Autoscaler 進行擴展,並且是具有各種運算需求的叢集的常見選項。

Karpenter 是由 AWS 建立的開放原始碼、工作負載原生節點自動擴展器。它會根據資源 (例如 GPU) 的工作負載需求,以及污點和容錯 (例如區域分散) 來擴展叢集中的節點,而無需管理節點群組。節點直接從 EC2 建立,可避免預設節點群組配額 - 每個群組 450 個節點 - 並提供更大的執行個體選擇彈性,並降低營運開銷。我們建議客戶盡可能使用 Karpenter。

使用許多不同的 EC2 執行個體類型

每個 AWS 區域每個執行個體類型的可用執行個體數量有限。如果您建立的叢集僅使用一種執行個體類型,並將節點數量擴展到超過該區域的容量,您會收到沒有執行個體可用的錯誤。為了避免此問題,您不應任意限制叢集中可以使用的執行個體類型。

根據預設,Karpenter 將使用廣泛的相容執行個體類型,並根據待定工作負載需求、可用性和成本在佈建時挑選執行個體。您可以擴大 NodePools karpenter.k8s.aws/instance-category金鑰中使用的執行個體類型清單。

Kubernetes Cluster Autoscaler 需要類似大小的節點群組,才能持續擴展。您應該根據 CPU 和記憶體大小建立多個群組,並獨立擴展。使用 ec2-instance-selector 來識別節點群組大小相似的執行個體。

ec2-instance-selector --service eks --vcpus-min 8 --memory-min 16
a1.2xlarge
a1.4xlarge
a1.metal
c4.4xlarge
c4.8xlarge
c5.12xlarge
c5.18xlarge
c5.24xlarge
c5.2xlarge
c5.4xlarge
c5.9xlarge
c5.metal

偏好較大的節點來減少 API 伺服器負載

決定要使用的執行個體類型時,較少的大型節點會對 Kubernetes 控制平面造成較少的負載,因為會有較少的 kubelet 和執行中的 DaemonSets。不過,大型節點可能無法完全使用,就像較小的節點一樣。節點大小應根據您的工作負載可用性和擴展需求進行評估。

具有三個 u-24tb1.metal 執行個體 (24 TB 記憶體和 448 個核心) 的叢集有 3 個 kubelet,預設每個節點限制為 110 個 Pod。如果您的 Pod 各使用 4 個核心,則可能預期會發生這種情況 (4 個核心 x 110 = 440 個核心/節點)。使用 3 節點叢集時,您處理執行個體事件的能力會很低,因為 1 個執行個體中斷可能會影響叢集的 1/3。您應該在工作負載中指定節點需求和 Pod,以便 Kubernetes 排程器可以正確放置工作負載。

工作負載應定義所需的資源,以及透過污點、容錯和 PodTopologySpread 所需的可用性。他們應該偏好可充分利用的最大節點,並符合可用性目標,以降低控制平面負載、降低操作並降低成本。

如果資源可用,Kubernetes 排程器會自動嘗試將工作負載分散到可用區域和主機。如果沒有可用的容量,Kubernetes Cluster Autoscaler 會嘗試在每個可用區域中平均新增節點。除非工作負載指定其他要求,否則 Karpenter 將嘗試盡可能快速且經濟實惠地新增節點。

若要強制工作負載隨著排程器和新節點分散到可用區域,您應該使用 topologySpreadConstraints:

spec:
  topologySpreadConstraints:
    - maxSkew: 3
      topologyKey: "topology.kubernetes.io/zone"
      whenUnsatisfiable: ScheduleAnyway
      labelSelector:
        matchLabels:
          dev: my-deployment
    - maxSkew: 2
      topologyKey: "kubernetes.io/hostname"
      whenUnsatisfiable: ScheduleAnyway
      labelSelector:
        matchLabels:
          dev: my-deployment

使用類似的節點大小來實現一致的工作負載效能

工作負載應定義需要執行的節點大小,以允許一致的效能和可預測的擴展。請求 500 公尺 CPU 的工作負載在具有 4 個核心的執行個體上的執行方式與具有 16 個核心的執行個體上的執行方式不同。避免使用爆量 CPUs執行個體類型,例如 T 系列執行個體。

為了確保工作負載獲得一致的效能,工作負載可以使用支援的 Karpenter 標籤來鎖定特定執行個體大小。

kind: deployment
...
spec:
  template:
    spec:
    containers:
    nodeSelector:
      karpenter.k8s.aws/instance-size: 8xlarge

使用 Kubernetes Cluster Autoscaler 在叢集中排程的工作負載,應根據標籤比對將節點選擇器與節點群組進行比對。

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/nodegroup
            operator: In
            values:
            - 8-core-node-group    # match your node group name

有效率地使用運算資源

運算資源包括 EC2 執行個體和可用區域。有效使用運算資源可提高您的可擴展性、可用性、效能,並降低您的總成本。在具有多個應用程式的自動擴展環境中,高效的資源使用非常困難。建立 Karpenter 是為了根據工作負載需求隨需佈建執行個體,以最大化使用率和彈性。

Karpenter 允許工作負載宣告所需的運算資源類型,而無需先建立節點群組或設定特定節點的標籤污點。如需詳細資訊,請參閱 Karpenter 最佳實務。請考慮在 Karpenter 佈建器中啟用整合,以取代使用率不足的節點。

自動化 Amazon Machine Image (AMI) 更新

將工作者節點元件保持在最新狀態,將確保您擁有最新的安全修補程式和與 Kubernetes API 相容的功能。更新 kubelet 是 Kubernetes 功能最重要的元件,但自動化作業系統、核心和本機安裝的應用程式修補程式將減少您擴展時的維護。

建議您為節點映像使用最新的 Amazon EKS 最佳化 Amazon Linux 2Amazon EKS 最佳化 Bottlerocket AMI。Karpenter 將自動使用最新的可用 AMI 來佈建叢集中的新節點。受管節點群組將在節點群組更新期間更新 AMI,但不會在節點佈建時間更新 AMI ID。

對於受管節點群組,您需要在可用於修補程式版本時,使用新的 AMI IDs 更新 Auto Scaling 群組 (ASG) 啟動範本。AMI 次要版本 (例如 1.23.5 到 1.24.3) 將可在 EKS 主控台和 API 中做為節點群組的升級。修補程式發行版本 (例如 1.23.5 到 1.23.6) 不會顯示為節點群組的升級。如果您想要讓節點群組與 AMI 修補程式版本保持最新狀態,您需要建立新的啟動範本版本,並讓節點群組將執行個體取代為新的 AMI 版本。

您可以從此頁面找到最新的可用 AMI,或使用 AWS CLI。

aws ssm get-parameter \
  --name /aws/service/eks/optimized-ami/1.24/amazon-linux-2/recommended/image_id \
  --query "Parameter.Value" \
  --output text

針對容器使用多個 EBS 磁碟區

EBS 磁碟區具有根據磁碟區類型 (例如 gp3) 和磁碟大小的輸入/輸出 (I/O) 配額。如果您的應用程式與主機共用單一 EBS 根磁碟區,這可能會耗盡整個主機的磁碟配額,並導致其他應用程式等待可用容量。如果應用程式將檔案寫入其浮水印分割區、從主機掛載本機磁碟區,以及根據所使用的記錄代理程式登入標準輸出 (STDOUT),則會寫入磁碟。

為了避免磁碟 I/O 耗盡,您應該將第二個磁碟區掛載到容器狀態資料夾 (例如 /run/containerd),請使用個別的 EBS 磁碟區進行工作負載儲存,並停用不必要的本機記錄。

若要使用 eksctl 將第二個磁碟區掛載到您的 EC2 執行個體,您可以使用具有此組態的節點群組:

managedNodeGroups:
  - name: al2-workers
    amiFamily: AmazonLinux2
    desiredCapacity: 2
    volumeSize: 80
    additionalVolumes:
      - volumeName: '/dev/sdz'
        volumeSize: 100
    preBootstrapCommands:
    - |
      "systemctl stop containerd"
      "mkfs -t ext4 /dev/nvme1n1"
      "rm -rf /var/lib/containerd/*"
      "mount /dev/nvme1n1 /var/lib/containerd/"
      "systemctl start containerd"

如果您使用 terraform 佈建節點群組,請參閱 EKS terraform 藍圖中的範例。如果您使用 Karpenter 佈建節點,則可以blockDeviceMappings搭配使用節點使用者資料來新增其他磁碟區。

若要將 EBS 磁碟區直接掛載到您的 Pod,您應該使用 AWS EBS CSI 驅動程式,並使用具有儲存類別的磁碟區。

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: public.ecr.aws/docker/library/nginx
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim

如果工作負載使用 EBS 磁碟區,請避免具有低 EBS 連接限制的執行個體

EBS 是工作負載擁有持久性儲存的最簡單方法之一,但也附帶可擴展性限制。每個執行個體類型都有可連接的 EBS 磁碟區數量上限。工作負載需要宣告應該在哪些執行個體類型上執行,並限制具有 Kubernetes 污點的單一執行個體上的複本數量。

停用不必要的磁碟記錄

避免不必要的本機記錄,方法是不要在生產環境中使用偵錯記錄執行應用程式,並停用經常讀取和寫入磁碟的記錄。日誌記錄是本機日誌記錄服務,可將日誌緩衝區保留在記憶體中,並定期排清至磁碟。日誌優先於將每行立即記錄到磁碟的 syslog。停用 syslog 也會降低您需要的總儲存量,並避免需要複雜的日誌輪換規則。若要停用 syslog,您可以將下列程式碼片段新增至 cloud-init 組態:

runcmd:
  - [ systemctl, disable, --now, syslog.service ]

當作業系統更新速度為必要時,會備妥修補程式執行個體

重要

只有在需要時才應完成就地修補執行個體。Amazon 建議將基礎設施視為不可變且徹底測試透過較低環境提升的更新,就像應用程式一樣。本節適用於無法做到的情況。

在現有的 Linux 主機上安裝套件需要幾秒鐘的時間,而不會中斷容器化工作負載。套件可以安裝和驗證,無需封鎖、耗盡或取代執行個體。

若要取代執行個體,您必須先建立、驗證和分發新的 AMIs。執行個體需要建立替換,且舊執行個體需要封鎖和耗盡。然後,需要在新執行個體上建立工作負載,並針對所有需要修補的執行個體進行驗證和重複。安全地取代執行個體需要數小時、數天或數週的時間,而不會中斷工作負載。

Amazon 建議使用從自動化宣告式系統建置、測試和提升的不可變基礎設施,但如果您需要快速修補系統,則需要修補系統,並在有新的 AMIs 可用時予以取代。由於修補和取代系統之間的時間差異很大,我們建議您在需要時使用 AWS Systems Manager Patch Manager 自動修補節點。

修補節點可讓您快速推出安全性更新,並在 AMI 更新後定期取代執行個體。如果您使用作業系統搭配唯讀根檔案系統,例如 Flatcar Container LinuxBottlerocket OS,我們建議您使用適用於這些作業系統的更新運算子。Flatcar Linux 更新運算子和 Bottlerocket 更新運算子會重新啟動執行個體,讓節點自動保持最新狀態。