feat(flux): upgrade to v2.8.0 + chart fixes for strict SSA & kstatus (folds #2612) (#2602)

## What this PR does

Upgrades Flux v2.7.3 → v2.8.0 across both the vendored tenant chart and
the embedded management-cluster manifests, and folds in the chart fixes
that become hard errors under the new strict helm-controller v1.5.

Flux v2.8's helm-controller v1.5.0 ships:
- **Server-Side Apply with `--force-conflicts`** — strict CRD schema
enforcement; misplaced fields (silently dropped on v2.7) now fail the
apply.
- **kstatus-based health checking** by default — parent HR waits for
every applied resource (including child HRs) to be Ready before flipping
its own Ready, surfacing latent ordering deadlocks.
- **Helm v4 embedded** — `upgrade.force: true` is deprecated and now
conflicts with SSA.
- **`HelmRelease.spec.healthCheckExprs`** — prerequisite for proper
readiness gating (used in PR #2601 split).

Folds in PR #2612 (kubevirt-instancetypes null TPM fix) since the same
Flux upgrade triggers it.

## Commits

**Flux upgrade itself:**
- `feat(fluxcd)`: bump `flux-operator` / `flux-instance` vendored charts
to v0.48.0; web UI opt-in.
- `feat(flux)`: regenerate embedded management-cluster manifests via
`make update` in `packages/core/flux-aio` (timoni bundle build).

**Chart fixes for strict SSA — fields the chart sent that v2.7 silently
dropped, v2.8 rejects:**
- `fix(kubevirt-instancetypes)`: drop persistent strip that produced
null `preferredTPM` (folds #2612).
- `fix(foundationdb)`: relocate `faultDomain`, `imageType`, `labels`,
`minimumUptimeSecondsForBounce` from inside `automationOptions` to
direct children of `spec`.
- `fix(kafka)`: place `enableServiceLinks` under `template.pod`, not a
phantom `template.spec`.
- `fix(vm-instance)`: emit `disk: {}` (not `disk:`/null) when no bus is
set.
- `fix(platform)`: drop deprecated `upgrade.force: true` from
HelmReleases; fix `kafka` WorkloadMonitor `replicas` paths.

**Ordering / deadlock fixes under v2.8 kstatus:**
- `fix(vpa)`: break circular wait between parent install and nested
`vpa-for-vpa` HR.
- `fix(kubernetes)`: drop lookup-guarded parent-HR `dependsOn` on tenant
addon child HRs (parent waits on child via kstatus, child waited on
parent — deadlock).

**E2E waits for v2.8 kstatus timing:**
- `test(e2e)`: bump app HR-Ready waits to 5m (was 20s–100s under v2.7's
faster dispatch).
- `test(e2e)`: wait for parent HR Ready before downstream asserts in
`run-kubernetes.sh` and `vminstance.bats`.

## Scope discipline

This PR is part of the split of #2619 (the consolidated CI fixes branch)
into review-friendly pieces. Companion PRs:
- **PR #2601** (seaweedfs split) — folded into this PR (commits
`29c6afc8`, `0e8b46d7`, `7157158c`, `dccdeb52`, `f880b324`): the
seaweedfs-system → seaweedfs-db + seaweedfs-system split, its adoption
migration 43 (targetVersion 44), and the configurable db resources all
land here, because the strict-SSA `upgrade.force` removal and the
kstatus parent-HR timeout bump only make sense together with the split.
#2601 is superseded.
- **PR #2558** (drop 3× retry on `Run E2E` + `Install Cozystack`) —
independent, lands separately.
- Several smaller standalone fixes lifted out of #2619 (startup probes,
cert-manager `dependsOn`, prepull machinery, CSI HR timeout, NFS/OIDC
test improvements) — opened as separate PRs.

## Verification

- `helm template` renders cleanly for both `fluxcd` and
`fluxcd-operator` packages with `web.enabled=false` (default) and
`web.enabled=true`.
- Embedded `cmd/cozystack-operator` binary contains the v1.5.0 / v1.8.0
/ v2.1.0 controller image strings.
- No references to the v0.39-removed `--disable-wait-interruption` flag
anywhere in `packages/` or `internal/`.

### Release note

```release-note
Flux upgraded to v2.8.0 (helm-controller v1.5 — Helm v4 Server-Side Apply with --force-conflicts, kstatus health checking).

When upgrading existing clusters:
- Kubernetes 1.33+ is now required for the platform (management) cluster, and for any tenant cluster that enables the optional (default-off) Flux addon — that addon ships the bumped Flux too.
- HelmReleases no longer set `upgrade.force: true`. Helm v4 SSA resolves field-ownership conflicts automatically (`--force-conflicts`), but that is not the old client-side replace: immutable-field changes (e.g. StatefulSet volumeClaimTemplates/serviceName) no longer self-heal and require manual recreation — delete the object (e.g. `kubectl delete sts <name> --cascade=orphan`) and let Flux recreate it.
- KubeVirt: persistent TPM/EFI is re-enabled for the Windows 11/2k22/2k25 preferences (KubeVirt 1.8 VMPersistentState); each affected VM provisions an extra RWO backend-storage PVC from the default StorageClass.
- KubeVirt: the EOL centos.7*/centos.stream8* preferences are retained as deprecated, hidden aliases (`tags: hidden`, `instancetype.kubevirt.io/deprecated: "true"`) — existing VMInstances on these profiles keep rendering and need no action on upgrade, but the profiles are no longer offered for new VMs; repoint to centos.stream9/10 when convenient. The gn1.* GPU instancetypes are likewise retained.
- FoundationDB: imageType now reaches the operator (silently dropped pre-SSA); it is pinned to `split` to match the value existing clusters effectively ran, so upgrades stay non-disruptive. Set `imageType: unified` to migrate deliberately.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Flux Status web UI: optional web server, config secret, service port,
HTTPRoute/Ingress, network policy, and RBAC roles.
  * New SeaweedFS DB Helm chart and optional managed DB release.

* **Improvements**
* CRD/schema enhancements: new provider kinds, validations, variant
option, and external checksum refs.
* Raised Kubernetes prerequisite to 1.30+; extended e2e timeouts for
reliability.

* **Chores**
* Bumped Flux Operator and Flux versions; documentation links updated to
fluxoperator.dev.
* **Bug Fixes**
  * Removed aggressive HelmRelease force-upgrade/install flags.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2602?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
myasnikovdaniil authored and GitHub committed 2026-06-02 14:08:39 +05:00
commit c435efa199
118 files changed
+4252 -4600

No files matched your search

+1 -1
View File
@@ -39,7 +39,7 @@ type ConfigSpec struct {
// +kubebuilder:default:={}
CustomParameters []string `json:"customParameters,omitempty"`
// Container image deployment type.
// +kubebuilder:default:="unified"
// +kubebuilder:default:="split"
ImageType ImageType `json:"imageType"`
// Security context for containers.
// +kubebuilder:default:={}
+1 -1
View File
@@ -19,7 +19,7 @@ spec:
EOF
# Wait for the bucket to be ready
kubectl -n tenant-test wait hr bucket-${name} --timeout=100s --for=condition=ready
kubectl -n tenant-test wait hr bucket-${name} --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get bucketclaims.objectstorage.k8s.io bucket-${name} >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait bucketclaims.objectstorage.k8s.io bucket-${name} --timeout=300s --for=jsonpath='{.status.bucketReady}'
timeout 60 sh -ec "until kubectl -n tenant-test get bucketaccesses.objectstorage.k8s.io bucket-${name}-admin >/dev/null 2>&1; do sleep 2; done"
+1 -1
View File
@@ -38,7 +38,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr clickhouse-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr clickhouse-$name --timeout=20s --for=condition=ready
kubectl -n tenant-test wait hr clickhouse-$name --timeout=5m --for=condition=ready
timeout 180 sh -ec "until kubectl -n tenant-test get svc chendpoint-clickhouse-$name -o jsonpath='{.spec.ports[*].port}' | grep -q '8123 9000'; do sleep 10; done"
timeout 60 sh -ec "until kubectl -n tenant-test get statefulset.apps/chi-clickhouse-$name-clickhouse-0-0 >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait statefulset.apps/chi-clickhouse-$name-clickhouse-0-0 --timeout=120s --for=jsonpath='{.status.replicas}'=1
+1 -1
View File
@@ -26,7 +26,7 @@ dump_diagnostics() {
# resource, so poll for existence first.
wait_etcd_hr_ready() {
timeout 60 sh -ec 'until kubectl -n tenant-test get hr/etcd >/dev/null 2>&1; do sleep 2; done'
kubectl -n tenant-test wait hr/etcd --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr/etcd --timeout=5m --for=condition=ready
}
@test "Create Etcd" {
+6 -4
View File
@@ -21,8 +21,9 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr ${name} >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr ${name} --timeout=120s --for=condition=ready
kubectl -n tenant-test wait hr ${name}-system --timeout=120s --for=condition=ready
kubectl -n tenant-test wait hr ${name} --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get hr ${name}-system >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr ${name}-system --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get deploy -l app.kubernetes.io/instance=${name}-system -o jsonpath='{.items[0].status.readyReplicas}' | grep -q '1'; do sleep 5; done"
kubectl -n tenant-test delete externaldns.apps.cozystack.io ${name}
@@ -46,8 +47,9 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr ${name} >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr ${name} --timeout=120s --for=condition=ready
kubectl -n tenant-test wait hr ${name}-system --timeout=120s --for=condition=ready
kubectl -n tenant-test wait hr ${name} --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get hr ${name}-system >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr ${name}-system --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get deploy -l app.kubernetes.io/instance=${name}-system -o jsonpath='{.items[0].status.readyReplicas}' | grep -q '1'; do sleep 5; done"
kubectl -n tenant-test delete externaldns.apps.cozystack.io ${name}
+1 -1
View File
@@ -41,7 +41,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr $release >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr $release --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr $release --timeout=5m --for=condition=ready
# Wait for COSI to provision bucket
timeout 60 sh -ec "until kubectl -n tenant-test get bucketclaims.objectstorage.k8s.io $release-registry >/dev/null 2>&1; do sleep 2; done"
+1 -1
View File
@@ -42,7 +42,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr kafka-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr kafka-$name --timeout=30s --for=condition=ready
kubectl -n tenant-test wait hr kafka-$name --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get kafkas $name >/dev/null 2>&1; do sleep 2; done"
kubectl wait kafkas -n tenant-test $name --timeout=300s --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get pvc data-kafka-$name-zookeeper-0; do sleep 10; done"
+1 -1
View File
@@ -38,7 +38,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr mariadb-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr mariadb-$name --timeout=30s --for=condition=ready
kubectl -n tenant-test wait hr mariadb-$name --timeout=5m --for=condition=ready
timeout 80 sh -ec "until kubectl -n tenant-test get svc mariadb-$name -o jsonpath='{.spec.ports[0].port}' | grep -q '3306'; do sleep 10; done"
timeout 80 sh -ec "until kubectl -n tenant-test get endpoints mariadb-$name -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
timeout 60 sh -ec "until kubectl -n tenant-test get statefulset.apps/mariadb-$name >/dev/null 2>&1; do sleep 2; done"
+1 -1
View File
@@ -30,7 +30,7 @@ EOF
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr mongodb-$name >/dev/null 2>&1; do sleep 2; done"
# Wait for HelmRelease
kubectl -n tenant-test wait hr mongodb-$name --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr mongodb-$name --timeout=5m --for=condition=ready
# Wait for MongoDB service (port 27017)
timeout 120 sh -ec "until kubectl -n tenant-test get svc mongodb-$name-rs0 -o jsonpath='{.spec.ports[0].port}' | grep -q '27017'; do sleep 10; done"
# Wait for endpoints
+2 -2
View File
@@ -21,8 +21,8 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr openbao-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr openbao-$name --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr openbao-$name-system --timeout=120s --for=condition=ready
kubectl -n tenant-test wait hr openbao-$name --timeout=5m --for=condition=ready
kubectl -n tenant-test wait hr openbao-$name-system --timeout=5m --for=condition=ready
# Wait for container to be started (pod Running does not guarantee container is ready for exec on slow CI)
if ! timeout 120 sh -ec "until kubectl -n tenant-test get pod openbao-$name-0 --output jsonpath='{.status.containerStatuses[0].started}' 2>/dev/null | grep -q true; do sleep 5; done"; then
+1 -1
View File
@@ -43,7 +43,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr postgres-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr postgres-$name --timeout=100s --for=condition=ready
kubectl -n tenant-test wait hr postgres-$name --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get job.batch postgres-$name-init-job >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait job.batch postgres-$name-init-job --timeout=50s --for=condition=Complete
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-r -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
+2 -2
View File
@@ -20,8 +20,8 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr qdrant-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr qdrant-$name --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr qdrant-$name-system --timeout=120s --for=condition=ready
kubectl -n tenant-test wait hr qdrant-$name --timeout=5m --for=condition=ready
kubectl -n tenant-test wait hr qdrant-$name-system --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get sts qdrant-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait sts qdrant-$name --timeout=90s --for=jsonpath='{.status.readyReplicas}'=1
timeout 60 sh -ec "until kubectl -n tenant-test get pvc qdrant-storage-qdrant-$name-0 >/dev/null 2>&1; do sleep 2; done"
+1 -1
View File
@@ -21,7 +21,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr redis-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr redis-$name --timeout=20s --for=condition=ready
kubectl -n tenant-test wait hr redis-$name --timeout=5m --for=condition=ready
timeout 60 sh -ec "until kubectl -n tenant-test get pvc redisfailover-persistent-data-rfr-redis-$name-0 >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait pvc redisfailover-persistent-data-rfr-redis-$name-0 --timeout=50s --for=jsonpath='{.status.phase}'=Bound
timeout 60 sh -ec "until kubectl -n tenant-test get deploy rfs-redis-$name >/dev/null 2>&1; do sleep 2; done"
+9
View File
@@ -477,6 +477,15 @@ EOF
delete ingress hairpin-probe --ignore-not-found 2>/dev/null || true
fi
# Wait for the parent kubernetes-${test_name} HR to be Ready before the
# remediation guard runs. The guard reads `.status.history`, which is empty
# until the helm install action completes — under Flux v2.8 kstatus the
# parent's helm install can still be "Running 'install'" after every child
# HR (cilium, coredns, csi, vsnap-crd, ingress-nginx) is already Ready,
# because kstatus walks all applied resources before flipping the parent
# Ready.
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
# Guard: parent HelmRelease must not have entered an install/upgrade remediation cycle.
# A non-zero installFailures/upgradeFailures indicates the helm-wait budget expired while
# admin-kubeconfig was still being provisioned, which would trigger uninstall remediation
+12 -7
View File
@@ -28,7 +28,7 @@ EOF
# Wait for the operator to materialise the HelmRelease before kubectl wait
# kicks in (kubectl wait errors immediately if the object does not exist yet).
timeout 60 sh -ec "until kubectl -n tenant-test get hr vm-disk-$name >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr vm-disk-$name --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr vm-disk-$name --timeout=5m --for=condition=ready
kubectl -n tenant-test wait dv vm-disk-$name --timeout=250s --for=condition=ready
kubectl -n tenant-test wait pvc vm-disk-$name --timeout=200s --for=jsonpath='{.status.phase}'=Bound
# Drop the VMDisk so the next test starts from a clean slate. Each test
@@ -63,7 +63,7 @@ spec:
storageClass: replicated
EOF
timeout 60 sh -ec "until kubectl -n tenant-test get hr vm-disk-$diskName >/dev/null 2>&1; do sleep 2; done"
kubectl -n tenant-test wait hr vm-disk-$diskName --timeout=60s --for=condition=ready
kubectl -n tenant-test wait hr vm-disk-$diskName --timeout=5m --for=condition=ready
kubectl -n tenant-test wait dv vm-disk-$diskName --timeout=250s --for=condition=ready
kubectl -n tenant-test wait pvc vm-disk-$diskName --timeout=200s --for=jsonpath='{.status.phase}'=Bound
kubectl apply -f - <<EOF
@@ -100,13 +100,18 @@ EOF
# Wait for the operator to materialise the HelmRelease before downstream
# waits proceed (kubectl wait errors immediately if the HR does not exist).
timeout 60 sh -ec "until kubectl -n tenant-test get hr vm-instance-$name >/dev/null 2>&1; do sleep 2; done"
# Wait for the parent HR Ready before polling for the VMI. Under Flux v2.8
# kstatus the helm install can be still dispatching when the previous
# ordering assumed it had already applied the VirtualMachine CR — without
# this the next poll for `vmi vm-instance-$name` returned NotFound for
# its entire 120s budget because kubevirt hadn't seen the VM yet.
kubectl -n tenant-test wait hr vm-instance-$name --timeout=5m --for=condition=ready
# Nested KubeVirt VM startup (virt-launcher + libvirt + cloud-init DHCP)
# routinely takes 30-60s under runner load; the previous 20s was unrealistic
# and produced flakes. 120s is a comfortable upper bound for nested virt.
timeout 120 sh -ec "until kubectl -n tenant-test get vmi vm-instance-$name -o jsonpath='{.status.interfaces[0].ipAddress}' | grep -q '[0-9]'; do sleep 2; done"
kubectl -n tenant-test wait hr vm-instance-$name --timeout=60s --for=condition=ready
# routinely takes 30-60s under runner load. 5m is a comfortable upper
# bound for nested virt + slow runner I/O after the HR-Ready gate.
timeout 5m sh -ec "until kubectl -n tenant-test get vmi vm-instance-$name -o jsonpath='{.status.interfaces[0].ipAddress}' | grep -q '[0-9]'; do sleep 2; done"
# VM ready follows IP assignment closely; 60s gives buffer for the qemu-guest-agent.
kubectl -n tenant-test wait vm vm-instance-$name --timeout=60s --for=condition=ready
kubectl -n tenant-test wait vm vm-instance-$name --timeout=5m --for=condition=ready
kubectl -n tenant-test delete vminstances.apps.cozystack.io $name --ignore-not-found --timeout=3m
kubectl -n tenant-test delete vmdisks.apps.cozystack.io $diskName --ignore-not-found --timeout=3m
}
@@ -5,7 +5,7 @@ metadata:
labels:
app.kubernetes.io/name: flux-tenants
app.kubernetes.io/part-of: flux
app.kubernetes.io/version: v2.7.3
app.kubernetes.io/version: v2.8.0
sharding.fluxcd.io/role: shard
name: flux-tenants
namespace: cozy-fluxcd
@@ -56,7 +56,7 @@ spec:
resource: limits.memory
- name: TUF_ROOT
value: /tmp/.sigstore
image: "ghcr.io/fluxcd/helm-controller:v1.4.3"
image: "ghcr.io/fluxcd/helm-controller:v1.5.0"
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
File diff suppressed because it is too large. Load diff
@@ -15,7 +15,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
+10 -10
View File
@@ -81,8 +81,8 @@ when it sees a chart-rendered Running backup against the same target.
customParameters:
- "knob_disable_posix_kernel_aio=1"
# Image type (unified is default and recommended for new deployments)
imageType: "unified"
# Image type (split is the default; matches existing clusters' effective value)
imageType: "split"
# Enable automatic pod replacements
automaticReplacements: true
@@ -191,12 +191,12 @@ For Cozystack-specific issues, consult the Cozystack documentation or support ch
### FoundationDB configuration
| Name | Description | Type | Value |
| ---------------------------- | ------------------------------------------ | ---------- | --------- |
| `customParameters` | Custom parameters to pass to FoundationDB. | `[]string` | `[]` |
| `imageType` | Container image deployment type. | `string` | `unified` |
| `securityContext` | Security context for containers. | `object` | `{}` |
| `securityContext.runAsUser` | User ID to run the container. | `int` | `4059` |
| `securityContext.runAsGroup` | Group ID to run the container. | `int` | `4059` |
| `automaticReplacements` | Enable automatic pod replacements. | `bool` | `true` |
| Name | Description | Type | Value |
| ---------------------------- | ------------------------------------------ | ---------- | ------- |
| `customParameters` | Custom parameters to pass to FoundationDB. | `[]string` | `[]` |
| `imageType` | Container image deployment type. | `string` | `split` |
| `securityContext` | Security context for containers. | `object` | `{}` |
| `securityContext.runAsUser` | User ID to run the container. | `int` | `4059` |
| `securityContext.runAsGroup` | Group ID to run the container. | `int` | `4059` |
| `automaticReplacements` | Enable automatic pod replacements. | `bool` | `true` |
@@ -21,21 +21,33 @@ spec:
automationOptions:
replacements:
enabled: {{ .Values.automaticReplacements }}
faultDomain:
key: {{ .Values.cluster.faultDomain.key }}
{{- if .Values.cluster.faultDomain.valueFrom }}
valueFrom: {{ .Values.cluster.faultDomain.valueFrom }}
{{- end }}
imageType: {{ .Values.imageType }}
labels:
filterOnOwnerReference: false
matchLabels:
foundationdb.org/fdb-cluster-name: {{ .Release.Name }}
processClassLabels:
- foundationdb.org/fdb-process-class
processGroupIDLabels:
- foundationdb.org/fdb-process-group-id
minimumUptimeSecondsForBounce: 60
# The FoundationDBCluster CRD schema places faultDomain, imageType, labels,
# and minimumUptimeSecondsForBounce as direct children of spec (siblings of
# automationOptions). The chart historically nested them under
# automationOptions; Flux v2.7's client-side patch silently dropped the
# unknown fields, so the misconfiguration had no runtime effect. Flux v2.8's
# Server-Side Apply enforces the CRD schema and rejects the apply with
# "field not declared in schema". Move all four fields to where the
# operator actually reads them.
faultDomain:
key: {{ .Values.cluster.faultDomain.key }}
{{- if .Values.cluster.faultDomain.valueFrom }}
valueFrom: {{ .Values.cluster.faultDomain.valueFrom }}
{{- end }}
imageType: {{ .Values.imageType }}
labels:
filterOnOwnerReference: false
matchLabels:
foundationdb.org/fdb-cluster-name: {{ .Release.Name }}
processClassLabels:
- foundationdb.org/fdb-process-class
processGroupIDLabels:
- foundationdb.org/fdb-process-group-id
minimumUptimeSecondsForBounce: 60
processes:
general:
@@ -299,7 +299,7 @@
"imageType": {
"description": "Container image deployment type.",
"type": "string",
"default": "unified",
"default": "split",
"enum": [
"unified",
"split"
+7 -2
View File
@@ -147,8 +147,13 @@ customParameters: []
## @value unified
## @value split
## @param {ImageType} imageType="unified" - Container image deployment type.
imageType: "unified"
## @param {ImageType} imageType="split" - Container image deployment type.
# Defaults to "split" to match the operator default that existing clusters
# already run: before the Flux v2.8 SSA fix this value was nested under
# automationOptions and silently dropped, so the operator never saw "unified".
# Setting it to "split" keeps upgrades non-disruptive; switch to "unified"
# deliberately to migrate (triggers an in-place image-type change).
imageType: "split"
## @typedef {struct} SecurityContext - Security context for containers.
## @field {int} runAsUser - User ID to run the container.
@@ -53,7 +53,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
+3
View File
@@ -1,6 +1,9 @@
include ../../../hack/package.mk
PRESET_ENUM := ["nano","micro","small","medium","large","xlarge","2xlarge"]
test:
helm unittest .
generate:
cozyvalues-gen -m 'kafka' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/kafka/types.go
../../../hack/update-crd.sh
+7 -3
View File
@@ -100,9 +100,13 @@ spec:
topicOperator: {}
userOperator: {}
template:
# `pod` accepts metadata + a flat set of pod-spec fields
# (enableServiceLinks, securityContext, affinity, …) directly.
# The previous file nested enableServiceLinks under a phantom
# `template.spec` key — Flux v2.7 dropped it silently, v2.8 SSA
# rejects it with "field not declared in schema".
pod:
metadata:
labels:
policy.cozystack.io/allow-to-apiserver: "true"
spec:
labels:
policy.cozystack.io/allow-to-apiserver: "true"
enableServiceLinks: false
@@ -6,7 +6,7 @@ metadata:
labels:
workloads.cozystack.io/resource-preset: {{ .Values.kafka.resourcesPreset | quote }}
spec:
replicas: {{ .Values.replicas }}
replicas: {{ .Values.kafka.replicas }}
minReplicas: 1
kind: kafka
type: kafka
@@ -24,7 +24,7 @@ metadata:
labels:
workloads.cozystack.io/resource-preset: {{ .Values.zookeeper.resourcesPreset | quote }}
spec:
replicas: {{ .Values.replicas }}
replicas: {{ .Values.zookeeper.replicas }}
minReplicas: 1
kind: kafka
type: zookeeper
@@ -0,0 +1,22 @@
suite: Kafka entityOperator pod template
# Regression cover for the strict-SSA fix that moved enableServiceLinks out of
# a phantom `entityOperator.template.spec` key (silently dropped by Flux v2.7,
# rejected by v2.8 SSA as "field not declared in schema") into the flat
# `entityOperator.template.pod` set where the Strimzi CRD actually reads it.
templates:
- templates/kafka.yaml
tests:
- it: enableServiceLinks lives under entityOperator.template.pod
release:
name: test-kafka
namespace: tenant-test
asserts:
- equal:
path: spec.entityOperator.template.pod.enableServiceLinks
value: false
# the phantom template.spec key must not reappear
- notExists:
path: spec.entityOperator.template.spec
@@ -0,0 +1,70 @@
suite: Kafka WorkloadMonitor replica paths
# Regression cover for the fix that split the WorkloadMonitor replica
# source from a single phantom `.Values.replicas` (which does not exist in
# this chart's values — kafka and zookeeper carry their own counts) into the
# correct `.Values.kafka.replicas` and `.Values.zookeeper.replicas`. Before
# the fix both monitors rendered `replicas:` empty, so the workload-monitor
# controller never knew the expected replica count.
templates:
- templates/workloadmonitor.yaml
tests:
- it: kafka and zookeeper monitors read their own replica counts
release:
name: test-kafka
namespace: tenant-test
set:
kafka:
replicas: 5
zookeeper:
replicas: 2
asserts:
- hasDocuments:
count: 2
# doc 0 — kafka monitor
- documentIndex: 0
equal:
path: metadata.name
value: test-kafka
- documentIndex: 0
equal:
path: spec.type
value: kafka
- documentIndex: 0
equal:
path: spec.replicas
value: 5
# doc 1 — zookeeper monitor
- documentIndex: 1
equal:
path: metadata.name
value: test-kafka-zookeeper
- documentIndex: 1
equal:
path: spec.type
value: zookeeper
- documentIndex: 1
equal:
path: spec.replicas
value: 2
- it: replica counts stay independent (kafka != zookeeper)
release:
name: test-kafka
namespace: tenant-test
set:
kafka:
replicas: 7
zookeeper:
replicas: 3
asserts:
- documentIndex: 0
equal:
path: spec.replicas
value: 7
- documentIndex: 1
equal:
path: spec.replicas
value: 3
+71 -50
View File
@@ -221,56 +221,77 @@ See [`docs/operations/resource-presets.md`](../../../docs/operations/resource-pr
The following instanceType resources are provided by Cozystack:
| Name | vCPUs | Memory |
|---------------|-------|--------|
| `cx1.2xlarge` | 8 | 16Gi |
| `cx1.4xlarge` | 16 | 32Gi |
| `cx1.8xlarge` | 32 | 64Gi |
| `cx1.large` | 2 | 4Gi |
| `cx1.medium` | 1 | 2Gi |
| `cx1.xlarge` | 4 | 8Gi |
| `gn1.2xlarge` | 8 | 32Gi |
| `gn1.4xlarge` | 16 | 64Gi |
| `gn1.8xlarge` | 32 | 128Gi |
| `gn1.xlarge` | 4 | 16Gi |
| `m1.2xlarge` | 8 | 64Gi |
| `m1.4xlarge` | 16 | 128Gi |
| `m1.8xlarge` | 32 | 256Gi |
| `m1.large` | 2 | 16Gi |
| `m1.xlarge` | 4 | 32Gi |
| `n1.2xlarge` | 16 | 32Gi |
| `n1.4xlarge` | 32 | 64Gi |
| `n1.8xlarge` | 64 | 128Gi |
| `n1.large` | 4 | 8Gi |
| `n1.medium` | 4 | 4Gi |
| `n1.xlarge` | 8 | 16Gi |
| `o1.2xlarge` | 8 | 32Gi |
| `o1.4xlarge` | 16 | 64Gi |
| `o1.8xlarge` | 32 | 128Gi |
| `o1.large` | 2 | 8Gi |
| `o1.medium` | 1 | 4Gi |
| `o1.micro` | 1 | 1Gi |
| `o1.nano` | 1 | 512Mi |
| `o1.small` | 1 | 2Gi |
| `o1.xlarge` | 4 | 16Gi |
| `rt1.2xlarge` | 8 | 32Gi |
| `rt1.4xlarge` | 16 | 64Gi |
| `rt1.8xlarge` | 32 | 128Gi |
| `rt1.large` | 2 | 8Gi |
| `rt1.medium` | 1 | 4Gi |
| `rt1.micro` | 1 | 1Gi |
| `rt1.small` | 1 | 2Gi |
| `rt1.xlarge` | 4 | 16Gi |
| `u1.2xlarge` | 8 | 32Gi |
| `u1.2xmedium` | 2 | 4Gi |
| `u1.4xlarge` | 16 | 64Gi |
| `u1.8xlarge` | 32 | 128Gi |
| `u1.large` | 2 | 8Gi |
| `u1.medium` | 1 | 4Gi |
| `u1.micro` | 1 | 1Gi |
| `u1.nano` | 1 | 512Mi |
| `u1.small` | 1 | 2Gi |
| `u1.xlarge` | 4 | 16Gi |
| Name | vCPUs | Memory |
|------------------|-------|--------|
| `cx1.2xlarge` | 8 | 16Gi |
| `cx1.2xlarge1gi` | 8 | 16Gi |
| `cx1.4xlarge` | 16 | 32Gi |
| `cx1.4xlarge1gi` | 16 | 32Gi |
| `cx1.8xlarge` | 32 | 64Gi |
| `cx1.8xlarge1gi` | 32 | 64Gi |
| `cx1.large` | 2 | 4Gi |
| `cx1.large1gi` | 2 | 4Gi |
| `cx1.medium` | 1 | 2Gi |
| `cx1.medium1gi` | 1 | 2Gi |
| `cx1.xlarge` | 4 | 8Gi |
| `cx1.xlarge1gi` | 4 | 8Gi |
| `d1.2xlarge` | 8 | 32Gi |
| `d1.2xmedium` | 2 | 4Gi |
| `d1.4xlarge` | 16 | 64Gi |
| `d1.8xlarge` | 32 | 128Gi |
| `d1.large` | 2 | 8Gi |
| `d1.medium` | 1 | 4Gi |
| `d1.micro` | 1 | 1Gi |
| `d1.nano` | 1 | 512Mi |
| `d1.small` | 1 | 2Gi |
| `d1.xlarge` | 4 | 16Gi |
| `gn1.2xlarge` | 8 | 32Gi |
| `gn1.4xlarge` | 16 | 64Gi |
| `gn1.8xlarge` | 32 | 128Gi |
| `gn1.xlarge` | 4 | 16Gi |
| `m1.2xlarge` | 8 | 64Gi |
| `m1.2xlarge1gi` | 8 | 64Gi |
| `m1.4xlarge` | 16 | 128Gi |
| `m1.4xlarge1gi` | 16 | 128Gi |
| `m1.8xlarge` | 32 | 256Gi |
| `m1.8xlarge1gi` | 32 | 256Gi |
| `m1.large` | 2 | 16Gi |
| `m1.large1gi` | 2 | 16Gi |
| `m1.xlarge` | 4 | 32Gi |
| `m1.xlarge1gi` | 4 | 32Gi |
| `n1.2xlarge` | 16 | 32Gi |
| `n1.4xlarge` | 32 | 64Gi |
| `n1.8xlarge` | 64 | 128Gi |
| `n1.large` | 4 | 8Gi |
| `n1.medium` | 4 | 4Gi |
| `n1.xlarge` | 8 | 16Gi |
| `o1.2xlarge` | 8 | 32Gi |
| `o1.4xlarge` | 16 | 64Gi |
| `o1.8xlarge` | 32 | 128Gi |
| `o1.large` | 2 | 8Gi |
| `o1.medium` | 1 | 4Gi |
| `o1.micro` | 1 | 1Gi |
| `o1.nano` | 1 | 512Mi |
| `o1.small` | 1 | 2Gi |
| `o1.xlarge` | 4 | 16Gi |
| `rt1.2xlarge` | 8 | 32Gi |
| `rt1.4xlarge` | 16 | 64Gi |
| `rt1.8xlarge` | 32 | 128Gi |
| `rt1.large` | 2 | 8Gi |
| `rt1.medium` | 1 | 4Gi |
| `rt1.micro` | 1 | 1Gi |
| `rt1.small` | 1 | 2Gi |
| `rt1.xlarge` | 4 | 16Gi |
| `u1.2xlarge` | 8 | 32Gi |
| `u1.2xmedium` | 2 | 4Gi |
| `u1.4xlarge` | 16 | 64Gi |
| `u1.8xlarge` | 32 | 128Gi |
| `u1.large` | 2 | 8Gi |
| `u1.medium` | 1 | 4Gi |
| `u1.micro` | 1 | 1Gi |
| `u1.nano` | 1 | 512Mi |
| `u1.small` | 1 | 2Gi |
| `u1.xlarge` | 4 | 16Gi |
### Kubelet Resource Reservations
@@ -26,7 +26,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
{{- if .Values.addons.certManager.valuesOverride }}
@@ -36,11 +35,6 @@ spec:
valuesKey: values
{{- end }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- if .Values.addons.certManager.valuesOverride }}
---
apiVersion: v1
@@ -36,16 +36,11 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
{{- toYaml (deepCopy .Values.addons.certManager.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultCertManagerValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-cert-manager-crds
@@ -42,17 +42,12 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
{{- toYaml (deepCopy .Values.addons.cilium.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultCiliumValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- if $.Values.addons.gatewayAPI.enabled }}
dependsOn:
- name: {{ .Release.Name }}-gateway-api-crds
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -31,16 +31,11 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
{{- toYaml (deepCopy .Values.addons.coredns.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultCoreDNSValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -36,8 +36,4 @@ spec:
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- end }}
@@ -26,7 +26,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
@@ -35,10 +34,6 @@ spec:
tolerations: []
hostNetwork: false
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
---
@@ -74,10 +69,6 @@ spec:
{{- toYaml . | nindent 4 }}
{{- end }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-fluxcd-operator
@@ -25,12 +25,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- end }}
@@ -34,7 +34,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
{{- $defaults := fromYaml (include "cozystack.defaultGpuOperatorValues" .) }}
@@ -46,10 +45,6 @@ spec:
{{- end }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -29,7 +29,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
{{- with .Values.addons.hami.valuesOverride }}
@@ -38,10 +37,6 @@ spec:
{{- end }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-gpu-operator
@@ -48,16 +48,11 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
{{- toYaml (deepCopy .Values.addons.ingressNginx.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultIngressValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -29,10 +29,6 @@ spec:
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-prometheus-operator-crds
@@ -28,14 +28,9 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cozy-victoria-metrics-operator
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-vertical-pod-autoscaler-crds
@@ -138,7 +138,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
@@ -160,10 +159,6 @@ spec:
documented on the OuroborosAddon field. */ -}}
{{- toYaml (deepCopy .Values.addons.ouroboros.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultOuroborosValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-coredns
@@ -27,9 +27,4 @@ spec:
upgrade:
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- end }}
@@ -26,7 +26,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
{{- with .Values.addons.velero.valuesOverride }}
@@ -35,10 +34,6 @@ spec:
{{- end }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -27,10 +27,4 @@ spec:
upgrade:
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- end }}
@@ -52,16 +52,11 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
{{- toYaml (deepCopy .Values.addons.verticalPodAutoscaler.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultVPAValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-monitoring-agents
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -26,14 +26,9 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-cert-manager-crds
@@ -26,12 +26,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
{{- end }}
-1
View File
@@ -47,7 +47,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -15,7 +15,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -16,7 +16,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
-1
View File
@@ -23,7 +23,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -23,7 +23,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
-1
View File
@@ -22,7 +22,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -23,7 +23,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -23,7 +23,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -23,7 +23,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -0,0 +1,69 @@
suite: tenant HelmReleases carry no deprecated upgrade.force
# Flux v2.8 / helm-controller v1.5 deprecates `upgrade.force: true` and rejects
# it under Server-Side Apply. The flux-bump PR swept the flag off every tenant
# HelmRelease; gateway.yaml was missed in the first pass. This suite pins the
# invariant across all swept HRs so a stray `force: true` cannot creep back in.
# Restrict rendering to the swept HelmRelease templates so the chart's
# namespace.yaml `lookup` (which errors under helm-unittest) is not evaluated.
templates:
- templates/etcd.yaml
- templates/info.yaml
- templates/ingress.yaml
- templates/monitoring.yaml
- templates/seaweedfs.yaml
- templates/gateway.yaml
release:
name: tenant-test
namespace: tenant-test
set:
_cluster:
expose-ingress: tenant-root
expose-external-ips: "192.0.2.10"
gateway-enabled: "true"
etcd: true
ingress: true
monitoring: true
seaweedfs: true
gateway: true
host: ""
tests:
- it: etcd HR has no upgrade.force
asserts:
- template: templates/etcd.yaml
notExists:
path: spec.upgrade.force
- it: info HR has no upgrade.force
asserts:
- template: templates/info.yaml
notExists:
path: spec.upgrade.force
- it: ingress HR has no upgrade.force
asserts:
- template: templates/ingress.yaml
notExists:
path: spec.upgrade.force
- it: monitoring HR has no upgrade.force
asserts:
- template: templates/monitoring.yaml
notExists:
path: spec.upgrade.force
- it: seaweedfs HR has no upgrade.force
asserts:
- template: templates/seaweedfs.yaml
notExists:
path: spec.upgrade.force
- it: gateway HR has no upgrade.force
asserts:
- template: templates/gateway.yaml
notExists:
path: spec.upgrade.force
+7 -1
View File
@@ -4,6 +4,12 @@ generate:
cozyvalues-gen -m 'vminstance' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/vminstance/types.go
#INSTANCE_TYPES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/instancetypes.yaml | yq 'split(" ") | . + [""]' -o json) \
# && yq -i -o json ".properties.instanceType.enum = $${INSTANCE_TYPES}" values.schema.json
PREFERENCES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/preferences.yaml | yq 'split(" ") | . + [""]' -o json) \
# Union the upstream preference catalog with the Cozystack-local deprecated
# aliases in extra-instancetypes.yaml, so retained EOL profiles (e.g.
# centos.7*/centos.stream8*) stay in the enum and the dynamic CRD does not
# reject existing VMInstance CRs that reference them.
PREFERENCES=$$( { yq e '.metadata.name' ../../system/kubevirt-instancetypes/templates/preferences.yaml; \
yq e 'select(.kind == "VirtualMachineClusterPreference") | .metadata.name' ../../system/kubevirt-instancetypes/templates/extra-instancetypes.yaml; } \
| grep -E -v -- '^(---)?$$' | sort -u | jq -R . | jq -s '. + [""]' ) \
&& yq -i -o json ".properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json
../../../hack/update-crd.sh
+40 -7
View File
@@ -184,20 +184,41 @@ The following instancetype resources are provided by Cozystack:
Name | vCPUs | Memory
-----|-------|-------
cx1.2xlarge | 8 | 16Gi
cx1.2xlarge1gi | 8 | 16Gi
cx1.4xlarge | 16 | 32Gi
cx1.4xlarge1gi | 16 | 32Gi
cx1.8xlarge | 32 | 64Gi
cx1.8xlarge1gi | 32 | 64Gi
cx1.large | 2 | 4Gi
cx1.large1gi | 2 | 4Gi
cx1.medium | 1 | 2Gi
cx1.medium1gi | 1 | 2Gi
cx1.xlarge | 4 | 8Gi
cx1.xlarge1gi | 4 | 8Gi
d1.2xlarge | 8 | 32Gi
d1.2xmedium | 2 | 4Gi
d1.4xlarge | 16 | 64Gi
d1.8xlarge | 32 | 128Gi
d1.large | 2 | 8Gi
d1.medium | 1 | 4Gi
d1.micro | 1 | 1Gi
d1.nano | 1 | 512Mi
d1.small | 1 | 2Gi
d1.xlarge | 4 | 16Gi
gn1.2xlarge | 8 | 32Gi
gn1.4xlarge | 16 | 64Gi
gn1.8xlarge | 32 | 128Gi
gn1.xlarge | 4 | 16Gi
m1.2xlarge | 8 | 64Gi
m1.2xlarge1gi | 8 | 64Gi
m1.4xlarge | 16 | 128Gi
m1.4xlarge1gi | 16 | 128Gi
m1.8xlarge | 32 | 256Gi
m1.8xlarge1gi | 32 | 256Gi
m1.large | 2 | 16Gi
m1.large1gi | 2 | 16Gi
m1.xlarge | 4 | 32Gi
m1.xlarge1gi | 4 | 32Gi
n1.2xlarge | 16 | 32Gi
n1.4xlarge | 32 | 64Gi
n1.8xlarge | 64 | 128Gi
@@ -237,23 +258,26 @@ The following preference resources are provided by Cozystack:
Name | Guest OS
-----|---------
alpine | Alpine
centos.7 | CentOS 7
centos.7.desktop | CentOS 7
centos.stream10 | CentOS Stream 10
centos.stream10.desktop | CentOS Stream 10
centos.stream8 | CentOS Stream 8
centos.stream8.desktop | CentOS Stream 8
centos.stream8.dpdk | CentOS Stream 8
centos.stream9 | CentOS Stream 9
centos.stream9.desktop | CentOS Stream 9
centos.stream9.dpdk | CentOS Stream 9
cirros | Cirros
debian | Debian
fedora | Fedora (amd64)
fedora.arm64 | Fedora (arm64)
fedora.s390x | Fedora (s390x)
legacy | Legacy Guest
linux | Linux Guest
linux.efi | Linux EFI Guest
linux.virtiotransitional | Linux Virtio Transitional Guest
opensuse.leap | OpenSUSE Leap
opensuse.tumbleweed | OpenSUSE Tumbleweed
rhel.10 | Red Hat Enterprise Linux 10 Beta (amd64)
rhel.10.arm64 | Red Hat Enterprise Linux 10 Beta (arm64)
oraclelinux | Oracle Linux
rhel.10 | Red Hat Enterprise Linux 10 (amd64)
rhel.10.arm64 | Red Hat Enterprise Linux 10 (arm64)
rhel.10.s390x | Red Hat Enterprise Linux 10 (s390x)
rhel.7 | Red Hat Enterprise Linux 7
rhel.7.desktop | Red Hat Enterprise Linux 7
rhel.8 | Red Hat Enterprise Linux 8
@@ -264,12 +288,15 @@ rhel.9.arm64 | Red Hat Enterprise Linux 9 (arm64)
rhel.9.desktop | Red Hat Enterprise Linux 9 Desktop (amd64)
rhel.9.dpdk | Red Hat Enterprise Linux 9 DPDK (amd64)
rhel.9.realtime | Red Hat Enterprise Linux 9 Realtime (amd64)
rhel.9.s390x | Red Hat Enterprise Linux 9 (s390x)
sles | SUSE Linux Enterprise Server
ubuntu | Ubuntu
windows.10 | Microsoft Windows 10
windows.10.virtio | Microsoft Windows 10 (virtio)
windows.11 | Microsoft Windows 11
windows.11.virtio | Microsoft Windows 11 (virtio)
windows.2k12 | Microsoft Windows Server 2012/2012 R2
windows.2k12.virtio | Microsoft Windows Server 2012/2012 R2 (virtio)
windows.2k16 | Microsoft Windows Server 2016
windows.2k16.virtio | Microsoft Windows Server 2016 (virtio)
windows.2k19 | Microsoft Windows Server 2019
@@ -278,3 +305,9 @@ windows.2k22 | Microsoft Windows Server 2022
windows.2k22.virtio | Microsoft Windows Server 2022 (virtio)
windows.2k25 | Microsoft Windows Server 2025
windows.2k25.virtio | Microsoft Windows Server 2025 (virtio)
windows.2k3 | Microsoft Windows Server 2003
windows.2k8 | Microsoft Windows Server 2008/2008 R2
windows.2k8.virtio | Microsoft Windows Server 2008/2008 R2 (virtio)
windows.7 | Microsoft Windows 7
windows.7.virtio | Microsoft Windows 7 (virtio)
windows.xp | Microsoft Windows XP
+6 -6
View File
@@ -67,14 +67,14 @@ spec:
- name: disk-{{ $disk.name }}
{{- $dv := lookup "cdi.kubevirt.io/v1beta1" "DataVolume" $.Release.Namespace (printf "vm-disk-%s" $disk.name) }}
{{- if $dv }}
{{- if and (hasKey $dv.metadata.annotations "vm-disk.cozystack.io/optical") (eq (index $dv.metadata.annotations "vm-disk.cozystack.io/optical") "true") }}
cdrom:
{{- $isOptical := and (hasKey $dv.metadata.annotations "vm-disk.cozystack.io/optical") (eq (index $dv.metadata.annotations "vm-disk.cozystack.io/optical") "true") }}
{{- $deviceKey := ternary "cdrom" "disk" $isOptical }}
{{- if $disk.bus }}
{{ $deviceKey }}:
bus: {{ $disk.bus }}
{{- else }}
disk:
{{ $deviceKey }}: {}
{{- end }}
{{- with $disk.bus }}
bus: {{ . }}
{{- end }}
bootOrder: {{ add $i 1 }}
{{- else }}
{{- fail (printf "Specified disk not exists in cluster: %s" .name) }}
@@ -65,12 +65,20 @@
"centos.stream9.desktop",
"centos.stream9.dpdk",
"cirros",
"debian",
"fedora",
"fedora.arm64",
"fedora.s390x",
"legacy",
"linux",
"linux.efi",
"linux.virtiotransitional",
"opensuse.leap",
"opensuse.tumbleweed",
"oraclelinux",
"rhel.10",
"rhel.10.arm64",
"rhel.10.s390x",
"rhel.7",
"rhel.7.desktop",
"rhel.8",
@@ -81,12 +89,15 @@
"rhel.9.desktop",
"rhel.9.dpdk",
"rhel.9.realtime",
"rhel.9.s390x",
"sles",
"ubuntu",
"windows.10",
"windows.10.virtio",
"windows.11",
"windows.11.virtio",
"windows.2k12",
"windows.2k12.virtio",
"windows.2k16",
"windows.2k16.virtio",
"windows.2k19",
@@ -95,6 +106,12 @@
"windows.2k22.virtio",
"windows.2k25",
"windows.2k25.virtio",
"windows.2k3",
"windows.2k8",
"windows.2k8.virtio",
"windows.7",
"windows.7.virtio",
"windows.xp",
""
]
},
+1
View File
@@ -22,3 +22,4 @@ update:
-e 's|\.cluster\.local\.,||g' -e 's|\.cluster\.local\,||g' -e 's|\.cluster\.local\.||g' \
-e 's|--storage-adv-addr=source-watcher.$$(RUNTIME_NAMESPACE).svc|--storage-adv-addr=flux.$$(RUNTIME_NAMESPACE).svc|'
yq eval '.spec.template.spec.containers[0].image = "'"$$(yq eval 'select(.kind == "Deployment" and .metadata.name == "flux") | .spec.template.spec.containers[] | select(.name == "helm-controller").image' $(MANIFESTS_DIR)/fluxcd.yaml)"'"' -i $(MANIFESTS_DIR)/fluxcd-tenants.yaml
yq eval '.metadata.labels."app.kubernetes.io/version" = "'"$$(yq eval 'select(.kind == "Deployment" and .metadata.name == "flux") | .metadata.labels."app.kubernetes.io/version"' $(MANIFESTS_DIR)/fluxcd.yaml)"'"' -i $(MANIFESTS_DIR)/fluxcd-tenants.yaml
+47
View File
@@ -0,0 +1,47 @@
#!/bin/sh
# Migration 43 --> 44
# Adopt existing Cluster/seaweedfs-db resources into the new seaweedfs-db
# HelmRelease introduced in this release.
#
# Pre-split, the CNPG Cluster lived inside the seaweedfs-system Helm release.
# Splitting moves it to a new release named seaweedfs-db. We rewrite the
# helm ownership annotations so Helm adopts the existing Cluster instead of
# erroring on the next reconcile, and stamp helm.sh/resource-policy: keep
# so the seaweedfs-system upgrade (which no longer renders the Cluster) does
# not delete it during the transition.
set -euo pipefail
# Iterate every namespace that has a Cluster named "seaweedfs-db".
for ns in $(kubectl get cluster.postgresql.cnpg.io -A \
-o jsonpath='{range .items[?(@.metadata.name=="seaweedfs-db")]}{.metadata.namespace}{"\n"}{end}'); do
current=$(kubectl get cluster.postgresql.cnpg.io seaweedfs-db -n "$ns" \
-o jsonpath='{.metadata.annotations.meta\.helm\.sh/release-name}' 2>/dev/null || true)
if [ "$current" = "seaweedfs-system" ]; then
echo "Re-annotating Cluster/seaweedfs-db in $ns: seaweedfs-system -> seaweedfs-db"
kubectl annotate cluster.postgresql.cnpg.io seaweedfs-db -n "$ns" \
meta.helm.sh/release-name=seaweedfs-db \
helm.sh/resource-policy=keep \
--overwrite
# release-namespace stays the same (tenant namespace, e.g. tenant-root)
fi
done
# Stamp version.
# Mirror migration 42's labeled manifest. A label-less apply by the same field
# manager (kubectl create | kubectl apply) would strip the
# platform.cozystack.io/no-delete label migration 42 added, dropping
# cozystack-version out of the cozystack-no-delete-guardrail
# ValidatingAdmissionPolicy. templates/cozystack-version.yaml only re-renders the
# labeled ConfigMap on first install, so the label must be carried inline here.
kubectl apply --filename - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: cozystack-version
namespace: cozy-system
labels:
platform.cozystack.io/no-delete: "true"
data:
version: "44"
EOF
@@ -17,6 +17,8 @@ spec:
- name: cozy-lib
path: library/cozy-lib
components:
- name: seaweedfs-db
path: system/seaweedfs-db
- name: seaweedfs-system
path: system/seaweedfs
- name: seaweedfs
+1 -1
View File
@@ -6,7 +6,7 @@ sourceRef:
migrations:
enabled: false
image: ghcr.io/cozystack/cozystack/platform-migrations:v1.4.0-rc.2@sha256:17390197a9b11d76a8dd1b24c6d1512adb7d3226b28b5bcba8551b14b1ec4be0
targetVersion: 43
targetVersion: 44
# Bundle deployment configuration
bundles:
system:
@@ -19,7 +19,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
values:
@@ -17,7 +17,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -15,7 +15,6 @@ spec:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -0,0 +1,47 @@
{{- if not (eq .Values.topology "Client") }}
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: {{ .Release.Name }}-db
labels:
sharding.fluxcd.io/key: tenants
spec:
chartRef:
kind: ExternalArtifact
name: cozystack-seaweedfs-application-default-seaweedfs-db
namespace: cozy-system
interval: 5m
timeout: 10m
install:
remediation:
retries: -1
upgrade:
remediation:
retries: -1
# `poller` waitStrategy is required for healthCheckExprs to be evaluated.
# Without it, the HR flips Ready as soon as helm install applies the Cluster CR,
# before CNPG has bootstrapped postgres.
waitStrategy:
name: poller
# CNPG sets Ready=False with reason=ClusterIsNotReady during normal bootstrap,
# so a plain Ready=False predicate flags the HR failed within seconds. Treat
# the bootstrap reason as in-progress; reserve `failed` for other Ready=False
# reasons CNPG might add in the future. The HR `timeout:` is the real backstop.
healthCheckExprs:
- apiVersion: postgresql.cnpg.io/v1
kind: Cluster
inProgress: has(status.conditions) && status.conditions.exists(e, e.type == 'Ready' && e.status == 'False' && e.reason == 'ClusterIsNotReady')
failed: has(status.conditions) && status.conditions.exists(e, e.type == 'Ready' && e.status == 'False' && e.reason != 'ClusterIsNotReady')
current: has(status.conditions) && status.conditions.exists(e, e.type == 'Ready' && e.status == 'True')
valuesFrom:
- kind: Secret
name: cozystack-values
values:
db:
replicas: {{ .Values.db.replicas }}
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.db.resourcesPreset .Values.db.resources $) | nindent 8 }}
size: {{ .Values.db.size }}
{{- with .Values.db.storageClass }}
storageClass: {{ . }}
{{- end }}
{{- end }}
@@ -104,12 +104,13 @@ metadata:
labels:
sharding.fluxcd.io/key: tenants
spec:
dependsOn:
- name: {{ .Release.Name }}-db
{{- if eq $ingress .Release.Namespace }}
# Ensure the ingress-nginx admission webhook is ready before creating Ingress resources.
# Only when this tenant owns its ingress; sub-tenants inherit ingress from a parent
# namespace where ingress-nginx-system already runs, and the dependency would deadlock
# because the HR doesn't exist locally.
dependsOn:
- name: ingress-nginx-system
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -117,13 +118,12 @@ spec:
kind: ExternalArtifact
name: cozystack-seaweedfs-application-default-seaweedfs-system
namespace: cozy-system
interval: 5m
interval: 30s
timeout: 10m
install:
remediation:
retries: -1
upgrade:
force: true
remediation:
retries: -1
valuesFrom:
@@ -132,13 +132,6 @@ spec:
values:
global:
serviceAccountName: "{{ .Release.Namespace }}-seaweedfs"
db:
replicas: {{ .Values.db.replicas }}
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.db.resourcesPreset .Values.db.resources $) | nindent 8 }}
size: {{ .Values.db.size }}
{{- with .Values.db.storageClass }}
storageClass: {{ . }}
{{- end }}
seaweedfs:
master:
{{ if eq .Values.topology "Simple" }}
@@ -37,7 +37,7 @@ spec:
name: cozystack-tenant-application-default-tenant
namespace: cozy-system
interval: 1m0s
timeout: 5m0s
timeout: 15m0s
valuesFrom:
- kind: Secret
name: cozystack-values
@@ -2,15 +2,15 @@ annotations:
artifacthub.io/license: AGPL-3.0
artifacthub.io/links: |
- name: Documentation
url: https://fluxcd.control-plane.io/operator
url: https://fluxoperator.dev/docs
- name: Chart Source
url: https://github.com/controlplaneio-fluxcd/charts
- name: Upstream Project
url: https://github.com/controlplaneio-fluxcd/flux-operator
apiVersion: v2
appVersion: v0.33.0
appVersion: v0.50.0
description: 'A Helm chart for deploying the Flux Operator. '
home: https://github.com/controlplaneio-fluxcd
home: https://fluxoperator.dev
icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png
keywords:
- flux
@@ -25,4 +25,4 @@ sources:
- https://github.com/controlplaneio-fluxcd/flux-operator
- https://github.com/controlplaneio-fluxcd/charts
type: application
version: 0.33.0
version: 0.50.0
@@ -1,6 +1,6 @@
# flux-operator
![Version: 0.33.0](https://img.shields.io/badge/Version-0.33.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.33.0](https://img.shields.io/badge/AppVersion-v0.33.0-informational?style=flat-square)
![Version: 0.50.0](https://img.shields.io/badge/Version-0.50.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.50.0](https://img.shields.io/badge/AppVersion-v0.50.0-informational?style=flat-square)
The [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator) provides a
declarative API for the installation and upgrade of CNCF [Flux](https://fluxcd.io) and the
@@ -9,12 +9,15 @@ ControlPlane [enterprise distribution](https://control-plane.io/enterprise-for-f
The operator automates the patching for hotfixes and CVEs affecting the Flux controllers container images
and enables the configuration of multi-tenancy lockdown on Kubernetes and OpenShift clusters.
The operator comes with the Flux Status Page web UI exposed on port `9080` that allows users to visualize the
status of the Flux installation and monitor the GitOps delivery pipeline in real-time.
## Prerequisites
- Kubernetes 1.22+
- Kubernetes 1.30+
- Helm 3.8+
## Installing the Chart
## Installing Flux Operator
To install the operator in the `flux-system` namespace:
@@ -25,8 +28,22 @@ helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-opera
--wait
```
## Installing the Flux Web UI as a Standalone Deployment
You can install the Flux Status Web UI as a dedicated deployment in your Kubernetes cluster,
separate from the Flux Operator with:
```console
helm install flux-web oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator \
--namespace flux-system \
--set fullnameOverride=flux-web \
--set web.serverOnly=true \
--set installCRDs=false \
--wait
```
To deploy the Flux controllers and to configure automated updates,
see the Flux Operator [documentation](https://fluxcd.control-plane.io/operator/).
see the Flux Operator [documentation](https://fluxoperator.dev/docs/).
## Values
@@ -47,7 +64,7 @@ see the Flux Operator [documentation](https://fluxcd.control-plane.io/operator/)
| livenessProbe | object | `{"httpGet":{"path":"/healthz","port":8081},"initialDelaySeconds":15,"periodSeconds":20}` | Container liveness probe settings. |
| logLevel | string | `"info"` | Container logging level flag. |
| marketplace | object | `{"account":"","license":"","type":""}` | Marketplace settings. |
| multitenancy | object | `{"defaultServiceAccount":"flux-operator","defaultWorkloadIdentityServiceAccount":"flux-operator","enabled":false,"enabledForWorkloadIdentity":false}` | Enable [multitenancy lockdown](https://fluxcd.control-plane.io/operator/resourceset/#role-based-access-control) for the ResourceSet APIs. |
| multitenancy | object | `{"defaultServiceAccount":"flux-operator","defaultWorkloadIdentityServiceAccount":"flux-operator","enabled":false,"enabledForWorkloadIdentity":false}` | Enable [multitenancy lockdown](https://fluxoperator.dev/docs/crd/resourceset/#role-based-access-control) for the ResourceSet APIs. |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | Pod Node Selector settings. |
| podSecurityContext | object | `{}` | Pod security context settings. |
@@ -55,12 +72,22 @@ see the Flux Operator [documentation](https://fluxcd.control-plane.io/operator/)
| rbac.create | bool | `true` | Grant the cluster-admin role to the flux-operator service account (required for the Flux Instance deployment). |
| rbac.createAggregation | bool | `true` | Grant the Kubernetes view, edit and admin roles access to ResourceSet APIs. |
| readinessProbe | object | `{"httpGet":{"path":"/readyz","port":8081},"initialDelaySeconds":5,"periodSeconds":10}` | Container readiness probe settings. |
| reporting | object | `{"interval":"5m"}` | Flux [reporting](https://fluxcd.control-plane.io/operator/fluxreport/) settings. |
| reporting | object | `{"interval":"5m"}` | Flux [reporting](https://fluxoperator.dev/docs/crd/fluxreport/) settings. |
| resources | object | `{"limits":{"cpu":"2000m","memory":"1Gi"},"requests":{"cpu":"100m","memory":"64Mi"}}` | Container resources requests and limits settings. |
| securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Container security context settings. The default is compliant with the pod security restricted profile. |
| service.ipFamilyPolicy | string | `""` | Sets the IP family policy on all Service resources. Uses Kubernetes defaults if unset |
| serviceAccount | object | `{"automount":true,"create":true,"name":""}` | Pod service account settings. The name of the service account defaults to the release name. |
| serviceMonitor | object | `{"create":false,"interval":"60s","labels":{},"scrapeTimeout":"30s"}` | Prometheus Operator scraping settings. |
| tolerations | list | `[]` | Pod tolerations settings. |
| web.config | object | `{}` | The spec of the [Web Config API](https://fluxoperator.dev/docs/web-ui/web-config-api/) |
| web.configSecretName | string | `""` | Reference to an existing Secret in the same namespace as the deployment containing the Web Config API. Should have the key `config.yaml`. |
| web.enabled | bool | `true` | Enable the [Flux Status web server](https://fluxoperator.dev/web-ui/) on port 9080. |
| web.httpRoute | object | `{"annotations":{},"enabled":false,"hostnames":[],"parentRefs":[]}` | Gateway API HTTPRoute settings for the Flux Status web interface. |
| web.ingress | object | `{"annotations":{},"className":"","enabled":false,"hosts":[],"tls":[]}` | Ingress settings for the Flux Status web interface. |
| web.networkPolicy | object | `{"create":true}` | Create a NetworkPolicy to allow access to the Flux Status web interface. |
| web.rbac | object | `{"createAggregation":false,"createRoles":true}` | Create standard roles for [user access management](https://fluxoperator.dev/docs/web-ui/user-management/). |
| web.serverOnly | bool | `false` | Run the Flux Status web server as a standalone deployment (requires a dedicated Helm release). |
| web.serverReplicas | int | `1` | Number of replicas for the Flux Status web server standalone deployment (only applicable if `web.serverOnly` is `true`). |
## Source Code
@@ -1 +1 @@
Documentation at https://fluxcd.control-plane.io/operator/
Documentation at https://fluxoperator.dev/docs/
@@ -56,3 +56,63 @@ Create the name of the service account to use
{{- define "flux-operator.serviceAccountName" -}}
{{- default (include "flux-operator.fullname" .) .Values.serviceAccount.name }}
{{- end }}
{{/*
Check if web config secret should be created.
Returns "true" when web is enabled, config is provided inline, and no external secret is referenced.
*/}}
{{- define "flux-operator.createWebConfigSecret" -}}
{{- if and .Values.web.enabled .Values.web.config (not .Values.web.configSecretName) -}}
true
{{- end -}}
{{- end }}
{{/*
Check if an external web config secret is referenced.
Returns "true" when web is enabled, an external secret name is provided, and no inline config is set.
*/}}
{{- define "flux-operator.useWebConfigSecret" -}}
{{- if and .Values.web.enabled .Values.web.configSecretName (not .Values.web.config) -}}
true
{{- end -}}
{{- end }}
{{/*
Check if running in web server only mode.
Returns "true" when web is enabled and serverOnly mode is set.
*/}}
{{- define "flux-operator.webServerOnly" -}}
{{- if and .Values.web.enabled .Values.web.serverOnly -}}
true
{{- end -}}
{{- end }}
{{/*
Check if web server replicas should be set.
Returns "true" when web is enabled, serverOnly mode is set, and serverReplicas is greater than 1.
*/}}
{{- define "flux-operator.setWebServerReplicas" -}}
{{- if and .Values.web.enabled .Values.web.serverOnly (gt (int .Values.web.serverReplicas) 1) -}}
true
{{- end -}}
{{- end }}
{{/*
Check if web roles should be created.
Returns "true" when web is enabled and createRoles is enabled.
*/}}
{{- define "flux-operator.createWebRoles" -}}
{{- if and .Values.web.enabled .Values.web.rbac.createRoles -}}
true
{{- end -}}
{{- end }}
{{/*
Check if web roles aggregation should be created.
Returns "true" when web is enabled and createAggregation is enabled.
*/}}
{{- define "flux-operator.createWebRolesAggregation" -}}
{{- if and .Values.web.enabled .Values.web.rbac.createAggregation -}}
true
{{- end -}}
{{- end }}
@@ -1,4 +1,4 @@
{{- if .Values.rbac.create }}
{{- if and .Values.rbac.create (not (include "flux-operator.webServerOnly" .)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
@@ -1,4 +1,4 @@
{{- if .Values.rbac.createAggregation }}
{{- if and .Values.rbac.createAggregation (not (include "flux-operator.webServerOnly" .)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.19.0
controller-gen.kubebuilder.io/version: v0.21.0
helm.sh/resource-policy: keep
labels:
app.kubernetes.io/instance: '{{ .Release.Name }}'
@@ -164,7 +164,11 @@ spec:
components:
description: |-
Components is the list of controllers to install.
Defaults to a commonly used subset.
Defaults to the core Flux controllers:
- source-controller
- kustomize-controller
- helm-controller
- notification-controller
items:
description: Component is the name of a controller to install.
enum:
@@ -211,6 +215,7 @@ spec:
- upstream-alpine
- enterprise-alpine
- enterprise-distroless
- enterprise-distroless-fips
type: string
version:
description: Version semver expression e.g. '2.x', '2.3.x'.
@@ -370,7 +375,8 @@ spec:
description: |-
Provider specifies OIDC provider for source authentication.
For OCIRepository and Bucket the provider can be set to 'aws', 'azure' or 'gcp'.
for GitRepository the accepted value can be set to 'azure' or 'github'.
For GitRepository the provider can be set to 'aws' (requires Flux 2.9 or later),
'azure' or 'github'.
To disable OIDC authentication the provider can be set to 'generic' or left empty.
enum:
- generic
@@ -404,6 +410,14 @@ spec:
- ref
- url
type: object
x-kubernetes-validations:
- message: sync.provider 'gcp' is only supported for OCIRepository
and Bucket
rule: '!has(self.provider) || self.provider != ''gcp'' || self.kind
== ''OCIRepository'' || self.kind == ''Bucket'''
- message: sync.provider 'github' is only supported for GitRepository
rule: '!has(self.provider) || self.provider != ''github'' || self.kind
== ''GitRepository'''
wait:
default: true
description: |-
@@ -618,7 +632,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.19.0
controller-gen.kubebuilder.io/version: v0.21.0
helm.sh/resource-policy: keep
labels:
app.kubernetes.io/instance: '{{ .Release.Name }}'
@@ -785,7 +799,7 @@ spec:
failing:
description: |-
Failing is the number of reconciled
resources in the Failing state.
resources in the Failing state and not Suspended.
type: integer
running:
description: |-
@@ -921,7 +935,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.19.0
controller-gen.kubebuilder.io/version: v0.21.0
helm.sh/resource-policy: keep
labels:
app.kubernetes.io/instance: '{{ .Release.Name }}'
@@ -985,9 +999,9 @@ spec:
- a PEM-encoded CA certificate (`ca.crt`)
- a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`)
When connecting to a Git or OCI provider that uses self-signed certificates, the CA certificate
must be set in the Secret under the 'ca.crt' key to establish the trust relationship.
When connecting to an OCI provider that supports client certificates (mTLS), the client certificate
When connecting to a Git, OCI, or ExternalService provider that uses self-signed certificates,
the CA certificate must be set in the Secret under the 'ca.crt' key to establish the trust relationship.
When connecting to a provider that supports client certificates (mTLS), the client certificate
and private key must be set in the Secret under the 'tls.crt' and 'tls.key' keys, respectively.
properties:
name:
@@ -1013,6 +1027,11 @@ spec:
ExcludeBranch specifies the regular expression to filter the branches
that the input provider should exclude.
type: string
excludeEnvironment:
description: |-
ExcludeEnvironment specifies the regular expression to filter the environments
that the input provider should exclude.
type: string
excludeTag:
description: |-
ExcludeTag specifies the regular expression to filter the tags
@@ -1023,6 +1042,11 @@ spec:
IncludeBranch specifies the regular expression to filter the branches
that the input provider should include.
type: string
includeEnvironment:
description: |-
IncludeEnvironment specifies the regular expression to filter the environments
that the input provider should include.
type: string
includeTag:
description: |-
IncludeTag specifies the regular expression to filter the tags
@@ -1048,6 +1072,11 @@ spec:
Supported only for tags at the moment.
type: string
type: object
insecure:
description: |-
Insecure allows connecting to an ExternalService or OCIArtifactTag provider
over plain HTTP without TLS. When not set, the URL must use HTTPS.
type: boolean
schedule:
description: Schedule defines the schedules for the input provider
to run.
@@ -1075,13 +1104,16 @@ spec:
type: array
secretRef:
description: |-
SecretRef specifies the Kubernetes Secret containing the basic-auth credentials
SecretRef specifies the Kubernetes Secret containing the credentials
to access the input provider.
When connecting to a Git provider, the secret must contain the keys
'username' and 'password', and the password should be a personal access token
that grants read-only access to the repository.
When connecting to an OCI provider, the secret must contain a Kubernetes
Image Pull Secret, as if created by `kubectl create secret docker-registry`.
When connecting to an ExternalService provider, the secret must contain either
a 'token' key for bearer token authentication, or 'username' and 'password'
keys for basic authentication.
properties:
name:
description: Name of the referent.
@@ -1119,13 +1151,21 @@ spec:
- GitLabBranch
- GitLabTag
- GitLabMergeRequest
- GitLabEnvironment
- AzureDevOpsBranch
- AzureDevOpsTag
- AzureDevOpsPullRequest
- AWSCodeCommitBranch
- AWSCodeCommitTag
- AWSCodeCommitPullRequest
- GiteaBranch
- GiteaTag
- GiteaPullRequest
- OCIArtifactTag
- ACRArtifactTag
- ECRArtifactTag
- GARArtifactTag
- ExternalService
type: string
url:
description: |-
@@ -1146,23 +1186,39 @@ spec:
is a Git provider
rule: '!self.type.startsWith(''Git'') || self.url.startsWith(''http'')'
- message: spec.url must start with 'http://' or 'https://' when spec.type
is a Git provider
rule: '!self.type.startsWith(''AzureDevOps'') || self.url.startsWith(''http'')'
is an AzureDevOps provider
rule: '!self.type.startsWith(''AzureDevOps'') || self.url.startsWith(''http://'')
|| self.url.startsWith(''https://'')'
- message: spec.url must start with 'https://' when spec.type is a AWSCodeCommit
provider
rule: '!self.type.startsWith(''AWSCodeCommit'') || self.url.startsWith(''https://'')'
- message: spec.url must start with 'oci://' when spec.type is an OCI
provider
rule: '!self.type.endsWith(''ArtifactTag'') || self.url.startsWith(''oci'')'
- message: spec.url must start with 'http://' or 'https://' when spec.type
is 'ExternalService'
rule: self.type != 'ExternalService' || self.url.startsWith('http')
- message: spec.insecure can only be set when spec.type is 'ExternalService'
or 'OCIArtifactTag'
rule: '!has(self.insecure) || !self.insecure || self.type == ''ExternalService''
|| self.type == ''OCIArtifactTag'''
- message: spec.url must use 'https://' unless spec.insecure is true
rule: self.type != 'ExternalService' || !self.url.startsWith('http://')
|| (has(self.insecure) && self.insecure)
- message: cannot specify spec.serviceAccountName when spec.type is not
one of AzureDevOps* or *ArtifactTag
one of AzureDevOps*, AWSCodeCommit* or *ArtifactTag
rule: '!has(self.serviceAccountName) || self.type.startsWith(''AzureDevOps'')
|| self.type.endsWith(''ArtifactTag'')'
|| self.type.startsWith(''AWSCodeCommit'') || self.type.endsWith(''ArtifactTag'')'
- message: cannot specify spec.certSecretRef when spec.type is one of
Static, AzureDevOps*, ACRArtifactTag, ECRArtifactTag or GARArtifactTag
Static, AzureDevOps*, AWSCodeCommit*, ACRArtifactTag, ECRArtifactTag
or GARArtifactTag
rule: '!has(self.certSecretRef) || !(self.url == ''Static'' || self.type.startsWith(''AzureDevOps'')
|| (self.type.endsWith(''ArtifactTag'') && self.type != ''OCIArtifactTag''))'
- message: cannot specify spec.secretRef when spec.type is one of Static,
ACRArtifactTag, ECRArtifactTag or GARArtifactTag
rule: '!has(self.secretRef) || !(self.url == ''Static'' || (self.type.endsWith(''ArtifactTag'')
|| self.type.startsWith(''AWSCodeCommit'') || (self.type.endsWith(''ArtifactTag'')
&& self.type != ''OCIArtifactTag''))'
- message: cannot specify spec.secretRef when spec.type is one of Static,
AWSCodeCommit*, ACRArtifactTag, ECRArtifactTag or GARArtifactTag
rule: '!has(self.secretRef) || !(self.url == ''Static'' || self.type.startsWith(''AWSCodeCommit'')
|| (self.type.endsWith(''ArtifactTag'') && self.type != ''OCIArtifactTag''))'
status:
description: ResourceSetInputProviderStatus defines the observed state
of ResourceSetInputProvider.
@@ -1289,7 +1345,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.19.0
controller-gen.kubebuilder.io/version: v0.21.0
helm.sh/resource-policy: keep
labels:
app.kubernetes.io/instance: '{{ .Release.Name }}'
@@ -1403,6 +1459,15 @@ spec:
input provider objects are used. Defaults to flattening all inputs
from all providers into a single list of input sets.
properties:
includeEmptyProviders:
description: |-
IncludeEmptyProviders controls how input providers that export no
inputs are treated. Only applies when Name is Permute. When true, if
any provider has zero inputs the resulting permutation set is empty
(mathematically correct Cartesian product behavior). When false or
unset (default), providers with zero inputs are silently skipped and
the remaining providers still permute among themselves.
type: boolean
name:
description: |-
Name defines how the inputs are combined when multiple
@@ -1425,6 +1490,9 @@ spec:
required:
- name
type: object
x-kubernetes-validations:
- message: includeEmptyProviders only applies when name is Permute
rule: '!has(self.includeEmptyProviders) || self.name == ''Permute'''
inputs:
description: Inputs contains the list of ResourceSet inputs.
items:
@@ -1603,6 +1671,16 @@ spec:
- type
type: object
type: array
externalChecksumRefs:
description: |-
ExternalChecksumRefs lists the ConfigMap and Secret references
discovered in checksumFrom annotations on the last reconciliation
that point to objects not rendered by this ResourceSet. Each entry
has the form "Kind/namespace/name". It is used to trigger a
reconciliation when one of the referenced objects changes.
items:
type: string
type: array
history:
description: |-
History contains the reconciliation history of the ResourceSet
@@ -13,6 +13,9 @@ metadata:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if include "flux-operator.setWebServerReplicas" . }}
replicas: {{ .Values.web.serverReplicas }}
{{- end }}
selector:
matchLabels:
{{- include "flux-operator.selectorLabels" . | nindent 6 }}
@@ -22,6 +25,9 @@ spec:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
{{- if include "flux-operator.createWebConfigSecret" . }}
checksum/web-config: {{ (include (print $.Template.BasePath "/web-secret.yaml") . | fromYaml).stringData | toYaml | sha256sum }}
{{- end }}
{{- with .Values.commonAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
@@ -56,6 +62,15 @@ spec:
{{- if .Values.multitenancy.enabledForWorkloadIdentity }}
- --default-workload-identity-service-account={{ .Values.multitenancy.defaultWorkloadIdentityServiceAccount }}
{{- end }}
{{- if include "flux-operator.webServerOnly" . }}
- --web-server-only=true
{{- end }}
{{- if include "flux-operator.createWebConfigSecret" . }}
- --web-config=/etc/flux-operator/web/config.yaml
{{- end }}
{{- if include "flux-operator.useWebConfigSecret" . }}
- --web-config-secret-name={{ .Values.web.configSecretName }}
{{- end }}
{{- range .Values.extraArgs }}
- {{ . }}
{{- end }}
@@ -66,6 +81,8 @@ spec:
fieldPath: metadata.namespace
- name: REPORTING_INTERVAL
value: {{ .Values.reporting.interval }}
- name: WEB_SERVER_PORT
value: "{{ ternary "9080" "0" .Values.web.enabled }}"
{{- with .Values.marketplace.type }}
- name: MARKETPLACE_TYPE
value: {{ . }}
@@ -93,6 +110,11 @@ spec:
- name: http
containerPort: 8081
protocol: TCP
{{- if .Values.web.enabled }}
- name: http-web
containerPort: 9080
protocol: TCP
{{- end }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
@@ -102,12 +124,22 @@ spec:
volumeMounts:
- name: temp
mountPath: /tmp
{{- if include "flux-operator.createWebConfigSecret" . }}
- name: web-config
mountPath: /etc/flux-operator/web
readOnly: true
{{- end }}
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
{{- end }}
volumes:
- name: temp
emptyDir: {}
{{- if include "flux-operator.createWebConfigSecret" . }}
- name: web-config
secret:
secretName: {{ include "flux-operator.fullname" . }}-web-config
{{- end }}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 8 }}
{{- end }}
@@ -0,0 +1,26 @@
{{- if .Values.web.httpRoute.enabled -}}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ include "flux-operator.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.web.httpRoute.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.web.httpRoute.parentRefs }}
parentRefs:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.web.httpRoute.hostnames }}
hostnames:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
- backendRefs:
- name: {{ include "flux-operator.fullname" . }}
port: 9080
{{- end }}
@@ -0,0 +1,44 @@
{{- if .Values.web.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "flux-operator.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.web.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.web.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- if .Values.web.ingress.tls }}
tls:
{{- range .Values.web.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.web.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- with .pathType }}
pathType: {{ . }}
{{- end }}
backend:
service:
name: {{ include "flux-operator.fullname" $ }}
port:
name: http-web
{{- end }}
{{- end }}
{{- end }}
@@ -14,6 +14,8 @@ spec:
protocol: TCP
- port: "8081"
protocol: TCP
- port: "9080"
protocol: TCP
ingress:
- fromEntities:
- cluster
@@ -0,0 +1,32 @@
{{- if and .Values.web.enabled .Values.web.networkPolicy.create }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "flux-operator.fullname" . }}-web
namespace: {{ .Release.Namespace }}
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
{{- include "flux-operator.selectorLabels" . | nindent 6 }}
ingress:
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 9080
{{- if .Values.serviceMonitor.create }}
- protocol: TCP
port: 8080
{{- end }}
{{- end }}
@@ -13,10 +13,19 @@ metadata:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.service.ipFamilyPolicy }}
ipFamilyPolicy: {{ . }}
{{- end }}
ports:
- port: 8080
targetPort: http-metrics
protocol: TCP
name: http
{{- if .Values.web.enabled }}
- port: 9080
targetPort: http-web
protocol: TCP
name: http-web
{{- end }}
selector:
{{- include "flux-operator.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,47 @@
{{- if include "flux-operator.webServerOnly" . }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "flux-operator.fullname" . }}-view
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create"]
- apiGroups: [""]
resources: ["users", "groups"]
verbs: ["impersonate"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "flux-operator.fullname" . }}
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "flux-operator.fullname" . }}-view
subjects:
- kind: ServiceAccount
name: {{ include "flux-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -0,0 +1,26 @@
{{- if and .Values.web.config .Values.web.configSecretName -}}
{{- fail "Invalid values: 'web.config' and 'web.configSecretName' cannot both be set. Set at most one." -}}
{{- end -}}
{{- if include "flux-operator.createWebConfigSecret" . -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "flux-operator.fullname" . }}-web-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
type: Opaque
stringData:
config.yaml: |
apiVersion: web.fluxcd.controlplane.io/v1
kind: Config
spec:
{{- toYaml .Values.web.config | nindent 6 }}
{{- end }}
@@ -0,0 +1,131 @@
{{- if include "flux-operator.createWebRoles" . }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: flux-web-user
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: flux-web-admin
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
- apiGroups:
- fluxcd.controlplane.io
- source.toolkit.fluxcd.io
- source.extensions.fluxcd.io
- kustomize.toolkit.fluxcd.io
- helm.toolkit.fluxcd.io
- image.toolkit.fluxcd.io
- notification.toolkit.fluxcd.io
resources: ["*"]
verbs:
- patch
- reconcile
- suspend
- resume
- download
- apiGroups:
- apps
resources:
- deployments
- statefulsets
- daemonsets
verbs:
- patch
- restart
- apiGroups:
- batch
resources:
- cronjobs
- jobs
verbs:
- create
- restart
- apiGroups:
- ""
resources:
- pods
verbs:
- delete
{{- end }}
{{- if include "flux-operator.createWebRolesAggregation" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: flux-web-edit
labels:
{{- include "flux-operator.labels" . | nindent 4 }}
{{- with .Values.commonLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
rbac.authorization.k8s.io/aggregate-to-edit: "true"
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
- apiGroups:
- fluxcd.controlplane.io
- source.toolkit.fluxcd.io
- source.extensions.fluxcd.io
- kustomize.toolkit.fluxcd.io
- helm.toolkit.fluxcd.io
- image.toolkit.fluxcd.io
- notification.toolkit.fluxcd.io
resources:
- '*'
verbs:
- reconcile
- suspend
- resume
- download
- apiGroups:
- apps
resources:
- deployments
- statefulsets
- daemonsets
verbs:
- patch
- restart
- apiGroups:
- batch
resources:
- cronjobs
- jobs
verbs:
- create
- restart
- apiGroups:
- ""
resources:
- pods
verbs:
- delete
{{- end }}
@@ -378,6 +378,20 @@
}
}
},
"service": {
"type": "object",
"properties": {
"ipFamilyPolicy": {
"type": "string",
"enum": [
"",
"SingleStack",
"PreferDualStack",
"RequireDualStack"
]
}
}
},
"serviceAccount": {
"default": {
"automount": true,
@@ -425,6 +439,115 @@
"items": {
"type": "object"
}
},
"web": {
"type": "object",
"properties": {
"config": {
"type": "object"
},
"configSecretName": {
"default": "",
"type": "string"
},
"enabled": {
"type": "boolean"
},
"httpRoute": {
"default": {
"annotations": {},
"enabled": false,
"hostnames": [],
"parentRefs": []
},
"type": "object",
"properties": {
"annotations": {
"type": "object"
},
"enabled": {
"default": false,
"type": "boolean"
},
"hostnames": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
}
},
"parentRefs": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "object"
}
}
}
},
"ingress": {
"default": {
"annotations": {},
"className": "",
"enabled": false
},
"type": "object",
"properties": {
"annotations": {
"type": "object"
},
"className": {
"type": "string"
},
"enabled": {
"default": false,
"type": "boolean"
},
"hosts": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "object"
}
},
"tls": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "object"
}
}
}
},
"networkPolicy": {
"type": "object",
"properties": {
"create": {
"type": "boolean"
}
}
},
"rbac": {
"type": "object",
"properties": {
"createAggregation": {
"default": false,
"type": "boolean"
},
"createRoles": {
"default": true,
"type": "boolean"
}
}
},
"serverOnly": {
"type": "boolean"
},
"serverReplicas": {
"default": 1,
"type": "integer"
}
}
}
}
}
@@ -3,17 +3,60 @@
nameOverride: ""
fullnameOverride: ""
# -- Enable [multitenancy lockdown](https://fluxcd.control-plane.io/operator/resourceset/#role-based-access-control) for the ResourceSet APIs.
# -- Enable [multitenancy lockdown](https://fluxoperator.dev/docs/crd/resourceset/#role-based-access-control) for the ResourceSet APIs.
multitenancy:
enabled: false
enabledForWorkloadIdentity: false
defaultServiceAccount: "flux-operator" # @schema required: true
defaultWorkloadIdentityServiceAccount: "flux-operator" # @schema required: true
# -- Flux [reporting](https://fluxcd.control-plane.io/operator/fluxreport/) settings.
# -- Flux [reporting](https://fluxoperator.dev/docs/crd/fluxreport/) settings.
reporting:
interval: 5m # @schema required: true
web:
# -- Enable the [Flux Status web server](https://fluxoperator.dev/web-ui/) on port 9080.
enabled: true
# -- The spec of the [Web Config API](https://fluxoperator.dev/docs/web-ui/web-config-api/)
config: { } # @schema type: object
# -- Reference to an existing Secret in the same namespace as the deployment containing the Web Config API. Should have the key `config.yaml`.
configSecretName: "" # @schema default: ""
# -- Create a NetworkPolicy to allow access to the Flux Status web interface.
networkPolicy:
create: true
# -- Create standard roles for [user access management](https://fluxoperator.dev/docs/web-ui/user-management/).
rbac:
createRoles: true # @schema default: true
createAggregation: false # @schema default: false
# -- Run the Flux Status web server as a standalone deployment (requires a dedicated Helm release).
serverOnly: false
# -- Number of replicas for the Flux Status web server standalone deployment (only applicable if `web.serverOnly` is `true`).
serverReplicas: 1 # @schema default: 1
# -- Ingress settings for the Flux Status web interface.
ingress: # @schema default: {"enabled":false,"className":"","annotations":{}}
enabled: false # @schema default: false
className: ""
annotations: { } # @schema type: object
hosts: [ ] # @schema item: object ; uniqueItems: true
# - host: flux-operator.example.com
# paths:
# - path: /
# pathType: ImplementationSpecific
tls: [ ] # @schema item: object ; uniqueItems: true
# - secretName: flux-operator-tls
# hosts:
# - flux-operator.example.com
# -- Gateway API HTTPRoute settings for the Flux Status web interface.
httpRoute: # @schema default: {"enabled":false,"annotations":{},"parentRefs":[],"hostnames":[]}
enabled: false # @schema default: false
annotations: { } # @schema type: object
parentRefs: [ ] # @schema item: object ; uniqueItems: true
# - name: my-gateway
# namespace: gateway-system
# sectionName: https
hostnames: [ ] # @schema item: string ; uniqueItems: true
# - flux.example.com
# -- Install and upgrade the custom resource definitions.
installCRDs: true # @schema default: true
@@ -140,6 +183,10 @@ serviceMonitor: # @schema default: {"create":false,"interval":"60s","scrapeTimeo
scrapeTimeout: 30s
labels: { }
service:
# -- Sets the IP family policy on all Service resources. Uses Kubernetes defaults if unset
ipFamilyPolicy: '' # @schema type: string; enum:['', SingleStack, PreferDualStack, RequireDualStack]
# -- Marketplace settings.
marketplace:
type: ""
@@ -2,7 +2,7 @@ diff --git a/charts/flux-operator/templates/network-policy.yaml b/packages/syste
new file mode 100644
--- /dev/null (revision 52a23eacfc32430d8b008b765c64a81526521bae)
+++ b/charts/flux-operator/templates/network-policy.yaml (revision 52a23eacfc32430d8b008b765c64a81526521bae)
@@ -0,0 +1,20 @@
@@ -0,0 +1,22 @@
+{{- if .Capabilities.APIVersions.Has "cilium.io/v2/CiliumClusterwideNetworkPolicy" }}
+apiVersion: cilium.io/v2
+kind: CiliumClusterwideNetworkPolicy
@@ -19,6 +19,8 @@ new file mode 100644
+ protocol: TCP
+ - port: "8081"
+ protocol: TCP
+ - port: "9080"
+ protocol: TCP
+ ingress:
+ - fromEntities:
+ - cluster
@@ -12,3 +12,11 @@ flux-operator:
requests:
cpu: 100m
memory: 350Mi
# Flux Status Web UI is opt-in. Override `web.enabled: true` (and configure
# `web.config` / `web.configSecretName` / `web.ingress` as needed) to enable.
# The upstream chart's NetworkPolicy is suppressed because Cozystack ships a
# CiliumClusterwideNetworkPolicy that already restricts ports 8080/8081/9080.
web:
enabled: false
networkPolicy:
create: false
@@ -2,15 +2,15 @@ annotations:
artifacthub.io/license: AGPL-3.0
artifacthub.io/links: |
- name: Documentation
url: https://fluxcd.control-plane.io/operator
url: https://fluxoperator.dev/docs
- name: Chart Source
url: https://github.com/controlplaneio-fluxcd/charts
- name: Upstream Project
url: https://github.com/controlplaneio-fluxcd/flux-operator
apiVersion: v2
appVersion: v0.33.0
appVersion: v0.50.0
description: 'A Helm chart for deploying a Flux instance managed by Flux Operator. '
home: https://github.com/controlplaneio-fluxcd
home: https://fluxoperator.dev
icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png
keywords:
- flux
@@ -25,4 +25,4 @@ sources:
- https://github.com/controlplaneio-fluxcd/flux-operator
- https://github.com/controlplaneio-fluxcd/charts
type: application
version: 0.33.0
version: 0.50.0
@@ -1,6 +1,6 @@
# flux-instance
![Version: 0.33.0](https://img.shields.io/badge/Version-0.33.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.33.0](https://img.shields.io/badge/AppVersion-v0.33.0-informational?style=flat-square)
![Version: 0.50.0](https://img.shields.io/badge/Version-0.50.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.50.0](https://img.shields.io/badge/AppVersion-v0.50.0-informational?style=flat-square)
This chart is a thin wrapper around the `FluxInstance` custom resource, which is
used by the [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator)
@@ -8,7 +8,7 @@ to install, configure and automatically upgrade Flux.
## Prerequisites
- Kubernetes 1.22+
- Kubernetes 1.30+
- Helm 3.8+
## Installing the Chart
@@ -20,7 +20,7 @@ helm -n flux-system install flux oci://ghcr.io/controlplaneio-fluxcd/charts/flux
```
For more information on the available configuration options,
see the [Flux Instance documentation](https://fluxcd.control-plane.io/operator/fluxinstance/).
see the [Flux Instance documentation](https://fluxoperator.dev/docs/crd/fluxinstance/).
## Uninstalling the Chart
@@ -39,14 +39,14 @@ helm -n flux-system uninstall flux
| fullnameOverride | string | `"flux"` | |
| healthcheck.enabled | bool | `false` | Enable post-install and post-upgrade health checks. |
| healthcheck.timeout | string | `"5m"` | Health check timeout in Go duration format. |
| instance.cluster | object | `{"domain":"cluster.local","multitenant":false,"networkPolicy":true,"size":"","tenantDefaultServiceAccount":"default","type":"kubernetes"}` | Cluster https://fluxcd.control-plane.io/operator/fluxinstance/#cluster-configuration |
| instance.commonMetadata | object | `{"annotations":{},"labels":{}}` | Common metadata https://fluxcd.control-plane.io/operator/fluxinstance/#common-metadata |
| instance.components | list | `["source-controller","kustomize-controller","helm-controller","notification-controller"]` | Components https://fluxcd.control-plane.io/operator/fluxinstance/#components-configuration |
| instance.distribution | object | `{"artifact":"oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests:latest","artifactPullSecret":"","imagePullSecret":"","registry":"ghcr.io/fluxcd","version":"2.x"}` | Distribution https://fluxcd.control-plane.io/operator/fluxinstance/#distribution-configuration |
| instance.kustomize.patches | list | `[]` | Kustomize patches https://fluxcd.control-plane.io/operator/fluxinstance/#kustomize-patches |
| instance.sharding | object | `{"key":"sharding.fluxcd.io/key","shards":[]}` | Sharding https://fluxcd.control-plane.io/operator/fluxinstance/#sharding-configuration |
| instance.storage | object | `{"class":"","size":""}` | Storage https://fluxcd.control-plane.io/operator/fluxinstance/#storage-configuration |
| instance.sync | object | `{"interval":"1m","kind":"GitRepository","name":"","path":"","provider":"","pullSecret":"","ref":"","url":""}` | Sync https://fluxcd.control-plane.io/operator/fluxinstance/#sync-configuration |
| instance.cluster | object | `{"domain":"cluster.local","multitenant":false,"networkPolicy":true,"size":"","tenantDefaultServiceAccount":"default","type":"kubernetes"}` | Cluster https://fluxoperator.dev/docs/crd/fluxinstance/#cluster-configuration |
| instance.commonMetadata | object | `{"annotations":{},"labels":{}}` | Common metadata https://fluxoperator.dev/docs/crd/fluxinstance/#common-metadata |
| instance.components | list | `["source-controller","kustomize-controller","helm-controller","notification-controller"]` | Components https://fluxoperator.dev/docs/crd/fluxinstance/#components-configuration |
| instance.distribution | object | `{"artifact":"oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests:latest","artifactPullSecret":"","imagePullSecret":"","registry":"ghcr.io/fluxcd","variant":"","version":"2.x"}` | Distribution https://fluxoperator.dev/docs/crd/fluxinstance/#distribution-configuration |
| instance.kustomize.patches | list | `[]` | Kustomize patches https://fluxoperator.dev/docs/crd/fluxinstance/#kustomize-patches |
| instance.sharding | object | `{"key":"sharding.fluxcd.io/key","shards":[]}` | Sharding https://fluxoperator.dev/docs/crd/fluxinstance/#sharding-configuration |
| instance.storage | object | `{"class":"","size":""}` | Storage https://fluxoperator.dev/docs/crd/fluxinstance/#storage-configuration |
| instance.sync | object | `{"interval":"1m","kind":"GitRepository","name":"","path":"","provider":"","pullSecret":"","ref":"","url":""}` | Sync https://fluxoperator.dev/docs/crd/fluxinstance/#sync-configuration |
| nameOverride | string | `""` | |
## Source Code
@@ -1 +1 @@
Documentation at https://fluxcd.control-plane.io/operator/
Documentation at https://fluxoperator.dev/docs/
@@ -3,6 +3,7 @@ apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-healthcheck"
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
@@ -14,7 +14,7 @@ metadata:
{{- end }}
spec:
distribution:
version: {{ .Values.instance.distribution.version }}
version: {{ .Values.instance.distribution.version | quote }}
registry: {{ .Values.instance.distribution.registry }}
artifact: {{ .Values.instance.distribution.artifact }}
{{- if .Values.instance.distribution.artifactPullSecret }}
@@ -23,6 +23,9 @@ spec:
{{- if .Values.instance.distribution.imagePullSecret }}
imagePullSecret: {{ .Values.instance.distribution.imagePullSecret }}
{{- end }}
{{- if .Values.instance.distribution.variant }}
variant: {{ .Values.instance.distribution.variant }}
{{- end }}
components: {{ .Values.instance.components | toYaml | nindent 4 }}
cluster:
{{- range $key, $value := .Values.instance.cluster }}
@@ -350,6 +350,16 @@
"registry": {
"type": "string"
},
"variant": {
"type": "string",
"enum": [
"",
"upstream-alpine",
"enterprise-alpine",
"enterprise-distroless",
"enterprise-distroless-fips"
]
},
"version": {
"type": "string"
}
@@ -4,20 +4,21 @@ nameOverride: ""
fullnameOverride: "flux"
instance:
# -- Distribution https://fluxcd.control-plane.io/operator/fluxinstance/#distribution-configuration
# -- Distribution https://fluxoperator.dev/docs/crd/fluxinstance/#distribution-configuration
distribution: # @schema required: true
version: "2.x" # @schema required: true
registry: "ghcr.io/fluxcd" # @schema required: true
artifact: "oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests:latest"
artifactPullSecret: ""
imagePullSecret: ""
# -- Components https://fluxcd.control-plane.io/operator/fluxinstance/#components-configuration
variant: "" # @schema enum:['',upstream-alpine,enterprise-alpine,enterprise-distroless,enterprise-distroless-fips]
# -- Components https://fluxoperator.dev/docs/crd/fluxinstance/#components-configuration
components: # @schema item: string; uniqueItems: true; itemEnum: [source-controller,kustomize-controller,helm-controller,notification-controller,image-reflector-controller,image-automation-controller,source-watcher]
- source-controller
- kustomize-controller
- helm-controller
- notification-controller
# -- Cluster https://fluxcd.control-plane.io/operator/fluxinstance/#cluster-configuration
# -- Cluster https://fluxoperator.dev/docs/crd/fluxinstance/#cluster-configuration
cluster: # @schema required: true
type: kubernetes # @schema enum:[kubernetes,openshift,aws,azure,gcp]
size: "" # @schema enum:['',small,medium,large]
@@ -25,19 +26,19 @@ instance:
networkPolicy: true
multitenant: false
tenantDefaultServiceAccount: "default"
# -- Common metadata https://fluxcd.control-plane.io/operator/fluxinstance/#common-metadata
# -- Common metadata https://fluxoperator.dev/docs/crd/fluxinstance/#common-metadata
commonMetadata: # @schema required: false
labels: { }
annotations: { }
# -- Storage https://fluxcd.control-plane.io/operator/fluxinstance/#storage-configuration
# -- Storage https://fluxoperator.dev/docs/crd/fluxinstance/#storage-configuration
storage: # @schema required: false
class: ""
size: ""
# -- Sharding https://fluxcd.control-plane.io/operator/fluxinstance/#sharding-configuration
# -- Sharding https://fluxoperator.dev/docs/crd/fluxinstance/#sharding-configuration
sharding: # @schema required: false
key: "sharding.fluxcd.io/key"
shards: [ ] # @schema item: string
# -- Sync https://fluxcd.control-plane.io/operator/fluxinstance/#sync-configuration
# -- Sync https://fluxoperator.dev/docs/crd/fluxinstance/#sync-configuration
sync: # @schema required: false
interval: 1m
kind: "GitRepository" # @schema enum:[GitRepository,OCIRepository,Bucket]
@@ -48,7 +49,7 @@ instance:
name: ""
provider: ""
kustomize: # @schema required: false
# -- Kustomize patches https://fluxcd.control-plane.io/operator/fluxinstance/#kustomize-patches
# -- Kustomize patches https://fluxoperator.dev/docs/crd/fluxinstance/#kustomize-patches
patches: [ ] # @schema item: object
# -- Common annotations to add to all deployed objects including pods.
+1 -1
View File
@@ -5,7 +5,7 @@ flux-instance:
domain: cozy.local # -- default value is overriden in patches
distribution:
artifact: ""
version: 2.7.x
version: 2.8.x
registry: ghcr.io/fluxcd
components:
- source-controller
Loaded 100 of 118 files, more files were not shown because too many files have changed in this diff. Show more