Run more than one replica¶
Run the issuer (sluis issuer) at two or more replicas so a node loss or a rollout stops neither sign-in nor reconciling.
Before you start¶
-
Every replica needs a shared State:
config.ports.adapter: dynamodbor thek8s-awspreset. Alegacycluster moves first (migrate the State, cutover). -
Every replica needs a signing key:
signingKey.existingSecret, the chart'sCertificate, or a KMS-wrapped key on AWS. -
The chart refuses
replicaCountabove 1 with a controller unless the adapter isdynamodb. Without a controller,legacywithvalkey.addressshares the issuer's state. -
A replica on a process-local store looks like an intermittent failure. Its log says
keeping logins in progress in memory: correct for one replica. -
The chart renders no PodDisruptionBudget, anti-affinity or topology-spread rule, and
values.schema.jsonrefuses anaffinitykey. Add them yourself. -
Keep the default
RollingUpdate.Recreatedeletes the old pod first, and a pod that crashes at start never becomes Ready (check health). -
Add no caching header to
/keysin front of the service.
Steps¶
-
Set
replicaCount: 2or more in the values and render. Withlegacyand a controller the render fails namingconfig.ports.adapter. -
Apply a PodDisruptionBudget of your own. For anti-affinity, use a Helm post-renderer or a
kustomizepatch overhelm template.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: sluis
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: sluis
app.kubernetes.io/instance: <the release name>
- Roll out.
kubectl -n <namespace> rollout status deploy/<release>
- To run one tick by hand, use
sluis tick <github|slack> <target> --config <file>. It runs once under the target's lease and acts only where the target is enabled (enable an organisation). Withlegacyit refuses unless the controller is scaled to 0 and you pass--unsafe-local-lease.
Verify¶
kubectl get pdb shows ALLOWED DISRUPTIONS of 1, and draining a node in a test cluster leaves one replica Ready. Both pods log keeping state in DynamoDB. sluis.leases.contended is non-zero while SluisLeaseLost stays quiet (telemetry).
/healthz is liveness and checks nothing outside the process. /readyz follows the State: periodSeconds: 10, timeoutSeconds: 3, failureThreshold: 3. A replica leaves rotation within about thirty seconds.
Roll back¶
Set replicaCount: 1 and roll out. Each replica sweeps every interval, so two replicas make about twice the GitHub and Slack API calls.