具有大型数据集的 Redis 就绪探针

Mar*_*arc 5 redis kubernetes

问题

我有一个 Redis K8s 部署,链接到一个单独的服务,清单大幅减少,如下(如果需要更多信息,请告诉我):

apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cache
      environment: dev
  template:
    metadata:
      labels:
        app: cache
        environment: dev
    spec:
      containers:
        - name: cache
          image: marketplace.gcr.io/google/redis5
          imagePullPolicy: IfNotPresent
          livenessProbe:
            exec:
              command:
              - redis-cli
              - ping
            initialDelaySeconds: 30
            timeoutSeconds: 5
          readinessProbe:
            exec:
              command:
              - redis-cli
              - ping
            initialDelaySeconds: 30
            timeoutSeconds: 5
      volumes:
        - name: data
          nfs:
            server: "nfs-server.recs-api.svc.cluster.local"
            path: "/data"
Run Code Online (Sandbox Code Playgroud)

我想定期使用新数据集重新部署 Redis,而不是更新现有缓存。当执行 a 时kubectl rollout restart deployment/cache,旧的 Redis Pod 在新的 Redis Pod 准备好接受流量之前被终止。这些新的 Redis pod 被标记为 READY,并且正如预期的那样,旧的 pod 被终止,但是redis-cli ping在新的 Redis pod 上返回(error) LOADING Redis is loading the dataset in memory。目前,Redis 需要 5-10 分钟才能停止加载数据集并准备好接受连接,但此时它们已准备好相同的时间,并且随着旧 Pod 已终止,活动流量将定向到它们。

我的怀疑是,由于此响应的状态代码为 0,因此会readinessProbe触发READY 1/1并杀死旧的 pod,但是我一直无法找到合适的方法exec: command:来避免此问题。

redis-cli info有一条loading:0|1线,所以我测试了:

readinessProbe:
  exec:
    command: ["redis-cli", "info", "|", "grep loading:", "|", "grep 0"]
Run Code Online (Sandbox Code Playgroud)

希望对于非 0 加载值,grep 将提供非零状态代码并使 readinessProbe 失败,但这似乎不起作用,并且具有与redis-cli ping过早终止 pod 和服务丢失相同的行为,直到加载完成完全的。

我想要的是

  • 部署新的 Redis 缓存 Pod 时,我希望有一个 Pod 随时可以接受连接,同时新的 Redis 缓存 Pod 正在将数据集加载到内存中
    • 理想情况下以整洁的就绪探针检查的形式进行,但对任何建议完全开放!
    • 我也可能误解了 readinessProbe 的目的,所以请让我知道
  • 如果可能,更好地理解为什么redis-cli ping其他 readinessProbe 仍然触发新 Pod 的 READY 状态,尽管上有非零状态代码exec: command:

谢谢!

Gaw*_*ain 4

我研究了 bitnami/redis 图表,并了解它们如何实现活性/就绪性探测。

他们根据图表创建了一个 health-configmap,其中包含一个 shell 脚本,使用 redis-cli ping 来检查 Redis 服务器的运行状况并处理响应。

这是定义的配置映射:

data:
  ping_readiness_local.sh: |-
    #!/bin/bash
{{- if .Values.usePasswordFile }}
    password_aux=`cat ${REDIS_PASSWORD_FILE}`
    export REDIS_PASSWORD=$password_aux
{{- end }}
{{- if .Values.usePassword }}
    no_auth_warning=$([[ "$(redis-cli --version)" =~ (redis-cli 5.*) ]] && echo --no-auth-warning)
{{- end }}
    response=$(
      timeout -s 3 $1 \
      redis-cli \
{{- if .Values.usePassword }}
        -a $REDIS_PASSWORD $no_auth_warning \
{{- end }}
        -h localhost \
{{- if .Values.tls.enabled }}
        -p $REDIS_TLS_PORT \
        --tls \
        --cacert {{ template "redis.tlsCACert" . }} \
        {{- if .Values.tls.authClients }}
          --cert {{ template "redis.tlsCert" . }} \
          --key {{ template "redis.tlsCertKey" . }} \
        {{- end }}
{{- else }}
        -p $REDIS_PORT \
{{- end }}
        ping
    )
    if [ "$response" != "PONG" ]; then
      echo "$response"
      exit 1
    fi
Run Code Online (Sandbox Code Playgroud)

并且在deployment/statefulset中,只需设置探针来执行这个shell脚本:

readinessProbe:
    initialDelaySeconds: {{ .Values.redis.readinessProbe.initialDelaySeconds }}
    periodSeconds: {{ .Values.redis.readinessProbe.periodSeconds }}
    timeoutSeconds: {{ .Values.redis.readinessProbe.timeoutSeconds }}
    successThreshold: {{ .Values.redis.readinessProbe.successThreshold }}
    failureThreshold: {{ .Values.redis.readinessProbe.failureThreshold }}
    exec:
      command:
        - sh
        - -c
        - /scripts/ping_readiness_local.sh {{ .Values.redis.readinessProbe.timeoutSeconds }}
Run Code Online (Sandbox Code Playgroud)