<h2>Issue</h2>
<p>I have a Redis K8s deployment that links to a separate service, with a heavily reduced manifest as follows (if more info is needed that's missing let me know):</p>
<pre class="lang-yaml prettyprint-override"><code>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: &quot;nfs-server.recs-api.svc.cluster.local&quot;
            path: &quot;/data&quot;
</code></pre>
<p>I want to regularly redeploy Redis with a new dataset, instead of updating the existing cache.
When doing a <code>kubectl rollout restart deployment/cache</code>, old Redis pods are Terminated before new Redis pods are ready to accept traffic. These new Redis pods are marked READY, and as expected the old ones are Terminated, however <code>redis-cli ping</code> on new Redis pods returns <code>(error) LOADING Redis is loading the dataset in memory</code>.
It currently takes 5-10 minutes for Redis to stop loading the dataset and be ready to accept connections, but by this point they've been READY for the same amount of time, with active traffic directed to them as old pods have been Terminated.</p>
<p>My suspicion is that because the status code for this response is 0, and so the <code>readinessProbe</code> triggers <code>READY 1/1</code> and kills the old pods, however I have not been able to find a suitable <code>exec: command:</code> that avoids this issue.</p>
<p><code>redis-cli info</code> has a <code>loading:0|1</code> line, and so I tested:</p>
<pre class="lang-yaml prettyprint-override"><code>readinessProbe:
  exec:
    command: [&quot;redis-cli&quot;, &quot;info&quot;, &quot;|&quot;, &quot;grep loading:&quot;, &quot;|&quot;, &quot;grep 0&quot;]
</code></pre>
<p>in the hope that for non 0 loading values, grep would provide a non-zero status code and fail the readinessProbe, but this didn't seem to work and had the same behavior as <code>redis-cli ping</code> with the prematurely terminating pods and loss of service until loading had completed.</p>
<h2>What I want</h2>
<ul>
<li>When deploying new Redis cache pods, I want there to be a pod ready to accept connections throughout, while the new Redis cache pods are loading dataset to memory
<ul>
<li>Ideally in the form of a tidy readinessProbe check, but fully open to any suggestions!</li>
<li>It's also possible I've misunderstood the purpose of a readinessProbe so please let me know</li>
</ul>
</li>
<li>If possible, better understand why <code>redis-cli ping</code> or other readinessProbes were still triggering a READY state for the new pods, despite non-zero status codes on <code>exec: command:</code></li>
</ul>
<p>Thanks!</p>

<p>I have investigated bitnami/redis charts and find out how do they implement liveness/readiness probe.</p>
<p>From their charts, they create a health-configmap, which contains a shell script using redis-cli ping to health check redis server, and handle responses.</p>
<p>Here is the configmap defined:</p>
<pre><code>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=$([[ &quot;$(redis-cli --version)&quot; =~ (redis-cli 5.*) ]] &amp;&amp; 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 &quot;redis.tlsCACert&quot; . }} \
        {{- if .Values.tls.authClients }}
          --cert {{ template &quot;redis.tlsCert&quot; . }} \
          --key {{ template &quot;redis.tlsCertKey&quot; . }} \
        {{- end }}
{{- else }}
        -p $REDIS_PORT \
{{- end }}
        ping
    )
    if [ &quot;$response&quot; != &quot;PONG&quot; ]; then
      echo &quot;$response&quot;
      exit 1
    fi
</code></pre>
<p>And in deployment/statefulset, just set the probe to execute this shell script:</p>
<pre><code>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 }}
</code></pre>
