kubeaid-addons
A Helm chart for managing firewall rules and common operator configurations per namespace - network policies, database instances, message brokers, and any other shared infrastructure primitive. The idea is simple: anything that is "common infrastructure" (CNPG, RabbitMQ, MariaDB, MongoDB, etc.) lives here rather than being scattered across individual application charts.
What does this chart do?
| Feature | Kind | Guard |
|---|---|---|
| Namespace-wide default-deny network policy | CiliumNetworkPolicy | defaultDeny.enabled |
| Per-component Cilium network policies | CiliumNetworkPolicy | global.netpol.enabled + component flag |
| CNPG PostgreSQL cluster + scheduled backup | Cluster, ScheduledBackup | global.postgresql.enabled |
| MongoDB replica set + logical backup | MongoDBCommunity, CronJob | global.mongodb.enabled |
| RabbitMQ cluster (via Cluster Operator) | RabbitmqCluster | global.rabbitmq.enabled |
| Argo CD baseline policy | CiliumNetworkPolicy | global.netpol.enabled + global.argocd.netpol |
| Harbor network policies | CiliumNetworkPolicy | global.netpol.enabled + global.harbor.netpol |
| SonarQube network policy | CiliumNetworkPolicy | global.netpol.enabled + global.sonarqube.netpol |
| OpenObserve network policy | CiliumNetworkPolicy | global.netpol.enabled + global.openobserve |
Everything is nil-safe - if a key is missing from values, the template renders nothing rather
than panicking. New operator types (MariaDB, MongoDB, etc.) can be added by dropping a new
template in templates/.
Private values live in
kubeaid-configrepo. The chart ships with empty/disabled defaults. All environment-specific configuration lives in yourkubeaid-configprivate repository.
Setup
1. Standalone ArgoCD app (default-deny)
Create one kubeaid-addons ArgoCD Application per cluster. This app is responsible for rendering
the namespace wide default deny policies across all managed namespaces and for providing shared
FQDN values consumed by other charts.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kubeaid-addons
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
namespace: kubeaid-addons
project: kubeaid
sources:
- repoURL: <your-repo-url>
path: argocd-helm-charts/kubeaid-addons
targetRevision: main
helm:
valueFiles:
- <path-to-values-kubeaid-addons.yaml>
- repoURL: <your-repo-url>
targetRevision: main
ref: values
syncPolicy:
syncOptions:
- ApplyOutOfSyncOnly=true
- CreateNamespace=true
The corresponding private values file contains only the default-deny configuration:
# default-deny - one entry per namespace you want protected
defaultDeny:
enabled: true
namespaces:
my-app-namespace: {} # full deny, no exclusions
another-namespace:
excludedPods:
- <label-key>: <label-value> # pods matching this are excluded from the deny
2. As a subchart dependency (component netpols + infra)
For each application chart that needs network policies or operator resources, add kubeaid-addons
as a Helm dependency. This gives the application chart access to all network policy templates and
infrastructure primitives without duplicating logic.
Chart.yaml:
dependencies:
- name: my-app
version: x.y.z
repository: https://charts.example.com
- name: kubeaid-addons
version: 0.1.0
repository: file://../kubeaid-addons
Create a symlink from the chart's charts/ directory to the kubeaid-addons source:
ln -s ../../kubeaid-addons argocd-helm-charts/my-app/charts/kubeaid-addons
git add argocd-helm-charts/my-app/charts/kubeaid-addons
ArgoCD resolves the symlink directly, so any changes to kubeaid-addons templates are picked up without re-packaging.
values.yaml (chart-level defaults):
global:
netpol:
enabled: false
my-component:
netpol: false
Private values:
global:
netpol:
enabled: true
releaseName: my-app
traefik:
namespace: traefik
labels:
app.kubernetes.io/name: traefik
app.kubernetes.io/instance: traefik
postgresql:
enabled: true
instanceName: my-app-pgsql
size: 10Gi
netpol: true
clients:
- labels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/component: backend
mongodb:
enabled: false
instanceName: my-app-mongodb
passwordSecretName: my-app-mongodb-user-password
Enabling network policies
Master switch
global:
netpol:
enabled: true
releaseName: <helm-release-name>
traefik:
namespace: traefik
labels:
app.kubernetes.io/name: traefik
app.kubernetes.io/instance: traefik
Per-component flags
global:
rabbitmq:
netpol: true
redis:
netpol: true
grafana:
netpol: true
engine:
netpol: true
celery:
netpol: true
whoami:
netpol: true
postgresql:
netpol: true
argocd:
netpol: true
harbor:
netpol: true
sonarqube:
netpol: true
openobserve:
netpol: true
postgres:
cnpgCluster: openobserve-postgres
ingestors:
- name: collector
namespace: openobserve
labels:
app.kubernetes.io/name: openobserve-collector
azure:
enabled: true
openfga:
enabled: true
OpenObserve (networkpolicy-openobserve*.yaml) renders policies across separate template files: core workloads (networkpolicy-openobserve.yaml), ingestor egress (networkpolicy-openobserve-ingestor.yaml), OpenFGA, NATS, CNPG postgres, and OpenTelemetry operator. Postgres is provisioned by the openobserve chart, not kubeaid-addons — set global.openobserve.postgres.cnpgCluster if the cluster name differs, and do not enable global.postgresql.enabled for OpenObserve.
Policies are rendered by the openobserve parent chart, which includes kubeaid-addons as a Helm dependency (openobserve/Chart.yaml + charts/kubeaid-addons symlink — same pattern as harbor / sonarqube). Enable them from the OpenObserve Argo CD app values via global.netpol.enabled and global.openobserve.netpol. Default-deny for the namespace still comes from the standalone kubeaid-addons Argo app (§1).
Argo CD baseline policy is configured under global.argocd plus shared global.netpol.traefik / global.netpol.prometheus. Render it via a parent chart (for example argo-cd) that includes kubeaid-addons as a dependency; Helm only passes global into subcharts.
global:
netpol:
enabled: true
traefik:
namespace: traefik
labels:
"k8s:app.kubernetes.io/name": traefik
"k8s:app.kubernetes.io/instance": traefik
prometheus:
namespace: monitoring
labels:
"k8s:app.kubernetes.io/name": prometheus
argocd:
netpol: true
namespace: argocd
endpointSelectorLabels:
app.kubernetes.io/part-of: argocd
kubeaidAgent:
namespace: monitoring
labels:
"k8s:app.kubernetes.io/name": kubeaid-agent
# Optional: allow kube-prometheus blackbox-exporter probes to Argo (off unless you use that).
blackboxExporter:
enabled: false
namespace: monitoring
labels:
"k8s:app.kubernetes.io/name": blackbox-exporter
Adding a new operator resource type
- Add a template in
templates/<resource>.yamlguarded by{{- if ((.Values.global).<type>).enabled }} - Document the values keys in
values.yamlwith# --comments - Because dependent charts use a symlink, no re-packaging is needed - changes are picked up immediately
Adding a new network policy template
- Create
charts/network-policies/templates/networkpolicy-<component>.yaml - Use the nil-safe guard:
For Argo CD, the guard is{{- if and ((.Values.global).netpol).enabled ((.Values.global).<component>).netpol }}
global.netpol.enabledplusglobal.argocd.netpol(seenetworkpolicy-argocd.yaml). - Add
global.<component>.netpol: falseto the parent chart'svalues.yaml(for Argo CD useglobal.argocd.netpol: false) - Because dependent charts use a symlink, no re-packaging is needed - changes are picked up immediately