EKSとALBで502を起こさずデプロイする


TL;DR

ALBのターゲットをinstanceipに変更する。
ALBの 登録解除の遅延 < Podの削除遅延(preStop)に設定する。

ALB+ローリングアップデートの問題

k8sを使っているとローリングアップデートが手軽にゼロダウンタイムでデプロイする方法です。
しかし、ALB(ingress)を使っているとローリングアップデート中の一部のアクセスが502になってしまいます。

いくつかissueが上がってますが、まだopen状態です。
https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues/1065
https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues/1131

色々試してみた結果、502を回避してデプロイする方法が見つかったので共有します。

ダウンタイムなしでデプロイする方法

  • ターゲットの種類(target-type)をipにする
    • Pod毎にIPが設定される(セカンダリプライベートIP)
    • ALBのターゲットがNodeのIPとポート(NodePort)からPod毎のIPとポートになる
  • ALBの 登録解除の遅延 < Podの削除遅延(preStop)に設定する

example.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "example-ingress"
  annotations:
    kubernetes.io/ingress.class: alb
    # annotations: https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-path: /
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: "5"
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: "3"
    alb.ingress.kubernetes.io/healthy-threshold-count: "2"
    alb.ingress.kubernetes.io/unhealthy-threshold-count: "2"
    alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=10
    alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=10
  labels:
    app: "example-ingress"
spec:
  rules:
    - http:
        paths:
          - path: /*
            backend:
              serviceName: "example-service"
              servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  type: NodePort
  selector:
    app: example
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
        - name: example
          image: nginx:alpine
          resources:
            limits:
              memory: "128Mi"
              cpu: "128m"
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 1
            periodSeconds: 10
            timeoutSeconds: 3
            successThreshold: 2
            failureThreshold: 2
          lifecycle:
            preStop:
              exec:
                command: ["sh", "-c", "sleep 20"]

最後に

まだまだk8s周りのツールはバグ等が多いので、頑張って追っていく必要がありそう