最近勉強も兼ねておうちサーバーにKubernetesを構築したのですが、 おうちkubernetesクラスタあるある「特にデプロイするものがない」が当たり前のように発動してしまいました。 せっかくなら自分でアプリケーションを作ってデプロイ、したいですよね(というかその勉強も目的のうちの1つなのだった。)
最近偶然Discordbotを作ってk8sに上げる機会ががあったのでついでにチュートリアルとして記事にまとめておくことにしました。 極力複雑なことを省いて、ひとまず動く状態まで持っていくというコンセプトになります。
今回作るDiscordBot
サンプルとして、約1分ごとにランダムな犬の画像を投稿するDiscordbotを作ってみましょう。 言語はpythonを使うことにします。 最終形はGithubのレポジトリとして上げてあるので併せて参考にしてください。
ランダムな犬の画像は、Dog APIを使います。
前準備として、DiscordDevelopeprPortalでBotを発行し、テスト用のサーバーに招待を行っておいてください。
Permissionは
- GENERAL PERMISSIONS - Messages/View Channels
- TEXT PERMISSIONS - Send Messages の2つを許可しておきます。
また、そこでBotTokenも併せて発行します(後で使います)
コード
botのコードはこんな感じになると思います。 bottokenとchannelIDを環境変数に設定して動作確認してみてください。
|
|
(pip3 install discord aiohttp asyncioするのお忘れなく!)
コンテナ化
k8s上に乗せるためにはDockerコンテナ化する必要があります。 かんたんにDockerfileを書きます
|
|
おすすめなのはgithub actionsでコンテナ化してghcrにアップロードしてしまうことです。 Actionsを追加するときに出てくるテンプレート一覧にある「Publish Docker Container」が便利です。
Manifestの作成
次にk8sのManifestを書きます。 今回はシンプルに1つpodを作成するDeploymentにしちゃいます。
|
|
今回はデプロイにargocdを使うので(そうじゃなければすぐkubectl applyしてしまえばおしまいですね)これもgithubに上げます。 ベストプラクティスとしてはアプリ本体のレポジトリとマニュフェストを管理するレポジトリは分けたほうがいいのですが(これは実際に 混ぜて運用してみると、明らかに分けたほうが良いことがわかると思います)、今回はシンプルなアプリということと、例ということで混ぜちゃいました。
僕はレポジトリの/manifests/deployment.yamlにこれを保存しました。
Secretのデプロイ
discordのbottokenをgithubに上げるわけにはいきません。 この辺はもっと良い仕組みを使ったほうがいいだろうな~と思いつつ、今回は手動で別途クラスタに登録することにします。 以下のmanifestでsecretを作成して、手動でkubectl applyします。
|
|
アプリ本体をArgoCDを使ってデプロイ
お待ちかねのデプロイタイムです! とは言え、argocdでポチポチするだけですね。
実際にポチポチしたら、アプリがちゃんとデプロイされて、discordチャンネルが犬の画像まみれになるはず!
liveness probeの追加
このbotはとても適当なので、例えば時間が立つとセッション切れとかで動作を止めてしまいます。 そういう部分を1つ1つ直してもいいのですが(本当は直したほうがいいのですが)、それはそれとして 「今ちゃんと正常に動作しているか?」を観測して、そうでなければコンテナを再構築するという手もあります。
一見雑な荒療治のように見えますが、「ソフトウェアが永久にサービスを提供し続けること」を保証することはとても難しいのに対し、 「起動後しばらくはサービスを提供すること」かつ「今正常にサービスを提供できているかを観測すること 」というのはちょっとだけまだ着手しやすいことがあります。
k8sでもそういうことを簡単に提供してくれる機能があって、それがliveness probeですね。
今回は、livenessprobeの中でもコンテナ内で一定時間ごとにコマンドを実行するexecを使います。
discordにpostする時に合わせて特定の空ファイルを生成しておいて、逆にliveness probeではそれを削除していくことで、ちゃんとpostしてるかどうかを確認します。
空ファイルを作るコード
|
|
livenessProbeを追加したdeployment.yaml
|
|
livenessProbeに失敗するとコンテナを自動で殺して作り直してくれます。 これで「あれ?なんか死んでるっぽい?プロセス再起動するか…」っていう作業から開放されると思うと、ちょっと新鮮な気持ちになりますね。
振り返り
こういうことをやってみると、そろそろpip3とかをローカルで叩いている場合ではなく、最初からdockerで環境作ってやったほうがいいかもしれませんね(すでに流行に乗り遅れている感)。
ちょっとテストで動かして終わりではなく、サービスとして動かす前提の開発ができると良さそうです。