0b7819bda3
Bump almalinux9 image tags to 20260606 Reviewed-on: #188 Co-authored-by: Ben Vincent <ben@unkin.net> Co-committed-by: Ben Vincent <ben@unkin.net>
262 lines
7.8 KiB
Markdown
262 lines
7.8 KiB
Markdown
# AGENTS.md
|
|
|
|
## Project Overview
|
|
|
|
This is an **ArgoCD GitOps repository** that manages Kubernetes applications for the `au-syd1` cluster using a Kustomize + Helm pattern. Applications are deployed via ArgoCD ApplicationSets that watch directory patterns in this repo.
|
|
|
|
The migration pattern for this repo is: **Terragrunt/Terraform → ArgoCD** (see `migration.md` for full guide).
|
|
|
|
---
|
|
|
|
## Essential Commands
|
|
|
|
```bash
|
|
# Build and render manifests for a path (outputs to manifests/<path>/)
|
|
make build apps/overlays/au-syd1/<app-name>
|
|
make build clusters/au-syd1/bootstrap
|
|
|
|
# Validate all apps and clusters with kubeconform
|
|
make kubeconform
|
|
|
|
# Clean generated manifests
|
|
make clean
|
|
|
|
# Quick build + inspect without persisting output
|
|
kustomize build --enable-helm apps/overlays/au-syd1/<app-name>
|
|
|
|
# Check all resource kinds produced by an overlay
|
|
kustomize build --enable-helm apps/overlays/au-syd1/<app-name> | grep "^kind:" | sort | uniq -c
|
|
|
|
# Run pre-commit checks against all files
|
|
uvx pre-commit run --all-files
|
|
```
|
|
|
|
---
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
argocd-apps/
|
|
├── argocd/
|
|
│ ├── applicationsets/ # ArgoCD ApplicationSet definitions (platform.yaml, storage.yaml)
|
|
│ └── projects/ # ArgoCD AppProject definitions (platform.yaml, storage.yaml)
|
|
├── apps/
|
|
│ ├── base/ # Base Kustomize resources per app (no cluster-specific config)
|
|
│ │ └── <app-name>/
|
|
│ │ ├── kustomization.yaml
|
|
│ │ ├── namespace.yaml
|
|
│ │ ├── vaultauth.yaml # (if Vault-managed secrets)
|
|
│ │ └── vaultstaticsecret.yaml
|
|
│ └── overlays/
|
|
│ └── au-syd1/ # Cluster-specific overlays
|
|
│ └── <app-name>/
|
|
│ ├── kustomization.yaml # references base + helmCharts
|
|
│ └── values.yaml # Helm values for this cluster
|
|
├── clusters/
|
|
│ └── au-syd1/
|
|
│ ├── apps/ # Entry point: references apps/base (ArgoCD app-of-apps)
|
|
│ └── bootstrap/ # ArgoCD install + initial Application manifest
|
|
├── ci/
|
|
│ ├── validate-apps.sh # kubeconform over apps/overlays/*/kustomization.yaml
|
|
│ ├── validate-clusters.sh # kubeconform over clusters/*/kustomization.yaml
|
|
│ └── validate-no-secrets.sh # pre-commit hook: blocks plain Kubernetes Secrets
|
|
└── sources/ # Reference sources (Terraform configs, upstream charts, etc.)
|
|
└── terraform-k8s/ # Original Terraform configs — reference when migrating
|
|
```
|
|
|
|
---
|
|
|
|
## Adding a New Application
|
|
|
|
Follow these 10 steps (detailed in `migration.md`):
|
|
|
|
### 1. Create base resources
|
|
```
|
|
apps/base/<app-name>/
|
|
├── kustomization.yaml
|
|
├── namespace.yaml
|
|
├── vaultauth.yaml # if needed
|
|
└── vaultstaticsecret.yaml # if needed
|
|
```
|
|
|
|
### 2. Create cluster overlay
|
|
```
|
|
apps/overlays/au-syd1/<app-name>/
|
|
├── kustomization.yaml
|
|
└── values.yaml
|
|
```
|
|
|
|
**Overlay kustomization.yaml pattern:**
|
|
```yaml
|
|
---
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../../base/<app-name>
|
|
|
|
helmCharts:
|
|
- name: <chart-name>
|
|
repo: <helm-repo-url>
|
|
version: "<version>"
|
|
releaseName: <release-name>
|
|
namespace: <namespace>
|
|
valuesFile: values.yaml
|
|
```
|
|
|
|
### 3. Register in ApplicationSet
|
|
Add a directory entry to `argocd/applicationsets/platform.yaml` (or `storage.yaml` for `csi-*` apps):
|
|
```yaml
|
|
- path: apps/overlays/*/<app-name>
|
|
```
|
|
|
|
### 4. Update AppProject
|
|
In `argocd/projects/platform.yaml` (or `storage.yaml`):
|
|
- Add the Helm repo URL to `sourceRepos`
|
|
- Add the namespace to `destinations`
|
|
- Add any required cluster-scoped resource types to `clusterResourceWhitelist`
|
|
|
|
### 5. Validate
|
|
```bash
|
|
kustomize build --enable-helm apps/overlays/au-syd1/<app-name>
|
|
make kubeconform
|
|
```
|
|
|
|
---
|
|
|
|
## Secret Management
|
|
|
|
**Plain Kubernetes `Secret` objects are blocked** by the pre-commit hook. Use Vault Operator CRDs instead:
|
|
|
|
### VaultAuth template
|
|
```yaml
|
|
apiVersion: secrets.hashicorp.com/v1beta1
|
|
kind: VaultAuth
|
|
metadata:
|
|
name: default
|
|
namespace: <namespace>
|
|
spec:
|
|
method: kubernetes
|
|
mount: k8s/au/syd1
|
|
vaultConnectionRef: vso-system/default
|
|
allowedNamespaces:
|
|
- <namespace>
|
|
kubernetes:
|
|
role: <role>
|
|
serviceAccount: <service-account>
|
|
audiences:
|
|
- vault
|
|
tokenExpirationSeconds: 600
|
|
```
|
|
|
|
### VaultStaticSecret template
|
|
```yaml
|
|
apiVersion: secrets.hashicorp.com/v1beta1
|
|
kind: VaultStaticSecret
|
|
metadata:
|
|
name: <secret-name>
|
|
namespace: <namespace>
|
|
spec:
|
|
vaultAuthRef: default
|
|
mount: kv
|
|
type: kv-v2
|
|
path: kubernetes/namespace/<namespace>/default/<secret-name>
|
|
refreshAfter: 5m
|
|
destination:
|
|
name: <k8s-secret-name>
|
|
create: true
|
|
overwrite: true
|
|
hmacSecretData: true
|
|
```
|
|
|
|
---
|
|
|
|
## YAML Conventions
|
|
|
|
- **2-space indentation** (enforced by yamllint)
|
|
- All files must end with a newline (`end-of-file-fixer`)
|
|
- No trailing whitespace
|
|
- YAML linting uses relaxed rules with `line-length: disable` (long base64/URLs are fine)
|
|
- yamllint ignores `chart` directories (vendored Helm charts)
|
|
- `---` document separator at top of every YAML file
|
|
- Multiple documents in one file are allowed (e.g., `vaultstaticsecret.yaml` often contains multiple secrets)
|
|
|
|
---
|
|
|
|
## Kubernetes Labels Pattern
|
|
|
|
Use standard `app.kubernetes.io/*` labels consistently:
|
|
```yaml
|
|
labels:
|
|
app.kubernetes.io/component: <component>
|
|
app.kubernetes.io/instance: <release-name>
|
|
app.kubernetes.io/name: <app-name>
|
|
app.kubernetes.io/version: <version>
|
|
```
|
|
|
|
---
|
|
|
|
## Resource Naming Conventions
|
|
|
|
Files in `apps/base/<app-name>/` follow the pattern:
|
|
```
|
|
<kind>_<name>.yaml
|
|
```
|
|
Examples:
|
|
- `deployment_puppetserver-master.yaml`
|
|
- `cronjob_g10k-code.yaml`
|
|
- `configmap_puppetboard-config.yaml`
|
|
- `horizontalpodautoscaler_puppetserver-compilers-autoscaler.yaml`
|
|
- `service_puppet-headless.yaml`
|
|
|
|
---
|
|
|
|
## Helm Chart Vendoring
|
|
|
|
Some overlays vendor Helm charts locally under `apps/overlays/au-syd1/<app-name>/charts/<chart-name>/`. When a chart is vendored, the overlay's `kustomization.yaml` references the local path. When not vendored, it references the OCI or HTTP repo directly.
|
|
|
|
Current Kubernetes target version: **1.33.7** (used by kubeconform in CI).
|
|
|
|
---
|
|
|
|
## Project Boundaries
|
|
|
|
| Project | ApplicationSet | App pattern |
|
|
|------------|---------------------------|--------------------------|
|
|
| `platform` | `argocd/applicationsets/platform.yaml` | Named apps (cert-manager, puppet, woodpecker, etc.) |
|
|
| `storage` | `argocd/applicationsets/storage.yaml` | `csi-*` apps |
|
|
|
|
The `clusters/au-syd1/apps/` entry-point is deployed as a standalone ArgoCD `Application` (not an ApplicationSet) called `au-syd1-apps`.
|
|
|
|
---
|
|
|
|
## CI / Pre-commit Hooks
|
|
|
|
Runs on every PR via Woodpecker CI (`.woodpecker/`):
|
|
|
|
| Check | Tool | Trigger |
|
|
|---|---|---|
|
|
| YAML lint + general file checks | `pre-commit` (yamllint + pre-commit-hooks) | PR |
|
|
| No plain Secrets | `ci/validate-no-secrets.sh` | PR (staged files) |
|
|
| Kubernetes manifest validation | `kubeconform` via `make kubeconform` | PR |
|
|
|
|
kubeconform skips: `CustomResourceDefinition`, `GpuDevicePlugin` (for apps validation).
|
|
|
|
---
|
|
|
|
## Git Workflow
|
|
|
|
- Branch naming: `benvin/<app-name>` (user prefix)
|
|
- **Never `git add .`** — add only relevant files explicitly
|
|
- If pre-commit modifies files, `git add -u` then `git commit --amend --no-edit`
|
|
- Use `git push --force-with-lease` after amending
|
|
|
|
---
|
|
|
|
## Security Policies
|
|
|
|
- `reloader.stakater.com/auto: "true"` annotation triggers rolling restarts on ConfigMap/Secret changes
|
|
- Security contexts follow least-privilege: `drop: [all]` then add only required capabilities
|
|
- `fsGroup: 999` on pod security context for Puppet workloads
|
|
- `runAsUser: 0` is used only for init containers that need to set file permissions, then regular containers run as non-root
|