🔨

[GCP無料枠のみで構築]#2:GKEにてアプリケーション実行

2022/02/12に公開

こんにちは!chameleonです!

GCP無料枠で構築するの第二弾です!
今日は巷でよく耳にする「Kubernetes」(クーバネティス)についてGCP無料枠のみで構築していこうと思います。

本記事の内容を実践することでKubernetesの大枠を理解する&実際に手を動かしてみることで構築の肌感覚が掴めるかと思います。

GCPの無料枠

前回と同じ内容の再掲なので前回読んだ人は飛ばしてください。
GCPの無料枠についてはトライアル中に利用できる$300の枠が有名ですが、実はトライアル期間が終了してもかなりのサービスが無料で使えます。詳細は下記記事をご覧ください。
GCP無料枠の記事

万が一、無料サービス以外の範囲を超えた場合にすぐ検知できるようにアラートを設定しておきましょう。これで安心!
GCP請求アラートの設定

それでは始めましょう!

想定する読者

・Kubernetesってよく聞くけど実際なんなのかよくわからない
・Kubernetesの概念は知ってるけど構築したことはないなー

ゴール

今回はGCPのKubernetesのマネージドサービスであるGKE(Google Kubernetes Engine)とArtifact Registryというコンテナレジストリを利用して、Kubernetes上にWebアクセスすると「Hello World!」という文字とhostname(処理しているPod名)が表示されるアプリケーションをデプロイしていこうと思います。

完成イメージ図は下記のような感じです。

そしてKubernetesのうまみを実感してもらうために、Podのアプリケーションをアップデートして、ローリングアップデート(システムの停止なしにアプリケーションの入替を実施)を実行してみます!

今回利用するGCPサービス

今回り用るするGCPサービスはGKEとArtifact Registryの2つです。

GKE(Google Kubernetes Engine)

GCPの提供するKubernetesのマネージドサービスです。
Kubernetesではコントロールプレーンとワーカーノードという2つの構成要素からなり、実際のアプリケーションが稼働するのはワーカーノードの方です。このワーカーノードをうまく管理する役目がコントロールプレーンなのですが、このコントロールプレーンの部分をGCPがGKE上で管理してくるため、GKEではワーカーノードのみを構築すればOKです。

GKEクラスタモード

GKEを利用する際にはワーカーノードを処理させるためのクラスタを作成する必要があります。
クラスタのモードにはStandardとAutopilotの2つモードがあります。

Standardモードは従来のモードであり、2021年2月24日に公開された新たなモードがAutopilotモードです。
Autopilotモードでは管理者が考えていたインスタンス数やグレード等の構成を自動的に最適化してくるため、管理者が構成について考える必要がなくなりました。
今回はこのAutopilotモードを利用してGKEクラスタの構築を行います。

Artifact Registry

ざっくり言うとこれまでコンテナイメージを管理するために使っていたContainer Registryの進化版です。Container Registryの機能に加え、OSや言語パッケージ、IAM対応によるリポジトリ単位でのパーミション制御等ができるようになりました。

今回はこの2つのサービスを利用して構築を行っていきます。

構築の大まかな流れ

構築の大まかな流れは下記の通りです。

0.事前準備(gcloud config設定)
1.Artifact Registryリポジトリ作成
2.コンテナイメージのbuild
3.コンテナイメージをArtifact Registryにpush
4.サンプルアプリのGKEへのデプロイ
5.インターネットへの公開
6.ローリングアップデート

構築スタート!!!

それでは構築スタートです!

0.事前準備

0.1.環境変数設定

PROJECT_IDにプロジェクトID、REGIONにリージョン、ZONEにゾーンを設定します。

各サービスGKEやArtifactRegistryを同一リージョンに配置することで、無駄なコスト発生を防ぐことができるので特段要件がなければ、最初にリージョンを環境変数で指定することで同一リージョンに構成するようにしましょう。
今回はリージョンはus-west1(オレゴン)を指定します。

export PROJECT_ID=awesome-height-240603
export REGION=us-west1
export ZONE=us-west1-a

0.2.gcloud config設定

gcloud configコマンドを使ってプロジェクトIDとリージョンとゾーンを設定します。

gcloud config set project $PROJECT_ID
gcloud config set compute/region $REGION
gcloud config set compute/zone ${ZONE}

1.Artifact Registryリポジトリ作成

まずはコンテナイメージを配置するArtifact Registryのリポジトリを作成していきましょう。
下記コマンドで指定したリージョンに「hello-repo」という名前のレポジトリを作成します。

gcloud artifacts repositories create hello-repo \
   --repository-format=docker \
   --location=$REGION \
   --description="Docker repository"

コンソールから確認します!

2.コンテナイメージのbuild

次にコンテナイメージのbuildです。
今回は「Hello World!!」というメッセージと処理したPodのhostnameを表示するhello-appというサンプルアプリケーションをGKEにデプロイしていきます。
まずは、ローカル環境でサンプルアプリケーションのコンテナイメージを作ります。

2.1.ローカルにサンプルアプリケーションのソースとDockerファイルをクローン

下記コマンドでローカル環境の任意のディレクトリにソースコードを配置します。

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/hello-app

2.2.タグをつけてbuildを実行

タグをつけてbuildを実行しコンテナイメージを作成します。

docker build -t ${REGION}-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1 .

作成したコンテナイメージは下記コマンドで確認できます。

docker images |grep 'hello-app'

ターミナルからローカル環境にイメージが作成されたかを確認してみましょう。

kubernetes-engine-samples $ docker images |grep 'hello-app'
us-west1-docker.pkg.dev/awesome-height-240603/hello-repo/hello-app   v1           d4dff7aebb4b   3 days ago      11.5MB

3.コンテナイメージをArtifact Registryにpush

3.1.Docker コマンドライン ツールから Artifact Registry への認証を構成

gcloud auth configure-docker ${REGION}-docker.pkg.dev

下記のように処理継続したいかを聞かれますが「Y」を選択して先に進めてください。

kubernetes-engine-samples $ gcloud auth configure-docker ${REGION}-docker.pkg.dev
Adding credentials for: us-west1-docker.pkg.dev
After update, the following will be written to your Docker config file located at [/Users/ken/.docker/config.json]:
 {
  "credHelpers": {
    "us-west1-docker.pkg.dev": "gcloud"
  }
}

Do you want to continue (Y/n)?  Y

Docker configuration file updated.

3.2.buildしたコンテナイメージをArtifact Registryにpush

Artifact Registryに作成しておいた「hello-repo」レポジトリにコンテナイメージをpushします。

docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1

コンソールから、先ほど作成した「hello-repo」レジストリ配下に「hello-app」のイメージが作成されていることを確認します。

4.サンプルアプリのGKEへのデプロイ

4.1.GKEクラスタの作成

まずはGKE上にKubernetesを動かすクラスタの作成を行います。
上で記載した通り、今回はAutopillotモードで「hello-cluster」という名前でクラスタ作成を行います。
コマンド完了まで3〜5分かかります。

gcloud container clusters create-auto hello-cluster \
    --region ${REGION} \
    --project=${PROJECT_ID}

コンソールで確認するとクラスタが作成されていることがわかります。

4.2.GKEクラスタへの接続確認

作成したGKEクラスタの接続確認を行います。

gcloud container clusters get-credentials hello-cluster --region ${REGION}

下記のようなログが出力されれば成功です。

kubernetes-engine-samples $ gcloud container clusters get-credentials hello-cluster --region ${REGION}
Fetching cluster endpoint and auth data.
kubeconfig entry generated for hello-cluster.

4.3.Kubernetesのdeployment作成

Kubernetesのdeploymentを作成します。
Kubernetesではアプリケーションを動かすコンテナはPodで稼働しますが、このPodを直接管理するのではなく、Podを管理するReplicaSetや、このReplicaSetを管理するdeployment等を通して管理を行います。
このdeploymentを利用することでコンテナのアプリケーション更新時の手間やPodに障害が発生した場合等の対応が簡単にできるようになってます。

詳しくは下記記事等をご覧ください。
https://qiita.com/tkusumi/items/01cd18c59b742eebdc6a

下記コマンドで「hello-app」という名前のdeploymentを作成し、Artifact Registryからコンテナイメージをデプロイするよう設定します。

kubectl create deployment hello-app --image=${REGION}-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1

コンソールのKubernetesのワークロードでタイプ「Deployment」のワークロードができていることを確認します。

さらに詳細を確認します。この時点だと起動しているPodは1つですね。

4.4.deploymentのreplicas(Podの複製数)のベースラインを設定

上記コマンドでdeploymentを作成した場合はAutopilotのデフォルトの設定になっていますので、下記コマンドでreplicasのベースラインを3に設定します。

kubectl scale deployment hello-app --replicas=3

コンソールで確認するとPodが3つに増えていることがわかります。

4.5.HorizontalPodAutoscaler(Podの複製数の上限、下限とオートスケール時のCPU閾値)

下記でオートスケール時の設定を行います。

kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5

5.インターネットへの公開

5.1.KubernetesのServiceを作成してインターネットへサービスを公開

このままだとこのサービスは外部に公開できません。
KubernetesのServiceを利用して、このサービスを外部公開します。

ServiceとはPodとの通信に単一のエンドポイントを提供するためのものです。
タイプが4種類ありそれぞれ下記の通りです。

タイプ 説明
ClusterIp デフォルトのサービスタイプ。クラスタ内からのみアクセス可能。
NodePort 各ノードのIP上のServiceを静的ポート(NodePort)に公開。<NodeIp>:<NodePort>を要求することで、クラスタ外からNodePort Serviceにアクセス可能。
LoadBalancer クラウドプロバイダのロードバランサを使用して外部にServiceを公開。外部ロードバランサがルーティングするNodePort ServiceとClusterIP Serviceが自動的に作成。
ExternalName 値を含むCNAMEレコードを返すことにより、ServiceをexternalNameフィールドのコンテンツ(たとえば、foo.bar.example.com)にマッピング

下記コマンドでタイプLoadBalancerのServiceを「hello-app」deploymentに設定します。
このコマンドでServiceのport80番にアクセスするとdeploymentのport8080にルーティングするようになります。

kubectl expose deployment hello-app --name=hello-app-service --type=LoadBalancer --port 80 --target-port 8080

コンソールからServiceが作成されていることを確認します。

5.2.アクセスしてみる

上記のコンソールのサービスに記載してあるエンドポイントのアドレスを押下してください。
下記のようにHello, world!とhostnameが表示されたら成功です。

6.ローリングアップデート

deploymentのうまみを理解するためにローリングアップデートを体感してみます。

6.1.deploymentに新たなバージョンのアプリケーションをデプロイ

2.2の手順を参考にローカル環境でタグをv2として再度build。
※タグのバージョンを変更するのみで、hello-app配下のプログラムは更新する必要はありません。

docker build -t ${REGION}-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2 .

次に、3.2の手順を参考にArtifact Registryにタグのバージョンをv2でpush。

docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2

最後に下記コマンドでdeploymentのアプリケーションを更新します。

kubectl set image deployment/hello-app hello-app=${REGION}-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2

すると、新しいバージョンのプログラムが稼働するPodが新規に立ち上がり、古いバージョンのプログラムが稼働するPodが自動で解放されていきます。
これがローリングアップデートです。

自分でわざわざ、Podの落とし上げをしなくてもスムーズにプログラムの移行を行ってくれます。

これで本日は終わりです。
なんとか2本目までかけました。

3本目も頑張りたいです!!!

Discussion