LoginSignup
2
0

More than 3 years have passed since last update.

k8sのpodへのリクエスト回数を可視化する

Last updated at Posted at 2021-01-24

はじめに

k8s の勉強に何かを作ろうと思い、 k8s の pod へのリクエスト回数を可視化するアプリを作った。

レプリカセットが4の状態でリクエストを実行している様子
k8s.gif

また、レプリカセットによる pod の停止 => 起動 もこんな感じで眺めることができる。
(死んだ pod は赤くなって、新しい pod が下の方に追加される)
delete.gif

pod 上で動いているサーバーの起動、停止、API 実行をクライアント側が検知できるようにするため、以下のライブラリを利用した。
redisのpub/subの機能とwebsocket、redisを組み合わせて、サーバーからクライアントへのpush通知ができるようにした。

  • socket.io サーバー(Next.js)
    "socket.io": "^3.1.0",
    "socket.io-emitter": "^3.2.0",
    "socket.io-redis": "^6.0.1"
  • クライアント(Next.js)
    "socket.io-client": "^3.1.0",
  • API が実行されると redis のパブリッシュを実行するサーバー(golang)

このサーバーがレプリカセットで複数起動される

    "github.com/go-redis/redis/v8"
  • redis
        - image: redis:6.0

コード

流れ

APIの実行をクライアント側へpush通知する流れは以下の通り。

1) 複数の pod 上で起動される go のサーバーの API が実行されると、 redis のパブリッシュが行われる

    if err := rdb.Publish(ctx, "EXEC_API", os.Getenv("POD_NAME")).Err(); err != nil {
        fmt.Println(err)
    }

2) redis イベントを受け取った socket.io サーバーは websocket のイベントを発火

  redis.on("message", (channel, message) => {
    switch (channel) {
      case "EXEC_API":
        emitter.broadcast.emit("NOTICE_EXEC_API", message);
        break;

3) websocket のイベントを subscribe しているクライアント側で、リクエスト回数を描画する

  useEffect(() => {
    const socket = io();
    socket.on("connect", () => {
      console.log(`connected, socket_id: ${socket.id}`);
    });
    socket.on("disconnect", () => {
      console.log("socket disconnected!!");
    });
    socket.on("NOTICE_EXEC_API", (podName: string) => {
      // リクエスト回数を更新する処理
    });

これと同じ要領で、サーバーの停止、起動時にも redisのイベントをpublishし、同様の流れでクライアント側へイベント通知している。

サーバー起動時

        if err := rdb.Publish(ctx, "READY_ON", os.Getenv("POD_NAME")).Err(); err != nil {
            fmt.Println(err)
        }

サーバー停止時

    if err := rdb.Publish(ctx, "SHUTDOWN", os.Getenv("POD_NAME")).Err(); err != nil {
        fmt.Println(err)
    }

k8s

こんな感じの構成。
単一の redis の pod と、レプリカセットで複数起動される golang の pod を k8s で用意した。

screencapture-localhost-8080-applications-k8s-request-counter-emitter-2021-01-30-14_04_53.png

redis

redisは NodePort のサービスで起動した後、 kubectl port-forward svc/redis-service 6379:6379 を実行し、localhost上でlistenされるようにする。

これにより socket.io のサーバーからは localhost で redis にアクセスできるようになる。

import redis from "redis";

const client = redis.createClient(6379, "localhost");

client.subscribe("EXEC_API");
client.subscribe("SHUTDOWN");

export { client };

go のサーバーからは サービス名:port番号 で redis にアクセスする。

    rdb = redis.NewClient(&redis.Options{
        Addr: "redis-service:6379",
    })

redis の publish をする go のサーバー

勉強のために、 ingress(nginx) => service(NodePort) => deployment(nginx、golang) の構成で作った。

終わりに

やはり、実際に手元で触ってみることで理解が進んだ気がする。(作るものをどうするかでいつも悩む)
今回はローカルで動かしただけなので、これを次はちゃんとした環境にデプロイしてみる

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0