Deploy the Sample App to Development
Publish a commit-addressed image and deploy it to the development Kubernetes environment.
Deploy the Sample App to Development
Expected time: 10–20 minutes after CI starts.
Outcome: The image built from an identified commit is running at https://dev.marsadlab.com/ and the GitOps overlay records the deployed revision.
This runbook deploys only sample-app to the sample-app-dev namespace. It does not deploy the main Marsad Web App, Model Server, or documentation site.
The release path is:
push to dev → GitHub Actions tests and publishes → select successful commit SHA
→ update and commit the dev overlay → apply with Kustomize → verify the rolloutThe current repository does not run a GitOps controller. Committing the overlay preserves the audit trail, but kubectl apply performs the deployment.
Before You Start
You need:
- permission to push or merge the application change into
dev; - access to the repository's GitHub Actions runs and artifacts;
kubectlconfigured for the Marsad development cluster;- permission to update Deployments and PVCs in
sample-app-dev; and - a ready
gateway-system/publicGateway,registry-credentialsSecret, andshared-data-sample-app-devstatic PV.
Run all local commands from the repository root. Confirm the cluster before changing it:
Set-Location F:\Projects\ByName\Marsad\Marsad
kubectl config current-context
kubectl auth can-i patch deployment/sample-app -n sample-app-dev
kubectl auth can-i create persistentvolumeclaims -n sample-app-dev
kubectl auth can-i patch persistentvolumeclaims -n sample-app-dev
kubectl -n sample-app-dev get secret registry-credentials
kubectl get pv shared-data-sample-app-dev
kubectl -n sample-app-dev get pvc shared-data --ignore-not-found -o yamlThe PV must be Available when no claim exists or Bound to
sample-app-dev/shared-data. Stop if the context is wrong, authorization
returns no, or either Ansible-owned prerequisite is missing.
1. Push the Application Change
Review and push the approved sample-app change to dev according to the team's branch policy:
git status --short
git branch --show-current
git push origin devThe Sample App CI workflow runs automatically for pushes to dev that change sample-app/** or .github/workflows/sample-app.yml. A push that changes only another path does not publish a sample-app image. An authorized operator can also start the workflow manually on the dev branch from GitHub Actions.
2. Confirm the Image Was Published
In GitHub, open Actions → Sample App CI and select the run for the commit you intend to deploy. Confirm both jobs succeeded:
- Test
- Build and publish Docker image
The publish job pushes two tags to Marsad's private registry. Deployment uses the immutable tag:
registry.marsadlab.com/rafiulbiswas/marsad:dev-sha-<full-commit-sha>Download the run artifact named sample-app-release-dev-<full-commit-sha> and inspect release-metadata.json. Confirm that:
environmentisdev;commitis the commit shown by the successful Actions run; andimmutable_imageends indev-sha-<the-same-full-commit-sha>.
Use the artifact's commit value as the release SHA. Do not use a shortened SHA, the mutable dev tag, a SHA from a failed run, or simply whichever commit is newest.
3. Update and Validate the Development Overlay
Open gitops/apps/sample-app/overlays/dev/kustomization.yaml and replace only the newTag value:
images:
- name: registry.marsadlab.com/rafiulbiswas/marsad
newTag: dev-sha-<full-40-character-commit-sha>Validate the SHA and render the resulting manifest before applying it:
$releaseSha = '<full-40-character-commit-sha>'
if ($releaseSha -notmatch '^[0-9a-f]{40}$') { throw 'Release SHA must be 40 lowercase hexadecimal characters.' }
Select-String -Path gitops/apps/sample-app/overlays/dev/kustomization.yaml -Pattern 'newTag:'
kubectl kustomize gitops/apps/sample-app/overlays/dev | Select-String -Pattern 'image:'
kubectl kustomize gitops/apps/sample-app/overlays/dev | Select-String -Pattern 'kind: PersistentVolumeClaim|volumeName: shared-data-sample-app-dev|mountPath: /shared-data'
kubectl apply --dry-run=client -k gitops/apps/sample-app/overlays/devThe rendered image must exactly match the immutable image recorded in
release-metadata.json, and the overlay must contain its PVC and mount. If a
shared-data claim already exists from the former Ansible ownership model,
compare its access mode, volume mode, storage class, volume name, and requested
capacity with the rendered claim. Stop if any immutable field differs; never
delete the claim to force adoption.
4. Commit the GitOps Revision
Review and commit only the intended overlay update:
git diff -- gitops/apps/sample-app/overlays/dev/kustomization.yaml
git add gitops/apps/sample-app/overlays/dev/kustomization.yaml
git commit -m "chore: deploy sample app to development"Push the commit directly or merge it through a pull request, according to the team's branch policy. Do not deploy an overlay revision that exists only in an operator's working tree. An overlay-only commit does not trigger Sample App CI because the workflow excludes gitops/** from its path filters.
5. Deploy Development
Apply the committed overlay, wait for the Deployment, and request the public endpoint:
Set-Location F:\Projects\ByName\Marsad\Marsad
kubectl apply -k gitops/apps/sample-app/overlays/dev
kubectl -n sample-app-dev get pvc shared-data
kubectl -n sample-app-dev rollout status deployment/sample-app --timeout=5m
curl.exe --fail --show-error https://dev.marsadlab.com/The claim must report Bound to shared-data-sample-app-dev. A successful
response contains "environment":"dev"; the command exits non-zero if HTTPS fails.
6. Verify the Exact Revision
Confirm that the Deployment and its Pods use the expected immutable image:
kubectl -n sample-app-dev get pvc shared-data
kubectl -n sample-app-dev get deployment sample-app -o jsonpath='{.spec.template.spec.containers[0].image}'
kubectl -n sample-app-dev get pods -l app.kubernetes.io/name=sample-app -o wide
kubectl -n sample-app-dev get httproute sample-appThe PVC must remain Bound, and the image output must end with
dev-sha-<release SHA>. All desired replicas must be available, Pods must be
Running and ready, and the route must be accepted.
If the Deployment Fails
Inspect the workload before retrying or changing the image:
kubectl -n sample-app-dev get pvc shared-data
kubectl -n sample-app-dev describe deployment sample-app
kubectl -n sample-app-dev get pods -l app.kubernetes.io/name=sample-app
kubectl -n sample-app-dev describe httproute sample-app- A
Pendingclaim means the Ansible-owned static PV is absent or its immutable binding contract differs from the GitOps claim. Do not delete either resource. - A volume mount failure usually points to NFS, CSI, export, or node access.
ImagePullBackOffusually means the tag was copied incorrectly, the publish job did not succeed, orregistry-credentialscannot read the private image.- A rollout timeout with a running container usually points to startup or readiness probe failures. Describe the failing Pod and inspect only its relevant recent logs.
- A successful rollout with a failed public request usually points to the
HTTPRoute, Gateway, certificate, or DNS rather than the image build.
Roll Back
Revert the committed overlay update, push or merge that revert, and apply the development overlay again:
git revert <gitops-image-update-commit>
kubectl apply -k gitops/apps/sample-app/overlays/dev
kubectl -n sample-app-dev rollout status deployment/sample-app --timeout=5m
curl.exe --fail --show-error https://dev.marsadlab.com/Rollback is complete only when the Deployment reports the previous immutable image and the public endpoint succeeds.