Skip to content

Deploying a New K8s Service

For something that runs on a schedule and exits rather than listening on a port, use New Scheduled Job instead — no Service, no SWAG conf and no DNS entry are needed.

See also: .amazonq/rules/adding-k8s-services-internal.md in q-mcp for the full checklist with examples.

Checklist

1. ECR repository

Add to terraform-heezy/environments/production/aws/ecr.tf:

resource "aws_ecr_repository" "my_service" {
  name = "heezy-my-service"
}
Push terraform change first — the build workflow will fail without the repo.

2. Dockerfile

Create heezy-containers/dockerfiles/heezy-my-service/Dockerfile.

3. Build workflow

Create heezy-containers/.gitea/workflows/deploy-heezy-my-service.yml. Copy an existing one (e.g. deploy-receipts.yml) and update paths + service name.

Workflows go in .gitea/workflows/ only — never .github/workflows/.

4. K8s manifests

Create heezy-k8s/apps/heezy-my-service/: - deployment.yaml - service.yaml - kustomization.yaml

Push to Gitea — auto-deploy.yml handles the rest. Never kubectl apply directly.

5. Schema (if using Postgres)

Add tables to ansible-heezy/roles/heezy-postgres-schema/files/schema.sql. Tables are applied idempotently on every Ansible run via IF NOT EXISTS.

6. SWAG proxy conf

Add a proxy conf to the swag-proxy-confs ConfigMap in heezy-k8s/apps/swag/:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name my-service.*;
    include /config/nginx/ssl.conf;
    location / {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app my-service.heezy.svc.cluster.local;
        set $upstream_port 8080;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

7. DNS

Add entries to the appropriate template in ansible-heezy/roles/dnsmasq/templates/: - k8s-services.j2 — for *.heezy.local → MetalLB VIP (192.168.1.25) - heezy-info-overrides.j2 — for *.heezy.info → 192.168.1.25

Push to Gitea → playbook-dnsmasq-execution.yml runs automatically.

8. NodePort (for internal LAN access)

Edit heezy-k8s/apps/media-nodeports.yaml and add a NodePort service. Check existing assignments in .amazonq/rules/adding-k8s-services-internal.md before picking a port.

9. Cloudflare (for public access)

Add CNAME in terraform-heezy/environments/production/cloudflare/ and add a Cloudflare Access policy if needed.

Naming Convention

heezy-<service>[-<subservice>]

Examples: heezy-finance, heezy-finance-reconcile, heezy-cs16-leaderboard

For DMZ Container Services

See .amazonq/rules/new-dmz-container-app.md and .amazonq/rules/deploy-new-dmz-server.md in q-mcp.