

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

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

# アプリケーションを新しいノードグループに移行する
<a name="migrate-stack"></a>

このトピックは、新しいノードグループを作成し、既存のアプリケーションを新しいグループに適切に移行し、クラスターから古いノードグループを削除する方法について説明します。新しいノードグループに移行するには、`eksctl` または AWS マネジメントコンソール を使用します。
+  [`eksctl`](#eksctl_migrate_apps) 
+  [AWS マネジメントコンソール および AWS CLI](#console_migrate_apps) 

## `eksctl`
<a name="eksctl_migrate_apps"></a>

 **`eksctl` を使用してアプリケーションを新しいノードグループに移行する** 

eksctl を移行に使用する方法の詳細については、`eksctl` ドキュメントの「[管理対象外のノードグループ](https://eksctl.io/usage/nodegroup-unmanaged/)」を参照してください。

この手順には、`eksctl` バージョン `0.215.0` 以降が必要です。お使いのバージョンは、以下のコマンドを使用して確認できます。

```
eksctl version
```

`eksctl` のインストールまたはアップグレードの手順については、`eksctl` ドキュメントの「[インストール](https://eksctl.io/installation)」を参照してください。

**注記**  
この手順は、`eksctl` で作成されたクラスターとノードグループに対してのみ機能します。

1. *my-cluster* をクラスター名に置き換えて、既存のノードグループの名前を取得します。

   ```
   eksctl get nodegroups --cluster=my-cluster
   ```

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

   ```
   CLUSTER      NODEGROUP          CREATED               MIN SIZE      MAX SIZE     DESIRED CAPACITY     INSTANCE TYPE     IMAGE ID
   default      standard-nodes   2019-05-01T22:26:58Z  1             4            3                    t3.medium         ami-05a71d034119ffc12
   ```

1. 次のコマンドを使用して、`eksctl` で新しいノードグループを起動します。コマンドのすべての*サンプル値*を独自の値に置き換えます。バージョン番号をお使いのコントロールプレーンの Kubernetes バージョンよりも新しいものにすることはできません。また、コントロールプレーンの Kubernetes バージョンより 3 つ以上前のマイナーなバージョンにすることもできません。コントロールプレーンと同じバージョンを使用することをお勧めします。

   次の条件が true の場合、IMDS への Pod アクセスをブロックすることをお勧めします。
   + IAM ロールをすべての Kubernetes サービスアカウントに割り当てることによって、必要最小限のアクセス許可のみを Pod に付与しようとしている。
   + クラスター内の Pod が、現在の AWS リージョンの取得など、その他の理由で Amazon EC2 インスタンスメタデータサービス (IMDS) へのアクセスを必要としていない。

     詳細については「[ワーカーノードに割り当てられたインスタンスプロファイルへのアクセスを制限する](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)」を参照してください。

     Pod から IMDS へのアクセスをブロックするには、次のコマンドに `--disable-pod-imds` オプションを追加します。
**注記**  
使用可能なフラグとその説明については、「https://eksctl.io/」を参照してください。

   ```
   eksctl create nodegroup \
     --cluster my-cluster \
     --version 1.35 \
     --name standard-nodes-new \
     --node-type t3.medium \
     --nodes 3 \
     --nodes-min 1 \
     --nodes-max 4 \
     --managed=false
   ```

1. 前のコマンドが完了したら、次のコマンドを使用して、すべてのノードが `Ready` 状態になったことを確認します。

   ```
   kubectl get nodes
   ```

1. 次のコマンドを使用して、元のノードグループを削除します。このコマンドで、すべての*サンプル値*を自分のクラスター名とノードグループ名に置き換えます。

   ```
   eksctl delete nodegroup --cluster my-cluster --name standard-nodes-old
   ```

## AWS マネジメントコンソール および AWS CLI
<a name="console_migrate_apps"></a>

 **AWS マネジメントコンソール と AWS CLI を使用してアプリケーションを新しいノードグループに移行する** 

1. 新しいノードグループを起動するには、「[セルフマネージド Amazon Linux ノードを作成する](launch-workers.md)」で説明されている手順に従います。

1. スタックの作成が完了したら、コンソールで選択し、**[出力]** を選択してください。

1.  作成されたノードグループの **NodeInstanceRole** を記録します。Amazon EKS ノードをクラスターに追加するには、これが必要です。
**注記**  
追加の IAM ポリシーを古いノードグループの IAM ロールにアタッチした場合は、この同じポリシーを新しいノードグループの IAM ロールにアタッチして、新しいグループでその機能を管理します。これは、たとえば、Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) のアクセス許可を追加した場合に適用されます。

1. 相互通信できるように、両方のノードグループのセキュリティグループを更新します。詳細については、「[クラスターの Amazon EKS セキュリティグループ要件を表示する](sec-group-reqs.md)」を参照してください。

   1. 両方のノードグループのセキュリティグループ ID を記録します。これは、AWS CloudFormation スタックからの出力に、**NodeSecurityGroup** の値として表示されます。

      次の AWS CLI コマンドを使用して、スタック名からセキュリティグループ ID を取得します。これらのコマンドで、`oldNodes` は、古いノードスタックの AWS CloudFormation スタック名、`newNodes` は、移行先のスタックの名前です。各*サンプル値*は独自の値に置き換えます。

      ```
      oldNodes="old_node_CFN_stack_name"
      newNodes="new_node_CFN_stack_name"
      
      oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      ```

   1. 互いにトラフィックを受け入れるように、各ノードのセキュリティグループに進入ルールを追加します。

      以下の AWS CLI コマンドでは、他のセキュリティグループからのすべてのプロトコルのトラフィックをすべて許可するインバウンドルールを各セキュリティグループに追加します。この設定により、ワークロードを新しいグループに移行している際に、各ノードグループ内の Pod が相互に通信できるようになります。

      ```
      aws ec2 authorize-security-group-ingress --group-id $oldSecGroup \
      --source-group $newSecGroup --protocol -1
      aws ec2 authorize-security-group-ingress --group-id $newSecGroup \
      --source-group $oldSecGroup --protocol -1
      ```

1. `aws-auth` configmap を編集して、新しいノードインスタンスロールを RBAC にマッピングします。

   ```
   kubectl edit configmap -n kube-system aws-auth
   ```

   新しいノードグループの新しい `mapRoles` エントリを追加します。

   ```
   apiVersion: v1
   data:
     mapRoles: |
       - rolearn: ARN of instance role (not instance profile)
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes>
       - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-U11V27W93CX5
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes
   ```

   *インスタンスロールの ARN (インスタンスプロファイルではない)* スニペットを、[前の手順](#node-instance-role-step)で記録した **NodeInstanceRole** の値に置き換えます。次に、更新された configmap を適用するには、ファイルを保存して閉じます。

1. ノードのステータスを監視し、新しいノードがクラスターに結合され、`Ready` ステータスになるまで待機します。

   ```
   kubectl get nodes --watch
   ```

1. (オプション) [Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) を使用している場合は、スケーリングアクションの競合を回避するために、デプロイをゼロ (0) レプリカにスケールダウンします。

   ```
   kubectl scale deployments/cluster-autoscaler --replicas=0 -n kube-system
   ```

1. 以下のコマンドを使用して、`NoSchedule` で削除する各ノードをテイントに設定します。その目的は、ノードを置き換えたときにそのノードで新しい Pod がスケジュールまたは再スケジュールされないようにすることです。詳細については、Kubernetes ドキュメントの「[テイントと容認](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)」を参照してください。

   ```
   kubectl taint nodes node_name key=value:NoSchedule
   ```

   ノードを新しい Kubernetes バージョンにアップグレードする場合は、次のコードスニペットを使用して、特定の Kubernetes バージョン (この場合は `1.33`) のすべてのノードを識別してテイントに設定できます。バージョン番号をお使いのコントロールプレーンの Kubernetes バージョンよりも新しいものにすることはできません。また、コントロールプレーンの Kubernetes バージョンより 3 つ以上前のマイナーなバージョンにすることもできません。コントロールプレーンと同じバージョンを使用することをお勧めします。

   ```
   K8S_VERSION=1.33
   nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}")
   for node in ${nodes[@]}
   do
       echo "Tainting $node"
       kubectl taint nodes $node key=value:NoSchedule
   done
   ```

1.  クラスターの DNS プロバイダーを決定します。

   ```
   kubectl get deployments -l k8s-app=kube-dns -n kube-system
   ```

   出力例は次のとおりです。このクラスターでは、DNS 解決に CoreDNS を使用していますが、クラスターからは `kube-dns` が返される場合もあります。

   ```
   NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
   coredns   1         1         1            1           31m
   ```

1. 現在のデプロイメントで実行しているレプリカが 2 つ未満の場合は、そのデプロイメントを 2 つのレプリカにスケールアウトします。前のコマンドの出力が kubedns を返していた場合は、*coredns* を `kubedns` に置き換えます。

   ```
   kubectl scale deployments/coredns --replicas=2 -n kube-system
   ```

1. 次のコマンドを使用して、クラスターから削除する各ノードをドレーンします。

   ```
   kubectl drain node_name --ignore-daemonsets --delete-local-data
   ```

   ノードを新しい Kubernetes バージョンにアップグレードする場合は、次のコードスニペットを使用して、特定の Kubernetes バージョン (この場合は *1.33*) のすべてのノードを識別してドレインします。

   ```
   K8S_VERSION=1.33
   nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}")
   for node in ${nodes[@]}
   do
       echo "Draining $node"
       kubectl drain $node --ignore-daemonsets --delete-local-data
   done
   ```

1. 古いノードのドレーンが完了したら、以前承認したセキュリティグループのインバウンドルールを取り消します。次に、AWS CloudFormation スタックを削除してインスタンスを終了してください。
**注記**  
さらに IAM ポリシーを古いノードグループの IAM ロールにアタッチした場合 ([Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) に対するアクセス許可を追加する場合など) は、ロールからその追加ポリシーをデタッチしてから、AWS CloudFormation スタックを削除できます。

   1. 先ほどノードのセキュリティグループ用に作成したインバウンドルールを取り消します。これらのコマンドで、`oldNodes` は、古いノードスタックの AWS CloudFormation スタック名、`newNodes` は、移行先のスタックの名前です。

      ```
      oldNodes="old_node_CFN_stack_name"
      newNodes="new_node_CFN_stack_name"
      
      oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      aws ec2 revoke-security-group-ingress --group-id $oldSecGroup \
      --source-group $newSecGroup --protocol -1
      aws ec2 revoke-security-group-ingress --group-id $newSecGroup \
      --source-group $oldSecGroup --protocol -1
      ```

   1. [AWS CloudFormation コンソール](https://console.aws.amazon.com/cloudformation/)を開きます。

   1. 古いノードスタックを選択します。

   1. **[削除]** を選択します。

   1. **[スタックの削除]** 確認ダイアログボックスで、**[スタックを削除]** をクリックします。

1. `aws-auth` configmap を編集して、RBAC から古いノードインスタンスロールを削除します。

   ```
   kubectl edit configmap -n kube-system aws-auth
   ```

   古いノードグループの `mapRoles` エントリを削除します。

   ```
   apiVersion: v1
   data:
     mapRoles: |
       - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-W70725MZQFF8
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes
       - rolearn: arn:aws:iam::111122223333:role/nodes-1-15-NodeInstanceRole-U11V27W93CX5
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes>
   ```

   更新された configmap を適用するには、ファイルを保存して閉じます。

1. (オプション) Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) を使用している場合は、デプロイのスケーリングを 1 レプリカに戻します。
**注記**  
必要に応じて、新しい Auto Scaling グループにタグ (`k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster` など) を付け、新しくタグ付けした Auto Scaling グループを参照するように、Cluster Autoscaler デプロイのコマンドを更新する必要があります。詳細については、「[AWS の Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/cluster-autoscaler-release-1.3/cluster-autoscaler/cloudprovider/aws)」を参照してください。

   ```
   kubectl scale deployments/cluster-autoscaler --replicas=1 -n kube-system
   ```

1. (オプション) 最新バージョンの [Amazon VPC CNI Plugin for Kubernetes](https://github.com/aws/amazon-vpc-cni-k8s) を使用していることを確認します。サポートされている最新のインスタンスタイプを利用するにはCNI のバージョンを更新することが必要になる場合があります。詳細については、「[Amazon VPC CNI を使用して Pod に IP を割り当てる](managing-vpc-cni.md)」を参照してください。

1. クラスターが DNS 解決 ([[migrate-determine-dns-step]](#migrate-determine-dns-step) を参照) に `kube-dns` を使用している場合は、`kube-dns` デプロイを 1 レプリカにスケールインします。

   ```
   kubectl scale deployments/kube-dns --replicas=1 -n kube-system
   ```