

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

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

# Amazon EKS ノードのセカンダリネットワークインターフェイスをカスタマイズする
<a name="cni-custom-network-tutorial"></a>

このチュートリアルを開始する前に以下を完了してください：
+ 考慮事項を確認する
+ Amazon VPC CNI plugin for Kubernetes によるセカンダリネットワークインターフェイスの作成と、Pod への IP アドレス割り当て方法に関する知識。詳細については、GitHub の「[ENI Allocation](https://github.com/aws/amazon-vpc-cni-k8s#eni-allocation)」(ENI 割り当て) を参照してください。
+ ご使用のデバイスまたは AWS クラウドシェル で、バージョン `2.12.3` 以降、または AWS コマンドラインインターフェイス (AWS CLI のバージョン `1.27.160` 以降がインストールおよび設定されていること。現在のバージョンを確認するには「`aws --version | cut -d / -f2 | cut -d ' ' -f1`」を参照してください。`yum`、`apt-get`、macOS 用の Homebrew などのパッケージマネージャーは、多くの場合 AWS CLI の最新バージョンより数バージョン古くなっています。最新バージョンをインストールするには「*AWS コマンドラインインターフェイスユーザーガイド*」の「[インストール](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)」および「[aws configure を使用したクイック設定](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)」を参照してください。AWS クラウドシェル にインストールされている AWS CLI バージョンも最新バージョンより数バージョン遅れることがあります。更新するには、「*AWS CloudShell ユーザーガイド*」の「[ホームディレクトリへの AWS CLI のインストール](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)」を参照してください。
+ デバイスまたは AWS クラウドシェル に、`kubectl` コマンドラインツールがインストールされていること。`kubectl` をインストールまたはアップグレードする方法については「[`kubectl` および `eksctl` のセットアップ](install-kubectl.md)」を参照してください。
+ このトピック内のステップはBash シェル内で実行することが推奨されます。Bash シェルを使用していない場合、行継続文字や、変数の設定と使用に関する方法など、一部のスクリプトコマンドのためにシェルの調整が必要となります。さらに、シェルの引用規則とエスケープ規則は異なる場合があります。詳細については「AWS コマンドラインインターフェイスのユーザーガイド」の「[AWS CLI での文字列への引用符の使用](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-quoting-strings.html)」を参照してください。

このチュートリアルでは置き換えが必要だと明記されている場合を除き、サンプル値をそのまま使用することをお勧めします。本番向けクラスター向けにステップを完了する際には例値 を任意の値に置き換えることができます。すべてのステップは同一のターミナルで実行することをお勧めします。設定された変数はステップ全体で使用され、また、これらは異なるターミナルには存在しないためです。

このトピックのコマンドは「[AWS CLI 使用例を使用する](https://docs.aws.amazon.com/cli/latest/userguide/welcome-examples.html)」に記載されている規則に従ってフォーマットされています。使用している AWS CLI [プロファイル](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-profiles)で定義されているデフォルトの AWS リージョンとは異なる AWS リージョンにあるリソースに対してコマンドラインからコマンドを実行する場合はコマンドに `--region us-west-2` を追加する必要があります。`us-west-2` は自分の AWS リージョンに置き換えます。

カスタムネットワーキングを本番用クラスターにデプロイする場合は、[ステップ 2: VPC を設定する](#custom-networking-configure-vpc) にスキップします。

## ステップ 1: テスト VPC およびクラスターを作成する
<a name="custom-networking-create-cluster"></a>

次の手順により、テスト VPC とクラスターを作成し、そのたクラスターのためにカスタムネットワークを構成できます。本番向けのクラスターで必要になるいくつかの機能で、このトピックに関連のないものについては説明していません。そのため、本番ワークロード向けに、このテストクラスターを使用することはお勧めしません。詳細については、「[Amazon EKS クラスターを作成します。](create-cluster.md)」を参照してください。

1. 以下のコマンドを実行して、`account_id` 変数を定義します。

   ```
   account_id=$(aws sts get-caller-identity --query Account --output text)
   ```

1. VPC を作成します。

   1. テストシステムにデプロイする場合は Amazon EKS AWS クラウドフォーメーション テンプレートを使用して VPC を作成します。

      ```
      aws cloudformation create-stack --stack-name my-eks-custom-networking-vpc \
        --template-url https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/amazon-eks-vpc-private-subnets.yaml \
        --parameters ParameterKey=VpcBlock,ParameterValue=192.168.0.0/24 \
        ParameterKey=PrivateSubnet01Block,ParameterValue=192.168.0.64/27 \
        ParameterKey=PrivateSubnet02Block,ParameterValue=192.168.0.96/27 \
        ParameterKey=PublicSubnet01Block,ParameterValue=192.168.0.0/27 \
        ParameterKey=PublicSubnet02Block,ParameterValue=192.168.0.32/27
      ```

   1. AWS クラウドFormation スタックが作成されるまで数分かかります。次のコマンドを実行して、スタックのデプロイステータスを確認します。

      ```
      aws cloudformation describe-stacks --stack-name my-eks-custom-networking-vpc --query Stacks\[\].StackStatus  --output text
      ```

      コマンドの出力が「`CREATE_COMPLETE`」になるまで、次のステップに進まないでください。

   1. テンプレートによって作成された、プライベートサブネット ID の値により変数を定義します。

      ```
      subnet_id_1=$(aws cloudformation describe-stack-resources --stack-name my-eks-custom-networking-vpc \
          --query "StackResources[?LogicalResourceId=='PrivateSubnet01'].PhysicalResourceId" --output text)
      subnet_id_2=$(aws cloudformation describe-stack-resources --stack-name my-eks-custom-networking-vpc \
          --query "StackResources[?LogicalResourceId=='PrivateSubnet02'].PhysicalResourceId" --output text)
      ```

   1. 前のステップで取得した、サブネットのアベイラビリティーゾーンを使用して変数を定義します。

      ```
      az_1=$(aws ec2 describe-subnets --subnet-ids $subnet_id_1 --query 'Subnets[*].AvailabilityZone' --output text)
      az_2=$(aws ec2 describe-subnets --subnet-ids $subnet_id_2 --query 'Subnets[*].AvailabilityZone' --output text)
      ```

1. クラスターの IAM ロールを作成します。

   1. IAM 信頼ポリシー用の JSON ファイルを作成するには次のコマンドを実行してください。

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
              "Service": "eks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
          }
        ]
      }
      ```

   1. Amazon EKS クラスター の IAM ロールを作成します。必要に応じて、`eks-cluster-role-trust-policy.json` の前に、ステップでファイルの書き込み先となったコンピュータ上のパスを追加します。このコマンドは前のステップで作成した信頼ポリシーをロールに関連付けます。IAM ロールを作成するにはロールを作成する [IAM プリンシパル](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#iam-term-principal)に `iam:CreateRole` アクション (許可) を割り当てる必要があります。

      ```
      aws iam create-role --role-name myCustomNetworkingAmazonEKSClusterRole --assume-role-policy-document file://"eks-cluster-role-trust-policy.json"
      ```

   1. [AmazonEKSClusterPolicy](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEKSClusterPolicy.html#AmazonEKSClusterPolicy-json) という名前の Amazon EKS マネージド型ポリシーをロールにアタッチします。IAM ポリシーを [IAM プリンシパル](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#iam-term-principal)にアタッチするにはポリシーのアタッチを行っているプリンシパルに、次のいずれかの IAM アクション (許可) を割り当てる必要があります: `iam:AttachUserPolicy` または `iam:AttachRolePolicy`

      ```
      aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy --role-name myCustomNetworkingAmazonEKSClusterRole
      ```

1. Amazon EKS クラスターを作成し、このクラスターとデバイスの間の通信を設定します。

   1. クラスターを作成する。

      ```
      aws eks create-cluster --name my-custom-networking-cluster \
         --role-arn arn:aws:iam::$account_id:role/myCustomNetworkingAmazonEKSClusterRole \
         --resources-vpc-config subnetIds="$subnet_id_1","$subnet_id_2"
      ```
**注記**  
リクエストで指定したアベイラビリティーゾーンのいずれかに、Amazon EKS クラスターの作成に十分な容量がない場合にはエラーが表示されることがあります。このエラー出力には新しいクラスターをサポートできるアベイラビリティーゾーンが表示されます。アカウント向けにサポートされているアベイラビリティーゾーンにある 2 つ以上のサブネットを使用して、クラスターを作成します。詳細については「[容量不足](troubleshooting.md#ice)」を参照してください。

   1. クラスターが作成されるまでに数分かかります。次のコマンドを実行して、クラスターのデプロイステータスを確認します。

      ```
      aws eks describe-cluster --name my-custom-networking-cluster --query cluster.status
      ```

      コマンドの出力が「`"ACTIVE"`」になるまで、次のステップに進まないでください。

   1. クラスターと通信するために `kubectl` を設定します。

      ```
      aws eks update-kubeconfig --name my-custom-networking-cluster
      ```

## ステップ 2: VPC を設定する
<a name="custom-networking-configure-vpc"></a>

このチュートリアルでは、[ステップ 1: テスト VPC およびクラスターを作成する](#custom-networking-create-cluster) で作成した VPC が必要です。本番向けクラスターの場合は、example values をすべて実際の値に置き換えて、VPC に合うように各ステップを調整します。

1. 現在インストールされている Amazon VPC CNI plugin for Kubernetes が最新バージョンであることを確認します。Amazon EKS アドオンタイプの最新バージョンを確認し、そのバージョンに更新するには「[Amazon EKS アドオンを更新する](updating-an-add-on.md)」を参照してください。セルフマネージドアドオンタイプの最新バージョンを確認し、そのバージョンに更新するには「[Amazon VPC CNI を使用して Pod に IP を割り当てる](managing-vpc-cni.md)」を参照してください。

1. クラスター VPC の ID を取得し、後のステップで使用するために変数に格納します。

   ```
   vpc_id=$(aws eks describe-cluster --name my-custom-networking-cluster --query "cluster.resourcesVpcConfig.vpcId" --output text)
   ```

1. 追加の Classless Inter-Domain Routing (CIDR ブロックを、クラスターの VPC に関連付けます。CIDR ブロックは既存の関連付けられた CIDR ブロックと重複することはできません。

   1. 現在 VPC に関連付けられている CIDR ブロックを表示します。

      ```
      aws ec2 describe-vpcs --vpc-ids $vpc_id \
          --query 'Vpcs[*].CidrBlockAssociationSet[*].{CIDRBlock: CidrBlock, State: CidrBlockState.State}' --out table
      ```

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

      ```
      ----------------------------------
      |          DescribeVpcs          |
      +-----------------+--------------+
      |    CIDRBlock    |    State     |
      +-----------------+--------------+
      |  192.168.0.0/24 |  associated  |
      +-----------------+--------------+
      ```

   1. 追加の CIDR ブロックを VPC に関連付けます。次のコマンドで CIDR ブロック値を置き換えます。詳細については「Amazon VPC ユーザーガイド」の「[追加の IPv4 CIDR ブロックと VPC の関連付け](https://docs.aws.amazon.com/vpc/latest/userguide/modify-vpcs.html#add-ipv4-cidr)」を参照してください。

      ```
      aws ec2 associate-vpc-cidr-block --vpc-id $vpc_id --cidr-block 192.168.1.0/24
      ```

   1. 新しいブロックが関連付けられていることを確認します。

      ```
      aws ec2 describe-vpcs --vpc-ids $vpc_id --query 'Vpcs[*].CidrBlockAssociationSet[*].{CIDRBlock: CidrBlock, State: CidrBlockState.State}' --out table
      ```

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

      ```
      ----------------------------------
      |          DescribeVpcs          |
      +-----------------+--------------+
      |    CIDRBlock    |    State     |
      +-----------------+--------------+
      |  192.168.0.0/24 |  associated  |
      |  192.168.1.0/24 |  associated  |
      +-----------------+--------------+
      ```

   新しい CIDR ブロックの `State` が `associated` に遷移するまで、次のステップには進まないでください。

1. 既存のサブネットが存在する各アベイラビリティーゾーン内で、使用するサブネットを必要な数だけ作成します。前のステップで VPC に関連付けた、CIDR ブロック内にある CIDR ブロックを指定します。

   1. 新しいサブネットを作成します。次のコマンドで CIDR ブロック値を置き換えます。サブネットは既存のサブネットが置かれているものとは異なる VPC CIDR ブロックの中に作成する必要があり、作成するアベイラビリティーゾーンは既存のサブネットと同じにする必要があります。この例では現在のプライベートサブネットが存在する各アベイラビリティーゾーンにある新しい CIDR ブロックの中に、1 つのサブネットが作成されます。作成されたサブネットの ID は後のステップで使用するために変数に格納されます。`Name` の値は前のステップで Amazon EKS VPC テンプレートを使用して作成されたサブネットに、割り当てられている値と一致します。名前は必須ではありません。名前には異なる値を使用できます。

      ```
      new_subnet_id_1=$(aws ec2 create-subnet --vpc-id $vpc_id --availability-zone $az_1 --cidr-block 192.168.1.0/27 \
          --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=my-eks-custom-networking-vpc-PrivateSubnet01},{Key=kubernetes.io/role/internal-elb,Value=1}]' \
          --query Subnet.SubnetId --output text)
      new_subnet_id_2=$(aws ec2 create-subnet --vpc-id $vpc_id --availability-zone $az_2 --cidr-block 192.168.1.32/27 \
          --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=my-eks-custom-networking-vpc-PrivateSubnet02},{Key=kubernetes.io/role/internal-elb,Value=1}]' \
          --query Subnet.SubnetId --output text)
      ```
**重要**  
デフォルトで新しいサブネットはVPC の[メインルートテーブル](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html#RouteTables)に暗黙的に関連付けられます。このルートテーブルにより、その VPC にデプロイされているすべてのリソース間の通信が可能になります。ただし、VPC に関連付けられた CIDR ブロックの外部にある IP アドレスが割り当てられたリソースとの通信は許可されません。この動作を変更するには独自のルートテーブルをサブネットに関連付けます。詳細については「Amazon VPC ユーザーガイド」の「[サブネットルートテーブル](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html#subnet-route-tables)」を参照してください。

   1. 使用している VPC の現在のサブネットを表示します。

      ```
      aws ec2 describe-subnets --filters "Name=vpc-id,Values=$vpc_id" \
          --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \
          --output table
      ```

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

      ```
      ----------------------------------------------------------------------
      |                           DescribeSubnets                          |
      +------------------+--------------------+----------------------------+
      | AvailabilityZone |     CidrBlock      |         SubnetId           |
      +------------------+--------------------+----------------------------+
      |  us-west-2d      |  192.168.0.0/27    |     subnet-example1        |
      |  us-west-2a      |  192.168.0.32/27   |     subnet-example2        |
      |  us-west-2a      |  192.168.0.64/27   |     subnet-example3        |
      |  us-west-2d      |  192.168.0.96/27   |     subnet-example4        |
      |  us-west-2a      |  192.168.1.0/27    |     subnet-example5        |
      |  us-west-2d      |  192.168.1.32/27   |     subnet-example6        |
      +------------------+--------------------+----------------------------+
      ```

      作成した `192.168.1.0` CIDR ブロック内のサブネットが、`192.168.0.0` CIDR ブロック内のサブネットと同じアベイラビリティーゾーンに置かれていることが確認できます。

## ステップ 3: Kubernetes リソースを設定する
<a name="custom-networking-configure-kubernetes"></a>

1. `aws-node` DaemonSet で `AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG` 環境変数を `true` に設定します。

   ```
   kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true
   ```

1. [クラスターのセキュリティグループ](sec-group-reqs.md)の ID を取得し、次のステップで使用するために変数に格納します。このセキュリティグループはクラスターの作成時に Amazon EKS により自動的に作成されます。

   ```
   cluster_security_group_id=$(aws eks describe-cluster --name my-custom-networking-cluster --query cluster.resourcesVpcConfig.clusterSecurityGroupId --output text)
   ```

1.   Pod をデプロイするサブネットごとに `ENIConfig` カスタムリソースを作成します。

   1. 各ネットワークインターフェイス設定に固有のファイルを作成します。

      次のコマンドでは、前のステップで作成した 2 つのサブネットのそれぞれに、個別の `ENIConfig` ファイルが作成されます。`name` の値は一意である必要があります。これらの名前はサブネットが存在するアベイラビリティーゾーンと同じものが付けられます。クラスターセキュリティグループは、`ENIConfig` に割り当てられます。

      ```
      cat >$az_1.yaml <<EOF
      apiVersion: crd.k8s.amazonaws.com/v1alpha1
      kind: ENIConfig
      metadata:
        name: $az_1
      spec:
        securityGroups:
          - $cluster_security_group_id
        subnet: $new_subnet_id_1
      EOF
      ```

      ```
      cat >$az_2.yaml <<EOF
      apiVersion: crd.k8s.amazonaws.com/v1alpha1
      kind: ENIConfig
      metadata:
        name: $az_2
      spec:
        securityGroups:
          - $cluster_security_group_id
        subnet: $new_subnet_id_2
      EOF
      ```

      本番向けのクラスターでは、前のコマンドに次の変更を行います。
      + \$1cluster\$1security\$1group\$1id は各 `ENIConfig` で使用する既存の[セキュリティグループ](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)の ID に置き換えます。
      + 可能な限り、`ENIConfig` が使用されるアベイラビリティーゾーンと同じ名前を、`ENIConfigs` に付けることをお勧めします。いくつかの理由から、`ENIConfigs` に対して、アベイラビリティーゾーンとは異なる名前を使用する必要が生じることがあります。例えば、同じアベイラビリティーゾーンに 3 つ以上のサブネットがあり、そのすべてでカスタムネットワーキングを使用したい場合は同一のアベイラビリティーゾーンに複数の `ENIConfigs` が必要になります。各 `ENIConfig` には一意の名前が必要であるため、複数の `ENIConfigs` に対しアベイラビリティーゾーンの名前を使用することはできません。

        `ENIConfig` の中で、アベイラビリティーゾーンと異なる名前を持つものについては前のコマンドで \$1az\$11 と \$1az\$12 を独自の名前に置き換えます。さらに、この後のチュートリアルで [ENIConfig でノードをアノテーション](#custom-networking-annotate-eniconfig)します。
**注記**  
本番向けクラスターで使用するために有効なセキュリティグループを指定しておらず、かつ:
      + Amazon VPC CNI plugin for Kubernetes のバージョン `1.8.0` 以降を使用する場合は、ノードのプライマリ Elastic Network Interface に関連付けられたセキュリティグループが使用されます。
      + `1.8.0` より前のバージョンの Amazon VPC CNI plugin for Kubernetes を使用している場合は、VPC のデフォルトのセキュリティグループが、セカンダリネットワークインターフェイスに割り当てられます。
**重要**  
 `AWS_VPC_K8S_CNI_EXTERNALSNAT=false` は、Kubernetes 用 Amazon VPC CNI プラグインのデフォルトの設定です。デフォルト設定を使用している場合、VPC に関連付けられた CIDR ブロックのいずれにもない IP アドレスに向けて送信されたトラフィックにはノードのプライマリネットワークインターフェイスでの、セキュリティグループとサブネットが使用されます。セカンダリネットワークインターフェイスを作成するために使用された、`ENIConfigs` で定義されているサブネットとセキュリティグループはこのトラフィックでは使用されません。この設定の詳細については「[Pod のアウトバウンドインターネットアクセスを有効にする](external-snat.md)」を参照してください。
また、Pod でもセキュリティグループを使用する場合、そのセキュリティグループは `SecurityGroupPolicy` で指定されたものとなり、`ENIConfigs` で指定されたものは使用されません。詳細については、「[セキュリティグループを個別の Pod に割り当てる](security-groups-for-pods.md)」を参照してください。

   1. 以下のコマンドを使用して、作成したカスタムリソースファイルをそれぞれクラスターに適用します。

      ```
      kubectl apply -f $az_1.yaml
      kubectl apply -f $az_2.yaml
      ```

1. `ENIConfigs` が作成されたことを確認します。

   ```
   kubectl get ENIConfigs
   ```

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

   ```
   NAME         AGE
   us-west-2a   117s
   us-west-2d   105s
   ```

1. 本番向けのクラスターで、カスタムネットワーキングを有効にしており、`ENIConfigs` の名前を使用されているアベイラビリティーゾーンとは異なるものにした場合は[次のステップ](#custom-networking-deploy-nodes)に移り、Amazon EC2 ノードをデプロイします。

   クラスターで作成された任意の新しい Amazon EC2 ノードに対し、Kubernetes がアベイラビリティーゾーン用の `ENIConfig` を自動的に適用することを許可します。

   1. このチュートリアルでのテスト用クラスターの場合は、このまま[次のステップ](#custom-networking-automatically-apply-eniconfig)に移動します。

      実稼働クラスターの場合は、` [ENI\$1CONFIG\$1ANNOTATION\$1DEF](https://github.com/aws/amazon-vpc-cni-k8s#eni_config_annotation_def) ` 環境変数用のキー `aws-node` を使用するアノテーションが、`k8s.amazonaws.com/eniConfig` DaemonSet のためのコンテナ仕様内に存在することを確認します。

      ```
      kubectl describe daemonset aws-node -n kube-system | grep ENI_CONFIG_ANNOTATION_DEF
      ```

      出力が返される場合はアノテーションが存在します。出力が返されない場合、その変数は設定されていません。本番向けクラスターの場合にはここでの設定と、以降のステップで示す設定のどちらも使用可能です。ここでの設定を使用すると、以降のステップの設定は上書きされます。このチュートリアルではこの後のステップでの設定を使用します。

   1.  クラスター内に作成された任意の新しい Amazon EC2 ノードに対し、自動的にアベイラビリティーゾーンの `ENIConfig` を適用するように、`aws-node` DaemonSet を更新します。

      ```
      kubectl set env daemonset aws-node -n kube-system ENI_CONFIG_LABEL_DEF=topology.kubernetes.io/zone
      ```

## ステップ 4: Amazon EC2 ノードをデプロイする
<a name="custom-networking-deploy-nodes"></a>

1. ノードの IAM ロールを作成します。

   1. IAM 信頼ポリシー用の JSON ファイルを作成するには次のコマンドを実行してください。

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
              "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
          }
        ]
      }
      ```

   1. IAM ロールを作成し、返された Amazon リソースネーム (ARN) を、後のステップで使用するために変数に格納します。

      ```
      node_role_arn=$(aws iam create-role --role-name myCustomNetworkingNodeRole --assume-role-policy-document file://"node-role-trust-relationship.json" \
          --query Role.Arn --output text)
      ```

   1. IAM ロールに、3 つの必須な IAM マネージドポリシーをアタッチします。

      ```
      aws iam attach-role-policy \
        --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy \
        --role-name myCustomNetworkingNodeRole
      aws iam attach-role-policy \
        --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \
        --role-name myCustomNetworkingNodeRole
      aws iam attach-role-policy \
          --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy \
          --role-name myCustomNetworkingNodeRole
      ```
**重要**  
分かりやすくするため、このチュートリアルでは[AmazonEKS\$1CNI\$1Policy](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEKS_CNI_Policy.html) ポリシーはノードの IAM ロールにアタッチされています。ただし、本番向けクラスターの場合は、Amazon VPC CNI plugin for Kubernetes のみで使用される IAM ロールに、個別にポリシーをアタッチすることをお勧めします。詳細については、「[IRSA を使用するように Amazon VPC CNI プラグインを設定する](cni-iam-role.md)」を参照してください。

1. 次のいずれかのタイプのノードグループを作成します。デプロイするインスタンスタイプを確認するには「[最適な Amazon EC2 ノードインスタンスタイプを選択する](choosing-instance-type.md)」を参照してください。このチュートリアルのために、**マネージド型**、および**起動テンプレートを使用しない、または AMI ID が指定されていない起動テンプレートを使用する**オプションを完了します。本番ワークロードでノードグループを使用する場合はそのグループをデプロイする前に、[マネージドノードグループ](create-managed-node-group.md)および[セルフマネージドノードグループ](worker.md)のすべてのオプションについて理解しておくことをお勧めします。
   +  **マネージド型** — 次のいずれかのオプションを使用して、ノードグループをデプロイします：
     +  **起動テンプレートを使用しない、または AMI ID が指定されていない起動テンプレートを使用する** — 次のコマンドを実行してください。このチュートリアルではサンプルの値を使用します。本番向けのノードグループの場合はすべてのサンプルの値を、実際の値に置き換えてください。ノードグループ名は 63 文字以下である必要があります。先頭は文字または数字でなければなりませんが、残りの文字にはハイフンおよびアンダースコアを含めることもできます。

       ```
       aws eks create-nodegroup --cluster-name my-custom-networking-cluster --nodegroup-name my-nodegroup \
           --subnets $subnet_id_1 $subnet_id_2 --instance-types t3.medium --node-role $node_role_arn
       ```
     +  **指定された AMI ID を持つ起動テンプレートを使用** 

       1. ノードでの Pod について、Amazon EKS で推奨される最大数を決定します。「」の指示に従い、そのトピックのステップ 3 で `--cni-custom-networking-enabled` を追加します。後のステップで使用するために、この出力を書き留めます。

       1. 起動テンプレートで、Amazon EKS 最適化 AMI ID を指定するか、Amazon EKS 最適化 AMI から構築されたカスタム AMI を指定します。その後、[起動テンプレートを使用してノードグループをデプロイ](launch-templates.md)し、さらに、起動テンプレートにある次のユーザーデータを指定します。このユーザーデータは、引数を `NodeConfig` 仕様に渡します。NodeConfig の詳細については、「[NodeConfig API リファレンス](https://awslabs.github.io/amazon-eks-ami/nodeadm/doc/api/#nodeconfig)」を参照してください。`20` は、前のステップで使用した値 (推奨) か、または独自の値に置き換えることができます。

          ```
          ---
          MIME-Version: 1.0
          Content-Type: multipart/mixed; boundary="BOUNDARY"
          --BOUNDARY
          Content-Type: application/node.eks.aws
          
          ---
          apiVersion: node.eks.aws/v1alpha1
          kind: NodeConfig
          spec:
            cluster:
              name: my-cluster
              ...
              kubelet:
                config:
                  maxPods: 20
          ```

          Amazon EKS 最適化 AMI から構築されていないカスタム AMI を作成した場合は自分で設定をカスタム作成する必要があります。
   +  **セルフマネージド型** 

     1. ノードでの Pod について、Amazon EKS で推奨される最大数を決定します。 の手順に従います (`--cni-custom-networking-enabled` をステップ 3 に追加してください)。後のステップで使用するために、この出力を書き留めます。

     1. [セルフマネージド Amazon Linux ノードを作成する](launch-workers.md) の手順に従ってノードグループをデプロイします。
**注記**  
本番クラスター内のノードで、非常に大量の Pod をサポートさせる場合には、「」のスクリプトを再度実行します。また、このコマンドには `--cni-prefix-delegation-enabled` オプションを追加します。例えば、`m5.large` インスタンスタイプの場合は `110` が返されます。この機能を有効化する方法については「[プレフィックスを使用して Amazon EKS ノードに割り当てる IP アドレスを増やす](cni-increase-ip-addresses.md)」を参照してください。この機能はカスタムネットワーキングで使用できます。

1. ノードグループの作成には数分かかります。次のコマンドを使用すると、マネージド型のノードグループ作成のステータスを確認できます。

   ```
   aws eks describe-nodegroup --cluster-name my-custom-networking-cluster --nodegroup-name my-nodegroup --query nodegroup.status --output text
   ```

   出力が「`ACTIVE`」を返すまで、次のステップに進まないでください。

1.  このチュートリアルではこのステップをスキップできます。

   本番向けのクラスターにおいて、`ENIConfigs` の名前を、それが使用されているアベイラビリティーゾーンと同じにしなかった場合にはノードに対し、そのノードで使用すべき `ENIConfig` の名前をアノテーションします。各アベイラビリティーゾーンにサブネットが 1 つしかなく、`ENIConfigs` にアベイラビリティーゾーンと同じ名前を付けている場合にはこのステップは必要ありません。[前のステップ](#custom-networking-automatically-apply-eniconfig)でその設定を有効にしている場合、Amazon VPC CNI plugin for Kubernetes が適切な `ENIConfig` をノードに対し自動的に関連付けるためです。

   1. クラスター内のノードのリストを取得します。

      ```
      kubectl get nodes
      ```

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

      ```
      NAME                                          STATUS   ROLES    AGE     VERSION
      ip-192-168-0-126.us-west-2.compute.internal   Ready    <none>   8m49s   v1.22.9-eks-810597c
      ip-192-168-0-92.us-west-2.compute.internal    Ready    <none>   8m34s   v1.22.9-eks-810597c
      ```

   1. 各ノードが属するアベイラビリティーゾーンを決定します。前の出力に基づいて IP アドレスを置き換えて、前のステップで返されたノードごとに次のコマンドを実行します。

      ```
      aws ec2 describe-instances --filters Name=network-interface.private-dns-name,Values=ip-192-168-0-126.us-west-2.compute.internal \
      --query 'Reservations[].Instances[].{AvailabilityZone: Placement.AvailabilityZone, SubnetId: SubnetId}'
      ```

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

      ```
      [
          {
              "AvailabilityZone": "us-west-2d",
              "SubnetId": "subnet-Example5"
          }
      ]
      ```

   1. 各ノードを、サブネット ID とアベイラビリティーゾーンのために作成した `ENIConfig` でアノテーションします。各ノードのアノテーションに使用できる `ENIConfig` は 1 つだけです。ただし、複数のノードに対し同じ `ENIConfig` でアノテーションすることは可能です。値の例 は実際に使用する値に置き換えます。

      ```
      kubectl annotate node ip-192-168-0-126.us-west-2.compute.internal k8s.amazonaws.com/eniConfig=EniConfigName1
      kubectl annotate node ip-192-168-0-92.us-west-2.compute.internal k8s.amazonaws.com/eniConfig=EniConfigName2
      ```

1.  カスタムネットワーキング機能の使用に切り替える前に、Pod を実行している本稼働クラスターにノードがあった場合は、以下のタスクを完了してください。

   1. カスタムネットワーク機能を使用しているノードが、使用可能であることを確認します。

   1. ノードを遮断およびドレインして、Pod をスムーズにシャットダウンします。詳細については、Kubernetes ドキュメントの「[Safely Drain a Node](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)」(ノードを安全にドレインする) を参照してください。

   1. ノードを終了します。ノードが既存のマネージド型ノードグループ内にある場合はそのノードグループを削除できます。以下のコマンドを実行してください。

      ```
      aws eks delete-nodegroup --cluster-name my-custom-networking-cluster --nodegroup-name my-nodegroup
      ```

   カスタムネットワーク機能は`k8s.amazonaws.com/eniConfig` ラベルで登録されている新しいノードでのみ使用されます。

1. Pod に、前の手順で作成したサブネットの 1 つに関連付けられた CIDR ブロックから、IP アドレスが割り当てられていることを確認します。

   ```
   kubectl get pods -A -o wide
   ```

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

   ```
   NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE     IP              NODE                                          NOMINATED NODE   READINESS GATES
   kube-system   aws-node-2rkn4             1/1     Running   0          7m19s   192.168.0.92    ip-192-168-0-92.us-west-2.compute.internal    <none>           <none>
   kube-system   aws-node-k96wp             1/1     Running   0          7m15s   192.168.0.126   ip-192-168-0-126.us-west-2.compute.internal   <none>           <none>
   kube-system   coredns-657694c6f4-smcgr   1/1     Running   0          56m     192.168.1.23    ip-192-168-0-92.us-west-2.compute.internal    <none>           <none>
   kube-system   coredns-657694c6f4-stwv9   1/1     Running   0          56m     192.168.1.28    ip-192-168-0-92.us-west-2.compute.internal    <none>           <none>
   kube-system   kube-proxy-jgshq           1/1     Running   0          7m19s   192.168.0.92    ip-192-168-0-92.us-west-2.compute.internal    <none>           <none>
   kube-system   kube-proxy-wx9vk           1/1     Running   0          7m15s   192.168.0.126   ip-192-168-0-126.us-west-2.compute.internal   <none>           <none>
   ```

   VPC に追加した `192.168.1.0` CIDR ブロックからの IP アドレスが、coredns Pod に割り当てられていることが確認できます。カスタムネットワーキングを使用していない場合はここに `192.168.0.0` CIDR ブロックからのアドレスが割り当てられています。この CIDR ブロックが、元々 VPC に関連付けられている唯一のブロックであるためです。

   Pod の `spec` が `hostNetwork=true` を含む場合には、ノードのプライマリ IP アドレスが割り当てられます。追加したサブネットのアドレスは割り当てられません。デフォルトではこの値は `false` に設定されます。クラスターで実行される `kube-proxy` および Amazon VPC CNI plugin for Kubernetes (`aws-node`) の Pod に対して、この値は `true` に設定されます。これが、`kube-proxy` とプラグインの `aws-node` の Pod に、前の出力にある 192.168.1.x アドレスが割り当てられない理由です。Pod の `hostNetwork` 設定の詳細については、Kubernetes API リファレンスの「[PodSpec v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#podspec-v1-core)」を参照してください。

## ステップ 5: チュートリアルでのリソースを削除する
<a name="custom-network-delete-resources"></a>

このチュートリアル完了後は作成したリソースを削除することをお勧めします。その後、ここでのステップを調整して、本番向けクラスターのカスタムネットワーキングを有効化することができます。

1. 作成したノードグループが完全にテスト向けである場合はそれを削除してください。

   ```
   aws eks delete-nodegroup --cluster-name my-custom-networking-cluster --nodegroup-name my-nodegroup
   ```

1. AWS CLI から、クラスターが削除済みだと出力された場合でも、実際にはその削除プロセスが完了していない場合があります。削除のプロセスには数分かかります。次のコマンドを実行して、処理の完了を確認します。

   ```
   aws eks describe-nodegroup --cluster-name my-custom-networking-cluster --nodegroup-name my-nodegroup --query nodegroup.status --output text
   ```

   次のように出力されるまで、次に進まないでください。

   ```
   An error occurred (ResourceNotFoundException) when calling the DescribeNodegroup operation: No node group found for name: my-nodegroup.
   ```

1. 作成したノードグループが完全にテスト向けである場合はノードの IAM ロールを削除します。

   1. ロールからポリシーをデタッチします。

      ```
      aws iam detach-role-policy --role-name myCustomNetworkingNodeRole --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
      aws iam detach-role-policy --role-name myCustomNetworkingNodeRole --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
      aws iam detach-role-policy --role-name myCustomNetworkingNodeRole --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
      ```

   1. ロールを削除します。

      ```
      aws iam delete-role --role-name myCustomNetworkingNodeRole
      ```

1. クラスターを削除します。

   ```
   aws eks delete-cluster --name my-custom-networking-cluster
   ```

   以下のコマンドを使用して、クラスターが削除されたことを確認します。

   ```
   aws eks describe-cluster --name my-custom-networking-cluster --query cluster.status --output text
   ```

   次のような出力が返された場合はクラスターが正常に削除されています。

   ```
   An error occurred (ResourceNotFoundException) when calling the DescribeCluster operation: No cluster found for name: my-custom-networking-cluster.
   ```

1. クラスターの IAM ロールを削除します。

   1. ロールからポリシーをデタッチします。

      ```
      aws iam detach-role-policy --role-name myCustomNetworkingAmazonEKSClusterRole --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
      ```

   1. ロールを削除します。

      ```
      aws iam delete-role --role-name myCustomNetworkingAmazonEKSClusterRole
      ```

1. 前のステップで作成したサブネットを削除します。

   ```
   aws ec2 delete-subnet --subnet-id $new_subnet_id_1
   aws ec2 delete-subnet --subnet-id $new_subnet_id_2
   ```

1. 作成した VPC を削除します。

   ```
   aws cloudformation delete-stack --stack-name my-eks-custom-networking-vpc
   ```