Documentation Index
Fetch the complete documentation index at: https://kubestarterkit.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide walks through adding a new service to the platform. You’ll create the application code, Dockerfile, Kubernetes manifests, and CI/CD configuration.
Create the Service
Create the service directory
mkdir -p services/my-new-service
cd services/my-new-service
Add your application code
Create your application. For example, a Go service:go mod init my-new-service
mkdir cmd
Create cmd/main.go:package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
log.Println("Starting server on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Create a Dockerfile
Create Dockerfile:FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server ./cmd
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
Create mise.toml for service configuration
Create mise.toml:[env]
# Replace with your AWS account ID and region
IMAGE_REPO = "<ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/services/my-new-service"
SERVICE_RELEASE_TAG = "services/my-new-service"
[tasks]
run = "go run ./cmd"
build-image = "docker build ."
Test locally
# Run the service
mise run run
# In another terminal, test it
curl http://localhost:8080/health
Create ECR Repository
Add the new repository to the ECR configuration:
Add repository to the list
Edit terraform/live/shared/<REGION>/ecr-repositories/main.tf and add your service to the local.repos list:locals {
region = var.aws_region
repos = [
"services/container-only-dummy",
"services/go-backend",
"services/go-backend/migrations",
"services/go-backend-no-migrations",
"services/my-new-service" # Add this
]
}
Apply the Terraform change
Commit and open a PR. The Terramate workflow will run a preview, and once merged, the ECR repository will be created.Alternatively, apply directly:cd terraform
terramate run --tags ecr -- terraform apply
Create Kubernetes Manifests
Choose your preferred templating approach. The kit demonstrates three options.
Helm (Recommended)
Kustomize
Create a Helm chart in kubernetes/src/services/my-new-service/:mkdir -p kubernetes/src/services/my-new-service/templates
Chart.yaml:apiVersion: v2
name: my-new-service
version: 0.1.0
values.yaml:replicas: 1
image:
# Replace with your AWS account ID and region
repository: "<ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/services/my-new-service"
version: 0.1.0 # staging_services/my-new-service
ingress:
hostname: "my-new-service.staging.<YOUR_DOMAIN>"
templates/deployment.yaml:apiVersion: apps/v1
kind: Deployment
metadata:
name: my-new-service
namespace: my-new-service
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: my-new-service
template:
metadata:
labels:
app: my-new-service
spec:
containers:
- name: my-new-service
image: "{{ .Values.image.repository }}:{{ .Values.image.version }}"
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
Add additional templates for Service, Ingress, etc. Create a Kustomize structure in kubernetes/src/services/my-new-service/:mkdir -p kubernetes/src/services/my-new-service/{base,staging,production}
base/kustomization.yaml:apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
staging/kustomization.yaml:apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
images:
- name: my-new-service
# Replace with your AWS account ID and region
newName: "<ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/services/my-new-service"
newTag: "0.1.0" # staging_services/my-new-service
Add mise Tasks for Rendering
Create kubernetes/src/services/my-new-service/mise.toml:
[tasks.render-cluster]
description = "Render manifests for a specific cluster"
usage = "arg '<cluster>' help='Target cluster (staging, production)'"
run = '''
#!/usr/bin/env bash
set -euo pipefail
CLUSTER="${usage_cluster}"
OUTPUT_DIR="$(git rev-parse --show-toplevel)/kubernetes/rendered/${CLUSTER}/services/my-new-service"
mise run //tools:render:prep-output-dir "$OUTPUT_DIR"
helm template my-new-service . \
--namespace my-new-service \
--values values.yaml \
--values "values.${CLUSTER}.yaml" \
| mise run //tools:render:split-k8s-docs "$OUTPUT_DIR"
'''
Register with ArgoCD
Add the service to the ArgoCD services app-of-apps:
Add to services values
Edit kubernetes/src/argocd/services/values.yaml:applications:
go-backend:
enabled: true
go-backend-helm:
enabled: true
my-new-service:
enabled: true # Add this
Render ArgoCD manifests
mise run //kubernetes/src/argocd:render-all "<CLUSTER>" # Adds the ArgoCD Application to the app-of-apps
mise run //kubernetes/src/services:render-all "<CLUSTER>" # Renders the service manifests
Add to CI/CD
Add path filter
Edit .github/utils/file-filters.yaml:services/my-new-service:
- 'services/my-new-service/**'
Add to workflow inputs
Edit .github/workflows/ci-build-push.yml:inputs:
service:
options:
- services/go-backend
- services/my-new-service # Add this
Also update .github/workflows/gitops-update-manifests.yml.
Test Locally
Add to Tilt
Edit kubernetes/src/services/Tiltfile to include your new service:# Add your service
load_dynamic('./my-new-service/Tiltfile')
Create kubernetes/src/services/my-new-service/Tiltfile following the pattern of existing services. Start Tilt
cd local
mise run tilt-up
Verify the service
Access via the sslip.io URL or port-forward:kubectl port-forward svc/my-new-service -n my-new-service 8080:80
curl http://localhost:8080/health
Deploy to Staging
Commit and push
git add .
git commit -m "feat: add my-new-service"
git push origin main
Monitor the deployment
- Watch the CI workflow build the image
- Watch the GitOps workflow update manifests
- Check ArgoCD for the new Application
Next Steps