【初心者】AWS Wavelengthを使ってみる #2 (Amazon EKSの利用)

# 1.目的
- AWS Wavelength 上で動作するサービスとしてAmazon EKSが挙げられているが、どのように設定していくのか、また、リージョンでEKSを使う場合と比較して、どのような違いがあるのかを確認する。
- AWS Wavelength の概要については以前の記事「[【初心者】AWS Wavelengthを使ってみる](https://qiita.com/mksamba/items/9a45a666ae938053fa72)」を参照のこと。

# 2.やったこと
以下の内容を実施した。※あくまで「やってみて動きました」という内容で、ベストプラクティスかどうかは微妙。

- 東京リージョンにVPCを作成し、パブリックサブネット及び Wavelength Zoneのサブネットを作成する。
- 東京リージョンにEKSクラスター(コントロールプレーン)を作成する。
- Wavelength Zone に EKSワーカーノードとなるEC2インスタンスを作成する。
- EKSクラスターとEKSワーカーノードが通信できることを確認する。
- EKSワーカーノード上にnginxコンテナを作成し、外部(キャリア網)からアクセスできることを確認する。

# 3.構成図

![eks-wl構成図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/ccb8570c-72e0-39f2-5fc0-874ec3988acf.png)


# 4.予習
- 公式ドキュメント「[Wavelength considerations and quotas](https://docs.aws.amazon.com/ja_jp/wavelength/latest/developerguide/wavelength-quotas.html)」にWavelength上でEKSを利用する場合の注意点の記載がある。それを参考に環境を構築する。

- 以下は2020/2時点の上記サイトでのEKSに関する注意事項の内容。


>Amazon Elastic Kubernetes Service considerations
>Take the following information into consideration when you run an Amazon EKS cluster:
> - You must run Kubernetes 1.17 or later.
> - When you create your Amazon EKS cluster, you must select an Availability Zone in the VPC, and not a Wavelength Zone.
> - When you create your Amazon EKS cluster for private subnets only, you need to add VPC endpoints for Amazon ECR and Amazon Simple Storage Service. For more information, see Amazon VPC considerations.
> - To create node groups in Wavelength Zones for your Amazon EKS cluster, see Launching self-managed Amazon Linux 2 nodes in the Amazon EKS User Guide.
> - To apply the aws-auth ConfigMap to your Amazon EKS cluster, see Managing users or IAM roles for your cluster in the Amazon EKS User Guide.

- 記載事項に対して結果的には以下のような対応とした。
    - Kubernetesのバージョンは1.18(執筆時点の最新)とした。
    - EKSクラスターを作成する時、東京リージョンのサブネットを指定した。
    - パブリックサブネットも存在しているVPCを作ったが、結果としてVPCエンドポイントも作成した。（作成しないと動作しなかった）
    - Wavelength Zoneにノードグループを作成する際、「self-managed Amazon Linux nodes」の手順を使用した。
    - aws-auth ConfigMapの手順を実施した。

- 元々、プライベートなVPC環境にEKSを構築する場合の手順(VPCエンドポイントの作成など)が準備されており、基本的にはそれらの手順を実行すればよいと理解した。



# 5. 作業手順

## 5.1 VPCの作成
- 公式ドキュメント[「Getting started with Amazon EKS – AWS Management Console and AWS CLI 」](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html)に従い、EKSを動かす用のVPCを作成する。
- 2021/2時点でのドキュメントでは、CloudFormationのスタックをCLIから実行して作成しているが、今回はマネージメントコンソールのGUIから実行し、CIDRなどのパラメータを変更する。
- CloudFormationのスタックの作成画面にて、AWSが提供するCloudFormationテンプレートを指定する。

![11a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/4e8e0bcd-7ab4-9f27-f65a-b22aa16131bf.png)

- スタック名をmksamba-eks-qiita とし、CIDRを分かりやすい体系(10.0.0.0/16ベース)に変更する。他の値は特に変更せずにスタックを生成する。

![12a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/036e4236-e10c-2bdd-1871-a9f54f8ad965.png)

- スタックの作成が成功すると、VPC、サブネット(Public 2個、Private 2個)、InternetGateway、NatGateway(2個)、EKS用のセキュリティグループなどが作成される。

## 5.2 EKSクラスターロールの作成
- 引き続き公式ドキュメント[「Getting started with Amazon EKS – AWS Management Console and AWS CLI 」](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html)に従い、EKSクラスター用のロールを作成する。
- 今回は「mksamba-eks-cluster-role」という名前でロールを作成している。ポイントとしては以下2点。
    - アクセス権限としてポリシー「AmazonEKSClusterPolicy」がアタッチされていること。「AmazonEKSClusterPolicy」には、EC2インスタンスやELBを操作する権限が含まれる。
    - 信頼されたエンティティとして、「eks.amazonaws.com」が登録されていること。

## 5.3 EKSクラスターの作成
- 引き続き公式ドキュメント[「Getting started with Amazon EKS – AWS Management Console and AWS CLI 」](https://docs.aws.amazon.com/eks/latest/userguide/getting-started-console.html)に従い、EKSクラスターを作成する。
- 「EKS > クラスタ」から、クラスターの作成を行う。
- クラスタ名「mksamba-eks-qiita」を設定し、クラスターサービスロールとして先の手順で作成したロール「mksamba-eks-cluster-role」を指定する。

![13a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/e09b3df4-8687-bb60-0237-b9b77560b441.png)

- EKSを使用するVPCとして、先の手順で作成したVPC「mksamba-eks-qiita-VPC」を指定し、サブネットもそのまま4つ選択する。今回はクラスターエンドポイントアクセスを「プライベート」にする。

![14a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/89131c00-cd91-be4c-1304-4db77d48a9a2.png)

- 内容を確認しEKSクラスタの作成を行う。

![16a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/247a5f3d-b954-a4f3-b13c-aeb159ea395f.png)

- クラスターが無事作成され、エンドポイントがプライベートになっていることを確認する。

![17a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/2dd9ee3a-6501-84ac-fa76-3fa8230c2810.png)

## 5.4 作業用インスタンスの作成
- 作成したVPCのPublic Subnetに、作業用のインスタンス(踏み台＆kubectl実行用)を作成し、aws cli(v2)、kubectl を入れておく。手順は以下(公式ドキュメント)を参照。
    - [Linux での AWS CLI バージョン 2 のインストール、更新、アンインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html)
    - [kubectlのインストール](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/install-kubectl.html)

```
[ec2-user@ip-10-0-0-130 ~]$ aws --version
aws-cli/2.1.27 Python/3.7.3 Linux/4.14.214-160.339.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off
[ec2-user@ip-10-0-0-130 ~]$ kubectl version --short --client
Client Version: v1.18.9-eks-d1db3c
```

- aws eks update-kubeconfig コマンドにより、今回作成したEKSクラスターの操作ができるようにする。

```
[ec2-user@ip-10-0-0-130 ~]$ aws eks update-kubeconfig --region ap-northeast-1 --name mksamba-eks-qiita
Added new context arn:aws:eks:ap-northeast-1:XXXXXXXXXXXX:cluster/mksamba-eks-qiita to /home/ec2-user/.kube/config
[ec2-user@ip-10-0-0-130 ~]$ kubectl get svc
^C　※この時点では接続不可
```

- EKSクラスターとの通信ができない状態のため、EKSクラスタとの接続用のセキュリティグループを変更し、VPC内からの接続を許可する(Inbound 10.0.0.0/16 に対して許可ルールの追加)。その結果、kubectl get svc ができることを確認する。

```
[ec2-user@ip-10-0-0-130 ~]$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP   2d23h
```

- AZごとにEKSクラスターと接続するためのエンドポイントが存在していることを確認する。(エンドポイント名はEKSクラスターの管理画面で確認可能)

```
[ec2-user@ip-10-0-0-130 ~]$ nslookup XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.yl4.ap-northeast-1.eks.amazonaws.com
Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.yl4.ap-northeast-1.eks.amazonaws.com
Address: 10.0.2.178
Name:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.yl4.ap-northeast-1.eks.amazonaws.com
Address: 10.0.1.61
```

## 5.5 Wavelength関連リソースの設定

- 5.1の手順で作成した本検証用のVPCに対し、Wavelength関連のリソースの追加作成を行う。
- 東京Wavelength Zone (ap-northeast-1-wl1-nrt-wlz-1)にサブネット10.0.10.0/24を作成する。

![20a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/309049aa-e04d-4fba-6950-cfb45bef2bf6.png)

- キャリアゲートウェイの作成、キャリアゲートウェイへのルートを含むルートテーブルの作成、サブネットへのルートテーブルの関連付けを行う。

![21a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/56f73981-ad05-1406-ea99-d0faeb3f8089.png)


## 5.6 ノードグループの作成

- 公式ドキュメント「[セルフマネージド型 Amazon Linux ノードの起動](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/launch-workers.html)」に従い、ノードグループを作成する。
- ノードグループを作成する用のCloudFormationテンプレートを指定してスタックを作成する。(ステップ1:テンプレートの指定)

![22a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/03f435e6-bf32-0279-5c6c-9f8fbc3f0d30.png)

- スタック作成のためのパラメータを入力する。(ステップ2: スタックの詳細を指定)
    - ClusterName: 既に作成済のEKSクラスタの名前(今回は「mksamba-eks-qiita」)
    - ClusterControlPlaneSecurityGroup: EKSクラスタのセキュリティグループ。EKSクラスタを作成した時に合わせて作成されているものを指定する(今回は「eks-cluster-sg-mksamba-eks-qiita-XXXXXXXXXXX」)
    - NodeImageIdSSMParam: 埋め込まれている値の「1.17」の部分を、クラスター側のバージョンにあわせて「1.18」に変更(今回は 「/aws/service/eks/optimized-ami/1.18/amazon-linux-2/recommended/image_id」)
    - BootstrapArguments: EKSクラスターのエンドポイントと認証機関の値を設定する。「--apiserver-endpoint "EKSクラスター
のAPIサーバエンドポイント" --b64-cluster-ca "認証機関"」それぞれの値はEKSクラスターの管理画面で参照可能。
    - Subnets: Wavelength zone に作成したサブネットを指定。

![23a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/50276935-bac9-30ce-8b32-95e8b8d244a7.png)

![24a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/229158af-a2b4-beee-69b0-cec75ead4114.png)

- スタックオプションは特に変更せず、設定内容を確認してスタック作成を開始する。(ステップ3: スタックオプション、ステップ4: レビュー)
- スタックの作成が完了すると、指定した数のインスタンスが起動される。

![25a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/5d3ee4de-d515-af6c-8862-d7a061e30251.png)

## 5.7 IAM オーセンティケーター設定マップの適用

- 公式ドキュメント通りに、configmapの設定を行う。

```
[ec2-user@ip-10-0-0-130 ~]$ cat aws-auth-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: arn:aws:iam::XXXXXXXXXXXX:role/mksamba-eks-qiita-nodegroup-NodeInstanceRole-XXXXXXXXXXXXX
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
        
[ec2-user@ip-10-0-0-130 ~]$ kubectl apply -f aws-auth-cm.yaml
configmap/aws-auth created
```

## 5.8 VPCエンドポイントの追加

- 公式ドキュメント[「プライベートクラスター」](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/private-clusters.html#vpc-endpoints-private-clusters)に従い、VPCエンドポイントを作成する。
- 以下の3つのインタフェースエンドポイントを作成する(画面はcom.amazonaws.ap-northeast-1.ec2のもの)。
    - com.amazonaws.ap-northeast-1.ec2
    - com.amazonaws.ap-northeast-1.ecr.api
    - com.amazonaws.ap-northeast-1.ecr.dkr
- 今回は検証のため、1個のサブネット(東京リージョンのPublicSubnet01)のみにエンドポイントを作成している。
- エンドポイントのセキュリティグループ設定(Inbound)として、VPCのCIDR(10.0.0.0/16)を追加で許可している。


![26c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/0d7e7380-60fe-6655-45db-02eceef7e9af.png)


- 以下のゲートウェイエンドポイントを作成する。
    - com.amazonaws.ap-northeast-1.s3 
- 「ルートテーブルの追加」設定において、wavelength zoneに作成したサブネットも対象として選択する。

![27a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/d584a2e3-8b0e-e87e-8e53-6ddfcf379762.png)






- エンドポイントの設定完了後、kubectl get nodes でnodeがReadyであることが確認できる。

```
[ec2-user@ip-10-0-0-130 ~]$ kubectl get nodes
NAME                                             STATUS   ROLES    AGE     VERSION
ip-10-0-10-132.ap-northeast-1.compute.internal   Ready    <none>   7m43s   v1.18.9-eks-d1db3c
ip-10-0-10-70.ap-northeast-1.compute.internal    Ready    <none>   7m42s   v1.18.9-eks-d1db3c
```

## 5.9 ノード(インスタンス)へのキャリアIPのアサイン

- ノードやコンテナに外部(キャリア網)からアクセスできるようにするため、キャリアIPのアサインを行う。
- Elastic IP アドレス割り当ての画面にて、ネットワークボーダーグループに「ap-northeast-1-wl1-nrt-wiz-1」を指定して割り当てを実行する。そうすると、東京Wavelength ZoneのキャリアIPが取得できる。

![28a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/a828989f-94e6-67e8-1033-b9ac3c658f7a.png)

- 取得したキャリアIPを、Wavelengh上のワーカーノードに紐づける。
- Elastic IPアドレスの関連付けの画面で、対象のENIを指定して関連付けを行う。（ワーカーノードとなるインスタンスは、ENIを複数持つため、インスタンスIDの指定ではキャリアIPを紐づけることができない。）ENIはインスタンスの管理画面で確認可能。元々あるENI(「説明」欄が空欄のほうのENI）のIDを確認し、関連付けの画面で指定する。

![30a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/8906e394-93b5-b410-7c83-93136a869df8.png)

![32a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/196bb478-cfb0-a8cc-3bfd-d7e0ab5e7ca4.png)

## 5.10 NodePortでの動作確認

- nginx を Deploymentとして作成し、nodeportで公開する。

```
[ec2-user@ip-10-0-0-130 ~]$ cat nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx

[ec2-user@ip-10-0-0-130 ~]$ kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created

[ec2-user@ip-10-0-0-130 ~]$ cat nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 32000

[ec2-user@ip-10-0-0-130 ~]$ kubectl apply -f nginx-service.yaml
service/nginx-service created

```

- auスマホでテザリングしたPCから、「http://キャリアIP:32000/」にアクセスして、nginxの画面が開けることを確認する。

![33a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/43cea11b-f9d2-7714-50b0-f57dac55e703.png)

# 6. 所感
- それなりに設定項目があり、結構長い記事になってしまった。もう少し手順が整理できるのかもしれない。