This guide explains how to build local source code changes, push them to a container registry, and deploy them to an in-cluster console instance (e.g., vcluster or remote test cluster) using Helm.
Developers frequently need to test local code changes in a real Kubernetes environment. This requires:
This guide provides a generalized, copy-pasteable command that handles all of these steps.
Before deploying local changes, ensure you have:
You must have push access to a container registry. Common options:
docker.io/yourusernameghcr.io/yourusernamegcr.io/your-projectaws_account_id.dkr.ecr.region.amazonaws.comLog in to your registry:
# Docker Hub
docker login
# GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# Google Container Registry
gcloud auth configure-docker
# AWS ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.us-east-1.amazonaws.com
Your kubectl context must be set to the target cluster:
# Verify current context
kubectl config current-context
# Switch context if needed
kubectl config use-context your-cluster-context
This guide assumes you have an existing console installation deployed via Helm. If not, see the Installation Guide first.
Verify the release exists:
helm list -n kubestellar-console
You should see a release named ks-console (or similar).
Replace <YOUR_DOCKER_REGISTRY> with your container registry (e.g., docker.io/yourusername, ghcr.io/yourusername):
TAG="dev-local-$(date +%Y%m%d-%H%M%S)" && \
docker build -t <YOUR_DOCKER_REGISTRY>/kubestellar-console:$TAG . && \
docker push <YOUR_DOCKER_REGISTRY>/kubestellar-console:$TAG && \
helm upgrade --install ks-console ./deploy/helm/kubestellar-console \
-n kubestellar-console \
--reuse-values \
--set github.existingSecret=kc-github \
--set github.existingSecretKeys.clientId=github-client-id \
--set github.existingSecretKeys.clientSecret=github-client-secret \
--set feedbackGithubToken.existingSecret=kc-feedback-token \
--set feedbackGithubToken.existingSecretKey=feedback-github-token \
--set image.repository=<YOUR_DOCKER_REGISTRY>/kubestellar-console \
--set image.tag=$TAG \
--set extraEnv[0].name=FRONTEND_URL \
--set extraEnv[0].value=http://localhost:8080 \
--set extraEnv[1].name=KAGENTI_CONTROLLER_URL \
--set 'extraEnv[1].value=http://kagenti-backend.kagenti-system.svc:8000' \
--wait --timeout 300s && \
kubectl -n kubestellar-console rollout status deploy/ks-console-kubestellar-console --timeout=300s
dev-local-20260512-143022.)--reuse-valuesTAG="dev-local-$(date +%Y%m%d-%H%M%S)"
Creates a unique tag like dev-local-20260512-143022. This ensures you can track which build is deployed.
docker build -t <YOUR_DOCKER_REGISTRY>/kubestellar-console:$TAG .
Builds the console image from the Dockerfile in the current directory. The image is tagged with your registry and the generated tag.
docker push <YOUR_DOCKER_REGISTRY>/kubestellar-console:$TAG
Pushes the newly built image to your container registry so Kubernetes can pull it.
helm upgrade --install ks-console ./deploy/helm/kubestellar-console \
-n kubestellar-console \
--reuse-values \
...
| Flag | Purpose |
|---|---|
--install | Install if the release doesn’t exist (idempotent) |
-n kubestellar-console | Deploy to the kubestellar-console namespace |
--reuse-values | Critical — preserves all existing Helm values from the previous installation |
--set image.repository=... | Overrides the image repository to use your registry |
--set image.tag=$TAG | Overrides the image tag to use your new build |
--wait --timeout 300s | Waits up to 5 minutes for Helm to apply changes |
--set github.existingSecret=kc-github \
--set github.existingSecretKeys.clientId=github-client-id \
--set github.existingSecretKeys.clientSecret=github-client-secret \
--set feedbackGithubToken.existingSecret=kc-feedback-token \
--set feedbackGithubToken.existingSecretKey=feedback-github-token \
These lines ensure that GitHub OAuth credentials (if deployed separately as Kubernetes secrets) are retained during the upgrade.
Adjust these values to match your actual secret names if they differ. If you don’t use GitHub OAuth, you can omit these lines.
--set extraEnv[0].name=FRONTEND_URL \
--set extraEnv[0].value=http://localhost:8080 \
--set extraEnv[1].name=KAGENTI_CONTROLLER_URL \
--set 'extraEnv[1].value=http://kagenti-backend.kagenti-system.svc:8000' \
These inject environment variables into the console deployment:
FRONTEND_URL — useful when port-forwarding (kubectl port-forward) to access the console locallyKAGENTI_CONTROLLER_URL — points to the Kagenti AI backend if deployed in the clusterCustomize these based on your environment. If you don’t use Kagenti, omit the second variable.
kubectl -n kubestellar-console rollout status deploy/ks-console-kubestellar-console --timeout=300s
Waits for the Kubernetes deployment to finish rolling out the new pods. This ensures the command completes the new version is fully deployed and ready.
If you don’t have GitHub OAuth or Kagenti, you can simplify the command:
TAG="dev-local-$(date +%Y%m%d-%H%M%S)" && \
docker build -t docker.io/yourusername/kubestellar-console:$TAG . && \
docker push docker.io/yourusername/kubestellar-console:$TAG && \
helm upgrade --install ks-console ./deploy/helm/kubestellar-console \
-n kubestellar-console \
--reuse-values \
--set image.repository=docker.io/yourusername/kubestellar-console \
--set image.tag=$TAG \
--wait --timeout 300s && \
kubectl -n kubestellar-console rollout status deploy/ks-console-kubestellar-console --timeout=300s
After deploying, if you want to access the console from your local machine:
kubectl port-forward -n kubestellar-console svc/ks-console-kubestellar-console 8080:80
Then open http://localhost:8080 in your browser.
If you’re testing a specific feature (e.g., AI missions), you might want to tail logs while deploying:
# In terminal: deploy the new version
TAG="dev-local-$(date +%Y%m%d-%H%M%S)" && \
docker build -t docker.io/yourusername/kubestellar-console:$TAG . && \
docker push docker.io/yourusername/kubestellar-console:$TAG && \
helm upgrade --install ks-console ./deploy/helm/kubestellar-console \
-n kubestellar-console \
--reuse-values \
--set image.repository=docker.io/yourusername/kubestellar-console \
--set image.tag=$TAG \
--wait --timeout 300s
# In another terminal: tail logs
kubectl logs -n kubestellar-console -l app.kubernetes.io/name=kubestellar-console -f
Symptom: Pods fail with ImagePullBackOff or ErrImagePull
Cause: Kubernetes cannot pull the image from your registry
Solutions:
Ensure you pushed the image: docker images | grep kubestellar-console
Verify registry credentials: kubectl get secret -n kubestellar-console
Check image name matches exactly (including registry and tag)
If using a private registry, create an image pull secret:
kubectl create secret docker-registry regcred \
-n kubestellar-console \
--docker-server=<YOUR_REGISTRY> \
--docker-username=<USERNAME> \
--docker-password=<PASSWORD>
# Then add to Helm upgrade:
--set imagePullSecrets[0].name=regcred
Symptom: Command hangs at Waiting for deployment rollout to finish...
Cause: Pods are failing to start
Solutions:
kubectl get pods -n kubestellar-consolekubectl logs -n kubestellar-console <pod-name>kubectl describe pod -n kubestellar-console <pod-name>kubectl get deploy -n kubestellar-console ks-console-kubestellar-console -o yamlSymptom: docker build fails
Cause: Missing dependencies or incorrect Dockerfile
Solutions:
Dockerfile is)docker builder prunedocker psSymptom: Helm returns an error about missing values or invalid chart
Cause: Incorrect Helm chart path or incompatible values
Solutions:
ls -la ./deploy/helm/kubestellar-consolehelm get values ks-console -n kubestellar-consolehelm lint ./deploy/helm/kubestellar-console--reuse-values temporarily to start fresh (may lose configuration)Always use timestamped tags (as shown) rather than latest. This ensures:
latest)Create a simple log file to track deployments:
echo "$(date): Deployed $TAG to $(kubectl config current-context)" >> deployment-log.txt
Before deploying to a shared cluster, test your changes locally:
./startup-oauth.sh # or ./start-dev.sh
``` deploy to the cluster you've verified the changes work in local mode.
### 4. Clean Up Old Images
Your registry can fill up with dev images over time. Periodically remove old tags:
```bash
# List images
docker images | grep kubestellar-console
# Remove specific tags
docker rmi <YOUR_REGISTRY>/kubestellar-console:dev-local-20260510-120000
If you’re using custom extraEnv settings, document them in a deploy-env.yaml file:
# deploy-env.yaml
extraEnv:
- name: FRONTEND_URL
value: http://localhost:8080
- name: KAGENTI_CONTROLLER_URL
value: http://kagenti-backend.kagenti-system.svc:8000
- name: MY_CUSTOM_VAR
value: some-value
Then use it with Helm:
helm upgrade --install ks-console ./deploy/helm/kubestellar-console \
-n kubestellar-console \
--reuse-values \
--set image.repository=<YOUR_REGISTRY>/kubestellar-console \
--set image.tag=$TAG \
-f deploy-env.yaml \
--wait --timeout 300s
For contribution guidelines, see the Development Methodology page.