Kubernetes はオープンソースのプロジェクトで、ノートパソコンから可用性の高いマルチノード クラスタ、パブリック クラウドからオンプレミスのデプロイ、仮想マシン(VM)インスタンスからベアメタルまで、さまざまな環境で実行できます。
この Codelab では、シンプルな Spring Boot Java ウェブアプリを GKE の Kubernetes にデプロイします。この Codelab の目的は、ウェブアプリを Kubernetes で複製されたアプリとして実行することです。自分のマシンで開発したコードを Docker コンテナ イメージに変換してから、そのイメージを GKE で実行します。
このラボでは、基盤となるインフラストラクチャの設定ではなく、Kubernetes の操作に集中できるように、Google Cloud のフルマネージド Kubernetes サービスである GKE を使用します。
Kubernetes を開発用のノートパソコンなどのローカルのマシンで実行したい場合は、Minikube について調べることをおすすめします。Minikube では、開発とテスト用に単一ノードの Kubernetes クラスタを簡単に設定できます。Minikube をこの Codelab の学習に使用することも可能です。
この Codelab では、Spring Boot を使用したアプリの構築に関するガイドのサンプルコードを使用します。
前提条件
- Java プログラミング言語とツールに関する知識
- Linux の標準的なテキスト エディタ(Vim、Emacs、nano など)に関する知識
演習内容
- シンプルな Java アプリを Docker コンテナとしてパッケージ化する。
- GKE で Kubernetes クラスタを作成します。
- Java アプリを GKE の Kubernetes にデプロイします。
- サービスをスケールアップし、アップグレードをロールアウトする。
- ウェブベースの Kubernetes ユーザー インターフェースである Access Dashboard にアクセスします。
必要なもの
- Google Cloud プロジェクト
- ブラウザ(Google Chrome など)
セルフペース型の環境設定
- Cloud コンソールにログインして、新しいプロジェクトを作成するか、既存のプロジェクトを再利用します。(Gmail アカウントまたは G Suite アカウントをお持ちでない場合は、アカウントを作成する必要があります)。
プロジェクト ID を忘れないようにしてください。プロジェクト ID はすべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているので使用できません)。以降、このコードラボでは PROJECT_ID
と呼びます。
- 次に、Google Cloud リソースを使用するために、Cloud Console で課金を有効にする必要があります。
この Codelab の操作をすべて行って、費用が生じたとしても、少額です。ただし、リソースの使用量を増やしたり、実行したままにしたりすると、費用が増加する可能性があります。
Google Cloud の新規ユーザーは、300 ドル分の無料トライアルの特典があります。
Cloud Shell をアクティブにする
- Cloud コンソールで、[Cloud Shell をアクティブにする]
をクリックします。
Cloud Shell を起動したことがない場合、その内容を説明する中間画面が(スクロールしなければ見えない範囲に)が表示されます。その場合は、[続行] をクリックします(以後表示されなくなります)。この中間画面は次のようになります。
Cloud Shell のプロビジョニングと接続に少し時間がかかる程度です。
この仮想マシンには、必要な開発ツールがすべて用意されています。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働するため、ネットワーク パフォーマンスが充実しており認証もスムーズです。このコードラボでの作業のほとんどは、ブラウザまたは Chromebook から実行できます。
Cloud Shell に接続すると、すでに認証は完了しており、プロジェクトに各自のプロジェクト ID が設定されていることがわかります。
- Cloud Shell で次のコマンドを実行して、認証されたことを確認します。
gcloud auth list
コマンド出力
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
コマンド出力
[core] project = <PROJECT_ID>
上記のようになっていない場合は、次のコマンドで設定できます。
gcloud config set project <PROJECT_ID>
コマンド出力
Updated property [core/project].
Cloud Shell の起動後に以下のコマンドラインを使用すると、ホーム ディレクトリ内にサンプル ソースコードのクローンを作成できます。
$ git clone https://github.com/spring-guides/gs-spring-boot.git $ cd gs-spring-boot/complete
- Spring Boot プラグインを使用して、Spring Boot アプリを通常どおりに起動できます。
$ ./mvnw -DskipTests spring-boot:run
- アプリが起動したら、Cloud Shell ツールバーの [ウェブでプレビュー]
アイコンをクリックし、[ポート 8080 でプレビュー] を選択します。
ブラウザのタブが開き、起動したサーバーに接続されます。
次に、アプリを Kubernetes で実行するための準備を行います。最初のステップとして、コンテナとその内容を定義します。
- アプリのデプロイ可能な JAR を作成します。
$ ./mvnw -DskipTests package
- 作成するコンテナ イメージを保存するように Container Registry を有効にします。
$ gcloud services enable containerregistry.googleapis.com
- Jib を使用してコンテナ イメージを作成し、Container Registry に push します。
$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \ -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
- すべてが正常に実行されると、[Container Registry] > [イメージ] に移動して、コンテナ イメージがコンソールに表示されることを確認できます。これで、Docker イメージをプロジェクト全体で利用できるようになりました。数分後に実演するとおり、Kubernetes でこのイメージにアクセスし、オーケストレートできます。
- この処理が完了したら(すべてをダウンロードして抽出するのに時間がかかります)、次のコマンドを使用してイメージをローカルでテストできます。このコマンドは、新たに作成したコンテナ イメージから Docker コンテナをポート 8080 上のデーモンとして実行します。
$ docker run -ti --rm -p 8080:8080 \ gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
- ここでも Cloud Shell のウェブ プレビュー機能を利用します。
- 新しいタブにデフォルトのページが表示されます。アプリが Docker コンテナでローカルに実行されていることを確認したら、
Control+C
を押して実行中のコンテナを停止できます。
これで、GKE クラスタを作成する準備が整いました。クラスタは、Google が管理する Kubernetes API サーバーと一連のワーカーノードで構成されます。ワーカーノードは Compute Engine VM です。
- まず、関連する API 機能が有効になっていることを確認します。
$ gcloud services enable compute.googleapis.com container.googleapis.com Operation "operations/..." finished successfully
- 2 つの
n1-standard-1
ノードを含むクラスタを作成します(完了するまでに数分かかります)。
$ gcloud container clusters create hello-java-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
最終的に、作成されたクラスタが表示されます。
Creating cluster hello-java-cluster...done. Created [https://container.googleapis.com/v1/projects/...]. kubeconfig entry generated for hello-dotnet-cluster. NAME ZONE MASTER_VERSION hello-java-cluster us-central1-c ...
これで、GKE を搭載した、完全版の Kubernetes クラスタが作成されました。
次に、コンテナ化されたアプリを Kubernetes クラスタにデプロイします。ここからは kubectl
コマンドライン(Cloud Shell 環境で設定済み)を使用します。この Codelab の残りの部分では、Kubernetes のクライアントとサーバーがどちらもバージョン 1.2 以降である必要があります。kubectl version
を実行すると、コマンドの現在のバージョンが表示されます。
- Kubernetes Deployment は、作成したコンテナ イメージを使用して、アプリの複数のインスタンスを作成、管理、スケーリングできます。
kubectl run
コマンドを使用して、アプリの 1 つのインスタンスを Kubernetes にデプロイします。
$ kubectl create deployment hello-java \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
- 作成したデプロイを表示するには、次のコマンドを実行します。
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-java 1 1 1 1 37s
- デプロイによって作成されたアプリ インスタンスを表示するには、次のコマンドを実行します。
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-java-714049816-ztzrb 1/1 Running 0 57s
この時点で、コンテナは Kubernetes の制御の下に動作するようになりますが、外部からはまだアクセスできないので、アクセスを許可する必要があります。
デフォルトでは、Pod にはクラスタ内の内部 IP からしかアクセスできません。hello-java
コンテナに Kubernetes 仮想ネットワークの外部からアクセスできるようにするには、Pod を Kubernetes Service として公開する必要があります。
- Cloud Shell で、
kubectl expose
コマンドを--type=LoadBalancer
フラグ付きで実行すると、Pod をインターネットで公開できます。外部からアクセスできる IP を作成するには、このフラグが必要です。
$ kubectl create service loadbalancer hello-java --tcp=8080:8080
このコマンドで使用したフラグは、基盤となるインフラストラクチャからロードバランサを使用することを指定します。Pod ではなく、Deployment を直接公開していることに注意してください。これにより、Deployment で管理されるすべての Pod でトラフィックをロードバランスする Service が作成されます(ここでは 1 つの Pod だけですが、後でレプリカを追加します)。
Kubernetes マスターによってロードバランサ、それに関連する Compute Engine 転送ルール、ターゲット プール、ファイアウォール ルールが作成され、Google Cloud の外部からこの Service に完全にアクセスできるようになります。
- サービスのパブリック IP アドレスを確認するには、
kubectl
をリクエストしてすべてのクラスタ サービスを一覧表示します。
$ kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE Hello-java 10.3.253.62 aaa.bbb.ccc.ddd 8080/TCP 1m kubernetes 10.3.240.1 <none> 443/TCP 5m
- サービスに対して 2 つの IP アドレスが表示されます。いずれもポート 8080 を使用しています。1 つは、Virtual Private Cloud 内でのみ表示される内部 IP アドレスです。もう 1 つは外部ロードバランス IP アドレスです。この例では、外部 IP アドレスは
aaa.bbb.ccc.ddd
です。ブラウザで http://<EXTERNAL_IP>:8080 を指定すれば、対象のサービスにアクセスできるようになっています。
Kubernetes の優れた特長の一つは、アプリのスケールが容易なことです。アプリの容量が突然必要になったとします。レプリケーション コントローラに、アプリ インスタンスの新しいレプリカ数を管理するよう指示するだけで簡単に対応できます。
$ kubectl scale deployment hello-java --replicas=3 deployment "hello-java" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-java 3 3 3 3 22m
宣言型アプローチに注目してください。新しいインスタンスの起動や停止を行うのではなく、実行するインスタンスの数を宣言します。Kubernetes の調整ループは、リクエストした内容と実際の状態が一致しているかどうかが照合され、必要に応じて調整が行われます。
本番環境にデプロイしたアプリは、いずれかの時点でバグ修正や追加機能の実装が必要になります。Kubernetes を使用すると、ユーザーに影響を及ぼすことなく、新しいバージョンを本番環境にデプロイできます。
- Cloud Shell メニューの [エディタを起動 ]
をクリックして、コードエディタを開きます。
src/main/java/hello/HelloController.java
に移動して、レスポンスの値を更新します。
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Greetings from Google Kubernetes Engine!";
}
}
- Jib を使用して、コンテナ イメージの新しいバージョンをビルドして push します。
$ ./mvnw -DskipTests package \ com.google.cloud.tools:jib-maven-plugin:build \ -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2
これで、Kubernetes がレプリケーション コントローラを新しいバージョンのアプリにスムーズに更新する準備が整いました。
- コンテナの実行中にイメージラベルを変更するには、既存の
hello-java
デプロイを編集し、イメージをgcr.io/PROJECT_ID/hello-java:v1
からgcr.io/PROJECT_ID/hello-java:v2
に変更する必要があります。
kubectl set image
コマンドを使用すると、ローリング アップデートで新しいバージョンのアプリをクラスタ全体に一度に 1 つのインスタンスでデプロイするように Kubernetes に指示できます。
$ kubectl set image deployment/hello-java \ hello-java=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2 deployment "hello-java" image updated
- http://EXTERNAL_IP:8080 を再度確認し、新しいレスポンスが返されていることを確認します。
エラー: アプリの新しいバージョンで間違いがありましたか?新しいバージョンにエラーが含まれており、迅速にロールバックする必要がある場合などです。Kubernetes を使用すると、以前の状態に簡単にロールバックできます。次のコマンドを実行して、アプリをロールバックします。
$ kubectl rollout undo deployment/hello-java
新しい Java ベースのウェブアプリをビルドして GKE の Kubernetes にデプロイする方法を学習しました。