

 **このページの改善にご協力ください** 

このユーザーガイドに貢献するには、すべてのページの右側のペインにある「**GitHub でこのページを編集する**」リンクを選択してください。

# Amazon EKS Pod のセキュリティグループポリシーを使用する
<a name="sg-pods-example-deployment"></a>

Pod のセキュリティグループを使用するには、既存のセキュリティグループが必要です。次のステップは、Pod に対してセキュリティグループポリシーを使用する方法を示しています。次のステップではターミナル間で保持されない変数が使用されるため、特に明記されていない限り、同じターミナルからすべてのステップを完了してください。

Amazon EC2 インスタンスを持つ Pod がある場合は、この手順を使用する前にプラグインを設定する必要があります。詳細については、「[Amazon EKS Pod のセキュリティグループ用に Amazon VPC CNI Plugin for Kubernetes を設定する](security-groups-pods-deployment.md)」を参照してください。

1.  リソースをデプロイする Kubernetes 名前空間を作成します。{{my-namespace}} は使用する名前空間の名前に置き換えることができます。

   ```
   kubectl create namespace my-namespace
   ```

1.  アマゾン EKS `SecurityGroupPolicy` をクラスターにデプロイします。

   1. 次のコンテンツをデバイスにコピーします。サービスアカウントラベルに基づいて Pod を選択したい場合は、{{podSelector}} を `serviceAccountSelector` で置き換えることができます。セレクターをどちらか 1 つ指定する必要があります。`podSelector` が空 (例: `podSelector: {}`) であると、名前空間内のすべての Pod が選択されます。{{my-role}} は自分の役割名に変更できます。`serviceAccountSelector` が空であると、名前空間内のすべてのサービスアカウントが選択されます。{{my-security-group-policy}} を自分の `SecurityGroupPolicy` の名前に置き換え、{{my-namespace}} は `SecurityGroupPolicy` を作成する名前空間に置き換えることができます。

      {{my\_pod\_security\_group\_id}} を既存のセキュリティグループの ID に置き換える必要があります。既存のセキュリティグループがない場合は作成する必要があります。詳細については「[アマゾン EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/)」の「[アマゾン EC2 security groups for リナックス instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)」(リナックス インスタンス用の アマゾン EC2 セキュリティグループ) を参照してください。1～5 個のセキュリティグループ ID を指定できます。複数の ID を指定した場合、すべてのセキュリティグループ内のすべてのルールの組み合わせが、選択した Pod に対して有効になります。

      ```
      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 に対して指定した 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 を実行しているPod (または Pod が実行されるノード) に割り当てられたセキュリティグループへ許可する必要があります。CoreDNS Pod のセキュリティグループは、指定したセキュリティグループからのインバウンド `TCP` および `UDP` ポート 53 番トラフィックを許可する必要があります。
セキュリティグループには、通信を行う必要がある他の Pod との通信に必要なインバウンドルールとアウトバウンドルールを含める必要があります。
Fargate でセキュリティグループを使用している場合は、セキュリティグループに、Pod と Kubernetes コントロールプレーンとの通信を許可するルールを含める必要があります。最も簡単な方法はクラスターセキュリティグループをセキュリティグループの 1 つとして指定することです。
セキュリティグループポリシーは、新しくスケジュールされた Pod にのみ適用されます。実行中の Pod には影響しません。

   1. ポリシーをデプロイします。

      ```
      kubectl apply -f my-security-group-policy.yaml
      ```

1. 前のステップで指定した {{podSelector}} の {{my-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
      ```

   1. 次のコマンドを使用して、アプリケーションをデプロイします。アプリケーションをデプロイすると、Amazon VPC CNI Plugin for Kubernetes が `role` ラベルと一致し、前のステップで指定したセキュリティグループが Pod に適用されます。

      ```
      kubectl apply -f sample-application.yaml
      ```

1. サンプルアプリケーションでデプロイされた Pod を表示します。このトピックの以降の説明ではこのターミナルを `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>
   ```
**注記**  
Pod がスタックしている場合は次のヒントをお試しください。  
`Waiting` 状態でスタックした Pod があれば、`kubectl describe pod {{my-deployment-xxxxxxxxxx-xxxxx}} -n {{my-namespace}} ` を実行してください。`Insufficient permissions: Unable to create Elastic Network Interface.` が表示された場合、前のステップで IAM クラスター役割に IAM ポリシーを追加したことを確認します。
Pod が `Pending` 状態でスタックした場合、ノードのインスタンスタイプが [limits.go](https://github.com/aws/amazon-vpc-resource-controller-k8s/blob/master/pkg/aws/vpc/limits.go) のリストに含まれていることを確認します。そのうえで、インスタンスタイプでサポートされるブランチネットワークインターフェイスの最大製品数とノードグループ内のノード数を乗算した数にまだ達していないことを確認します。例えば、`m5.large` インスタンスでは9 つのブランチネットワークインターフェイスがサポートされています。ノードグループに 5 つのノードがある場合、ノードグループに対して最大 45 のブランチネットワークインターフェイスを作成できます。46 番目の Pod をデプロイしようとすると、セキュリティグループに関連付けられた別の Pod が削除されるまで `Pending` 状態のままになります。

   `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
   ```

   インスタンスタイプで実行できる Pod の最大数を超えることはできません。各インスタンスタイプで実行できるポッドの最大数の一覧については、GitHub の「[eni-max-pods.txt](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/misc/eni-max-pods.txt)」を参照してください。セキュリティグループが関連付けられているポッドを削除するか、ポッドが実行されているノードを削除すると、VPC リソースコントローラーによってブランチネットワークインターフェイスが削除されます。セキュリティグループ用に Pod を含むクラスターを Pod で削除する場合、コントローラーではブランチネットワークインターフェイスを削除しないため、自分で削除する必要があります。ネットワークインターフェイスの削除方法の詳細については「Amazon EC2 ユーザーガイド」の「[ネットワークインターフェイスの削除](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#delete_eni)」を参照してください。

1. 別のターミナルで、Pod のいずれかをシェルで操作します。このトピックの以降の説明ではこのターミナルを `TerminalB` と呼びます。{{5df6f7687b-4fbjm}} を、前の手順の出力で返された Pod のいずれかの ID に置き換えます。

   ```
   kubectl exec -it -n my-namespace my-deployment-5df6f7687b-4fbjm -- /bin/bash
   ```

1. `TerminalB` のシェルから、サンプルアプリケーションが動作することを確認します。

   ```
   curl my-app
   ```

   出力例は次のとおりです。

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

   アプリケーションを実行しているすべての Pod が作成したセキュリティグループに関連付けられているため、出力を受信できます。そのグループにはセキュリティグループが関連付けられているすべての Pod 間のすべてのトラフィックを許可するルールが含まれています。DNS トラフィックはそのセキュリティグループからノードに関連付けられているクラスターセキュリティグループへのアウトバウンドで許可されます。ノードは、Pod が名前のルックアップを実行した CoreDNS Pod を実行しています。

1. `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
   ```

1. `TerminalB` で、アプリケーションにもう一度アクセスしてみます。

   ```
   curl my-app
   ```

   出力例は次のとおりです。

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

   クラスターセキュリティグループが関連付けられている CoreDNS Pod に Pod がアクセスできなくなったため、この試行は失敗します。クラスターセキュリティグループから、Pod に関連付けられたセキュリティグループからの DNS 通信を許可するセキュリティグループルールがなくなりました。

   前のステップで、いずれかの Pod に返された IP アドレスを使用してアプリケーションにアクセスしようとすると、セキュリティグループが関連付けられており、名前のルックアップが不要な Pod 間ですべてのポートが許可されているため、引き続き応答を受信します。

1. 試行し終えたら、作成したサンプルのセキュリティグループポリシー、アプリケーション、およびセキュリティグループを削除できます。`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
   ```