【初心者向け】AssumeRole利用時のEKSクラスター作成について

この記事は [Amazon EKS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/amazon-eks) の16日目の記事です。
公開が遅くなってしまい申し訳ありません

AWSの利用が進むにつれ、複数のAWSアカウントを利用することが多くなります。
開発、STG、本番と環境を分けるために利用したり、「課金管理を行いたい」、「プロジェクトが違う」など理由は様々ですが、複数のAWSアカウントごとにIAMユーザを発行するとアカウント管理が煩雑になってしまうため、1つのAWSアカウントからAssume Roleを利用して各AWSアカウントにアクセスする方法を採用されている方も多くいるかと思います。

今回は、このような環境で、Assume Roleを利用しながら、EKSクラスタを作成し、そこにアクセスするまでを整理したいと思います。
Kubernetesは使い慣れているが、AWSは不慣れ、という方や、　複数のAWSアカウント利用に慣れていない方の助けになれば幸いです。

なお、今回は例として下記のようなアカウント構成を想定します。

![Qiita_assume_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54228/6ae9cb2e-0c89-a0ee-7184-88a1c25869bb.png)

利用者の方は管理用アカウントにIAM Userとしてログインし、作業対象アカウントにAssume Roleを利用してアクセスして実際の作業を行います。

Assume Roleを利用した他アカウントへのアクセスについては下記のdocumentもご覧ください。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html

EKSの構築については[こちら](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started.html)で紹介されている[eksctlの開始方法](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html) と[コンソールの開始方法](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-console.html) それぞれのシナリオをAssume Roleで実施する方法について記載します。

## 「eksctlの開始方法」 の場合

eksctlを利用する場合、[eksctlの開始方法](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html) の [前提条件](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html#eksctl-prereqs) でも説明されている通り、何も指定しない場合、AWS CLIのdefault プロファイルの認証情報が利用されます。
今回想定している構成の場合、利用者の方は管理用アカウントのIAM Userのアクセスキー/シークレットアクセスキーをお持ちのはずなので、このまま[こちら](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html#eksctl-create-cluster)の手順を実行すると、管理用アカウント上にEKS クラスタが作成されてしまいます。

##### 管理用アカウント上にEKS クラスタが作成されてしまう
![Qiita_assume_role_not_assume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54228/0ab1307b-8965-9f4b-b11b-26d83b1b9815.png)

本来は、下記のように作業対象アカウントにEKS クラスタを作成することが目的のはずです。

##### 本来やりたいこと→作業対象アカウントにEKS クラスタを作成したい
![Qiita_assume_role_assume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54228/68549f62-0363-e567-52e3-225238c0ceba.png)

### 手順
上記は下記の手順を実施することで実現できます。

1. CLI設定ファイルで作業対象アカウントのRoleを利用するように設定する
2. ドキュメントの手順に沿ってeksctlを利用する際に、1.で設定したプロファイルを指定する

#### 1. CLI設定ファイルで作業対象アカウントのRoleを利用するように設定する
~/.aws/config (Linux または macOS の場合) または C:\Users\USERNAME\.aws\config (Windows の場合)に下記の設定を追加します。
(defaultのプロファイルは管理用アカウントのIAM Userが東京リージョンで jsonをoutputとして設定されている前提とします)

```bash:~/.aws/config
## defaultのprofile
[default]
region = ap-northeast-1
output = json

## 下記の設定を追加
[profile assume]
role_arn = <作業対象アカウントのroleのarn>
source_profile = default
````

CLIでIAM Roleを利用するための設定の詳細は下記のドキュメントもご覧ください。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html

正しく設定できたかを確認するために、下記のコマンドを実行してください。

```bash

aws sts get-caller-identity --p assume
```

レスポンスとして、下記のような結果が帰って来れば成功です。

```
{
    "UserId": "XXXXXXXXXXXXXXXXXXXX:botocore-session-1111111111",
    "Account": "<管理対象のAWSアカウントID>",
    "Arn": "arn:aws:sts::<管理対象のAWSアカウントID>:assumed-role/<Role名>/botocore-session-1111111111"
}
```

#### 2. ドキュメントの手順に沿ってeksctlを利用する際に、1.で設定したプロファイルを指定する
作業対象アカウントのRoleを利用するAWS CLIのプロファイルの設定はできたので、次はeksctlを実行する際に上記で設定したプロファイルを利用するによう指定します。
eksctl でクラスタを作成する際には、 `-p` もしくは `--profile` flagを利用することで利用するプロファイルを指定できます。

[こちら](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html#eksctl-create-cluster)の手順で AWS Fargate-only clusterを作成するコマンドを例とすると、下記のようにflagを追加します。

```bash
eksctl create cluster \
--name prod \
--version 1.14 \
--region us-east-2 \
--fargate \
-p assume ##追加するflag
```

#### 利用するプロファイルを指定する環境変数

なお、毎回 `-p`のflagをつけるのが面倒な場合、下記のようにデフォルトで利用するプロファイルを環境変数で指定することができます。これを設定した場合、AWS CLIやeksctlでプロファイルを指定する必要はありません。

```bash:環境変数によるプロファイルの指定
export AWS_PROFILE=assume
```

設定後、eksctlでプロファイルを指定しないでも、先ほど作成したクラスタを参照できることを下記のコマンドで確認できます。

```bash
eksctl get cluster
```
※環境変数でプロファイルを指定して`eksctl create cluster` でEKS クラスタを作成した場合、その後のkubectlでのkubernetesの操作時にも `AWS_PROFILE` の環境変数が設定されている必要があリます。(設定ファイルを書き換えることで変更できますがここでは割愛)

## 「コンソールの開始方法」の場合
マネジメントコンソールから作成する場合、マネジメントコンソールからAssume Roleで作業対象アカウントにログインして、[ステップ 1: Amazon EKS クラスターを作成する](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-console.html#eks-create-cluster)の手順を実行します。ここはドキュメントの通り進めれば問題ありません。

ここでは[ステップ 2: kubeconfig ファイルを作成する](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-console.html#eks-configure-kubectl)について、整理します。ステップ2では以下の2つのkubeconfig ファイルの作成方法が紹介されています。

- AWS CLIを利用する方法
- 手作業で設定する方法

#### AWS CLIを利用する方法
AWS CLIを利用する方法の場合、[「eksctlの開始方法」 の場合](#「eksctlの開始方法」 の場合)と同じように、AWS CLIがAssume Roleを利用して作業対象アカウントへアクセスするようにします。
[こちら](#1. CLI設定ファイルで作業対象アカウントのRoleを利用するように設定する)の手順でAWS CLIの設定を完了後、AWS CLI の update-kubeconfig コマンド実行時にAssume Roleを利用するプロファイルを使用するようにします。前述の通り、`--p` optionでプロファイルを指定するか、環境変数で利用するプロファイルを指定することができます。

```bash:optionでプロファイルを指定する場合
aws eks --region <region> update-kubeconfig --name <cluster_name> --p assume
```

```bash:環境変数でプロファイルを指定する場合
export AWS_PROFILE=assume
aws eks --region <region> update-kubeconfig --name <cluster_name> ## --pの指定は不要になります
```

#### 手作業で設定する方法
[こちら](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-kubeconfig.html) の「kubeconfig ファイルを手動で作成するには」で紹介されている方法の場合、紹介されているkubeconfigのコードブロックでコメントアウトされている設定を利用することで実現できます。ここでは`aws eks get-token `を利用する場合のコードブロックを例にご紹介します。

```yaml
apiVersion: v1
clusters:
- cluster:
    server: <endpoint-url>
    certificate-authority-data: <base64-encoded-ca-cert>
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: aws
  name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      command: aws
      args:
        - "eks"
        - "get-token"
        - "--cluster-name"
        - "<cluster-name>"
        - "--role"
        - "<作業対象アカウントのRoleのarnを記載>"
      env:
        - name: AWS_PROFILE
          value: "<上記のroleにAssume Roleできるプロファイルを指定>"
```

users.user.argsの `--role` に作業対象アカウントのRoleのarnを設定します。
また、users.user.envに `AWS_PROFILE`を設定することで、利用するプロファイルを指定することもできますので、defaultのプロファイルが作業対象アカウントのRoleにアクセスできないときや、[「eksctlの開始方法」 の場合](#「eksctlの開始方法」 の場合)の手順でAssumr Roleするプロファイルを事前に設定した場合は、こちらを指定することで、プロファイルを切り替えて、EKSのクラスタにアクセスできます。
AWS CLIの設定ごとの各設定項目については下記にまとめます。


| AWS CLIの設定       |users.user.argsの `--role`  |users.user.envの`AWS_PROFILE`        |
|-----------------|:------------------:|:------------------:|
| defaultのプロファイルがAssume Role可能             |   必要 |        不要        |
| defaultのプロファイルがAssume Role不可            | 必要 | Assume Roleできるプロファイルを指定する       |
| `~/.aws/config` でAssume Roleするプロファイルを設定している  |不要 | 設定したプロファイルを指定   |



## 最後に

AWS CLIやEKSを使い慣れている人には当たり前のことかと思いますが、AWSの経験がまだ少ない方で、EKSの利用を検討されている方がスムーズに検証を開始する一助になるかと思いまとめてみました。

内容については動作検証もしておりますが間違いなどお気付きの点ありましたらぜひ教えてください。
また、もっと簡単にやれる方法あるよ!などありましたらぜひご指摘ください。

なお、近しいお話として、MFAを利用した認証を利用したい場合は下記もご参照ください。
https://github.com/toricls/eks-kubectl-mfa-helper

以上です。