Common Runbooks
Recurring operational procedures for the DataReadyAI platform team running the Nexa clusters. Each runbook assumes you have kubectl access to the target EKS cluster, ArgoCD access, and write access to the relevant repo. These cover the DataReadyAI-operated environments; they are distinct from the customer-facing operations guide.
Background you should have first: images are built and pushed by CI/CD with branch-per-env tags, and rolled out by ArgoCD from nexa-deployments. Most of these procedures are git edits, not kubectl apply — the cluster is reconciled from git.
Deploy a new service
Section titled “Deploy a new service”Adding a new containerized service means wiring it into both the build pipeline and the GitOps flow.
-
Add the build pipeline. In the service repo, copy the
build-push-ecr.ymltemplate from an existing service (e.g.nexa-slackbot-service). Ensure the ECR repositoryaws-iac-<service>exists — it is declared inaws-iac(modules/ecr/), so add it there and apply if missing. -
Grant image pull / cloud identity. Add a Pod Identity association (AWS) or Workload Identity federated credential (Azure) for the service’s ServiceAccount in the IaC repo, scoped to its Secrets Manager / Key Vault secret. See AWS vs Azure.
-
Create the base manifests. In
nexa-deployments/base/<service>/, adddeployment.yaml,service.yaml,httproute.yaml,security-policy.yaml,traffic-policy.yaml, andkustomization.yaml. Give theHTTPRoutea unique path prefix and the correct backend port. -
Create the overlay. In
nexa-deployments/overlays/dev/<service>/, addkustomization.yaml(withnamePrefix: dev-and the ECRimages:block),namespace.yaml,service-account.yaml,secret-provider-class.yaml, and the patch files. -
Register the ArgoCD Application. Add
argocd/applications/<service>-dev.yamlwithtargetRevision: develop, the destination namespace,automatedsync, and theargocd-image-updaterannotations (update-strategy: newest-build,allow-tags: regexp:^develop-.*$,write-back-method: git). The dev app-of-apps (*-dev.yamlglob) picks it up automatically. -
Merge and verify. Merge to
develop. Confirm the child Application appears and syncs Healthy in ArgoCD, and that the route resolves through the gateway.
Roll back an image
Section titled “Roll back an image”Because image tags are pinned in git (via argocd-image-updater git write-back), a rollback is a git revert, not a kubectl edit.
-
Find the last-good tag. In the overlay, open
overlays/<env>/<service>/.argocd-source-<service>-<env>.yaml(or thekustomization.yamlimages:block) and look at the git history for the previousdevelop-<sha>/release-<sha>tag. -
Pin the previous tag. Edit the
newTag(or the.argocd-sourcekustomize.imagesentry) back to the last-good tag and commit to the environment’s branch. Do not just delete the newer image. -
Pause auto-update if needed. If image-updater would immediately re-bump to the bad newest build, temporarily set the app’s
allow-tagsto pin the specific tag, or disable the updater annotation, until the bad image is removed from ECR. -
Sync. For dev/test, ArgoCD self-heals to the pinned tag. For prod, trigger the manual sync in ArgoCD.
-
Verify the pods are running the expected digest (
kubectl -n <ns> get pods -o jsonpathon the image field) and the service is healthy.
Verify or rotate the TLS certificate
Section titled “Verify or rotate the TLS certificate”The gateway certificate is a cert-manager-issued wildcard *.nexa-drai.com from Let’s Encrypt via DNS-01 over Route53. It auto-renews (rotationPolicy: Always, ~90-day duration, renews ~30 days before expiry), so routine rotation is automatic — this runbook is for verifying that, or forcing a reissue.
-
Check certificate status:
Terminal window kubectl -n envoy-gateway-system get certificate nexa-gateway-tls-devkubectl -n envoy-gateway-system describe certificate nexa-gateway-tls-devREADY: Trueand a futureNot Aftermean it is healthy; no action needed. -
If issuance is stuck, inspect the
CertificateRequestandOrder/Challenge:Terminal window kubectl -n envoy-gateway-system get certificaterequest,order,challengekubectl -n envoy-gateway-system describe challenge <name>DNS-01 failures usually mean the Route53 permission (Pod Identity for cert-manager) or the hosted zone ID is wrong — check the
ClusterIssuerletsencrypt-prod-dns01. -
Force a reissue (only if you must rotate early) by deleting the Secret so cert-manager re-requests:
Terminal window kubectl -n envoy-gateway-system delete secret nexa-gateway-tls-devcert-manager reissues into the same Secret name; the
GatewaycertificateRefspicks it up.
Add a secret key to a service
Section titled “Add a secret key to a service”Secrets are delivered by the Secrets Store CSI driver from AWS Secrets Manager (or Key Vault on Azure). A new environment variable must be added in two places or the pod will not see it.
-
Add the key/value to the backing AWS Secrets Manager secret (
nexa-shared-secret-<env>for shared keys, or the service’s own<service>-<env>secret). Do not commit secret values to git. -
In the service’s overlay
secret-provider-class.yaml, add the key underobjects(the JMESPath extraction) and undersecretObjects(so it syncs into the k8s Secret consumed viaenvFrom). -
Commit the overlay change, let ArgoCD sync, and restart the deployment so the CSI volume remounts:
Terminal window kubectl -n <ns> rollout restart deployment/<name>
-
Add the secret to the service’s Key Vault.
-
Update the overlay
SecretProviderClass(Azure provider)objectsandsecretObjectsto include the new key. -
Commit, let ArgoCD sync, and
kubectl rollout restartthe deployment so the mounted secret refreshes.
There is no cross-namespace secret sharing — each service reads its own synced Secret. See GitOps & Deployments for the SecretProviderClass structure.
Restart or inspect a workload
Section titled “Restart or inspect a workload”Quick reference for the day-to-day checks:
# List a service's pods and their imagekubectl -n <ns> get pods -o wide
# Tail logskubectl -n <ns> logs deploy/<name> -f
# Restart (picks up new secret mounts / forces reschedule)kubectl -n <ns> rollout restart deploy/<name>
# Check the gateway routeskubectl -n envoy-gateway-system get gateway nexa-gatewaykubectl get httproute -ANamespaces follow the <service>-<env> pattern — web-dev, backend-dev, databricks-prod, agents-dev, and so on. If a service is unreachable but pods are Healthy, check its HTTPRoute path prefix and the nexa-gateway listener before touching the deployment.