QuarkusアプリをGKE(Google Kubernetes Engine)に載せてみた。

# お題
> Supersonic Subatomic Java
> A Kubernetes Native Java stack tailored for GraalVM & OpenJDK HotSpot, crafted from the best of breed Java libraries and standards

という謳い文句の[Quarkus](https://quarkus.io/)を試してみた。
既に↓のように、紹介、ないし、試してみた記事はいろいろあるので、違いとして、[GKE(Google Kubernetes Engine)](https://cloud.google.com/kubernetes-engine/?hl=ja)に載せてみることを試してみた。

- [Javaフレームワーク「Quarkus」登場。Javaコードからネイティブバイナリを生成し瞬時にJavaアプリが起動、コンテナへの最適化を実現。Red Hatがリリース](https://www.publickey1.jp/blog/19/javaquarkusjavajavared_hat.html)
- [Quarkus: コンテナ上で Java アプリを高速起動する新しい手法のご紹介](https://yoshio3.com/2019/03/11/try-quarkus/)
- [Quarkus: Container First Microservices Framework](https://codewithmansoor.com/quarkus/)
- [JavaアプリをNativeコンパイルして爆速で起動するQuarkusを試してたら利用例にプルリクエストがマージされた](http://kdnakt.hatenablog.com/entry/2019/03/15/080000)
- [Javaのフレームワーク「Quarkus」を試してみた](https://qiita.com/mr-hisa-child/items/92e0417460adc328596a)
- [KubernetesネイティブなJavaフレームワーク Quarkus について調査してみた件](https://qiita.com/mamomamo/items/e73e5216605609e40082#kubernetes%E3%81%B8%E3%81%AE%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)

# 作業環境
### # OS
<pre>
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
</pre>

### # Java
<pre>
$ java -version
openjdk version "10.0.2" 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)
OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4, mixed mode)
</pre>
※ちなみに、**Java12**で試したら動きませんでした。

### # Docker
<pre>
$ sudo docker version
　　〜〜〜
Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 03:42:13 2019
  OS/Arch:          linux/amd64
  Experimental:     false
</pre>

### # Maven
<pre>
$ mvn -version
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
</pre>

### # gcloud
<pre>
$ gcloud version
Google Cloud SDK 240.0.0
　〜〜〜
kubectl 2019.03.22
</pre>
※`gcloud auth`は済んでいる状態。

# 実践

## Quarkusアプリ作成
↓のチュートリアルに沿ってMavenプロジェクトを作成し、あとは、作成したプロジェクトに含まれている `mvnw` コマンドを叩くだけ。
https://quarkus.io/guides/getting-started-guide

ソースを一部抜粋すると、↓のようなSpringライクなWebAPIコードとなる。
[GCPのCloud Endpoints](https://cloud.google.com/endpoints/docs/about-cloud-endpoints?hl=ja)を使おうとした時も、やはり似たようなコードになったし。

```java:[org.acme.quickstart.GreetingResource]
@Path("/hello")
public class GreetingResource {

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam("name") String name) {
        return service.greeting(name);
    }
}
```

## Dockerコンテナ
これもチュートリアル通りだけど、下記のようなDockerfileをプロジェクト配下に作成。

```dockerfile:[Dockerfile]
FROM openjdk:11-jre-slim
RUN mkdir /app
COPY target/lib /app/lib
COPY target/*-runner.jar /app/application.jar
EXPOSE 8080
CMD ["java", "-jar", "/app/application.jar"]
```
※チュートリアルでは `openjdk:8-jre-slim` だったのだけど、試した時の Quarkus のバージョンの問題か、コンテナ作成後に `docker run` した時にうまく起動しなかったため「11」に上げた。

## ビルド by [Cloud Build](https://cloud.google.com/cloud-build/?hl=ja)
下記のようにCloud Buildを利用するためのYamlファイルをプロジェクト配下に作成。

```yaml:[cloudbuild.yaml]
steps:
- name: 'gcr.io/cloud-builders/docker'
  args: [ 'build', '-t', 'gcr.io/$PROJECT_ID/quarkus-microservice', '.' ]
images:
- 'gcr.io/$PROJECT_ID/quarkus-microservice'
```
　
で、ビルド実行。すると、出来上がったコンテナイメージが[GCR(Google Container Registry)](https://cloud.google.com/container-registry/?hl=ja)に上がる。

```
$ gcloud builds submit --config cloudbuild.yaml .
Creating temporary tarball archive of 137 file(s) totalling 9.6 MiB before compression.
Uploading tarball of [.] to [gs://【GCPプロジェクトID】_cloudbuild/source/1553878212.23-a25ba1029b4a4979b2a049769da45570.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/【GCPプロジェクトID】/builds/1bff9b28-a9da-4113-9c41-c9de7f9af1d7].
　　　〜〜〜
DONE
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ID                                    CREATE_TIME                DURATION  SOURCE                                                                                  IMAGES                                              STATUS
1bff9b28-a9da-4113-9c41-c9de7f9af1d7  2019-03-29T16:50:16+00:00  46S       gs://【GCPプロジェクトID】_cloudbuild/source/1553878212.23-a25ba1029b4a4979b2a049769da45570.tgz  gcr.io/【GCPプロジェクトID】/quarkus-microservice (+1 more)  SUCCESS
```

実際にビルド成功してコンテナイメージが格納されていることをGCPコンソールで確認。
![screenshot-console.cloud.google.com-2019-03-30-01-54-34-080.png](https://qiita-image-store.s3.amazonaws.com/0/180599/a3eb41de-c4ce-b890-a668-d19096b8aab5.png)
![screenshot-console.cloud.google.com-2019-03-30-01-57-09-002.png](https://qiita-image-store.s3.amazonaws.com/0/180599/6eb16f98-0a16-4c7d-c502-1e082ae9269b.png)

ちなみに、このへんの手順は下記の過去記事に基づく。
[GKE試行（その2：「GitHub -> CSR へ。そしてGCBによりGCRへ」）](https://qiita.com/sky0621/items/4d27f979199a9ea1efa4#cloud-build)

## GKEクラスタ作成
GCPにおけるk8sのマネージドサービスを利用するため、まずはクラスタを作成。
GCPコンソールからも作成可能だけど、（節約のため）作ったり消したりするのでコマンドとして残しておくことにする。
サービス公開でなくただのトライ記事用なのでプリエンプティブで作成。

```
$ gcloud container clusters create clst-pe-01 --preemptible --machine-type=f1-micro --num-nodes=3 --disk-size=10
WARNING: In June 2019, node auto-upgrade will be enabled by default for newly created clusters and node pools. To disable it, use the `--no-enable-autoupgrade` flag.
　　　〜〜〜
Creating cluster clst-pe-01 in asia-northeast1-c... Cluster is being health-checked (master is healthy)...done.                                                                                              
Created [https://container.googleapis.com/v1/projects/【GCPプロジェクトID】/zones/asia-northeast1-c/clusters/clst-pe-01].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/asia-northeast1-c/clst-pe-01?project=【GCPプロジェクトID】
kubeconfig entry generated for clst-pe-01.
NAME        LOCATION           MASTER_VERSION  MASTER_IP       MACHINE_TYPE  NODE_VERSION   NUM_NODES  STATUS
clst-pe-01  asia-northeast1-c  1.11.7-gke.12   xx.xxx.xxx.xxx  f1-micro      1.11.7-gke.12  3          RUNNING
```

実際にクラスタが作られていることを確認。
![screenshot-console.cloud.google.com-2019-03-30-02-07-20-951.png](https://qiita-image-store.s3.amazonaws.com/0/180599/a0d68718-29a8-a150-894e-b98a16fd9ae1.png)

ちなみに、このへんの手順は下記の過去記事に基づく。
[GKE試行（その3：「クラスタ作成」）](https://qiita.com/sky0621/items/d3c28b67dbabf3df88be)
また、節約のためのクラスタ作成云々は下記が参考になる。
[安価なGKE（k8s）クラスタを作って趣味開発に活用する](https://blog.a-know.me/entry/2018/06/17/220222)

## [GCR(Container Registry)](https://cloud.google.com/container-registry/?hl=ja)にあるコンテナイメージを[GKE(Kubernetes Engine)](https://cloud.google.com/kubernetes-engine/?hl=ja)にデプロイ

```
$ kubectl run quarkus-microservice --image gcr.io/【GCPプロジェクトID】/quarkus-microservice@sha256:18a20d4307785a7aec3b19738a849430e2181720cb357d8a7ea6f8fe4ed1f850 --port 80
deployment.apps/quarkus-microservice created
```

はい。デプロイメントできてる。
![screenshot-console.cloud.google.com-2019-03-30-02-21-46-308.png](https://qiita-image-store.s3.amazonaws.com/0/180599/0040fc89-403f-3110-61ec-6c53cee12156.png)

## アプリを公開
デプロイメントできただけだと外部からのアクセスの口がないので、公開用にサービスを作る。

```
$ kubectl expose deployment quarkus-microservice --type "LoadBalancer"
service/quarkus-microservice exposed
```

はい。サービスできてる。
![screenshot-console.cloud.google.com-2019-03-30-02-25-48-306.png](https://qiita-image-store.s3.amazonaws.com/0/180599/ef2e7acb-6e55-8d67-f41b-96286d38d23f.png)

## アクセス確認
![screenshot-34.85.95.35-8080-2019-03-30-02-48-08-274.png](https://qiita-image-store.s3.amazonaws.com/0/180599/432d88bd-dc0e-f517-6349-6559fdcc84bc.png)
簡素すぎてわからないけど、成功。

ちなみに、このへんの手順は下記の過去記事に基づく。
[GKE試行（その4：「GKEデプロイ->サービス公開」](https://qiita.com/sky0621/items/aadeb53a5be2800066de#４アプリを公開)

# まとめ
今回は、ただの初回チュートリアルレベルの自動生成アプリをGKEに載せただけ。
GitHubのサンプルコードとしては、JSON-REST、WebSocket、ORM、バリデーションなどいろいろある。
https://github.com/quarkusio/quarkus-quickstarts#getting-started-guides
![screenshot-github.com-2019.03.30-01-31-12.png](https://qiita-image-store.s3.amazonaws.com/0/180599/b4cb2363-296d-f8f5-188e-e0c3c1498006.png)
[k8s](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)に載せるアプリを考えた時、これまでは「[Golang](https://golang.org)で書こう。」になっていたけど、Quarkus登場のおかげで、今後は豊富な既存資産を使えるJavaも候補になるかも。