All checks were successful
Build and Publish TechDocs (Helm Chart Resource) / build-and-publish-helm-chart (push) Successful in 1m9s
Change-Id: I26d65d84aa31f5cc4cc0835e3fb7269fedc73b45
255 lines
12 KiB
Markdown
255 lines
12 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Commands
|
|
|
|
### Linting and Template Validation (no cluster needed)
|
|
|
|
```bash
|
|
# Test all charts
|
|
./test/local-test.sh
|
|
|
|
# Test a single chart
|
|
./test/local-test.sh haproxy-unified-gateway
|
|
./test/local-test.sh kubernetes-ingress
|
|
|
|
# Helm lint a chart directly
|
|
helm lint kubernetes-ingress/
|
|
helm lint haproxy-unified-gateway/ -f haproxy-unified-gateway/ci/deployment-default-values.yaml
|
|
|
|
# Render templates to stdout
|
|
helm template test-release kubernetes-ingress/
|
|
helm template test-release haproxy-unified-gateway/ --set controller.kind=DaemonSet
|
|
helm template test-release haproxy-unified-gateway/ --api-versions monitoring.coreos.com/v1
|
|
```
|
|
|
|
### Chart-testing (ct) — matches CircleCI
|
|
|
|
```bash
|
|
# Lint all charts
|
|
./test/ct-test.sh lint
|
|
|
|
# Lint a single chart
|
|
./test/ct-test.sh lint haproxy-unified-gateway
|
|
|
|
# Install (creates a Kind cluster automatically)
|
|
./test/ct-test.sh install haproxy-unified-gateway
|
|
|
|
# Keep the Kind cluster after install tests
|
|
KIND_KEEP_CLUSTER=1 ./test/ct-test.sh install
|
|
```
|
|
|
|
### Integration Tests (real Kind cluster)
|
|
|
|
```bash
|
|
# Test all charts
|
|
./test/integration-test.sh
|
|
|
|
# Test a single chart
|
|
./test/integration-test.sh haproxy-unified-gateway
|
|
|
|
# Run a specific test scenario (defaults, daemonset, hpa, pdb, metrics-port, monitoring, hugconf-cleanup, ci)
|
|
TEST_FILTER=monitoring ./test/integration-test.sh haproxy-unified-gateway
|
|
|
|
# Keep namespaces after failure for debugging
|
|
KEEP_NS=1 ./test/integration-test.sh
|
|
```
|
|
|
|
## Contribution Requirements
|
|
|
|
- All commits require a `Signed-off-by` line (DCO): `git commit -s -m "message"`
|
|
- Any change to a chart requires a chart **version bump** in `Chart.yaml` following semver
|
|
- Submit changes to multiple charts in **separate PRs**
|
|
|
|
## Project Structure
|
|
|
|
This repo contains Helm charts for HAProxy products:
|
|
|
|
- `kubernetes-ingress/` - HAProxy Kubernetes Ingress Controller chart (mature, feature-rich)
|
|
- `haproxy/` - HAProxy community chart
|
|
- `haproxy-unified-gateway/` - HAProxy Unified Gateway (HUG) chart
|
|
|
|
## kubernetes-ingress Chart
|
|
|
|
- **Chart version**: follows its own semver (currently 1.49.x)
|
|
- **Image**: `haproxytech/kubernetes-ingress`
|
|
- **Supports**: Deployment + DaemonSet modes, IngressClass, Gateway API, HPA, KEDA, ServiceMonitor/PodMonitor, PDB, proxy service (fetch sync mode), ConfigMap-based HAProxy config, publish-service, default TLS cert generation
|
|
- **Templates**: 25 files in `templates/`
|
|
- **CI tests**: 38 test value files in `ci/`
|
|
- **Kubernetes**: >=1.23
|
|
- **Maintainer**: Dinko Korunic
|
|
|
|
## haproxy-unified-gateway Chart
|
|
|
|
- **Chart version**: 0.1.0 (appVersion 0.9.1)
|
|
- **Image**: `haproxytech/haproxy-unified-gateway`
|
|
- **Purpose**: Kubernetes Gateway API controller powered by HAProxy
|
|
- **Kubernetes**: >=1.26
|
|
- **Binary**: `/usr/local/sbin/hug` inside the container
|
|
- **Entry point**: `/start.sh`
|
|
- **Key flag**: `--hugconf-crd=<namespace>/<name>` for HugConf CRD reference
|
|
|
|
### Templates
|
|
|
|
| Template | Purpose |
|
|
|---|---|
|
|
| `_helpers.tpl` | Name, labels, image, serviceAccount, hugconfCrd, serviceMonitorName, podMonitorName helpers |
|
|
| `controller-deployment.yaml` | Deployment (when controller.kind=Deployment) |
|
|
| `controller-daemonset.yaml` | DaemonSet with hostNetwork/hostPort support (when controller.kind=DaemonSet) |
|
|
| `controller-service.yaml` | NodePort Service (HTTP 31080, HTTPS 31443, Stats 31024) |
|
|
| `controller-serviceaccount.yaml` | ServiceAccount |
|
|
| `clusterrole.yaml` | RBAC: Gateway API resources, HUG CRDs (gate.v3.haproxy.org incl. globals/defaults), core K8s resources, auth/authz for kube-rbac metrics |
|
|
| `clusterrolebinding.yaml` | ClusterRoleBinding |
|
|
| `controller-hugconf.yaml` | HugConf CR (logging, globalRef, defaultsRef configuration) — post-install hook (weight 5) |
|
|
| `controller-hugconf-cleanup.yaml` | Pre-delete hook Job that deletes the HugConf CR on `helm uninstall` |
|
|
| `controller-crdjob.yaml` | Helm hook Job: installs HUG CRDs (`--job-check-crd`) — post-install hook (weight 0) |
|
|
| `controller-crdjob-rbac.yaml` | SA + ClusterRole + Binding for CRD/GWAPI jobs |
|
|
| `controller-gwapijob.yaml` | Helm hook Job: installs Gateway API CRDs (`--job-gwapi=VERSION`) |
|
|
| `controller-hpa.yaml` | HPA (disabled by default, mutually exclusive with KEDA) |
|
|
| `controller-keda.yaml` | KEDA ScaledObject (disabled by default, Deployment only) |
|
|
| `controller-servicemonitor.yaml` | ServiceMonitor for Prometheus Operator (disabled by default, gated behind `.Capabilities.APIVersions`) |
|
|
| `controller-podmonitor.yaml` | PodMonitor for Prometheus Operator (disabled by default, gated behind `.Capabilities.APIVersions`) |
|
|
| `controller-service-metrics.yaml` | ClusterIP metrics Service with stat + metrics ports (created when serviceMonitor is enabled) |
|
|
| `controller-poddisruptionbudget.yaml` | PDB (disabled by default) |
|
|
| `controller-podsecuritypolicy.yaml` | PSP (disabled by default, K8s <1.25 only) |
|
|
| `controller-role.yaml` | Role for PSP usage |
|
|
| `controller-rolebinding.yaml` | RoleBinding for PSP Role |
|
|
| `namespace.yaml` | Optional namespace creation (pre-install hook) |
|
|
| `NOTES.txt` | Post-install instructions |
|
|
|
|
### Values Structure
|
|
|
|
- `rbac.create` - RBAC resources
|
|
- `namespace.create` - optional namespace
|
|
- `serviceAccount` - create, name, annotations
|
|
- `controller` - kind (Deployment/DaemonSet), image, replicaCount, hugconfCrd, metricsAuth, extraArgs, containerPort, resources, securityContext, probes, scheduling (nodeSelector/tolerations/affinity/topologySpreadConstraints), extraEnvs/Volumes/Containers, daemonset (useHostNetwork/useHostPort/hostPorts/hostIP), service config (incl. metrics service), serviceMonitor, podMonitor, autoscaling, keda (ScaledObject), PDB
|
|
- `hugconf` - create, name, logging (defaultLevel, categoryLevelList), globalRef, defaultsRef
|
|
- `crdjob` - enabled, podAnnotations, ttl, scheduling, resources, image override
|
|
- `gwapijob` - enabled, version (Gateway API CRD version), same options as crdjob
|
|
|
|
### Metrics
|
|
|
|
HUG exposes two separate metrics endpoints:
|
|
|
|
| Port | Name | Source | Default |
|
|
|---|---|---|---|
|
|
| 31024 | `stat` | HAProxy stats (via `--stats-port`) | Always exposed |
|
|
| 31060 | `metrics` | Controller metrics (via `--controller-port`) | Always exposed |
|
|
|
|
- `controller.metricsAuth` controls `--metrics-auth` flag; default is `kube-rbac`
|
|
- Supported values: `none`, `kube-rbac`, `basic`
|
|
- When `kube-rbac`: controller serves HTTPS, validates bearer tokens via TokenReview API
|
|
- When `none`: plain HTTP, no authentication
|
|
- ClusterRole includes `tokenreviews` and `subjectaccessreviews` for kube-rbac auth
|
|
- The metrics Service (`controller-service-metrics.yaml`) exposes both `stat` and `metrics` ports, created only when ServiceMonitor is enabled
|
|
|
|
### What HUG chart intentionally does NOT have (compared to kubernetes-ingress)
|
|
|
|
- No IngressClass
|
|
- No ConfigMap-based HAProxy configuration
|
|
- No proxy service / fetch sync mode
|
|
- No publish-service
|
|
- No default TLS cert generation
|
|
|
|
### HUG Source Project
|
|
|
|
Source code lives at: `/home/zlatko/src/gitlab.int.haproxy.com/zbratkovic/unified-k8s-gateway`
|
|
|
|
Key paths in source:
|
|
- `cmd/controller/main.go` - controller entry point
|
|
- `hug/configuration/configuration.go` - CLI flags definition
|
|
- `build/Dockerfile` - container image build
|
|
- `api/definition/` - CRD definitions
|
|
- `example/dev-init/` - example Gateway/HTTPRoute manifests
|
|
- `documentation/metrics*.md` - metrics documentation
|
|
|
|
### HUG Controller Flags
|
|
|
|
All flags (for `extraArgs`):
|
|
|
|
| Flag | Default | Description |
|
|
|---|---|---|
|
|
| `--hugconf-crd` | | `namespace/name` of the HugConf CRD |
|
|
| `--controller-name` | `gate.haproxy.org/hug` | `spec.controllerName` GatewayClass selector |
|
|
| `--ipv4-bind-address` | | IPv4 address to bind to |
|
|
| `--ipv6-bind-address` | | IPv6 address to bind to |
|
|
| `--log-type` | `json` | Log output type (`text` or `json`) |
|
|
| `--job-gwapi` | | Install Gateway API experimental CRDs for given version (e.g. `1.3.0`) and exit |
|
|
| `--namespaces` | | Comma-separated list of namespaces to monitor |
|
|
| `--stats-port` | `1024` | Port for HAProxy stats |
|
|
| `--controller-port` | `31060` | Port for controller metrics (prometheus) |
|
|
| `--sync-period` | `0` | Period for HAProxy config computation (e.g. `5s`, `1m`) |
|
|
| `--startup-sync-period` | `0` | Startup period for HAProxy config computation |
|
|
| `--cache-resync-period` | `0` | Controller-runtime manager cache SyncPeriod (default: 10 hours) |
|
|
| `--add-stats-port` | `true` | Add stats port bind to existing stats frontend |
|
|
| `--force-restart-haproxy` | `false` | Force HAProxy restart at controller startup |
|
|
| `--leader-election-enabled` | `false` | Enable leader election |
|
|
| `--with-s6-overlay` | `false` | Use s6 overlay to start/stop/restart HAProxy |
|
|
| `--with-pebble` | `false` | Use pebble to start/stop/restart HAProxy |
|
|
| `--disable-ipv4` | `false` | Disable IPv4 support |
|
|
| `--disable-ipv6` | `false` | Disable IPv6 support |
|
|
| `--job-check-crd` | `false` | Run CRD refresh job and exit |
|
|
| `-e` / `--external` | `false` | Use as external controller (out of k8s cluster) |
|
|
| `--external-config-dir` | | Path to HAProxy configuration directory |
|
|
| `--external-haproxy-binary` | | Path to HAProxy binary |
|
|
| `--external-runtime-dir` | | Path to HAProxy runtime directory |
|
|
| `--external-state-dir` | | Path to HAProxy state directory |
|
|
| `--external-aux-dir` | | Path to HAProxy aux directory |
|
|
| `--metrics-auth` | `none` | Metrics endpoint auth mode: `none`, `kube-rbac`, `basic` |
|
|
| `--metrics-basic-auth-user` | | Basic auth username (when `--metrics-auth=basic`) |
|
|
| `--metrics-basic-auth-password` | | Basic auth password (when `--metrics-auth=basic`) |
|
|
| `-t` | `false` | Simulate running HAProxy (test mode) |
|
|
|
|
Note: The HUG binary default for `--metrics-auth` is `none`, but the Helm chart overrides this to `kube-rbac` via `controller.metricsAuth`.
|
|
|
|
## CI Values Files
|
|
|
|
23 test value files in `haproxy-unified-gateway/ci/`:
|
|
- 8 DaemonSet variants (default, customnodeport, extraargs, extraenvs, extraports, hostport, serviceannotation, strategy)
|
|
- 15 Deployment variants (default, customnodeport, disabled-jobs, extraargs, extraenvs, extraports, hpa, hugconf, keda, keda-advanced, metrics-none, pdb, podmonitor, servicemonitor, strategy)
|
|
|
|
Naming convention: `<mode>-<feature>-values.yaml`
|
|
|
|
## Testing
|
|
|
|
Three test scripts in `test/`:
|
|
|
|
| Script | Purpose |
|
|
|---|---|
|
|
| `test/local-test.sh` | Offline lint + template validation (no cluster needed) |
|
|
| `test/integration-test.sh` | Deploy to a real Kind cluster and verify resources |
|
|
| `test/ct-test.sh` | Wrapper around `ct` (chart-testing), matches CircleCI pipeline |
|
|
|
|
### local-test.sh
|
|
|
|
Tests: Chart.yaml metadata, helm lint, helm template, Deployment vs DaemonSet switching, HugConf cleanup hooks, metrics port rendering + `--metrics-auth` flag, ServiceMonitor/PodMonitor rendering, all ci/ values files.
|
|
|
|
### integration-test.sh
|
|
|
|
Tests on a real Kind cluster: default install, DaemonSet mode, HPA, PDB, metrics port (container port 31060, `--metrics-auth=kube-rbac` arg), ServiceMonitor/PodMonitor with metrics Service port verification, HugConf cleanup on uninstall, all ci/ values files.
|
|
|
|
`TEST_FILTER` values: `defaults`, `daemonset`, `hpa`, `pdb`, `metrics-port`, `monitoring`, `hugconf-cleanup`, `ci`
|
|
|
|
### ct-test.sh
|
|
|
|
Runs `ct lint` and `ct install` locally, same as CircleCI. Auto-downloads `chart_schema.yaml` and `lintconf.yaml` from the ct release on first run (files are gitignored).
|
|
|
|
Modes: `lint`, `install`, `all`
|
|
|
|
### CircleCI Pipeline
|
|
|
|
`.circleci/config.yml` workflow: `lint-scripts` (shellcheck) -> `lint-charts` (ct lint) -> `install-charts` (ct install on Kind) -> `release-charts` (helm package + push to GitHub Releases, GHCR OCI, update gh-pages index).
|
|
|
|
## Conventions
|
|
|
|
- Template names prefixed with `controller-` for controller-specific resources
|
|
- All templates use `include "<chart>.fullname"` for resource naming
|
|
- All templates use `include "<chart>.namespace"` for namespace
|
|
- Helm hooks used for CRD installation jobs (post-install, pre-upgrade)
|
|
- ArgoCD hook annotations included alongside Helm hooks
|
|
- HugConf CR is a post-install hook (weight 5) that runs after the CRD job (weight 0)
|
|
- HugConf cleanup is a pre-delete hook Job
|
|
- Security context: non-root (UID 1000), CAP_NET_BIND_SERVICE, seccomp RuntimeDefault
|
|
- ServiceMonitor/PodMonitor gated behind `.Capabilities.APIVersions "monitoring.coreos.com/v1"`
|