Pods 的安全群組 - Amazon EKS

協助改善此頁面

想要為此使用者指南做出貢獻嗎? 捲動至此頁面底部,然後選取 [編輯此頁面於] GitHub。您的貢獻將有助於使我們的用戶指南更適合所有人。

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

Pods 的安全群組

Pods 的安全群組整合了 Amazon EC2 安全群組與 Kubernetes Pods。您可以使用 Amazon EC2 安全群組定義規則,允許您部署的 Pods 到許多 Amazon EC2 執行個體類型和 Fargate 上執行的節點之間的對內和對外網路流量。如需此功能的詳細說明,請參閱 Pods 的安全群組簡介部落格文章。

考量事項

  • 部署 Pods 的安全群組之前,請考慮下列限制和條件:

  • Pods 的安全群組無法與 Windows 節點搭配使用。

  • Pods 的安全群組可與為包含 Amazon EC2 節點的 IPv6 系列設定的叢集搭配使用,方法是使用 1.16.0 版或更新的 Amazon VPC CNI 外掛程式。Pods 的安全群組可與為僅包含 Fargate 節點的 IPv6 系列設定的叢集搭配使用,方法是使用 1.7.7 版或更新的 Amazon VPC CNI 外掛程式。如需更多資訊,請參閱IPv6叢集的位址Pods、和 services

  • Pods 的安全群組受大多數 Nitro 型 Amazon EC2 執行個體系列支援,但並非受所有系列世代皆支援。例如,支援m5c5r5m6gc6g、和r6g例證族群和層代。不支援 t 系列中的執行個體類型。如需完整的支援執行個體類型清單,請參閱 GitHub 上的 limits.go 檔案。您的節點必須為該檔案列出的具有 IsTrunkingCompatible: true 的執行個體類型之一。

  • 如果您也使用 Pod 安全政策來限制對 Pod 變動的存取權,則必須針對 psp 被指派到的 role 在 Kubernetes ClusterRoleBinding 中指定 eks:vpc-resource-controller Kubernetes 使用者。如果您使用的是預設 Amazon EKS psproleClusterRoleBinding,則為 eks:podsecuritypolicy:authenticated ClusterRoleBinding。例如,您可以將使用者新增至 subjects: 區段,如下列範例所示:

    [...] subjects: - kind: Group apiGroup: rbac.authorization.k8s.io name: system:authenticated - apiGroup: rbac.authorization.k8s.io kind: User name: eks:vpc-resource-controller - kind: ServiceAccount name: eks-vpc-resource-controller
  • 如果您使用的是自訂聯網和 Pods 的安全群組,則會使用 Pods 安全群組指定的安全群組,而不是 ENIConfig 指定的安全群組。

  • 如果您使用的是版本 1.10.2 或更舊版本的 Amazon VPC CNI 外掛程式,且 terminationGracePeriodSeconds 規格包括 Pod 設定,則該設定的值不能為零。

  • 如果您使用的是版本 1.10 或更舊版本的 Amazon VPC CNI 外掛程式,或預設設定為 POD_SECURITY_GROUP_ENFORCING_MODE=strict 的版本 1.11,則使用 externalTrafficPolicy 設定為 Local 的執行個體目標的 NodePortLoadBalancer 類型 Kubernetes 服務,就不支援指派安全群組至其 Pods。如需將負載平衡器與執行個體目標搭配使用的詳細資訊,請參閱 Amazon EKS 上的網路負載平衡

  • 如果您使用的是版本 1.10 或更舊版本的 Amazon VPC CNI 外掛程式或預設設定為 POD_SECURITY_GROUP_ENFORCING_MODE=strict 的版本 1.11,來自具有指派安全群組之 Pods 的對外流量會停用來源 NAT,以便套用輸出安全群組規則。若要存取網際網路,必須在部署在使用 NAT 閘道或執行個體設定的私有子網中的節點上啟動具有指派安全群組的 Pods。已指派安全群組部署至公有子網的 Pods 無法存取網際網路。

    如果您使用的是版本 1.11 或更新版本的搭配 POD_SECURITY_GROUP_ENFORCING_MODE=standard 的外掛程式,則以 VPC 外部為目標的 Pod 流量會轉換為執行個體主要網路介面的 IP 地址。對於此流量,將使用主要網路介面的安全群組中的規則,而不是使用 Pod's 安全群組中的規則。

  • 若要將 Calico 網路政策與和安全群組關聯的 Pods 搭配使用,則必須使用版本 1.11.0 或更新版本的 Amazon VPC CNI 外掛程式,並設定為 POD_SECURITY_GROUP_ENFORCING_MODE=standard。否則,具有關聯的安全群組之 Pods 的流量流出和流向不受 Calico 網路政策強制執行的約束,且僅限於 Amazon EC2 安全群組強制執行。若要更新 Amazon VPC CNI 版本,請參閱 使用 Amazon VPC CNI plugin for Kubernetes Amazon EKS 附加元件

  • Pods 在 Amazon EC2 節點上執行,這些節點使用位於使用 Nodelocal DNSCache 的叢集內的安全群組,僅受 Amazon VPC CNI 外掛程式版本 1.11.0 或更新版本以及 POD_SECURITY_GROUP_ENFORCING_MODE=standard 支援。若要更新您的 Amazon VPC CNI 外掛程式版本,請參閱 使用 Amazon VPC CNI plugin for Kubernetes Amazon EKS 附加元件

  • Pods 的安全群組可能會導致具有高流失率的 Pods 產生更高的 Pod 啟動延遲。原因是資源控制器的速率限制。

為 Pods 設定安全群組的 Amazon VPC CNI plugin for Kubernetes

若要部署 Pods 的安全群組

如果您僅使用 Fargate Pods 的安全群組,且叢集中沒有任何 Amazon EC2 節點,請跳至步驟 部署範例應用程式

  1. 使用以下命令查看您目前的 Amazon VPC CNI plugin for Kubernetes 版本:

    kubectl describe daemonset aws-node --namespace kube-system | grep amazon-k8s-cni: | cut -d : -f 3

    範例輸出如下。

    v1.7.6

    如果您的 Amazon VPC CNI plugin for Kubernetes 版本早於 1.7.7,則請將外掛程式更新至版本 1.7.7 或更新版本。如需更多資訊,請參閱使用 Amazon VPC CNI plugin for Kubernetes Amazon EKS 附加元件

  2. AmazonEKSVPCResourceController 受管 IAM 政策新增至與您 Amazon EKS 叢集相關聯的叢集角色。此政策允許角色管理網路介面、其私有 IP 地址以及其與網路執行個體之間的連接和分離。

    1. 擷取叢集 IAM 角色的名稱,並存放在變數中。使用您叢集的名稱取代 my-cluster

      cluster_role=$(aws eks describe-cluster --name my-cluster --query cluster.roleArn --output text | cut -d / -f 2)
    2. 將政策連接到角色。

      aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKSVPCResourceController --role-name $cluster_role
  3. 啟用 Amazon VPC CNI 外掛程式來管理 Pods 的網路介面,方法是將 ENABLE_POD_ENI 變數設定為 aws-node DaemonSet 中的 true。一旦此設定設定為 true,對於叢集中的每個節點,該附加元件會建立一個 cninode 自訂資源。VPC 資源控制器會建立並連接一個稱為幹線網路介面與描述 aws-k8s-trunk-eni 的特殊網路介面。

    kubectl set env daemonset aws-node -n kube-system ENABLE_POD_ENI=true
    注意

    幹線網路介面包含在執行個體類型所支援的最大網路介面數量中。如需每種執行個體類型支援的最大網路界面數目清單,請參閱 Amazon EC2 使用者指南每個執行個體類型每個網路界面的 IP 地址。如果您的節點已經連接到標準網路介面的最大數量,那麼 VPC 資源控制器將保留一個空間。您將不得不縮減正在執行的 Pods 的規模,以便控制器分開並刪除標準網路介面,建立幹線網路介面,並將其連接到執行個體。

  4. 您可以使用以下命令查看您的哪些節點擁有 CNINode 自訂資源。如果傳回 No resources found,則等待幾秒鐘後再重試一次。上一步驟要求重新啟動 Amazon VPC CNI plugin for Kubernetes Pods,這需要幾秒鐘的時間。

    $ kubectl get cninode -A NAME FEATURES ip-192-168-64-141.us-west-2.compute.internal [{"name":"SecurityGroupsForPods"}] ip-192-168-7-203.us-west-2.compute.internal [{"name":"SecurityGroupsForPods"}]

    如果您使用的 VPC CNI 版本低於 1.15,則會使用節點標籤而非 CNINode 自訂資源。您可以使用以下命令查看您的哪些節點已將節點標籤 aws-k8s-trunk-eni 設定為 true。如果傳回 No resources found,則等待幾秒鐘後再重試一次。上一步驟要求重新啟動 Amazon VPC CNI plugin for Kubernetes Pods,這需要幾秒鐘的時間。

    kubectl get nodes -o wide -l vpc.amazonaws.com/has-trunk-attached=true -

    一旦建立幹線網路介面,Pods 就可以從幹線或標準網路介面指派次要 IP 地址。如果刪除節點,則會自動刪除幹線介面。

    當您在稍後的步驟中為 Pod 部署安全群組時,VPC 資源控制器會建立稱為分支網路介面與 描述 aws-k8s-branch-eni的特殊網路介面,並將安全群組與其關聯。除了連接至節點的標準和幹線網路介面之外,還會建立分支網路介面。

    如果您使用的是存活或整備探查,則還需要停用 TCP 早期的 demux,以便 kubelet 可以透過 TCP 連接到分支網路介面上的 Pods。若要停用 TCP 早期的 Demux,請執行下列命令:

    kubectl patch daemonset aws-node -n kube-system \ -p '{"spec": {"template": {"spec": {"initContainers": [{"env":[{"name":"DISABLE_TCP_EARLY_DEMUX","value":"true"}],"name":"aws-vpc-cni-init"}]}}}}'
    注意

    如果您使用的是 1.11.0 或更新版本的 Amazon VPC CNI plugin for Kubernetes 附加元件和設定 POD_SECURITY_GROUP_ENFORCING_MODE=standard,如下一個步驟所述,則不需要執行之前的命令。

  5. 如果您的叢集使用 NodeLocal DNSCache,或者您希望將 Calico 網路政策與具有自己的安全群組的 Pods 搭配使用,或者您的 Kubernetes 服務類型為 NodePortLoadBalancer,其使用的執行個體目標中您欲指派安全群組的 externalTrafficPolicyLocal 設定為 Pods,則必須使用版本 1.11.0 或更新版本的 Amazon VPC CNI plugin for Kubernetes 附加元件,且您必須啟用下列設定:

    kubectl set env daemonset aws-node -n kube-system POD_SECURITY_GROUP_ENFORCING_MODE=standard
    重要
    • Pod 安全群組規則不會套用至介於Pods 或 介於 Pods 和 services 之間的流量,例如位於同一個節點上的 kubeletnodeLocalDNS。在相同節點上使用不同安全群組的 Pod 無法進行通訊,這是因為它們在不同子網路中設定,且這些子網路之間已停用路由。

    • 來自 Pods 的輸出流量傳輸到 VPC 外部的地址是轉換為執行個體主要網路介面的 IP 地址的網路地址 (除非您還設定了AWS_VPC_K8S_CNI_EXTERNALSNAT=true)。對於此流量,將使用主要網路介面的安全群組中的規則,而不是使用 Pod's 安全群組中的規則。

    • 若要將此設定套用至現有的 Pods,您必須重新啟動 Pods 或 Pods 正在運行之節點。

部署範例應用程式

若要將安全群組用於 Pods,您必須擁有現有的安全群組和部署 Amazon EKS SecurityGroupPolicy至叢集,如下列步驟所述。下列步驟介紹如何使用 Pod 的安全群組政策。除非另有備註,請從同一終端機完成所有步驟,因為變數用於不會保留跨終端機的以下步驟。

使用安全群組部署範例 Pod
  1. 建立 Kubernetes 命名空間以部署資源。您可以將 my-namespace 取代為要使用的命名空間的名稱。

    kubectl create namespace my-namespace
  2. 將 Amazon EKS SecurityGroupPolicy 部署至您的叢集。

    1. 將以下內容複製到您的裝置。若您希望根據服務帳戶標籤選取 Pods,則您可以使用 serviceAccountSelector 取代 podSelector。您必須指定其中一個選取器或其他工具。空白 podSelector (例如:podSelector: {}) 選取命名空間中的所有 Pods。您可以將 my-role 變更為您的角色名稱。空白 serviceAccountSelector 會選取命名空間中的所有服務帳戶。您可以將 my-security-group-policy 取代為您的 SecurityGroupPolicy 的名稱,將 my-namespace 取代為要在其中建立 SecurityGroupPolicy 的命名空間。

      您必須將 my_pod_security_group_id 取代為現有安全群組的 ID。如果您沒有現有的安全群組,則必須先建立一個。如需詳細資訊,請參閱《Amazon EC2 使用者指南》https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/中的適用於 Linux 執行個體的 Amazon EC2 安全群組一節。您可以指定 1-5 個安全群組 ID。如果您指定多個 ID,則所有安全群組中的所有規則的組合對選取的 Pods 都有效。

      cat >my-security-group-policy.yaml <<EOF apiVersion: vpcresources.k8s.aws/v1beta1 kind: SecurityGroupPolicy metadata: name: my-security-group-policy namespace: my-namespace spec: podSelector: matchLabels: role: my-role securityGroups: groupIds: - my_pod_security_group_id EOF
      重要

      您指定的 Pod 的一個或多個安全群組 必須符合下列條件:

      • 它們必須存在。如果安全群組不存在,那麼當您部署符合選取器的 Pod 時,您的 Pod 仍會停留在建立程序中。如果您描述 Pod,您會看到類似下列的錯誤訊息:An error occurred (InvalidSecurityGroupID.NotFound) when calling the CreateNetworkInterface operation: The securityGroup ID 'sg-05b1d815d1EXAMPLE' does not exist

      • 安全群組必須允許透過您已設定偵測的任何連接埠,而來自套用於您節點的安全群組的傳入通訊 (適用於 kubelet)。

      • 其必須允許透過 TCPUDP 連接埠 53 與指派給執行 CoreDNS 的 Pods 的安全群組 (或 Pods 在其上執行的節點) 進行對外通訊。您的 CoreDNS Pods 的安全群組必須允許來自您所指定安全群組的傳入 TCPUDP 連接埠 53 流量。

      • 其必須具備必要的傳入和傳出規則,從而和其需要與之溝通的其他 Pods 溝通。

      • 如果您使用具有 Fargate 的安全群組,其必須具有允許 Pods 與 Kubernetes 控制平面通訊的規則。執行此動作最簡單的方法是指定叢集安全群組為其中一個安全群組。

      安全群組政策僅適用於新排程的 Pods。它們不會影響執行中的 Pods。

    2. 部署政策。

      kubectl apply -f my-security-group-policy.yaml
  3. 部署範例應用程式,其中標籤符合您在上一步驟指定的 podSelectormy-role 值。

    1. 將以下內容複製到您的裝置。使用您自己的值取代範例值,然後執行修改後的命令。如果您取代 my-role,請確保其與您在上一步中為選取器指定的值相同。

      cat >sample-application.yaml <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment namespace: my-namespace labels: app: my-app spec: replicas: 4 selector: matchLabels: app: my-app template: metadata: labels: app: my-app role: my-role spec: terminationGracePeriodSeconds: 120 containers: - name: nginx image: public.ecr.aws/nginx/nginx:1.23 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-app namespace: my-namespace labels: app: my-app spec: selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 80 EOF
    2. 使用下列命令部署應用程式。當您部署應用程式時,Amazon VPC CNI plugin for Kubernetes 符合您在上一步驟中指定的 role 標籤和安全群組,已套用至 Pod。

      kubectl apply -f sample-application.yaml
  4. 檢視與範例應用程式一起部署的 Pods。對於本主題的餘數,該終端機稱為 TerminalA

    kubectl get pods -n my-namespace -o wide

    範例輸出如下。

    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-deployment-5df6f7687b-4fbjm 1/1 Running 0 7m51s 192.168.53.48 ip-192-168-33-28.region-code.compute.internal <none> <none> my-deployment-5df6f7687b-j9fl4 1/1 Running 0 7m51s 192.168.70.145 ip-192-168-92-33.region-code.compute.internal <none> <none> my-deployment-5df6f7687b-rjxcz 1/1 Running 0 7m51s 192.168.73.207 ip-192-168-92-33.region-code.compute.internal <none> <none> my-deployment-5df6f7687b-zmb42 1/1 Running 0 7m51s 192.168.63.27 ip-192-168-33-28.region-code.compute.internal <none> <none>
    注意
    • 若有任何 Pods 卡在 Waiting 狀態,則請執行 kubectl describe pod my-deployment-xxxxxxxxxx-xxxxx -n my-namespace。若您看到 Insufficient permissions: Unable to create Elastic Network Interface.,請確認您已在上一步驟中將 IAM 政策新增至 IAM 叢集角色。

    • 如果有任何 Pods 卡在 Pending 狀態,請確認您的節點執行個體類型已列在 limits.go 中,並且尚未達到該執行個體類型支援的分支網路界面數量上限乘以節點群組中節點數量的乘積。例如,m5.large 執行個體支援九個分支網路介面。如果您的節點群組有五個節點,則最多可以為節點群組建立 45 個分支網路介面。您嘗試部署的第 46 個 Pod 將位於 Pending 狀態,直到刪除具有相關聯安全群組的另一個 Pod 為止。

    如果您執行 kubectl describe pod my-deployment-xxxxxxxxxx-xxxxx -n my-namespace,並看到類似下列訊息的訊息,則可以放心地將其忽略。如果在系統建立網路介面時 Amazon VPC CNI plugin for Kubernetes 嘗試設定主機聯網並失敗,可能會出現此訊息。外掛程式會記錄此事件,直到網路介面建立為止。

    Failed to create Pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "e24268322e55c8185721f52df6493684f6c2c3bf4fd59c9c121fd4cdc894579f" network for Pod "my-deployment-5df6f7687b-4fbjm": networkPlugin
    cni failed to set up Pod "my-deployment-5df6f7687b-4fbjm-c89wx_my-namespace" network: add cmd: failed to assign an IP address to container

    您不能超過執行個體類型上可以執行的 Pods 數量上限。關於每種執行個體類型上可執行的 Pods 數量上限清單,請參閱 GitHub 上的 eni-max-pods.txt。當您刪除具有關聯安全群組的 Pod,或刪除 Pod 執行所在的節點時,VPC 資源控制器會刪除分支網路介面。如果您使用安全群組的 Pods 來刪除具有 Pods 的叢集,則控制器不會刪除分支網路介面,因此您需要自行刪除它們。如需如何刪除網路界面的詳細資訊,請參閱 Amazon EC2 使用者指南中的刪除網路界面

  5. 在單獨的終端機中,shell 轉換為 Pods。對於本主題的餘數,該終端機稱為 TerminalB。使用從上一步驟傳回的輸出中的其中一個 Pods 的 ID 取代 5df6f7687b-4fbjm

    kubectl exec -it -n my-namespace my-deployment-5df6f7687b-4fbjm -- /bin/bash
  6. TerminalB 中的 shell,確認範例應用程式是否正常運作。

    curl my-app

    範例輸出如下。

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    [...]

    您收到了輸出,因為所有執行該應用程式的 Pods 都與您建立的安全群組關聯。該群組包含一個規則,其允許與安全群組關聯的所有 Pods 之間的流量。允許從該安全群組傳出 DNS 流量到與節點關聯的叢集安全群組。這些節點正在執行 CoreDNS Pods,您的 Pods 對此進行了名稱查詢。

  7. TerminalA 中,移除允許從安全群組與叢集進行 DNS 通訊的安全群組規則。如果在上一步驟並未新增 DNS 規則至叢集安全群組,則用您在其中建立規則的安全群組的 ID 取代 $my_cluster_security_group_id

    aws ec2 revoke-security-group-ingress --group-id $my_cluster_security_group_id --security-group-rule-ids $my_tcp_rule_id aws ec2 revoke-security-group-ingress --group-id $my_cluster_security_group_id --security-group-rule-ids $my_udp_rule_id
  8. TerminalB,再次嘗試存取該應用程式。

    curl my-app

    範例輸出如下。

    curl: (6) Could not resolve host: my-app

    嘗試失敗,因為 Pod 不再能存取 CoreDNS Pods,其具有與之關聯的叢集安全群組。叢集安全群組不再具有允許從與 Pod 關聯的安全群組進行 DNS 通訊的安全群組規則。

    如果您在上一步驟中,嘗試存取使用其中一個 Pods 傳回的 IP 地址的應用程式,您仍會接收到回應,因為已允許具有與之關聯的安全群組的 Pods 之間的所有連接埠,並且不需要進行名稱查詢。

  9. 在實驗完成後,您可以移除自己建立的範例安全群組政策、應用程式和安全群組。從 TerminalA 執行下列命令。

    kubectl delete namespace my-namespace aws ec2 revoke-security-group-ingress --group-id $my_pod_security_group_id --security-group-rule-ids $my_inbound_self_rule_id wait sleep 45s aws ec2 delete-security-group --group-id $my_pod_security_group_id