🍣

Next.jsをEKSに載せたい[~deployment編]

2023/12/23に公開

ちょっと株式会社 アドベントカレンダー2023 12月23日の記事です。
https://adventar.org/calendars/8910

環境のセットアップ

  1. AWS上でのIAMの作成
  2. Dockerのセットアップ
  3. 便利ツールのインストール

ここでは1~3に関しての詳細は割愛します。

  1. 今回は簡易的なものであるため、IAMロールにはAdministratorAccessをアタッチしました。
    また、VSCode上でAWS CLIを使えるようにもしておきましょう。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html

  1. DockerDesktopは下記からインストールが可能です。

https://www.docker.com/ja-jp/products/docker-desktop/

3の便利なツールについては下記です。

  1. kubectl
  2. eksctl
$ brew install kubectl
$ kubectl version --client
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3

https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/

$ brew tap weaveworks/tap && brew install weaveworks/tap/eksctl
$ eksctl version
0.166.0

https://docs.aws.amazon.com/ja_jp/emr/latest/EMR-on-EKS-DevelopmentGuide/setting-up-eksctl.html

Next.jsの環境構築

今回は簡潔にするため、exampleのリポジトリを使用します。

npx create-next-app --example with-docker-compose sample-eks-next-app

上記のコマンドの実行でFE環境が整います。
今回はコンテナ環境であるため、スタンドアローンモードである必要があります。サンプルリポジトリをcloneしてるため、next.config.jsにてあらかじめ指定されてます✌️

https://github.com/vercel/next.js/blob/canary/examples/with-docker-compose/next-app/next.config.js#L3

READMEにあるコマンドを実行すればNextが起動することも確認できました 🙌

# Create a network, which allows containers to communicate
# with each other, by using their container name as a hostname
docker network create my_network

# Build prod
docker compose -f docker-compose.prod.yml build

# Up prod in detached mode
docker compose -f docker-compose.prod.yml up -d

ECRの作成

https://aws.amazon.com/jp/ecr/

ECRはフルマネージドなDockerコンテナレジストリです。こちらを使用することでコンテナイメージの共有や保存が可能になります。
ECRはEKSと連携しているので、EKSで使用するイメージはECRで管理すると便利そうです。

公開/非公開の好みによって、Public/Privateのどちらかのregistryを選択してください。どちらでもいいのですが、今回はPrivateにし、名前は安直にsample-eks-next-appにします。設定はデフォルトのまま作成しました。

リポジトリが作成されたら詳細ページへいき、プッシュコマンドをコピーしましょう。モーダルに表示されるコマンドを順に実行していきます(with-docker-composeのサンプルを使用する場合、下記コマンド内-t(タグ)などを多少改変する必要があります)。

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxx.amazonaws.com
Login Succeeded
$ docker build -t sample-eks-next-app .
[+] Building 3.5s (24/24) FINISHED
$ docker tag sample-eks-next-app:latest xxxxxxxxxxx.amazonaws.com/sample-eks-next-app:latest
$ docker push xxxxxxxxxxx.amazonaws.com/sample-eks-next-app:latest

ここまで上手くいっていれば、詳細ページをリロードした際にイメージが追加されているはずです。

EKSクラスターの作成

https://aws.amazon.com/jp/eks/

EKSはKubernetes(=k8s)をAWS上で利用可能にするマネージドサービスです。実行基盤としてはEC2またはFargateの選択が可能となっています。今回はデフォであるEC2を使っていきます。

下記のドキュメントを参考にCLI上でクラスターの作成をしていきましょう。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-cluster.html

$ eksctl create cluster --name sample-eks-next-app --version 1.27 --managed
00:00:00 [ℹ]  eksctl version 0.166.0
.
.  10分ほど待機(少し時間がかかる)
.
00:00:00 [✔]  EKS cluster "next-eks" in "ap-northeast-1" region is ready

クラスターやノードの情報については下記のコマンドで確認が可能です。

$ eksctl get cluster
$ kubectl cluster-info
$ kubectl get node

コンテナの最小単位であるPod(小さなサーバー的なもの)も確認してみます。

$ kubectl get namespace
NAME              STATUS   AGE
default           Active   18m
kube-node-lease   Active   18m
kube-public       Active   18m
kube-system       Active   18m

$ kubectl get pod -n kube-system -A   
NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE
kube-system   aws-node-ksxpw             1/1     Running   0          20m
kube-system   aws-node-zd2vl             1/1     Running   0          20m
kube-system   coredns-8496bbc677-t49jq   1/1     Running   0          26m
kube-system   coredns-8496bbc677-vgqh7   1/1     Running   0          26m
kube-system   kube-proxy-jlhfv           1/1     Running   0          20m
kube-system   kube-proxy-pdj52           1/1     Running   0          20m

各種マニフェストの作成

アプリケーションのデプロイのために、まずは名前空間を作成し、

$ kubectl create namespace sample-eks-next-app

次にデプロイマニフェストを作成します。今回はGHに落ちていたものを参照しました。

manifests/deployments.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-eks-next-app
spec:
  selector:
    matchLabels:
      app: sample-eks-next-app
  replicas: 2
  template:
    metadata:
      labels:
        app: sample-eks-next-app
    spec:
      containers:
      - name: sample-eks-next-app
        image: <ここにECRのURIをペースト。リポジトリの詳細ページからURIを取得することができます>
        imagePullPolicy: Always
        ports:
        - containerPort: 3000

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment

続いて、作成したymlを適用します。

$ kubectl apply -f deployments.yml -n sample-eks-next-app

ここでは、-nオプションを使用し、名前空間を指定しましたが、kubensを使用するとデフォルトの名前空間をセットすることができて便利そうです。

この他にもマニフェストとして、サービスとイングレスがあり、同様の手順を踏み、yamlをapplyすることになるため、インストールしてもいいかもしれません。サービスおよびイングレスに関しては下記記事が分かりやすいです。

https://thinkit.co.jp/article/18263

上記記事でいうところのdeploymentは先ほどのコマンドをもってリソース作成が完了しています。試しにget deploymentを実行し、確認。

$ kubectl get deployment
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
sample-eks-next-app   2/2     2            2           73s

Podが2つ動いてることが確認できました。わーい。

エンドユーザーは、このPodに直接アクセスするのではなく、サービスを介してアクセスします。例えば、フロントエンドにアクセスする場合、フロントエンドのサービスを介してアクセスするというイメージです。イングレスは、クラスター内外のアクセスを制御するために使用されます。つまり、イングレスを通じてサービスにアクセスし、そのサービスを通じてPodにアクセスする流れです。

また、外部からのアクセス、例えばブラウザにURLを入力してアクセスする場合は、ALB Controllerの設定が必要です。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/aws-load-balancer-controller.html

ALB Controllerを設定すると、イングレスのリソースを作成した際にAWSのロードバランサー(ALB)が自動的に作成され、外部からのアクセスが可能になります。便利〜〜。

まとめ

長くなってしまうため今回はブラウザ上での確認までは割愛しましたが、無事にdeploymentまで漕ぎ着けることができました。

また時間を取れた際にALBControllerの設定などもし、ブラウザ上でNextを確認するところまでやっていきたいと思います💪

参考

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/sample-deployment.html

chot Inc. tech blog

Discussion