SvelteKitで始めるKubenetes（GKE）

# はじめに

[Ateam Brides Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ateam-brides)の19日目は、GCPの試験が近づき焦っている@mkinがお送りします。
さて、この記事は前回の記事「[SvelteKitをローカルのDocker環境で動かすまで](https://qiita.com/mkin/items/5b4fb2e61cf47fc5f904)」の続編になります。

タイトルにある`GKE`とはGoogle Kubernetes Engineの略で、コンテナ技術を使って自動デプロイや柔軟なスケーリングを実現できるクラウドサービスです。

会社でもサクッとSvelteを使ってもらえるような情報を記事にできたらいいなと思います。

## 概要と前回までのあらすじ
![概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/3723a3a2-f95a-826c-34fe-fd399e395c3e.png)
前回は上の概要図の1と2にあたる部分まで行いました。詳しくは前回の記事「[SvelteKitをローカルのDocker環境で動かすまで](https://qiita.com/mkin/items/5b4fb2e61cf47fc5f904)」をご参照ください。
なので、この記事は、ローカルにはコンテナイメージがある状態から始めようと思います。

```sh:コンテナイメージを確認
$ docker images

> REPOSITORY   TAG      IMAGE ID       CREATED          SIZE
> svelte-app   latest   ac73e372efbf   15 minutes ago   259MB
```

# GKEでSvelteKitを動かす
## Container Registoryにコンテナイメージをpushする
![概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/05e93eba-37b9-d709-4e4c-8cbb2a69b657.png)
### 1. GCPコンソールからプロジェクトを作成

今回は`svelte-project`という名前で作成しました。
事前にGCPコンソールから下記のAPIを有効にしておきましょう。

- Container Registry API
- Kubernetes Engine API 

### 2. Cloud SDKの設定

割愛させてください。
下記のコマンドで今回用のアカウント、プロジェクトが指定されていればOKです。

```sh:GCPの設定を確認
$ gcloud config configurations list
```

[参考： Cloud SDK のインストール](https://cloud.google.com/sdk/docs/install?hl=JA)

### 3. Container Registoryを使うための認証設定

ローカルPCからContainer Registryを使えるように認証を済ませておきましょう。

```sh:ContainerRegistoryの認証設定
$ gcloud components install docker-credential-gcr
$ gcloud auth configure-docker
```

### 4. DockerイメージをContainer Registoryにpush

設定ができたら、いよいよDockerイメージをContainer Registoryにpushします。pushすると言っても、どのデータセンターにホストするか選ぶ必要があります。
今回は、アジアのデータセンターにホストしようと思います:beach:

| ホスト名 | ストレージの場所 |
|:-|:-|
| gcr.io | 米国のデータセンターにイメージを保存します。  |
| asia.gcr.io  | アジアのデータセンターにイメージを保存します。  |
| eu.gcr.io  |  欧州連合の加盟国内のデータセンターにイメージを保存します。 |
| us.gcr.io  | 米国のデータセンターにイメージを保存します。  |

pushする際のイメージタグには命名規則があるので、適宜、置き換えてください。
`ホスト名/プロジェクトID/Dockerイメージ名:バージョン`

```sh:ContainerRegistory用のdockerイメージタグを作成する
$ docker image tag svelte-app:latest asia.gcr.io/svelte-project-335404/svelte-app:latest

# イメージタグを確認
$ docker images
> REPOSITORY                                     TAG        IMAGE ID       CREATED          SIZE
> asia.gcr.io/svelte-project-335404/svelte-app   latest     ac73e372efbf   44 minutes ago   259MB
> svelte-app                                     latest     ac73e372efbf   44 minutes ago   259MB
```

先にあった`svelte-app`のイメージIDと同じpush用のイメージタグを作成できました。
それでは、Container Registoryにpushしてみましょう:rocket:

```sh:ContainerRegistoryにpush
$ docker image push asia.gcr.io/svelte-project-335404/svelte-app:latest
```

GCPコンソールからイメージが保存されていることを確認できます。

![ContainerRegistory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/b920bda9-0a95-4ea4-8458-60c292496718.png)

## GKEで動かす

![概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/7ee8230a-371e-1197-2795-0a94ed2a1c6e.png)

### 1. クラスターを作成

Kubernetes Engineを使ってクラスターを作成します。
クラスターとは、アプリのコンテンやそのデプロイ方法、公開方法などをひと塊に抽象化することで管理しやすくしたものです。なので、中にはワークロードのためのNodeがいくつか動いています（デフォルト3つ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/66126d8c-cbbb-7203-68b8-65bb00d91b5e.png)

とりあえず、クラスターを作成してみましょう。

```sh:クラスターを作成
$ gcloud container clusters create svelte-cluster
```

数分かかります。

```sh:作成されたnodeを確認
$ kubectl get nodes

> NAME                                            STATUS   ROLES    AGE    VERSION
> gke-svelte-cluster-default-pool-27e939cb-83rm   Ready    <none>   116s   v1.21.5-gke.1302
> gke-svelte-cluster-default-pool-27e939cb-n3cs   Ready    <none>   116s   v1.21.5-gke.1302
> gke-svelte-cluster-default-pool-27e939cb-t1sp   Ready    <none>   116s   v1.21.5-gke.1302
```

nodeが3つ作成されていますが、実際にGCPコンソールのGoogle Compute Engineを見ると、3つのVMが起動していることを確認できます。

### 2. Deploymentを作成

先程、Container Registoryにpushしたイメージをデプロイする定義を作成します。今回はやりませんが、このDeploymentの定義次第で、ローリングアップデートや、ブルー・グリーンデプロイができるようになります。

```sh:DockerイメージのDeploymentを作成
$ kubectl create deployment svelte-deployment --image=asia.gcr.io/svelte-project-335204/svelte-app:latest
```

SvelteKitのコンテナを内包するPodが動くようになりましたが、これを3つに増やしてスケーリングさせてみましょう。これで、もし何か1つのPodが死んでしまっても、自動的に1つPodが作成されるようになります。これがKubernetesの凄いところですね :open_mouth:

```sh:Podを増やしてスケーリング
$ kubectl scale deployment svelte-deployment --replicas=3

$ kubectl get pods

> NAME                                READY   STATUS    RESTARTS   AGE
> svelte-deployment-5d4865985-btwmf   1/1     Running   0          2m50s
> svelte-deployment-5d4865985-pb5rs   1/1     Running   0          5m51s
> svelte-deployment-5d4865985-qfls4   1/1     Running   0          2m50s
```

### 3. サービスを作成（公開）

先のデプロイしたアプリケーションへのリクエストを受けるロードバランサを定義します。これにより、http(80番ポート)のアクセスを受け付け、SvelteKitが動いている3000番ポートに流してくれます。

```sh
# SvelteKitのコンテナで開いている3000ポートに設定
$ kubectl expose deployment svelte-deployment --name=svelte-service --type=LoadBalancer --port 80 --target-port 3000

# EXTERNAL-IPは数十秒で割り振られます
$ kubectl get service

> NAME             TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
> kubernetes       ClusterIP      10.76.0.1     <none>        443/TCP        6m29s
> svelte-service   LoadBalancer   10.76.4.100   35.200.86.4   80:30595/TCP   85s
```

数十秒後、svelte-serviceに割り振られた`EXTERNAL-IP`からアクセスできるようになります。ここでは、`http://35.200.86.4/`にアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/bc8b8240-0d31-9aed-3180-13b26df1a60b.png)

正常にアクセスできることを確認しました。

# お片付け

ランニングコストがかかってしまうので、削除しておきます。

```sh:作成したリソースを削除
$ gcloud container clusters delete svelte-cluster
$ gcloud container images delete asia.gcr.io/svelte-project-335204/svelte-app:latest
```

# おわりに

この記事を書き終わるころ、「あ、Cloud Runを使ってサーバーレスで動かしたほうがいいじゃん！コスト抑えられるし！」と気づいたのでGKEで動かすより、まずCloud Runで動かすことをオススメします！！ また記事にしますね:relaxed:

[Ateam Brides Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ateam-brides)の20日目は、面白いことへのアンテナが敏感なデザイナー @miinm030 の出番です。お楽しみに！

# 参考
https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro/