Kubernetes Migration Guide

Follow these steps to migrate your application to Kubernetes. This tool automates Steps 3–7 for you.

Migration Flow:
Containerize App β†’ Push to GHCR β†’ Configure Project β†’ Deploy to Repo β†’ CI/CD Builds Image β†’ ArgoCD Syncs β†’ App Live βœ…

1 Containerize Your Application

Create a Dockerfile in your project root. Below are examples for common stacks:

Node.js / Express:

# Use official Node.js image
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]

Python / FastAPI / Django:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Java / Spring Boot:

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
πŸ’‘ Tip: Add a .dockerignore file to exclude node_modules/, .git/, .env, and other unnecessary files from the image.

Test locally:

docker build -t my-app .
docker run -p 8080:8080 my-app

2 Migrate from Local Storage to Cloud Storage

⚠️ Important: If your app uses multer diskStorage, local file system writes, or stores uploads on disk β€” you must migrate to cloud storage before deploying to Kubernetes. Containers are ephemeral; local files are lost on restart or scaling.

Why?

  • Kubernetes pods are ephemeral β€” local files are destroyed when pods restart or scale
  • Multiple replicas cannot share a local disk
  • Use our internal cloud storage API for file uploads, downloads, and folder management
πŸ“„ Cloud Storage API Documentation:
Refer to the complete Files & Folders API guide for endpoints, authentication, upload/download, folder structure, and code examples:

πŸ“˜ FILES_AND_FOLDERS_API.md β€” Full Reference
πŸ’‘ Tip: Store API keys and credentials as environment variables. This tool can inject them automatically via the Environment Variables section in Project Config β†’ they'll be stored as a Kubernetes Secret and mounted into your pods.

3 Add Health Check Endpoints

Kubernetes uses health checks to know if your app is alive and ready to serve traffic. Add these endpoints:

// Node.js / Express
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.get('/ready', (req, res) => {
  // Check DB connection, redis, etc.
  res.json({ status: 'ready' });
});
# Python / FastAPI
@app.get("/health")
async def health(): return {"status": "ok"}

@app.get("/ready")
async def ready(): return {"status": "ready"}
πŸ’‘ These paths are configurable in the Project Config tab (default: /health and /ready).

4 Prepare Environment Variables

Move all configuration to environment variables. Never hardcode secrets, database URLs, or API keys.

Create a .env file (do NOT commit this to git):

DATABASE_URL=postgres://user:pass@db-host:5432/mydb
REDIS_URL=redis://redis-host:6379
S3_BUCKET=my-uploads
S3_ENDPOINT=https://s3.amazonaws.com
S3_ACCESS_KEY=AKIA...
S3_SECRET_KEY=xxxxx
JWT_SECRET=my-super-secret
NODE_ENV=production
πŸ’‘ In the Project Config tab, upload this .env file. The tool will create a Kubernetes Secret ({project}-secrets) and inject all variables into your pod automatically.

5 Configure This Tool (One-Time Setup)

Go to the Setup tab and configure:

  1. Chart Repository β€” URL of your universal Helm chart repo
  2. GitOps Repository β€” Central config repo that ArgoCD watches for new apps
  3. GHCR Credentials β€” GitHub username + PAT so image pull secrets are created automatically
  4. Cloudflare DNS β€” API token + Zone ID + Cluster IP for automatic DNS pointing
πŸ’‘ These settings are stored in-memory and reset on pod restart. You'll need to re-enter them after a backend restart.

6 Fill in Project Configuration

Go to the Project Config tab and provide:

  1. Project name β€” lowercase, dashes only (e.g., designer-backend)
  2. Namespace β€” K8s namespace for isolation (e.g., design)
  3. Git repo URL + token β€” where your source code lives
  4. Image registry/repository β€” usually ghcr.io / org-name/app-name
  5. Hostname β€” domain for the app (e.g., app.admarksolution.com)
  6. Container port β€” the port your app listens on inside the container
  7. Environment variables β€” upload your .env file

7 Generate & Deploy

Click "Generate Configuration" to preview all files, then click "Deploy to Repository". The tool will automatically:

Action What it does
Git Push Commits values.yaml, ArgoCD app, GitHub Actions workflow to your repo
Namespace Creates the K8s namespace if it doesn't exist
Image Pull Secret Creates ghcr-secret so the cluster can pull your private images
Env Secret Creates {project}-secrets with your environment variables
ArgoCD Registers app in the GitOps repo β†’ ApplicationSet auto-creates the ArgoCD Application
DNS Creates/updates Cloudflare A record pointing your hostname to the cluster IP

8 Push Code & Watch It Deploy

After the initial setup, the CI/CD pipeline handles everything:

  1. Push code to your repo’s main branch
  2. GitHub Actions builds Docker image with timestamp tag
  3. Image pushed to GHCR
  4. Workflow updates k8s/values.yaml with new image tag
  5. ArgoCD detects the change and auto-syncs
  6. New version is live! πŸŽ‰
πŸ’‘ That’s it! After initial setup, every git push to main triggers a full build β†’ deploy cycle automatically. No manual kubectl commands needed.

πŸ”§ Quick Troubleshooting

Symptom Fix
ImagePullBackOff Check ghcr-secret exists in namespace. Re-save GHCR creds in Setup tab and re-deploy.
CrashLoopBackOff App is crashing. Check logs: kubectl logs -n NAMESPACE POD_NAME. Usually missing env vars or wrong port.
ArgoCD OutOfSync Click Sync in ArgoCD. If errors, check Events tab for specifics.
502 Bad Gateway Pod is running but app isn’t listening on the configured port. Verify containerPort matches your app.
TLS Certificate Pending cert-manager needs DNS to resolve. Wait 2–5 min after DNS creation. Check: kubectl get certificate -n NAMESPACE
Workflow not triggering Ensure the first push has a Dockerfile and .github/workflows/deploy.yml. GitHub Actions won’t run from the default branch until the workflow file exists there.

Chart Repository Configuration

Configure the universal chart repository that will be used for all deployments.

URL of your universal Helm chart repository
Required only for private repositories

GitOps Config Repository (ArgoCD ApplicationSet)

Configure the central GitOps repo where app configs are registered. ArgoCD ApplicationSet watches this repo to auto-create Applications.

Central repo where app configs (apps/*.yaml) are stored
Git username for pushing to the config repo
Token with write access to the GitOps config repo

Container Registry Credentials (Image Pull Secret)

Configure GHCR/registry credentials so the service can automatically create ghcr-secret in each project namespace. No more manual secret creation!

Container registry hostname (default: ghcr.io)
GitHub username or org name for GHCR
PAT with read:packages scope for pulling images

Cloudflare DNS (Auto DNS Pointing)

When enabled, A records are auto-created/updated for project hostnames (DNS only, not proxied).

Project Configuration

Kubernetes-compatible name (lowercase, dashes)

Repository Information

Optional, for private repos

Image Configuration

Path after registry (e.g., username/app-name)
Domain where your app will be accessible

Deployment Type

Environment Variables / Secrets

Upload a .env file or paste key=value pairs. These will be stored as a Kubernetes Secret ({project-name}-secrets) in the namespace and injected into your containers automatically.

Accepts .env or .txt files with KEY=VALUE format (one per line)

Additional Options

Deployment Templates

Quick start with pre-configured templates

🌐 Web Application

Single web application with ingress and TLS

πŸ’» Full Stack Application

Frontend and Backend services with separate domains

πŸ”§ Microservices

Multiple microservices architecture

Generated Configuration Files

πŸ“„ values.yaml

Generate configuration first...

πŸ“„ argocd-application.yaml

Generate configuration first...

πŸ“„ .github/workflows/deploy.yml

Generate configuration first...
πŸ“ Next Steps:
  1. Click "Deploy to Repository" to automatically commit files to your Git repo
  2. Or download files manually and commit them yourself
  3. Create image pull secret: kubectl create secret docker-registry ghcr-secret --docker-server=ghcr.io --docker-username=USERNAME --docker-password=TOKEN -n NAMESPACE
  4. Apply ArgoCD application: kubectl apply -f k8s/argocd-application.yaml
  5. Sync in ArgoCD UI and watch your deployment! πŸŽ‰