

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

# 混合部署的最佳實務
<a name="hybrid"></a>

本指南提供使用 EKS 混合節點或 EKS Anywhere 在內部部署或邊緣環境中執行部署的指引。

我們目前已發佈下列主題的指南：
+  [EKS 混合節點和網路連線中斷的最佳實務](hybrid-nodes-network-disconnections.md) 

# EKS 混合節點和網路連線中斷
<a name="hybrid-nodes-network-disconnections"></a>

對於習慣完全在其資料中心或節點中執行本機 Kubernetes 叢集的客戶而言，EKS 混合節點架構可能是新的。使用 EKS 混合節點時，Kubernetes 控制平面會在 AWS 區域中執行，只有節點會在內部部署執行，導致「延伸」或「延伸」Kubernetes 叢集架構。

這會導致一個常見問題：「如果我的節點與 Kubernetes 控制平面中斷連線會發生什麼情況？」

在本指南中，我們透過檢閱下列主題來回答這個問題。建議您透過網路連線來驗證應用程式的穩定性和可靠性，因為每個應用程式的行為可能根據其相依性、組態和環境而有所不同。如需測試設定、程序和結果，請參閱 aws-samples/eks-hybrid-examples GitHub 儲存庫，您可以參考這些儲存庫，以使用 EKS 混合節點和您自己的應用程式測試網路連線中斷。GitHub 儲存庫也包含測試的其他詳細資訊，用於驗證本指南中說明的行為。
+  [透過網路連線的穩定性最佳實務](hybrid-nodes-network-disconnection-best-practices.md) 
+  [透過網路連線的 Kubernetes Pod 容錯移轉行為](hybrid-nodes-kubernetes-pod-failover.md) 
+  [透過網路連線的應用程式網路流量](hybrid-nodes-app-network-traffic.md) 
+  [透過網路連線的主機登入資料](hybrid-nodes-host-creds.md) 

# 透過網路連線的穩定性最佳實務
<a name="hybrid-nodes-network-disconnection-best-practices"></a>

## 高可用性的聯網
<a name="_highly_available_networking"></a>

避免混合節點與 Kubernetes 控制平面之間中斷網路連線的最佳方法是使用備援、彈性的內部部署環境與 AWS 之間的連線。如需使用這些解決方案建構高可用性混合網路的詳細資訊，請參閱 [AWS Direct Connect 彈性工具組](https://docs.aws.amazon.com/directconnect/latest/UserGuide/resiliency_toolkit.html)和 [AWS Site-to-Site VPN 文件](https://docs.aws.amazon.com/vpn/latest/s2svpn/vpn-redundant-connection.html)。

## 高度可用的應用程式
<a name="_highly_available_applications"></a>

架構應用程式時，請考慮您的故障網域和不同類型的中斷的影響。Kubernetes 提供內建機制，可跨節點、區域和區域網域部署和維護應用程式複本。這些機制的使用取決於您的應用程式架構、環境和可用性需求。例如，無狀態應用程式通常可以使用多個複本部署，並且可以在任意主機和基礎設施容量之間移動，而且您可以使用節點選擇器和拓撲分散限制條件，在不同網域之間執行應用程式的執行個體。如需在 Kubernetes 上建置彈性應用程式的應用程式層級技術詳細資訊，請參閱 [EKS 最佳實務指南](https://aws.github.io/aws-eks-best-practices/reliability/docs/application/)。

Kubernetes 會在決定是否將 Pod 移至其他節點時，評估與 Kubernetes 控制平面中斷連接的節點的區域資訊。如果區域中的所有節點都無法連線，Kubernetes 會取消該區域中節點的 Pod 移出。最佳實務是，如果您部署的節點在多個資料中心或實體位置執行，請根據其資料中心或實體位置將區域指派給每個節點。當您使用雲端中的節點執行 EKS 時，AWS cloud-controller-manager 會自動套用此區域標籤。不過，cloud-controller-manager 不會與混合節點搭配使用，因此您可以透過 kubelet 組態傳遞此資訊。如何在混合節點的節點組態中設定區域的範例如下所示。當您使用混合節點 CLI () 將混合節點連接至叢集時，會傳遞組態`nodeadm`。如需`topology.kubernetes.io/zone`標籤的詳細資訊，請參閱 [Kubernetes 文件](https://kubernetes.io/docs/reference/labels-annotations-taints/#topologykubernetesiozone)。如需混合節點 CLI 的詳細資訊，請參閱[混合節點節點廣告參考](https://docs.aws.amazon.com/eks/latest/userguide/hybrid-nodes-nodeadm.html)。

```
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name: my-cluster
    region: my-region
  kubelet:
    flags:
       - --node-labels=topology.kubernetes.io/zone=dc1
  hybrid:
    ...
```

## 網路監控
<a name="_network_monitoring"></a>

如果您使用 AWS Direct Connect 或 AWS Site-to-Site VPN 進行混合連線，則可以利用 CloudWatch 警示、日誌和指標來觀察混合連線的狀態並診斷問題。如需詳細資訊，請參閱[監控 AWS Direct Connect 資源](https://docs.aws.amazon.com/directconnect/latest/UserGuide/monitoring-overview.html)和[監控 AWS Site-to-Site VPN 連接](https://docs.aws.amazon.com/vpn/latest/s2svpn/monitoring-overview-vpn.html)。

建議為在 EKS 控制平面上執行的node-lifecycle-controller所報告`NodeNotReady`的事件建立警示，這表示混合節點可能正在發生網路連線中斷。您可以為 Controller Manager 啟用 EKS 控制平面記錄，並在 CloudWatch 中為狀態為「NodeNotReady」的「節點記錄狀態變更事件訊息」訊息建立指標篩選條件，以建立此警示。建立指標篩選條件後，您可以根據所需的閾值為此篩選條件建立警示。如需詳細資訊，請參閱 [ CloudWatch 文件中的日誌警示](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Alarm-On-Logs.html)。

您可以使用 Transit Gateway (TGW) 和 Virtual Private Gateway (VGW) 內建指標來觀察進出 TGW 或 VGW 的網路流量。您可以為這些指標建立警示，以偵測網路流量低於正常層級的情況，指出混合節點和 EKS 控制平面之間可能發生網路問題。下表說明 TGW 和 VGW 指標。


| 閘道 | 指標 | Description | 
| --- | --- | --- | 
|  轉換閘道  |  BytesIn  |  TGW 從附件接收的位元組 (EKS 控制平面到混合節點）  | 
|  轉換閘道  |  BytesOut  |  從 TGW 傳送至附件的位元組 （混合節點至 EKS 控制平面）  | 
|  虛擬私有閘道  |  TunnelDataIn  |  從連線的 AWS 端透過 VPN 通道傳送到客戶閘道的位元組 (EKS 控制平面到混合節點）  | 
|  虛擬私有閘道  |  TunnelDataOut  |  從客戶閘道透過 VPN 通道在連線的 AWS 端接收的位元組 （混合節點到 EKS 控制平面）  | 

您也可以使用 [CloudWatch Network Monitor](https://aws.amazon.com/blogs/networking-and-content-delivery/monitor-hybrid-connectivity-with-amazon-cloudwatch-network-monitor/) 深入了解混合連線，以減少復原的平均時間，並判斷網路問題是源自 AWS 還是您的環境。CloudWatch Network Monitor 可用來視覺化混合網路連線中的封包遺失和延遲、設定警示和閾值，然後採取行動來改善網路效能。如需詳細資訊，請參閱[使用 Amazon CloudWatch Network Monitor](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/what-is-network-monitor.html)。

EKS 提供多種選項來監控叢集和應用程式的運作狀態。對於叢集運作狀態，您可以使用 EKS 主控台中的可觀測性儀表板來快速偵測、疑難排解和修復問題。您也可以使用 Amazon Managed Service for Prometheus、AWS Distro for Open Telemetry (ADOT) 和 CloudWatch 進行叢集、應用程式和基礎設施監控。如需 EKS 可觀測性選項的詳細資訊，請參閱[監控叢集效能和檢視日誌](https://docs.aws.amazon.com/eks/latest/userguide/eks-observe.html)。

## 本機故障診斷
<a name="_local_troubleshooting"></a>

若要準備混合節點和 EKS 控制平面之間的網路連線中斷，您可以設定次要監控和記錄後端，以在區域 AWS 服務無法連線時維持應用程式的可觀測性。例如，您可以設定 AWS Distro for Open Telemetry (ADOT) 收集器，將指標和日誌傳送至多個後端。您也可以使用本機工具，例如 `crictl` CLI，在本機與 Pod 和容器互動，以取代 `kubectl`或其他通常查詢 Kubernetes API 伺服器端點的 Kubernetes API 相容用戶端。如需 的詳細資訊`crictl`，請參閱 cri-tools GitHub 中的 [`crictl` 文件](https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md)。以下列出一些有用的`crictl`命令。

列出在主機上執行的 Pod：

```
crictl pods
```

列出在主機上執行的容器：

```
crictl ps
```

列出在主機上執行的映像：

```
crictl images
```

取得在主機上執行之容器的日誌：

```
crictl logs CONTAINER_NAME
```

取得在主機上執行的 Pod 統計資料：

```
crictl statsp
```

## 應用程式網路流量
<a name="_application_network_traffic"></a>

使用混合節點時，請務必考慮並了解應用程式流量的網路流程，以及您用來向叢集外部公開應用程式的技術。不同的應用程式負載平衡和傳入技術在網路連線中斷期間會有不同的行為。例如，如果您使用 Cilium 的 BGP 控制平面功能進行應用程式負載平衡，則 Pod 和服務的 BGP 工作階段可能會在網路連線中斷期間關閉。這是因為 BGP 發言者功能與 Cilium 代理程式整合，並且 Cilium 代理程式會在與 Kubernetes 控制平面中斷連線時持續重新啟動。重新啟動的原因是因為 Cilium 的運作狀態檢查失敗，因為其運作狀態與 Kubernetes 控制平面的存取權結合 （請參閱 [CFP：\$131702](https://github.com/cilium/cilium/issues/31702) 搭配 Cilium v1.17 的選擇加入改進）。同樣地，如果您將 Application Load Balancer (ALB) 或 Network Load Balancer (NLB) 用於 AWS 區域來源的應用程式流量，則如果您的現場部署環境失去與 AWS 區域的連線，則該流量可能會暫時中斷。建議在部署到生產環境之前，先驗證您用於負載平衡和傳入的技術在網路連線中斷期間是否保持穩定。[aws-samples/eks-hybrid-examples](https://github.com/aws-samples/eks-hybrid-examples) GitHub 儲存庫中的範例使用 MetalLB 在 [L2 模式下](https://metallb.universe.tf/concepts/layer2/)進行負載平衡，這在混合節點和 EKS 控制平面之間的網路連線中斷期間保持穩定。

## 檢閱遠端 AWS 服務的相依性
<a name="_review_dependencies_on_remote_aws_services"></a>

使用混合節點時，請注意您在內部部署或邊緣環境外部的區域 AWS 服務上採取的相依性。範例包括存取 Amazon S3 或 Amazon RDS 以取得應用程式資料、使用 Amazon Managed Service for Prometheus 或 CloudWatch 取得指標和日誌、使用 Application and Network Load Balancer 取得區域來源流量，以及從 Amazon Elastic Container Registry 提取容器。在內部部署環境和 AWS 之間的網路連線中斷期間，將無法存取這些服務。如果您的內部部署環境容易與 AWS 中斷網路連線，請檢閱 AWS 服務的使用情況，並確保失去與這些服務的連線不會影響應用程式的靜態穩定性。

## 調校 Kubernetes Pod 容錯移轉行為
<a name="_tune_kubernetes_pod_failover_behavior"></a>

對於非跨主機可攜式的應用程式，或資源受限的環境，如果沒有 Pod 容錯移轉的備用容量，可以選擇在網路連線中斷期間調整 Pod 容錯移轉行為。一般而言，請務必考慮您應用程式的資源需求，並有足夠的容量讓一或多個應用程式執行個體在節點故障時容錯移轉至不同的主機。
+  選項 1 - 使用 DaemonSets：此選項適用於可以且應該在叢集中所有節點上執行的應用程式。DaemonSets 會自動設定為容忍無法連線的污點，這會讓 DaemonSet Pod 透過網路連線來繫結至其節點。
+  選項 2 - 針對無法連線`tolerationSeconds`的污點進行調校：您可以調校裝置在網路連線中斷期間與節點繫結的時間。透過設定應用程式 Pod 來容忍無法連線的污點，在您指定的持續時間 (`tolerationSeconds`在應用程式規格中） 內產生`NoExecute`效果。使用此選項時，當發生網路連線中斷時，您的應用程式 Pod 會持續繫結至節點，直到 `tolerationSeconds` 到期為止。仔細考慮這一點，因為使用 `tolerationSeconds`增加無法連線污點`NoExecute`意味著在無法連線的主機上執行的 Pod 可能需要更長的時間才能移至其他可連線且運作狀態良好的主機。
+  選項 3：自訂控制器：您可以建立並執行自訂控制器 （或其他軟體），以監控 Kubernetes 是否有無法連線的污點並產生`NoExecute`效果。偵測到此污點時，自訂控制器可以檢查應用程式特定的指標，以評估應用程式運作狀態。如果應用程式狀態良好，自訂控制器可以移除無法連線的污點，防止在網路連線中斷期間從節點移出 Pod。

以下顯示如何使用 `tolerationSeconds`為無法連線的污點設定部署的範例。在此範例中， `tolerationSeconds` 設定為 `1800`(30 分鐘），這表示只有在網路連線中斷持續超過 30 分鐘時，才會移出在無法連線的節點上執行的 Pod。

```
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
...
      tolerations:
      - key: "node.kubernetes.io/unreachable"
        operator: "Exists"
        effect: "NoExecute"
        tolerationSeconds: 1800
```

# 透過網路連線的 Kubernetes Pod 容錯移轉
<a name="hybrid-nodes-kubernetes-pod-failover"></a>

首先，我們會回顧影響 Kubernetes 在節點和 Kubernetes 控制平面之間的網路連線中斷期間的行為的重要概念、元件和設定。EKS 符合上游 Kubernetes 規範，因此此處所述的所有 Kubernetes 概念、元件和設定都適用於 EKS 和 EKS 混合節點部署。

EKS 已針對改善網路連線中斷期間的 Pod 容錯移轉行為進行改善，如需詳細資訊，請參閱上游 Kubernetes 儲存庫中的 GitHub 問題 [\$1131294](https://github.com/kubernetes/kubernetes/pull/131294) 和 [\$1131481](https://github.com/kubernetes/kubernetes/issues/131481)。

## 概念
<a name="_concepts"></a>

 標記和容錯：在 Kubernetes 中使用標記和容錯來控制 Pod 在節點上的排程。污點是由 node-lifecycle-controller 設定，以表示節點不符合排程資格，或應移出這些節點上的 Pod。當節點因網路連線中斷而無法連線時，node-lifecycle-controller會使用 NoSchedule 效果套用 node.kubernetes.io/unreachable 污點，並在符合特定條件時套用 NoExecute 效果。node.kubernetes.io/unreachable 污點對應至 NodeCondition Ready be Unknown。使用者可以在 PodSpec 中的應用程式層級為污點指定容錯。
+ NoSchedule：除非有相符的容錯，否則不會在污點節點上排程新的 Pod。不會移出已在節點上執行的 Pod。
+ NoExecute：不會容忍污點的 Pod 會立即被移出。容忍污點的 Pod （不指定tolerationSeconds) 會永遠保持繫結。使用指定的tolerationSeconds容忍污點的 Pod 在指定的時間內保持繫結。經過這段時間後，節點生命週期控制器會從節點移出 Pod。

 節點租用：Kubernetes 使用租用 API 將 kubelet 節點活動訊號與 Kubernetes API 伺服器通訊。對於每個節點，都有一個具有相符名稱的租用物件。在內部，每個 kubelet 活動訊號都會更新租用物件的 spec.renewTime 欄位。Kubernetes 控制平面會使用此欄位的時間戳記來判斷節點可用性。如果節點與 Kubernetes 控制平面中斷連線，則無法更新其租用的 spec.renewTime，且控制平面會將該節點解譯為 NodeCondition Ready 為未知。

## 元件
<a name="_components"></a>

![\[涉及 Pod 容錯移轉行為的 Kubernetes 元件\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/hybrid/k8s-components-pod-failover.png)



| 元件 | 子元件 | Description | 
| --- | --- | --- | 
|  Kubernetes 控制平面  |  kube-api-server  |  API 伺服器是 Kubernetes 控制平面的核心元件，可公開 Kubernetes API。  | 
|  Kubernetes 控制平面  |  node-lifecycle-controller  |  kube-controller-manager 執行的其中一個控制器。它負責偵測和回應節點問題。  | 
|  Kubernetes 控制平面  |  kube-scheduler  |  控制平面元件，可監看沒有指派節點的新建立 Pod，並選取要在其上執行的節點。  | 
|  Kubernetes 節點  |  kubelet  |  在叢集中每個節點上執行的代理程式。kubelet 會監看 PodSpecs，並確保這些 PodSpecs 中所述的容器執行正常。  | 

## 組態設定
<a name="_configuration_settings"></a>


| 元件 | 設定 | Description | K8s 預設 | EKS 預設 | 可在 EKS 中設定 | 
| --- | --- | --- | --- | --- | --- | 
|  kube-api-server  |  default-unreachable-toleration-seconds  |  指出 的 公差的 `tolerationSeconds` `unreachable:NoExecute`，預設會新增至尚未具有此類公差的每個 Pod。  |  300  |  300  |  否  | 
|  node-lifecycle-controller  |  node-monitor-grace-period  |  節點在標示為運作狀態不佳之前可能沒有回應的時間量。必須是 kubelet 的 N 倍`nodeStatusUpdateFrequency`，其中 N 是允許 kubelet 張貼節點狀態的重試次數。  |  40  |  40  |  否  | 
|  node-lifecycle-controller  |  large-cluster-size-threshold  |  對於移出邏輯，node-lifecycle-controller將叢集視為大型的節點數目。對於此大小或更小的叢集`--secondary-node-eviction-rate`， 會覆寫為 0。  |  50  |  100,000  |  否  | 
|  node-lifecycle-controller  |  unhealthy-zone-threshold  |  區域中必須尚未就緒，才能將該區域視為運作狀態不佳的節點百分比。  |  55%  |  55%  |  否  | 
|  kubelet  |  node-status-update-frequency  |  kubelet 將節點狀態發佈到控制平面的頻率。必須與 node-lifecycle-controller `nodeMonitorGracePeriod`中的 相容。  |  10  |  10  |  是  | 
|  kubelet  |  節點標籤  |  在叢集中註冊節點時要新增的標籤。`topology.kubernetes.io/zone` 可以使用混合節點指定標籤，將節點分組到區域中。  |  無  |  無  |  是  | 

## 透過網路連線的 Kubernetes Pod 容錯移轉
<a name="_kubernetes_pod_failover_through_network_disconnections"></a>

此處描述的行為假設 Pod 正在執行為具有預設設定的 Kubernetes 部署，且 EKS 用作 Kubernetes 供應商。實際行為可能會因您的環境、網路連線類型、應用程式、相依性和叢集組態而有所不同。本指南中的內容已使用特定應用程式、叢集組態和外掛程式子集進行驗證。強烈建議在進入生產環境之前，先使用您自己的應用程式來測試行為。

當節點與 Kubernetes 控制平面之間發生網路連線中斷時，每個中斷連線節點上的 kubelet 無法與 Kubernetes 控制平面通訊。因此，在連線還原之前，kubelet 無法移出這些節點上的 Pod。這表示在網路連線中斷之前在這些節點上執行的 Pod 會在中斷連線期間繼續執行，假設沒有其他失敗導致它們關閉。總而言之，您可以在節點與 Kubernetes 控制平面之間的網路連線中斷期間達到靜態穩定性，但在連線還原之前，您無法對節點或工作負載執行變動操作。

有五種主要案例會根據網路連線的性質產生不同的 Pod 容錯移轉行為。在所有情況下，當節點重新連線至 Kubernetes 控制平面時，叢集會再次正常運作，無需操作員介入。以下案例根據我們的觀察概述預期結果，但這些結果可能不適用於所有可能的應用程式和叢集組態。

### 案例 1：完全叢集中斷
<a name="_scenario_1_full_cluster_disruption"></a>

 **預期結果**：無法連線節點上的 Pod 不會移出，並繼續在這些節點上執行。

完整的叢集中斷表示叢集中的所有節點都與 Kubernetes 控制平面中斷連線。在此案例中，控制平面上的node-lifecycle-controller會偵測到叢集中的所有節點都無法連線，並取消任何 Pod 移出。

叢集管理員將在中斷連線`Not Ready`期間看到狀態為 的所有節點。Pod 狀態不會變更，而且在中斷連線和後續重新連線期間，不會在任何節點上排程新的 Pod。

### 案例 2：全區域中斷
<a name="_scenario_2_full_zone_disruption"></a>

 **預期結果**：無法連線節點上的 Pod 不會移出，並繼續在這些節點上執行。

完全區域中斷表示該區域中的所有節點都與 Kubernetes 控制平面中斷連線。在此案例中，控制平面上的node-lifecycle-controller偵測到區域中的所有節點都無法連線，並取消任何 Pod 移出。

叢集管理員將在中斷連線`Not Ready`期間看到狀態為 的所有節點。Pod 狀態不會變更，而且在中斷連線和後續重新連線期間，不會在任何節點上排程新的 Pod。

### 案例 3：主要區域中斷
<a name="_scenario_3_majority_zone_disruption"></a>

 **預期結果**：無法連線節點上的 Pod 不會移出，並繼續在這些節點上執行。

大多數區域中斷表示指定區域中的大多數節點都與 Kubernetes 控制平面中斷連線。Kubernetes 中的區域由具有相同`topology.kubernetes.io/zone`標籤的節點定義。如果叢集中未定義任何區域，則大多數中斷表示整個叢集中的大多數節點都會中斷連線。根據預設，大多數是由 node-lifecycle-controller 的 定義`unhealthy-zone-threshold`，在 Kubernetes 和 EKS 中均設為 55%。由於 `large-cluster-size-threshold` EKS 中的 設為 100，000，如果區域中 55% 以上的節點無法連線，則會取消 Pod 移出 （因為大多數叢集遠小於 100，000 個節點）。

叢集管理員會在中斷連線`Not Ready`期間看到區域中狀態為 的大多數節點，但 Pod 的狀態不會變更，也不會在其他節點上重新排程這些節點。

請注意，上述行為僅適用於大於三個節點的叢集。在不超過三個節點的叢集中，無法連線節點上的 Pod 會排程為移出，而新的 Pod 會排程在運作狀態良好的節點上。

在測試期間，我們偶爾會觀察到 Pod 在網路連線中斷期間從剛好一個無法連線的節點移出，即使大部分的區域節點都無法連線。作為此行為的原因，我們仍在 Kubernetes node-lifecycle-controller中調查可能的競爭條件。

### 案例 4：少數區域中斷
<a name="_scenario_4_minority_zone_disruption"></a>

 **預期結果**：從無法連線的節點移出 Pod，並在可用的合格節點上排程新的 Pod。

少數中斷表示區域中較少百分比的節點與 Kubernetes 控制平面中斷連線。如果叢集中未定義任何區域，則少數中斷表示整個叢集中節點的少數節點會中斷連線。如上所述，少數是節點node-lifecycle-controller`unhealthy-zone-threshold`的設定，預設為 55%。在此案例中，如果網路連線的持續時間超過 `default-unreachable-toleration-seconds`(5 分鐘） 和 `node-monitor-grace-period`(40 秒），且區域中少於 55% 的節點無法連線，則會在運作狀態良好的節點上排程新的 Pod，而無法連線節點上的 Pod 會標記為移出。

叢集管理員將看到在運作狀態良好的節點上建立的新 Pod，中斷連線節點上的 Pod 將顯示為 `Terminating`。請記住，即使已中斷連線節點上的 Pod 具有 `Terminating` 狀態，在節點重新連線至 Kubernetes 控制平面之前，它們不會完全移出。

## 案例 5：網路中斷期間節點重新啟動
<a name="_scenario_5_node_restart_during_network_disruption"></a>

 **預期結果**：在節點重新連線至 Kubernetes 控制平面之前，無法連線節點上的 Pod 不會啟動。Pod 容錯移轉遵循案例 1–3 中所述的邏輯，取決於無法連線的節點數量。

網路中斷期間節點重新啟動表示節點上發生另一個故障 （例如電源循環、out-of-memory事件或其他問題） 與網路中斷連線同時發生。如果 kubelet 也已重新啟動，則網路中斷連線開始時在該節點上執行的 Pod 不會在中斷連線期間自動重新啟動。kubelet 會在啟動期間查詢 Kubernetes API 伺服器，以了解應執行哪些 Pod。如果 kubelet 由於網路連線中斷而無法連接 API 伺服器，則無法擷取啟動 Pod 所需的資訊。

在這種情況下，無法使用本機故障診斷工具，例如 `crictl` CLI，將 Pod 手動啟動為「中斷玻璃」量值。Kubernetes 通常會移除故障的 Pod 並建立新的 Pod，而不是重新啟動現有的 Pod （如需詳細資訊，請參閱容器化 GitHub 儲存庫中的 [\$110213](https://github.com/containerd/containerd/pull/10213))。靜態 Pod 是唯一由 kubelet 控制的 Kubernetes 工作負載物件，並且可以在這些情況下重新啟動。不過，通常不建議使用靜態 Pod 進行應用程式部署。相反地，在不同的主機之間部署多個複本，以確保在發生多個同時故障時應用程式可用性，例如節點故障，以及節點和 Kubernetes 控制平面之間的網路連線中斷。

# 透過網路連線的應用程式網路流量
<a name="hybrid-nodes-app-network-traffic"></a>

本頁面上的主題與 Kubernetes 叢集聯網和節點與 Kubernetes 控制平面之間的網路連線中斷期間的應用程式流量有關。

## Cilium
<a name="_cilium"></a>

Cilium 有多種模式可用於 IP 地址管理 (IPAM)、封裝、負載平衡和叢集路由。本指南中驗證的模式使用 Cluster Scope IPAM、VXLAN 浮水印、BGP 負載平衡和 kube-proxy。Cilium 也在沒有 BGP 負載平衡的情況下使用，將其取代為 MetalLB L2 負載平衡。

Cilium 安裝的基礎包含 Cilium 運算子和 Cilium 代理程式。Cilium Operator 會做為部署執行，並註冊 Cilium Custom Resource Definitions (CRDs、管理 IPAM，以及同步叢集物件與 Kubernetes API 伺服器[等功能](https://docs.cilium.io/en/stable/internals/cilium_operator/)。Cilium 代理程式會以 DaemonSet 的形式在每個節點上執行，並管理 eBPF 程式，以控制叢集上執行工作負載的網路規則。

一般而言，Cilium 設定的叢集內路由在網路連線中斷期間仍然可用且就地，這可以透過觀察 Pod 網路的叢集內流量和 IP 資料表 (iptable) 規則來確認。

```
ip route show table all | grep cilium
```

```
10.86.2.0/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450
10.86.2.64/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450
10.86.2.128/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450
10.86.2.192/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450
10.86.3.0/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16
10.86.3.16 dev cilium_host proto kernel scope link
...
```

不過，在網路連線中斷期間，Cilium 運算子和 Cilium 代理程式會因運作狀態檢查與 Kubernetes API 伺服器連線的運作狀態耦合而重新啟動。預計在網路連線中斷期間，Cilium 運算子和 Cilium 代理程式的日誌中會看到以下內容。在網路連線中斷期間，您可以使用 CLI `crictl` 等工具來觀察這些元件的重新啟動，包括其日誌。

```
msg="Started gops server" address="127.0.0.1:9890" subsys=gops
msg="Establishing connection to apiserver" host="https://<k8s-cluster-ip>:443" subsys=k8s-client
msg="Establishing connection to apiserver" host="https://<k8s-cluster-ip>:443" subsys=k8s-client
msg="Unable to contact k8s api-server" error="Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" ipAddr="https://<k8s-cluster-ip>:443" subsys=k8s-client
msg="Start hook failed" function="client.(*compositeClientset).onStart (agent.infra.k8s-client)" error="Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout"
msg="Start failed" error="Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" duration=1m5.003834026s
msg=Stopping
msg="Stopped gops server" address="127.0.0.1:9890" subsys=gops
msg="failed to start: Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" subsys=daemon
```

如果您使用 Cilium 的 BGP 控制平面功能進行應用程式負載平衡，則 Pod 和 服務的 BGP 工作階段可能會在網路中斷連線期間關閉，因為 BGP 發言者功能已與 Cilium 代理程式整合，且 Cilium 代理程式會在與 Kubernetes 控制平面中斷連線時持續重新啟動。如需詳細資訊，請參閱 Cilium 文件中的 Cilium BGP 控制平面操作指南。此外，如果您在網路中斷期間同時發生故障，例如電源循環或機器重新開機，則不會透過這些動作保留 Cilium 路由，不過當節點重新連線至 Kubernetes 控制平面且 Cilium 再次啟動時，會重新建立路由。

## Calico
<a name="_calico"></a>

 *即將推出* 

## MetalLB
<a name="_metallb"></a>

MetalLB 有兩種負載平衡模式：[L2 模式](https://metallb.universe.tf/concepts/layer2/)和 [BGP 模式](https://metallb.universe.tf/concepts/bgp/)。如需這些負載平衡模式的運作方式及其限制的詳細資訊，請參閱 MetalLB 文件。本指南的驗證在 L2 模式中使用 MetalLB，其中叢集中的一台機器取得 Kubernetes Service 的所有權，並使用適用於 IPv4 的 ARP，讓負載平衡器 IP 地址可在本機網路上連線。執行 MetalLB 時，有一個控制器負責在每個節點上執行的 IP 指派和發言者，這些節點負責使用指派的 IP 地址公告服務。MetalLB 控制器會做為部署執行，而 MetalLB 發言者則會做為 DaemonSet 執行。在網路連線中斷期間，MetalLB 控制器和發言者無法監看叢集資源的 Kubernetes API 伺服器，但繼續執行。最重要的是，在網路連線中斷期間，使用 MetalLB 進行外部連線的 服務仍然可用且可存取。

## kube-proxy
<a name="_kube_proxy"></a>

在 EKS 叢集中，kube-proxy 在每個節點上以 DaemonSet 的形式執行，並負責管理網路規則，透過將服務 IP 地址轉譯為基礎 Pod 的 IP 地址來啟用服務和 Pod 之間的通訊。kube-proxy 設定的 IP 資料表 (iptable) 規則會在網路連線中斷期間維護，叢集內路由會繼續運作，而 kube-proxy Pod 會繼續執行。

您可以使用下列 iptables 命令來觀察 kube-proxy 規則。第一個命令顯示經過`PREROUTING`鏈結的封包會導向至`KUBE-SERVICES`鏈結。

```
iptables -t nat -L PREROUTING
```

```
Chain PREROUTING (policy ACCEPT)
target         prot opt source      destination
KUBE-SERVICES  all  --  anywhere    anywhere      /* kubernetes service portals */
```

檢查`KUBE-SERVICES`鏈結，我們可以看到各種叢集服務的規則。

```
Chain KUBE-SERVICES (2 references)
target                     prot opt source      destination
KUBE-SVL-NZTS37XDTDNXGCKJ  tcp  --  anywhere    172.16.189.136  /* kube-system/hubble-peer:peer-service cluster IP /
KUBE-SVC-2BINP2AXJOTI3HJ5  tcp  --  anywhere    172.16.62.72    / default/metallb-webhook-service cluster IP /
KUBE-SVC-LRNEBRA3Z5YGJ4QC  tcp  --  anywhere    172.16.145.111  / default/redis-leader cluster IP /
KUBE-SVC-I7SKRZYQ7PWYV5X7  tcp  --  anywhere    172.16.142.147  / kube-system/eks-extension-metrics-api:metrics-api cluster IP /
KUBE-SVC-JD5MR3NA4I4DYORP  tcp  --  anywhere    172.16.0.10     / kube-system/kube-dns:metrics cluster IP /
KUBE-SVC-TCOU7JCQXEZGVUNU  udp  --  anywhere    172.16.0.10     / kube-system/kube-dns:dns cluster IP /
KUBE-SVC-ERIFXISQEP7F7OF4  tcp  --  anywhere    172.16.0.10     / kube-system/kube-dns:dns-tcp cluster IP /
KUBE-SVC-ENODL3HWJ5BZY56Q  tcp  --  anywhere    172.16.7.26     / default/frontend cluster IP /
KUBE-EXT-ENODL3HWJ5BZY56Q  tcp  --  anywhere    <LB-IP>    / default/frontend loadbalancer IP /
KUBE-SVC-NPX46M4PTMTKRN6Y  tcp  --  anywhere    172.16.0.1      / default/kubernetes:https cluster IP /
KUBE-SVC-YU5RV2YQWHLZ5XPR  tcp  --  anywhere    172.16.228.76   / default/redis-follower cluster IP /
KUBE-NODEPORTS             all  --  anywhere    anywhere        / kubernetes service nodeports; NOTE: this must be the last rule in this chain */
```

檢查前端服務的鏈結是否有應用程式，我們可以看到支援服務的 Pod IP 地址。

```
iptables -t nat -L KUBE-SVC-ENODL3HWJ5BZY56Q
```

```
Chain KUBE-SVC-ENODL3HWJ5BZY56Q (2 references)
target                     prot opt source    destination
KUBE-SEP-EKXE7ASH7Y74BGBO  all  --  anywhere  anywhere    /* default/frontend -> 10.86.2.103:80 / statistic mode random probability 0.33333333349
KUBE-SEP-GCY3OUXWSVMSEAR6  all  --  anywhere  anywhere    / default/frontend -> 10.86.2.179:80 / statistic mode random probability 0.50000000000
KUBE-SEP-6GJJR3EF5AUP2WBU  all  --  anywhere  anywhere    / default/frontend -> 10.86.3.47:80 */
```

下列 kube-proxy 日誌訊息預期會在網路中斷連線期間嘗試監看 Kubernetes API 伺服器，以取得節點和端點資源的更新。

```
"Unhandled Error" err="k8s.io/client-go/informers/factory.go:160: Failed to watch *v1.Node: failed to list *v1.Node: Get \"https://<k8s-endpoint>/api/v1/nodes?fieldSelector=metadata.name%3D<node-name>&resourceVersion=2241908\": dial tcp <k8s-ip>:443: i/o timeout" logger="UnhandledError"
"Unhandled Error" err="k8s.io/client-go/informers/factory.go:160: Failed to watch *v1.EndpointSlice: failed to list *v1.EndpointSlice: Get \"https://<k8s-endpoint>/apis/discovery.k8s.io/v1/endpointslices?labelSelector=%21service.kubernetes.io%2Fheadless%2C%21service.kubernetes.io%2Fservice-proxy-name&resourceVersion=2242090\": dial tcp <k8s-ip>:443: i/o timeout" logger="UnhandledError"
```

## CoreDNS
<a name="_coredns"></a>

根據預設，EKS 叢集中的 Pod 會使用 CoreDNS 叢集 IP 地址做為叢集內 DNS 查詢的名稱伺服器。在 EKS 叢集中，CoreDNS 會在節點上執行為部署。使用混合節點時，當混合節點上有在本機執行的 CoreDNS 複本時，Pod 可以在網路連線中斷期間繼續與 CoreDNS 通訊。如果您的 EKS 叢集的雲端節點和內部部署環境中的混合節點，建議在每個環境中至少有一個 CoreDNS 複本。CoreDNS 會繼續為在網路中斷連線之前建立的記錄提供 DNS 查詢，並繼續透過網路重新連線執行，以確保靜態穩定性。

在網路中斷連線期間，當嘗試從 Kubernetes API 伺服器列出物件時，預期會發生下列 CoreDNS 日誌訊息。

```
Failed to watch *v1.Namespace: failed to list *v1.Namespace: Get "https://<k8s-cluster-ip>:443/api/v1/namespaces?resourceVersion=2263964": dial tcp <k8s-cluster-ip>:443: i/o timeout
Failed to watch *v1.Service: failed to list *v1.Service: Get "https://<k8s-cluster-ip>:443/api/v1/services?resourceVersion=2263966": dial tcp <k8s-cluster-ip>:443: i/o timeout
Failed to watch *v1.EndpointSlice: failed to list *v1.EndpointSlice: Get "https://<k8s-cluster-ip>:443/apis/discovery.k8s.io/v1/endpointslices?resourceVersion=2263896": dial tcp <k8s-cluster-ip>: i/o timeout
```

# 透過網路連線的主機登入資料
<a name="hybrid-nodes-host-creds"></a>

EKS 混合節點與 AWS Systems Manager (SSM) 混合啟用和 AWS IAM Roles Anywhere 整合，用於使用 EKS 控制平面驗證節點的臨時 IAM 登入資料。SSM 和 IAM Roles Anywhere 都會自動重新整理他們在內部部署主機上管理的臨時憑證。建議您在叢集中跨混合節點使用單一登入資料提供者，無論是 SSM 混合啟用或 IAM Roles Anywhere，但不能同時使用兩者。

## SSM 混合啟用
<a name="_ssm_hybrid_activations"></a>

SSM 佈建的臨時登入資料有效期為一小時。使用 SSM 做為登入資料提供者時，您無法變更登入資料有效期間。SSM 會在臨時登入資料過期之前自動輪換，輪換不會影響節點或應用程式的狀態。不過，當 SSM 代理程式與 SSM 區域端點之間發生網路連線中斷時，SSM 無法重新整理登入資料，登入資料可能會過期。

如果 SSM 無法連線至 SSM 區域端點，SSM 會使用指數退避進行登入資料重新整理重試。在 SSM 代理程式版本 `3.3.808.0` 和更新版本 (2024 年 8 月發行） 中，指數退避上限為 30 分鐘。視網路連線的持續時間而定，SSM 重新整理登入資料最多可能需要 30 分鐘，而且在重新整理登入資料之前，混合節點不會重新連線至 EKS 控制平面。在此案例中，您可以重新啟動 SSM 代理程式來強制重新整理登入資料。作為目前 SSM 憑證重新整理行為的副作用，節點可能會在不同時間重新連線，具體取決於每個節點上的 SSM 代理程式何時設法重新整理其憑證。因此，您可能會看到來自尚未重新連線至已重新連線節點之節點的 Pod 容錯移轉。

取得 SSM 代理程式版本。您也可以查看 SSM 主控台的機群管理員區段：

```
# AL2023, RHEL
yum info amazon-ssm-agent
# Ubuntu
snap list amazon-ssm-agent
```

重新啟動 SSM 代理程式：

```
# AL2023, RHEL
systemctl restart amazon-ssm-agent
# Ubuntu
systemctl restart snap.amazon-ssm-agent.amazon-ssm-agent
```

檢視 SSM 代理程式日誌：

```
tail -f /var/log/amazon/ssm/amazon-ssm-agent.log
```

網路連線中斷期間的預期日誌訊息：

```
INFO [CredentialRefresher] Credentials ready
INFO [CredentialRefresher] Next credential rotation will be in 29.995040663666668 minutes
ERROR [CredentialRefresher] Retrieve credentials produced error: RequestError: send request failed
INFO [CredentialRefresher] Sleeping for 35s before retrying retrieve credentials
ERROR [CredentialRefresher] Retrieve credentials produced error: RequestError: send request failed
INFO [CredentialRefresher] Sleeping for 56s before retrying retrieve credentials
ERROR [CredentialRefresher] Retrieve credentials produced error: RequestError: send request failed
INFO [CredentialRefresher] Sleeping for 1m24s before retrying retrieve credentials
```

## IAM Roles Anywhere
<a name="_iam_roles_anywhere"></a>

根據預設，IAM Roles Anywhere 佈建的臨時登入資料有效期為一小時。您可以透過 IAM Roles Anywhere 設定檔中的 [https://docs.aws.amazon.com/rolesanywhere/latest/userguide/authentication-create-session.html#credentials-object](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/authentication-create-session.html#credentials-object) 欄位，使用 IAM Roles Anywhere 設定憑證有效期間。登入資料有效性的持續時間上限為 12 小時。混合節點 IAM 角色上的[https://docs.aws.amazon.com/managedservices/latest/ctref/management-advanced-identity-and-access-management-iam-update-maxsessionduration.html](https://docs.aws.amazon.com/managedservices/latest/ctref/management-advanced-identity-and-access-management-iam-update-maxsessionduration.html)設定必須大於 IAM Roles Anywhere 設定檔上的`durationSeconds`設定。

使用 IAM Roles Anywhere 做為混合節點的登入資料提供者時，網路中斷後，通常會在網路還原後的幾秒內重新連線至 EKS 控制平面，因為 kubelet 會呼叫 `aws_signing_helper credential-process` 來隨需取得登入資料。雖然與混合節點或網路連線不直接相關，但您可以在使用 IAM Roles Anywhere 時設定憑證過期的通知和提醒。如需詳細資訊，請參閱在 [IAM Roles Anywhere 中自訂通知設定](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/customize-notification-settings.html)。