5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

kubernetesでenvoy使ってgRPCしながら終了時にパケットロストしない方法

Posted at

概要

kubernetesでmicroservicesアーキテクチャを採用している場合、envoyでgRPC通信するケースが多いかと思います。詳しくはこちらの記事を。
そんなときに瞬断の影響が大きいサービスを運用している場合、アプリをシャットダウンするタイミングで何も考えないで運用しているとパケットをロストします。

これは、serviceから切り離される前にPodが終了してしまうことや、Podに対して終了シグナルが送られた場合に、アプリより先にenvoyが終了しちゃう事などで発生します。
これはサイドカーしている他のコンテナでも同様のことが言えます。

対策

grpcはhttp2の通信なのでコネクションを永続化します。つまりserviceから張られていたコネクションは処理中のものも含めて切断されてしまいます。

それを避けるためには
① serviceから当該Podへの新規のコネクションを止める
② すべての処理が終わるまですべてのコンテナを落とさない
を行う必要があります。

しかしながら②を実現することは困難なので sleep 30 で妥協することにしました。
30秒程度あればすべての処理は終了するだろうという考えです。

事前準備

まず、複数のコンテナ間で状態を共有するためにunhealthyという名前の共有volumeを作成します。

これを各コンテナの /tmp にマウントしておきます。
ここに状態共有のための情報を書き込みます。

appコンテナの挙動

appコンテナはSIGTERMを受け取ると /tmpunhealthy というファイルを作成し30秒sleepします。

同時に unhealthy がある場合は readinessProbe を失敗させ、serviceから切り離します。

envoyはheadless servicesを利用してバランシングしているので、このPodに対して新しいコネクションは張られなくなります。

envoyコンテナの挙動

envoyコンテナはSIGTERMを受け取ると unhealthy ファイルを発見するまでループします。
これでappコンテナが終了するよりも前にenvoyコンテナが終了することを防ぎます。
unhealthy ファイルを発見したら、こちらも同様に30秒sleepします。

30秒後に両コンテナが完全に終了するという流れになります。

具体的には下記のようなyamlになります。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: app
spec:
...
      containers:
      - name: sidecar-envoy
        image: envoyproxy/envoy:v1.7.0
...
        volumeMounts:
        - name: unhealthy
          mountPath: /tmp
          readOnly: true
        lifecycle:
          preStop:
            exec:
              command:
              - sh
              - -c
              - while (! test -e /tmp/unhealthy); do sleep 1; done; sleep 30
      - name: app
        image: path/to/app:latest
...
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - exit `! test -e /tmp/unhealthy; echo $?`
          initialDelaySeconds: 5
          timeoutSeconds : 3
          periodSeconds: 3
          failureThreshold: 1
        lifecycle:
          preStop:
            exec:
              command:
              - sh
              - -c
              - touch /tmp/unhealthy; sleep 30
      volumes:
      - name: unhealthy
        emptyDir: {}

initialDelaySeconds とか timeoutSeconds あたりは短めにしてるって程度で深い意味はありません!
これでHappy gRPC lifeを!!

5
5
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
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?