Amazon EKS Podのセキュリティグループポリシーを使用する
Podsのセキュリティグループを使用するには、既存のセキュリティグループが必要です。次のステップは、Pod に対してセキュリティグループポリシーを使用する方法を示しています。次のステップではターミナル間で保持されない変数が使用されるため、特に明記されていない限り、同じターミナルからすべてのステップを完了してください。
Amazon EC2 インスタンスを持つPodがある場合は、この手順を使用する前にプラグインを設定する必要があります。詳細については、「Amazon EKS Podsのセキュリティグループ用に Amazon VPC CNI plugin for Kubernetes を設定する」を参照してください。
-
リソースをデプロイする Kubernetes 名前空間を作成します。
my-namespace
は、使用する名前空間の名前に置き換えることができます。kubectl create namespace my-namespace
-
Amazon EKS
SecurityGroupPolicy
をクラスターにデプロイします。-
次のコンテンツをデバイスにコピーします。サービスアカウントラベルに基づいて Pods を選択したい場合は、
podSelector
をserviceAccountSelector
で置き換えることができます。セレクターをどちらか 1 つ指定する必要があります。podSelector
が空 (例:podSelector: {}
) であると、名前空間内のすべての Pods が選択されます。my-role
は自分のロール名に変更できます。serviceAccountSelector
が空であると、名前空間内のすべてのサービスアカウントが選択されます。my-security-group-policy
を自分のSecurityGroupPolicy
の名前に置き換え、my-namespace
はSecurityGroupPolicy
を作成する名前空間に置き換えることができます。my_pod_security_group_id
を既存のセキュリティグループの ID に置き換える必要があります。既存のセキュリティグループがない場合は、作成する必要があります。詳細については、「Amazon EC2 ユーザーガイド」の「Amazon EC2 security groups for Linux instances」(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
重要
Pods に対して指定した 1 つまたは複数のセキュリティグループは、次の基準を満たす必要があります。
-
存在している必要があります。セキュリティグループが存在しない場合、セレクターに一致する Pod をデプロイすると、Pod は作成プロセスでスタックしたままになります。Pod を記述すると、
An error occurred (InvalidSecurityGroupID.NotFound) when calling the CreateNetworkInterface operation: The securityGroup ID '
のようなエラーメッセージが表示されます。sg-05b1d815d1EXAMPLE
' does not exist -
プローブを設定した任意のポートを介して、ノードに適用されたセキュリティ グループ (
kubelet
の場合) からのインバウンド通信を許可する必要があります。 -
TCP
およびUDP
ポート 53 番経由のアウトバウンド通信を、CoreDNS を実行している Pods (または Pods が実行されるノード) に割り当てられたセキュリティグループへ許可する必要があります。CoreDNS Pods のセキュリティグループは、指定したセキュリティグループからのインバウンドTCP
およびUDP
ポート 53 番トラフィックを許可する必要があります。 -
セキュリティグループには、通信を行う必要がある他の Pods との通信に必要なインバウンドルールとアウトバウンドルールを含める必要があります。
-
Fargate でセキュリティグループを使用している場合は、セキュリティグループに、Pods と Kubernetes コントロールプレーンとの通信を許可するルールを含める必要があります。最も簡単な方法は、クラスターセキュリティグループをセキュリティグループの 1 つとして指定することです。
セキュリティグループポリシーは、新しくスケジュールされた Pods にのみ適用されます。実行中の Pods には影響しません。
-
-
ポリシーをデプロイします。
kubectl apply -f my-security-group-policy.yaml
-
-
前のステップで指定した
podSelector
のmy-role
の値に一致するラベルを持つサンプルアプリケーションをデプロイします。-
次のコンテンツをデバイスにコピーします。
サンプル値
を独自のものに置き換えて、変更したコマンドを実行します。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
-
次のコマンドを使用して、アプリケーションをデプロイします。アプリケーションをデプロイすると、Amazon VPC CNI plugin for Kubernetes は
role
ラベルと一致し、前のステップで指定したセキュリティグループが Pod に適用されます。kubectl apply -f sample-application.yaml
-
-
サンプルアプリケーションでデプロイされた 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
状態でスタックした Pods があれば、kubectl describe pod
を実行します。my-deployment-xxxxxxxxxx-xxxxx
-nmy-namespace
Insufficient permissions: Unable to create Elastic Network Interface.
が表示された場合、前のステップで IAM クラスターロールに IAM ポリシーを追加したことを確認します。 -
Pods が
Pending
状態でスタックした場合、ノードのインスタンスタイプが limits.goのリストに含まれていることを確認します。そのうえで、インスタンスタイプでサポートされるブランチネットワークインターフェイスの最大製品数とノードグループ内のノード数を乗算した数にまだ達していないことを確認します。例えば、 m5.large
インスタンスでは、9 つのブランチネットワークインターフェイスがサポートされています。ノードグループに 5 つのノードがある場合、ノードグループに対して最大 45 のブランチネットワークインターフェイスを作成できます。46 個目の Pod をデプロイしようとすると、セキュリティグループに関連付けられた別の Pod が削除されるまでPending
状態のままになります。
kubectl describe pod
を実行したときに次のようなメッセージが表示されている場合は、無視しても問題ありません。このメッセージは、Amazon VPC CNI plugin for Kubernetes がホストネットワークの設定を試み、ネットワークインターフェイスの作成中に失敗したときに表示される場合があります。プラグインは、ネットワークインターフェイスが作成されるまで、このイベントをログに記録します。my-deployment-xxxxxxxxxx-xxxxx
-nmy-namespace
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 ユーザーガイド」の「ネットワークインターフェイスの削除」を参照してください。 -
-
別のターミナルから Pods のいずれかをシェルで操作します。このトピックの以降の説明では、このターミナルを
TerminalB
と呼びます。5df6f7687b
-4fbjm
kubectl exec -it -n my-namespace my-deployment-5df6f7687b-4fbjm -- /bin/bash
-
TerminalB
のシェルから、サンプルアプリケーションが動作することを確認します。curl my-app
出力例は次のとおりです。
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> [...]
アプリケーションを実行しているすべての Pods が、作成したセキュリティグループに関連付けられているため、出力を受信できます。そのグループには、セキュリティグループが関連付けられているすべての Pods 間のすべてのトラフィックを許可するルールが含まれています。DNS トラフィックは、そのセキュリティグループからノードに関連付けられているクラスターセキュリティグループへのアウトバウンドで許可されます。ノードは、Pods が名前のルックアップを実行した CoreDNS Podsを実行しています。
-
TerminalA
で、クラスターセキュリティグループへの DNS 通信を許可するセキュリティグループルールを、セキュリティグループから削除します。前のステップで DNS ルールをクラスターセキュリティグループに追加しなかった場合は、$my_cluster_security_group_id
を、ルールを作成したセキュリティグループの 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
-
TerminalB
で、アプリケーションにもう一度アクセスしてみます。curl my-app
出力例は次のとおりです。
curl: (6) Could not resolve host: my-app
クラスターセキュリティグループが関連付けられている CoreDNS Pods に Pod がアクセスできなくなったため、この試行は失敗します。クラスターセキュリティグループから、Pod に関連付けられたセキュリティグループからの DNS 通信を許可するセキュリティグループルールがなくなりました。
前のステップで、いずれかの Pods に返された IP アドレスを使用してアプリケーションにアクセスしようとすると、セキュリティグループが関連付けられており、名前のルックアップが不要な Pods 間ですべてのポートが許可されているため、引き続き応答を受信します。
-
試行し終えたら、作成したサンプルのセキュリティグループポリシー、アプリケーション、およびセキュリティグループを削除できます。
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