当我有正在进行的 HTTP 请求时,如何防止 Kubernetes 中的 Elixir pod 被关闭

How do I prevent my Elixir pod in Kubernetes from getting taken down while I have in flight HTTP requests

我们的 Phoenix 应用程序中有一些支付端点的超时时间为 153 秒。这些环绕 CardConnect Bolt API 需要很长超时的端点。

支付端点中断会导致双重收费,我们希望尽可能避免这种情况。

我认为这有两个部分。

  1. 停止 GKE 向 pods 运行 旧图像发送新请求,一旦我有一个部署了新图像的 pod
  2. 让旧的 pod 保持活动状态,直到 153 秒过去,让所有这些支付端点在那里完成工作。

#1 可能是 Kubernetes 配置,#2 可能是 Kubernetes 和 phoenix 配置。

我看到的唯一能部分解决这个问题的是 pod https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#podspec-v1-core.

terminationGracePeriodSeconds

这似乎是一个常见问题,但搜索文档对我来说并没有什么收获。

Kubernetes 有服务。服务具有用于匹配 pods 的选择器。匹配记录存储为 Endpoint。你所描述的是可能的。让我们看看是否可以一起满足要求:

  1. 你需要确保 K8s 在关闭这个 pod 之前启动新的 pod。
  2. 你需要确保 K8s 有探测器来检查新的何时可以开始服务连接(然后它将被添加到 Endpoint 对象并删除旧的)。从 Endpoint 中删除它不会断开打开的 TCP 连接。它只是阻止新的进入旧的 pod。
  3. 您需要让 运行 pod 有足够的时间在开始关闭之前完成飞行中的请求。
  4. 您需要允许 Kubernetes 在 pod 超过运行中时间加上充足的关闭时间时终止它。

现在进入 YAML

apiVersion: v1
kind: Service
metadata:
  name: web-app
  namespace: default
spec:
  ports:
    - name: web
      port: 8080
      protocol: TCP
      targetPort: web
  selector:
    app: web-app
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web-app
  name: web-app
  namespace: default
spec:
  revisionHistoryLimit: 1
  replicas: 1
  selector:
    matchLabels:
      app: web-app
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - image: nginx:latest
          imagePullPolicy: IfNotPresent
          name: web-app
          lifecycle:
            # This "sleep" preStop hook delays the
            # Pod shutdown 
            preStop:
              exec:
                command:
                  - /bin/sleep
                  - "154" # The max timeout for in flight requests + plus 1 second
          readinessProbe:
            initialDelaySeconds: 5
            periodSeconds: 3
            failureThreshold: 3
            successThreshold: 1
            httpGet:
              port: web
              path: /
          livenessProbe:
            initialDelaySeconds: 10
            periodSeconds: 10
            failureThreshold: 1
            successThreshold: 1
            httpGet:
              port: web
              path: /
          ports:
            - containerPort: 80
              name: web
              protocol: TCP
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      terminationGracePeriodSeconds: 155  # sleep period plus the shutdown time

试试这个,看看它是否适合你。