IntelliJ IDEA + Codewind + Appsody でKabanero 入門

## TL;DR
巷で噂のKabanero にIntelliJ IDEA で入門してみました。
Codewind でプロジェクト作成 --> Appsody でKubernetes クラスタにデプロイまでの作業ログです。
それぞれv1.0 を迎えていないですが、普段`docker` / `kubectl` をバシバシ打っている人には、そこそこ便利に使えそうという感じです。

## 環境
- PC: Macbook Pro
- IDE: IntelliJ IDEA Ultimate 2020.1
- Appsody CLI: 0.6.4
- Codewind: 0.14.0

## Appsody とは
Appsody は、すぐにKubernetes にデプロイ可能なプロジェクトの雛形を提供するオープンソースプロジェクトです。
また、コンテナレジストリやGithubと組み合わせて独自の雛形を共有することも可能なようです。

公式👉 https://appsody.dev/

## Codewind とは
Codewind は、コンテナでの開発を支援するIDE 拡張です。
IDE から簡単にアプリケーションコンテナのシェルにアクセスできたり、コンテナのログを閲覧できたりします。
また、ホットリロードのような機能もあり、ローカルの変更が自動的にコンテナ上のアプリに反映されます。
VS Code / Eclipse / IntelliJ をサポートしているため、Java プログラマーの大体はすんなり使用できそうです。

公式👉 https://www.eclipse.org/codewind/

## IntelliJ IDEA にCodewind を導入
Plugins のMarketplace から`Codewind` で検索すれば出てくるので、それをインストールするだけです。

## Codewind で新規プロジェクト作成
新規プロジェクト作成時に、Codewind の選択肢が追加されていることがわかります。
<img width="1278" alt="0697365564E663E6F5DA441D5C2E312B.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/4161aa9e-f1b6-b357-2dea-12541f0fbd41.jpeg">

Codewind を使用するには、どうやらCodewind 用のDocker コンテナが必要のようです。
初回のみですが、`INSTALL CODEWIND IMAGES` をクリックして、インストールします。

インストールが終わると、Appsody のプロジェクトの雛形を選択することができます。（今回は`Quarkus default template` を選択）
<img width="1271" alt="F3887E4CB67C5ACC61E698619E565530.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/3c978418-75f3-9519-43d5-80fa90d26889.jpeg">

あとは、プロジェクトの名前などを決めたら終了です。

## 作成されたプロジェクトをいじいじ
作成されたプロジェクトは、こんな感じです。
正直、Maven なのか😞と思いましたが、今後Gradle も選択できるようになると嬉しいですね。

```
example-codewind/
├── .appsody-config.yaml   # Appsody の構成情報
├── .appsody_init          # 実は、これがアプリの本丸？Dockerfileとか入ってる
├── .cw-settings           # Codewind の設定が入っているっぽいが内容はよくわからん
├── .idea
├── .vscode                # プロジェクト作成時点であった
├── example-codewind.iml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
```

プロジェクト作成直後、ビルドが走ってDocker 上にアプリが立ち上がります。
その様子は、新たに追加されたCodewind ビューから確認できます。
このビューから、ログをみたり、コンテナの中に入ったりできます。
個人的には、ターミナルとIDEを行ったり来たりしなくて良いので結構便利に感じました。
<img width="485" alt="7CABCA90DE8F8E88E341749F0BF45125.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126632/59818788-d803-5788-f76f-44e49d2e2503.jpeg">

ホットリロードもしっかり確認できます。

```
[Container] __  ____  __  _____   ___  __ ____  ______ 
[Container]  --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
[Container]  -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
[Container] --\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
[Container] 2020-07-29 06:29:15,402 WARN  [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Using Java versions older than 11 to build Quarkus applications is deprecated and will be disallowed in a future release!
[Container] 2020-07-29 06:29:15,631 INFO  [io.quarkus] (Quarkus Main Thread) example 1.0-SNAPSHOT on JVM (powered by Quarkus 1.6.0.Final) started in 0.230s. Listening on: http://0.0.0.0:8080
[Container] 2020-07-29 06:29:15,632 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
[Container] 2020-07-29 06:29:15,632 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, smallrye-metrics]
[Container] 2020-07-29 06:29:15,632 INFO  [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-3) Hot replace total time: 1.091s 
[Container] 2020-07-29 06:29:34,524 INFO  [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-2) Changed source files detected, recompiling [/project/user-app/src/main/java/com/example/kabanero/GreetingResource.java, /project/user-app/src/main/java/com/example/kabanero/GreetingService.java]
[Container] 2020-07-29 06:29:34,635 INFO  [io.quarkus] (Quarkus Main Thread) example stopped in 0.001s
[Container] __  ____  __  _____   ___  __ ____  ______ 
[Container]  --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
[Container]  -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
[Container] --\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
[Container] 2020-07-29 06:29:34,638 WARN  [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-2) Using Java versions older than 11 to build Quarkus applications is deprecated and will be disallowed in a future release!
[Container] 2020-07-29 06:29:34,857 INFO  [io.quarkus] (Quarkus Main Thread) example 1.0-SNAPSHOT on JVM (powered by Quarkus 1.6.0.Final) started in 0.219s. Listening on: http://0.0.0.0:8080
[Container] 2020-07-29 06:29:34,857 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
[Container] 2020-07-29 06:29:34,858 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, smallrye-metrics]
[Container] 2020-07-29 06:29:34,858 INFO  [io.qua.dep.dev.RuntimeUpdatesProcessor] (vert.x-worker-thread-2) Hot replace total time: 0.346s 
```

## Appsody でKubernetes クラスタにデプロイ
ここまでで、Codewind さんの出番はほぼ終わりです。ここからは、`appsody` コマンドを使用してデプロイしていきます。
まずは、`kubectl` でコンテキストを適切に設定しておきましょう。

### Appsody Operator のインストール
`appsody` でのデプロイでは、AppsodyApplication というカスタムリソースを用います。
そのため、Kubernetes クラスタにAppsody Operator をインストールする必要があります。

```sh
appsody operator install
```

### ワンライナーでデプロイ
通常、Kubernetes クラスタへのデプロイには、以下のようなステップを踏む必要があります。

0. Docker イメージをビルド
1. Docker イメージをDocker レジストリにプッシュ
2. Deployment リソースをKubernetes クラスタに作成

`appsody` コマンドではこれらをワンライナーで済ませられます。

```sh
# --push-url のデフォルトは、Docker Hub
appsody deploy -t <namespace>/<repository>[:<tag>] --push --push-url <registry-url>
```

### プライベートなDocker レジストリのイメージを使用してデプロイ
ワンライナー簡単でとっても便利なんですが、プライベートなDocker レジストリを使用したい場合は罠があります。
具体的には、Service Account (`default`) に`ImagePullSecrets`を指定するだけでは、Pod が`ImagePullBackOff` で起動できません。（めちゃくちゃハマった）
Appsody Operator によってDeployment が作成されることに起因しているのかなぁと想像しています。

#### 1. `appsody build` してAppsodyApplication マニフェストファイルを作成
以下コマンドを実行して、`app-deploy.yaml` を作成します。
ついでにDocker レジストリにプッシュします。

```sh
appsody build -t <namespace>/<repository>[:<tag>] --push --push-url <registry-url>
```

#### 2. `app-deploy.yaml`を編集
`spec.pullSecret` に`docker-registry` タイプのSecret 名を指定します。

#### 3. `appsody deploy` でデプロイ
以下コマンドを実行して、デプロイを行います。

```sh
appsody deploy -t <namespace>/<repository>[:<tag>] --push-url <registry-url> --no-build
```

## `kubectl` でリソースを確認
`kubectl get appsodyapplication` で作成されたAppsodyApplication が確認できます。
また、関連してDeployment, Service などの作成も確認できます。
NodePort が作成されているため、簡単にアプリにアクセス可能です。

## まとめ
- 今までは、`docker` / `kubectl` をたくさん叩く必要があったが、`appsody` で一本化できるのはいい感じ
- Codewind の存在で、IDE にこもって作業ができるのもいい感じ
- アプリが大きくなるにつれて、Docker を使ったホットリロードが重くならないかが気になる
- `spec.pullSecret` の追記はKustomize でさくっとやりたいので、結局デプロイは`kubectl apply` になりそう
- Jetbrains 信者としては、Codewind で選択できるAppsody テンプレートがJava プロジェクトのみなのは解せない😡

## 余談
今回はQuarkus アプリを作成してみたが、ビルドでハマった。
Quarkus のネイティブビルドはめちゃくちゃメモリ食い虫でかつ、Appsody はDocker のマルチステージビルドでネイティブビルドするため、Docker への割り当てメモリが足りなくてエラーになっているようだった。
Docker に16GB 割り当てるとエラーは解消した。（Quarkus くん…😢）

[参考]
https://medium.com/analytics-vidhya/maybe-native-executable-in-quarkus-is-not-for-you-but-it-is-awesome-967588e80a4

ということもあるので、ちゃんとDevOps 環境整えてAWS CodePipeline 、Code Build とかでビルドするようにしましょう。