Kubernetes Services Structure#
All cluster services are managed through a single meta Helm chart in the
kubernetes-services/ directory. ArgoCD deploys this chart, and each template
within it becomes an independent ArgoCD Application.
Directory layout#
kubernetes-services/
├── Chart.yaml # Minimal Helm chart metadata
├── values.yaml # Shared values (repo_branch, oauth2_emails, etc.)
├── templates/ # One ArgoCD Application per service
│ ├── cert-manager.yaml
│ ├── cloudflared.yaml
│ ├── dashboard.yaml # Headlamp
│ ├── echo.yaml
│ ├── grafana.yaml
│ ├── ingress.yaml
│ ├── kernel-settings.yaml
│ ├── llamacpp.yaml
│ ├── longhorn.yaml
│ ├── nvidia-device-plugin.yaml
│ ├── oauth2-proxy.yaml
│ ├── open-webui.yaml
│ ├── rkllama.yaml
│ └── sealed-secrets.yaml
└── additions/ # Extra manifests per service
├── argocd/ # Custom CM for ArgoCD health checks
├── cert-manager/ # SealedSecret + ClusterIssuer
├── cloudflared/ # Deployment + SealedSecret
├── dashboard/ # RBAC for Headlamp
├── echo/ # Echo-server manifests
├── ingress/ # Reusable ingress sub-chart
├── llamacpp/ # NFS volume + GPU config
├── longhorn/ # VolumeSnapshotClass
├── oauth2-proxy/ # SealedSecret for OAuth config
└── rkllama/ # DaemonSet + ConfigMap + Ingress + Service
How it works#
The root Application#
The Ansible cluster role creates a root ArgoCD Application called
all-cluster-services. It points at kubernetes-services/ and passes shared
values via Helm:
repo_remote— Git repository URLrepo_branch— comes fromkubernetes-services/values.yaml(self-referential)cluster_domain— domain name for ingress hostsdomain_email— for Let’s Encrypt registration
Template rendering#
ArgoCD renders the Helm chart. Each file in templates/ produces an ArgoCD
Application resource. These are child apps — each one independently manages
its own service lifecycle.
Multi-source Applications#
Most services use the multi-source pattern — combining an external Helm chart with local additions from this repo:
sources:
# Source 1: External Helm chart
- repoURL: https://charts.jetstack.io
targetRevision: "v1.19.3"
chart: cert-manager
helm:
valuesObject:
crds:
enabled: true
# Source 2: Local additions (SealedSecrets, ClusterIssuers, etc.)
- repoURL: "{{ .Values.repo_remote }}"
targetRevision: "{{ .Values.repo_branch }}"
path: kubernetes-services/additions/cert-manager
# Source 3: Reusable ingress sub-chart (optional)
- repoURL: "{{ .Values.repo_remote }}"
targetRevision: "{{ .Values.repo_branch }}"
path: kubernetes-services/additions/ingress
helm:
valuesObject:
cluster_domain: "{{ .Values.cluster_domain }}"
service_name: cert-manager
service_port: 443
The reusable ingress sub-chart#
The additions/ingress/ directory contains a minimal Helm chart that generates
a standardised Ingress resource. It supports:
TLS via the
letsencrypt-prodClusterIssuerHost-based routing (
<service_name>.<cluster_domain>)basic_auth: true— nginx basic-auth via theadmin-authsecretoauth2_proxy: true— protect with oauth2-proxy authentication gatewayssl_redirect: false— disable HTTP→HTTPS redirect (default true)ssl_passthrough: true— TLS passthrough mode (e.g. for ArgoCD)
This avoids duplicating ingress boilerplate across services.
Plain manifest services#
Some services (echo, cloudflared, rkllama) don’t use external Helm charts — they
deploy raw Kubernetes manifests directly from additions/<service>/. The ArgoCD
Application simply points at the directory.
Values flow#
flowchart TD
GV["group_vars/all.yml<br/>(Ansible vars)"] -->|"cluster role"| ROOT["Root Application CR<br/>valuesObject"]
VY["kubernetes-services/values.yaml<br/>(repo_branch)"] -->|"Helm values"| ROOT
ROOT -->|"{{ .Values.* }}"| CHILD["Child Application templates"]
CHILD -->|"Service-specific values"| SVC["Deployed services"]
Key values propagated to all child apps:
Value |
Source |
Purpose |
|---|---|---|
|
|
Git repo URL for multi-source apps |
|
|
Branch for |
|
|
Domain for ingress hosts |
|
|
Let’s Encrypt email |
Renovate integration#
Renovate monitors kubernetes-services/templates/*.yaml
for targetRevision fields and automatically creates pull requests when upstream Helm
charts release new versions. See renovate.json for the full configuration.