Google Kubernetes Engine 上で Spring Boot を動かしてみる

高幡不動のあじさい

先日、珈琲仲間に誘われて高幡不動のあじさいを観に行ってきました。
あいにくの雨でしたが、色んな種類のあじさいが綺麗に咲いていて心が洗われました。

写真の右側のようなあじさいを「がくあじさい」と呼ぶそうです。
これまで中央部分が単に咲いていない(これから開花する)んだと思ってた… (´▽`*)

meet K8s

その内、GCPがAWSのシェアを塗り替えるんじゃないかと思っているのと
DockerやKubernetesとうワードを見かけない日がないので
GCP上でKubernetesを触って理解を深めたいと思います。


2018/8/1 追記
世界的にシェアを見ればAWS、Microsoft、Googleの順なんですね!
Alibabaの勢いもすごい…


Dockerとは

Docker enables true independence between applications and infrastructure and developers and IT ops to unlock their potential and creates a model for better collaboration and innovation.

Containers are an abstraction at the app layer that packages code and dependencies together. Multiple containers can run on the same machine and share the OS kernel with other containers, each running as isolated processes in user space. Containers take up less space than VMs (container images are typically tens of MBs in size), and start almost instantly.

Docker 社が開発しているコンテナ型の仮想環境を作成/配布/実行するためのプラットフォーム。
「コンテナ」と呼ばれる技術によりホストマシンのカーネルを利用しプロセスを隔離することで、あたかも別のマシン上のように動かすことができる。
ゲスト OS をインストールした上でミドルウェアやライブラリ、アプリケーションを動かすハイパーバイザ型やホスト型の仮想実行環境と比べリソースを効率的に利用できるのが特徴。

開発環境の準備/統一に便利だな〜くらいの認識でしたが、最近は運用にも使われているよう。
まさしく DevOps ですね。

ハイパーバイザ型やホスト型の仮想実行環境を使うことが多いのですが
確かに時間もリソースもかかるので、そこが簡略できるのはとても魅力的。

Kubernetes とは

It has a large, rapidly growing ecosystem.
Kubernetes provides a container-centric management environment. It orchestrates computing, networking, and storage infrastructure on behalf of user workloads. This provides much of the simplicity of Platform as a Service (PaaS) with the flexibility of Infrastructure as a Service (IaaS), and enables portability across infrastructure providers.

コンテナオーケストレーションツールと称される Kubernetes。
コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を行うために用いる。
コンテナオーケストレーションツールは Kubernetes の他に、Docker Swarm や Apache Mesos などがある。

Kubernetes はクラスターが強力なのだそう。
GUI が用意されているし、オートスケーリングやロードバランシング、ヘルスチェック以外で自己修復もしてくれる。

オーケストレーション、賑やかな印象を受けます。

Kubernetes Clusters とは

Kubernetes のアーキテクチャについてはTHENEWSTACKさんの図がわかりやすいです。
#ぱっと見た中では公式サイトのドキュメントから概要図を見つけられませんでした。

a Kubernetes cluster consists of at least one master and multiple compute nodes. The master is responsible for exposing the application program interface (API), scheduling the deployments and managing the overall cluster. Each node runs a container runtime, such as Docker or rkt, along with an agent that communicates with the master. The node also runs additional components for logging, monitoring, service discovery and optional add-ons. Nodes are the workhorses of a Kubernetes cluster. They expose compute, networking and storage resources to applications. Nodes can be virtual machines (VMs) running in a cloud or bare metal servers running within the data center.
A pod is a collection of one or more containers. The pod serves as Kubernetes’ core unit of management. Pods act as the logical boundary for containers sharing the same context and resources. The grouping mechanism of pods make up for the differences between containerization and virtualization by making it possible to run multiple dependent processes together. At runtime, pods can be scaled by creating replica sets, which ensure that the deployment always runs the desired number of pods.

Kubernetes のクラスターは少なくとも 1 つのマスターと複数のノードから構成されており、マスターは API の公開、デプロイのスケジューリング、すべてのクラスタの管理を行います。
各ノードは Docker などのコンテナとマスターと通信するエージェントを実行します。加えて、ロギング、モニタリング、サービス検出やオプションのアドオンなど追加のコンポーネントも実行します。
ポッドは 1 つまたは複数のコンテナをグループ化します。このグループ化におけるメカニズムは、複数の依存プロセスを一緒に実行できるようにすることで、コンテナ化と仮想化の違いを補っています。実行時、ポッドはレプリカセットを作成することでスケールを可能にします。

…大雑把に言えば、マスターの配下にポッド、レプリカセット、サービス等 Kubernetes オブジェクトがありロードバランシングを可能にしてしてくれているんですね。

実際に触ってみる

なんとなく概要をみたところで GCP のチュートリアルにトライします。
書いてあることを実行する中で 2 点エラーが発生したのでそこを中心に明記します。

Dockerizing your application

Creating a Dockerfile

ローカルでビルドした際にはうまくいったのですが、GCP でビルドを行った際に gradlew に権限がないとエラーが発生しました。

そこで実行権限を付与することで対応しました。

1
2
3
4
5
6
7
8
9
10
// Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
RUN mkdir /work
COPY . /work
WORKDIR /work
RUN chmod +x /work/gradlew
RUN /work/gradlew build
RUN mv /work/build/libs/*.jar /work/app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/.urandom", "-jar", "/work/app.jar"]

Create a cluster

クラスターを作成する際にzoneregionを指定してと言われました。

こちらは--zone=asia-northeast1をつけることで対応。
参照 => gcloud container clusters create

Deploy to the cluster

ポッドをデプロイ、デプロイしたポッドをロードバランシングで公開します。

EXTERNAL-IP に割り当てられたアドレスにアクセス、動作していることが確認できました。

Scaling and updating your application

Set the replica count

レプリカセットの値を 3 から 2 へ変更します。
スケールされていることが確認できました。

まとめ

難しいと思っていた K8s ですが、触るだけなら簡単にできました。GCP のおかげですね!
動かすアプリケーションの規模が小さいこともあり、スケーリングの恩恵はあまり感じられませんでしたが、それでもお手軽さは感じることができました。

クラウド化による Paas、IaaS でもすごいと感じるのに
さらにコンテナ化したものをオーケストレーションする技術まで出てきて
クラウドの技術革新には目を見張ります。

そもそも開発体制として Docker を導入していないので
Kubernetes を業務で扱うことはないだろうけど
社内ツール類をコンテナ化してまとめられたらすっきりしそう。
弊社は(お客様の)鶴の一声がないと新しいツールの導入はまずないので難しいかな…。
少しでも便利に、安定に、なサイクルを模索していきたいところ。

The DevOps ハンドブック、読み始めました。

参考

ごみ収集日前にアラートを出すLINEbot

meet line-bot

最近 引越をした友人から「ごみ出しリマインダーを作って」と言われ模索することに。

ポイントは既存かつよく使用するアプリでリマンドできること。
APIもSDKも用意されているLINEがぴったりだと思い、挑戦しました。

構想

  • Springのスケジュール機能(cron)を使って、ごみ収集日前に該当者へリマインドをプッシュ
  • 該当者から何かメッセージが来たらレスポンス
  • ごみ捨てが終わっていたら褒め、まだだったら捨てようねと励ます(大事)

レスポンスに応対する箇所は「Webhook」、リマインド箇所は「Messaging API」で実装します。

環境

  • jdk1.8
  • Spring Boot
  • Heroku

herokuでアプリケーションの作成、LINEでチャンネルの作成、Webhookの有効化、Webhookのurlの登録が必要です。

SDKの使い方に慣れる

まずLINEでチャンネルを解説し
SDKのページにあるサンプル「echo」をherokuにデプロイし、エコーバックを楽しみました。
続いてサンプル「kitchensink」をherokuにデプロイしどのように作ればいいかを理解。
機能が網羅されているので、掴みやすかったです。

プロジェクト構成

依存関係

1
2
3
4
5
<dependency>
<groupId>com.linecorp.bot</groupId>
<artifactId>line-bot-spring-boot</artifactId>
<version>1.11.0</version>
</dependency>

LINE Messaging API SDKを追加します。

プロパティ

1
2
3
line.bot.channelSecret = XXXXX
line.bot.channelToken = XXXXX
line.bot.handler.path = /callback

LINEで開設したチャンネルの情報を設定します。

プッシュの実装

confirm.png
ごみ出しが完了したか確認するため、確認テンプレートを使用します。

コントローラ化する必要はありませんが、GETで呼び出せるようにすると確認する時に楽です。

余談ですが作っている当初、この部分ははSDKを使わずに地道実装していました…w
#こちらでも動作はします。

レスポンスの実装

Webhookはメッセージやスタンプなど何か送られた際に応答を返すことができます。
確認で「はい」もしくは「いいえ」が返却されるようにしたので、この2つのワードを拾い
スタンプとメッセージを返すようにします。

replyにreplyTokenとメッセージを設定します。
メッセージはコードに記述しているようにリストで複数設定することができます。

スケジューリング

Springのスケジュール機能@Scheduledを利用します。

※@EnableSchedulingアノテーションをmain関数のあるクラスにつけるのを忘れずに

備考

環境変数

1
2
3
4
line.bot.channelSecret = ${LINE_BOT_CHANNEL_SECRET}
line.bot.channelToken= ${LINE_BOT_CHANNEL_TOKEN}
cron.setting = ${LINE_CRON}
garbage.reminder.id = ${LINE_ID}

環境変数は全てherokuに持たせるようにしました。
コンソールで変更できるのでらくちんですね!

botのアイコン

アイコンはtabagotchiから拝借。
お気に入りの拡張機能です

動作確認

まとめ

SDKを使用すると、すっきり書けて楽ですね。

自前実装ではOkHttp3ClientHttpRequestFactoryを用いたRestTemplateの実装ができました。
こういう小さな達成感は大事(笑

楽しく書けました X)
あとは気に入ってくれるといいなぁ

ソースコード

https://github.com/aytdm/garbage-reminder-bot

参考