Kubernetesにシャーディングを全部押し付ける

作成者:tuna2134

自己紹介

tuna2134

  • 某大学系属校に所属しています。
  • neodyなどでbot開発をしています。
  • RT, Glow-botなどの運営に携わっています。

shardとは 1

Discordはイベント受信でwebsocketを利用している。それを僕らはゲートウェイと呼んでいる。
ただDiscordサーバ(以降はGuildと呼ぶ)が増えすぎると、サーバに対する負荷が増大してしまう!

shardとは 2

そこでシャード!
シャードはGuildをIDごとに振り分けることができ、イベントを分散して受信ができる。
そうすることでサーバの負荷を軽減することができる。

シャードIDの求め方

(GuildのID >> 22) % シャードの数

現状の問題点

人力によるノード分散、人力によるシャードの割り当てをしているせいで、Guildの導入数が増えてしまうとシャードの数を増やさないといけない。(手動k8s)
-> そのため毎回毎回nanoなどのエディターを使ってシャードの割り当てを変更せざるを得ない。

このままやり続けると死ぬ!

そこでk8sにシャーディングを委託しちゃおう!

元々の計画だと、環境変数でシャードIDを渡す方式だったが、Deploymentで動かすため環境変数を各Podずつに渡すことができない。
-> そこでシャードを管理するソフトを作成!(gRPCで取得する仕組み)

仕組み

  1. 起動時にgRPC使って、問い合わせる。ただし一定数を超えたらsleepをしないといけない。(これはDiscord APIの仕様上仕方ない)
  2. 返ってきたシャードIDで割り当てる
  3. そのあと定期的にハートビートを送る
  4. 一定時間内に来なかった場合、そのシャードIDをべつのに割り当てれるようにする

完成!

シャード割り当てソフト完成したけど、discord.pyなどを使う場合、内部をいじる必要性があり!なぜなら仕組みの1にあった「一定数を超えたらsleepをしないといけない」をd.py側が実装しているからである。
そのため本番ではいまだに使えてない。

k8sとの連携編

さて、ソフトが完成したのはいいけど、肝心のk8sとの連携ができていない。連携することによって初めて我々は苦労から逃れることができるであろう。以下がその仕組みだ。

  1. 割り当てソフトに定期的に問い合わせする。
  2. Deploymentのレプリカ数と問い合わせた際に返ってきたレプリカ数を比べる。
  3. もしもレプリカが不整合であれば、変更する。

これらをCronJob利用して実装した。

ご清聴ありがとうございました。