diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2482712d..2045ec5a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters @sircthulhu @myasnikovdaniil +* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters @sircthulhu diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fefdab82..1a119259 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: Bug report about: Create a report to help us improve -labels: 'kind/bug' +labels: 'bug' assignees: '' --- diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 044dd6a0..b9475846 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,9 @@ - -# v1.2.3 (2026-04-20) - -A patch release with bug fixes and documentation updates. - -## Features and Improvements - -_No notable features in this patch release._ - -## Fixes - -* **fix(kubernetes): set explicit ephemeral-storage on virt-launcher pods**: Prevents VM crashes caused by ephemeral-storage eviction by setting explicit `domain.resources` ephemeral-storage on the VirtualMachine spec. Uses sanitized limits and requests so virt-launcher pods do not inherit too-small namespace defaults. ([**@kvaps**](https://github.com/kvaps) in #2317, backport #2423). - -## Documentation - -* **[website] feat: add Telemetry page under OSS Health section**: Add Telemetry page and initial data seeding to OSS Health docs ([**@tym83**](https://github.com/tym83) in cozystack/website#471). -* **[website] Refactor docs versions to major.minor variants**: Move docs to major.minor versioning for v1.x series ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#477). -* **[website] docs(tenants): document namespace layout and parent/child derivation** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#479). -* **[website] docs(tenants): document the checkbox-then-edit-CR customization pattern** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#485). -* **[website] docs: fix 14 broken links and stale talm anchor across v1 docs** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#486). -* **[website] fix(og): update social badge image and title** ([**@tym83**](https://github.com/tym83) in cozystack/website#487). -* **[website] docs(external-apps): rewrite guide for ApplicationDefinition API** ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/website#488). -* **[website] docs: add CLAUDE.md for AI agent guidance** ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#489). -* **[website] fix: update /docs/v1/ redirect to latest v1.2** ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#492). -* **[website] fix(ci): add OpenAPI spec download to GitHub Pages build** ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#494). -* **[website] feat(blog): add managed PostgreSQL with synchronous replication post** ([**@tym83**](https://github.com/tym83) in cozystack/website#497). -* **[website] chore(blog): add images frontmatter for social preview on existing posts** ([**@tym83**](https://github.com/tym83) in cozystack/website#498). -* **[website] feat(blog): taxonomies and client-side filter UI** ([**@tym83**](https://github.com/tym83) in cozystack/website#499). -* **[website] style(oss-health): add breathing room between navbar and hero** ([**@tym83**](https://github.com/tym83) in cozystack/website#500). - -## Other repositories - -* **[talm] feat(config): migrate to Talos v1.12 multi-document config format**: Upgrade Talos config format and modernize configuration handling ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#116). -* **[talm] chore(deps): bump dependencies and modernize codebase** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#124). -* **[external-apps-example] feat: replace MongoDB example with Minecraft apps from cozylex** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/external-apps-example#2). -* **[ansible-cozystack] fix(examples): add v prefix to collection version in requirements.yml** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#23). -* **[ansible-cozystack] fix(plugins): replace ansible.utils.ipaddr with stdlib-based test plugin** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#24). -* **[ansible-cozystack] feat(examples): comprehensive node prerequisites audit (fixes #19)** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#27). -* **[ansible-cozystack] chore(deps): update dependency cozystack.installer to v1.2.3** ([**@app/renovate**](https://github.com/apps/renovate) in cozystack/ansible-cozystack#29). -* **[ansible-cozystack] feat(role): expose publishing.externalIPs and tenant-root ingress via role variables** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#30). - -## Contributors - -Thanks to everyone who contributed to this patch release: - -* [**@app/github-actions**](https://github.com/apps/github-actions) -* [**@app/renovate**](https://github.com/apps/renovate) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@tym83**](https://github.com/tym83) - - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.2...v1.2.3 diff --git a/docs/changelogs/v1.3.0.md b/docs/changelogs/v1.3.0.md deleted file mode 100644 index 60c800a8..00000000 --- a/docs/changelogs/v1.3.0.md +++ /dev/null @@ -1,238 +0,0 @@ - - -# Cozystack v1.3.0 - -Cozystack v1.3.0 brings **storage-aware pod scheduling** via a LINSTOR scheduler extender, a managed **LINSTOR GUI** web console with Keycloak SSO, a curated **VM Default Images** catalog for out-of-the-box virtual-machine provisioning, a new **WorkloadsReady / Events** observability surface with S3 bucket metering, and **cross-namespace VMInstance backup restore** with a full **RestoreJob dashboard** flow. The release also ships stricter tenant-name validation, VMInstance network-selector improvements, Keycloak theme injection and SMTP configuration, a host-runtime preflight check, and rolls up every fix from the v1.2.1 → v1.2.4 patch line. - -> **Note:** Items marked *(backported to v1.2.x)* were also shipped in v1.2.1, v1.2.2, v1.2.3, or v1.2.4 patch releases. - -## Feature Highlights - -### Storage-Aware Scheduling via the LINSTOR Extender - -The `cozystack-scheduler` now calls a **LINSTOR scheduler extender** for storage-locality-aware pod placement. When a pod declares both a `SchedulingClass` and LINSTOR-backed PVCs, the scheduler consults LINSTOR to prefer nodes where volume replicas already exist — reducing cross-node replication traffic and improving I/O latency for storage-heavy workloads such as databases, object stores, and VMs. - -The integration builds on the existing `SchedulingClass` tenant workload placement system introduced in v1.2.0 and requires no tenant-side configuration — workloads simply benefit once a SchedulingClass is assigned. Administrators can mix storage locality with the existing data-center / hardware-generation constraints defined on SchedulingClass CRs ([**@lllamnyp**](https://github.com/lllamnyp) in #2330). - -### LINSTOR GUI: Managed Web Console for Storage Administration - -A new opt-in `linstor-gui` system package deploys **LINBIT's linstor-gui web UI** alongside the LINSTOR controller with mTLS client authentication, non-root security context, and a ClusterIP-only service by default. When OIDC is configured on the platform, an optional **Keycloak-protected Ingress** (via oauth2-proxy) exposes the UI for browser access. Access is restricted to members of the `cozystack-cluster-admin` Keycloak group, consistent with host-cluster admin RBAC, and the gatekeeper blocks in-app LINSTOR authentication setup at the nginx proxy layer so the managed configuration cannot be subverted through the UI. - -Operators who prefer CLI access keep the existing `linstor` command; the GUI is strictly additive and stays disabled by default ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2382, #2390, #2415, #2419). - -### VM Default Images: Out-of-the-Box VM Provisioning - -The new `vm-default-images` package provides a curated set of **cluster-wide virtual-machine images** (Ubuntu, Debian, CentOS Stream, and others) as pre-populated DataVolumes, so tenants can provision VMs against well-known base images without first having to upload them. The package is opt-in via the `iaas` bundle and defaults to replicated storage for high availability. Migration 38 renames legacy `vm-image-*` DataVolumes to the new `vm-default-images-*` naming scheme, and the `vm-disk` chart gains a new "disk" source type for cloning from existing vm-disks in the same namespace ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2258). - -### Application Observability: WorkloadsReady, Events, and S3 Bucket Metering - -Applications now expose a **WorkloadsReady** condition on their status by querying associated WorkloadMonitor resources, giving operators a single place to check whether all underlying workloads (Deployments, StatefulSets, DaemonSets, PVCs) are healthy. The dashboard gains a new **Events tab** showing namespace-scoped Kubernetes events per application, with fallback to `.firstTimestamp` when `.eventTime` is absent. A long-standing bug where WorkloadMonitor's `Operational` status was never persisted is fixed in the same change ([**@lexfrei**](https://github.com/lexfrei) in #2356). - -The WorkloadMonitor reconciler is extended to track **COSI BucketClaim** objects as first-class Workloads, and the bucket controller now queries SeaweedFS logical and physical bucket-size metrics from VictoriaMetrics via a namespace-scoped monitoring endpoint, enabling S3 billing integration on par with Pods and PVCs ([**@kitsunoff**](https://github.com/kitsunoff) in #2391). Workloads are also enriched with `workloads.cozystack.io/resource-preset` and source-object labels so downstream billing pipelines can correlate monitors with the tenant preset that produced them ([**@androndo**](https://github.com/androndo) in #2416). - -### Cross-Namespace VM Backup Restore and RestoreJob Dashboard - -The backup system now supports **restoring VMInstance backups into a different namespace** (cross-namespace copy restores) with IP/MAC preservation and safe rename semantics. In-place backup and restore flows for VMDisk and VMInstance are improved: HelmReleases and DataVolumes are properly handled, and Velero failure messages are propagated to the Application status. The backup status structure has been refactored to store underlying resources as a generic opaque JSON object, enabling arbitrary application-specific metadata without status-schema churn ([**@androndo**](https://github.com/androndo) in #2251, #2319, #2329). - -The dashboard now ships a complete **RestoreJob experience**: list view, details page, create form, and sidebar entry, with a "Same as backup" fallback rendering when `spec.targetApplicationRef` is omitted. Non-CRD-backed sidebar factories (`kube-*`, `plan`, `backupjob`, `backup`, `restorejob`) are marked static so they pick up consistent managed-by labels across reconciles ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2437). - -## Major Features and Improvements - -* **[api] Reject tenant names with dashes at Create time**: Enforces alphanumeric-only naming for Tenants at the API level, preventing names with hyphens that would silently fail during Helm reconciliation. A corresponding regex tightening and regression test suite hardens the validation ([**@lexfrei**](https://github.com/lexfrei) in #2380). - -* **[platform] Validate computed tenant namespace length**: Rejects Tenant creation when the computed ancestor-chain namespace would exceed the 63-character Kubernetes namespace limit, preventing opaque HelmRelease reconcile errors downstream ([**@lexfrei**](https://github.com/lexfrei) in #2376). - -* **[vm-instance] Rename subnets to networks and add dropdown selector**: Renames the misleading `subnets` field to `networks` in VMInstance for clarity, adds a dropdown selector for available networks in the dashboard form, and includes migration 36 to copy existing `subnets` values. The old field remains supported for backward compatibility ([**@sircthulhu**](https://github.com/sircthulhu) in #2263). - -* **[keycloak] Enable injecting themes**: Cozystack administrators can now inject custom Keycloak themes via `initContainers` for UI white-labeling and customization ([**@lllamnyp**](https://github.com/lllamnyp) in #2142). - -* **[keycloak-configure] Add email verification and SMTP configuration**: Adds configurable Keycloak settings for user self-registration, email verification, and SMTP server configuration, enabling automated user onboarding flows ([**@BROngineer**](https://github.com/BROngineer) in #2318). - -* **[postgres] Pin system PostgreSQL to 17.7-standard-trixie**: Pins the PostgreSQL image for system databases (Grafana, Alerta, Harbor, Keycloak, SeaweedFS) to `17.7-standard-trixie` across chart templates and `values.yaml`, and ships migration 37 to patch existing CNPG Cluster `imageName` fields to the same variant (handling unset, any PG 17 tag, and bare-version tags). This prevents CNPG from defaulting to PostgreSQL 18 and locks system databases to the trixie variant consistent with the monitoring stack requirements *(related backports shipped in v1.2.1 via #2309 and v1.2.2 via #2364)* ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2369). - -* **[platform] Prevent installed packages deletion**: Adds the `helm.sh/resource-policy: keep` annotation to platform packages so disabling a package no longer triggers automatic Helm deletion, restoring the documented behavior where operators must explicitly delete a package *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2273). - -* **[mariadb] Always enable replication for consistent service naming**: MariaDB now always enables replication, creating `-primary`/`-secondary` services even for single-replica instances. This fixes dashboard visibility and backup functionality for single-replica setups ([**@sircthulhu**](https://github.com/sircthulhu) in #2279). - -* **[hack] Add host runtime preflight check**: New `check-host-runtime.sh` script and `make preflight` target that warns operators when a standalone containerd or docker runtime is running alongside the embedded k3s runtime, helping diagnose container-runtime conflicts early in an installation ([**@lexfrei**](https://github.com/lexfrei) in #2371). - -* **[hack] Add check-readiness.sh diagnostic script**: A new diagnostic script for tracking platform reconciliation by checking readiness of Packages, ArtifactGenerators, ExternalArtifacts, and HelmReleases, with support for watch mode and continuous monitoring ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2294). - -* **[platform] Add resourcePreset labels to WorkloadMonitor labels**: WorkloadMonitor labels with the `workloads.cozystack.io/` prefix are now propagated onto created Workloads; created Workloads always include the reserved `workloads.cozystack.io/monitor` label, and Helm app charts add `workloads.cozystack.io/resource-preset` metadata to WorkloadMonitor manifests, enabling downstream billing pipelines to correlate monitors with the tenant preset that produced them ([**@androndo**](https://github.com/androndo) in #2416). - -## Bug Fixes - -* **[platform] Migrate ACME HTTP-01 to ingressClassName API**: Switches ACME HTTP-01 issuance from the deprecated `acme.cert-manager.io/http01-ingress-class` annotation to the modern `ingressClassName` field on `ClusterIssuer` and solver pods. Previously, ClusterIssuers referenced a non-existent `nginx` class while each Ingress individually overrode it via annotation — producing `ingressClassName and class cannot be set at the same time` errors when tenants attempted to migrate to the modern field. The migration is atomic: both the ClusterIssuer and consuming Ingresses are updated together *(backported to v1.2.4)* ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2436). - -* **[harbor] Remove incorrect tenant module flags**: Harbor is a PaaS service, not a tenant module. Incorrect `spec.dashboard.module: true` and `internal.cozystack.io/tenantmodule` flags caused Harbor to appear in the sidebar "Modules" section and be misclassified by controllers handling tenant modules. The flags are now removed so Harbor is displayed in its proper PaaS category and is no longer treated as a tenant-scoped HelmRelease ([**@kvaps**](https://github.com/kvaps) in #2444). - -* **[kube-ovn] Resolve kubeovn-plunger RBAC forbidden on deployments**: Grants `kube-ovn-plunger` the RBAC needed to list Deployments so it can reconcile `ovn-central`, fixing `deployments.apps is forbidden` errors in `cozy-kubeovn` ([**@kvaps**](https://github.com/kvaps) in #2441). - -* **[cilium] Opt-out of cri-containerd.apparmor.d for nsenter init containers**: Opts cilium-agent init containers out of the `cri-containerd.apparmor.d` AppArmor profile on non-Talos variants (`cilium-generic`, `kubeovn-cilium-generic`), fixing `Init:CrashLoopBackOff` on Ubuntu 22.04+ and Debian where the profile denies `nsenter` namespace entry. Talos variants are untouched as Talos does not load the AppArmor LSM *(backported to v1.2.2)* ([**@lexfrei**](https://github.com/lexfrei) in #2370). - -* **[virtual-machine] Exclude external VM services from Cilium BPF LB**: Adds the `service.kubernetes.io/service-proxy-name: cozy-proxy` label to VM LoadBalancer services with `external: true`, telling Cilium to skip BPF processing entirely. Fixes inter-tenant connectivity via public LB IPs (Cilium's DNAT caused cross-tenant pod-to-pod flow classification, triggering CiliumClusterwideNetworkPolicy blocks) and restores WholeIP behavior on Cilium 1.19+ where wildcard service drop entries previously blocked traffic to LB IPs on undeclared ports *(backported to v1.2.2)* ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2357). - -* **[monitoring] Fix infra dashboards missing in default variant**: Includes the `cozy-monitoring` namespace in the dashboard rendering condition, fixing infrastructure Grafana dashboards not rendering in the default platform variant (only the `tenant-root` namespace was previously checked) *(backported to v1.2.2)* ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2365). - -* **[build] Filter git describe to match only v* tags**: Adds `--match 'v*'` to all `git describe` calls in `hack/common-envs.mk`, preventing the `api/apps/v1alpha1/vX.Y.Z` subtag from being picked up instead of the release tag and producing invalid Docker image tags *(backported to v1.2.2)* ([**@kvaps**](https://github.com/kvaps) in #2386). - -* **[platform] Fix resource allocation ratios not propagated to packages**: Restores propagation of `cpuAllocationRatio`, `memoryAllocationRatio`, and `ephemeralStorageAllocationRatio` from `platform/values.yaml` to the `cozystack-values` Secret that managed applications and KubeVirt read, fixing a regression introduced in the bundle restructure that silently ignored operator-configured ratios *(backported to v1.2.1)* ([**@sircthulhu**](https://github.com/sircthulhu) in #2296). - -* **[kubernetes] Set explicit ephemeral-storage on virt-launcher pods**: Sets explicit `domain.resources` ephemeral-storage on the VirtualMachine spec to prevent virt-launcher pods from being evicted because LimitRange defaults were too small for the actual emptyDisk capacity *(backported to v1.2.3)* ([**@kvaps**](https://github.com/kvaps) in #2317). - -* **[multus] Pin master CNI to 05-cilium.conflist**: Prevents a boot-time race where multus could auto-detect kube-ovn's conflist instead of Cilium's, which would cause pods to bypass the Cilium chain entirely and lose their endpoint *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2315). - -* **[multus] Build custom image with DEL cache fix**: Fixes sandbox cleanup deadlock when CNI ADD never completes, preventing stale sandbox name reservations from permanently blocking pod creation after a node disruption *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2313). - -* **[linstor] Set verify-alg to crc32c**: Prevents DRBD connection failures on kernels where `crct10dif` is unavailable (e.g., Talos v1.12.6 with kernel 6.18.18) by setting the LINSTOR verify-alg controller default to `crc32c` *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2303). - -* **[linstor] Preserve TCP ports during toggle-disk operations**: Saves existing TCP ports into the `LayerPayload` before `removeLayerData()` deletes them, preventing DRBD resources from entering StandAlone state when a satellite misses the resulting update *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2292). - -* **[linstor] Increase satellite startup probe failure threshold**: Raises the LINSTOR satellite `startupProbe` `failureThreshold` from 3 to 30 (30s → 300s) in the `LinstorSatelliteConfiguration` pod template, giving satellites with slow storage initialization enough time to come up without being killed and restarted ([**@Arsolitt**](https://github.com/Arsolitt) in #2425). - -## Security - -* **docs: add SECURITY.md**: Adds vulnerability reporting procedures, disclosure expectations, and supported release lines ([**@kvaps**](https://github.com/kvaps) in #2230). - -* **docs: add OpenSSF Best Practices badge to README**: Adds the OpenSSF Best Practices passing badge to the project README ([**@lexfrei**](https://github.com/lexfrei) in #2320). - -## Dependencies & Version Updates - -* **[kube-ovn] Bump kube-ovn to v1.15.10 with port-group regression fix**: Updates `packages/system/kubeovn` to upstream v1.15.10 (from v1.15.3) and carries a patch for `pkg/controller/pod.go` that preserves a VM LSP's port-group memberships when Kubernetes GCs a completed virt-launcher pod while another virt-launcher pod of the same VM is still running. Without the patch, the destination pod of a successful live migration lost its security groups, network policies, and node-scoped routing until `kube-ovn-controller` was restarted ([**@kvaps**](https://github.com/kvaps) in #2443). - -* **[monitoring] Upgrade victoria-metrics-operator to v0.68.4**: Bumps the vendored `victoria-metrics-operator` Helm chart from 0.59.1 to 0.61.0 (operator appVersion v0.68.1 → v0.68.4), picking up upstream fixes for `VMPodScrape` port routing on VMAgent/VLAgent and `StatefulSet` pod deletion (not eviction) when `maxUnavailable=100%` ([**@lexfrei**](https://github.com/lexfrei) in #2426). - -* **[linstor] Update piraeus-server to v1.33.2 with selected backports**: Bumps LINSTOR server from v1.33.1 to v1.33.2 with backported patches for stale bitmap adjust retry, LUKS2 header sizing, optimal I/O size detection, and the maintainer implementation. All patches verified against upstream v1.33.2 with `git apply --check` and `gradlew compileJava` *(backported to v1.2.2)* ([**@kvaps**](https://github.com/kvaps) in #2331). - -* **[kamaji] Update to 26.3.5-edge, drop upstreamed patches**: Updates Kamaji from edge-26.2.4 to 26.3.5-edge and removes two patches accepted upstream. Adds configurable probe tuning and DataStore readiness conditions ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2260). - -* **[talm] Release v0.23.0, v0.23.1, v0.24.0** (github.com/cozystack/talm): Migrates to the Talos v1.12 multi-document machine config format ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#116); renders templates online in `apply` to resolve lookups ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/talm#119); bumps dependencies and modernizes the codebase ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#124). - -* **[ansible-cozystack] Release v1.2.1, v1.2.2, v1.2.4** (github.com/cozystack/ansible-cozystack): Exposes `publishing.externalIPs` and tenant-root ingress via role variables ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#30); adds a comprehensive node prerequisites audit ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#27); replaces `ansible.utils.ipaddr` with a stdlib-based test plugin ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#24); adds `v` prefix to collection version in requirements.yml examples ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#23); tracks installer releases v1.2.1 through v1.2.4 ([**@app/renovate**](https://github.com/apps/renovate) in cozystack/ansible-cozystack#20, #22, #29, #31, #32). - -## Development, Testing, and CI/CD - -* **[ci] Replace cozystack-bot PAT with cozystack-ci GitHub App**: Replaces the long-lived `cozystack-bot` personal access token with short-lived, scoped tokens from the `cozystack-ci` GitHub App across all release workflows (`tags.yaml`, `auto-release.yaml`, `pull-requests-release.yaml`), improving security and auditability of CI operations ([**@tym83**](https://github.com/tym83) in #2351; [**@kvaps**](https://github.com/kvaps) in #2383, #2392). - -* **[ci] Add Gemini Code Assist and CodeRabbit configuration**: Adds repository-level configuration for AI code reviewers with ignore patterns for vendored/generated code and incremental review settings ([**@lexfrei**](https://github.com/lexfrei) in #2385). - -* **[ci] Promote next/ trunk on new minor/major releases**: Updates `update-website-docs` in `tags.yaml` to match the new docs-versioning contract — the website repo replaces the old "pre-create `vX.Y/` draft directory" scheme with a permanent `content/en/docs/next/` trunk, and released version directories are promoted explicitly by the release workflow ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2433). - -* **[tests] Fix Kafka E2E test timeout and retry race condition**: Increases Kafka E2E test timeout from 60s to 300s and fixes a retry race where `kubectl apply` could hit a still-deleting resource ([**@lexfrei**](https://github.com/lexfrei) in #2358). - -* **docs: adopt Conventional Commits for commit and PR titles**: Standardizes commit and PR title format to `type(scope): description` across all contributing docs and the PR template ([**@lexfrei**](https://github.com/lexfrei) in #2395). - -* **docs(ci): require screenshots for UI changes in PR template**: Adds a mandatory screenshots section to the PR template for UI-related changes ([**@kitsunoff**](https://github.com/kitsunoff) in #2407). - -* **chore(maintenance): add @myasnikovdaniil to CODEOWNERS**: Adds @myasnikovdaniil to the default owners in `.github/CODEOWNERS` for automatic review requests ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2434). - -## Documentation - -* **[website] Add ApplicationDefinition naming convention reference**: Documents how `cozystack-api` resolves kinds to their backing definitions ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#478). - -* **[website] Document Talos / talosctl / Cozystack version pairing**: Adds a version compatibility matrix for installation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#484). - -* **[website] Document namespace layout and parent/child derivation**: Explains tenant namespace hierarchy and parent/child namespace derivation rules ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#479). - -* **[website] Document the checkbox-then-edit-CR customization pattern for tenants**: Describes the workflow for customizing tenant settings via the CR after initial checkbox-based creation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#485). - -* **[website] Add custom Keycloak themes documentation**: Covers the theme image contract, configuration, `imagePullSecrets`, and theme activation in the Keycloak admin console ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#463). - -* **[website] Add bonding (LACP) configuration how-to guide**: Covers network bonding configuration for Cozystack installations ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#459). - -* **[website] Improve registry mirrors for tenant Kubernetes in air-gapped guide**: Improves documentation for configuring registry mirrors in air-gapped environments ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#461). - -* **[website] Rewrite guide for ApplicationDefinition API (external-apps)**: Comprehensive rewrite of the external apps guide using the ApplicationDefinition API with Minecraft server examples ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/website#488). - -* **[website] Add documentation for Go types usage**: Guide for using generated Go types for Cozystack managed applications as a Go module ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#465). - -* **[website] Update backup/restore documentation for VMI/VMDisk**: Updates backup documentation with VM instance and VM disk restore improvements ([**@androndo**](https://github.com/androndo) in cozystack/website#466). - -* **[website] Refactor docs versions to major.minor variants**: Moves docs to major.minor versioning for the v1.x series ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#477). - -* **[website] Trunk-based versioning with permanent next/ directory**: Replaces the old "pre-create `vX.Y/` draft directory" scheme with a permanent `content/en/docs/next/` trunk; released version directories are promoted explicitly by `hack/release_next.sh` on new minor/major releases, and routing between `next/` and `vX.Y/` is Makefile-driven ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#495). - -* **[website] Add updated OpenAPI spec**: Updates the OpenAPI specification for managed applications reference ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#469). - -* **[website] Add OpenAPI spec download to GitHub Pages build**: Fixes the GitHub Pages build to include the OpenAPI spec download ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#494). - -* **[website] Add OSS Health pages and OpenSSF badge**: Adds OSS Health section with OpenSSF Scorecard and Best Practices badges to the website ([**@tym83**](https://github.com/tym83) in cozystack/website#470). - -* **[website] Add Telemetry page under OSS Health section**: Adds the Telemetry page with initial data seeding to the OSS Health docs ([**@tym83**](https://github.com/tym83) in cozystack/website#471, cozystack/website#504). - -* **[website] Blog: OSS Health section launch announcement**: Publishes the announcement blog post for the OSS Health section ([**@tym83**](https://github.com/tym83) in cozystack/website#474). - -* **[website] Fix OpenSSF canonical status URL**: Changes the OpenSSF canonical status URL from pt-BR to en ([**@tym83**](https://github.com/tym83) in cozystack/website#475). - -* **[website] Add CozySummit Virtual 2026 program announcement**: Publishes the CozySummit Virtual 2026 program announcement blog post ([**@tym83**](https://github.com/tym83) in cozystack/website#472). - -* **[website] Add missing release announcements for v0.1–v0.41**: Backfills missing release announcement blog posts for historical Cozystack versions ([**@tym83**](https://github.com/tym83) in cozystack/website#468). - -* **[website] Blog: managed PostgreSQL with synchronous replication**: Adds a post covering the managed PostgreSQL synchronous-replication feature ([**@tym83**](https://github.com/tym83) in cozystack/website#497). - -* **[website] Blog taxonomies and client-side filter UI**: Registers article-type and topic taxonomies and adds a client-side filter on the blog list page ([**@tym83**](https://github.com/tym83) in cozystack/website#499). - -* **[website] Add images frontmatter for social preview on existing posts**: Adds images frontmatter for social preview on existing blog posts ([**@tym83**](https://github.com/tym83) in cozystack/website#498). - -* **[website] Fix broken links and stale anchors across v1 docs**: Fixes 14 broken links and stale talm anchors ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#486). - -* **[website] Prefix bundle package names with cozystack. in v1 examples**: Corrects package naming in documentation examples ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#482). - -* **[website] Finish isolated-field removal and document opt-in policy labels**: Removes the obsolete `isolated` field from tenant documentation and documents the new opt-in policy labels approach ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#481). - -* **[website] Add --take-ownership flag and describe networking.* fields**: Documents the `--take-ownership` flag and `networking.*` fields in the installation guide ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#480). - -* **[website] Fix KubeOVN MASTER_NODES example path and key in troubleshooting**: Corrects the MASTER_NODES example path and key ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#483). - -* **[website] Add CLAUDE.md for AI agent guidance**: Adds a CLAUDE.md file describing the trunk-based docs architecture for AI agent guidance ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#489). - -* **[website] Update /docs/v1/ redirect to latest v1.2**: Updates the `/docs/v1/` redirect target to point to the latest v1.2 docs on GitHub Pages ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#492). - -* **[website] Remove nbykov from CODEOWNERS and CLAUDE.md**: Cleans up CODEOWNERS and CLAUDE.md entries ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#491). - -* **[website] Add Ahrefs Analytics tracker**: Adds the Ahrefs Analytics tracker to the website ([**@tym83**](https://github.com/tym83) in cozystack/website#503). - -* **[website] Add breathing room between navbar and hero on OSS Health**: Minor styling fix for the OSS Health section ([**@tym83**](https://github.com/tym83) in cozystack/website#500). - -* **[website] Fix og social badge image and title**: Updates the social badge image and title ([**@tym83**](https://github.com/tym83) in cozystack/website#487). - -* **[website] Update managed apps reference for v1.2.1**: Automated managed-apps reference update ([**@cozystack-bot**](https://github.com/cozystack-bot) in cozystack/website#464). - -* **[external-apps-example] Replace MongoDB example with Minecraft apps**: Refactors the external apps example to use the ApplicationDefinition API with Minecraft server applications ([**@lexfrei**](https://github.com/lexfrei) in cozystack/external-apps-example#2). - -* **docs: update README introductory description**: Refines the platform positioning and improves clarity on core capabilities in the main README ([**@tym83**](https://github.com/tym83) in #2409). - -## Governance - -* **Add Mattia Eleuteri ([@mattia-eleuteri](https://github.com/mattia-eleuteri)) as Maintainer**: CSI, Storage, Networking & Security ([**@tym83**](https://github.com/tym83) in #2345). - -* **Add Matthieu Robin ([@matthieu-robin](https://github.com/matthieu-robin)) as Maintainer**: Managed applications, platform quality, and benchmarking ([**@tym83**](https://github.com/tym83) in #2346). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@Arsolitt**](https://github.com/Arsolitt) -* [**@BROngineer**](https://github.com/BROngineer) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@mattia-eleuteri**](https://github.com/mattia-eleuteri) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@sircthulhu**](https://github.com/sircthulhu) -* [**@tym83**](https://github.com/tym83) - -### New Contributors - -We're excited to welcome our first-time contributors: - -* [**@Arsolitt**](https://github.com/Arsolitt) — First contribution! - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.0...v1.3.0 diff --git a/docs/changelogs/v1.3.1.md b/docs/changelogs/v1.3.1.md deleted file mode 100644 index 0f149d0d..00000000 --- a/docs/changelogs/v1.3.1.md +++ /dev/null @@ -1,37 +0,0 @@ - - -# v1.3.1 (2026-04-28) - -Patch release covering a TenantNamespace IDOR fix in the API, a destructive `post-upgrade` hook removed from the etcd chart, kamaji controller stability, a `linstor-csi` bump that fixes live migration on Protocol-A/B DRBD resources, the missing `linstor-gui` build wiring, and a velero RBAC fix that unblocked installs on bundles without Velero. - -## Security - -* **fix(api): prevent IDOR in TenantNamespace Get and Watch handlers**: Two IDOR (Insecure Direct Object Reference) vulnerabilities allowed authenticated users to read TenantNamespace metadata they had no RoleBinding for. The `Get` and `Watch` handlers now go through a new `hasAccessToNamespace()` helper that lists RoleBindings scoped only to the target namespace (orders of magnitude faster than the previous all-cluster scan), returns `NotFound` instead of leaking existence on unauthorized access, and applies the same check on the `Watch` filter path. Includes regression tests for the unauthorized paths. ([**@IvanHunters**](https://github.com/IvanHunters) in #2471, backport #2524) - -## Features - -* **feat(linstor): bump linstor-csi to v1.10.6 with Protocol-C dual-attach fix**: Live migration of KubeVirt VMs on Protocol-A/B (async) DRBD volumes no longer fails with `Protocol C required`. `linstor-csi` v1.10.6 now installs a `Protocol=C` override on the resource-definition during dual-attach and reverts it on detach, so `replicated-async` StorageClasses and other Protocol-A/B resource groups support live migration without manual `drbdadm adjust` intervention. ([**@kvaps**](https://github.com/kvaps) in #2496, backport #2505) - -## Fixes - -* **fix(backups): move velero-configmap Role to velero chart**: The `backupstrategy-controller` (a default package) declared a Role/RoleBinding scoped to the `cozy-velero` namespace for managing `ResourceModifier` ConfigMaps. On bundles where Velero was not enabled, that namespace did not exist and the HelmRelease failed with `namespaces "cozy-velero" not found`, blocking installation. The Role/RoleBinding now lives in the velero chart, so it is created only when velero is actually deployed. ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2459, backport #2467) - -* **fix(etcd): remove destructive post-upgrade cert-regeneration hook**: The etcd chart ran a `post-upgrade` Helm hook on every upgrade that deleted etcd TLS Secrets (`etcd-ca-tls`, `etcd-peer-ca-tls`, `etcd-client-tls`, `etcd-peer-tls`, `etcd-server-tls`) and then deleted etcd pods, forcing cert-manager to re-issue the entire etcd CA chain. On clusters with Kamaji-managed tenant control planes this put every tenant `kube-apiserver` into CrashLoopBackOff until each DataStore was manually re-reconciled. The hook was a one-shot `2.6.0 → 2.6.1` migration that became a permanent footgun once chart versioning moved to `0.0.0+` (always `< 2.6.1` per semver) and after the underlying `rotationPolicy: Always` issue was fixed in `47d81f70`. The hook is now removed entirely. ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2462, backport #2511) - -* **fix(kamaji): increase memory limits and add startup probe**: The kamaji controller frequently entered CrashLoopBackOff due to OOMKills (exit 137) within ~20–25 seconds of startup, with the readiness probe failing while the controller was still finishing initialization. Memory limit raised from 500Mi to 512Mi, request from 100Mi to 256Mi, and a 60-second startup probe (12 attempts × 5s periods) is added so the controller has room to boot before liveness/readiness probes engage. ([**@IvanHunters**](https://github.com/IvanHunters) in #2421, backport #2491) - -## Build - -* **build(linstor): include linstor-gui in root image build target**: The `linstor-gui` package (added in #2382) was never wired into the root `Makefile`'s `build:` target, so CI never built or published the image. `ghcr.io/cozystack/cozystack/linstor-gui` returned `NAME_UNKNOWN` and `values.yaml` stayed pinned to `tag: 2.3.0` without a digest. The missing build line is added so the next CI run publishes the image and the per-package `Makefile` digest-pins `values.yaml` automatically. ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2498, backport #2518) - -## Contributors - -Thanks to everyone who contributed to this patch release: - -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kvaps**](https://github.com/kvaps) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.3.0...v1.3.1 diff --git a/hack/admin-kubeconfig-invariant.bats b/hack/admin-kubeconfig-invariant.bats deleted file mode 100644 index a4b98b00..00000000 --- a/hack/admin-kubeconfig-invariant.bats +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env bats -# ----------------------------------------------------------------------------- -# Chart-wide invariant for packages/apps/kubernetes: -# -# Every Deployment in this chart that mounts -admin-kubeconfig as a -# Secret volume MUST: -# - declare that volume optional: true (so kubelet does not FailedMount -# while Kamaji is still provisioning the Secret), AND -# - include the wait-for-kubeconfig init container (so the pod becomes -# Ready only after Kamaji publishes the Secret). -# -# The per-template unittests in packages/apps/kubernetes/tests/ lock in -# today's three Deployments (cluster-autoscaler, kccm, csi controller) by -# name. This invariant is stricter: any future Deployment added to this -# chart that mounts the same Secret but forgets the guard will fail here. -# -# Requires: helm, yq (mikefarah v4+), jq. All three are available on the -# project's CI runners and on the maintainer workstation. -# ----------------------------------------------------------------------------- - -@test "every Deployment mounting admin-kubeconfig has optional:true and wait-for-kubeconfig init" { - values_file="packages/apps/kubernetes/tests/values-ci.yaml" - [ -f "$values_file" ] - - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - helm template invariant packages/apps/kubernetes \ - --namespace tenant-root \ - --values "$values_file" \ - 2>/dev/null > "$tmp/rendered.yaml" - - # yq streams one JSON object per input document. jq -s slurps the stream - # into an array so we can treat all Deployments as a single collection. - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s --raw-output ' - map(select(.kind == "Deployment")) | - map({ - name: .metadata.name, - volumes: (.spec.template.spec.volumes // []), - initNames: ((.spec.template.spec.initContainers // []) | map(.name)), - }) | - map( - .name as $n | - .initNames as $ins | - (.volumes[] | select(.secret.secretName | test("-admin-kubeconfig$")?)) - | { - name: $n, - optional: (.secret.optional == true), - hasInit: ($ins | index("wait-for-kubeconfig") != null), - } - ) - ' > "$tmp/summary.json" - - # At least one Deployment must match; if a refactor removes every - # admin-kubeconfig volume from this chart, the test must be updated - # deliberately rather than silently passing. - matched=$(jq 'length' "$tmp/summary.json") - [ "$matched" -ge 1 ] - - offenders=$(jq --raw-output '.[] | select(.optional != true or .hasInit != true) | .name' "$tmp/summary.json") - - if [ -n "$offenders" ]; then - echo "Deployments mounting *-admin-kubeconfig without optional:true + wait-for-kubeconfig init:" >&2 - echo "$offenders" >&2 - echo "Full summary:" >&2 - cat "$tmp/summary.json" >&2 - exit 1 - fi - - echo "Invariant holds for $matched Deployment(s)" -} - -@test "chart emits zero admin-kubeconfig Deployments when tenant has no etcd DataStore" { - # Without a DataStore (parent Tenant has not populated _namespace.etcd yet) - # the control-plane-side Deployments must NOT render at all. If they did, - # the wait-for-kubeconfig init would CrashLoopBackOff indefinitely - there - # would be no KamajiControlPlane to provision the Secret - consuming the - # HelmRelease wait budget and triggering exactly the remediation cycle the - # rest of this chart tries to avoid. This test renders the whole chart - # with etcd empty and asserts no Deployment references the admin-kubeconfig - # Secret. - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - helm template invariant packages/apps/kubernetes \ - --namespace tenant-root \ - --values packages/apps/kubernetes/tests/values-ci-no-etcd.yaml \ - 2>/dev/null > "$tmp/rendered.yaml" - - matched=$( - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s ' - map(select(.kind == "Deployment")) | - map(select( - (.spec.template.spec.volumes // []) - | any(.secret.secretName | test("-admin-kubeconfig$")?) - )) | - length - ' - ) - - if [ "$matched" -ne 0 ]; then - echo "Expected zero Deployments mounting *-admin-kubeconfig when etcd is empty, got $matched:" >&2 - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s 'map(select(.kind == "Deployment") | .metadata.name)' >&2 - exit 1 - fi - - echo "No admin-kubeconfig Deployments rendered for empty etcd (as expected)" -} - -@test "chart emits zero admin-kubeconfig HelmReleases when tenant has no etcd DataStore" { - # Same principle as the Deployment variant above, extended to every child - # HelmRelease (cilium, coredns, csi, cert-manager, ...). They reference - # *-admin-kubeconfig via kubeConfig.secretRef and would otherwise sit in - # NotReady forever on an etcd-less tenant, polluting the HelmRelease list - # the operator sees and contradicting the "awaiting-etcd beacon only" - # contract of the soft-skip path. - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - helm template invariant packages/apps/kubernetes \ - --namespace tenant-root \ - --values packages/apps/kubernetes/tests/values-ci-no-etcd.yaml \ - 2>/dev/null > "$tmp/rendered.yaml" - - matched=$( - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s ' - map(select(.kind == "HelmRelease")) | - map(select(.spec.kubeConfig.secretRef.name | test("-admin-kubeconfig$")?)) | - length - ' - ) - - if [ "$matched" -ne 0 ]; then - echo "Expected zero HelmReleases referencing *-admin-kubeconfig when etcd is empty, got $matched:" >&2 - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s 'map(select(.kind == "HelmRelease") | .metadata.name)' >&2 - exit 1 - fi - - echo "No admin-kubeconfig HelmReleases rendered for empty etcd (as expected)" -} diff --git a/hack/check-gpu-recording-rules.bats b/hack/check-gpu-recording-rules.bats deleted file mode 100644 index bae6785e..00000000 --- a/hack/check-gpu-recording-rules.bats +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env bats -# ----------------------------------------------------------------------------- -# Cross-validation between GPU recording rules, the dashboards that consume -# them, and the DCGM Exporter metric set the cluster actually scrapes. Catches: -# -# 1. dangling references — a dashboard query mentions a recording rule name -# that doesn't exist in gpu-recording.rules.yaml. This is the bug the -# pre-merge review caught: gpu-efficiency.json shipped panels keyed on -# pod:tensor_saturation:avg5m without the rule being defined, so the -# panel showed "No data" everywhere. -# -# 2. typos in rule names — same bug class, manifested as a single-character -# difference between rule and reference. -# -# 3. undeclared DCGM metrics — a dashboard query or recording rule mentions -# a DCGM_FI_* metric that is neither in the upstream default CSV nor in -# the project's custom CSV (dcgm-custom-metrics.yaml), meaning DCGM -# Exporter would never emit it and the panel silently shows "No data". -# Example regression: gpu-fleet.json shipped a TDP panel referencing -# DCGM_FI_DEV_POWER_MGMT_LIMIT before the custom CSV declared it. -# -# Scope: only dashboards listed in packages/system/monitoring/dashboards-infra.list -# under the "gpu/" prefix (i.e. shipped to production), not every JSON file in -# dashboards/gpu/. Untracked drafts stay out of scope on purpose — adding one -# to dashboards-infra.list is what brings it under the test. -# -# Reverse direction (rule defined but never consumed) is intentionally NOT -# enforced: some rules exist for ad-hoc PromQL or upcoming dashboards. Treat -# unused rules as an editorial concern, not a regression. -# -# Title syntax constraints from cozytest.sh's awk parser: -# - Titles delimited by ASCII double quotes; embedded quotes truncate. -# - Only [A-Za-z0-9] from the title survives into the function name; titles -# differing only in punctuation collapse to the same function. -# -# Run with: hack/cozytest.sh hack/check-gpu-recording-rules.bats -# ----------------------------------------------------------------------------- - -REPO_ROOT="$(cd "$(dirname "${BATS_TEST_FILENAME:-$0}")/.." && pwd)" -RULES_FILE="$REPO_ROOT/packages/system/monitoring-agents/alerts/gpu-recording.rules.yaml" -DASHBOARDS_LIST="$REPO_ROOT/packages/system/monitoring/dashboards-infra.list" -DASHBOARDS_DIR="$REPO_ROOT/dashboards" -DCGM_DEFAULT_CSV="$REPO_ROOT/hack/dcgm-default-counters.csv" -DCGM_CUSTOM_CSV="$REPO_ROOT/packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml" - -# Extract the set of "- record: NAME" entries from the rules YAML. -# Outputs one rule name per line, sorted and deduplicated. -extract_rules() { - awk '/^[[:space:]]*-[[:space:]]*record:[[:space:]]/ { - sub(/^[[:space:]]*-[[:space:]]*record:[[:space:]]*/, "") - sub(/[[:space:]]*$/, "") - print - }' "$RULES_FILE" | sort -u -} - -# Extract the set of recording-rule references from a dashboard JSON. -# A recording-rule reference is matched by the pattern -# :(:)+ -# where each is [a-z0-9_]. Raw DCGM metrics (DCGM_FI_*), -# kube-state-metrics (kube_*) and similar uppercase / single-word metric -# names do not match because the leading segment must be lowercase and the -# whole expression must contain at least two ':' characters. -extract_refs() { - json_file=$1 - # Prometheus convention allows 2-segment rule names (level:metric); this - # regex is tuned to the 3+ segment convention used in this repo - # (level:metric:op — e.g. cluster:gpu_count:total). Update if future - # rules use 2 segments, otherwise they will be silently skipped. - grep -hoE '[a-z][a-z0-9_]*:[a-z0-9_]+:[a-z0-9_]+' "$json_file" | sort -u -} - -# Resolve "gpu/foo" -> "$DASHBOARDS_DIR/gpu/foo.json" -list_tracked_gpu_dashboards() { - awk '/^gpu\// { print $0 ".json" }' "$DASHBOARDS_LIST" -} - -# Extract the set of DCGM_FI_* metric names declared in a CSV file. Handles -# both the upstream-style default CSV (unindented) and the ConfigMap-style -# custom CSV (YAML-indented). A declaration line starts — after any leading -# whitespace — with "DCGM_FI_," ; comment lines begin with "#" and are -# skipped. Uses POSIX awk's match()+RSTART/RLENGTH so no GNU extensions -# are required. -extract_csv_metrics() { - file=$1 - awk ' - { - line = $0 - sub(/^[[:space:]]+/, "", line) - if (line ~ /^#/) next - if (match(line, /^DCGM_FI_[A-Z0-9_]+/)) { - print substr(line, RSTART, RLENGTH) - } - } - ' "$file" | sort -u -} - -# Extract the set of DCGM_FI_* metric references from a text file (dashboard -# JSON or rules YAML). A DCGM metric name has at least two underscore-delimited -# segments after the "DCGM_FI_" prefix (e.g. DCGM_FI_DEV_GPU_UTIL, DCGM_FI_PROF_ -# PIPE_TENSOR_ACTIVE, DCGM_FI_DRIVER_VERSION). Requiring two segments keeps -# the matcher from latching onto glob stubs like "DCGM_FI_DEV_*_VIOLATION" that -# appear in comments. -extract_dcgm_refs() { - file=$1 - grep -hoE 'DCGM_FI_[A-Z0-9]+(_[A-Z0-9]+)+' "$file" | sort -u -} - -@test "every recording rule reference in tracked GPU dashboards has a matching record" { - TMP=$(mktemp -d) - trap 'rm -rf "$TMP"' EXIT - - extract_rules > "$TMP/rules.txt" - [ -s "$TMP/rules.txt" ] || { echo "no recording rules extracted from $RULES_FILE" >&2; exit 1; } - - list_tracked_gpu_dashboards > "$TMP/dashboards.txt" - [ -s "$TMP/dashboards.txt" ] || { echo "no gpu/* dashboards listed in $DASHBOARDS_LIST" >&2; exit 1; } - - failed=0 - while IFS= read -r dashboard_rel; do - dashboard="$DASHBOARDS_DIR/$dashboard_rel" - if [ ! -f "$dashboard" ]; then - echo "ERROR: dashboard listed but file missing: $dashboard" >&2 - failed=1 - continue - fi - - extract_refs "$dashboard" > "$TMP/refs.txt" - # comm -23: lines unique to refs.txt (referenced but not defined) - # Both inputs must be sorted; extract_* helpers already sort. - comm -23 "$TMP/refs.txt" "$TMP/rules.txt" > "$TMP/missing.txt" - if [ -s "$TMP/missing.txt" ]; then - echo "ERROR: $dashboard_rel references undefined recording rules:" >&2 - sed 's/^/ - /' "$TMP/missing.txt" >&2 - failed=1 - fi - done < "$TMP/dashboards.txt" - - [ "$failed" -eq 0 ] -} - -@test "every DCGM metric referenced in tracked dashboards and rules is declared" { - TMP=$(mktemp -d) - trap 'rm -rf "$TMP"' EXIT - - [ -f "$DCGM_DEFAULT_CSV" ] || { echo "missing $DCGM_DEFAULT_CSV" >&2; exit 1; } - [ -f "$DCGM_CUSTOM_CSV" ] || { echo "missing $DCGM_CUSTOM_CSV" >&2; exit 1; } - - { - extract_csv_metrics "$DCGM_DEFAULT_CSV" - extract_csv_metrics "$DCGM_CUSTOM_CSV" - } | sort -u > "$TMP/declared.txt" - [ -s "$TMP/declared.txt" ] || { echo "no DCGM metrics extracted from CSVs" >&2; exit 1; } - - list_tracked_gpu_dashboards > "$TMP/dashboards.txt" - [ -s "$TMP/dashboards.txt" ] || { echo "no gpu/* dashboards listed in $DASHBOARDS_LIST" >&2; exit 1; } - - failed=0 - - # Dashboard coverage — every dashboard's DCGM references must resolve. - while IFS= read -r dashboard_rel; do - dashboard="$DASHBOARDS_DIR/$dashboard_rel" - [ -f "$dashboard" ] || continue # handled by the existence test - extract_dcgm_refs "$dashboard" > "$TMP/refs.txt" - [ -s "$TMP/refs.txt" ] || continue # dashboard relies entirely on recording rules - comm -23 "$TMP/refs.txt" "$TMP/declared.txt" > "$TMP/missing.txt" - if [ -s "$TMP/missing.txt" ]; then - echo "ERROR: $dashboard_rel references DCGM metrics not declared in any CSV:" >&2 - sed 's/^/ - /' "$TMP/missing.txt" >&2 - failed=1 - fi - done < "$TMP/dashboards.txt" - - # Rules coverage — recording rules consume DCGM directly, so their set - # must be declared too, otherwise derived series on every dashboard - # collapse to empty. - extract_dcgm_refs "$RULES_FILE" > "$TMP/rule-refs.txt" - if [ -s "$TMP/rule-refs.txt" ]; then - comm -23 "$TMP/rule-refs.txt" "$TMP/declared.txt" > "$TMP/rule-missing.txt" - if [ -s "$TMP/rule-missing.txt" ]; then - echo "ERROR: gpu-recording.rules.yaml references DCGM metrics not declared in any CSV:" >&2 - sed 's/^/ - /' "$TMP/rule-missing.txt" >&2 - failed=1 - fi - fi - - [ "$failed" -eq 0 ] -} - -@test "every tracked GPU dashboard listed in dashboards-infra.list exists on disk" { - TMP=$(mktemp -d) - trap 'rm -rf "$TMP"' EXIT - - list_tracked_gpu_dashboards > "$TMP/dashboards.txt" - [ -s "$TMP/dashboards.txt" ] || { echo "no gpu/* dashboards listed in $DASHBOARDS_LIST" >&2; exit 1; } - - failed=0 - while IFS= read -r dashboard_rel; do - dashboard="$DASHBOARDS_DIR/$dashboard_rel" - if [ ! -f "$dashboard" ]; then - echo "ERROR: $dashboard_rel listed in dashboards-infra.list but $dashboard does not exist" >&2 - failed=1 - fi - done < "$TMP/dashboards.txt" - - [ "$failed" -eq 0 ] -} diff --git a/hack/dcgm-default-counters.csv b/hack/dcgm-default-counters.csv deleted file mode 100644 index b5e94540..00000000 --- a/hack/dcgm-default-counters.csv +++ /dev/null @@ -1,104 +0,0 @@ -# Snapshot of the upstream DCGM Exporter default-counters.csv used as a -# fixture by hack/check-gpu-recording-rules.bats. The test verifies that -# every DCGM_FI_* metric referenced by a tracked GPU dashboard is either -# declared here (upstream defaults) or in -# packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml -# (the project's custom CSV). -# -# Source: https://github.com/NVIDIA/dcgm-exporter/blob/4.1.1-4.0.4/etc/default-counters.csv -# Pinned to the DCGM Exporter image tag shipped by the gpu-operator -# chart under packages/system/gpu-operator/charts/gpu-operator/values.yaml -# (dcgmExporter.version = 4.1.1-4.0.4-ubuntu22.04). When that image is -# bumped, refresh this file from the matching tag in the NVIDIA/dcgm-exporter -# repo and re-run `./hack/cozytest.sh hack/check-gpu-recording-rules.bats`. - -# Format -# If line starts with a '#' it is considered a comment -# DCGM FIELD, Prometheus metric type, help message - -# Clocks -DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency (in MHz). -DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz). - -# Temperature -DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature (in C). -DCGM_FI_DEV_GPU_TEMP, gauge, GPU temperature (in C). - -# Power -DCGM_FI_DEV_POWER_USAGE, gauge, Power draw (in W). -DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION, counter, Total energy consumption since boot (in mJ). - -# PCIE -# DCGM_FI_PROF_PCIE_TX_BYTES, counter, Total number of bytes transmitted through PCIe TX via NVML. -# DCGM_FI_PROF_PCIE_RX_BYTES, counter, Total number of bytes received through PCIe RX via NVML. -DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total number of PCIe retries. - -# Utilization (the sample period varies depending on the product) -DCGM_FI_DEV_GPU_UTIL, gauge, GPU utilization (in %). -DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory utilization (in %). -DCGM_FI_DEV_ENC_UTIL, gauge, Encoder utilization (in %). -DCGM_FI_DEV_DEC_UTIL , gauge, Decoder utilization (in %). - -# Errors and violations -DCGM_FI_DEV_XID_ERRORS, gauge, Value of the last XID error encountered. -# DCGM_FI_DEV_POWER_VIOLATION, counter, Throttling duration due to power constraints (in us). -# DCGM_FI_DEV_THERMAL_VIOLATION, counter, Throttling duration due to thermal constraints (in us). -# DCGM_FI_DEV_SYNC_BOOST_VIOLATION, counter, Throttling duration due to sync-boost constraints (in us). -# DCGM_FI_DEV_BOARD_LIMIT_VIOLATION, counter, Throttling duration due to board limit constraints (in us). -# DCGM_FI_DEV_LOW_UTIL_VIOLATION, counter, Throttling duration due to low utilization (in us). -# DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Throttling duration due to reliability constraints (in us). - -# Memory usage -DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free (in MiB). -DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used (in MiB). - -# ECC -# DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Total number of single-bit volatile ECC errors. -# DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Total number of double-bit volatile ECC errors. -# DCGM_FI_DEV_ECC_SBE_AGG_TOTAL, counter, Total number of single-bit persistent ECC errors. -# DCGM_FI_DEV_ECC_DBE_AGG_TOTAL, counter, Total number of double-bit persistent ECC errors. - -# Retired pages -# DCGM_FI_DEV_RETIRED_SBE, counter, Total number of retired pages due to single-bit errors. -# DCGM_FI_DEV_RETIRED_DBE, counter, Total number of retired pages due to double-bit errors. -# DCGM_FI_DEV_RETIRED_PENDING, counter, Total number of pages pending retirement. - -# NVLink -# DCGM_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_TOTAL, counter, Total number of NVLink flow-control CRC errors. -# DCGM_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_TOTAL, counter, Total number of NVLink data CRC errors. -# DCGM_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_TOTAL, counter, Total number of NVLink retries. -# DCGM_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_TOTAL, counter, Total number of NVLink recovery errors. -DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL, counter, Total number of NVLink bandwidth counters for all lanes. -# DCGM_FI_DEV_NVLINK_BANDWIDTH_L0, counter, The number of bytes of active NVLink rx or tx data including both header and payload. - -# VGPU License status -DCGM_FI_DEV_VGPU_LICENSE_STATUS, gauge, vGPU License status - -# Remapped rows -DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for uncorrectable errors -DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for correctable errors -DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, Whether remapping of rows has failed - -# Static configuration information. These appear as labels on the other metrics -DCGM_FI_DRIVER_VERSION, label, Driver Version -# DCGM_FI_NVML_VERSION, label, NVML Version -# DCGM_FI_DEV_BRAND, label, Device Brand -# DCGM_FI_DEV_SERIAL, label, Device Serial Number -# DCGM_FI_DEV_OEM_INFOROM_VER, label, OEM inforom version -# DCGM_FI_DEV_ECC_INFOROM_VER, label, ECC inforom version -# DCGM_FI_DEV_POWER_INFOROM_VER, label, Power management object inforom version -# DCGM_FI_DEV_INFOROM_IMAGE_VER, label, Inforom image version -# DCGM_FI_DEV_VBIOS_VERSION, label, VBIOS version of the device - -# Datacenter Profiling (DCP) metrics -# NOTE: supported on Nvidia datacenter Volta GPUs and newer -DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active. -# DCGM_FI_PROF_SM_ACTIVE, gauge, The ratio of cycles an SM has at least 1 warp assigned. -# DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident on an SM. -DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active. -DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of cycles the device memory interface is active sending or receiving data. -# DCGM_FI_PROF_PIPE_FP64_ACTIVE, gauge, Ratio of cycles the fp64 pipes are active. -# DCGM_FI_PROF_PIPE_FP32_ACTIVE, gauge, Ratio of cycles the fp32 pipes are active. -# DCGM_FI_PROF_PIPE_FP16_ACTIVE, gauge, Ratio of cycles the fp16 pipes are active. -DCGM_FI_PROF_PCIE_TX_BYTES, gauge, The rate of data transmitted over the PCIe bus - including both protocol headers and data payloads - in bytes per second. -DCGM_FI_PROF_PCIE_RX_BYTES, gauge, The rate of data received over the PCIe bus - including both protocol headers and data payloads - in bytes per second. diff --git a/hack/e2e-apps/remediation-guard.sh b/hack/e2e-apps/remediation-guard.sh deleted file mode 100644 index b45561b9..00000000 --- a/hack/e2e-apps/remediation-guard.sh +++ /dev/null @@ -1,39 +0,0 @@ -# Helpers for asserting that a Flux HelmRelease did not fall into an -# install/upgrade remediation cycle during an e2e run. -# -# Background: Flux helm-controller's ClearFailures() zeroes -# .status.installFailures / .status.upgradeFailures on every successful -# reconciliation (see the upstream ClearFailures method on -# HelmReleaseStatus). That makes those counters useless for a guard that -# runs after the HelmRelease has reached Ready - the values are always 0. -# -# What survives a successful reconciliation is .status.history, a bounded -# list of release Snapshots. Each Snapshot carries a status field that -# tracks the Helm release state: deployed, superseded, failed, uninstalled, -# and so on. A remediation cycle leaves the footprint behind: a snapshot -# with status "uninstalled" (from install/upgrade remediation) or "failed" -# (Helm release failure that remediation then uninstalled). Those stay in -# history even after a subsequent successful reinstall. -# -# helmrelease_has_remediation_cycle takes a newline-delimited list of -# snapshot statuses (whatever the caller extracted via kubectl -o jsonpath -# or equivalent) and returns 0 (detected) when any entry is "failed" or -# "uninstalled", 1 otherwise. Empty input is treated as "no history yet, -# no cycle observed". - -helmrelease_has_remediation_cycle() { - statuses="$1" - if [ -z "${statuses}" ]; then - return 1 - fi - # printf + grep over the pipe, rather than a heredoc plus while read. - # printf %s treats the status string as a literal payload, so any stray - # $ in a future caller's input does not trigger shell expansion. grep - # returns 0 iff at least one line matches the allowlist, which is - # exactly the contract the caller wants, so we can return its exit - # status directly. - if printf '%s\n' "${statuses}" | grep --extended-regexp --quiet '^(failed|uninstalled)$'; then - return 0 - fi - return 1 -} diff --git a/hack/e2e-apps/run-kubernetes.sh b/hack/e2e-apps/run-kubernetes.sh index 761ee57d..be6dcd6f 100644 --- a/hack/e2e-apps/run-kubernetes.sh +++ b/hack/e2e-apps/run-kubernetes.sh @@ -1,5 +1,3 @@ -. hack/e2e-apps/remediation-guard.sh - run_kubernetes_test() { local version_expr="$1" local test_name="$2" @@ -322,35 +320,6 @@ EOF done kubectl wait hr kubernetes-${test_name}-ingress-nginx -n tenant-test --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 - # and churn the Cluster CR. - # Flux helm-controller v2 retains per-revision release Snapshots in - # .status.history; each Snapshot's .status reflects the Helm release - # state (deployed/superseded/failed/uninstalled). A remediation cycle - # leaves a "failed" or "uninstalled" entry behind that survives a later - # successful reinstall, unlike the installFailures/upgradeFailures - # counters (which ClearFailures zeroes on every successful reconcile). - # The shape is pinned by hack/remediation-guard.bats; the upstream - # types are github.com/fluxcd/helm-controller/api v2 Snapshot. - history_statuses=$(kubectl get hr -n tenant-test "kubernetes-${test_name}" \ - -ojsonpath='{range .status.history[*]}{.status}{"\n"}{end}') - # Always emit the raw value so a silent future-Flux field rename shows - # up as "empty history on a Ready HR" in CI logs rather than vanishing. - echo "Parent HelmRelease history statuses:" - printf '%s\n' "${history_statuses:-}" - if [ -z "${history_statuses}" ]; then - echo "Unexpected empty .status.history on a Ready HelmRelease - Flux API shape may have changed." >&2 - kubectl -n tenant-test describe hr "kubernetes-${test_name}" >&2 - exit 1 - fi - if helmrelease_has_remediation_cycle "${history_statuses}"; then - echo "Parent HelmRelease entered remediation cycle." >&2 - kubectl -n tenant-test describe hr "kubernetes-${test_name}" >&2 - exit 1 - fi - # Clean up pkill -f "port-forward.*${port}:" 2>/dev/null || true rm -f "tenantkubeconfig-${test_name}" diff --git a/hack/e2e-prepare-cluster.bats b/hack/e2e-prepare-cluster.bats index df90b91a..7c5e85ff 100644 --- a/hack/e2e-prepare-cluster.bats +++ b/hack/e2e-prepare-cluster.bats @@ -235,8 +235,11 @@ EOF } @test "Bootstrap Talos cluster" { - # Bootstrap etcd on the first node - timeout 10 sh -ec 'until talosctl bootstrap -n 192.168.123.11 -e 192.168.123.11; do sleep 1; done' + # Bootstrap etcd on the first node. + # Retry for up to 60s: talosctl bootstrap refuses with "time is not in + # sync yet" until NTP converges on a freshly booted node, which on fast + # ephemeral runners can take several attempts of ~5s each. + timeout 60 sh -ec 'until talosctl bootstrap -n 192.168.123.11 -e 192.168.123.11; do sleep 2; done' # Wait until etcd is healthy if ! timeout 180 sh -ec 'until talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 >/dev/null 2>&1; do sleep 1; done'; then diff --git a/hack/remediation-guard.bats b/hack/remediation-guard.bats deleted file mode 100644 index 092fe06d..00000000 --- a/hack/remediation-guard.bats +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bats -# ----------------------------------------------------------------------------- -# Unit tests for hack/e2e-apps/remediation-guard.sh -# -# helmrelease_has_remediation_cycle takes a newline-delimited list of -# HelmRelease history snapshot status values (deployed/superseded/failed/ -# uninstalled/...) and returns 0 when any entry is "failed" or "uninstalled" -# (meaning flux helm-controller performed install/upgrade remediation). -# -# This is used by the e2e script after the HelmRelease reaches Ready. The -# failure/upgrade counters (.status.installFailures / .status.upgradeFailures) -# are useless there because flux's ClearFailures zeroes them on successful -# reconciliation; .status.history retains the snapshot trail. -# -# cozytest.sh's awk parser recognizes only @test blocks and a bare `}` on -# its own line; there is no bats `run` or `$status`. Assertions are -# expressed as direct shell tests that exit non-zero on failure. -# -# Run with: hack/cozytest.sh hack/remediation-guard.bats -# ----------------------------------------------------------------------------- - -@test "empty history returns not-detected" { - . hack/e2e-apps/remediation-guard.sh - if helmrelease_has_remediation_cycle ""; then - echo "expected not-detected for empty history" >&2 - exit 1 - fi -} - -@test "single deployed snapshot returns not-detected" { - . hack/e2e-apps/remediation-guard.sh - if helmrelease_has_remediation_cycle "deployed"; then - echo "expected not-detected for deployed-only history" >&2 - exit 1 - fi -} - -@test "deployed then superseded returns not-detected" { - . hack/e2e-apps/remediation-guard.sh - statuses=$(printf 'deployed\nsuperseded\n') - if helmrelease_has_remediation_cycle "${statuses}"; then - echo "expected not-detected for deployed+superseded history" >&2 - exit 1 - fi -} - -@test "single failed snapshot returns detected" { - . hack/e2e-apps/remediation-guard.sh - if ! helmrelease_has_remediation_cycle "failed"; then - echo "expected detected when history contains failed snapshot" >&2 - exit 1 - fi -} - -@test "single uninstalled snapshot returns detected" { - # The exact signature of the install-remediation race: the first install - # exceeded flux's wait budget, remediation uninstalled, the next retry - # eventually succeeded. History still carries the uninstalled snapshot. - . hack/e2e-apps/remediation-guard.sh - if ! helmrelease_has_remediation_cycle "uninstalled"; then - echo "expected detected when history contains uninstalled snapshot" >&2 - exit 1 - fi -} - -@test "uninstalled then deployed still returns detected" { - . hack/e2e-apps/remediation-guard.sh - statuses=$(printf 'uninstalled\ndeployed\n') - if ! helmrelease_has_remediation_cycle "${statuses}"; then - echo "expected detected despite later successful deploy" >&2 - exit 1 - fi -} - -@test "deployed then failed still returns detected" { - . hack/e2e-apps/remediation-guard.sh - statuses=$(printf 'deployed\nfailed\n') - if ! helmrelease_has_remediation_cycle "${statuses}"; then - echo "expected detected when any entry is failed" >&2 - exit 1 - fi -} - -@test "status.history extraction pins HR v2 status.history shape" { - # Pins the Flux HelmRelease v2 .status.history[].status shape that - # run-kubernetes.sh relies on. If a future flux release renames the - # field, the jsonpath returns nothing, the guard reports no cycle, - # and real remediation loops slip past the e2e assertion. This test - # uses yq to read the exact path used in the e2e script; the upstream - # Snapshot type lives at - # github.com/fluxcd/helm-controller/api/v2.Snapshot (via go.mod). - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - cat > "$tmp/hr.yaml" <<'YAML' -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: kubernetes-test - namespace: tenant-test -status: - history: - - name: kubernetes-test - namespace: tenant-test - version: 1 - status: uninstalled - - name: kubernetes-test - namespace: tenant-test - version: 2 - status: deployed -YAML - - # Default yq output is yaml scalar format, which for string values emits - # bare unquoted tokens - matching what kubectl -o jsonpath produces in - # e2e. Do not switch to JSON output here; that would quote the values - # and break the loop in helmrelease_has_remediation_cycle. - statuses=$(yq '.status.history[].status' "$tmp/hr.yaml") - - [ -n "$statuses" ] - echo "$statuses" | grep --quiet '^uninstalled$' - - . hack/e2e-apps/remediation-guard.sh - if ! helmrelease_has_remediation_cycle "$statuses"; then - echo "expected detected for pinned HR snippet with uninstalled + deployed history" >&2 - exit 1 - fi -} diff --git a/internal/controller/dashboard/sidebar.go b/internal/controller/dashboard/sidebar.go index 69c933fb..90721b3d 100644 --- a/internal/controller/dashboard/sidebar.go +++ b/internal/controller/dashboard/sidebar.go @@ -144,9 +144,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati // Add sidebar for backups.cozystack.io Backup resource keysAndTags["backups"] = []any{"backup-sidebar"} - // Add sidebar for backups.cozystack.io RestoreJob resource - keysAndTags["restorejobs"] = []any{"restorejob-sidebar"} - // 3) Sort items within each category by Weight (desc), then Label (A→Z) for cat := range categories { sort.Slice(categories[cat], func(i, j int) bool { @@ -218,11 +215,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati "label": "Backups", "link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backups", }, - map[string]any{ - "key": "restorejobs", - "label": "RestoreJobs", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/restorejobs", - }, }, }) @@ -266,7 +258,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati "stock-project-factory-plan-details", "stock-project-factory-backupjob-details", "stock-project-factory-backup-details", - "stock-project-factory-restorejob-details", "stock-project-factory-external-ips", "stock-project-api-form", "stock-project-api-table", @@ -281,12 +272,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati "stock-instance-builtin-table", } - // Add details sidebars for all CRDs with dashboard config, and collect - // the set of IDs that are genuinely CRD-backed (dynamic). The hardcoded - // `-details` IDs above (e.g. kube-* and backup/backupjob/plan/restorejob) - // are not tied to an ApplicationDefinition and must be treated as static - // so they receive consistent labels via upsertMultipleSidebars(). - dynamicDetailsIDs := map[string]bool{} + // Add details sidebars for all CRDs with dashboard config for i := range all { def := &all[i] if def.Spec.Dashboard == nil { @@ -296,22 +282,17 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati lowerKind := strings.ToLower(kind) detailsID := fmt.Sprintf("stock-project-factory-%s-details", lowerKind) targetIDs = append(targetIDs, detailsID) - dynamicDetailsIDs[detailsID] = true } // 7) Upsert all target sidebars with identical menuItems and keysAndTags - return m.upsertMultipleSidebars(ctx, crd, targetIDs, dynamicDetailsIDs, keysAndTags, menuItems) + return m.upsertMultipleSidebars(ctx, crd, targetIDs, keysAndTags, menuItems) } // upsertMultipleSidebars creates/updates several Sidebar resources with the same menu spec. -// dynamicDetailsIDs identifies `stock-project-factory--details` sidebars that are -// backed by an ApplicationDefinition and should therefore be owned by that CRD. -// Any other ID is treated as a static sidebar (managed-by labels, no owner ref). func (m *Manager) upsertMultipleSidebars( ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition, ids []string, - dynamicDetailsIDs map[string]bool, keysAndTags map[string]any, menuItems []any, ) error { @@ -327,10 +308,8 @@ func (m *Manager) upsertMultipleSidebars( if _, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error { // Only set owner reference for dynamic sidebars (stock-project-factory-{kind}-details) - // that are actually backed by an ApplicationDefinition. Static sidebars — including - // hardcoded details sidebars for built-in/backup resources — must fall through to the - // static-label branch so they're managed consistently. - if strings.HasPrefix(id, "stock-project-factory-") && strings.HasSuffix(id, "-details") && dynamicDetailsIDs[id] { + // Static sidebars (stock-instance-*, stock-project-*) should not have owner references + if strings.HasPrefix(id, "stock-project-factory-") && strings.HasSuffix(id, "-details") { // This is a dynamic sidebar, set owner reference only if it matches the current CRD _, _, kind := pickGVK(crd) lowerKind := strings.ToLower(kind) diff --git a/internal/controller/dashboard/static_refactored.go b/internal/controller/dashboard/static_refactored.go index 9f28c0fb..d96bbaaa 100644 --- a/internal/controller/dashboard/static_refactored.go +++ b/internal/controller/dashboard/static_refactored.go @@ -425,14 +425,6 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createTimestampColumn("Taken At", ".spec.takenAt"), createTimestampColumn("Created", ".metadata.creationTimestamp"), }), - - // Stock namespace backups cozystack io v1alpha1 restorejobs - createCustomColumnsOverride("stock-namespace-/backups.cozystack.io/v1alpha1/restorejobs", []any{ - createCustomColumnWithJsonPath("Name", ".metadata.name", "RestoreJob", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/restorejob-details/{reqsJsonPath[0]['.metadata.name']['-']}"), - createStringColumn("Phase", ".status.phase"), - createStringColumn("Backup", ".spec.backupRef.name"), - createTimestampColumn("Created", ".metadata.creationTimestamp"), - }), } } @@ -555,31 +547,6 @@ func CreateAllCustomFormsOverrides() []*dashboardv1alpha1.CustomFormsOverride { "backupClassName": listInputScemaItemBackupClass(), }), }), - - // RestoreJobs form override - backups.cozystack.io/v1alpha1 - createCustomFormsOverride("default-/backups.cozystack.io/v1alpha1/restorejobs", map[string]any{ - "formItems": []any{ - createFormItem("metadata.name", "Name", "text"), - createFormItem("metadata.namespace", "Namespace", "text"), - createFormItem("spec.backupRef.name", "Backup", "text"), - // Target application: leave empty to restore into the same application - // as referenced by the selected Backup. Fill all three to restore into - // a different application (e.g. rename, or restore into a new target). - createFormItem("spec.targetApplicationRef.apiGroup", "Target Application API Group (optional, used to restore into a different application)", "text"), - createFormItem("spec.targetApplicationRef.kind", "Target Application Kind (optional, used to restore into a different application)", "text"), - createFormItem("spec.targetApplicationRef.name", "Target Application Name (optional, used to restore into a different application)", "text"), - // Driver-specific options (key-value editor). Refer to the backup driver - // documentation for supported keys. - createFormItem("spec.options", "Options (driver-specific key/value pairs)", "object"), - }, - "schema": createSchema(map[string]any{ - "backupRef": map[string]any{ - "properties": map[string]any{ - "name": listInputSchemaItemBackup(), - }, - }, - }), - }), } } @@ -1970,177 +1937,6 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { } backupSpec := createUnifiedFactory(backupConfig, backupTabs, []any{"/api/clusters/{2}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{3}/backups/{6}"}) - // RestoreJob details factory using unified approach - restoreJobConfig := UnifiedResourceConfig{ - Name: "restorejob-details", - ResourceType: "factory", - Kind: "RestoreJob", - Plural: "restorejobs", - Title: "restorejob", - } - restoreJobTabs := []any{ - map[string]any{ - "key": "details", - "label": "Details", - "children": []any{ - contentCard("details-card", map[string]any{ - "marginBottom": "24px", - }, []any{ - antdText("details-title", true, "RestoreJob details", map[string]any{ - "fontSize": 20, - "marginBottom": "12px", - }), - spacer("details-spacer", 16), - antdRow("details-grid", []any{48, 12}, []any{ - antdCol("col-left", 12, []any{ - antdFlexVertical("col-left-stack", 24, []any{ - antdFlexVertical("meta-name-block", 4, []any{ - antdText("meta-name-label", true, "Name", nil), - parsedText("meta-name-value", "{reqsJsonPath[0]['.metadata.name']['-']}", nil), - }), - antdFlexVertical("meta-namespace-block", 8, []any{ - antdText("meta-namespace-label", true, "Namespace", nil), - antdFlex("header-row", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "header-badge", - "text": "NS", - "title": "namespace", - "style": map[string]any{ - "backgroundColor": "#a25792ff", - "borderRadius": "20px", - "color": "#fff", - "display": "inline-block", - "fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif", - "fontSize": "15px", - "fontWeight": 400, - "lineHeight": "24px", - "minWidth": 24, - "padding": "0 9px", - "textAlign": "center", - "whiteSpace": "nowrap", - }, - }, - }, - map[string]any{ - "type": "antdLink", - "data": map[string]any{ - "id": "namespace-link", - "text": "{reqsJsonPath[0]['.metadata.namespace']['-']}", - "href": "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace", - }, - }, - }), - }), - antdFlexVertical("meta-created-block", 4, []any{ - antdText("created-time-label", true, "Created", nil), - antdFlex("created-time-block", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "created-time-icon", - "text": "🌐", - }, - }, - map[string]any{ - "type": "parsedText", - "data": map[string]any{ - "formatter": "timestamp", - "id": "created-time-value", - "text": "{reqsJsonPath[0]['.metadata.creationTimestamp']['-']}", - }, - }, - }), - }), - }), - }), - antdCol("col-right", 12, []any{ - antdFlexVertical("col-right-stack", 24, []any{ - antdFlexVertical("status-phase-block", 4, []any{ - antdText("phase-label", true, "Phase", nil), - parsedText("phase-value", "{reqsJsonPath[0]['.status.phase']['-']}", nil), - }), - antdFlexVertical("spec-backup-ref-block", 4, []any{ - antdText("backup-ref-label", true, "Backup Ref", nil), - parsedText("backup-ref-value", "{reqsJsonPath[0]['.spec.backupRef.name']['-']}", nil), - }), - antdFlexVertical("spec-target-application-ref-block", 4, []any{ - antdText("target-application-ref-label", true, "Target Application", nil), - // targetApplicationRef is optional — when absent, the restore targets - // the same application as the selected Backup. Show a single friendly - // fallback in that case instead of rendering "-.-/-". - parsedText("target-application-ref-value", "{reqsJsonPath[0]['.spec.targetApplicationRef.name']['Same as backup']}", nil), - }), - antdFlexVertical("spec-options-target-namespace-block", 4, []any{ - antdText("options-target-namespace-label", true, "Target Namespace", nil), - parsedText("options-target-namespace-value", "{reqsJsonPath[0]['.spec.options.targetNamespace']['-']}", nil), - }), - antdFlexVertical("spec-options-fail-if-target-exists-block", 4, []any{ - antdText("options-fail-if-target-exists-label", true, "Fail If Target Exists", nil), - parsedText("options-fail-if-target-exists-value", "{reqsJsonPath[0]['.spec.options.failIfTargetExists']['-']}", nil), - }), - antdFlexVertical("spec-options-keep-original-pvc-block", 4, []any{ - antdText("options-keep-original-pvc-label", true, "Keep Original PVC", nil), - parsedText("options-keep-original-pvc-value", "{reqsJsonPath[0]['.spec.options.keepOriginalPVC']['-']}", nil), - }), - antdFlexVertical("spec-options-keep-original-ip-mac-block", 4, []any{ - antdText("options-keep-original-ip-mac-label", true, "Keep Original IP/MAC", nil), - parsedText("options-keep-original-ip-mac-value", "{reqsJsonPath[0]['.spec.options.keepOriginalIpAndMac']['-']}", nil), - }), - antdFlexVertical("status-started-at-block", 4, []any{ - antdText("started-at-label", true, "Started At", nil), - antdFlex("started-at-time-block", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "started-at-time-icon", - "text": "🌐", - }, - }, - map[string]any{ - "type": "parsedText", - "data": map[string]any{ - "formatter": "timestamp", - "id": "started-at-time-value", - "text": "{reqsJsonPath[0]['.status.startedAt']['-']}", - }, - }, - }), - }), - antdFlexVertical("status-completed-at-block", 4, []any{ - antdText("completed-at-label", true, "Completed At", nil), - antdFlex("completed-at-time-block", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "completed-at-time-icon", - "text": "🌐", - }, - }, - map[string]any{ - "type": "parsedText", - "data": map[string]any{ - "formatter": "timestamp", - "id": "completed-at-time-value", - "text": "{reqsJsonPath[0]['.status.completedAt']['-']}", - }, - }, - }), - }), - antdFlexVertical("status-message-block", 4, []any{ - antdText("message-label", true, "Message", nil), - parsedText("message-value", "{reqsJsonPath[0]['.status.message']['-']}", nil), - }), - }), - }), - }), - }), - }, - }, - } - restoreJobSpec := createUnifiedFactory(restoreJobConfig, restoreJobTabs, []any{"/api/clusters/{2}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{3}/restorejobs/{6}"}) - // External IPs factory (filtered services) externalIPsTabs := []any{ map[string]any{ @@ -2193,7 +1989,6 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { createFactory("plan-details", planSpec), createFactory("backupjob-details", backupJobSpec), createFactory("backup-details", backupSpec), - createFactory("restorejob-details", restoreJobSpec), createFactory("external-ips", externalIPsSpec), } } @@ -2213,10 +2008,9 @@ func CreateAllNavigations() []*dashboardv1alpha1.Navigation { "base-factory-namespaced-api-networking.k8s.io-v1-ingresses": "kube-ingress-details", "base-factory-namespaced-api-cozystack.io-v1alpha1-workloadmonitors": "workloadmonitor-details", // Backup resources (not ApplicationDefinitions, so ensureNavigation doesn't cover them) - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-plans": "plan-details", - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-backupjobs": "backupjob-details", - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-backups": "backup-details", - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-restorejobs": "restorejob-details", + "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-plans": "plan-details", + "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-backupjobs": "backupjob-details", + "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-backups": "backup-details", } return []*dashboardv1alpha1.Navigation{ @@ -2341,19 +2135,6 @@ func listInputScemaItemBackupClass() map[string]any { } } -// listInputSchemaItemBackup returns a listInput schema overlay for selecting a Backup -// from the current namespace (used by RestoreJob form for spec.backupRef.name). -func listInputSchemaItemBackup() map[string]any { - return map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{namespace}/backups", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } -} - // backupClassSchema returns the schema for spec.backupClassName as listInput (BackupJob/Plan). func createSchema(customProps map[string]any) map[string]any { return map[string]any{ diff --git a/internal/crdinstall/manifests/cozystack.io_packagesources.yaml b/internal/crdinstall/manifests/cozystack.io_packagesources.yaml index 1d0037df..0acfcdd2 100644 --- a/internal/crdinstall/manifests/cozystack.io_packagesources.yaml +++ b/internal/crdinstall/manifests/cozystack.io_packagesources.yaml @@ -118,19 +118,6 @@ spec: ReleaseName is the name of the HelmRelease resource that will be created If not specified, defaults to the component Name field type: string - upgradeCRDs: - description: |- - UpgradeCRDs controls how CRDs from the chart's crds/ directory are - handled on HelmRelease upgrades. Maps to HelmRelease.Spec.Upgrade.CRDs. - Empty string (default) preserves the helm-controller default (Skip). - Use "CreateReplace" for operators that evolve their CRD set between - versions. Warning: CreateReplace overwrites CRDs and may cause data - loss if upstream drops fields from a CRD with live objects. - enum: - - Skip - - Create - - CreateReplace - type: string type: object libraries: description: |- diff --git a/internal/operator/package_reconciler.go b/internal/operator/package_reconciler.go index 0e724e49..32e667e4 100644 --- a/internal/operator/package_reconciler.go +++ b/internal/operator/package_reconciler.go @@ -45,16 +45,6 @@ const ( SecretCozystackValues = "cozystack-values" ) -// parseCRDPolicy maps ComponentInstall.UpgradeCRDs to a helmv2.CRDsPolicy. -// Empty / nil preserves the helm-controller default (Skip on upgrade); -// the CRD enum marker restricts the string to Skip/Create/CreateReplace. -func parseCRDPolicy(install *cozyv1alpha1.ComponentInstall) helmv2.CRDsPolicy { - if install == nil || install.UpgradeCRDs == "" { - return "" - } - return helmv2.CRDsPolicy(install.UpgradeCRDs) -} - // PackageReconciler reconciles Package resources type PackageReconciler struct { client.Client @@ -231,7 +221,6 @@ func (r *PackageReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct Remediation: &helmv2.UpgradeRemediation{ Retries: -1, }, - CRDs: parseCRDPolicy(component.Install), }, }, } diff --git a/internal/operator/package_reconciler_test.go b/internal/operator/package_reconciler_test.go deleted file mode 100644 index f0ee2c19..00000000 --- a/internal/operator/package_reconciler_test.go +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package operator - -import ( - "encoding/json" - "os" - "path/filepath" - "testing" - - cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - helmv2 "github.com/fluxcd/helm-controller/api/v2" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "sigs.k8s.io/yaml" -) - -func TestParseCRDPolicy(t *testing.T) { - tests := []struct { - name string - install *cozyv1alpha1.ComponentInstall - want helmv2.CRDsPolicy - }{ - { - name: "nil install leaves flux default", - install: nil, - want: "", - }, - { - name: "empty upgradeCRDs leaves flux default", - install: &cozyv1alpha1.ComponentInstall{}, - want: "", - }, - { - name: "Skip is passed through", - install: &cozyv1alpha1.ComponentInstall{UpgradeCRDs: "Skip"}, - want: helmv2.Skip, - }, - { - name: "Create is passed through", - install: &cozyv1alpha1.ComponentInstall{UpgradeCRDs: "Create"}, - want: helmv2.Create, - }, - { - name: "CreateReplace is passed through", - install: &cozyv1alpha1.ComponentInstall{UpgradeCRDs: "CreateReplace"}, - want: helmv2.CreateReplace, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - got := parseCRDPolicy(tc.install) - if got != tc.want { - t.Errorf("parseCRDPolicy() = %q, want %q", got, tc.want) - } - }) - } -} - -// TestPackageSourceCRDHasUpgradeCRDsEnum guards the generated CRD schema: the -// invalid-value case from the spec is enforced at the API server via a -// kubebuilder enum marker, not in the reconciler. If someone drops the marker -// and forgets to regenerate, this test catches it. -func TestPackageSourceCRDHasUpgradeCRDsEnum(t *testing.T) { - path := filepath.Join("..", "crdinstall", "manifests", "cozystack.io_packagesources.yaml") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read %s: %v", path, err) - } - - var crd apiextensionsv1.CustomResourceDefinition - if err := yaml.Unmarshal(data, &crd); err != nil { - t.Fatalf("unmarshal CRD: %v", err) - } - - var field *apiextensionsv1.JSONSchemaProps - for i := range crd.Spec.Versions { - v := &crd.Spec.Versions[i] - if v.Schema == nil || v.Schema.OpenAPIV3Schema == nil { - continue - } - spec, ok := v.Schema.OpenAPIV3Schema.Properties["spec"] - if !ok { - continue - } - variants, ok := spec.Properties["variants"] - if !ok || variants.Items == nil || variants.Items.Schema == nil { - continue - } - components, ok := variants.Items.Schema.Properties["components"] - if !ok || components.Items == nil || components.Items.Schema == nil { - continue - } - install, ok := components.Items.Schema.Properties["install"] - if !ok { - continue - } - f, ok := install.Properties["upgradeCRDs"] - if !ok { - continue - } - field = &f - break - } - - if field == nil { - t.Fatal("upgradeCRDs field not found in PackageSource CRD schema") - } - - got := map[string]bool{} - for _, e := range field.Enum { - var s string - if err := json.Unmarshal(e.Raw, &s); err != nil { - t.Fatalf("unmarshal enum value %q: %v", e.Raw, err) - } - got[s] = true - } - - for _, want := range []string{"Skip", "Create", "CreateReplace"} { - if !got[want] { - t.Errorf("enum value %q missing from upgradeCRDs; got %v", want, got) - } - } -} diff --git a/packages/apps/harbor/templates/ingress.yaml b/packages/apps/harbor/templates/ingress.yaml index 70933f5f..bb6ef07c 100644 --- a/packages/apps/harbor/templates/ingress.yaml +++ b/packages/apps/harbor/templates/ingress.yaml @@ -15,7 +15,7 @@ metadata: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/backend-protocol: "HTTP" {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} spec: diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index 4fea42ef..01cf736d 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -4,9 +4,6 @@ KUBERNETES_PKG_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) include ../../../hack/common-envs.mk include ../../../hack/package.mk -test: - helm unittest . - generate: cozyvalues-gen -m 'kubernetes' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/kubernetes/types.go ../../../hack/update-crd.sh @@ -70,4 +67,3 @@ image-cluster-autoscaler: echo "$(REGISTRY)/cluster-autoscaler:$(call settag,$(KUBERNETES_PKG_TAG))@$$(yq e '."containerimage.digest"' images/cluster-autoscaler.json -o json -r)" \ > images/cluster-autoscaler.tag rm -f images/cluster-autoscaler.json - diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index bed1117a..d62d3a39 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -128,9 +128,6 @@ See the reference for components utilized in this service: | `addons.gpuOperator` | NVIDIA GPU Operator. | `object` | `{}` | | `addons.gpuOperator.enabled` | Enable GPU Operator. | `bool` | `false` | | `addons.gpuOperator.valuesOverride` | Custom Helm values overrides. | `object` | `{}` | -| `addons.hami` | HAMi GPU virtualization middleware. | `object` | `{}` | -| `addons.hami.enabled` | Enable HAMi (requires GPU Operator). | `bool` | `false` | -| `addons.hami.valuesOverride` | Custom Helm values overrides. | `object` | `{}` | | `addons.fluxcd` | FluxCD GitOps operator. | `object` | `{}` | | `addons.fluxcd.enabled` | Enable FluxCD. | `bool` | `false` | | `addons.fluxcd.valuesOverride` | Custom Helm values overrides. | `object` | `{}` | @@ -148,33 +145,31 @@ See the reference for components utilized in this service: ### Kubernetes Control Plane Configuration -| Name | Description | Type | Value | -| --------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------- | ------- | -| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` | -| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` | -| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` | -| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` | -| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `large` | -| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` | -| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` | -| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` | -| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` | -| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` | -| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` | -| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` | -| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `images` | Optional image overrides for air-gapped or rate-limited registries. | `object` | `{}` | -| `images.waitForKubeconfig` | Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag. | `string` | `""` | +| Name | Description | Type | Value | +| --------------------------------------------------- | ------------------------------------------------ | ---------- | ------- | +| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` | +| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` | +| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` | +| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` | +| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `large` | +| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` | +| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` | +| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` | +| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` | +| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` | +| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` | +| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` | +| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | ## Parameter examples and reference diff --git a/packages/apps/kubernetes/images/busybox.tag b/packages/apps/kubernetes/images/busybox.tag deleted file mode 100644 index 39de220a..00000000 --- a/packages/apps/kubernetes/images/busybox.tag +++ /dev/null @@ -1 +0,0 @@ -docker.io/library/busybox:1.37.0@sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index 00aa2caa..ea4a21b3 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:72154a97054e16cdf3dea6129d962b8d7e86b55cf9386095e8ac2ce7c8b69172 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:36e26a6b9063761ca3f5597bbd6272651d8a502abbc1c4e3a20e6b7e45a2875a diff --git a/packages/apps/kubernetes/templates/_helpers.tpl b/packages/apps/kubernetes/templates/_helpers.tpl index 40a8ae7a..36c06b64 100644 --- a/packages/apps/kubernetes/templates/_helpers.tpl +++ b/packages/apps/kubernetes/templates/_helpers.tpl @@ -49,52 +49,3 @@ Selector labels app.kubernetes.io/name: {{ include "kubernetes.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} - -{{/* -wait-for-kubeconfig init container shared by the control-plane-side -Deployments (cluster-autoscaler, kccm, kcsi-controller) that mount the -*-admin-kubeconfig Secret provisioned asynchronously by Kamaji. The -Secret volume is declared optional so kubelet does not FailedMount while -Kamaji is still bootstrapping; this container polls the mounted path and -exits only when super-admin.svc appears, which happens after kubelet's -optional-Secret refresh cycle. - -The 10m deadline stays strictly below the 15m HelmRelease -Install.Timeout set by cozystack-api for the Kubernetes kind (via the -release.cozystack.io/helm-install-timeout annotation) so the -CrashLoopBackOff surfaces before flux remediation fires and uninstalls -the Cluster CR. - -The default image lives in images/busybox.tag and points directly at -docker.io by digest (not mirrored to ghcr.io like the other .tag files -here): the payload is a one-shot sh loop and the digest pin makes the -pull immutable. Operators in air-gapped or rate-limited environments -can override it via .Values.images.waitForKubeconfig (any registry -reference kubelet can pull). When the value is empty the chart falls -back to the bundled digest pin, preserving the prior default. - -Call site owns the surrounding volumes block; the kubeconfig volume -must exist on the pod and mount at /etc/kubernetes/kubeconfig. -*/}} -{{- define "kubernetes.waitForAdminKubeconfig" -}} -- name: wait-for-kubeconfig - image: "{{ default (.Files.Get "images/busybox.tag" | trim) .Values.images.waitForKubeconfig }}" - command: - - sh - - -c - - | - set -eu - deadline=$(( $(date +%s) + 600 )) - until [ -s /etc/kubernetes/kubeconfig/super-admin.svc ]; do - if [ "$(date +%s)" -ge "$deadline" ]; then - echo "admin kubeconfig was not provisioned within 10m; exiting so the pod goes CrashLoopBackOff and surfaces in dashboards" >&2 - exit 1 - fi - echo "waiting for admin kubeconfig (provisioned by Kamaji, visible after kubelet Secret refresh)..." - sleep 5 - done - volumeMounts: - - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true -{{- end }} diff --git a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml index 298d86db..a00e0155 100644 --- a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml +++ b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml @@ -1,14 +1,3 @@ -{{- /* - Gate the control-plane-side workloads on the parent tenant having an etcd - DataStore. Without it no KamajiControlPlane is ever created, Kamaji never - provisions -admin-kubeconfig, and rendering these Deployments would cause - the wait-for-kubeconfig init to CrashLoopBackOff indefinitely, consuming - the parent HelmRelease install timeout and triggering the very uninstall - remediation cycle this chart is supposed to avoid. Rendering them only - when $etcd is set keeps the HelmRelease Ready while flux retries on its - interval and picks up the DataStore as soon as the Tenant chart finishes. -*/}} -{{- if .Values._namespace.etcd }} --- apiVersion: apps/v1 kind: Deployment @@ -34,8 +23,6 @@ spec: - key: node-role.kubernetes.io/control-plane operator: Exists effect: "NoSchedule" - initContainers: - {{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }} containers: - image: "{{ $.Files.Get "images/cluster-autoscaler.tag" | trim }}" name: cluster-autoscaler @@ -69,7 +56,6 @@ spec: name: cloud-config - secret: secretName: {{ .Release.Name }}-admin-kubeconfig - optional: true name: kubeconfig serviceAccountName: {{ .Release.Name }}-cluster-autoscaler terminationGracePeriodSeconds: 10 @@ -119,4 +105,3 @@ rules: - list - update - watch -{{- end }} diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index e1494e64..10d6fd80 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -1,15 +1,4 @@ {{- $etcd := .Values._namespace.etcd }} -{{- /* - When $etcd is empty, the parent Tenant application has not populated - _namespace.etcd in cozystack-values yet - either the operator forgot to - set etcd: true on an ancestor Tenant, or the Tenant HelmRelease is still - reconciling. Either way, rendering a KamajiControlPlane with an empty - dataStoreName would be rejected by Kamaji's admission webhook and the - HelmRelease would fail to install, triggering remediation. Instead, emit - a single ConfigMap as a user-visible status beacon and skip the rest so - flux marks the HelmRelease Ready and retries its 5m reconcile loop until - the Tenant chart catches up. -*/}} {{- $ingress := .Values._namespace.ingress }} {{- $host := .Values._namespace.host }} {{- $kubevirtmachinetemplateNames := list }} @@ -95,26 +84,6 @@ spec: - name: default pod: {} {{- end }} -{{- if not $etcd }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Release.Name }}-awaiting-etcd - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/name: kubernetes - app.kubernetes.io/instance: {{ .Release.Name }} -data: - status: "awaiting-etcd" - message: | - No DataStore is available for this tenant Kubernetes cluster. The parent - Tenant application has not populated _namespace.etcd. Set spec.etcd: true - on an ancestor Tenant (usually tenant-root) and wait for its HelmRelease - to reconcile - this HelmRelease will pick up the DataStore on its next - 5m reconcile loop and provision the cluster. -{{- else }} --- apiVersion: cluster.x-k8s.io/v1beta1 kind: Cluster @@ -435,4 +404,3 @@ metadata: spec: {{- .spec | toYaml | nindent 2 }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/csi/deploy.yaml b/packages/apps/kubernetes/templates/csi/deploy.yaml index de62104c..938b6d67 100644 --- a/packages/apps/kubernetes/templates/csi/deploy.yaml +++ b/packages/apps/kubernetes/templates/csi/deploy.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} kind: Deployment apiVersion: apps/v1 metadata: @@ -25,8 +24,6 @@ spec: - key: node-role.kubernetes.io/control-plane operator: Exists effect: "NoSchedule" - initContainers: - {{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }} containers: - name: csi-driver imagePullPolicy: Always @@ -237,6 +234,4 @@ spec: emptyDir: {} - secret: secretName: {{ .Release.Name }}-admin-kubeconfig - optional: true name: kubeconfig -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml index fd9dac7e..be07a8b9 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.certManager.enabled .Values._namespace.etcd }} +{{- if .Values.addons.certManager.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml index 700b666e..6857581a 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml @@ -8,7 +8,7 @@ cert-manager: {{- end }} {{- end }} -{{- if and .Values.addons.certManager.enabled .Values._namespace.etcd }} +{{- if .Values.addons.certManager.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index d8c90cbf..d032f5b6 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -14,7 +14,6 @@ cilium: {{- end }} {{- end }} -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -56,4 +55,3 @@ spec: - name: {{ .Release.Name }}-gateway-api-crds namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/coredns.yaml b/packages/apps/kubernetes/templates/helmreleases/coredns.yaml index 0711a51d..bdb6c682 100644 --- a/packages/apps/kubernetes/templates/helmreleases/coredns.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/coredns.yaml @@ -4,7 +4,6 @@ coredns: clusterIP: "10.95.0.10" {{- end }} -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -43,4 +42,3 @@ spec: {{- end }} - name: {{ .Release.Name }}-cilium namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/csi.yaml b/packages/apps/kubernetes/templates/helmreleases/csi.yaml index 109d78e1..dd2c69a6 100644 --- a/packages/apps/kubernetes/templates/helmreleases/csi.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/csi.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -40,4 +39,3 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml index 25fff01c..76499dfe 100644 --- a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.fluxcd.enabled .Values._namespace.etcd }} +{{- if .Values.addons.fluxcd.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml index b4172ed1..2bcc8d4d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml @@ -1,4 +1,4 @@ -{{- if and $.Values.addons.gatewayAPI.enabled $.Values._namespace.etcd }} +{{- if $.Values.addons.gatewayAPI.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml index 655dc868..5ef48912 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml @@ -1,12 +1,4 @@ -{{- define "cozystack.defaultGpuOperatorValues" -}} -{{- if .Values.addons.hami.enabled }} -gpu-operator: - devicePlugin: - enabled: false -{{- end }} -{{- end }} - -{{- if and .Values.addons.gpuOperator.enabled .Values._namespace.etcd }} +{{- if .Values.addons.gpuOperator.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -37,12 +29,9 @@ spec: force: true remediation: retries: -1 - {{- $defaults := fromYaml (include "cozystack.defaultGpuOperatorValues" .) }} - {{- $overrides := deepCopy (default (dict) .Values.addons.gpuOperator.valuesOverride) }} - {{- $merged := mergeOverwrite (default (dict) $defaults) $overrides }} - {{- if $merged }} + {{- with .Values.addons.gpuOperator.valuesOverride }} values: - {{- toYaml $merged | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} dependsOn: diff --git a/packages/apps/kubernetes/templates/helmreleases/hami.yaml b/packages/apps/kubernetes/templates/helmreleases/hami.yaml deleted file mode 100644 index f1538c7c..00000000 --- a/packages/apps/kubernetes/templates/helmreleases/hami.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if and .Values.addons.hami.enabled .Values._namespace.etcd }} -{{- if not .Values.addons.gpuOperator.enabled }} -{{- fail "addons.hami requires addons.gpuOperator to be enabled" }} -{{- end }} -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-hami - labels: - cozystack.io/repository: system - cozystack.io/target-cluster-name: {{ .Release.Name }} - sharding.fluxcd.io/key: tenants -spec: - releaseName: hami - chartRef: - kind: ExternalArtifact - name: cozystack-kubernetes-application-kubevirt-kubernetes-hami - namespace: cozy-system - kubeConfig: - secretRef: - name: {{ .Release.Name }}-admin-kubeconfig - key: super-admin.svc - targetNamespace: cozy-hami - storageNamespace: cozy-hami - interval: 5m - timeout: 10m - install: - createNamespace: true - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - {{- with .Values.addons.hami.valuesOverride }} - values: - {{- 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 }}-gpu-operator - namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index 6e2183d3..5cafff90 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -20,7 +20,7 @@ ingress-nginx: node-role.kubernetes.io/ingress-nginx: "" {{- end }} -{{- if and .Values.addons.ingressNginx.enabled .Values._namespace.etcd }} +{{- if .Values.addons.ingressNginx.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml b/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml index 3e6f9660..3cc81a14 100644 --- a/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -37,4 +36,3 @@ spec: namespace: {{ .Release.Namespace }} - name: {{ .Release.Name }}-prometheus-operator-crds namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml index a811f7dd..ea84dec0 100644 --- a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml @@ -1,6 +1,6 @@ {{- $targetTenant := .Values._namespace.monitoring }} {{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml index 3038a058..600a7994 100644 --- a/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -32,4 +31,3 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/velero.yaml b/packages/apps/kubernetes/templates/helmreleases/velero.yaml index 781b9c49..ad236d53 100644 --- a/packages/apps/kubernetes/templates/helmreleases/velero.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/velero.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.velero.enabled .Values._namespace.etcd }} +{{- if .Values.addons.velero.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml index 55a5faac..a3b7a9b4 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index 74fb5a39..178df3e3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -24,7 +24,7 @@ vertical-pod-autoscaler: memory: 1600Mi {{- end }} -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml index 7302f8f5..99744277 100644 --- a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml b/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml index d50fd93c..025f01b7 100644 --- a/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -34,4 +33,3 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/kccm/manager.yaml b/packages/apps/kubernetes/templates/kccm/manager.yaml index bd9e2798..81426d4e 100644 --- a/packages/apps/kubernetes/templates/kccm/manager.yaml +++ b/packages/apps/kubernetes/templates/kccm/manager.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: apps/v1 kind: Deployment metadata: @@ -23,8 +22,6 @@ spec: - key: node-role.kubernetes.io/control-plane operator: Exists effect: "NoSchedule" - initContainers: - {{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }} containers: - name: kubevirt-cloud-controller-manager args: @@ -58,7 +55,5 @@ spec: name: cloud-config - secret: secretName: {{ .Release.Name }}-admin-kubeconfig - optional: true name: kubeconfig serviceAccountName: {{ .Release.Name }}-kccm -{{- end }} diff --git a/packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml b/packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml deleted file mode 100644 index 507e00af..00000000 --- a/packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml +++ /dev/null @@ -1,155 +0,0 @@ -suite: admin-kubeconfig wait guards - -release: - name: test - namespace: tenant-root - -values: - - values-ci.yaml - -tests: - - it: cluster-autoscaler mounts admin-kubeconfig as optional - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.secretName - value: test-admin-kubeconfig - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.optional - value: true - - - it: cluster-autoscaler waits for admin-kubeconfig via initContainer - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.initContainers[0].name - value: wait-for-kubeconfig - - contains: - path: spec.template.spec.initContainers[0].volumeMounts - content: - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true - - - it: kccm mounts admin-kubeconfig as optional - template: templates/kccm/manager.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.secretName - value: test-admin-kubeconfig - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.optional - value: true - - - it: kccm waits for admin-kubeconfig via initContainer - template: templates/kccm/manager.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.initContainers[0].name - value: wait-for-kubeconfig - - contains: - path: spec.template.spec.initContainers[0].volumeMounts - content: - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true - - - it: csi controller mounts admin-kubeconfig as optional - template: templates/csi/deploy.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.secretName - value: test-admin-kubeconfig - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.optional - value: true - - - it: csi controller waits for admin-kubeconfig via initContainer - template: templates/csi/deploy.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.initContainers[0].name - value: wait-for-kubeconfig - - contains: - path: spec.template.spec.initContainers[0].volumeMounts - content: - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true - - - it: wait-for-kubeconfig defaults to bundled busybox digest pin - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - matchRegex: - path: spec.template.spec.initContainers[0].image - pattern: '^docker\.io/library/busybox:[^@]+@sha256:[0-9a-f]{64}$' - - - it: wait-for-kubeconfig honours images.waitForKubeconfig override - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - set: - images: - waitForKubeconfig: "registry.example.test/library/busybox:1.37.0@sha256:0000000000000000000000000000000000000000000000000000000000000000" - asserts: - - equal: - path: spec.template.spec.initContainers[0].image - value: "registry.example.test/library/busybox:1.37.0@sha256:0000000000000000000000000000000000000000000000000000000000000000" - - - it: cluster.yaml renders and wires dataStoreName when tenant has etcd - template: templates/cluster.yaml - documentSelector: - path: kind - value: KamajiControlPlane - asserts: - - equal: - path: spec.dataStoreName - value: tenant-root - - - it: cluster.yaml skips Cluster resources when tenant has no etcd DataStore - # Must NOT fail rendering - the parent Tenant chart populates - # _namespace.etcd asynchronously, so rendering failures here would cause - # flux install remediation on every cold bootstrap. Instead, emit only a - # ConfigMap status beacon so the HelmRelease reports Ready while flux - # retries on its interval until the DataStore appears. - template: templates/cluster.yaml - set: - _namespace: - etcd: "" - monitoring: "" - ingress: "" - seaweedfs: "" - host: "" - asserts: - - hasDocuments: - count: 1 - - isKind: - of: ConfigMap - - equal: - path: metadata.name - value: test-awaiting-etcd - - equal: - path: data.status - value: awaiting-etcd diff --git a/packages/apps/kubernetes/tests/gpu_operator_hami_test.yaml b/packages/apps/kubernetes/tests/gpu_operator_hami_test.yaml deleted file mode 100644 index 44528470..00000000 --- a/packages/apps/kubernetes/tests/gpu_operator_hami_test.yaml +++ /dev/null @@ -1,99 +0,0 @@ -suite: GPU Operator HelmRelease HAMi integration tests -templates: - - templates/helmreleases/gpu-operator.yaml -values: - - values-ci.yaml -tests: - - it: should disable devicePlugin when hami is enabled - set: - addons: - gpuOperator: - enabled: true - valuesOverride: {} - hami: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: false - - - it: should not have values when hami is disabled and no overrides - set: - addons: - gpuOperator: - enabled: true - valuesOverride: {} - hami: - enabled: false - valuesOverride: {} - asserts: - - notExists: - path: spec.values - - - it: should apply hami defaults when valuesOverride key is omitted - set: - addons: - gpuOperator: - enabled: true - hami: - enabled: true - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: false - - - it: should allow user overrides to merge with hami defaults - set: - addons: - gpuOperator: - enabled: true - valuesOverride: - gpu-operator: - driver: - enabled: false - hami: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: false - - equal: - path: spec.values.gpu-operator.driver.enabled - value: false - - - it: should let user explicitly override devicePlugin.enabled to true with hami enabled - set: - addons: - gpuOperator: - enabled: true - valuesOverride: - gpu-operator: - devicePlugin: - enabled: true - driver: - enabled: false - hami: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: true - - equal: - path: spec.values.gpu-operator.driver.enabled - value: false - - - it: should not render when gpuOperator is disabled - set: - addons: - gpuOperator: - enabled: false - valuesOverride: {} - hami: - enabled: false - valuesOverride: {} - asserts: - - hasDocuments: - count: 0 diff --git a/packages/apps/kubernetes/tests/hami_test.yaml b/packages/apps/kubernetes/tests/hami_test.yaml deleted file mode 100644 index 27f7c75b..00000000 --- a/packages/apps/kubernetes/tests/hami_test.yaml +++ /dev/null @@ -1,153 +0,0 @@ -suite: HAMi HelmRelease tests -templates: - - templates/helmreleases/hami.yaml -values: - - values-ci.yaml -tests: - - it: should not render when hami is disabled - set: - addons: - hami: - enabled: false - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - hasDocuments: - count: 0 - - - it: should render HelmRelease when hami is enabled - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - hasDocuments: - count: 1 - - isKind: - of: HelmRelease - - - it: should fail when gpuOperator is not enabled - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: false - valuesOverride: {} - asserts: - - failedTemplate: - errorMessage: "addons.hami requires addons.gpuOperator to be enabled" - - - it: should have correct metadata labels - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: metadata.labels["cozystack.io/repository"] - value: system - - equal: - path: metadata.labels["sharding.fluxcd.io/key"] - value: tenants - - - it: should use ExternalArtifact chartRef - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.chartRef.kind - value: ExternalArtifact - - equal: - path: spec.chartRef.namespace - value: cozy-system - - - it: should target cozy-hami namespace - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.targetNamespace - value: cozy-hami - - equal: - path: spec.storageNamespace - value: cozy-hami - - - it: should depend on gpu-operator and cilium - release: - name: test - namespace: test-ns - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - contains: - path: spec.dependsOn - content: - name: test-cilium - namespace: test-ns - - contains: - path: spec.dependsOn - content: - name: test-gpu-operator - namespace: test-ns - - - it: should not render spec.values when valuesOverride is empty - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - hasDocuments: - count: 1 - - notExists: - path: spec.values - - - it: should pass through valuesOverride - set: - addons: - hami: - enabled: true - valuesOverride: - hami: - devicePlugin: - deviceSplitCount: 5 - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.hami.devicePlugin.deviceSplitCount - value: 5 diff --git a/packages/apps/kubernetes/tests/values-ci-no-etcd.yaml b/packages/apps/kubernetes/tests/values-ci-no-etcd.yaml deleted file mode 100644 index c7c8196f..00000000 --- a/packages/apps/kubernetes/tests/values-ci-no-etcd.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_namespace: - etcd: "" - monitoring: "" - ingress: "" - seaweedfs: "" - host: "" -_cluster: - cluster-domain: cozy.local -nodeGroups: null diff --git a/packages/apps/kubernetes/tests/values-ci.yaml b/packages/apps/kubernetes/tests/values-ci.yaml deleted file mode 100644 index 13365e8c..00000000 --- a/packages/apps/kubernetes/tests/values-ci.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_namespace: - etcd: tenant-root - monitoring: "" - ingress: "" - seaweedfs: "" - host: "" -_cluster: - cluster-domain: cozy.local -nodeGroups: null diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index a43deaec..1beeff9c 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -149,7 +149,6 @@ "fluxcd", "gatewayAPI", "gpuOperator", - "hami", "ingressNginx", "monitoringAgents", "velero", @@ -269,28 +268,6 @@ } } }, - "hami": { - "description": "HAMi GPU virtualization middleware.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "valuesOverride" - ], - "properties": { - "enabled": { - "description": "Enable HAMi (requires GPU Operator).", - "type": "boolean", - "default": false - }, - "valuesOverride": { - "description": "Custom Helm values overrides.", - "type": "object", - "default": {}, - "x-kubernetes-preserve-unknown-fields": true - } - } - }, "ingressNginx": { "description": "Ingress-NGINX controller.", "type": "object", @@ -653,18 +630,6 @@ } } } - }, - "images": { - "description": "Optional image overrides for air-gapped or rate-limited registries.", - "type": "object", - "default": {}, - "properties": { - "waitForKubeconfig": { - "description": "Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag.", - "type": "string", - "default": "" - } - } } } } diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index d609476c..a67b5d69 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -94,10 +94,6 @@ host: "" ## @field {bool} enabled - Enable FluxCD. ## @field {object} valuesOverride - Custom Helm values overrides. -## @typedef {struct} HAMiAddon - HAMi GPU virtualization middleware. -## @field {bool} enabled - Enable HAMi (requires GPU Operator). -## @field {object} valuesOverride - Custom Helm values overrides. - ## @typedef {struct} MonitoringAgentsAddon - Monitoring agents (Fluent Bit, VMAgents). ## @field {bool} enabled - Enable monitoring agents. ## @field {object} valuesOverride - Custom Helm values overrides. @@ -118,7 +114,6 @@ host: "" ## @field {GatewayAPIAddon} gatewayAPI - Gateway API addon. ## @field {IngressNginxAddon} ingressNginx - Ingress-NGINX controller. ## @field {GPUOperatorAddon} gpuOperator - NVIDIA GPU Operator. -## @field {HAMiAddon} hami - HAMi GPU virtualization middleware. ## @field {FluxCDAddon} fluxcd - FluxCD GitOps operator. ## @field {MonitoringAgentsAddon} monitoringAgents - Monitoring agents. ## @field {VerticalPodAutoscalerAddon} verticalPodAutoscaler - Vertical Pod Autoscaler. @@ -142,9 +137,6 @@ addons: gpuOperator: enabled: false valuesOverride: {} - hami: - enabled: false - valuesOverride: {} fluxcd: enabled: false valuesOverride: {} @@ -205,10 +197,3 @@ controlPlane: server: resources: {} resourcesPreset: "micro" - -## @typedef {struct} Images - Optional image overrides for chart-internal helpers. -## @field {string} [waitForKubeconfig] - Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag. - -## @param {Images} images - Optional image overrides for air-gapped or rate-limited registries. -images: - waitForKubeconfig: "" diff --git a/packages/apps/mariadb/images/mariadb-backup.tag b/packages/apps/mariadb/images/mariadb-backup.tag index 6c830892..1e381661 100644 --- a/packages/apps/mariadb/images/mariadb-backup.tag +++ b/packages/apps/mariadb/images/mariadb-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/mariadb-backup:0.0.0@sha256:3841eb171416711977dea0cf8cd45d32344caac9727af760c37d5e1dd41ee4bb +ghcr.io/cozystack/cozystack/mariadb-backup:0.0.0@sha256:0ddbbec0568dcb9fbc317cd9cc654e826dbe88ba3f184fa9b6b58aacb93b4570 diff --git a/packages/apps/postgres/README.md b/packages/apps/postgres/README.md index 4cda7284..5a550f7a 100644 --- a/packages/apps/postgres/README.md +++ b/packages/apps/postgres/README.md @@ -133,13 +133,12 @@ See: ### Bootstrap (recovery) parameters -| Name | Description | Type | Value | -| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -| `bootstrap` | Bootstrap configuration. | `object` | `{}` | -| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` | -| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` | -| `bootstrap.oldName` | Previous cluster name before deletion. | `string` | `""` | -| `bootstrap.serverName` | Barman server name (S3 path prefix) used by the original cluster when writing backups. Set this only when the original cluster had an explicit barmanObjectStore.serverName that differed from its Kubernetes resource name. | `string` | `""` | +| Name | Description | Type | Value | +| ------------------------ | ------------------------------------------------------------------- | -------- | ------- | +| `bootstrap` | Bootstrap configuration. | `object` | `{}` | +| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` | +| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` | +| `bootstrap.oldName` | Previous cluster name before deletion. | `string` | `""` | ## Parameter examples and reference diff --git a/packages/apps/postgres/templates/db.yaml b/packages/apps/postgres/templates/db.yaml index 2cdaec1d..5c40b2c7 100644 --- a/packages/apps/postgres/templates/db.yaml +++ b/packages/apps/postgres/templates/db.yaml @@ -32,9 +32,6 @@ spec: - name: {{ .Values.bootstrap.oldName }} barmanObjectStore: destinationPath: {{ .Values.backup.destinationPath }} - {{- if .Values.bootstrap.serverName }} - serverName: {{ .Values.bootstrap.serverName }} - {{- end }} endpointURL: {{ .Values.backup.endpointURL }} s3Credentials: accessKeyId: diff --git a/packages/apps/postgres/values.schema.json b/packages/apps/postgres/values.schema.json index 98e29822..b2a4aeba 100644 --- a/packages/apps/postgres/values.schema.json +++ b/packages/apps/postgres/values.schema.json @@ -254,11 +254,6 @@ "description": "Timestamp (RFC3339) for point-in-time recovery; empty means latest.", "type": "string", "default": "" - }, - "serverName": { - "description": "Barman server name (S3 path prefix) used by the original cluster when writing backups. Set this only when the original cluster had an explicit barmanObjectStore.serverName that differed from its Kubernetes resource name.", - "type": "string", - "default": "" } } } diff --git a/packages/apps/postgres/values.yaml b/packages/apps/postgres/values.yaml index 2ceaa9cf..b8f07f63 100644 --- a/packages/apps/postgres/values.yaml +++ b/packages/apps/postgres/values.yaml @@ -154,7 +154,6 @@ backup: ## @field {bool} enabled - Whether to restore from a backup. ## @field {string} [recoveryTime] - Timestamp (RFC3339) for point-in-time recovery; empty means latest. ## @field {string} oldName - Previous cluster name before deletion. -## @field {string} [serverName] - Barman server name (S3 path prefix) used by the original cluster when writing backups. Set this only when the original cluster had an explicit barmanObjectStore.serverName that differed from its Kubernetes resource name. ## @param {Bootstrap} bootstrap - Bootstrap configuration. bootstrap: @@ -162,4 +161,3 @@ bootstrap: # example: 2020-11-26 15:22:00.00000+00 recoveryTime: "" oldName: "" - serverName: "" diff --git a/packages/apps/tenant/Makefile b/packages/apps/tenant/Makefile index 2f51d836..3fe3810d 100644 --- a/packages/apps/tenant/Makefile +++ b/packages/apps/tenant/Makefile @@ -3,6 +3,3 @@ include ../../../hack/package.mk generate: cozyvalues-gen -m 'tenant' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/tenant/types.go ../../../hack/update-crd.sh - -test: - helm unittest . diff --git a/packages/apps/tenant/templates/cilium-lb-pool.yaml b/packages/apps/tenant/templates/cilium-lb-pool.yaml deleted file mode 100644 index 63dbcaca..00000000 --- a/packages/apps/tenant/templates/cilium-lb-pool.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- $exposeMode := (index .Values._cluster "expose-mode") | default "externalIPs" }} -{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} -{{- $exposeIPs := (index .Values._cluster "expose-external-ips") | default "" | nospace }} -{{- $ipsList := list }} -{{- range splitList "," $exposeIPs }} - {{- $ip := . | trim }} - {{- if $ip }} - {{- $ipsList = append $ipsList $ip }} - {{- end }} -{{- end }} -{{- $isPublishingIngressLB := and - (eq $exposeMode "loadBalancer") - (eq $exposeIngress .Release.Namespace) - .Values.ingress }} -{{- if and $isPublishingIngressLB $ipsList }} -apiVersion: cilium.io/v2 -kind: CiliumLoadBalancerIPPool -metadata: - name: {{ trimPrefix "tenant-" .Release.Namespace }}-exposure -spec: - blocks: - {{- range $ipsList }} - - cidr: {{ . }}{{ if not (contains "/" .) }}/{{ if contains ":" . }}128{{ else }}32{{ end }}{{ end }} - {{- end }} - serviceSelector: - matchLabels: - "io.kubernetes.service.namespace": {{ .Release.Namespace | quote }} -{{- end }} diff --git a/packages/apps/tenant/tests/exposure_test.yaml b/packages/apps/tenant/tests/exposure_test.yaml deleted file mode 100644 index e86fab5b..00000000 --- a/packages/apps/tenant/tests/exposure_test.yaml +++ /dev/null @@ -1,141 +0,0 @@ -suite: tenant CiliumLoadBalancerIPPool rendering for publishing.exposure=loadBalancer -templates: - - templates/cilium-lb-pool.yaml - -release: - name: tenant-root - namespace: tenant-root - -tests: - - it: default exposure (externalIPs) renders no pool - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - asserts: - - hasDocuments: - count: 0 - - - it: loadBalancer mode in publishing tenant with ingress=true renders v2 pool with namespace-only selector - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 1 - - equal: - path: apiVersion - value: cilium.io/v2 - - equal: - path: kind - value: CiliumLoadBalancerIPPool - - equal: - path: metadata.name - value: root-exposure - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 192.0.2.11/32 - - equal: - path: spec.serviceSelector.matchLabels["io.kubernetes.service.namespace"] - value: tenant-root - - notExists: - path: spec.serviceSelector.matchLabels["app.kubernetes.io/name"] - - - it: loadBalancer mode with IPv6 emits /128 CIDR - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "2001:db8::1" - expose-mode: loadBalancer - asserts: - - equal: - path: spec.blocks - value: - - cidr: 2001:db8::1/128 - - - it: loadBalancer mode with mixed IPv4 and IPv6 emits correct CIDR per family - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,2001:db8::1" - expose-mode: loadBalancer - asserts: - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 2001:db8::1/128 - - - it: loadBalancer mode accepts pre-CIDR input without double-suffixing - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10/32,2001:db8::1/128" - expose-mode: loadBalancer - asserts: - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 2001:db8::1/128 - - - it: loadBalancer mode filters out empty entries from externalIPs (trailing, leading, repeated commas) - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,,192.0.2.11," - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 1 - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 192.0.2.11/32 - - - it: loadBalancer mode with ingress=false in publishing tenant renders no pool - set: - ingress: false - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 0 - - - it: loadBalancer mode in a non-publishing tenant renders no pool - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadBalancer - release: - name: tenant-u1 - namespace: tenant-u1 - asserts: - - hasDocuments: - count: 0 - - - it: loadBalancer mode in publishing tenant with empty externalIPs renders no pool - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "" - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 0 diff --git a/packages/apps/vm-instance/README.md b/packages/apps/vm-instance/README.md index 9d6a52b2..a2b6603e 100644 --- a/packages/apps/vm-instance/README.md +++ b/packages/apps/vm-instance/README.md @@ -36,32 +36,31 @@ virtctl ssh @ ### Common parameters -| Name | Description | Type | Value | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ----------- | -| `external` | Enable external access from outside the cluster. | `bool` | `false` | -| `externalMethod` | Method to pass through traffic to the VM. | `string` | `PortList` | -| `externalPorts` | Ports to forward from outside the cluster. | `[]int` | `[22]` | -| `externalAllowICMP` | Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect. | `bool` | `true` | -| `runStrategy` | Requested running state of the VirtualMachineInstance | `string` | `Always` | -| `instanceType` | Virtual Machine instance type. | `string` | `u1.medium` | -| `instanceProfile` | Virtual Machine preferences profile. | `string` | `ubuntu` | -| `disks` | List of disks to attach. | `[]object` | `[]` | -| `disks[i].name` | Disk name. | `string` | `""` | -| `disks[i].bus` | Disk bus type (e.g. "sata"). | `string` | `""` | -| `networks` | Networks to attach the VM to. | `[]object` | `[]` | -| `networks[i].name` | Network attachment name. | `string` | `""` | -| `subnets` | Deprecated: use networks instead. | `[]object` | `[]` | -| `subnets[i].name` | Network attachment name. | `string` | `""` | -| `gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` | -| `gpus[i].name` | The name of the GPU resource to attach. | `string` | `""` | -| `cpuModel` | Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map | `string` | `""` | -| `resources` | Resource configuration for the virtual machine. | `object` | `{}` | -| `resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `resources.sockets` | Number of CPU sockets (vCPU topology). | `quantity` | `""` | -| `sshKeys` | List of SSH public keys for authentication. | `[]string` | `[]` | -| `cloudInit` | Cloud-init user data. | `string` | `""` | -| `cloudInitSeed` | Seed string to generate SMBIOS UUID for the VM. | `string` | `""` | +| Name | Description | Type | Value | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------- | ----------- | +| `external` | Enable external access from outside the cluster. | `bool` | `false` | +| `externalMethod` | Method to pass through traffic to the VM. | `string` | `PortList` | +| `externalPorts` | Ports to forward from outside the cluster. | `[]int` | `[22]` | +| `runStrategy` | Requested running state of the VirtualMachineInstance | `string` | `Always` | +| `instanceType` | Virtual Machine instance type. | `string` | `u1.medium` | +| `instanceProfile` | Virtual Machine preferences profile. | `string` | `ubuntu` | +| `disks` | List of disks to attach. | `[]object` | `[]` | +| `disks[i].name` | Disk name. | `string` | `""` | +| `disks[i].bus` | Disk bus type (e.g. "sata"). | `string` | `""` | +| `networks` | Networks to attach the VM to. | `[]object` | `[]` | +| `networks[i].name` | Network attachment name. | `string` | `""` | +| `subnets` | Deprecated: use networks instead. | `[]object` | `[]` | +| `subnets[i].name` | Network attachment name. | `string` | `""` | +| `gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` | +| `gpus[i].name` | The name of the GPU resource to attach. | `string` | `""` | +| `cpuModel` | Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map | `string` | `""` | +| `resources` | Resource configuration for the virtual machine. | `object` | `{}` | +| `resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `resources.sockets` | Number of CPU sockets (vCPU topology). | `quantity` | `""` | +| `sshKeys` | List of SSH public keys for authentication. | `[]string` | `[]` | +| `cloudInit` | Cloud-init user data. | `string` | `""` | +| `cloudInitSeed` | Seed string to generate SMBIOS UUID for the VM. | `string` | `""` | ## U Series diff --git a/packages/apps/vm-instance/templates/service.yaml b/packages/apps/vm-instance/templates/service.yaml index cfeffa81..b7e3a420 100644 --- a/packages/apps/vm-instance/templates/service.yaml +++ b/packages/apps/vm-instance/templates/service.yaml @@ -9,10 +9,7 @@ metadata: {{- if .Values.external }} service.kubernetes.io/service-proxy-name: "cozy-proxy" annotations: - networking.cozystack.io/wholeIP: {{ ternary "true" "false" (eq .Values.externalMethod "WholeIP") | quote }} - {{- if eq .Values.externalMethod "PortList" }} - networking.cozystack.io/allowICMP: {{ ternary "true" "false" (ne .Values.externalAllowICMP false) | quote }} - {{- end }} + networking.cozystack.io/wholeIP: "true" {{- end }} spec: type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }} diff --git a/packages/apps/vm-instance/values.schema.json b/packages/apps/vm-instance/values.schema.json index 01bd30a9..34f7f634 100644 --- a/packages/apps/vm-instance/values.schema.json +++ b/packages/apps/vm-instance/values.schema.json @@ -26,11 +26,6 @@ "type": "integer" } }, - "externalAllowICMP": { - "description": "Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect.", - "type": "boolean", - "default": true - }, "runStrategy": { "description": "Requested running state of the VirtualMachineInstance", "type": "string", diff --git a/packages/apps/vm-instance/values.yaml b/packages/apps/vm-instance/values.yaml index 92e399c2..f07b75d3 100644 --- a/packages/apps/vm-instance/values.yaml +++ b/packages/apps/vm-instance/values.yaml @@ -31,9 +31,6 @@ externalMethod: PortList externalPorts: - 22 -## @param {bool} externalAllowICMP - Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect. -externalAllowICMP: true - ## @enum {string} RunStrategy - Requested running state of the VirtualMachineInstance ## @value Always - VMI should always be running ## @value Halted - VMI should never be running diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index eef691ea..f0a363e1 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,9 +1,9 @@ cozystackOperator: # Deployment variant: talos, generic, hosted variant: talos - image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.3.0@sha256:62574f12486bb40c901cf5ed484cca264405ce5810196d86555cbb27cce1ba48 + image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.3.0-rc.1@sha256:d833abf3eac990732440d7d04e2df62ef9cd46704e0637e63e86983132c6d958 platformSourceUrl: 'oci://ghcr.io/cozystack/cozystack/cozystack-packages' - platformSourceRef: 'digest=sha256:a0b9ef938446b3132d3d22ad2262beb1027c48c9037b6c2346fdc2f19acd3036' + platformSourceRef: 'digest=sha256:db28afd18635f6295342f58cd90ac7015c8f59d46ae9704fffeb2c654c3c8a0e' # Generic variant configuration (only used when cozystackOperator.variant=generic) cozystack: # Kubernetes API server host (IP only, no protocol/port) diff --git a/packages/core/platform/sources/hami.yaml b/packages/core/platform/sources/hami.yaml deleted file mode 100644 index 0184e405..00000000 --- a/packages/core/platform/sources/hami.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.hami -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.gpu-operator - components: - - name: hami - path: system/hami - valuesFiles: - - values.yaml - install: - privileged: true - namespace: cozy-hami - releaseName: hami diff --git a/packages/core/platform/sources/kubernetes-application.yaml b/packages/core/platform/sources/kubernetes-application.yaml index 088383ad..9787cb19 100644 --- a/packages/core/platform/sources/kubernetes-application.yaml +++ b/packages/core/platform/sources/kubernetes-application.yaml @@ -52,8 +52,6 @@ spec: path: system/cilium - name: kubernetes-gpu-operator path: system/gpu-operator - - name: kubernetes-hami - path: system/hami - name: kubernetes-vertical-pod-autoscaler path: system/vertical-pod-autoscaler - name: kubernetes-prometheus-operator-crds diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index 6e1ae25a..7ee0de52 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -30,7 +30,6 @@ stringData: expose-services: {{ .Values.publishing.exposedServices | join "," | quote }} expose-ingress: {{ .Values.publishing.ingressName | quote }} expose-external-ips: {{ .Values.publishing.externalIPs | join "," | quote }} - expose-mode: {{ .Values.publishing.exposure | default "externalIPs" | quote }} cluster-domain: {{ .Values.networking.clusterDomain | quote }} api-server-endpoint: {{ .Values.publishing.apiServerEndpoint | quote }} {{- with .Values.branding }} diff --git a/packages/core/platform/templates/bundles/iaas.yaml b/packages/core/platform/templates/bundles/iaas.yaml index 66ec98b2..ced0a322 100644 --- a/packages/core/platform/templates/bundles/iaas.yaml +++ b/packages/core/platform/templates/bundles/iaas.yaml @@ -10,7 +10,6 @@ {{include "cozystack.platform.package.default" (list "cozystack.kubevirt-cdi" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.vm-default-images" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.gpu-operator" $) }} -{{include "cozystack.platform.package.optional.default" (list "cozystack.hami" $) }} {{include "cozystack.platform.package.default" (list "cozystack.kamaji" $) }} {{include "cozystack.platform.package.default" (list "cozystack.capi-operator" $) }} {{include "cozystack.platform.package.default" (list "cozystack.capi-provider-bootstrap-kubeadm" $) }} diff --git a/packages/core/platform/templates/bundles/system.yaml b/packages/core/platform/templates/bundles/system.yaml index 6c587c82..43ea7266 100644 --- a/packages/core/platform/templates/bundles/system.yaml +++ b/packages/core/platform/templates/bundles/system.yaml @@ -105,6 +105,9 @@ {{- /* cozystack-api DaemonSet */ -}} {{- $apiValues := dict "cozystackAPI" (dict "nodeSelector" $genericNodeSelector) -}} {{- $_ := set $cozystackEngineComponents "cozystack-api" (dict "values" $apiValues) -}} +{{- /* lineage-controller-webhook DaemonSet */ -}} +{{- $lineageValues := dict "lineageControllerWebhook" (dict "nodeSelector" $genericNodeSelector) -}} +{{- $_ := set $cozystackEngineComponents "lineage-controller-webhook" (dict "values" $lineageValues) -}} {{- end -}} {{- if .Values.authentication.oidc.enabled }} {{include "cozystack.platform.package" (list "cozystack.cozystack-engine" "oidc" $ $cozystackEngineComponents) }} diff --git a/packages/core/platform/values.yaml b/packages/core/platform/values.yaml index 605e23bc..1d9a51c5 100644 --- a/packages/core/platform/values.yaml +++ b/packages/core/platform/values.yaml @@ -5,7 +5,7 @@ sourceRef: path: / migrations: enabled: false - image: ghcr.io/cozystack/cozystack/platform-migrations:v1.3.0@sha256:555e4b76421361805a84bc9088b01b23a9c4a9430bd8ebd2db82ef9677d7008c + image: ghcr.io/cozystack/cozystack/platform-migrations:v1.3.0-rc.1@sha256:555e4b76421361805a84bc9088b01b23a9c4a9430bd8ebd2db82ef9677d7008c targetVersion: 39 # Bundle deployment configuration bundles: @@ -45,41 +45,6 @@ publishing: - cdi-uploadproxy apiServerEndpoint: "" # example: "https://api.example.org" externalIPs: [] - # Exposure mode for the ingress-nginx Service. When "externalIPs" (current - # default) is selected, the Service is created as ClusterIP with - # Service.spec.externalIPs set from publishing.externalIPs. When - # "loadBalancer" is selected, the Service is type: LoadBalancer and a - # CiliumLoadBalancerIPPool makes those same addresses allocatable via LB IPAM. - # - # Service.spec.externalIPs is deprecated upstream in Kubernetes v1.36 - # (KEP-5707). The AllowServiceExternalIPs feature gate is expected to default - # to false around v1.40 and the implementation removed around v1.43 — switch - # to "loadBalancer" before upgrading past v1.40. - # - # Caveats for the "loadBalancer" mode: - # - publishing.externalIPs must contain at least one non-empty address, - # otherwise the chart render fails with an explicit error (a LoadBalancer - # Service without a pool would sit in forever). - # - The ingress-nginx Service is created with externalTrafficPolicy: Local - # to preserve the client source IP. Traffic arriving on a node that does - # not host an ingress-nginx pod is dropped, so the external IP must be - # routed to a node that runs the ingress pod (floating IP / keepalived / - # upstream router / podAntiAffinity). - # - Cilium does NOT announce the IP on its own unless L2 announcements or - # BGP are enabled in the Cilium values (disabled by default in Cozystack). - # This mode assumes the operator already routes the externalIPs to a - # cluster node; enabling announcements is out of scope for this setting. - # - Switching this value on a running cluster causes the ingress-nginx - # Service to be recreated (the HelmRelease has upgrade.force: true and - # the Service kind changes between ClusterIP and LoadBalancer). Expect a - # brief interruption of ingress traffic during the flip. - # - # Scope: this setting only controls the ingress-nginx Service. Other - # cozystack components that currently write Service.spec.externalIPs directly - # (e.g. the vpn app at packages/apps/vpn/templates/service.yaml) are NOT - # migrated by flipping this value and must be addressed separately before - # the AllowServiceExternalIPs feature gate flips to off in ~v1.40. - exposure: externalIPs # "externalIPs" or "loadBalancer" certificates: solver: http01 # "http01" or "dns01" issuerName: letsencrypt-prod diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index 9d4bdd10..fe76a451 100644 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.3.0@sha256:0367a03b981df2a3ea13f411d4cb7869c2bf2c89c07d3d5c8971b9a28921ccef + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.3.0-rc.1@sha256:0367a03b981df2a3ea13f411d4cb7869c2bf2c89c07d3d5c8971b9a28921ccef diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index f51c7675..214064c3 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v1.3.0@sha256:85b8e04bf6f0690612dd63e80475df269f4a436d16680f8a40f2860cf16e2f74 +ghcr.io/cozystack/cozystack/matchbox:v1.3.0-rc.1@sha256:27959a7e36fb5594049cf88e7b196e661c6ad161dc89330b2c0ef543d1d48367 diff --git a/packages/extra/bootbox/templates/matchbox/ingress.yaml b/packages/extra/bootbox/templates/matchbox/ingress.yaml index 5eef3489..4262cd10 100644 --- a/packages/extra/bootbox/templates/matchbox/ingress.yaml +++ b/packages/extra/bootbox/templates/matchbox/ingress.yaml @@ -10,7 +10,7 @@ metadata: app: bootbox annotations: {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} {{- if .Values.whitelistHTTP }} diff --git a/packages/extra/etcd/Makefile b/packages/extra/etcd/Makefile index 2b3ed61e..f37d6e1e 100644 --- a/packages/extra/etcd/Makefile +++ b/packages/extra/etcd/Makefile @@ -5,6 +5,3 @@ include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh - -test: - helm unittest . diff --git a/packages/extra/etcd/templates/hook/job.yaml b/packages/extra/etcd/templates/hook/job.yaml new file mode 100644 index 00000000..3bf2f84b --- /dev/null +++ b/packages/extra/etcd/templates/hook/job.yaml @@ -0,0 +1,39 @@ +{{- $shouldUpdateCerts := true }} +{{- $configMap := lookup "v1" "ConfigMap" .Release.Namespace "etcd-deployed-version" }} +{{- if $configMap }} + {{- $deployedVersion := index $configMap "data" "version" }} + {{- if $deployedVersion | semverCompare ">= 2.6.1" }} + {{- $shouldUpdateCerts = false }} + {{- end }} +{{- end }} + +{{- if $shouldUpdateCerts }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: etcd-hook + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +spec: + template: + metadata: + labels: + policy.cozystack.io/allow-to-apiserver: "true" + spec: + serviceAccountName: etcd-hook + containers: + - name: kubectl + image: docker.io/alpine/k8s:1.33.4 + command: + - sh + args: + - -exc + - |- + kubectl --namespace={{ .Release.Namespace }} delete secrets etcd-ca-tls etcd-peer-ca-tls + sleep 10 + kubectl --namespace={{ .Release.Namespace }} delete secrets etcd-client-tls etcd-peer-tls etcd-server-tls + kubectl --namespace={{ .Release.Namespace }} delete pods --selector=app.kubernetes.io/instance=etcd,app.kubernetes.io/managed-by=etcd-operator,app.kubernetes.io/name=etcd,cozystack.io/service=etcd + restartPolicy: Never +{{- end }} diff --git a/packages/extra/etcd/templates/hook/role.yaml b/packages/extra/etcd/templates/hook/role.yaml new file mode 100644 index 00000000..327eeadb --- /dev/null +++ b/packages/extra/etcd/templates/hook/role.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + name: etcd-hook +rules: +- apiGroups: + - "" + resources: + - secrets + - pods + verbs: + - get + - list + - watch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch diff --git a/packages/extra/etcd/templates/hook/rolebinding.yaml b/packages/extra/etcd/templates/hook/rolebinding.yaml new file mode 100644 index 00000000..0ee0ffd1 --- /dev/null +++ b/packages/extra/etcd/templates/hook/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: etcd-hook + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: etcd-hook +subjects: + - kind: ServiceAccount + name: etcd-hook + namespace: {{ .Release.Namespace | quote }} diff --git a/packages/extra/etcd/templates/hook/serviceaccount.yaml b/packages/extra/etcd/templates/hook/serviceaccount.yaml new file mode 100644 index 00000000..552fb5fc --- /dev/null +++ b/packages/extra/etcd/templates/hook/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: etcd-hook + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded diff --git a/packages/extra/etcd/templates/version.yaml b/packages/extra/etcd/templates/version.yaml new file mode 100644 index 00000000..cc9375bb --- /dev/null +++ b/packages/extra/etcd/templates/version.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: etcd-deployed-version +data: + version: {{ .Chart.Version }} diff --git a/packages/extra/etcd/tests/no-post-upgrade-hook_test.yaml b/packages/extra/etcd/tests/no-post-upgrade-hook_test.yaml deleted file mode 100644 index 0e4f5aa3..00000000 --- a/packages/extra/etcd/tests/no-post-upgrade-hook_test.yaml +++ /dev/null @@ -1,34 +0,0 @@ -suite: etcd chart does not ship a destructive post-upgrade cert-regeneration hook - -release: - name: etcd - namespace: tenant-root - -templates: - - templates/check-release-name.yaml - - templates/dashboard-resourcemap.yaml - - templates/datastore.yaml - - templates/etcd-defrag.yaml - - templates/hook/job.yaml - - templates/podscrape.yaml - - templates/prometheus-rules.yaml - - templates/version.yaml - -tests: - - it: renders no Job named etcd-hook - documentSelector: - path: metadata.name - value: etcd-hook - skipEmptyTemplates: true - asserts: - - hasDocuments: - count: 0 - - - it: renders no ConfigMap named etcd-deployed-version - documentSelector: - path: metadata.name - value: etcd-deployed-version - skipEmptyTemplates: true - asserts: - - hasDocuments: - count: 0 diff --git a/packages/extra/ingress/Makefile b/packages/extra/ingress/Makefile index 65b53c03..958ce484 100644 --- a/packages/extra/ingress/Makefile +++ b/packages/extra/ingress/Makefile @@ -10,6 +10,3 @@ get-cloudflare-ips: generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh - -test: - helm unittest . diff --git a/packages/extra/ingress/README.md b/packages/extra/ingress/README.md index c541d8e9..0e786dfb 100644 --- a/packages/extra/ingress/README.md +++ b/packages/extra/ingress/README.md @@ -14,17 +14,3 @@ | `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | | `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `micro` | - -## Exposure mode - -The ingress Service type is driven by the cluster-wide `publishing.exposure` value in the platform chart, not by any key in this package. Two modes exist: - -- `externalIPs` (default) has three rendered shapes: - - Release namespace matches `publishing.ingressName` AND `publishing.externalIPs` is non-empty → Service is `ClusterIP` with `Service.spec.externalIPs` set from that list and `externalTrafficPolicy: Cluster`. - - Release namespace matches `publishing.ingressName` but `publishing.externalIPs` is empty → Service falls back to `type: LoadBalancer` with `externalTrafficPolicy: Local`. - - Release namespace does not match `publishing.ingressName` (non-root tenants) → Service is `type: LoadBalancer` with `externalTrafficPolicy: Local`. - `Service.spec.externalIPs` is deprecated upstream in Kubernetes v1.36 (KEP-5707); plan migration before v1.40. -- `loadBalancer` — Service is `type: LoadBalancer` with `externalTrafficPolicy: Local`, and a `CiliumLoadBalancerIPPool` makes the addresses in `publishing.externalIPs` allocatable via Cilium LB IPAM. Requires `publishing.externalIPs` to contain at least one non-empty address (render fails otherwise) and assumes the addresses are already routed to a cluster node (floating IP / upstream router). See the inline comment on `publishing.exposure` in the platform chart for full caveats, including the note that switching the value on a running cluster causes the ingress Service to be recreated. - -This setting only migrates ingress-nginx away from `Service.spec.externalIPs`. Other cozystack components that use the same deprecated field (e.g. the `vpn` app) must be migrated separately before Kubernetes v1.40 flips the `AllowServiceExternalIPs` feature gate off. - diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index 8e1f00fb..ca50d276 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -1,19 +1,5 @@ {{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} {{- $exposeExternalIPs := (index .Values._cluster "expose-external-ips") | default "" | nospace }} -{{- $exposeMode := (index .Values._cluster "expose-mode") | default "externalIPs" }} -{{- $exposeIPsList := list }} -{{- range splitList "," $exposeExternalIPs }} - {{- $ip := . | trim }} - {{- if $ip }} - {{- $exposeIPsList = append $exposeIPsList $ip }} - {{- end }} -{{- end }} -{{- if not (has $exposeMode (list "externalIPs" "loadBalancer")) }} -{{- fail (printf "unknown publishing.exposure mode %q: must be \"externalIPs\" or \"loadBalancer\"" $exposeMode) }} -{{- end }} -{{- if and (eq $exposeMode "loadBalancer") (eq $exposeIngress .Release.Namespace) (not $exposeIPsList) }} -{{- fail "publishing.exposure=loadBalancer requires publishing.externalIPs to contain at least one non-empty address: the CiliumLoadBalancerIPPool has nothing to advertise and the Service would stay in ." }} -{{- end }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -55,12 +41,9 @@ spec: enabled: false {{- end }} service: - {{- if and (eq $exposeIngress .Release.Namespace) (eq $exposeMode "loadBalancer") }} - type: LoadBalancer - externalTrafficPolicy: Local - {{- else if and (eq $exposeIngress .Release.Namespace) $exposeIPsList }} + {{- if and (eq $exposeIngress .Release.Namespace) $exposeExternalIPs }} externalIPs: - {{- toYaml $exposeIPsList | nindent 12 }} + {{- toYaml (splitList "," $exposeExternalIPs) | nindent 12 }} type: ClusterIP externalTrafficPolicy: Cluster {{- else }} diff --git a/packages/extra/ingress/tests/exposure_test.yaml b/packages/extra/ingress/tests/exposure_test.yaml deleted file mode 100644 index 1c76b3da..00000000 --- a/packages/extra/ingress/tests/exposure_test.yaml +++ /dev/null @@ -1,165 +0,0 @@ -suite: ingress exposure modes -templates: - - templates/nginx-ingress.yaml - -release: - name: ingress - namespace: tenant-root - -tests: - - it: default exposure (externalIPs) renders ClusterIP Service with spec.externalIPs - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: ClusterIP - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Cluster - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalIPs - value: - - 192.0.2.10 - - 192.0.2.11 - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.labels - - - it: legacy config without expose-mode falls back to externalIPs behavior - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: ClusterIP - - - it: externalIPs mode in a namespace other than publishing.ingressName renders LoadBalancer fallback without externalIPs - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - release: - namespace: tenant-other - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: LoadBalancer - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Local - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.externalIPs - - - it: loadBalancer mode renders LoadBalancer Service without externalIPs on the Service - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - expose-mode: loadBalancer - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: LoadBalancer - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Local - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.labels - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.externalIPs - - - it: loadBalancer mode without externalIPs fails chart render with explicit message - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "" - expose-mode: loadBalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "publishing.exposure=loadBalancer requires publishing.externalIPs to contain at least one non-empty address: the CiliumLoadBalancerIPPool has nothing to advertise and the Service would stay in ." - - - it: unknown exposure mode is rejected with a clear error (case-sensitive enum) - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: LoadBalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "unknown publishing.exposure mode \"LoadBalancer\": must be \"externalIPs\" or \"loadBalancer\"" - - - it: another typo in exposure mode also fails - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadbalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "unknown publishing.exposure mode \"loadbalancer\": must be \"externalIPs\" or \"loadBalancer\"" - - - it: loadBalancer mode in a namespace other than publishing.ingressName falls back to LoadBalancer Service without pool - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadBalancer - release: - namespace: tenant-other - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: LoadBalancer - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Local - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.labels - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.externalIPs - - - it: loadBalancer mode with only-empty externalIPs fails chart render (comma-only input) - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: ",," - expose-mode: loadBalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "publishing.exposure=loadBalancer requires publishing.externalIPs to contain at least one non-empty address: the CiliumLoadBalancerIPPool has nothing to advertise and the Service would stay in ." - - - it: externalIPs mode also filters out empty entries (trailing comma) - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10," - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalIPs - value: - - 192.0.2.10 diff --git a/packages/extra/seaweedfs/images/objectstorage-sidecar.tag b/packages/extra/seaweedfs/images/objectstorage-sidecar.tag index 9b413da5..6d85d153 100644 --- a/packages/extra/seaweedfs/images/objectstorage-sidecar.tag +++ b/packages/extra/seaweedfs/images/objectstorage-sidecar.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.3.0@sha256:5bcccbdb13979a16cee535eb5fbcdf0d87973689010a10b7b25e55c5be3edaa6 +ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.3.0-rc.1@sha256:5bcccbdb13979a16cee535eb5fbcdf0d87973689010a10b7b25e55c5be3edaa6 diff --git a/packages/extra/seaweedfs/templates/seaweedfs.yaml b/packages/extra/seaweedfs/templates/seaweedfs.yaml index 2f5720ca..42441b26 100644 --- a/packages/extra/seaweedfs/templates/seaweedfs.yaml +++ b/packages/extra/seaweedfs/templates/seaweedfs.yaml @@ -243,7 +243,7 @@ spec: nginx.ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} tls: diff --git a/packages/system/backup-controller/values.yaml b/packages/system/backup-controller/values.yaml index 34e033ce..3c8834dc 100644 --- a/packages/system/backup-controller/values.yaml +++ b/packages/system/backup-controller/values.yaml @@ -1,5 +1,5 @@ backupController: - image: "ghcr.io/cozystack/cozystack/backup-controller:v1.3.0@sha256:e1a083dc92f26dfef004f47c1cd20a6357174aad835004f58e751c494b76649a" + image: "ghcr.io/cozystack/cozystack/backup-controller:v1.3.0-rc.1@sha256:9d1727b80b436387141b43fd8c12ec36d75220e1d6014ebb58e2e8df3caba5e8" replicas: 2 debug: false metrics: diff --git a/packages/system/backupstrategy-controller/templates/rbac-bind.yaml b/packages/system/backupstrategy-controller/templates/rbac-bind.yaml index 03578cc2..4ecacce0 100644 --- a/packages/system/backupstrategy-controller/templates/rbac-bind.yaml +++ b/packages/system/backupstrategy-controller/templates/rbac-bind.yaml @@ -10,3 +10,17 @@ subjects: - kind: ServiceAccount name: backupstrategy-controller namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: backups.cozystack.io:strategy-controller:velero-configmaps + namespace: cozy-velero +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: backups.cozystack.io:strategy-controller:velero-configmaps +subjects: +- kind: ServiceAccount + name: backupstrategy-controller + namespace: {{ .Release.Namespace }} diff --git a/packages/system/backupstrategy-controller/templates/rbac.yaml b/packages/system/backupstrategy-controller/templates/rbac.yaml index 634ea88b..bbdb74f8 100644 --- a/packages/system/backupstrategy-controller/templates/rbac.yaml +++ b/packages/system/backupstrategy-controller/templates/rbac.yaml @@ -27,9 +27,7 @@ rules: resources: ["pods"] verbs: ["get", "list", "watch"] # ConfigMaps: controller-runtime cache requires cluster-scoped list/watch; -# create/update/delete is scoped to cozy-velero via a Role shipped by the -# velero chart (packages/system/velero/templates/backupstrategy-controller-rbac.yaml) -# so it is only created when velero is installed. +# create/update/delete is scoped to cozy-velero via the Role below. - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"] @@ -80,3 +78,14 @@ rules: - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["get", "list", "watch", "create", "update", "patch"] +--- +# To create ResourceModifiers in ConfigMaps for Restore in Velero install namespace. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: backups.cozystack.io:strategy-controller:velero-configmaps + namespace: cozy-velero +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "delete", "deletecollection", "patch", "update"] diff --git a/packages/system/backupstrategy-controller/values.yaml b/packages/system/backupstrategy-controller/values.yaml index d6453124..326dd7c2 100644 --- a/packages/system/backupstrategy-controller/values.yaml +++ b/packages/system/backupstrategy-controller/values.yaml @@ -1,5 +1,5 @@ backupStrategyController: - image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.3.0@sha256:be0a9ec1f4307064b16388a24628aee46e06252738338add80b99ea1e04e62bf" + image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.3.0-rc.1@sha256:aebdf354e15bff73d4e12d3f6117494002e8a4e586d1c46450cd0a3da493fbb5" replicas: 2 debug: false metrics: diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 889db0af..30b082df 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:fb65e734bbdbdaef2238769cc2ecfb54dbddaf1e0952ad438a9b3e26b9dbb4b5 +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:cfffa1267ad72d138c6e9eed6fa282f4fa23698bef2180be98c0be39c073ec28 diff --git a/packages/system/bucket/templates/ingress.yaml b/packages/system/bucket/templates/ingress.yaml index b7ffaf8b..6e5028fc 100644 --- a/packages/system/bucket/templates/ingress.yaml +++ b/packages/system/bucket/templates/ingress.yaml @@ -12,7 +12,7 @@ metadata: nginx.ingress.kubernetes.io/proxy-read-timeout: "99999" nginx.ingress.kubernetes.io/proxy-send-timeout: "99999" {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} spec: diff --git a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml index 3b582082..442f1fb3 100644 --- a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml +++ b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml @@ -1,7 +1,6 @@ {{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} -apiVersion: cert-manager.io/v1 +apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod @@ -18,9 +17,9 @@ spec: name: cloudflare-api-token-secret key: api-token {{- else }} - http01: - ingress: - ingressClassName: {{ $exposeIngress }} + http01: + ingress: + class: nginx {{- end }} --- @@ -42,9 +41,9 @@ spec: name: cloudflare-api-token-secret key: api-token {{- else }} - http01: - ingress: - ingressClassName: {{ $exposeIngress }} + http01: + ingress: + class: nginx {{- end }} --- diff --git a/packages/system/cilium/charts/cilium/Chart.yaml b/packages/system/cilium/charts/cilium/Chart.yaml index 5fe2baed..0bb34451 100644 --- a/packages/system/cilium/charts/cilium/Chart.yaml +++ b/packages/system/cilium/charts/cilium/Chart.yaml @@ -76,7 +76,7 @@ annotations: Cilium Gateway Class Config\n description: |\n CiliumGatewayClassConfig defines a configuration for Gateway API GatewayClass.\n" apiVersion: v2 -appVersion: 1.19.3 +appVersion: 1.19.1 description: eBPF-based Networking, Security, and Observability home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg @@ -92,4 +92,4 @@ kubeVersion: '>= 1.21.0-0' name: cilium sources: - https://github.com/cilium/cilium -version: 1.19.3 +version: 1.19.1 diff --git a/packages/system/cilium/charts/cilium/README.md b/packages/system/cilium/charts/cilium/README.md index d7697c56..fe8aea3f 100644 --- a/packages/system/cilium/charts/cilium/README.md +++ b/packages/system/cilium/charts/cilium/README.md @@ -1,6 +1,6 @@ # cilium -![Version: 1.19.3](https://img.shields.io/badge/Version-1.19.3-informational?style=flat-square) ![AppVersion: 1.19.3](https://img.shields.io/badge/AppVersion-1.19.3-informational?style=flat-square) +![Version: 1.19.1](https://img.shields.io/badge/Version-1.19.1-informational?style=flat-square) ![AppVersion: 1.19.1](https://img.shields.io/badge/AppVersion-1.19.1-informational?style=flat-square) Cilium is open source software for providing and transparently securing network connectivity and loadbalancing between application workloads such as @@ -89,7 +89,7 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.install.agent.tolerations | list | `[{"effect":"NoSchedule","key":"node.kubernetes.io/not-ready"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","value":"true"},{"key":"CriticalAddonsOnly","operator":"Exists"}]` | SPIRE agent tolerations configuration By default it follows the same tolerations as the agent itself to allow the Cilium agent on this node to connect to SPIRE. ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | authentication.mutual.spire.install.enabled | bool | `true` | Enable SPIRE installation. This will only take effect only if authentication.mutual.spire.enabled is true | | authentication.mutual.spire.install.existingNamespace | bool | `false` | SPIRE namespace already exists. Set to true if Helm should not create, manage, and import the SPIRE namespace. | -| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.37.0","useDigest":true}` | init container image of SPIRE agent and server | +| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:b3255e7dfbcd10cb367af0d409747d511aeb66dfac98cf30e97e87e4207dd76f","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.37.0","useDigest":true}` | init container image of SPIRE agent and server | | authentication.mutual.spire.install.namespace | string | `"cilium-spire"` | SPIRE namespace to install into | | authentication.mutual.spire.install.server.affinity | object | `{}` | SPIRE server affinity configuration | | authentication.mutual.spire.install.server.annotations | object | `{}` | SPIRE server annotations | @@ -175,7 +175,7 @@ contributors across the globe, there is almost always someone available to help. | bpf.tproxy | bool | `false` | Configure the eBPF-based TPROXY (beta) to reduce reliance on iptables rules for implementing Layer 7 policy. Note this is incompatible with netkit (`bpf.datapathMode=netkit`, `bpf.datapathMode=netkit-l2`). | | bpf.vlanBypass | list | `[]` | Configure explicitly allowed VLAN id's for bpf logic bypass. [0] will allow all VLAN id's without any filtering. | | bpfClockProbe | bool | `false` | Enable BPF clock source probing for more efficient tick retrieval. | -| certgen | object | `{"affinity":{},"annotations":{"cronJob":{},"job":{}},"cronJob":{"failedJobsHistoryLimit":1,"successfulJobsHistoryLimit":3},"extraVolumeMounts":[],"extraVolumes":[],"generateCA":true,"image":{"digest":"sha256:f0c656830e856d26b24b0e144df1f8b327d3b46748d76a630514111fc365b697","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.4.1","useDigest":true},"nodeSelector":{},"podLabels":{},"priorityClassName":"","resources":{},"tolerations":[],"ttlSecondsAfterFinished":null}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | +| certgen | object | `{"affinity":{},"annotations":{"cronJob":{},"job":{}},"cronJob":{"failedJobsHistoryLimit":1,"successfulJobsHistoryLimit":3},"extraVolumeMounts":[],"extraVolumes":[],"generateCA":true,"image":{"digest":"sha256:19921f48ee7e2295ea4dca955878a6cd8d70e6d4219d08f688e866ece9d95d4d","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.3.2","useDigest":true},"nodeSelector":{},"podLabels":{},"priorityClassName":"","resources":{},"tolerations":[],"ttlSecondsAfterFinished":null}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | | certgen.affinity | object | `{}` | Affinity for certgen | | certgen.annotations | object | `{"cronJob":{},"job":{}}` | Annotations to be added to the hubble-certgen initial Job and CronJob | | certgen.cronJob.failedJobsHistoryLimit | int | `1` | The number of failed finished jobs to keep | @@ -214,7 +214,7 @@ contributors across the globe, there is almost always someone available to help. | clustermesh.apiserver.extraVolumeMounts | list | `[]` | Additional clustermesh-apiserver volumeMounts. | | clustermesh.apiserver.extraVolumes | list | `[]` | Additional clustermesh-apiserver volumes. | | clustermesh.apiserver.healthPort | int | `9880` | TCP port for the clustermesh-apiserver health API. | -| clustermesh.apiserver.image | object | `{"digest":"sha256:a8136a7615d6c6041d3aa6f2674d17beaec238170d669507ccc05328a778e2b7","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.19.3","useDigest":true}` | Clustermesh API server image. | +| clustermesh.apiserver.image | object | `{"digest":"sha256:56d6c3dc13b50126b80ecb571707a0ea97f6db694182b9d61efd386d04e5bb28","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.19.1","useDigest":true}` | Clustermesh API server image. | | clustermesh.apiserver.kvstoremesh.enabled | bool | `true` | Enable KVStoreMesh. KVStoreMesh caches the information retrieved from the remote clusters in the local etcd instance (deprecated - KVStoreMesh will always be enabled once the option is removed). | | clustermesh.apiserver.kvstoremesh.extraArgs | list | `[]` | Additional KVStoreMesh arguments. | | clustermesh.apiserver.kvstoremesh.extraEnv | list | `[]` | Additional KVStoreMesh environment variables. | @@ -340,10 +340,6 @@ contributors across the globe, there is almost always someone available to help. | cni.resources | object | `{"limits":{"cpu":1,"memory":"1Gi"},"requests":{"cpu":"100m","memory":"10Mi"}}` | Specifies the resources for the cni initContainer | | cni.uninstall | bool | `false` | Remove the CNI configuration and binary files on agent shutdown. Enable this if you're removing Cilium from the cluster. Disable this to prevent the CNI configuration file from being removed during agent upgrade, which can cause nodes to go unmanageable. | | commonLabels | object | `{}` | commonLabels allows users to add common labels for all Cilium resources. | -| configDriftDetection | object | `{"driftChecker":true,"enabled":true,"ignoredKeys":[]}` | Configuration for the ConfigMap drift detection feature. When enabled, the agent continuously watches the cilium-config ConfigMap and exposes a cilium_drift_checker_config_delta Prometheus metric reporting the number of keys that differ between the ConfigMap and the agent's active settings. A non-zero value indicates that the agent has not yet applied all current ConfigMap changes and needs to be restarted. | -| configDriftDetection.driftChecker | bool | `true` | Enable the drift checker which compares the DynamicConfig table against the agent's active settings and publishes the cilium_drift_checker_config_delta metric. | -| configDriftDetection.enabled | bool | `true` | Enable watching of the cilium-config ConfigMap and reflecting its contents into the agent's internal DynamicConfig table. | -| configDriftDetection.ignoredKeys | list | `[]` | List of config-map keys to ignore when computing the drift delta. | | connectivityProbeFrequencyRatio | float64 | `0.5` | Ratio of the connectivity probe frequency vs resource usage, a float in [0, 1]. 0 will give more frequent probing, 1 will give less frequent probing. Probing frequency is dynamically adjusted based on the cluster size. | | conntrackGCInterval | string | `"0s"` | Configure how frequently garbage collection should occur for the datapath connection tracking table. | | conntrackGCMaxInterval | string | `""` | Configure the maximum frequency for the garbage collection of the connection tracking table. Only affects the automatic computation for the frequency and has no effect when 'conntrackGCInterval' is set. This can be set to more frequently clean up unused identities created from ToFQDN policies. | @@ -384,6 +380,7 @@ contributors across the globe, there is almost always someone available to help. | enableMasqueradeRouteSource | bool | `false` | Enables masquerading to the source of the route for traffic leaving the node from endpoints. | | enableNoServiceEndpointsRoutable | bool | `true` | Enable routing to a service that has zero endpoints | | enableNonDefaultDenyPolicies | bool | `true` | Enable Non-Default-Deny policies | +| enableTunnelBIGTCP | bool | `false` | Enable BIG TCP in tunneling mode and increase maximum GRO/GSO limits for VXLAN/GENEVE tunnels | | enableXTSocketFallback | bool | `true` | Enables the fallback compatibility solution for when the xt_socket kernel module is missing and it is needed for the datapath L7 redirection to work properly. See documentation for details on when this can be disabled: https://docs.cilium.io/en/stable/operations/system_requirements/#linux-kernel. | | encryption.enabled | bool | `false` | Enable transparent network encryption. | | encryption.ipsec.encryptedOverlay | bool | `false` | Enable IPsec encrypted overlay | @@ -404,29 +401,8 @@ contributors across the globe, there is almost always someone available to help. | encryption.strictMode.ingress.enabled | bool | `false` | Enable strict ingress encryption. When enabled, all unencrypted overlay ingress traffic will be dropped. This option is only applicable when WireGuard and tunneling are enabled. | | encryption.type | string | `"ipsec"` | Encryption method. Can be one of ipsec, wireguard or ztunnel. | | encryption.wireguard.persistentKeepalive | string | `"0s"` | Controls WireGuard PersistentKeepalive option. Set 0s to disable. | -| encryption.ztunnel | object | `{"affinity":{},"annotations":{},"caAddress":"https://localhost:15012","extraEnv":[],"extraVolumeMounts":[],"extraVolumes":[],"healthPort":15021,"image":{"digest":null,"override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/istio/ztunnel","tag":"1.28.0-distroless","useDigest":false},"nodeSelector":{"kubernetes.io/os":"linux"},"podAnnotations":{},"podLabels":{},"priorityClassName":null,"readinessProbe":{"failureThreshold":3,"initialDelaySeconds":0,"periodSeconds":10},"resources":{"requests":{"cpu":"200m","memory":"512Mi"}},"secrets":{"bootstrapRootCert":null},"terminationGracePeriodSeconds":30,"tolerations":[{"effect":"NoSchedule","operator":"Exists"},{"key":"CriticalAddonsOnly","operator":"Exists"},{"effect":"NoExecute","operator":"Exists"}],"updateStrategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}}` | ztunnel encryption configuration. ztunnel is Istio's purpose-built, per-node proxy for handling L4 traffic in ambient mesh mode. These settings only apply when encryption.type is set to "ztunnel". | -| encryption.ztunnel.affinity | object | `{}` | Affinity for ztunnel pods. | -| encryption.ztunnel.annotations | object | `{}` | Annotations to be added to all ztunnel resources. | -| encryption.ztunnel.caAddress | string | `"https://localhost:15012"` | CA server address for certificate requests. | -| encryption.ztunnel.extraEnv | list | `[]` | Additional ztunnel container environment variables. | -| encryption.ztunnel.extraVolumeMounts | list | `[]` | Additional ztunnel volumeMounts. | -| encryption.ztunnel.extraVolumes | list | `[]` | Additional ztunnel volumes. | -| encryption.ztunnel.healthPort | int | `15021` | TCP port for the health API. | -| encryption.ztunnel.image | object | `{"digest":null,"override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/istio/ztunnel","tag":"1.28.0-distroless","useDigest":false}` | ztunnel container image. | -| encryption.ztunnel.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for ztunnel pods. | -| encryption.ztunnel.podAnnotations | object | `{}` | Annotations to be added to ztunnel pods. | -| encryption.ztunnel.podLabels | object | `{}` | Labels to be added to ztunnel pods. | -| encryption.ztunnel.priorityClassName | string | `nil` | The priority class to use for ztunnel pods. | -| encryption.ztunnel.readinessProbe | object | `{"failureThreshold":3,"initialDelaySeconds":0,"periodSeconds":10}` | Readiness probe configuration. | -| encryption.ztunnel.resources | object | `{"requests":{"cpu":"200m","memory":"512Mi"}}` | ztunnel resource limits & requests. | -| encryption.ztunnel.secrets | object | `{"bootstrapRootCert":null}` | ztunnel secrets configuration. | -| encryption.ztunnel.secrets.bootstrapRootCert | string | `nil` | Base64-encoded bootstrap root certificate content. If not provided, the secret must be created manually before deploying. @schema type: [null, string] @schema | -| encryption.ztunnel.terminationGracePeriodSeconds | int | `30` | Configure termination grace period for ztunnel DaemonSet. | -| encryption.ztunnel.tolerations | list | `[{"effect":"NoSchedule","operator":"Exists"},{"key":"CriticalAddonsOnly","operator":"Exists"},{"effect":"NoExecute","operator":"Exists"}]` | Node tolerations for ztunnel scheduling. | -| encryption.ztunnel.updateStrategy | object | `{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}` | ztunnel update strategy. | | endpointHealthChecking.enabled | bool | `true` | Enable connectivity health checking between virtual endpoints. | | endpointLockdownOnMapOverflow | bool | `false` | Enable endpoint lockdown on policy map overflow. | -| endpointPolicyUpdateTimeoutDuration | string | `nil` | Max duration to wait for envoy to respond to configuration changes. Default "10s". | | endpointRoutes.enabled | bool | `false` | Enable use of per endpoint routes instead of routing via the cilium_host interface. | | eni.awsEnablePrefixDelegation | bool | `false` | Enable ENI prefix delegation | | eni.awsReleaseExcessIPs | bool | `false` | Release IPs not used from the ENI | @@ -470,7 +446,7 @@ contributors across the globe, there is almost always someone available to help. | envoy.httpRetryCount | int | `3` | Maximum number of retries for each HTTP request | | envoy.httpUpstreamLingerTimeout | string | `nil` | Time in seconds to block Envoy worker thread while an upstream HTTP connection is closing. If set to 0, the connection is closed immediately (with TCP RST). If set to -1, the connection is closed asynchronously in the background. | | envoy.idleTimeoutDurationSeconds | int | `60` | Set Envoy upstream HTTP idle connection timeout seconds. Does not apply to connections with pending requests. Default 60s | -| envoy.image | object | `{"digest":"sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa","useDigest":true}` | Envoy container image. | +| envoy.image | object | `{"digest":"sha256:8188114a2768b5f49d6ce58e168b20d765e0fbc64eee0d83241aa2b150ccd788","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.35.9-1770979049-232ed4a26881e4ab4f766f251f258ed424fff663","useDigest":true}` | Envoy container image. | | envoy.initContainers | list | `[]` | Init containers added to the cilium Envoy DaemonSet. | | envoy.initialFetchTimeoutSeconds | int | `30` | Time in seconds after which the initial fetch on an xDS stream is considered timed out | | envoy.livenessProbe.enabled | bool | `true` | Enable liveness probe for cilium-envoy | @@ -615,7 +591,7 @@ contributors across the globe, there is almost always someone available to help. | hubble.relay.extraVolumes | list | `[]` | Additional hubble-relay volumes. | | hubble.relay.gops.enabled | bool | `true` | Enable gops for hubble-relay | | hubble.relay.gops.port | int | `9893` | Configure gops listen port for hubble-relay | -| hubble.relay.image | object | `{"digest":"sha256:5ee21d57b6ef2aa6db67e603a735fdceb162454b352b7335b651456e308f681b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.19.3","useDigest":true}` | Hubble-relay container image. | +| hubble.relay.image | object | `{"digest":"sha256:d8c4e13bc36a56179292bb52bc6255379cb94cb873700d316ea3139b1bdb8165","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.19.1","useDigest":true}` | Hubble-relay container image. | | hubble.relay.listenHost | string | `""` | Host to listen to. Specify an empty string to bind to all the interfaces. | | hubble.relay.listenPort | string | `"4245"` | Port to listen to. | | hubble.relay.logOptions | object | `{"format":null,"level":null}` | Logging configuration for hubble-relay. | @@ -733,7 +709,7 @@ contributors across the globe, there is almost always someone available to help. | identityAllocationMode | string | `"crd"` | Method to use for identity allocation (`crd`, `kvstore` or `doublewrite-readkvstore` / `doublewrite-readcrd` for migrating between identity backends). | | identityChangeGracePeriod | string | `"5s"` | Time to wait before using new identity on endpoint identity change. | | identityManagementMode | string | `"agent"` | Control whether CiliumIdentities are created by the agent ("agent"), the operator ("operator") or both ("both"). "Both" should be used only to migrate between "agent" and "operator". Operator-managed identities is a beta feature. | -| image | object | `{"digest":"sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.19.3","useDigest":true}` | Agent container image. | +| image | object | `{"digest":"sha256:41f1f74a0000de8656f1de4088ea00c8f2d49d6edea579034c73c5fd5fe01792","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.19.1","useDigest":true}` | Agent container image. | | imagePullSecrets | list | `[]` | Configure image pull secrets for pulling container images | | ingressController.default | bool | `false` | Set cilium ingress controller to be the default ingress controller This will let cilium ingress controller route entries without ingress class set | | ingressController.defaultSecretName | string | `nil` | Default secret name for ingresses without .spec.tls[].secretName set. | @@ -821,13 +797,12 @@ contributors across the globe, there is almost always someone available to help. | livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | | livenessProbe.periodSeconds | int | `30` | interval between checks of the liveness probe | | livenessProbe.requireK8sConnectivity | bool | `false` | whether to require k8s connectivity as part of the check. | -| loadBalancer | object | `{"acceleration":"disabled","l7":{"algorithm":"round_robin","backend":"disabled","ports":[]},"serviceTopology":false}` | Configure service load balancing | +| loadBalancer | object | `{"acceleration":"disabled","l7":{"algorithm":"round_robin","backend":"disabled","ports":[]}}` | Configure service load balancing | | loadBalancer.acceleration | string | `"disabled"` | acceleration is the option to accelerate service handling via XDP Applicable values can be: disabled (do not use XDP), native (XDP BPF program is run directly out of the networking driver's early receive path), or best-effort (use native mode XDP acceleration on devices that support it). | | loadBalancer.l7 | object | `{"algorithm":"round_robin","backend":"disabled","ports":[]}` | L7 LoadBalancer | | loadBalancer.l7.algorithm | string | `"round_robin"` | Default LB algorithm The default LB algorithm to be used for services, which can be overridden by the service annotation (e.g. service.cilium.io/lb-l7-algorithm) Applicable values: round_robin, least_request, random | | loadBalancer.l7.backend | string | `"disabled"` | Enable L7 service load balancing via envoy proxy. The request to a k8s service, which has specific annotation e.g. service.cilium.io/lb-l7, will be forwarded to the local backend proxy to be load balanced to the service endpoints. Please refer to docs for supported annotations for more configuration. Applicable values: - envoy: Enable L7 load balancing via envoy proxy. This will automatically set enable-envoy-config as well. - disabled: Disable L7 load balancing by way of service annotation. | | loadBalancer.l7.ports | list | `[]` | List of ports from service to be automatically redirected to above backend. Any service exposing one of these ports will be automatically redirected. Fine-grained control can be achieved by using the service annotation. | -| loadBalancer.serviceTopology | bool | `false` | serviceTopology enables K8s Topology Aware Hints -based service endpoints filtering | | localRedirectPolicies.addressMatcherCIDRs | string | `nil` | Limit the allowed addresses in Address Matcher rule of Local Redirect Policies to the given CIDRs. @schema@ type: [null, array] @schema@ | | localRedirectPolicies.enabled | bool | `false` | Enable local redirect policies. | | localRedirectPolicy | bool | `false` | Enable Local Redirect Policy (deprecated, please use 'localRedirectPolicies.enabled' instead) | @@ -885,7 +860,7 @@ contributors across the globe, there is almost always someone available to help. | operator.hostNetwork | bool | `true` | HostNetwork setting | | operator.identityGCInterval | string | `"15m0s"` | Interval for identity garbage collection. | | operator.identityHeartbeatTimeout | string | `"30m0s"` | Timeout for identity heartbeats. | -| operator.image | object | `{"alibabacloudDigest":"sha256:176321a65123373ff8c7823b25183102cbad98375e8d6c80b96d68b6e8491103","awsDigest":"sha256:a53dcbfb77282bf2ddd3abbe60f6d49762e7c1389a36cb35b71d504644a56640","azureDigest":"sha256:699c1571a3df1a98882ee13610d47cffb7b34ee7e8d276096db798a5f6c7e4cb","genericDigest":"sha256:205b09b0ed6accbf9fe688d312a9f0fcfc6a316fc081c23fbffb472af5dd62cd","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.19.3","useDigest":true}` | cilium-operator image. | +| operator.image | object | `{"alibabacloudDigest":"sha256:837b12f4239e88ea5b4b5708ab982c319a94ee05edaecaafe5fd0e5b1962f554","awsDigest":"sha256:18913d05a6c4d205f0b7126c4723bb9ccbd4dc24403da46ed0f9f4bf2a142804","azureDigest":"sha256:82bce78603056e709d4c4e9f9ebb25c222c36d8a07f8c05381c2372d9078eca8","genericDigest":"sha256:e7278d763e448bf6c184b0682cf98cdca078d58a27e1b2f3c906792670aa211a","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.19.1","useDigest":true}` | cilium-operator image. | | operator.nodeGCInterval | string | `"5m0s"` | Interval for cilium node garbage collection. | | operator.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for cilium-operator pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | operator.podAnnotations | object | `{}` | Annotations to be added to cilium-operator pods | @@ -943,11 +918,11 @@ contributors across the globe, there is almost always someone available to help. | preflight.affinity | object | `{"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-preflight | | preflight.annotations | object | `{}` | Annotations to be added to all top-level preflight objects (resources under templates/cilium-preflight) | | preflight.enabled | bool | `false` | Enable Cilium pre-flight resources (required for upgrade) | -| preflight.envoy.image | object | `{"digest":"sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa","useDigest":true}` | Envoy pre-flight image. | +| preflight.envoy.image | object | `{"digest":"sha256:8188114a2768b5f49d6ce58e168b20d765e0fbc64eee0d83241aa2b150ccd788","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.35.9-1770979049-232ed4a26881e4ab4f766f251f258ed424fff663","useDigest":true}` | Envoy pre-flight image. | | preflight.extraEnv | list | `[]` | Additional preflight environment variables. | | preflight.extraVolumeMounts | list | `[]` | Additional preflight volumeMounts. | | preflight.extraVolumes | list | `[]` | Additional preflight volumes. | -| preflight.image | object | `{"digest":"sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.19.3","useDigest":true}` | Cilium pre-flight image. | +| preflight.image | object | `{"digest":"sha256:41f1f74a0000de8656f1de4088ea00c8f2d49d6edea579034c73c5fd5fe01792","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.19.1","useDigest":true}` | Cilium pre-flight image. | | preflight.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for preflight pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | preflight.podAnnotations | object | `{}` | Annotations to be added to preflight pods | | preflight.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | @@ -1004,7 +979,6 @@ contributors across the globe, there is almost always someone available to help. | serviceAccounts.corednsMCSAPI | object | `{"annotations":{},"automount":true,"create":true,"name":"cilium-coredns-mcsapi-autoconfig"}` | CorednsMCSAPI is used if clustermesh.mcsapi.corednsAutoConfigure.enabled=true | | serviceAccounts.hubblecertgen | object | `{"annotations":{},"automount":true,"create":true,"name":"hubble-generate-certs"}` | Hubblecertgen is used if hubble.tls.auto.method=cronJob | | serviceAccounts.nodeinit.enabled | bool | `false` | Enabled is temporary until https://github.com/cilium/cilium-cli/issues/1396 is implemented. Cilium CLI doesn't create the SAs for node-init, thus the workaround. Helm is not affected by this issue. Name and automount can be configured, if enabled is set to true. Otherwise, they are ignored. Enabled can be removed once the issue is fixed. Cilium-nodeinit DS must also be fixed. | -| serviceAccounts.ztunnel | object | `{"annotations":{},"automount":false,"create":true,"name":"ztunnel-cilium"}` | Ztunnel is used if encryption.type=ztunnel | | serviceNoBackendResponse | string | `"reject"` | Configure what the response should be to traffic for a service without backends. Possible values: - reject (default) - drop | | sleepAfterInit | bool | `false` | Do not run Cilium agent when running with clean mode. Useful to completely uninstall Cilium as it will stop Cilium from starting and create artifacts in the node. | | socketLB | object | `{"enabled":false}` | Configure socket LB | diff --git a/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml b/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml index 90ebf4ac..ea1d3bda 100644 --- a/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml +++ b/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml @@ -167,8 +167,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -185,8 +183,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -208,8 +204,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -226,8 +220,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -312,4 +304,3 @@ admin: address: pipe: path: "/var/run/cilium/envoy/sockets/admin.sock" - mode: 0660 diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml index fff1b384..fa3afc14 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml @@ -546,7 +546,7 @@ spec: {{- toYaml .Values.initResources | trim | nindent 10 }} {{- end }} command: - - bash + - sh - -ec # The statically linked Go program binary is invoked to avoid any # dependency on utilities like sh and mount that can be missing on certain @@ -592,7 +592,7 @@ spec: - name: BIN_PATH value: {{ .Values.cni.binPath }} command: - - bash + - sh - -ec # The statically linked Go program binary is invoked to avoid any # dependency on utilities like sh that can be missing on certain @@ -660,7 +660,7 @@ spec: {{- toYaml . | trim | nindent 10 }} {{- end }} command: - - bash + - sh - -c - | until test -s {{ (print "/tmp/cilium-bootstrap.d/" (.Values.nodeinit.bootstrapFile | base)) | quote }}; do diff --git a/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml index 5d76944d..a3a38c09 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml @@ -464,9 +464,6 @@ data: {{- if has (kindOf .Values.bpf.policyMapPressureMetricsThreshold) (list "int64" "float64") }} bpf-policy-map-pressure-metrics-threshold: {{ .Values.bpf.policyMapPressureMetricsThreshold | quote }} {{- end }} -{{- if .Values.endpointPolicyUpdateTimeoutDuration }} - endpoint-policy-update-timeout: {{ .Values.endpointPolicyUpdateTimeoutDuration | quote }} -{{- end }} {{- if hasKey .Values.bpf "policyStatsMapMax" }} # bpf-policy-stats-map-max specifies the maximum number of entries in global # policy stats map @@ -709,6 +706,7 @@ data: enable-ipv4-big-tcp: {{ .Values.enableIPv4BIGTCP | quote }} enable-ipv6-big-tcp: {{ .Values.enableIPv6BIGTCP | quote }} enable-ipv6-masquerade: {{ .Values.enableIPv6Masquerade | quote }} + enable-tunnel-big-tcp: {{ .Values.enableTunnelBIGTCP | quote }} {{- if hasKey .Values.bpf "enableTCX" }} enable-tcx: {{ .Values.bpf.enableTCX | quote }} @@ -908,9 +906,9 @@ data: {{- end }} {{- if hasKey .Values.loadBalancer "serviceTopology" }} enable-service-topology: {{ .Values.loadBalancer.serviceTopology | quote }} -{{- end }} -{{- end }} +# {{- end }} +{{- end }} {{- if hasKey .Values.maglev "tableSize" }} bpf-lb-maglev-table-size: {{ .Values.maglev.tableSize | quote}} {{- end }} @@ -1382,7 +1380,11 @@ data: {{- if .Values.operator.unmanagedPodWatcher.restart }} {{- $interval := .Values.operator.unmanagedPodWatcher.intervalSeconds }} + {{- if kindIs "float64" $interval }} unmanaged-pod-watcher-interval: {{ printf "%ds" (int $interval) | quote }} + {{- else }} + unmanaged-pod-watcher-interval: {{ $interval | quote }} + {{- end }} {{- else }} unmanaged-pod-watcher-interval: "0" {{- end }} @@ -1515,14 +1517,6 @@ data: connectivity-probe-frequency-ratio: {{ .Values.connectivityProbeFrequencyRatio | quote }} {{- end }} -{{- if hasKey .Values "configDriftDetection" }} - enable-dynamic-config: {{ .Values.configDriftDetection.enabled | quote }} - enable-drift-checker: {{ .Values.configDriftDetection.driftChecker | quote }} - {{- if .Values.configDriftDetection.ignoredKeys }} - ignore-flags-drift-checker: {{ join "," .Values.configDriftDetection.ignoredKeys | quote }} - {{- end }} -{{- end }} - # Extra config allows adding arbitrary properties to the cilium config. # By putting it at the end of the ConfigMap, it's also possible to override existing properties. {{- if .Values.extraConfig }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml index c147e2b5..96f72c7f 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml @@ -407,15 +407,6 @@ rules: verbs: - update - patch -- apiGroups: - - multicluster.x-k8s.io - resources: - # The controller needs to be able to set serviceimport finalizers to be able to create a derived Service - # resource that is owned by the ServiceImport and sets blockOwnerDeletion=true in its ownerRef. - # This is required when the admission plugin OwnerReferencesPermissionEnforcement is activated. - - serviceimports/finalizers - verbs: - - update - apiGroups: - multicluster.x-k8s.io resources: diff --git a/packages/system/cilium/charts/cilium/templates/ztunnel/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/ztunnel/daemonset.yaml deleted file mode 100644 index f9363068..00000000 --- a/packages/system/cilium/charts/cilium/templates/ztunnel/daemonset.yaml +++ /dev/null @@ -1,165 +0,0 @@ -{{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") }} ---- -kind: DaemonSet -apiVersion: apps/v1 -metadata: - name: ztunnel-cilium - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.encryption.ztunnel.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} - labels: - app: ztunnel-cilium - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: ztunnel-cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - revisionHistoryLimit: 10 - selector: - matchLabels: - app: ztunnel-cilium - {{- with .Values.encryption.ztunnel.updateStrategy }} - updateStrategy: - {{- toYaml . | trim | nindent 4 }} - {{- end }} - template: - metadata: - annotations: - sidecar.istio.io/inject: "false" - {{- with .Values.encryption.ztunnel.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - app: ztunnel-cilium - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: ztunnel-cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.encryption.ztunnel.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - hostNetwork: true - dnsPolicy: ClusterFirst - containers: - - name: istio-proxy - image: {{ include "cilium.image" .Values.encryption.ztunnel.image | quote }} - imagePullPolicy: {{ .Values.encryption.ztunnel.image.pullPolicy }} - args: - - proxy - - ztunnel - env: - - name: XDS_ADDRESS - value: "https://localhost:15012" - - name: XDS_ROOT_CA - value: "/etc/ztunnel/bootstrap-root.crt" - - name: CA_ROOT_CA - value: "/etc/ztunnel/bootstrap-root.crt" - - name: CA_ADDRESS - value: {{ .Values.encryption.ztunnel.caAddress | quote }} - - name: ISTIO_META_DNS_CAPTURE - value: "false" - - name: INPOD_UDS - value: "/var/run/cilium/ztunnel.sock" - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: ISTIO_META_ENABLE_HBONE - value: "true" - {{- with .Values.encryption.ztunnel.extraEnv }} - {{- toYaml . | trim | nindent 12 }} - {{- end }} - readinessProbe: - httpGet: - path: /healthz/ready - port: {{ .Values.encryption.ztunnel.healthPort }} - host: "127.0.0.1" - scheme: HTTP - initialDelaySeconds: {{ .Values.encryption.ztunnel.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.encryption.ztunnel.readinessProbe.periodSeconds }} - failureThreshold: {{ .Values.encryption.ztunnel.readinessProbe.failureThreshold }} - successThreshold: 1 - timeoutSeconds: 1 - {{- with .Values.encryption.ztunnel.resources }} - resources: - {{- toYaml . | trim | nindent 12 }} - {{- end }} - securityContext: - allowPrivilegeEscalation: true - capabilities: - add: - - NET_ADMIN - - SYS_ADMIN - - NET_RAW - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsGroup: 1337 - runAsNonRoot: false - runAsUser: 0 - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - volumeMounts: - - mountPath: /var/run/cilium - name: cilium-dir - readOnly: false - - mountPath: /etc/ztunnel - name: cilium-ztunnel-secrets - readOnly: true - {{- with .Values.encryption.ztunnel.extraVolumeMounts }} - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.encryption.ztunnel.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.encryption.ztunnel.nodeSelector }} - nodeSelector: - {{- toYaml . | trim | nindent 8 }} - {{- end }} - {{- with .Values.encryption.ztunnel.tolerations }} - tolerations: - {{- toYaml . | trim | nindent 8 }} - {{- end }} - priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.encryption.ztunnel.priorityClassName "system-node-critical") }} - restartPolicy: Always - terminationGracePeriodSeconds: {{ .Values.encryption.ztunnel.terminationGracePeriodSeconds }} - {{- if .Values.serviceAccounts.ztunnel.create }} - serviceAccountName: {{ .Values.serviceAccounts.ztunnel.name | quote }} - automountServiceAccountToken: {{ .Values.serviceAccounts.ztunnel.automount }} - {{- else }} - automountServiceAccountToken: false - {{- end }} - volumes: - - name: cilium-dir - hostPath: - path: /var/run/cilium - type: DirectoryOrCreate - - name: cilium-ztunnel-secrets - secret: - secretName: cilium-ztunnel-secrets - defaultMode: 420 - items: - - key: bootstrap-root.crt - path: bootstrap-root.crt - mode: 420 - {{- with .Values.encryption.ztunnel.extraVolumes }} - {{- toYaml . | nindent 8 }} - {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/ztunnel/secret.yaml b/packages/system/cilium/charts/cilium/templates/ztunnel/secret.yaml deleted file mode 100644 index 520857dc..00000000 --- a/packages/system/cilium/charts/cilium/templates/ztunnel/secret.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") }} -{{- if .Values.encryption.ztunnel.secrets.bootstrapRootCert }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: cilium-ztunnel-secrets - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.encryption.ztunnel.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} - labels: - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: ztunnel-cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} -type: Opaque -data: - bootstrap-root.crt: {{ .Values.encryption.ztunnel.secrets.bootstrapRootCert | b64enc }} -{{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/ztunnel/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/ztunnel/serviceaccount.yaml deleted file mode 100644 index 4ef9e2bc..00000000 --- a/packages/system/cilium/charts/cilium/templates/ztunnel/serviceaccount.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") .Values.serviceAccounts.ztunnel.create }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.serviceAccounts.ztunnel.name | quote }} - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if or .Values.serviceAccounts.ztunnel.annotations .Values.encryption.ztunnel.annotations }} - annotations: - {{- with .Values.encryption.ztunnel.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccounts.ztunnel.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/values.schema.json b/packages/system/cilium/charts/cilium/values.schema.json index 65c84af5..d18566d7 100644 --- a/packages/system/cilium/charts/cilium/values.schema.json +++ b/packages/system/cilium/charts/cilium/values.schema.json @@ -1714,21 +1714,6 @@ "object" ] }, - "configDriftDetection": { - "properties": { - "driftChecker": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "ignoredKeys": { - "items": {}, - "type": "array" - } - }, - "type": "object" - }, "connectivityProbeFrequencyRatio": { "type": [ "null", @@ -1913,6 +1898,9 @@ "enableNonDefaultDenyPolicies": { "type": "boolean" }, + "enableTunnelBIGTCP": { + "type": "boolean" + }, "enableXTSocketFallback": { "type": "boolean" }, @@ -1996,184 +1984,6 @@ } }, "type": "object" - }, - "ztunnel": { - "properties": { - "affinity": { - "type": "object" - }, - "annotations": { - "type": "object" - }, - "caAddress": { - "type": "string" - }, - "extraEnv": { - "items": {}, - "type": "array" - }, - "extraVolumeMounts": { - "items": {}, - "type": "array" - }, - "extraVolumes": { - "items": {}, - "type": "array" - }, - "healthPort": { - "type": "integer" - }, - "image": { - "properties": { - "digest": { - "type": [ - "null", - "string" - ] - }, - "override": { - "type": [ - "null", - "string" - ] - }, - "pullPolicy": { - "type": "string" - }, - "repository": { - "type": "string" - }, - "tag": { - "type": "string" - }, - "useDigest": { - "type": "boolean" - } - }, - "type": "object" - }, - "nodeSelector": { - "properties": { - "kubernetes.io/os": { - "type": "string" - } - }, - "type": "object" - }, - "podAnnotations": { - "type": "object" - }, - "podLabels": { - "type": "object" - }, - "priorityClassName": { - "type": [ - "null", - "string" - ] - }, - "readinessProbe": { - "properties": { - "failureThreshold": { - "type": "integer" - }, - "initialDelaySeconds": { - "type": "integer" - }, - "periodSeconds": { - "type": "integer" - } - }, - "type": "object" - }, - "resources": { - "properties": { - "requests": { - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "secrets": { - "properties": { - "bootstrapRootCert": { - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "terminationGracePeriodSeconds": { - "type": "integer" - }, - "tolerations": { - "items": { - "anyOf": [ - { - "properties": { - "effect": { - "type": "string" - }, - "operator": { - "type": "string" - } - } - }, - { - "properties": { - "key": { - "type": "string" - }, - "operator": { - "type": "string" - } - } - }, - { - "properties": { - "effect": { - "type": "string" - }, - "operator": { - "type": "string" - } - } - } - ] - }, - "type": "array" - }, - "updateStrategy": { - "properties": { - "rollingUpdate": { - "properties": { - "maxSurge": { - "type": "integer" - }, - "maxUnavailable": { - "type": "integer" - } - }, - "type": "object" - }, - "type": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" } }, "type": "object" @@ -2189,9 +1999,6 @@ "endpointLockdownOnMapOverflow": { "type": "boolean" }, - "endpointPolicyUpdateTimeoutDuration": { - "type": "null" - }, "endpointRoutes": { "properties": { "enabled": { @@ -4677,9 +4484,6 @@ } }, "type": "object" - }, - "serviceTopology": { - "type": "boolean" } }, "type": "object" @@ -6225,23 +6029,6 @@ } }, "type": "object" - }, - "ztunnel": { - "properties": { - "annotations": { - "type": "object" - }, - "automount": { - "type": "boolean" - }, - "create": { - "type": "boolean" - }, - "name": { - "type": "string" - } - }, - "type": "object" } }, "type": "object" diff --git a/packages/system/cilium/charts/cilium/values.yaml b/packages/system/cilium/charts/cilium/values.yaml index 66f76982..b9b30830 100644 --- a/packages/system/cilium/charts/cilium/values.yaml +++ b/packages/system/cilium/charts/cilium/values.yaml @@ -210,12 +210,6 @@ serviceAccounts: name: cilium-coredns-mcsapi-autoconfig automount: true annotations: {} - # -- Ztunnel is used if encryption.type=ztunnel - ztunnel: - create: true - name: ztunnel-cilium - automount: false - annotations: {} # -- Configure termination grace period for cilium-agent DaemonSet. terminationGracePeriodSeconds: 1 # -- Install the cilium agent resources. @@ -224,22 +218,6 @@ agent: true name: cilium # -- Roll out cilium agent pods automatically when configmap is updated. rollOutCiliumPods: false -# -- Configuration for the ConfigMap drift detection feature. -# When enabled, the agent continuously watches the cilium-config ConfigMap -# and exposes a cilium_drift_checker_config_delta Prometheus metric reporting -# the number of keys that differ between the ConfigMap and the agent's active -# settings. A non-zero value indicates that the agent has not yet applied all -# current ConfigMap changes and needs to be restarted. -configDriftDetection: - # -- Enable watching of the cilium-config ConfigMap and reflecting its - # contents into the agent's internal DynamicConfig table. - enabled: true - # -- Enable the drift checker which compares the DynamicConfig table against - # the agent's active settings and publishes the - # cilium_drift_checker_config_delta metric. - driftChecker: true - # -- List of config-map keys to ignore when computing the drift delta. - ignoredKeys: [] # -- Agent container image. image: # @schema @@ -247,10 +225,10 @@ image: # @schema override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.19.3" + tag: "v1.19.1" pullPolicy: "IfNotPresent" # cilium-digest - digest: sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10 + digest: sha256:41f1f74a0000de8656f1de4088ea00c8f2d49d6edea579034c73c5fd5fe01792 useDigest: true # -- Scheduling configurations for cilium pods scheduling: @@ -1155,89 +1133,9 @@ encryption: wireguard: # -- Controls WireGuard PersistentKeepalive option. Set 0s to disable. persistentKeepalive: 0s - # -- ztunnel encryption configuration. - # ztunnel is Istio's purpose-built, per-node proxy for handling L4 traffic in ambient mesh mode. - # These settings only apply when encryption.type is set to "ztunnel". - ztunnel: - # -- ztunnel container image. - image: - # @schema - # type: [null, string] - # @schema - override: ~ - repository: "docker.io/istio/ztunnel" - tag: "1.28.0-distroless" - pullPolicy: "IfNotPresent" - # @schema - # type: [null, string] - # @schema - digest: ~ - useDigest: false - # -- CA server address for certificate requests. - caAddress: "https://localhost:15012" - # -- TCP port for the health API. - healthPort: 15021 - # -- ztunnel resource limits & requests. - resources: - requests: - cpu: 200m - memory: 512Mi - # -- ztunnel update strategy. - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - # -- Configure termination grace period for ztunnel DaemonSet. - terminationGracePeriodSeconds: 30 - # -- Readiness probe configuration. - readinessProbe: - initialDelaySeconds: 0 - periodSeconds: 10 - failureThreshold: 3 - # -- Node selector for ztunnel pods. - nodeSelector: - kubernetes.io/os: linux - # -- Node tolerations for ztunnel scheduling. - tolerations: - - effect: NoSchedule - operator: Exists - - key: CriticalAddonsOnly - operator: Exists - - effect: NoExecute - operator: Exists - # -- Affinity for ztunnel pods. - affinity: {} - # @schema - # type: [null, string] - # @schema - # -- The priority class to use for ztunnel pods. - priorityClassName: ~ - # -- Annotations to be added to all ztunnel resources. - annotations: {} - # -- Annotations to be added to ztunnel pods. - podAnnotations: {} - # -- Labels to be added to ztunnel pods. - podLabels: {} - # -- Additional ztunnel container environment variables. - extraEnv: [] - # -- Additional ztunnel volumes. - extraVolumes: [] - # -- Additional ztunnel volumeMounts. - extraVolumeMounts: [] - # -- ztunnel secrets configuration. - secrets: - # -- Base64-encoded bootstrap root certificate content. - # If not provided, the secret must be created manually before deploying. - # @schema - # type: [null, string] - # @schema - bootstrapRootCert: ~ endpointHealthChecking: # -- Enable connectivity health checking between virtual endpoints. enabled: true -# -- Max duration to wait for envoy to respond to configuration changes. Default "10s". -endpointPolicyUpdateTimeoutDuration: null endpointRoutes: # @schema # type: [boolean, string] @@ -1352,8 +1250,8 @@ certgen: # @schema override: ~ repository: "quay.io/cilium/certgen" - tag: "v0.4.1" - digest: "sha256:f0c656830e856d26b24b0e144df1f8b327d3b46748d76a630514111fc365b697" + tag: "v0.3.2" + digest: "sha256:19921f48ee7e2295ea4dca955878a6cd8d70e6d4219d08f688e866ece9d95d4d" useDigest: true pullPolicy: "IfNotPresent" # @schema @@ -1701,9 +1599,9 @@ hubble: # @schema override: ~ repository: "quay.io/cilium/hubble-relay" - tag: "v1.19.3" + tag: "v1.19.1" # hubble-relay-digest - digest: sha256:5ee21d57b6ef2aa6db67e603a735fdceb162454b352b7335b651456e308f681b + digest: sha256:d8c4e13bc36a56179292bb52bc6255379cb94cb873700d316ea3139b1bdb8165 useDigest: true pullPolicy: "IfNotPresent" # -- Specifies the resources for the hubble-relay pods @@ -2415,6 +2313,8 @@ enableMasqueradeRouteSource: false enableIPv4BIGTCP: false # -- Enables IPv6 BIG TCP support which increases maximum IPv6 GSO/GRO limits for nodes and pods enableIPv6BIGTCP: false +# -- Enable BIG TCP in tunneling mode and increase maximum GRO/GSO limits for VXLAN/GENEVE tunnels +enableTunnelBIGTCP: false nat: # -- Number of the top-k SNAT map connections to track in Cilium statedb. mapStatsEntries: 32 @@ -2492,7 +2392,8 @@ loadBalancer: # -- serviceTopology enables K8s Topology Aware Hints -based service # endpoints filtering - serviceTopology: false + # serviceTopology: false + # -- L7 LoadBalancer l7: # -- Enable L7 service load balancing via envoy proxy. @@ -2725,9 +2626,9 @@ envoy: # @schema override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa" + tag: "v1.35.9-1770979049-232ed4a26881e4ab4f766f251f258ed424fff663" pullPolicy: "IfNotPresent" - digest: "sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d" + digest: "sha256:8188114a2768b5f49d6ce58e168b20d765e0fbc64eee0d83241aa2b150ccd788" useDigest: true # -- Init containers added to the cilium Envoy DaemonSet. initContainers: [] @@ -3110,15 +3011,15 @@ operator: # @schema override: ~ repository: "quay.io/cilium/operator" - tag: "v1.19.3" + tag: "v1.19.1" # operator-generic-digest - genericDigest: sha256:205b09b0ed6accbf9fe688d312a9f0fcfc6a316fc081c23fbffb472af5dd62cd + genericDigest: sha256:e7278d763e448bf6c184b0682cf98cdca078d58a27e1b2f3c906792670aa211a # operator-azure-digest - azureDigest: sha256:699c1571a3df1a98882ee13610d47cffb7b34ee7e8d276096db798a5f6c7e4cb + azureDigest: sha256:82bce78603056e709d4c4e9f9ebb25c222c36d8a07f8c05381c2372d9078eca8 # operator-aws-digest - awsDigest: sha256:a53dcbfb77282bf2ddd3abbe60f6d49762e7c1389a36cb35b71d504644a56640 + awsDigest: sha256:18913d05a6c4d205f0b7126c4723bb9ccbd4dc24403da46ed0f9f4bf2a142804 # operator-alibabacloud-digest - alibabacloudDigest: sha256:176321a65123373ff8c7823b25183102cbad98375e8d6c80b96d68b6e8491103 + alibabacloudDigest: sha256:837b12f4239e88ea5b4b5708ab982c319a94ee05edaecaafe5fd0e5b1962f554 useDigest: true pullPolicy: "IfNotPresent" suffix: "" @@ -3443,9 +3344,9 @@ preflight: # @schema override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.19.3" + tag: "v1.19.1" # cilium-digest - digest: sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10 + digest: sha256:41f1f74a0000de8656f1de4088ea00c8f2d49d6edea579034c73c5fd5fe01792 useDigest: true pullPolicy: "IfNotPresent" envoy: @@ -3456,9 +3357,9 @@ preflight: # @schema override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa" + tag: "v1.35.9-1770979049-232ed4a26881e4ab4f766f251f258ed424fff663" pullPolicy: "IfNotPresent" - digest: "sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d" + digest: "sha256:8188114a2768b5f49d6ce58e168b20d765e0fbc64eee0d83241aa2b150ccd788" useDigest: true # -- The priority class to use for the preflight pod. priorityClassName: "" @@ -3702,9 +3603,9 @@ clustermesh: # @schema override: ~ repository: "quay.io/cilium/clustermesh-apiserver" - tag: "v1.19.3" + tag: "v1.19.1" # clustermesh-apiserver-digest - digest: sha256:a8136a7615d6c6041d3aa6f2674d17beaec238170d669507ccc05328a778e2b7 + digest: sha256:56d6c3dc13b50126b80ecb571707a0ea97f6db694182b9d61efd386d04e5bb28 useDigest: true pullPolicy: "IfNotPresent" # -- TCP port for the clustermesh-apiserver health API. @@ -4239,7 +4140,7 @@ authentication: override: ~ repository: "docker.io/library/busybox" tag: "1.37.0" - digest: "sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e" + digest: "sha256:b3255e7dfbcd10cb367af0d409747d511aeb66dfac98cf30e97e87e4207dd76f" useDigest: true pullPolicy: "IfNotPresent" # SPIRE agent configuration diff --git a/packages/system/cilium/charts/cilium/values.yaml.tmpl b/packages/system/cilium/charts/cilium/values.yaml.tmpl index 8039b40c..c21f1c26 100644 --- a/packages/system/cilium/charts/cilium/values.yaml.tmpl +++ b/packages/system/cilium/charts/cilium/values.yaml.tmpl @@ -213,12 +213,6 @@ serviceAccounts: name: cilium-coredns-mcsapi-autoconfig automount: true annotations: {} - # -- Ztunnel is used if encryption.type=ztunnel - ztunnel: - create: true - name: ztunnel-cilium - automount: false - annotations: {} # -- Configure termination grace period for cilium-agent DaemonSet. terminationGracePeriodSeconds: 1 # -- Install the cilium agent resources. @@ -227,22 +221,6 @@ agent: true name: cilium # -- Roll out cilium agent pods automatically when configmap is updated. rollOutCiliumPods: false -# -- Configuration for the ConfigMap drift detection feature. -# When enabled, the agent continuously watches the cilium-config ConfigMap -# and exposes a cilium_drift_checker_config_delta Prometheus metric reporting -# the number of keys that differ between the ConfigMap and the agent's active -# settings. A non-zero value indicates that the agent has not yet applied all -# current ConfigMap changes and needs to be restarted. -configDriftDetection: - # -- Enable watching of the cilium-config ConfigMap and reflecting its - # contents into the agent's internal DynamicConfig table. - enabled: true - # -- Enable the drift checker which compares the DynamicConfig table against - # the agent's active settings and publishes the - # cilium_drift_checker_config_delta metric. - driftChecker: true - # -- List of config-map keys to ignore when computing the drift delta. - ignoredKeys: [] # -- Agent container image. image: # @schema @@ -1170,89 +1148,9 @@ encryption: wireguard: # -- Controls WireGuard PersistentKeepalive option. Set 0s to disable. persistentKeepalive: 0s - # -- ztunnel encryption configuration. - # ztunnel is Istio's purpose-built, per-node proxy for handling L4 traffic in ambient mesh mode. - # These settings only apply when encryption.type is set to "ztunnel". - ztunnel: - # -- ztunnel container image. - image: - # @schema - # type: [null, string] - # @schema - override: ~ - repository: "docker.io/istio/ztunnel" - tag: "1.28.0-distroless" - pullPolicy: "IfNotPresent" - # @schema - # type: [null, string] - # @schema - digest: ~ - useDigest: false - # -- CA server address for certificate requests. - caAddress: "https://localhost:15012" - # -- TCP port for the health API. - healthPort: 15021 - # -- ztunnel resource limits & requests. - resources: - requests: - cpu: 200m - memory: 512Mi - # -- ztunnel update strategy. - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - # -- Configure termination grace period for ztunnel DaemonSet. - terminationGracePeriodSeconds: 30 - # -- Readiness probe configuration. - readinessProbe: - initialDelaySeconds: 0 - periodSeconds: 10 - failureThreshold: 3 - # -- Node selector for ztunnel pods. - nodeSelector: - kubernetes.io/os: linux - # -- Node tolerations for ztunnel scheduling. - tolerations: - - effect: NoSchedule - operator: Exists - - key: CriticalAddonsOnly - operator: Exists - - effect: NoExecute - operator: Exists - # -- Affinity for ztunnel pods. - affinity: {} - # @schema - # type: [null, string] - # @schema - # -- The priority class to use for ztunnel pods. - priorityClassName: ~ - # -- Annotations to be added to all ztunnel resources. - annotations: {} - # -- Annotations to be added to ztunnel pods. - podAnnotations: {} - # -- Labels to be added to ztunnel pods. - podLabels: {} - # -- Additional ztunnel container environment variables. - extraEnv: [] - # -- Additional ztunnel volumes. - extraVolumes: [] - # -- Additional ztunnel volumeMounts. - extraVolumeMounts: [] - # -- ztunnel secrets configuration. - secrets: - # -- Base64-encoded bootstrap root certificate content. - # If not provided, the secret must be created manually before deploying. - # @schema - # type: [null, string] - # @schema - bootstrapRootCert: ~ endpointHealthChecking: # -- Enable connectivity health checking between virtual endpoints. enabled: true -# -- Max duration to wait for envoy to respond to configuration changes. Default "10s". -endpointPolicyUpdateTimeoutDuration: null endpointRoutes: # @schema # type: [boolean, string] @@ -2441,6 +2339,8 @@ enableMasqueradeRouteSource: false enableIPv4BIGTCP: false # -- Enables IPv6 BIG TCP support which increases maximum IPv6 GSO/GRO limits for nodes and pods enableIPv6BIGTCP: false +# -- Enable BIG TCP in tunneling mode and increase maximum GRO/GSO limits for VXLAN/GENEVE tunnels +enableTunnelBIGTCP: false nat: # -- Number of the top-k SNAT map connections to track in Cilium statedb. @@ -2520,7 +2420,7 @@ loadBalancer: # -- serviceTopology enables K8s Topology Aware Hints -based service # endpoints filtering - serviceTopology: false + # serviceTopology: false # -- L7 LoadBalancer l7: diff --git a/packages/system/cilium/images/cilium/Dockerfile b/packages/system/cilium/images/cilium/Dockerfile index 32fc6fb8..b62f9b46 100644 --- a/packages/system/cilium/images/cilium/Dockerfile +++ b/packages/system/cilium/images/cilium/Dockerfile @@ -1,2 +1,2 @@ -ARG VERSION=v1.19.3 +ARG VERSION=v1.19.1 FROM quay.io/cilium/cilium:${VERSION} diff --git a/packages/system/cilium/values.yaml b/packages/system/cilium/values.yaml index 9aba7cb9..cfb2cd6b 100644 --- a/packages/system/cilium/values.yaml +++ b/packages/system/cilium/values.yaml @@ -15,8 +15,8 @@ cilium: mode: "kubernetes" image: repository: ghcr.io/cozystack/cozystack/cilium - tag: 1.19.3 - digest: "sha256:700f06f4803a838a8e830be5ace4650e3ad82bdefabfb2f4d110368d307a5efb" + tag: 1.19.1 + digest: "sha256:ab3acf270821df4614a8456348a4e0d3098aed72a4b2016a0edfa30d91428c3d" envoy: enabled: false rollOutCiliumPods: true diff --git a/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml b/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml index 58f166f6..13352680 100644 --- a/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml +++ b/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: cozy-proxy description: A simple kube-proxy addon for 1:1 NAT services in Kubernetes using an NFT backend type: application -version: 0.3.0 -appVersion: 0.3.0 +version: 0.2.0 +appVersion: 0.2.0 diff --git a/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml b/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml index e143e926..8cde5bed 100644 --- a/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml +++ b/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml @@ -1,6 +1,6 @@ image: repository: ghcr.io/cozystack/cozystack/cozy-proxy - tag: v0.3.0 + tag: v0.2.0 pullPolicy: IfNotPresent daemonset: diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index dddabf54..2ccdb706 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,3 +1,3 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v1.3.0@sha256:5fa8648821cf1e9e08cf7c2899c4b1c4226bb74c6773327141456c7d3f2b9b7e + image: ghcr.io/cozystack/cozystack/cozystack-api:v1.3.0-rc.1@sha256:c57f2e62a547e4d62ec1c88708bbce146653bc68e1e312ab16f97a9206bd6750 replicas: 2 diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 4d0d0fde..6addae2b 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,4 +1,4 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.3.0@sha256:d03d19b78c4c98f970ac549a68b01ef6bd1ad755f5e0dcb9e08503511cdf2fdc + image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.3.0-rc.1@sha256:5ab50893e9d0237d26f366c9d647da6337ca9b97bae764430571d4fb080f6200 debug: false disableTelemetry: false diff --git a/packages/system/dashboard/templates/configmap.yaml b/packages/system/dashboard/templates/configmap.yaml index a2b7684c..c2be8d46 100644 --- a/packages/system/dashboard/templates/configmap.yaml +++ b/packages/system/dashboard/templates/configmap.yaml @@ -1,6 +1,6 @@ {{- $brandingConfig := .Values._cluster.branding | default dict }} -{{- $tenantText := "v1.3.0" }} +{{- $tenantText := "v1.3.0-rc.1" }} {{- $footerText := "Cozystack" }} {{- $titleText := "Cozystack Dashboard" }} {{- $logoText := "" }} diff --git a/packages/system/dashboard/templates/ingress.yaml b/packages/system/dashboard/templates/ingress.yaml index 6cf01490..a10797fb 100644 --- a/packages/system/dashboard/templates/ingress.yaml +++ b/packages/system/dashboard/templates/ingress.yaml @@ -11,7 +11,7 @@ metadata: annotations: cert-manager.io/cluster-issuer: {{ $clusterIssuer }} {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $exposeIngress }} + acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }} {{- end }} nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/client-max-body-size: 100m diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index a5188825..63305af8 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -1,6 +1,6 @@ openapiUI: - image: ghcr.io/cozystack/cozystack/openapi-ui:v1.3.0@sha256:0fa79c373a62840a617ff1ca1b0e31931c13a6cf7b0bb0ff0dc191f047a465a3 + image: ghcr.io/cozystack/cozystack/openapi-ui:v1.3.0-rc.1@sha256:69dcecbea0cfff681043c75e3508c84f03a01b7be3e3a425deb740d629d3ab04 openapiUIK8sBff: - image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.3.0@sha256:1b3ea6d4c7dbbe6a8def3b2807fffdfab2ac4afc39d7a846e57dd491fa168f92 + image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.3.0-rc.1@sha256:873cf834deddaa3954b6d9c5d520a8e03714b77178eff44826d93540561f599e tokenProxy: - image: ghcr.io/cozystack/cozystack/token-proxy:v1.3.0@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc + image: ghcr.io/cozystack/cozystack/token-proxy:v1.3.0-rc.1@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc diff --git a/packages/system/gpu-operator/examples/README.md b/packages/system/gpu-operator/examples/README.md deleted file mode 100644 index b6f170c8..00000000 --- a/packages/system/gpu-operator/examples/README.md +++ /dev/null @@ -1,121 +0,0 @@ -# GPU operator — native pod workload on Talos (reference) - -The files in this directory are **not** templates. They are reference -artifacts that document one working configuration for running GPU -workloads directly in pods on a Talos-based Cozystack cluster, together -with the DCGM metrics needed by the `gpu/gpu-performance` Grafana -dashboard. - -The out-of-the-box `values-talos.yaml` for this package targets the -sandbox (VFIO passthrough to KubeVirt VMs) scenario. The files here -illustrate an alternative — running CUDA workloads in regular pods with -the NVIDIA device plugin — and the workarounds it currently requires on -Talos. - -## Files - -- [`values-native-talos.yaml`](./values-native-talos.yaml) — Cozystack - `Package` values that disable sandbox workloads, enable the device - plugin, point `hostPaths.driverInstallDir` at the staging location - used by the compat DaemonSet, and wire DCGM to the custom metrics - ConfigMap. -- [`dcgm-custom-metrics.yaml`](./dcgm-custom-metrics.yaml) — `ConfigMap` - with a DCGM metrics CSV that adds profiling, ECC, throttling and - energy counters on top of the upstream defaults. The CSV is a - superset needed for full coverage of the `gpu/gpu-performance` - dashboard. Which parts are actually required depends on which - dashboards you ship — see the table below. -- [`nvidia-driver-compat.yaml`](./nvidia-driver-compat.yaml) — DaemonSet - that stages `libnvidia-ml.so.1` and `nvidia-smi` from the Talos glibc - tree into a path where the NVIDIA GPU Operator validator expects - them. See the "Why the compat DaemonSet exists" section below. - -## Why these are reference, not templates - -Shipping these as first-class templates would silently impose -assumptions that do not hold for every user: - -- Whether the NVIDIA Talos system extension is installed on the nodes. -- Whether GPUs are exposed directly to pods or passed through to VMs. -- The exact path the installed driver ends up at (depends on the - extension version and Talos release). - -The sandbox-oriented `values-talos.yaml` remains the default. Operators -who want native pod GPU workloads can start from this directory and -adapt as needed. - -## Why the compat DaemonSet exists - -The NVIDIA GPU Operator validator checks for `libnvidia-ml.so.1` and -`bin/nvidia-smi` in the path given by `hostPaths.driverInstallDir`. -Talos installs them under `/usr/local/glibc/usr/lib/` and -`/usr/local/bin/`, which the validator does not look at. Until upstream -addresses [NVIDIA/gpu-operator#1687][1], the DaemonSet copies those -files into a directory the validator does inspect and creates the -`.driver-ctr-ready` flag file so the validator proceeds. - -[1]: https://github.com/NVIDIA/gpu-operator/issues/1687 - -The compat DaemonSet runs privileged and bind-mounts host paths, so -the target namespace must allow privileged pods. On clusters that -enforce the Kubernetes Pod Security Standards at `baseline` or -`restricted`, label the namespace with -`pod-security.kubernetes.io/enforce: privileged` (and the matching -`audit`/`warn` labels if the admission webhook is configured to -surface violations) before applying the manifest. - -## Dashboards and what DCGM metrics they need - -Five GPU dashboards live under `gpu/*` in -`packages/system/monitoring/dashboards-infra.list`. All of them share -`packages/system/monitoring-agents/alerts/gpu-recording.rules.yaml` as -their source of aggregated series. The recording rules are safe to -ship on any cluster — they evaluate to empty series when DCGM is not -scraped, or when optional counters are missing. - -What each dashboard needs on top of the upstream DCGM Exporter -[`default-counters.csv`][default-csv]: - -| Dashboard | Scope | Needs beyond defaults | -| ----------------- | ---------------------------------- | ----------------------------------------------------------------------- | -| `gpu-performance` | Per-node, per-GPU deep dive | `DCGM_FI_DEV_POWER_VIOLATION`, `DCGM_FI_DEV_THERMAL_VIOLATION` | -| `gpu-efficiency` | Per-workload util vs tensor active | `DCGM_FI_DEV_POWER_VIOLATION`, `DCGM_FI_DEV_THERMAL_VIOLATION` (via `gpu:*_throttle_fraction:rate5m` recording rules) | -| `gpu-fleet` | Cluster-wide admin inventory | `DCGM_FI_DEV_POWER_MGMT_LIMIT` (for the TDP vs draw panel) | -| `gpu-quotas` | Kube-quota vs live usage | `kube_pod_container_resource_requests`, `kube_pod_status_phase`, `kube_node_status_allocatable` (via `namespace:gpu_count:allocated` / `cluster:gpu_count:*` recording rules) | -| `gpu-tenants` | Per-namespace tenant view | nothing (works on default counters) | - -`DCGM_FI_PROF_PIPE_TENSOR_ACTIVE` and `DCGM_FI_PROF_GR_ENGINE_ACTIVE` -are already in the upstream default set for the pinned DCGM Exporter -version, so the tensor-saturation and engine-active panels work without -any CSV override. The three counters listed in the table — throttling -violations and the power management limit — are the only extras the -tracked dashboards need. The recording rules in -`gpu-recording.rules.yaml` consume utilization, FB used, power, -temperature and the tensor-active profiling counter from the default -set, plus `DCGM_FI_DEV_POWER_VIOLATION` and -`DCGM_FI_DEV_THERMAL_VIOLATION` — used by the -`gpu.recording.efficiency.1m` group to derive the -`gpu:power_throttle_fraction:rate5m` and -`gpu:thermal_throttle_fraction:rate5m` series consumed by the -throttling panels on the efficiency and fleet dashboards. - -The `gpu.recording.throttle.validation.5m` group additionally ships the -`GPUThrottleFractionOverOne` alert (severity `warning`) as a regression -detector: it fires when either throttle-fraction series exceeds 1.0, -which would indicate that DCGM changed the scale/divisor of the -underlying violation counters and the recording rules need to be -re-derived. - -## Verification status - -The minimum-CSV claims above are verified by -`hack/check-gpu-recording-rules.bats`, which cross-checks every -`DCGM_FI_*` reference in the tracked GPU dashboards and recording rules -against the union of the upstream default set (snapshotted at -`hack/dcgm-default-counters.csv` for the pinned DCGM Exporter version) -and the custom CSV in `dcgm-custom-metrics.yaml`. When the DCGM -Exporter image in `packages/system/gpu-operator/charts/gpu-operator/values.yaml` -is bumped, refresh the snapshot from the matching tag of the -[`NVIDIA/dcgm-exporter`][default-csv] repository and rerun the test. - -[default-csv]: https://github.com/NVIDIA/dcgm-exporter/blob/main/etc/default-counters.csv diff --git a/packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml b/packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml deleted file mode 100644 index ef2b0b88..00000000 --- a/packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# Custom DCGM Exporter metrics CSV. Referenced from -# examples/values-native-talos.yaml via dcgmExporter.config.name. -# -# Extends the upstream default set with profiling counters, ECC, page -# retirement, row remap, energy and throttling violations — everything -# the gpu/gpu-performance dashboard and the GPU recording rules in -# monitoring-agents expect. -apiVersion: v1 -kind: ConfigMap -metadata: - name: dcgm-custom-metrics - namespace: cozy-gpu-operator -data: - dcgm-metrics.csv: | - # Format - # If line starts with a '#' it is considered a comment - # DCGM FIELD, Prometheus metric type, help message - - # Identity - DCGM_FI_DRIVER_VERSION, label, Driver version. - - # Clocks - DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency (in MHz). - DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz). - - # Temperature - DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature (in C). - DCGM_FI_DEV_GPU_TEMP, gauge, GPU temperature (in C). - - # Power - DCGM_FI_DEV_POWER_USAGE, gauge, Power draw (in W). - DCGM_FI_DEV_POWER_MGMT_LIMIT, gauge, Current power management limit (in W). - DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION, counter, Total energy consumption since boot (in mJ). - - # PCIE - DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total number of PCIe retries. - - # Utilization (the sample period varies depending on the product) - DCGM_FI_DEV_GPU_UTIL, gauge, GPU utilization (in %). - DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory utilization (in %). - DCGM_FI_DEV_ENC_UTIL, gauge, Encoder utilization (in %). - DCGM_FI_DEV_DEC_UTIL, gauge, Decoder utilization (in %). - - # Errors and violations - DCGM_FI_DEV_XID_ERRORS, gauge, Value of the last XID error encountered. - - # Memory usage - DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free (in MiB). - DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used (in MiB). - DCGM_FI_DEV_FB_RESERVED, gauge, Framebuffer memory reserved (in MiB). - - # ECC (supported on datacenter-class GPUs such as A10) - DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Total number of single-bit volatile ECC errors. - DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Total number of double-bit volatile ECC errors. - DCGM_FI_DEV_ECC_SBE_AGG_TOTAL, counter, Total number of single-bit persistent ECC errors. - DCGM_FI_DEV_ECC_DBE_AGG_TOTAL, counter, Total number of double-bit persistent ECC errors. - - # Retired pages - DCGM_FI_DEV_RETIRED_SBE, counter, Total number of retired pages due to single-bit errors. - DCGM_FI_DEV_RETIRED_DBE, counter, Total number of retired pages due to double-bit errors. - DCGM_FI_DEV_RETIRED_PENDING, counter, Total number of pages pending retirement. - - # Row remapping (not applicable to GDDR6 but left for datacenter GPUs) - DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for uncorrectable errors. - DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for correctable errors. - DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, Whether remapping of rows has failed. - - # Throttle / violation counters (crucial for SLA and tenant monitoring) - DCGM_FI_DEV_POWER_VIOLATION, counter, Throttling duration due to power constraints (us per docs; ns on DCGM 3.x). - DCGM_FI_DEV_THERMAL_VIOLATION, counter, Throttling duration due to thermal constraints (us per docs; ns on DCGM 3.x). - DCGM_FI_DEV_SYNC_BOOST_VIOLATION, counter, Throttling duration due to sync-boost constraints (us per docs; ns on DCGM 3.x). - DCGM_FI_DEV_BOARD_LIMIT_VIOLATION, counter, Throttling duration due to board limit constraints (us per docs; ns on DCGM 3.x). - DCGM_FI_DEV_LOW_UTIL_VIOLATION, counter, Throttling duration due to low utilization (us per docs; ns on DCGM 3.x). - DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Throttling duration due to reliability constraints (us per docs; ns on DCGM 3.x). - - # NVLink — DCGM silently drops this metric on GPUs without NVLink, so - # enabling it unconditionally is safe and keeps this file reusable - # across GPU families. - DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL, counter, Total number of NVLink bandwidth counters for all lanes. - - # DCP (profiling) metrics — supported from Ampere onwards. - DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active. - DCGM_FI_PROF_SM_ACTIVE, gauge, The ratio of cycles an SM has at least 1 warp assigned. - DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident on an SM. - DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active. - DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of cycles the device memory interface is active sending or receiving data. - DCGM_FI_PROF_PCIE_TX_BYTES, counter, The number of bytes of active PCIe tx (transmit) data including both header and payload. - DCGM_FI_PROF_PCIE_RX_BYTES, counter, The number of bytes of active PCIe rx (read) data including both header and payload. diff --git a/packages/system/gpu-operator/examples/nvidia-driver-compat.yaml b/packages/system/gpu-operator/examples/nvidia-driver-compat.yaml deleted file mode 100644 index fc9d5981..00000000 --- a/packages/system/gpu-operator/examples/nvidia-driver-compat.yaml +++ /dev/null @@ -1,109 +0,0 @@ -# Workaround for https://github.com/NVIDIA/gpu-operator/issues/1687 -# -# On Talos, the NVIDIA system extension installs driver files under -# /usr/local/glibc/usr/lib/ and /usr/local/bin/. The GPU Operator -# validator only looks for libnvidia-ml.so.1 and bin/nvidia-smi under -# the path configured as hostPaths.driverInstallDir. This DaemonSet -# stages the required files into /var/nvidia-driver on each node and -# creates the .driver-ctr-ready flag so the validator proceeds. -# -# Paired with examples/values-native-talos.yaml, which sets -# hostPaths.driverInstallDir to /var/nvidia-driver. -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: nvidia-driver-compat - namespace: cozy-gpu-operator - labels: - app: nvidia-driver-compat -spec: - selector: - matchLabels: - app: nvidia-driver-compat - template: - metadata: - labels: - app: nvidia-driver-compat - # DaemonSet rather than a one-shot Job: staging is idempotent per-node, - # must re-run after every Talos reboot (hostPath contents are wiped on - # reboot when the system extension re-installs), and the pause container - # keeps the pod visible for operator observability (kubectl get pods). - spec: - priorityClassName: system-node-critical - # Restrict to GPU nodes only. Without this the DaemonSet schedules onto - # every node (including control-plane and CPU-only workers) and burns - # resources on hosts where the compat tree is meaningless. - # The label is published by Node Feature Discovery / GPU Operator's NFD - # subchart; if NFD is disabled, replace this with whatever label your - # cluster uses to mark GPU hosts. - nodeSelector: - nvidia.com/gpu.present: "true" - # Tolerate-all is intentionally broad: the nodeSelector above already - # confines scheduling to GPU nodes, so the "Exists" toleration only - # matters when those nodes carry extra taints (dedicated=gpu:NoSchedule, - # nvidia.com/gpu:NoSchedule from the GPU Operator's default policy, - # etc.). This mirrors the stance of the upstream nvidia-driver-daemonset - # and nvidia-device-plugin DaemonSets — blanket tolerations plus a - # narrow nodeSelector. - tolerations: - - operator: Exists - initContainers: - - name: create-driver-tree - image: busybox:1.37 - command: - - sh - - -c - - | - set -e - GLIBC_LIB="/host/usr/local/glibc/usr/lib" - SRC_BIN="/host/usr/local/bin" - DST="/host/var/nvidia-driver" - - mkdir -p "$DST/bin" - - [ -f "$GLIBC_LIB/libnvidia-ml.so.1" ] || { - echo "missing $GLIBC_LIB/libnvidia-ml.so.1" >&2 - exit 1 - } - [ -f "$SRC_BIN/nvidia-smi" ] || { - echo "missing $SRC_BIN/nvidia-smi" >&2 - exit 1 - } - - cp -f "$GLIBC_LIB/libnvidia-ml.so.1" "$DST/libnvidia-ml.so.1" - echo "Copied libnvidia-ml.so.1" - - cp -f "$SRC_BIN/nvidia-smi" "$DST/bin/nvidia-smi" - chmod +x "$DST/bin/nvidia-smi" - echo "Copied nvidia-smi" - - mkdir -p /host/run/nvidia/validations - touch /host/run/nvidia/validations/.driver-ctr-ready - echo "Created driver-ctr-ready flag" - echo "Done" - securityContext: - privileged: true - resources: - requests: - cpu: 10m - memory: 16Mi - limits: - cpu: 100m - memory: 64Mi - volumeMounts: - - name: host-root - mountPath: /host - containers: - - name: pause - image: registry.k8s.io/pause:3.10 - resources: - requests: - cpu: 10m - memory: 8Mi - limits: - cpu: 50m - memory: 16Mi - volumes: - - name: host-root - hostPath: - path: / diff --git a/packages/system/gpu-operator/examples/values-native-talos.yaml b/packages/system/gpu-operator/examples/values-native-talos.yaml deleted file mode 100644 index ef7b2891..00000000 --- a/packages/system/gpu-operator/examples/values-native-talos.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# Cozystack Package values for running GPU workloads natively in pods -# on Talos. This is the counterpart to values-talos.yaml, which targets -# the sandbox (VFIO passthrough) scenario. -# -# Prerequisites: -# - NVIDIA Talos system extension installed on GPU nodes. -# - examples/nvidia-driver-compat.yaml deployed to stage driver files -# where the gpu-operator validator looks for them. -# - examples/dcgm-custom-metrics.yaml applied so DCGM Exporter exports -# the full set of metrics used by the dashboard and recording rules. -apiVersion: cozystack.io/v1alpha1 -kind: Package -metadata: - name: cozystack.gpu-operator -spec: - variant: default - components: - gpu-operator: - values: - gpu-operator: - # The compat DaemonSet stages libnvidia-ml.so.1 and nvidia-smi - # under /var/nvidia-driver. Point the validator at that path. - hostPaths: - driverInstallDir: "/var/nvidia-driver" - # Disable the sandbox path — workloads run in pods, not VMs. - sandboxWorkloads: - enabled: false - vfioManager: - enabled: false - # The Talos extension provides the driver and runtime hooks, - # so the operator's own toolkit and driver components must be - # switched off to avoid conflicting installations. - toolkit: - enabled: false - devicePlugin: - enabled: true - # Export full set of DCGM metrics using the ConfigMap in - # examples/dcgm-custom-metrics.yaml. - dcgmExporter: - serviceMonitor: - enabled: true - # Matches the 1m evaluation cadence of GPU recording rules with - # 4x oversampling headroom. DCGM_FI_PROF_* counters have - # documented overhead concerns below 1s; 15s is safe. - interval: "15s" - honorLabels: true - relabelings: - - sourceLabels: [__meta_kubernetes_pod_node_name] - targetLabel: node - action: replace - config: - name: dcgm-custom-metrics diff --git a/packages/system/grafana-operator/images/grafana-dashboards.tag b/packages/system/grafana-operator/images/grafana-dashboards.tag index cde83a70..033a6742 100644 --- a/packages/system/grafana-operator/images/grafana-dashboards.tag +++ b/packages/system/grafana-operator/images/grafana-dashboards.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/grafana-dashboards:v1.3.0@sha256:2c9aa0b48e2bf6167db198f4d15882bfe51700108edf2e9f6d0942940a2c1204 +ghcr.io/cozystack/cozystack/grafana-dashboards:v1.3.0-rc.1@sha256:2c9aa0b48e2bf6167db198f4d15882bfe51700108edf2e9f6d0942940a2c1204 diff --git a/packages/system/hami/Chart.yaml b/packages/system/hami/Chart.yaml deleted file mode 100644 index 3fcf4c5d..00000000 --- a/packages/system/hami/Chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apiVersion: v2 -name: cozy-hami -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/hami/Makefile b/packages/system/hami/Makefile deleted file mode 100644 index 83663a66..00000000 --- a/packages/system/hami/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -export NAME=hami -export NAMESPACE=cozy-$(NAME) - -include ../../../hack/common-envs.mk -include ../../../hack/package.mk - -# When bumping the HAMi version, run `make update` and then review -# the resulting diff in `charts/hami/`. The recipe below reproduces the -# top-level vendoring overrides automatically: -# -# 1. Removes the broken hami-dra subchart. Upstream's NVIDIA DRA driver -# path requires kubelet DRA support that cozystack does not enable -# and has no upstream fix tracked. See commit 3c5521e. -# 2. Empties Chart.yaml dependencies and drops Chart.lock so Helm does -# not try to re-pull hami-dra at build time. See commit 2734dc0. -# 3. Strips dra/hami-dra/podSecurityPolicy blocks from the upstream -# values.yaml since the corresponding code paths are gone. PSP is -# removed from Kubernetes 1.25+ and is unused by cozystack. -# -# Template-level patches are NOT reproduced automatically: -# -# * Scheduler templates have `{{- if .Values.dra.enabled }}` blocks -# that need to be removed because the dra value is gone (commit -# 2734dc0 stripped them). -# * device-plugin/monitorservice.yaml uses `indent` with leading -# whitespace; it must be rewritten to `nindent` for the labels block -# to render correctly when devicePlugin.service.labels is set -# (commit 3685254). -# -# After `make update`, run `git diff -- charts/hami/templates/` and -# replay these template patches against the new upstream version, then -# verify with `helm unittest`. If upstream restructured the affected -# files, the patches may need to be redesigned rather than reapplied. - -update: - rm -rf charts - helm repo add hami-charts https://project-hami.github.io/HAMi/ - helm repo update hami-charts - helm pull hami-charts/hami --untar --untardir charts - rm -rf charts/hami/charts/hami-dra - yq --inplace '.dependencies = []' charts/hami/Chart.yaml - rm -f charts/hami/Chart.lock - yq --inplace 'del(.dra) | del(.["hami-dra"]) | del(.podSecurityPolicy)' charts/hami/values.yaml diff --git a/packages/system/hami/README.md b/packages/system/hami/README.md deleted file mode 100644 index 68669ac7..00000000 --- a/packages/system/hami/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# HAMi — GPU Virtualization Middleware - -[HAMi](https://github.com/Project-HAMi/HAMi) (Heterogeneous AI Computing Virtualization Middleware) is a CNCF Sandbox project that enables fractional GPU sharing in Kubernetes. It allows workloads to request specific amounts of GPU memory and compute cores instead of claiming entire GPUs. - -## Architecture - -HAMi consists of four components: - -- **MutatingWebhook** — intercepts pod creation, injects `schedulerName: hami-scheduler` -- **Scheduler Extender** — extends kube-scheduler with GPU-aware Filter and Bind logic -- **Device Plugin** (DaemonSet) — registers vGPU resources via the Kubernetes Device Plugin API -- **HAMi-core** (`libvgpu.so`) — `LD_PRELOAD` library injected into workload containers, intercepts CUDA API calls to enforce memory and compute isolation - -## Prerequisites - -- GPU Operator must be enabled (`addons.gpuOperator.enabled: true`) -- NVIDIA driver >= 440 on host nodes -- nvidia-container-toolkit configured as the default container runtime -- GPU nodes labeled with `gpu=on` - -## Known Limitations - -### glibc < 2.34 requirement for workload containers - -HAMi-core uses `LD_PRELOAD` to intercept `dlsym()` for CUDA symbol resolution. The fallback code path relies on `_dl_sym`, a private glibc internal symbol that was removed in glibc 2.34 when libdl and libpthread were merged into libc.so. - -**This limitation affects workload containers only**, not the host OS or HAMi's own components. - -| Distribution | glibc | Result | -| --------------- | ----- | -------------------------------------------- | -| Ubuntu 18.04 | 2.27 | Full isolation (memory + compute) | -| Ubuntu 20.04 | 2.31 | Full isolation (memory + compute) | -| Ubuntu 22.04 | 2.35 | Memory isolation works, compute breaks | -| Ubuntu 24.04 | 2.39 | Both memory and compute isolation break | -| Alpine (musl) | N/A | Completely incompatible (`dlvsym` absent) | - -Most modern ML/AI base images (CUDA 12.x, PyTorch 2.x, TensorFlow 2.x) use Ubuntu 22.04+ with glibc >= 2.35, which means compute isolation will not work with these images until the upstream fix is merged. - -**Upstream tracking issues:** - -- [HAMi-core#174](https://github.com/Project-HAMi/HAMi-core/issues/174) — `_dl_sym` removal in glibc 2.34 breaks HAMi-core's CUDA symbol resolution at the symbol level -- [HAMi#1190](https://github.com/Project-HAMi/HAMi/issues/1190) — maintainer thread confirming the empirical per-glibc-version isolation behavior shown in the table above - -### musl libc (Alpine) incompatibility - -HAMi-core is completely incompatible with musl libc. The `dlvsym()` function used by HAMi-core is a glibc extension not available in musl. Only glibc-based container images (Debian, Ubuntu, RHEL, etc.) can use HAMi GPU isolation. - -## Usage - -Enable HAMi in your tenant Kubernetes cluster values: - -```yaml -addons: - gpuOperator: - enabled: true - hami: - enabled: true -``` - -When HAMi is enabled, GPU Operator's built-in device plugin is automatically disabled to avoid conflicts. This default is preserved by setting `addons.gpuOperator.valuesOverride.gpu-operator.devicePlugin.enabled: false`; advanced topologies that partition GPU pools (e.g. some nodes use HAMi while others run the standard NVIDIA device plugin via node selectors) can re-enable it explicitly through `valuesOverride`. - -### Requesting fractional GPU resources - -```yaml -resources: - limits: - nvidia.com/gpu: 1 - nvidia.com/gpumem: 3000 # 3000 MB of GPU memory - nvidia.com/gpucores: 30 # 30% of GPU compute cores -``` - -## Parameters - -Default values shown below are inherited from the upstream HAMi chart and may change with upstream updates. - -| Name | Description | Default | -| --- | --- | --- | -| `hami.devicePlugin.runtimeClassName` | RuntimeClass for device plugin pods | `nvidia` | -| `hami.devicePlugin.deviceSplitCount` | Max virtual GPUs per physical GPU | `10` | -| `hami.devicePlugin.deviceMemoryScaling` | Memory overcommit factor (> 1.0 enables overcommit) | `1` | -| `hami.scheduler.defaultSchedulerPolicy.nodeSchedulerPolicy` | Node packing strategy (`binpack` or `spread`) | `binpack` | -| `hami.scheduler.defaultSchedulerPolicy.gpuSchedulerPolicy` | GPU packing strategy (`binpack` or `spread`) | `spread` | diff --git a/packages/system/hami/charts/hami/Chart.yaml b/packages/system/hami/charts/hami/Chart.yaml deleted file mode 100644 index 55f32ab6..00000000 --- a/packages/system/hami/charts/hami/Chart.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v2 -appVersion: 2.8.1 -dependencies: [] -description: Heterogeneous AI Computing Virtualization Middleware -keywords: -- vgpu -- gpu -kubeVersion: '>= 1.18.0-0' -maintainers: -- email: archlitchi@gmail.com - name: limengxuan -- email: xiaozhang0210@hotmail.com - name: zhangxiao -name: hami -sources: -- https://github.com/Project-HAMi/HAMi -type: application -version: 2.8.1 diff --git a/packages/system/hami/charts/hami/README.md b/packages/system/hami/charts/hami/README.md deleted file mode 100644 index e8217290..00000000 --- a/packages/system/hami/charts/hami/README.md +++ /dev/null @@ -1,237 +0,0 @@ -# HAMi Helm Chart Values Documentation - -This document provides detailed descriptions of all configurable values parameters for the HAMi Helm Chart. - -## Global Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `global.imageRegistry` | Global Docker image registry | `""` | -| `global.imagePullSecrets` | Global Docker image pull secrets | `[]` | -| `global.imageTag` | Image tag | `"v2.8.1"` | -| `global.gpuHookPath` | GPU Hook path | `/usr/local` | -| `global.labels` | Global labels | `{}` | -| `global.annotations` | Global annotations | `{}` | -| `global.managedNodeSelectorEnable` | Whether to enable managed node selector | `false` | -| `global.managedNodeSelector.usage` | Managed node selector usage | `"gpu"` | -| `nameOverride` | Name override | `""` | -| `fullnameOverride` | Full name override | `""` | -| `namespaceOverride` | Namespace override | `""` | - -## Resource Name Configuration - -### NVIDIA GPU Resources -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `resourceName` | GPU resource name | `"nvidia.com/gpu"` | -| `resourceMem` | GPU memory resource name | `"nvidia.com/gpumem"` | -| `resourceMemPercentage` | GPU memory percentage resource name | `"nvidia.com/gpumem-percentage"` | -| `resourceCores` | GPU core resource name | `"nvidia.com/gpucores"` | -| `resourcePriority` | GPU priority resource name | `"nvidia.com/priority"` | - -### Cambricon MLU Resources -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `mluResourceName` | MLU resource name | `"cambricon.com/vmlu"` | -| `mluResourceMem` | MLU memory resource name | `"cambricon.com/mlu.smlu.vmemory"` | -| `mluResourceCores` | MLU core resource name | `"cambricon.com/mlu.smlu.vcore"` | - -### Hygon DCU Resources -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `dcuResourceName` | DCU resource name | `"hygon.com/dcunum"` | -| `dcuResourceMem` | DCU memory resource name | `"hygon.com/dcumem"` | -| `dcuResourceCores` | DCU core resource name | `"hygon.com/dcucores"` | - -### Metax GPU Resources -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `metaxResourceName` | GPU resource name | `"metax-tech.com/sgpu"` | -| `metaxResourceCore` | GPU core resource name | `"metax-tech.com/vcore"` | -| `metaxResourceMem` | GPU memory resource name | `"metax-tech.com/vmemory"` | -| `metaxsGPUTopologyAware` | GPU topology awareness | `"false"` | - -### Enflame GCU Resources -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `enflameResourceNameVGCU` | vGCU resource name | `"enflame.com/vgcu"` | -| `enflameResourceNameVGCUPercentage` | vGCU percentage resource name | `"enflame.com/vgcu-percentage"` | - -### Kunlunxin XPU Resources -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `kunlunResourceName` | XPU resource name | `"kunlunxin.com/xpu"` | - -## Scheduler Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `schedulerName` | Scheduler name | `"hami-scheduler"` | -| `scheduler.nodeName` | Define node name, scheduler will schedule to this node | `""` | -| `scheduler.overwriteEnv` | Whether to overwrite environment variables | `"false"` | -| `scheduler.defaultSchedulerPolicy.nodeSchedulerPolicy` | Node scheduler policy | `binpack` | -| `scheduler.defaultSchedulerPolicy.gpuSchedulerPolicy` | GPU scheduler policy | `spread` | -| `scheduler.metricsBindAddress` | Metrics bind address | `":9395"` | -| `scheduler.forceOverwriteDefaultScheduler` | Whether to force overwrite default scheduler | `true` | -| `scheduler.livenessProbe` | Whether to enable liveness probe | `false` | -| `scheduler.leaderElect` | Whether to enable leader election | `true` | -| `scheduler.replicas` | Number of replicas | `1` | - -### Kube Scheduler Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `scheduler.kubeScheduler.enabled` | Whether to run kube-scheduler container in scheduler pod | `true` | -| `scheduler.kubeScheduler.image.registry` | Kube scheduler image registry | `"registry.cn-hangzhou.aliyuncs.com"` | -| `scheduler.kubeScheduler.image.repository` | Kube scheduler image repository | `"google_containers/kube-scheduler"` | -| `scheduler.kubeScheduler.image.tag` | Kube scheduler image tag | `""` | -| `scheduler.kubeScheduler.image.pullPolicy` | Kube scheduler image pull policy | `IfNotPresent` | -| `scheduler.kubeScheduler.image.pullSecrets` | Kube scheduler image pull secrets | `[]` | -| `scheduler.kubeScheduler.extraNewArgs` | Extra new arguments | `["--config=/config/config.yaml", "-v=4"]` | -| `scheduler.kubeScheduler.extraArgs` | Extra arguments | `["--policy-config-file=/config/config.json", "-v=4"]` | - -### Extender Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `scheduler.extender.image.registry` | Scheduler extender image registry | `"docker.io"` | -| `scheduler.extender.image.repository` | Scheduler extender image repository | `"projecthami/hami"` | -| `scheduler.extender.image.tag` | Scheduler extender image tag | `""` | -| `scheduler.extender.image.pullPolicy` | Scheduler extender image pull policy | `IfNotPresent` | -| `scheduler.extender.image.pullSecrets` | Scheduler extender image pull secrets | `[]` | -| `scheduler.extender.extraArgs` | Scheduler extender extra arguments | `["--debug", "-v=4"]` | - -### Admission Webhook Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `scheduler.admissionWebhook.enabled` | Whether to enable admission webhook | `true` | -| `scheduler.admissionWebhook.customURL.enabled` | Whether to enable custom URL | `false` | -| `scheduler.admissionWebhook.customURL.host` | Custom URL host | `127.0.0.1` | -| `scheduler.admissionWebhook.customURL.port` | Custom URL port | `31998` | -| `scheduler.admissionWebhook.customURL.path` | Custom URL path | `/webhook` | -| `scheduler.admissionWebhook.reinvocationPolicy` | Reinvocation policy | `Never` | -| `scheduler.admissionWebhook.failurePolicy` | Failure policy | `Ignore` | - -### TLS Certificate Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `scheduler.certManager.enabled` | Whether to use cert-manager to generate self-signed certificates | `false` | -| `scheduler.patch.enabled` | Whether to use kube-webhook-certgen to generate self-signed certificates | `true` | -| `scheduler.patch.image.registry` | Certgen image registry | `"docker.io"` | -| `scheduler.patch.image.repository` | Certgen image repository | `"jettech/kube-webhook-certgen"` | -| `scheduler.patch.image.tag` | Certgen image tag | `"v1.5.2"` | -| `scheduler.patch.image.pullPolicy` | Certgen image pull policy | `IfNotPresent` | -| `scheduler.patch.imageNew.registry` | New certgen image registry | `"docker.io"` | -| `scheduler.patch.imageNew.repository` | New certgen image repository | `"liangjw/kube-webhook-certgen"` | -| `scheduler.patch.imageNew.tag` | New certgen image tag | `"v1.1.1"` | - -### Scheduler Service Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `scheduler.service.type` | Service type | `NodePort` | -| `scheduler.service.httpPort` | HTTP port | `443` | -| `scheduler.service.schedulerPort` | Scheduler NodePort | `31998` | -| `scheduler.service.monitorPort` | Monitor port | `31993` | -| `scheduler.service.monitorTargetPort` | Monitor target port | `9395` | - -## Device Plugin Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devicePlugin.image.registry` | Device plugin image registry | `"docker.io"` | -| `devicePlugin.image.repository` | Device plugin image repository | `"projecthami/hami"` | -| `devicePlugin.image.tag` | Device plugin image tag | `""` | -| `devicePlugin.image.pullPolicy` | Device plugin image pull policy | `IfNotPresent` | -| `devicePlugin.image.pullSecrets` | Device plugin image pull secrets | `[]` | - -### Monitor Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devicePlugin.monitor.image.registry` | Monitor image registry | `"docker.io"` | -| `devicePlugin.monitor.image.repository` | Monitor image repository | `"projecthami/hami"` | -| `devicePlugin.monitor.image.tag` | Monitor image tag | `""` | -| `devicePlugin.monitor.image.pullPolicy` | Monitor image pull policy | `IfNotPresent` | -| `devicePlugin.monitor.image.pullSecrets` | Monitor image pull secrets | `[]` | -| `devicePlugin.monitor.ctrPath` | Container path | `/usr/local/vgpu/containers` | -| `devicePlugin.monitor.extraArgs` | Monitor extra arguments | `["-v=4"]` | -| `devicePlugin.monitor.extraEnvs` | Monitor extra environments | `{}` | - -### Device Plugin Other Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devicePlugin.deviceSplitCount` | Integer type, default value: 10. Maximum number of tasks assigned to a single GPU device | `10` | -| `devicePlugin.deviceMemoryScaling` | Device memory scaling ratio | `1` | -| `devicePlugin.deviceCoreScaling` | Device core scaling ratio | `1` | -| `devicePlugin.runtimeClassName` | Runtime class name | `""` | -| `devicePlugin.createRuntimeClass` | Whether to create runtime class | `false` | -| `devicePlugin.migStrategy` | String type, "none" means ignore MIG functionality, "mixed" means allocate MIG devices through independent resources | `"none"` | -| `devicePlugin.disablecorelimit` | String type, "true" means disable core limit, "false" means enable core limit | `"false"` | -| `devicePlugin.passDeviceSpecsEnabled` | Whether to enable passing device specs | `false` | -| `devicePlugin.extraArgs` | Device plugin extra arguments | `["-v=4"]` | -| `devicePlugin.nodeConfiguration.config` | Node configuration for device plugin by json | An example of default configuration. | -| `devicePlugin.nodeConfiguration.externalConfigName` | Node configuration for device plugin by external congimap | `""` | -| `devicePlugin.extraEnvs` | Device plugin extra environments | `{}` | - -### Device Plugin Service Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devicePlugin.service.type` | Service type | `NodePort` | -| `devicePlugin.service.httpPort` | HTTP port | `31992` | - -### Device Plugin Deployment Configuration - -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devicePlugin.pluginPath` | Plugin path | `/var/lib/kubelet/device-plugins` | -| `devicePlugin.libPath` | Library path | `/usr/local/vgpu` | -| `devicePlugin.nvidiaNodeSelector` | NVIDIA node selector | `{"gpu": "on"}` | -| `devicePlugin.updateStrategy.type` | Update strategy type | `RollingUpdate` | -| `devicePlugin.updateStrategy.rollingUpdate.maxUnavailable` | Maximum unavailable count | `1` | - -## Device Configuration - -### AWS Neuron -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devices.awsneuron.customresources` | Custom resources | `["aws.amazon.com/neuron", "aws.amazon.com/neuroncore"]` | - -### Kunlunxin -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devices.kunlun.enabled` | Whether to enable | `true` | -| `devices.kunlun.customresources` | Custom resources | `["kunlunxin.com/xpu"]` | - -### Mthreads -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devices.mthreads.enabled` | Whether to enable | `true` | -| `devices.mthreads.customresources` | Custom resources | `["mthreads.com/vgpu"]` | - -### NVIDIA -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devices.nvidia.gpuCorePolicy` | GPU core policy | `default` | -| `devices.nvidia.libCudaLogLevel` | CUDA library log level | `1` | - -### Huawei Ascend -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devices.ascend.enabled` | Whether to enable | `false` | -| `devices.ascend.image` | Image | `""` | -| `devices.ascend.imagePullPolicy` | Image pull policy | `IfNotPresent` | -| `devices.ascend.extraArgs` | Extra arguments | `[]` | -| `devices.ascend.nodeSelector` | Node selector | `{"ascend": "on"}` | -| `devices.ascend.tolerations` | Tolerations | `[]` | -| `devices.ascend.customresources` | Custom resources | `["huawei.com/Ascend910A", "huawei.com/Ascend910A-memory", ...]` | - -### Iluvatar -| Parameter | Description | Default Value | -|-----------|-------------|---------------| -| `devices.iluvatar.enabled` | Whether to enable | `false` | -| `devices.iluvatar.customresources` | Custom resources | `["iluvatar.ai/BI-V150-vgpu", "iluvatar.ai/BI-V150.vMem","iluvatar.ai/BI-V150.vCore", ...]` | diff --git a/packages/system/hami/charts/hami/templates/NOTES.txt b/packages/system/hami/charts/hami/templates/NOTES.txt deleted file mode 100644 index 15bb1218..00000000 --- a/packages/system/hami/charts/hami/templates/NOTES.txt +++ /dev/null @@ -1,3 +0,0 @@ -** Please be patient while the chart is being deployed ** -Resource name: {{ .Values.resourceName }} - diff --git a/packages/system/hami/charts/hami/templates/_commons.tpl b/packages/system/hami/charts/hami/templates/_commons.tpl deleted file mode 100644 index b68018e4..00000000 --- a/packages/system/hami/charts/hami/templates/_commons.tpl +++ /dev/null @@ -1,49 +0,0 @@ -{{/* -Return the proper image name -{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} -*/}} -{{- define "common.images.image" -}} -{{- $registryName := .imageRoot.registry -}} -{{- $repositoryName := .imageRoot.repository -}} -{{- $tag := .imageRoot.tag | toString -}} -{{- if .global }} - {{- if .global.imageRegistry }} - {{- $registryName = .global.imageRegistry -}} - {{- end -}} -{{- end -}} -{{- if .tag }} - {{- $tag = .tag | toString -}} -{{- end -}} -{{- if $registryName }} -{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- else -}} -{{- printf "%s:%s" $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) -{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} -*/}} -{{- define "common.images.pullSecrets" -}} - {{- $pullSecrets := list }} - - {{- if .global }} - {{- range .global.imagePullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- range .images -}} - {{- range .pullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- if (not (empty $pullSecrets)) }} -imagePullSecrets: - {{- range $pullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/_helpers.tpl b/packages/system/hami/charts/hami/templates/_helpers.tpl deleted file mode 100644 index ffcc61da..00000000 --- a/packages/system/hami/charts/hami/templates/_helpers.tpl +++ /dev/null @@ -1,163 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "hami-vgpu.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "hami-vgpu.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "hami-vgpu.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* -The app name for Scheduler -*/}} -{{- define "hami-vgpu.scheduler" -}} -{{- printf "%s-scheduler" ( include "hami-vgpu.fullname" . ) | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -The app name for DevicePlugin -*/}} -{{- define "hami-vgpu.device-plugin" -}} -{{- printf "%s-device-plugin" ( include "hami-vgpu.fullname" . ) | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* - The app name for MockDevicePlugin - */}} -{{- define "hami-vgpu.mock-device-plugin" -}} -{{- printf "%s-mock-device-plugin" ( include "hami-vgpu.fullname" . ) | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -The tls secret name for Scheduler -*/}} -{{- define "hami-vgpu.scheduler.tls" -}} -{{- printf "%s-scheduler-tls" ( include "hami-vgpu.fullname" . ) | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -The webhook name -*/}} -{{- define "hami-vgpu.scheduler.webhook" -}} -{{- printf "%s-webhook" ( include "hami-vgpu.fullname" . ) | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "hami-vgpu.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "hami-vgpu.labels" -}} -helm.sh/chart: {{ include "hami-vgpu.chart" . }} -{{ include "hami-vgpu.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "hami-vgpu.selectorLabels" -}} -app.kubernetes.io/name: {{ include "hami-vgpu.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - - -{{/* - Resolve the tag for kubeScheduler. -*/}} -{{- define "resolvedKubeSchedulerTag" -}} -{{- if .Values.scheduler.kubeScheduler.image.tag }} -{{- .Values.scheduler.kubeScheduler.image.tag | trim -}} -{{- else }} -{{- include "strippedKubeVersion" . | trim -}} -{{- end }} -{{- end }} - -{{/* - Return the stripped Kubernetes version string by removing extra parts after semantic version number. - v1.31.1+k3s1 -> v1.31.1 - v1.30.8-eks-2d5f260 -> v1.30.8 - v1.31.1 -> v1.31.1 -*/}} -{{- define "strippedKubeVersion" -}} -{{ regexReplaceAll "^(v[0-9]+\\.[0-9]+\\.[0-9]+)(.*)$" .Capabilities.KubeVersion.Version "$1" }} -{{- end -}} - -{{- define "hami.scheduler.kubeScheduler.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.scheduler.kubeScheduler.image "global" .Values.global "tag" (include "resolvedKubeSchedulerTag" .)) }} -{{- end -}} - -{{- define "hami.scheduler.extender.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.scheduler.extender.image "global" .Values.global "tag" .Values.global.imageTag) }} -{{- end -}} - -{{- define "hami.devicePlugin.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.devicePlugin.image "global" .Values.global "tag" .Values.global.imageTag) }} -{{- end -}} - -{{- define "hami.mockDevicePlugin.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.mockDevicePlugin.image "global" .Values.global "tag" .Values.mockDevicePlugin.tag) }} -{{- end -}} - -{{- define "hami.devicePlugin.monitor.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.devicePlugin.monitor.image "global" .Values.global "tag" .Values.global.imageTag) }} -{{- end -}} - -{{- define "hami.scheduler.patch.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.scheduler.patch.image "global" .Values.global) }} -{{- end -}} - -{{- define "hami.scheduler.patch.new.image" -}} -{{ include "common.images.image" (dict "imageRoot" .Values.scheduler.patch.imageNew "global" .Values.global) }} -{{- end -}} - -{{- define "hami.scheduler.extender.imagePullSecrets" -}} -{{ include "common.images.pullSecrets" (dict "images" (list .Values.scheduler.extender.image) "global" .Values.global) }} -{{- end -}} - -{{- define "hami.devicePlugin.imagePullSecrets" -}} -{{ include "common.images.pullSecrets" (dict "images" (list .Values.devicePlugin.image) "global" .Values.global) }} -{{- end -}} - -{{- define "hami.scheduler.patch.imagePullSecrets" -}} -{{ include "common.images.pullSecrets" (dict "images" (list .Values.scheduler.patch.image) "global" .Values.global) }} -{{- end -}} - -{{- define "hami.scheduler.patch.new.imagePullSecrets" -}} -{{ include "common.images.pullSecrets" (dict "images" (list .Values.scheduler.patch.imageNew) "global" .Values.global) }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/configmap.yaml b/packages/system/hami/charts/hami/templates/device-plugin/configmap.yaml deleted file mode 100644 index 74631e24..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if and .Values.devicePlugin.enabled (not .Values.devicePlugin.nodeConfiguration.externalConfigName) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "hami-vgpu.device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-device-plugin - {{- include "hami-vgpu.labels" . | nindent 4 }} -data: - config.json: | -{{- .Values.devicePlugin.nodeConfiguration.config | nindent 4 }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/daemonsetmock.yaml b/packages/system/hami/charts/hami/templates/device-plugin/daemonsetmock.yaml deleted file mode 100644 index a0dc4ff3..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/daemonsetmock.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if .Values.mockDevicePlugin.enabled }} -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: {{ include "hami-vgpu.mock-device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} -spec: - selector: - matchLabels: - app.kubernetes.io/component: hami-mock-device-plugin - {{- include "hami-vgpu.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: "" - labels: - app.kubernetes.io/component: hami-mock-device-plugin - {{- include "hami-vgpu.selectorLabels" . | nindent 8 }} - spec: - serviceAccountName: {{ include "hami-vgpu.mock-device-plugin" . }} - tolerations: - - key: CriticalAddonsOnly - operator: Exists - containers: - - image: {{ include "hami.mockDevicePlugin.image" . }} - imagePullPolicy: {{ .Values.mockDevicePlugin.image.pullPolicy }} - name: hami-mock-dp-cntr - env: - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - command: - - ./k8s-device-plugin - - -v=5 - - --device-config-file=/device-config.yaml - volumeMounts: - - name: dp - mountPath: /var/lib/kubelet/device-plugins - - name: sys - mountPath: /sys - - name: device-config - mountPath: /device-config.yaml - subPath: device-config.yaml - volumes: - - name: dp - hostPath: - path: /var/lib/kubelet/device-plugins - - name: sys - hostPath: - path: /sys - - name: device-config - configMap: - name: {{ include "hami-vgpu.scheduler" . }}-device -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/daemonsetnvidia.yaml b/packages/system/hami/charts/hami/templates/device-plugin/daemonsetnvidia.yaml deleted file mode 100644 index 1f4c24f3..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/daemonsetnvidia.yaml +++ /dev/null @@ -1,262 +0,0 @@ -{{- if .Values.devicePlugin.enabled }} -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: {{ include "hami-vgpu.device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-device-plugin - {{- include "hami-vgpu.labels" . | nindent 4 }} - {{- with .Values.global.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if .Values.global.annotations }} - annotations: {{ toYaml .Values.global.annotations | nindent 4}} - {{- end }} -spec: - updateStrategy: - {{- with .Values.devicePlugin.updateStrategy }} - {{- toYaml . | nindent 4 }} - {{- end }} - selector: - matchLabels: - app.kubernetes.io/component: hami-device-plugin - {{- include "hami-vgpu.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - app.kubernetes.io/component: hami-device-plugin - hami.io/webhook: ignore - {{- include "hami-vgpu.selectorLabels" . | nindent 8 }} - annotations: - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - checksum/hami-scheduler-newversion-config: {{ include (print $.Template.BasePath "/scheduler/configmapnew.yaml") . | sha256sum }} - {{- else }} - checksum/hami-scheduler-config: {{ include (print $.Template.BasePath "/scheduler/configmap.yaml") . | sha256sum }} - {{- end }} - checksum/hami-scheduler-device-config: {{ include (print $.Template.BasePath "/scheduler/device-configmap.yaml") . | sha256sum }} - {{- if .Values.devicePlugin.podAnnotations }} - {{- toYaml .Values.devicePlugin.podAnnotations | nindent 8 }} - {{- end }} - spec: - {{- if .Values.devicePlugin.runtimeClassName }} - runtimeClassName: {{ .Values.devicePlugin.runtimeClassName }} - {{- end }} - serviceAccountName: {{ include "hami-vgpu.device-plugin" . }} - priorityClassName: system-node-critical - hostPID: true - hostNetwork: true - {{- include "hami.devicePlugin.imagePullSecrets" . | nindent 6 }} - {{- if .Values.devicePlugin.gpuOperatorToolkitReady.enabled }} - initContainers: - - name: toolkit-validation - image: {{ include "hami.devicePlugin.image" . }} - imagePullPolicy: {{ .Values.devicePlugin.image.pullPolicy }} - securityContext: - privileged: true - runAsUser: 0 - command: ["sh", "-c"] - args: - - | - echo "Waiting for NVIDIA Toolkit to be ready..." - until [ -f {{ .Values.devicePlugin.gpuOperatorToolkitReady.hostPath }}/toolkit-ready ]; do - echo "Waiting for {{ .Values.devicePlugin.gpuOperatorToolkitReady.hostPath }}/toolkit-ready..." - sleep 5 - done - echo "NVIDIA Toolkit is ready!" - volumeMounts: - - name: nvidia-validations - mountPath: {{ .Values.devicePlugin.gpuOperatorToolkitReady.hostPath | quote }} - mountPropagation: HostToContainer - readOnly: true - {{- end }} - containers: - - name: device-plugin - image: {{ include "hami.devicePlugin.image" . }} - imagePullPolicy: {{ .Values.devicePlugin.image.pullPolicy }} - lifecycle: - postStart: - exec: - command: ["/bin/sh","-c", {{ printf "/k8s-vgpu/bin/vgpu-init.sh %s/vgpu/" .Values.global.gpuHookPath | quote }}] - command: - - nvidia-device-plugin - - --config-file=/device-config.yaml - - --mig-strategy={{ .Values.devicePlugin.migStrategy }} - - --disable-core-limit={{ .Values.devicePlugin.disablecorelimit }} - {{- range .Values.devicePlugin.extraArgs }} - - {{ . }} - {{- end }} - env: - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: NVIDIA_MIG_MONITOR_DEVICES - value: all - - name: DEVICE_LIST_STRATEGY - value: {{ .Values.devicePlugin.deviceListStrategy }} - - name: HOOK_PATH - value: {{ .Values.global.gpuHookPath }} - {{- if typeIs "bool" .Values.devicePlugin.passDeviceSpecsEnabled }} - - name: PASS_DEVICE_SPECS - value: {{ .Values.devicePlugin.passDeviceSpecsEnabled | quote }} - {{- end }} - {{- if typeIs "string" .Values.devicePlugin.nvidiaDriverRoot }} - - name: NVIDIA_DRIVER_ROOT - value: {{ .Values.devicePlugin.nvidiaDriverRoot }} - {{- end }} - {{- if typeIs "string" .Values.devicePlugin.nvidiaHookPath }} - - name: NVIDIA_CDI_HOOK_PATH - value: {{ .Values.devicePlugin.nvidiaHookPath }} - {{- end }} - {{- if typeIs "bool" .Values.devicePlugin.gdrcopyEnabled }} - - name: GDRCOPY_ENABLED - value: {{ .Values.devicePlugin.gdrcopyEnabled | quote }} - {{- end }} - {{- if typeIs "bool" .Values.devicePlugin.gdsEnabled }} - - name: GDS_ENABLED - value: {{ .Values.devicePlugin.gdsEnabled | quote }} - {{- end }} - {{- if typeIs "bool" .Values.devicePlugin.mofedEnabled }} - - name: MOFED_ENABLED - value: {{ .Values.devicePlugin.mofedEnabled | quote }} - {{- end }} - {{- if eq (.Values.scheduler.defaultSchedulerPolicy.gpuSchedulerPolicy | default "spread") "topology-aware" }} - - name: ENABLE_TOPOLOGY_SCORE - value: "true" - {{- end }} - {{- with .Values.devicePlugin.extraEnvs }} - {{- . | toYaml | nindent 12 }} - {{- end }} - securityContext: - privileged: true - allowPrivilegeEscalation: true - capabilities: - drop: ["ALL"] - add: ["SYS_ADMIN"] - resources: - {{- toYaml .Values.devicePlugin.resources | nindent 12 }} - volumeMounts: - - name: device-plugin - mountPath: /var/lib/kubelet/device-plugins - - name: lib - mountPath: {{ printf "%s%s" .Values.global.gpuHookPath "/vgpu" }} - - name: usrbin - mountPath: /usrbin - - name: deviceconfig - mountPath: /config - - name: hosttmp - mountPath: /tmp - - name: device-config - mountPath: /device-config.yaml - subPath: device-config.yaml - - name: cdi-root - mountPath: /var/run/cdi - {{- if typeIs "string" .Values.devicePlugin.nvidiaDriverRoot }} - # We always mount the driver root at /driver-root in the container. - # This is required for CDI detection to work correctly. - - name: driver-root - mountPath: /driver-root - readOnly: true - {{- end }} - - name: vgpu-monitor - image: {{ include "hami.devicePlugin.monitor.image" . }} - imagePullPolicy: {{ .Values.devicePlugin.monitor.image.pullPolicy }} - command: - - "vGPUmonitor" - {{- range .Values.devicePlugin.monitor.extraArgs }} - - {{ . }} - {{- end }} - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - add: ["SYS_ADMIN"] - env: - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: NVIDIA_VISIBLE_DEVICES - value: "all" - - name: NVIDIA_MIG_MONITOR_DEVICES - value: "all" - - name: HOOK_PATH - value: "{{ .Values.global.gpuHookPath }}/vgpu" - - name: HAMI_RESYNC_INTERVAL - value: {{ .Values.devicePlugin.monitor.resyncInterval | default "5m" | quote }} - {{- with .Values.devicePlugin.monitor.extraEnvs }} - {{- . | toYaml | nindent 12 }} - {{- end }} - resources: - {{- toYaml .Values.devicePlugin.monitor.resources | nindent 12 }} - volumeMounts: - - name: ctrs - mountPath: {{ .Values.devicePlugin.monitor.ctrPath }} - - name: dockers - mountPath: /run/docker - - name: containerds - mountPath: /run/containerd - - name: sysinfo - mountPath: /sysinfo - - name: hostvar - mountPath: /hostvar - - name: hosttmp - mountPath: /tmp - volumes: - - name: ctrs - hostPath: - path: {{ .Values.devicePlugin.monitor.ctrPath }} - - name: hosttmp - hostPath: - path: /tmp - - name: dockers - hostPath: - path: /run/docker - - name: containerds - hostPath: - path: /run/containerd - - name: device-plugin - hostPath: - path: {{ .Values.devicePlugin.pluginPath }} - - name: lib - hostPath: - path: {{ .Values.devicePlugin.libPath }} - {{- if .Values.devicePlugin.gpuOperatorToolkitReady.enabled }} - - name: nvidia-validations - hostPath: - path: {{ .Values.devicePlugin.gpuOperatorToolkitReady.hostPath }} - type: DirectoryOrCreate - {{- end }} - {{- if typeIs "string" .Values.devicePlugin.nvidiaDriverRoot }} - - name: driver-root - hostPath: - path: {{ .Values.devicePlugin.nvidiaDriverRoot }} - type: Directory - {{- end }} - - name: cdi-root - hostPath: - path: /var/run/cdi - type: DirectoryOrCreate - - name: usrbin - hostPath: - path: /usr/bin - - name: sysinfo - hostPath: - path: /sys - - name: hostvar - hostPath: - path: /var - - name: deviceconfig - configMap: - name: {{ .Values.devicePlugin.nodeConfiguration.externalConfigName | default (include "hami-vgpu.device-plugin" .) }} - - name: device-config - configMap: - name: {{ include "hami-vgpu.scheduler" . }}-device - {{- if .Values.devicePlugin.nvidiaNodeSelector }} - nodeSelector: {{ toYaml .Values.devicePlugin.nvidiaNodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.devicePlugin.tolerations }} - tolerations: {{ toYaml .Values.devicePlugin.tolerations | nindent 8 }} - {{- end }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/monitorrole.yaml b/packages/system/hami/charts/hami/templates/device-plugin/monitorrole.yaml deleted file mode 100644 index 6ac757f2..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/monitorrole.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if .Values.devicePlugin.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "hami-vgpu.device-plugin" . }}-monitor -rules: - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - create - - watch - - list - - update - - patch - - apiGroups: - - "" - resources: - - nodes - verbs: - - get - - update - - list - - patch -{{- end -}} - diff --git a/packages/system/hami/charts/hami/templates/device-plugin/monitorrolebinding.yaml b/packages/system/hami/charts/hami/templates/device-plugin/monitorrolebinding.yaml deleted file mode 100644 index 2f0a14ba..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/monitorrolebinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.devicePlugin.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hami-vgpu.device-plugin" . }} - labels: - app.kubernetes.io/component: "hami-device-plugin" - {{- include "hami-vgpu.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "hami-vgpu.device-plugin" . }}-monitor -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/monitorservice.yaml b/packages/system/hami/charts/hami/templates/device-plugin/monitorservice.yaml deleted file mode 100644 index 88f1b214..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/monitorservice.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if .Values.devicePlugin.enabled -}} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "hami-vgpu.device-plugin" . }}-monitor - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-device-plugin - {{- include "hami-vgpu.labels" . | nindent 4 }} - {{- with .Values.devicePlugin.service.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if .Values.devicePlugin.service.annotations }} # Use devicePlugin instead of scheduler - annotations: {{ toYaml .Values.devicePlugin.service.annotations | nindent 4 }} - {{- end }} -spec: - type: {{ .Values.devicePlugin.service.type | default "NodePort" }} # Default type is NodePort - ports: - - name: monitorport - port: {{ .Values.devicePlugin.service.httpPort | default 31992 }} # Default HTTP port is 31992 - targetPort: 9394 - {{- if eq (.Values.devicePlugin.service.type | default "NodePort") "NodePort" }} # If type is NodePort, set nodePort - nodePort: {{ .Values.devicePlugin.service.httpPort | default 31992 }} - {{- end }} - protocol: TCP - selector: - app.kubernetes.io/component: hami-device-plugin - {{- include "hami-vgpu.selectorLabels" . | nindent 4 }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/monitorserviceaccount.yaml b/packages/system/hami/charts/hami/templates/device-plugin/monitorserviceaccount.yaml deleted file mode 100644 index 6e3c2a44..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/monitorserviceaccount.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if .Values.devicePlugin.enabled -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "hami-vgpu.device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: "hami-device-plugin" - {{- include "hami-vgpu.labels" . | nindent 4 }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/device-plugin/runtime-class.yaml b/packages/system/hami/charts/hami/templates/device-plugin/runtime-class.yaml deleted file mode 100644 index ebcc2c9c..00000000 --- a/packages/system/hami/charts/hami/templates/device-plugin/runtime-class.yaml +++ /dev/null @@ -1,9 +0,0 @@ -{{- if and .Values.devicePlugin.enabled .Values.devicePlugin.createRuntimeClass .Values.devicePlugin.runtimeClassName -}} -apiVersion: node.k8s.io/v1 -kind: RuntimeClass -metadata: - name: {{ .Values.devicePlugin.runtimeClassName }} - annotations: - helm.sh/hook: pre-install,pre-upgrade -handler: nvidia -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/scheduler/certmanager.yaml b/packages/system/hami/charts/hami/templates/scheduler/certmanager.yaml deleted file mode 100644 index e6d28721..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/certmanager.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.scheduler.admissionWebhook.enabled -}} -{{- if .Values.scheduler.certManager.enabled }} -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: {{ include "hami-vgpu.scheduler" . }}-serving-cert - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} -spec: - dnsNames: - - {{ include "hami-vgpu.scheduler" . }}.{{ include "hami-vgpu.namespace" . }}.svc - - {{ include "hami-vgpu.scheduler" . }}.{{ include "hami-vgpu.namespace" . }}.svc.cluster.local - issuerRef: - kind: Issuer - name: {{ include "hami-vgpu.scheduler" . }}-selfsigned-issuer - secretName: {{ include "hami-vgpu.scheduler.tls" . }} ---- -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: {{ include "hami-vgpu.scheduler" . }}-selfsigned-issuer - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} -spec: - selfSigned: {} -{{- end }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/clusterrole.yaml b/packages/system/hami/charts/hami/templates/scheduler/clusterrole.yaml deleted file mode 100644 index 81c4fddf..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/clusterrole.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} -rules: - - apiGroups: [""] - resources: ["pods", "configmaps"] - verbs: ["get", "list", "watch", "patch"] - - apiGroups: [""] - resources: ["pods/binding"] - verbs: ["create"] - - apiGroups: [""] - resources: ["nodes"] - verbs: ["get", "list", "patch", "watch"] - - apiGroups: [""] - resources: ["events"] - verbs: ["create", "get", "list"] - - apiGroups: [""] - resources: ["resourcequotas"] - verbs: ["get", "list", "watch"] ---- -{{- if .Values.mockDevicePlugin.enabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "hami-vgpu.mock-device-plugin" . }} -rules: - - apiGroups: [""] - resources: ["nodes"] - verbs: ["get", "update", "list", "patch"] -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/scheduler/clusterrolebinding.yaml b/packages/system/hami/charts/hami/templates/scheduler/clusterrolebinding.yaml deleted file mode 100644 index a81d425c..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/clusterrolebinding.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hami-vgpu.scheduler" . }}-kube - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:kube-scheduler -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hami-vgpu.scheduler" . }}-volume - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:volume-scheduler -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "hami-vgpu.scheduler" . }} -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/configmap.yaml b/packages/system/hami/charts/hami/templates/scheduler/configmap.yaml deleted file mode 100644 index 109ecbce..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/configmap.yaml +++ /dev/null @@ -1,142 +0,0 @@ -{{- if .Values.scheduler.kubeScheduler.enabled -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} -data: - config.json: | - { - "kind": "Policy", - "apiVersion": "v1", - "extenders": [ - { - {{- if .Values.scheduler.admissionWebhook.enabled }} - "urlPrefix": "https://127.0.0.1:443", - "enableHttps": true, - "tlsConfig": { - "insecure": true - }, - {{- else }} - "urlPrefix": "http://127.0.0.1:80", - "enableHttps": false, - {{- end }} - "filterVerb": "filter", - "bindVerb": "bind", - "weight": 1, - "nodeCacheCapable": true, - "httpTimeout": 30000000000, - "managedResources": [ - {{- range .Values.devices.amd.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- if .Values.devices.ascend.enabled }} - {{- range .Values.devices.ascend.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- end }} - {{- if .Values.devices.mthreads.enabled }} - {{- range .Values.devices.mthreads.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- end }} - {{- if .Values.devices.enflame.enabled }} - {{- range .Values.devices.enflame.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- end }} - {{- if .Values.devices.kunlun.enabled }} - {{- range .Values.devices.kunlun.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- end }} - {{- range .Values.devices.awsneuron.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- if .Values.devices.iluvatar.enabled }} - {{- range .Values.devices.iluvatar.customresources }} - { - "name": "{{ . }}", - "ignoredByScheduler": true - }, - {{- end }} - {{- end }} - { - "name": "{{ .Values.resourceName }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.resourceMem }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.resourceCores }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.resourceMemPercentage }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.resourcePriority }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.mluResourceName }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.dcuResourceName }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.dcuResourceMem }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.dcuResourceCores }}", - "ignoredByScheduler": true - }, - { - "name": "metax-tech.com/gpu", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.metaxResourceName }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.metaxResourceCore }}", - "ignoredByScheduler": true - }, - { - "name": "{{ .Values.metaxResourceMem }}", - "ignoredByScheduler": true - } - ], - "ignoreable": false - } - ] - } -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/configmapnew.yaml b/packages/system/hami/charts/hami/templates/scheduler/configmapnew.yaml deleted file mode 100644 index 6f6db097..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/configmapnew.yaml +++ /dev/null @@ -1,102 +0,0 @@ -{{- if .Values.scheduler.kubeScheduler.enabled -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "hami-vgpu.scheduler" . }}-newversion - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} -data: - config.yaml: | - {{- if gt (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 25}} - apiVersion: kubescheduler.config.k8s.io/v1 - {{- else }} - apiVersion: kubescheduler.config.k8s.io/v1beta2 - {{- end }} - kind: KubeSchedulerConfiguration - leaderElection: - leaderElect: false - profiles: - - schedulerName: {{ .Values.schedulerName }} - extenders: - {{- if .Values.scheduler.admissionWebhook.enabled }} - - urlPrefix: "https://127.0.0.1:443" - enableHTTPS: true - tlsConfig: - insecure: true - {{- else }} - - urlPrefix: "http://127.0.0.1:80" - enableHTTPS: false - {{- end }} - filterVerb: filter - bindVerb: bind - nodeCacheCapable: true - weight: 1 - httpTimeout: 30s - managedResources: - - name: {{ .Values.resourceName }} - ignoredByScheduler: true - - name: {{ .Values.resourceMem }} - ignoredByScheduler: true - - name: {{ .Values.resourceCores }} - ignoredByScheduler: true - - name: {{ .Values.resourceMemPercentage }} - ignoredByScheduler: true - - name: {{ .Values.resourcePriority }} - ignoredByScheduler: true - - name: {{ .Values.mluResourceName }} - ignoredByScheduler: true - - name: {{ .Values.dcuResourceName }} - ignoredByScheduler: true - - name: {{ .Values.dcuResourceMem }} - ignoredByScheduler: true - - name: {{ .Values.dcuResourceCores }} - ignoredByScheduler: true - - name: "metax-tech.com/gpu" - ignoredByScheduler: true - - name: {{ .Values.metaxResourceName }} - ignoredByScheduler: true - - name: {{ .Values.metaxResourceCore }} - ignoredByScheduler: true - - name: {{ .Values.metaxResourceMem }} - ignoredByScheduler: true - {{- if .Values.devices.ascend.enabled }} - {{- range .Values.devices.ascend.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} - {{- end }} - {{- if .Values.devices.mthreads.enabled }} - {{- range .Values.devices.mthreads.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} - {{- end }} - {{- if .Values.devices.enflame.enabled }} - {{- range .Values.devices.enflame.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} - {{- end }} - {{- if .Values.devices.kunlun.enabled }} - {{- range .Values.devices.kunlun.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} - {{- end }} - {{- range .Values.devices.awsneuron.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} - {{- if .Values.devices.iluvatar.enabled }} - {{- range .Values.devices.iluvatar.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} - {{- end }} - {{- range .Values.devices.amd.customresources }} - - name: {{ . }} - ignoredByScheduler: true - {{- end }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/deployment.yaml b/packages/system/hami/charts/hami/templates/scheduler/deployment.yaml deleted file mode 100644 index 1d89e189..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/deployment.yaml +++ /dev/null @@ -1,225 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} - {{- with .Values.global.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if .Values.global.annotations }} - annotations: {{ toYaml .Values.global.annotations | nindent 4}} - {{- end }} -spec: - {{- if .Values.scheduler.leaderElect }} - replicas: {{ .Values.scheduler.replicas }} - {{- else }} - replicas: 1 - {{- end }} - selector: - matchLabels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.selectorLabels" . | nindent 8 }} - hami.io/webhook: ignore - annotations: - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - checksum/hami-scheduler-newversion-config: {{ include (print $.Template.BasePath "/scheduler/configmapnew.yaml") . | sha256sum }} - {{- else }} - checksum/hami-scheduler-config: {{ include (print $.Template.BasePath "/scheduler/configmap.yaml") . | sha256sum }} - {{- end }} - checksum/hami-scheduler-device-config: {{ include (print $.Template.BasePath "/scheduler/device-configmap.yaml") . | sha256sum }} - {{- if .Values.scheduler.podAnnotations }} - {{- toYaml .Values.scheduler.podAnnotations | nindent 8 }} - {{- end }} - spec: - serviceAccountName: {{ include "hami-vgpu.scheduler" . }} - priorityClassName: system-node-critical - {{- include "hami.scheduler.extender.imagePullSecrets" . | nindent 6 }} - containers: - {{- if .Values.scheduler.kubeScheduler.enabled }} - - name: kube-scheduler - image: {{ include "hami.scheduler.kubeScheduler.image" . }} - imagePullPolicy: {{ .Values.scheduler.kubeScheduler.image.pullPolicy }} - command: - - kube-scheduler - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - {{- range .Values.scheduler.kubeScheduler.extraNewArgs }} - - {{ . }} - {{- end }} - {{- else }} - - --scheduler-name={{ .Values.schedulerName }} - {{- range .Values.scheduler.kubeScheduler.extraArgs }} - - {{ . }} - {{- end }} - {{- end }} - - --leader-elect={{ .Values.scheduler.leaderElect }} - - --leader-elect-resource-name={{ .Values.schedulerName }} - - --leader-elect-resource-namespace={{ include "hami-vgpu.namespace" . }} - resources: - {{- toYaml .Values.scheduler.kubeScheduler.resources | nindent 12 }} - volumeMounts: - - name: scheduler-config - mountPath: /config - {{- end }} - {{- if .Values.scheduler.livenessProbe }} - livenessProbe: - failureThreshold: 8 - httpGet: - path: /healthz - port: 10259 - scheme: HTTPS - initialDelaySeconds: 10 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 15 - {{- end }} - - name: vgpu-scheduler-extender - image: {{ include "hami.scheduler.extender.image" . }} - imagePullPolicy: {{ .Values.scheduler.extender.image.pullPolicy }} - env: - {{- if .Values.scheduler.nodeLockExpire }} - - name: HAMI_NODELOCK_EXPIRE - value: "{{ .Values.scheduler.nodeLockExpire }}" - {{- end }} - {{- if .Values.global.managedNodeSelectorEnable }} - {{- range $key, $value := .Values.global.managedNodeSelector }} - - name: NODE_SELECTOR_{{ $key | upper | replace "-" "_" }} - value: "{{ $value }}" - {{- end }} - {{- end }} - command: - - scheduler - {{- if .Values.scheduler.admissionWebhook.enabled }} - - --http_bind=0.0.0.0:443 - - --cert_file=/tls/tls.crt - - --key_file=/tls/tls.key - {{- else }} - - --http_bind=0.0.0.0:80 - {{- end }} - - --scheduler-name={{ .Values.schedulerName }} - - --metrics-bind-address={{ .Values.scheduler.metricsBindAddress }} - - --node-scheduler-policy={{ .Values.scheduler.defaultSchedulerPolicy.nodeSchedulerPolicy }} - - --gpu-scheduler-policy={{ .Values.scheduler.defaultSchedulerPolicy.gpuSchedulerPolicy }} - - --force-overwrite-default-scheduler={{ .Values.scheduler.forceOverwriteDefaultScheduler}} - - --device-config-file=/device-config.yaml - - --leader-elect={{ .Values.scheduler.leaderElect }} - - --leader-elect-resource-name={{ .Values.schedulerName }} - - --leader-elect-resource-namespace={{ include "hami-vgpu.namespace" . }} - {{- if .Values.devices.ascend.enabled }} - - --enable-ascend=true - {{- end }} - {{- if .Values.devices.iluvatar.enabled }} - - --enable-iluvatar=true - {{- end }} - {{- if .Values.scheduler.nodeLabelSelector }} - - --node-label-selector={{- $first := true -}} - {{- range $key, $value := .Values.scheduler.nodeLabelSelector -}} - {{- if not $first }},{{ end -}} - {{- $key }}={{ $value -}} - {{- $first = false -}} - {{- end -}} - {{- end }} - {{- range .Values.scheduler.extender.extraArgs }} - - {{ . }} - {{- end }} - ports: - {{- if .Values.scheduler.admissionWebhook.enabled }} - - name: https - containerPort: 443 - protocol: TCP - {{- else }} - - name: http - containerPort: 80 - protocol: TCP - {{- end }} - - name: metrics - containerPort: {{ last (splitList ":" .Values.scheduler.metricsBindAddress) | int }} - protocol: TCP - resources: - {{- toYaml .Values.scheduler.extender.resources | nindent 12 }} - volumeMounts: - - name: device-config - mountPath: /device-config.yaml - subPath: device-config.yaml - {{- if .Values.scheduler.admissionWebhook.enabled }} - - name: tls-config - mountPath: /tls - {{- end }} - {{- if .Values.scheduler.livenessProbe }} - livenessProbe: - httpGet: - path: /healthz - {{- if .Values.scheduler.admissionWebhook.enabled }} - port: https - scheme: HTTPS - {{- else }} - port: http - scheme: HTTP - {{- end }} - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 3 - timeoutSeconds: 5 - {{- end }} - {{- if .Values.scheduler.leaderElect }} - readinessProbe: - httpGet: - path: /readyz - {{- if .Values.scheduler.admissionWebhook.enabled }} - port: https - scheme: HTTPS - {{- else }} - port: http - scheme: HTTP - {{- end }} - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 3 - timeoutSeconds: 5 - {{- end }} - {{- if .Values.scheduler.leaderElect }} - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app.kubernetes.io/component - operator: In - values: - - hami-scheduler - topologyKey: "kubernetes.io/hostname" - {{- end }} - volumes: - {{- if .Values.scheduler.admissionWebhook.enabled }} - - name: tls-config - secret: - secretName: {{ template "hami-vgpu.scheduler.tls" . }} - {{- end }} - {{- if .Values.scheduler.kubeScheduler.enabled }} - - name: scheduler-config - configMap: - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - name: {{ template "hami-vgpu.scheduler" . }}-newversion - {{- else }} - name: {{ template "hami-vgpu.scheduler" . }} - {{- end }} - {{- end }} - - name: device-config - configMap: - name: {{ include "hami-vgpu.scheduler" . }}-device - {{- if .Values.scheduler.nodeSelector }} - nodeSelector: {{ toYaml .Values.scheduler.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.scheduler.tolerations }} - tolerations: {{ toYaml .Values.scheduler.tolerations | nindent 8 }} - {{- end }} - {{- if .Values.scheduler.nodeName }} - nodeName: {{ .Values.scheduler.nodeName }} - {{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/device-configmap.yaml b/packages/system/hami/charts/hami/templates/scheduler/device-configmap.yaml deleted file mode 100644 index 873b813b..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/device-configmap.yaml +++ /dev/null @@ -1,408 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "hami-vgpu.scheduler" . }}-device - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} -data: - device-config.yaml: |- - {{- if .Files.Glob "files/device-config.yaml" }} - {{- .Files.Get "files/device-config.yaml" | nindent 4}} - {{- else }} - nvidia: - resourceCountName: {{ .Values.resourceName }} - resourceMemoryName: {{ .Values.resourceMem }} - resourceMemoryPercentageName: {{ .Values.resourceMemPercentage }} - resourceCoreName: {{ .Values.resourceCores }} - resourcePriorityName: {{ .Values.resourcePriority }} - overwriteEnv: false - defaultMemory: 0 - defaultCores: 0 - defaultGPUNum: 1 - memoryFactor: 1 - deviceSplitCount: {{ .Values.devicePlugin.deviceSplitCount }} - deviceMemoryScaling: {{ .Values.devicePlugin.deviceMemoryScaling }} - deviceCoreScaling: {{ .Values.devicePlugin.deviceCoreScaling }} - gpuCorePolicy: {{ .Values.devices.nvidia.gpuCorePolicy }} - libCudaLogLevel: {{ .Values.devices.nvidia.libCudaLogLevel }} - runtimeClassName: "{{ .Values.devicePlugin.runtimeClassName }}" - knownMigGeometries: - - models: [ "A30" ] - allowedGeometries: - - - - name: 1g.6gb - core: 25 - memory: 6144 - count: 4 - - - - name: 2g.12gb - core: 50 - memory: 12288 - count: 2 - - - - name: 4g.24gb - core: 100 - memory: 24576 - count: 1 - - models: [ "A100-SXM4-40GB", "A100-40GB-PCIe", "A100-PCIE-40GB"] - allowedGeometries: - - - - name: 1g.5gb - core: 14 - memory: 5120 - count: 7 - - - - name: 1g.5gb - core: 14 - memory: 5120 - count: 1 - - name: 2g.10gb - core: 28 - memory: 10240 - count: 3 - - - - name: 3g.20gb - core: 42 - memory: 20480 - count: 2 - - - - name: 7g.40gb - core: 100 - memory: 40960 - count: 1 - - models: [ "A100-SXM4-80GB", "A100-80GB-PCIe", "A100-PCIE-80GB"] - allowedGeometries: - - - - name: 1g.10gb - core: 14 - memory: 10240 - count: 7 - - - - name: 1g.10gb - core: 14 - memory: 10240 - count: 1 - - name: 2g.20gb - core: 28 - memory: 20480 - count: 3 - - - - name: 3g.40gb - core: 42 - memory: 40960 - count: 2 - - - - name: 7g.79gb - core: 100 - memory: 80896 - count: 1 - - models: [ "H100-PCIE-80GB", "H100-SXM5-80GB"] - allowedGeometries: - - - - name: 1g.10gb - core: 14 - memory: 10240 - count: 7 - - - - name: 1g.10gb - core: 14 - memory: 10240 - count: 1 - - name: 2g.20gb - core: 28 - memory: 20480 - count: 3 - - - - name: 3g.40gb - core: 42 - memory: 40960 - count: 2 - - - - name: 7g.80gb - core: 100 - memory: 81920 - count: 1 - - models: [ "H100-PCIE-94GB", "H100-SXM5-94GB"] - allowedGeometries: - - - - name: 1g.12gb - core: 14 - memory: 12288 - count: 7 - - - - name: 1g.12gb - core: 14 - memory: 12288 - count: 1 - - name: 2g.24gb - core: 28 - memory: 24576 - count: 3 - - - - name: 3g.47gb - core: 42 - memory: 48128 - count: 2 - - - - name: 7g.94gb - core: 100 - memory: 96256 - count: 1 - - models: [ "H20", "H100 on GH200"] - allowedGeometries: - - - - name: 1g.12gb - core: 14 - memory: 12288 - count: 7 - - - - name: 1g.12gb - core: 14 - memory: 12288 - count: 1 - - name: 2g.24gb - core: 28 - memory: 24576 - count: 3 - - - - name: 3g.48gb - core: 42 - memory: 49152 - count: 2 - - - - name: 7g.96gb - core: 100 - memory: 98304 - count: 1 - - models: [ "H200 NVL", "H200-SXM5"] - allowedGeometries: - - - - name: 1g.18gb - core: 14 - memory: 18432 - count: 7 - - - - name: 1g.18gb - core: 14 - memory: 18432 - count: 1 - - name: 2g.35gb - core: 28 - memory: 35840 - count: 3 - - - - name: 3g.71gb - core: 42 - memory: 72704 - count: 2 - - - - name: 7g.141gb - core: 100 - memory: 144384 - count: 1 - - models: [ "B200" ] - allowedGeometries: - - - - name: 1g.23gb - core: 14 - memory: 23552 - count: 7 - - - - name: 1g.23gb - core: 14 - memory: 23552 - count: 1 - - name: 2g.45gb - core: 28 - memory: 46080 - count: 3 - - - - name: 3g.90gb - core: 42 - memory: 92160 - count: 2 - - - - name: 7g.180gb - core: 100 - memory: 184320 - count: 1 - cambricon: - resourceCountName: {{ .Values.mluResourceName }} - resourceMemoryName: {{ .Values.mluResourceMem }} - resourceCoreName: {{ .Values.mluResourceCores }} - hygon: - resourceCountName: {{ .Values.dcuResourceName }} - resourceMemoryName: {{ .Values.dcuResourceMem }} - resourceCoreName: {{ .Values.dcuResourceCores }} - memoryFactor: 1 - metax: - resourceCountName: "metax-tech.com/gpu" - resourceVCountName: {{ .Values.metaxResourceName }} - resourceVMemoryName: {{ .Values.metaxResourceMem }} - resourceVCoreName: {{ .Values.metaxResourceCore }} - sgpuTopologyAware: {{ .Values.metaxsGPUTopologyAware }} - enflame: - resourceNameGCU: "enflame.com/gcu" - resourceNameVGCU: {{ .Values.enflameResourceNameVGCU }} - resourceNameVGCUPercentage: {{ .Values.enflameResourceNameVGCUPercentage }} - mthreads: - resourceCountName: "mthreads.com/vgpu" - resourceMemoryName: "mthreads.com/sgpu-memory" - resourceCoreName: "mthreads.com/sgpu-core" - iluvatars: - - chipName: MR-V100 - commonWord: MR-V100 - resourceCountName: iluvatar.ai/MR-V100-vgpu - resourceMemoryName: iluvatar.ai/MR-V100.vMem - resourceCoreName: iluvatar.ai/MR-V100.vCore - - chipName: MR-V50 - commonWord: MR-V50 - resourceCountName: iluvatar.ai/MR-V50-vgpu - resourceMemoryName: iluvatar.ai/MR-V50.vMem - resourceCoreName: iluvatar.ai/MR-V50.vCore - - chipName: BI-V150 - commonWord: BI-V150 - resourceCountName: iluvatar.ai/BI-V150-vgpu - resourceMemoryName: iluvatar.ai/BI-V150.vMem - resourceCoreName: iluvatar.ai/BI-V150.vCore - - chipName: BI-V100 - commonWord: BI-V100 - resourceCountName: iluvatar.ai/BI-V100-vgpu - resourceMemoryName: iluvatar.ai/BI-V100.vMem - resourceCoreName: iluvatar.ai/BI-V100.vCore - kunlun: - resourceCountName: {{ .Values.kunlunResourceName }} - resourceVCountName: {{ .Values.kunlunResourceVCountName }} - resourceVMemoryName: {{ .Values.kunlunResourceVMemoryName }} - awsneuron: - resourceCountName: "aws.amazon.com/neuron" - resourceCoreName: "aws.amazon.com/neuroncore" - amd: - resourceCountName: "amd.com/gpu" - vnpus: - - chipName: 910A - commonWord: Ascend910A - resourceName: huawei.com/Ascend910A - resourceMemoryName: huawei.com/Ascend910A-memory - memoryAllocatable: 32768 - memoryCapacity: 32768 - memoryFactor: 1 - aiCore: 30 - templates: - - name: vir02 - memory: 2184 - aiCore: 2 - - name: vir04 - memory: 4369 - aiCore: 4 - - name: vir08 - memory: 8738 - aiCore: 8 - - name: vir16 - memory: 17476 - aiCore: 16 - - chipName: 910B2 - commonWord: Ascend910B2 - resourceName: huawei.com/Ascend910B2 - resourceMemoryName: huawei.com/Ascend910B2-memory - memoryAllocatable: 65536 - memoryCapacity: 65536 - memoryFactor: 1 - aiCore: 24 - aiCPU: 6 - templates: - - name: vir03_1c_8g - memory: 8192 - aiCore: 3 - aiCPU: 1 - - name: vir06_1c_16g - memory: 16384 - aiCore: 6 - aiCPU: 1 - - name: vir12_3c_32g - memory: 32768 - aiCore: 12 - aiCPU: 3 - - chipName: 910B3 - commonWord: Ascend910B3 - resourceName: huawei.com/Ascend910B3 - resourceMemoryName: huawei.com/Ascend910B3-memory - memoryAllocatable: 65536 - memoryCapacity: 65536 - memoryFactor: 1 - aiCore: 20 - aiCPU: 7 - templates: - - name: vir05_1c_16g - memory: 16384 - aiCore: 5 - aiCPU: 1 - - name: vir10_3c_32g - memory: 32768 - aiCore: 10 - aiCPU: 3 - - chipName: 910B4-1 - commonWord: Ascend910B4-1 - resourceName: huawei.com/Ascend910B4-1 - resourceMemoryName: huawei.com/Ascend910B4-1-memory - memoryAllocatable: 65536 - memoryCapacity: 65536 - memoryFactor: 1 - aiCore: 20 - aiCPU: 7 - templates: - # NOTE: Names of vnpu template for 910B4-1 are fixed by Ascend runtime and must not be changed. - # The memory is used for scheduling so the correct values must be set. - # Template vir05_1c_8g actually provides 16GB memory, - - name: vir05_1c_8g - memory: 16384 - aiCore: 5 - aiCPU: 1 - # Template vir10_3c_16g actually provides 32GB memory - - name: vir10_3c_16g - memory: 32768 - aiCore: 10 - aiCPU: 3 - - chipName: 910B4 - commonWord: Ascend910B4 - resourceName: huawei.com/Ascend910B4 - resourceMemoryName: huawei.com/Ascend910B4-memory - memoryAllocatable: 32768 - memoryCapacity: 32768 - memoryFactor: 1 - aiCore: 20 - aiCPU: 7 - templates: - - name: vir05_1c_8g - memory: 8192 - aiCore: 5 - aiCPU: 1 - - name: vir10_3c_16g - memory: 16384 - aiCore: 10 - aiCPU: 3 - - chipName: 310P3 - commonWord: Ascend310P - resourceName: huawei.com/Ascend310P - resourceMemoryName: huawei.com/Ascend310P-memory - memoryAllocatable: 21527 - memoryCapacity: 24576 - memoryFactor: 1 - aiCore: 8 - aiCPU: 7 - templates: - - name: vir01 - memory: 3072 - aiCore: 1 - aiCPU: 1 - - name: vir02 - memory: 6144 - aiCore: 2 - aiCPU: 2 - - name: vir04 - memory: 12288 - aiCore: 4 - aiCPU: 4 - {{ end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/clusterrole.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/clusterrole.yaml deleted file mode 100644 index 77e891cc..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/clusterrole.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -rules: - - apiGroups: - - admissionregistration.k8s.io - resources: - #- validatingwebhookconfigurations - - mutatingwebhookconfigurations - verbs: - - get - - update -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/clusterrolebinding.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/clusterrolebinding.yaml deleted file mode 100644 index 2b82f926..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "hami-vgpu.fullname" . }}-admission -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.fullname" . }}-admission - namespace: {{ include "hami-vgpu.namespace" . }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/job-createSecret.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/job-createSecret.yaml deleted file mode 100644 index 0e36d95f..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/job-createSecret.yaml +++ /dev/null @@ -1,68 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) -}} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission-create - namespace: {{ include "hami-vgpu.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -spec: - {{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} - # Alpha feature since k8s 1.12 - ttlSecondsAfterFinished: 0 - {{- end }} - template: - metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission-create - {{- if .Values.scheduler.patch.podAnnotations }} - annotations: {{ toYaml .Values.scheduler.patch.podAnnotations | nindent 8 }} - {{- end }} - labels: - {{- include "hami-vgpu.labels" . | nindent 8 }} - app.kubernetes.io/component: admission-webhook - hami.io/webhook: ignore - spec: - {{- if .Values.scheduler.patch.priorityClassName }} - priorityClassName: {{ .Values.scheduler.patch.priorityClassName }} - {{- end }} - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - {{- include "hami.scheduler.patch.new.imagePullSecrets" . | nindent 6 }} - {{- else }} - {{- include "hami.scheduler.patch.imagePullSecrets" . | nindent 6 }} - {{- end }} - containers: - - name: create - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - image: {{ include "hami.scheduler.patch.new.image" . }} - imagePullPolicy: {{ .Values.scheduler.patch.imageNew.pullPolicy }} - {{- else }} - image: {{ include "hami.scheduler.patch.image" . }} - imagePullPolicy: {{ .Values.scheduler.patch.image.pullPolicy }} - {{- end }} - args: - - create - - --cert-name=tls.crt - - --key-name=tls.key - {{- if .Values.scheduler.admissionWebhook.customURL.enabled }} - - --host={{ printf "%s.%s.svc,127.0.0.1,%s" (include "hami-vgpu.scheduler" .) (include "hami-vgpu.namespace" .) .Values.scheduler.admissionWebhook.customURL.host}} - {{- else }} - - --host={{ printf "%s.%s.svc,127.0.0.1" (include "hami-vgpu.scheduler" .) (include "hami-vgpu.namespace" .) }} - {{- end }} - - --namespace={{ include "hami-vgpu.namespace" . }} - - --secret-name={{ include "hami-vgpu.scheduler.tls" . }} - restartPolicy: OnFailure - serviceAccountName: {{ include "hami-vgpu.fullname" . }}-admission - {{- if .Values.scheduler.patch.nodeSelector }} - nodeSelector: {{ toYaml .Values.scheduler.patch.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.scheduler.patch.tolerations }} - tolerations: {{ toYaml .Values.scheduler.patch.tolerations | nindent 8 }} - {{- end }} - securityContext: - runAsNonRoot: true - runAsUser: {{ .Values.scheduler.patch.runAsUser }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/job-patchWebhook.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/job-patchWebhook.yaml deleted file mode 100644 index ce52042c..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/job-patchWebhook.yaml +++ /dev/null @@ -1,63 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) -}} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission-patch - namespace: {{ include "hami-vgpu.namespace" . }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -spec: - {{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} - # Alpha feature since k8s 1.12 - ttlSecondsAfterFinished: 0 - {{- end }} - template: - metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission-patch - {{- if .Values.scheduler.patch.podAnnotations }} - annotations: {{ toYaml .Values.scheduler.patch.podAnnotations | nindent 8 }} - {{- end }} - labels: - {{- include "hami-vgpu.labels" . | nindent 8 }} - app.kubernetes.io/component: admission-webhook - hami.io/webhook: ignore - spec: - {{- if .Values.scheduler.patch.priorityClassName }} - priorityClassName: {{ .Values.scheduler.patch.priorityClassName }} - {{- end }} - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - {{- include "hami.scheduler.patch.new.imagePullSecrets" . | nindent 6 }} - {{- else }} - {{- include "hami.scheduler.patch.imagePullSecrets" . | nindent 6 }} - {{- end }} - containers: - - name: patch - {{- if ge (regexReplaceAll "[^0-9]" .Capabilities.KubeVersion.Minor "" | int) 22 }} - image: {{ include "hami.scheduler.patch.new.image" . }} - imagePullPolicy: {{ .Values.scheduler.patch.imageNew.pullPolicy }} - {{- else }} - image: {{ include "hami.scheduler.patch.image" . }} - imagePullPolicy: {{ .Values.scheduler.patch.image.pullPolicy }} - {{- end }} - args: - - patch - - --webhook-name={{ include "hami-vgpu.scheduler.webhook" . }} - - --namespace={{ include "hami-vgpu.namespace" . }} - - --patch-validating=false - - --secret-name={{ include "hami-vgpu.scheduler.tls" . }} - restartPolicy: OnFailure - serviceAccountName: {{ include "hami-vgpu.fullname" . }}-admission - {{- if .Values.scheduler.patch.nodeSelector }} - nodeSelector: {{ toYaml .Values.scheduler.patch.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.scheduler.patch.tolerations }} - tolerations: {{ toYaml .Values.scheduler.patch.tolerations | nindent 8 }} - {{- end }} - securityContext: - runAsNonRoot: true - runAsUser: {{ .Values.scheduler.patch.runAsUser }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/role.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/role.yaml deleted file mode 100644 index 56682f8e..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/role.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission - namespace: {{ include "hami-vgpu.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -rules: - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - create -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/rolebinding.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/rolebinding.yaml deleted file mode 100644 index 7239b128..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/rolebinding.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission - namespace: {{ include "hami-vgpu.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ include "hami-vgpu.fullname" . }}-admission -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.fullname" . }}-admission - namespace: {{ include "hami-vgpu.namespace" . }} -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/job-patch/serviceaccount.yaml b/packages/system/hami/charts/hami/templates/scheduler/job-patch/serviceaccount.yaml deleted file mode 100644 index 857c6a8d..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/job-patch/serviceaccount.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if and .Values.scheduler.admissionWebhook.enabled (.Values.scheduler.patch.enabled) (not .Values.scheduler.certManager.enabled) }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "hami-vgpu.fullname" . }}-admission - namespace: {{ include "hami-vgpu.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - {{- include "hami-vgpu.labels" . | nindent 4 }} - app.kubernetes.io/component: admission-webhook -{{- end }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/role.yaml b/packages/system/hami/charts/hami/templates/scheduler/role.yaml deleted file mode 100644 index 5f7d7e44..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/role.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} -rules: - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["create", "list", "watch", "get", "update", "patch"] diff --git a/packages/system/hami/charts/hami/templates/scheduler/rolebinding.yaml b/packages/system/hami/charts/hami/templates/scheduler/rolebinding.yaml deleted file mode 100644 index 96e175a1..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/rolebinding.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ include "hami-vgpu.scheduler" . }} -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} ---- -{{- if .Values.mockDevicePlugin.enabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hami-vgpu.mock-device-plugin" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "hami-vgpu.mock-device-plugin" . }} -subjects: - - kind: ServiceAccount - name: {{ include "hami-vgpu.mock-device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/scheduler/service.yaml b/packages/system/hami/charts/hami/templates/scheduler/service.yaml deleted file mode 100644 index d7538fed..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/service.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.labels" . | nindent 4 }} - {{- if .Values.scheduler.service.labels }} - {{ toYaml .Values.scheduler.service.labels | indent 4 }} - {{- end }} - {{- if .Values.scheduler.service.annotations }} - annotations: {{ toYaml .Values.scheduler.service.annotations | nindent 4 }} - {{- end }} -spec: - type: {{ .Values.scheduler.service.type | default "NodePort" }} # Default type is NodePort - ports: - - name: http - port: {{ .Values.scheduler.service.httpPort | default 443 }} # Default HTTP port is 443 - targetPort: {{ .Values.scheduler.service.httpTargetPort | default 443 }} - {{- if eq (.Values.scheduler.service.type | default "NodePort") "NodePort" }} # If type is NodePort, set nodePort - nodePort: {{ .Values.scheduler.service.schedulerPort | default 31998 }} - {{- end }} - protocol: TCP - - name: monitor - port: {{ .Values.scheduler.service.monitorPort | default 31993 }} # Default monitoring port is 31993 - targetPort: {{ .Values.scheduler.service.monitorTargetPort | default 9395 }} - {{- if eq (.Values.scheduler.service.type | default "NodePort") "NodePort" }} # If type is NodePort, set nodePort - nodePort: {{ .Values.scheduler.service.monitorPort | default 31993 }} - {{- end }} - protocol: TCP - selector: - app.kubernetes.io/component: hami-scheduler - {{- include "hami-vgpu.selectorLabels" . | nindent 4 }} diff --git a/packages/system/hami/charts/hami/templates/scheduler/serviceaccount.yaml b/packages/system/hami/charts/hami/templates/scheduler/serviceaccount.yaml deleted file mode 100644 index 0435c003..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/serviceaccount.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - labels: - app.kubernetes.io/component: "hami-scheduler" - {{- include "hami-vgpu.labels" . | nindent 4 }} ---- -{{- if .Values.mockDevicePlugin.enabled }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "hami-vgpu.mock-device-plugin" . }} - namespace: {{ include "hami-vgpu.namespace" . }} -{{- end -}} diff --git a/packages/system/hami/charts/hami/templates/scheduler/webhook.yaml b/packages/system/hami/charts/hami/templates/scheduler/webhook.yaml deleted file mode 100644 index db9f8029..00000000 --- a/packages/system/hami/charts/hami/templates/scheduler/webhook.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- if .Values.scheduler.admissionWebhook.enabled -}} -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - {{- if .Values.scheduler.certManager.enabled }} - annotations: - cert-manager.io/inject-ca-from: {{ include "hami-vgpu.namespace" . }}/{{ include "hami-vgpu.scheduler" . }}-serving-cert - {{- end }} - name: {{ include "hami-vgpu.scheduler.webhook" . }} -webhooks: - - admissionReviewVersions: - - v1beta1 - clientConfig: - {{- if .Values.scheduler.admissionWebhook.customURL.enabled }} - url: https://{{ .Values.scheduler.admissionWebhook.customURL.host}}:{{.Values.scheduler.admissionWebhook.customURL.port}}{{.Values.scheduler.admissionWebhook.customURL.path}} - {{- else }} - service: - name: {{ include "hami-vgpu.scheduler" . }} - namespace: {{ include "hami-vgpu.namespace" . }} - path: /webhook - port: {{ .Values.scheduler.service.httpPort }} - {{- end }} - failurePolicy: {{ .Values.scheduler.admissionWebhook.failurePolicy }} - matchPolicy: Equivalent - name: vgpu.hami.io - namespaceSelector: - matchExpressions: - - key: hami.io/webhook - operator: NotIn - values: - - ignore - {{- if .Values.scheduler.admissionWebhook.whitelistNamespaces }} - - key: kubernetes.io/metadata.name - operator: NotIn - values: - {{- toYaml .Values.scheduler.admissionWebhook.whitelistNamespaces | nindent 10 }} - {{- end }} - objectSelector: - matchExpressions: - - key: hami.io/webhook - operator: NotIn - values: - - ignore - reinvocationPolicy: {{ .Values.scheduler.admissionWebhook.reinvocationPolicy }} - rules: - - apiGroups: - - "" - apiVersions: - - v1 - operations: - - CREATE - resources: - - pods - scope: '*' - sideEffects: None - timeoutSeconds: 10 -{{- end }} diff --git a/packages/system/hami/charts/hami/values.yaml b/packages/system/hami/charts/hami/values.yaml deleted file mode 100644 index 01caca0b..00000000 --- a/packages/system/hami/charts/hami/values.yaml +++ /dev/null @@ -1,455 +0,0 @@ -## @section Global configuration -## @param global.imageRegistry Global Docker image registry -## @param global.imagePullSecrets Global Docker image pull secrets -global: - ## @param global.imageRegistry Global Docker image registry - imageRegistry: "" - ## E.g. - ## imagePullSecrets: - ## - myRegistryKeySecretName - ## @param global.imagePullSecrets Global Docker image pull secrets - imagePullSecrets: [] - imageTag: "v2.8.1" - gpuHookPath: /usr/local - labels: {} - annotations: {} - managedNodeSelectorEnable: false - managedNodeSelector: - usage: "gpu" - -nameOverride: "" -fullnameOverride: "" -namespaceOverride: "" - -#Nvidia GPU Parameters -resourceName: "nvidia.com/gpu" -resourceMem: "nvidia.com/gpumem" -resourceMemPercentage: "nvidia.com/gpumem-percentage" -resourceCores: "nvidia.com/gpucores" -resourcePriority: "nvidia.com/priority" - -#MLU Parameters -mluResourceName: "cambricon.com/vmlu" -mluResourceMem: "cambricon.com/mlu.smlu.vmemory" -mluResourceCores: "cambricon.com/mlu.smlu.vcore" - -#Hygon DCU Parameters -dcuResourceName: "hygon.com/dcunum" -dcuResourceMem: "hygon.com/dcumem" -dcuResourceCores: "hygon.com/dcucores" - -#Metax sGPU Parameters -metaxResourceName: "metax-tech.com/sgpu" -metaxResourceCore: "metax-tech.com/vcore" -metaxResourceMem: "metax-tech.com/vmemory" -metaxsGPUTopologyAware: "false" - -#Enflame VGCU Parameters -enflameResourceNameVGCU: "enflame.com/vgcu" -enflameResourceNameVGCUPercentage: "enflame.com/vgcu-percentage" - -#Kunlun XPU Parameters -kunlunResourceName: "kunlunxin.com/xpu" -kunlunResourceVCountName: "kunlunxin.com/vxpu" -kunlunResourceVMemoryName: "kunlunxin.com/vxpu-memory" - -schedulerName: "hami-scheduler" - -scheduler: - # @param nodeName defines the node name and the nvidia-vgpu-scheduler-scheduler will schedule to the node. - # if we install the nvidia-vgpu-scheduler-scheduler as default scheduler, we need to remove the k8s default - # scheduler pod from the cluster first, we must specify node name to skip the schedule workflow. - nodeName: "" - #nodeLabelSelector: - # "gpu": "on" - overwriteEnv: "false" - defaultSchedulerPolicy: - nodeSchedulerPolicy: binpack - gpuSchedulerPolicy: spread - metricsBindAddress: ":9395" - # If set to false, When Pod.Spec.SchedulerName equals to the const DefaultSchedulerName in k8s.io/api/core/v1 package, webhook will not overwrite it - forceOverwriteDefaultScheduler: true - livenessProbe: false - leaderElect: true - # when leaderElect is true, replicas is available, otherwise replicas is 1. - replicas: 1 - kubeScheduler: - # @param enabled indicate whether to run kube-scheduler container in the scheduler pod, it's true by default. - enabled: true - ## @param image.registry kube scheduler image registry - ## @param image.repository kube scheduler image repository - ## @param image.tag kube scheduler image tag (immutable tags are recommended) - ## @param image.pullPolicy kube scheduler image pull policy - ## @param image.pullSecrets Specify docker-registry secret names as an array - image: - registry: "registry.cn-hangzhou.aliyuncs.com" - repository: "google_containers/kube-scheduler" - tag: "" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - resources: {} - # If you do want to specify resources, uncomment the following lines, adjust them as necessary. - # and remove the curly braces after 'resources:'. -# limits: -# cpu: 1000m -# memory: 1000Mi -# requests: -# cpu: 100m -# memory: 100Mi - extraNewArgs: - - --config=/config/config.yaml - - -v=4 - extraArgs: - - --policy-config-file=/config/config.json - - -v=4 - extender: - ## @param image.registry scheduler extender image registry - ## @param image.repository scheduler extender image repository - ## @param image.tag scheduler extender image tag (immutable tags are recommended) - ## @param image.pullPolicy scheduler extender image pull policy - ## @param image.pullSecrets Specify docker-registry secret names as an array - image: - registry: "docker.io" - repository: "projecthami/hami" - tag: "" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - resources: {} - # If you do want to specify resources, uncomment the following lines, adjust them as necessary, - # and remove the curly braces after 'resources:'. -# limits: -# cpu: 1000m -# memory: 1000Mi -# requests: -# cpu: 100m -# memory: 100Mi - extraArgs: - - --debug - - -v=4 - nodeLockExpire: "5m" - podAnnotations: {} - tolerations: [] - #serviceAccountName: "hami-vgpu-scheduler-sa" - admissionWebhook: - # If set to false, the admission webhook is not installed and any pods that should use HAMi must be - # configured to use the right 'schedulerName' and other device-specific configurations. - enabled: true - customURL: - enabled: false - # must be an endpoint using https. - # should generate host certs here - host: 127.0.0.1 # hostname or ip, can be your node'IP if you want to use https://:/ - port: 31998 - path: /webhook - whitelistNamespaces: - # Specify the namespaces that the webhook will not be applied to. - # - default - # - kube-system - # - istio-system - reinvocationPolicy: Never - failurePolicy: Ignore - ## TLS Certificate Option 1: Use cert-manager to generate self-signed certificate. - ## If enabled, always takes precedence over options 2. - certManager: - enabled: false - ## TLS Certificate Option 2: Use kube-webhook-certgen to generate self-signed certificate. - ## If true and certManager.enabled is false, Helm will automatically create a self-signed cert and secret for you. - patch: - enabled: true - ## @param image.registry scheduler extender image registry - ## @param image.repository scheduler extender image repository - ## @param image.tag scheduler extender image tag (immutable tags are recommended) - ## @param image.pullPolicy scheduler extender image pull policy - ## @param image.pullSecrets Specify docker-registry secret names as an array - image: - registry: "docker.io" - repository: "jettech/kube-webhook-certgen" - tag: "v1.5.2" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## @param image.registry scheduler extender image registry - ## @param image.repository scheduler extender image repository - ## @param image.tag scheduler extender image tag (immutable tags are recommended) - ## @param image.pullPolicy scheduler extender image pull policy - ## @param image.pullSecrets Specify docker-registry secret names as an array - imageNew: - registry: "docker.io" - repository: "liangjw/kube-webhook-certgen" - tag: "v1.1.1" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - priorityClassName: "" - podAnnotations: {} - nodeSelector: {} - tolerations: [] - runAsUser: 2000 - service: - type: NodePort # Default type is NodePort, can be changed to ClusterIP - httpPort: 443 # HTTP port - schedulerPort: 31998 # NodePort for HTTP - monitorPort: 31993 # Monitoring port - monitorTargetPort: 9395 - httpTargetPort: 443 - labels: {} - annotations: {} - -devicePlugin: - enabled: true - gpuOperatorToolkitReady: - enabled: false - hostPath: "/run/nvidia/validations" - ## @param image.registry devicePlugin image registry - ## @param image.repository devicePlugin image repository - ## @param image.tag devicePlugin image tag (immutable tags are recommended) - ## @param image.pullPolicy devicePlugin image pull policy - ## @param image.pullSecrets Specify docker-registry secret names as an array - image: - registry: "docker.io" - repository: "projecthami/hami" - tag: "" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - monitor: - ## @param image.registry monitor image registry - ## @param image.repository monitor image repository - ## @param image.tag monitor image tag (immutable tags are recommended) - ## @param image.pullPolicy monitor image pull policy - ## @param image.pullSecrets Specify docker-registry secret names as an array - image: - registry: "docker.io" - repository: "projecthami/hami" - tag: "" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ctrPath: /usr/local/vgpu/containers - resyncInterval: "5m" - extraArgs: - - -v=4 - extraEnvs: {} - resources: {} - # If you do want to specify resources, uncomment the following lines, adjust them as necessary. - # and remove the curly braces after 'resources:'. -# limits: -# cpu: 1000m -# memory: 1000Mi -# requests: -# cpu: 100m -# memory: 100Mi - - deviceSplitCount: 10 - deviceMemoryScaling: 1 - deviceCoreScaling: 1 - # Node configuration for device plugin, Priority: externalConfigName > config > default config - nodeConfiguration: - # If you want to use a custom config.json, you can set the content here. - # If this is set, it will override the default config.json(An example is as follows). - config: | - { - "nodeconfig": [ - { - "name": "your-node-name", - "operatingmode": "hami-core", - "devicememoryscaling": 1, - "devicesplitcount": 10, - "migstrategy": "none", - "filterdevices": { - "uuid": [], - "index": [] - } - } - ] - } - # If you want to use an existing ConfigMap, you can set the name here. - # If this is set, the chart will not create the ConfigMap and will use the existing one. - externalConfigName: "" - # The runtime class name to be used by the device plugin, and added to the pod.spec.runtimeClassName of applications utilizing NVIDIA GPUs - runtimeClassName: "" - # Whether to create runtime class, name comes from runtimeClassName when it is set - createRuntimeClass: false - migStrategy: "none" - disablecorelimit: "false" - passDeviceSpecsEnabled: false - deviceListStrategy: "envvar" - nvidiaHookPath: null - nvidiaDriverRoot: null - gdrcopyEnabled: null - gdsEnabled: null - mofedEnabled: null - - extraArgs: - - -v=4 - extraEnvs: {} - service: - type: NodePort # Default type is NodePort, can be changed to ClusterIP - httpPort: 31992 - labels: {} - annotations: {} - - pluginPath: /var/lib/kubelet/device-plugins - libPath: /usr/local/vgpu - - podAnnotations: {} - nvidiaNodeSelector: - gpu: "on" - tolerations: [] - # The updateStrategy for DevicePlugin DaemonSet. - # If you want to update the DaemonSet by manual, set type as "OnDelete". - # We recommend use OnDelete update strategy because DevicePlugin pod restart will cause business pod restart, this behavior is destructive. - # Otherwise, you can use RollingUpdate update strategy to rolling update DevicePlugin pod. - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxUnavailable: 1 - - resources: {} - # If you do want to specify resources, uncomment the following lines, adjust them as necessary. - # and remove the curly braces after 'resources:'. -# limits: -# cpu: 1000m -# memory: 1000Mi -# requests: -# cpu: 100m -# memory: 100Mi - -mockDevicePlugin: - enabled: false - image: - registry: "docker.io" - repository: "projecthami/mock-device-plugin" - tag: "1.0.1" - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] -devices: - amd: - customresources: - - amd.com/gpu - - amd.com/gpu-memory - awsneuron: - customresources: - - aws.amazon.com/neuron - - aws.amazon.com/neuroncore - kunlun: - enabled: true - customresources: - - kunlunxin.com/xpu - - kunlunxin.com/vxpu - - kunlunxin.com/vxpu-memory - enflame: - enabled: true - customresources: - - enflame.com/vgcu - - enflame.com/vgcu-percentage - - enflame.com/gcu - mthreads: - enabled: true - customresources: - - mthreads.com/vgpu - nvidia: - gpuCorePolicy: default - libCudaLogLevel: 1 - ascend: - enabled: false - image: "" - imagePullPolicy: IfNotPresent - extraArgs: [] - nodeSelector: - ascend: "on" - tolerations: [] - customresources: - - huawei.com/Ascend910A - - huawei.com/Ascend910A-memory - - huawei.com/Ascend910B2 - - huawei.com/Ascend910B2-memory - - huawei.com/Ascend910B3 - - huawei.com/Ascend910B3-memory - - huawei.com/Ascend910B4 - - huawei.com/Ascend910B4-memory - - huawei.com/Ascend910B4-1 - - huawei.com/Ascend910B4-1-memory - - huawei.com/Ascend310P - - huawei.com/Ascend310P-memory - iluvatar: - enabled: false - customresources: - - iluvatar.ai/BI-V100-vgpu - - iluvatar.ai/BI-V100.vCore - - iluvatar.ai/BI-V100.vMem - - iluvatar.ai/BI-V150-vgpu - - iluvatar.ai/BI-V150.vCore - - iluvatar.ai/BI-V150.vMem - - iluvatar.ai/MR-V100-vgpu - - iluvatar.ai/MR-V100.vCore - - iluvatar.ai/MR-V100.vMem - - iluvatar.ai/MR-V50-vgpu - - iluvatar.ai/MR-V50.vCore - - iluvatar.ai/MR-V50.vMem diff --git a/packages/system/hami/values.yaml b/packages/system/hami/values.yaml deleted file mode 100644 index 76e8d631..00000000 --- a/packages/system/hami/values.yaml +++ /dev/null @@ -1,17 +0,0 @@ -hami: - scheduler: - kubeScheduler: - image: - registry: registry.k8s.io - repository: kube-scheduler - devicePlugin: - runtimeClassName: nvidia - updateStrategy: - type: RollingUpdate - # See https://github.com/Project-HAMi/HAMi/blob/v2.8.1/deployments/charts/hami/values.yaml - # Each entry: {"name": "node-name", "operatingmode": "hami-core", "devicesplitcount": N, ...} - nodeConfiguration: - config: | - { - "nodeconfig": [] - } diff --git a/packages/system/harbor-rd/cozyrds/harbor.yaml b/packages/system/harbor-rd/cozyrds/harbor.yaml index 5682c053..5abc725f 100644 --- a/packages/system/harbor-rd/cozyrds/harbor.yaml +++ b/packages/system/harbor-rd/cozyrds/harbor.yaml @@ -13,6 +13,7 @@ spec: prefix: "harbor-" labels: sharding.fluxcd.io/key: tenants + internal.cozystack.io/tenantmodule: "true" chartRef: kind: ExternalArtifact name: cozystack-harbor-application-default-harbor @@ -23,6 +24,7 @@ spec: plural: Harbor name: harbor description: Managed Harbor container registry + module: true tags: - registry - container diff --git a/packages/system/hetzner-robotlb/charts/robotlb/Chart.yaml b/packages/system/hetzner-robotlb/charts/robotlb/Chart.yaml index 192470dd..743f255d 100644 --- a/packages/system/hetzner-robotlb/charts/robotlb/Chart.yaml +++ b/packages/system/hetzner-robotlb/charts/robotlb/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 0.0.6 +appVersion: 0.0.5 description: A Helm chart for robotlb (loadbalancer on hetzner cloud). name: robotlb type: application diff --git a/packages/system/hetzner-robotlb/charts/robotlb/templates/deployment.yaml b/packages/system/hetzner-robotlb/charts/robotlb/templates/deployment.yaml index 41b4661a..4fd71366 100644 --- a/packages/system/hetzner-robotlb/charts/robotlb/templates/deployment.yaml +++ b/packages/system/hetzner-robotlb/charts/robotlb/templates/deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: {{- include "robotlb.labels" . | nindent 4 }} spec: - replicas: 1 + replicas: {{ .Values.replicas }} selector: matchLabels: {{- include "robotlb.selectorLabels" . | nindent 6 }} diff --git a/packages/system/hetzner-robotlb/charts/robotlb/templates/role.yaml b/packages/system/hetzner-robotlb/charts/robotlb/templates/role.yaml index 76bac249..3a7b9334 100644 --- a/packages/system/hetzner-robotlb/charts/robotlb/templates/role.yaml +++ b/packages/system/hetzner-robotlb/charts/robotlb/templates/role.yaml @@ -3,8 +3,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: {{ include "robotlb.fullname" . }}-cr -rules: - {{- toYaml .Values.serviceAccount.permissions | nindent 2 }} +rules: {{- toYaml .Values.serviceAccount.permissions | nindent 2 }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding diff --git a/packages/system/hetzner-robotlb/charts/robotlb/values.yaml b/packages/system/hetzner-robotlb/charts/robotlb/values.yaml index 4365f677..739c7b73 100644 --- a/packages/system/hetzner-robotlb/charts/robotlb/values.yaml +++ b/packages/system/hetzner-robotlb/charts/robotlb/values.yaml @@ -36,9 +36,6 @@ serviceAccount: - apiGroups: [""] resources: [nodes, pods] verbs: [get, list, watch] - - apiGroups: [discovery.k8s.io] - resources: [endpointslices] - verbs: [get, list, watch] podAnnotations: {} podLabels: {} diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml index 6ba649f0..b1ca3cb7 100644 --- a/packages/system/kamaji/values.yaml +++ b/packages/system/kamaji/values.yaml @@ -3,37 +3,14 @@ kamaji: deploy: false image: pullPolicy: IfNotPresent - tag: v1.3.0@sha256:8c9af083b60600c0800eb56a2cda75f26007b7272a1cf019140de003bfce1a4d + tag: v1.3.0-rc.1@sha256:8c9af083b60600c0800eb56a2cda75f26007b7272a1cf019140de003bfce1a4d repository: ghcr.io/cozystack/cozystack/kamaji resources: limits: cpu: 200m - memory: 512Mi + memory: 500Mi requests: cpu: 100m - memory: 256Mi - startupProbe: - httpGet: - path: /healthz - port: healthcheck - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 3 - successThreshold: 1 - failureThreshold: 12 - livenessProbe: - httpGet: - path: /healthz - port: healthcheck - initialDelaySeconds: 30 - periodSeconds: 20 - timeoutSeconds: 1 - readinessProbe: - httpGet: - path: /readyz - port: healthcheck - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 1 + memory: 100Mi extraArgs: - - --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.3.0@sha256:8c9af083b60600c0800eb56a2cda75f26007b7272a1cf019140de003bfce1a4d + - --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.3.0-rc.1@sha256:8c9af083b60600c0800eb56a2cda75f26007b7272a1cf019140de003bfce1a4d diff --git a/packages/system/keycloak/templates/ingress.yaml b/packages/system/keycloak/templates/ingress.yaml index 7f9fd476..aa282f71 100644 --- a/packages/system/keycloak/templates/ingress.yaml +++ b/packages/system/keycloak/templates/ingress.yaml @@ -11,7 +11,7 @@ metadata: {{- with .Values.ingress.annotations }} annotations: {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $exposeIngress }} + acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }} {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} {{- toYaml . | nindent 4 }} diff --git a/packages/system/kubeovn-plunger/templates/deployment.yaml b/packages/system/kubeovn-plunger/templates/deployment.yaml index 37b49620..183e8c5e 100644 --- a/packages/system/kubeovn-plunger/templates/deployment.yaml +++ b/packages/system/kubeovn-plunger/templates/deployment.yaml @@ -29,8 +29,6 @@ spec: {{- end }} - --metrics-bind-address=:8080 - --metrics-secure=false - - --kube-ovn-namespace={{ .Release.Namespace }} - - --ovn-central-name={{ .Values.ovnCentralName }} ports: - name: metrics containerPort: 8080 diff --git a/packages/system/kubeovn-plunger/templates/rbac.yaml b/packages/system/kubeovn-plunger/templates/rbac.yaml index 3ca22740..a0c5527b 100644 --- a/packages/system/kubeovn-plunger/templates/rbac.yaml +++ b/packages/system/kubeovn-plunger/templates/rbac.yaml @@ -22,6 +22,8 @@ rules: - get - list - watch + resourceNames: + - {{ .Values.ovnCentralName }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/system/kubeovn-plunger/values.yaml b/packages/system/kubeovn-plunger/values.yaml index 02620593..a6946967 100644 --- a/packages/system/kubeovn-plunger/values.yaml +++ b/packages/system/kubeovn-plunger/values.yaml @@ -1,4 +1,4 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.3.0@sha256:b75a0facb99c3b0fe8090414b3425f5c4858fff632d1de122ce9944c4daa89c0 +image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.3.0-rc.1@sha256:4819095c5237239b8e2282ed1710141a327b3e97773f598f983a22ec0f5add05 ovnCentralName: ovn-central diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index 0c6ce81a..24d75d95 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.3.0@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.3.0-rc.1@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a diff --git a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml index 9c01c123..f0295b87 100644 --- a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml @@ -15,12 +15,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: v1.15.10 +version: v1.15.3 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.15.10" +appVersion: "1.15.3" kubeVersion: ">= 1.29.0-0" diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml index 62ae328e..5b093be6 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml @@ -1353,77 +1353,6 @@ spec: type: string type: object type: array - resources: - description: |- - `resources` are the compute resources required by this container. - For more information, see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - - This field depends on the DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - bandwidth: - type: object - description: Optional bandwidth limit for each egress gateway instance in both ingress and egress directions. - properties: - ingress: - type: integer - format: int64 - description: ingress bandwidth limit in Mbps - egress: - type: integer - format: int64 - description: egress bandwidth limit in Mbps --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml index 06971d01..8be8eba6 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml @@ -126,9 +126,6 @@ spec: - --enable-ovn-ipsec={{- .Values.func.ENABLE_OVN_IPSEC }} - --set-vxlan-tx-off={{- .Values.func.SET_VXLAN_TX_OFF }} - --non-primary-cni-mode={{- .Values.cni_conf.NON_PRIMARY_CNI }} - {{- with .Values.mtu }} - - --mtu={{ . }} - {{- end }} securityContext: runAsUser: 0 privileged: false diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/pre-upgrade-ovs-ovn.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/pre-upgrade-ovs-ovn.yaml deleted file mode 100644 index a18a4111..00000000 --- a/packages/system/kubeovn/charts/kube-ovn/templates/pre-upgrade-ovs-ovn.yaml +++ /dev/null @@ -1,129 +0,0 @@ -{{- if include "kubeovn.ovn.versionCompatibility" . -}} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: ovs-ovn-pre-upgrade - namespace: {{ .Values.namespace }} - annotations: - "helm.sh/hook": pre-upgrade - "helm.sh/hook-weight": "1" - "helm.sh/hook-delete-policy": hook-succeeded -automountServiceAccountToken: false ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - annotations: - rbac.authorization.k8s.io/system-only: "true" - "helm.sh/hook": pre-upgrade - "helm.sh/hook-weight": "2" - "helm.sh/hook-delete-policy": hook-succeeded - name: system:ovs-ovn-pre-upgrade -rules: - - apiGroups: - - "" - resources: - - pods - verbs: - - list - - get - - apiGroups: - - "" - resources: - - pods/exec - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: ovs-ovn-pre-upgrade - annotations: - "helm.sh/hook": pre-upgrade - "helm.sh/hook-weight": "3" - "helm.sh/hook-delete-policy": hook-succeeded -roleRef: - name: system:ovs-ovn-pre-upgrade - kind: ClusterRole - apiGroup: rbac.authorization.k8s.io -subjects: - - kind: ServiceAccount - name: ovs-ovn-pre-upgrade - namespace: {{ .Values.namespace }} ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{ .Chart.Name }}-pre-upgrade-hook" - namespace: {{ .Values.namespace }} - labels: - app.kubernetes.io/managed-by: {{ .Release.Service | quote }} - app.kubernetes.io/instance: {{ .Release.Name | quote }} - app.kubernetes.io/version: {{ .Chart.AppVersion }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - annotations: - "helm.sh/hook": pre-upgrade - "helm.sh/hook-weight": "4" - "helm.sh/hook-delete-policy": hook-succeeded -spec: - completions: 1 - template: - metadata: - name: "{{ .Release.Name }}" - labels: - app.kubernetes.io/managed-by: {{ .Release.Service | quote }} - app.kubernetes.io/instance: {{ .Release.Name | quote }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - app: pre-upgrade - component: job - spec: - tolerations: - - key: "" - operator: "Exists" - effect: "NoSchedule" - affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - topologyKey: kubernetes.io/hostname - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - pre-upgrade - - key: component - operator: In - values: - - job - restartPolicy: Never - hostNetwork: true - nodeSelector: - kubernetes.io/os: "linux" - serviceAccountName: ovs-ovn-pre-upgrade - automountServiceAccountToken: true - securityContext: - seccompProfile: - type: RuntimeDefault - containers: - - name: ovs-ovn-pre-upgrade - image: "{{ .Values.global.registry.address}}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}" - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - command: - - bash - - -eo - - pipefail - - -c - - bash /kube-ovn/pre-upgrade-ovs.sh 2>&1 | tee -a /var/log/kube-ovn/pre-upgrade-ovs.log - volumeMounts: - - mountPath: /var/log/kube-ovn - name: kube-ovn-log - volumes: - - name: kube-ovn-log - hostPath: - path: {{ .Values.log_conf.LOG_DIR }}/kube-ovn -{{- end -}} diff --git a/packages/system/kubeovn/charts/kube-ovn/values.yaml b/packages/system/kubeovn/charts/kube-ovn/values.yaml index fd3472f6..3ffb7750 100644 --- a/packages/system/kubeovn/charts/kube-ovn/values.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/values.yaml @@ -8,11 +8,11 @@ global: images: kubeovn: repository: kube-ovn - tag: v1.15.10 + tag: v1.15.3 natgateway: repository: vpc-nat-gateway # Falls back to the same tag as kubeovn if empty - tag: v1.15.10 + tag: v1.15.3 image: pullPolicy: IfNotPresent diff --git a/packages/system/kubeovn/values.yaml b/packages/system/kubeovn/values.yaml index e9d2d10f..6911f8aa 100644 --- a/packages/system/kubeovn/values.yaml +++ b/packages/system/kubeovn/values.yaml @@ -65,4 +65,4 @@ global: images: kubeovn: repository: kubeovn - tag: v1.15.10@sha256:741299cbd0081a786a6b60c460fa3156b3a42a38141c559dd8ac031f50c5504f + tag: v1.15.3@sha256:fa53d5f254f640cb626329ad35d9e7aad647dd8e1e645e68f3f13c3659472a30 diff --git a/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml b/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml index f81eaff0..5e9e8f94 100644 --- a/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml +++ b/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml @@ -2,27 +2,13 @@ apiVersion: cozystack.io/v1alpha1 kind: ApplicationDefinition metadata: name: kubernetes - annotations: - # Kubernetes tenants boot a Kamaji control plane whose admin-kubeconfig - # Secret is provisioned asynchronously. Cold Kamaji start (image pull + - # etcd + apiserver Ready) plus admin-kubeconfig generation can exceed - # Flux helm-controller's default wait budget, causing remediation loops - # that uninstall the Cluster CR. This override is applied by cozystack-api - # to the HelmRelease Spec.Install.Timeout and Spec.Upgrade.Timeout. - # - # Coupling: the wait-for-kubeconfig init container in - # packages/apps/kubernetes/templates/_helpers.tpl hard-codes a 10m - # deadline chosen to stay strictly below this value so the pod's - # CrashLoopBackOff surfaces before flux remediation fires. If this - # annotation is raised, update that init deadline correspondingly. - release.cozystack.io/helm-install-timeout: "15m" spec: application: kind: Kubernetes singular: kubernetes plural: kuberneteses openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated"},"nodeGroups":{"description":"Worker nodes configuration map.","type":"object","default":{"md0":{"ephemeralStorage":"20Gi","gpus":[],"instanceType":"u1.medium","maxReplicas":10,"minReplicas":0,"resources":{},"roles":["ingress-nginx"]}},"additionalProperties":{"type":"object","required":["ephemeralStorage","instanceType","maxReplicas","minReplicas","resources"],"properties":{"ephemeralStorage":{"description":"Ephemeral storage size.","default":"20Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"gpus":{"description":"List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).","type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"description":"Name of GPU, such as \"nvidia.com/AD102GL_L40S\".","type":"string"}}}},"instanceType":{"description":"Virtual machine instance type.","type":"string","default":"u1.medium"},"maxReplicas":{"description":"Maximum number of replicas.","type":"integer","default":10},"minReplicas":{"description":"Minimum number of replicas.","type":"integer","default":0},"resources":{"description":"CPU and memory resources for each worker node.","type":"object","properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"roles":{"description":"List of node roles.","type":"array","items":{"type":"string"}}}}},"version":{"description":"Kubernetes major.minor version to deploy","type":"string","default":"v1.35","enum":["v1.35","v1.34","v1.33","v1.32","v1.31","v1.30"]},"host":{"description":"External hostname for Kubernetes cluster. Defaults to `.` if empty.","type":"string","default":""},"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"required":["certManager","cilium","coredns","fluxcd","gatewayAPI","gpuOperator","hami","ingressNginx","monitoringAgents","velero","verticalPodAutoscaler"],"properties":{"certManager":{"description":"Cert-manager addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable cert-manager.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"cilium":{"description":"Cilium CNI plugin.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"coredns":{"description":"CoreDNS addon.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"fluxcd":{"description":"FluxCD GitOps operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable FluxCD.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"gatewayAPI":{"description":"Gateway API addon.","type":"object","default":{},"required":["enabled"],"properties":{"enabled":{"description":"Enable Gateway API.","type":"boolean","default":false}}},"gpuOperator":{"description":"NVIDIA GPU Operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable GPU Operator.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"hami":{"description":"HAMi GPU virtualization middleware.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable HAMi (requires GPU Operator).","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"ingressNginx":{"description":"Ingress-NGINX controller.","type":"object","default":{},"required":["enabled","exposeMethod","valuesOverride"],"properties":{"enabled":{"description":"Enable the controller (requires nodes labeled `ingress-nginx`).","type":"boolean","default":false},"exposeMethod":{"description":"Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.","type":"string","default":"Proxied","enum":["Proxied","LoadBalancer"]},"hosts":{"description":"Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.","type":"array","default":[],"items":{"type":"string"}},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"monitoringAgents":{"description":"Monitoring agents.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable monitoring agents.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"velero":{"description":"Velero backup/restore addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable Velero.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"verticalPodAutoscaler":{"description":"Vertical Pod Autoscaler.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}}}},"controlPlane":{"description":"Kubernetes control-plane configuration.","type":"object","default":{},"required":["apiServer","controllerManager","konnectivity","replicas","scheduler"],"properties":{"apiServer":{"description":"API Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for API Server.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"large","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"controllerManager":{"description":"Controller Manager configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Controller Manager.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"konnectivity":{"description":"Konnectivity configuration.","type":"object","default":{},"required":["server"],"properties":{"server":{"description":"Konnectivity Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Konnectivity.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"replicas":{"description":"Number of control-plane replicas.","type":"integer","default":2},"scheduler":{"description":"Scheduler configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Scheduler.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"images":{"description":"Optional image overrides for air-gapped or rate-limited registries.","type":"object","default":{},"properties":{"waitForKubeconfig":{"description":"Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag.","type":"string","default":""}}}}} + {"title":"Chart Values","type":"object","properties":{"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated"},"nodeGroups":{"description":"Worker nodes configuration map.","type":"object","default":{"md0":{"ephemeralStorage":"20Gi","gpus":[],"instanceType":"u1.medium","maxReplicas":10,"minReplicas":0,"resources":{},"roles":["ingress-nginx"]}},"additionalProperties":{"type":"object","required":["ephemeralStorage","instanceType","maxReplicas","minReplicas","resources"],"properties":{"ephemeralStorage":{"description":"Ephemeral storage size.","default":"20Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"gpus":{"description":"List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).","type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"description":"Name of GPU, such as \"nvidia.com/AD102GL_L40S\".","type":"string"}}}},"instanceType":{"description":"Virtual machine instance type.","type":"string","default":"u1.medium"},"maxReplicas":{"description":"Maximum number of replicas.","type":"integer","default":10},"minReplicas":{"description":"Minimum number of replicas.","type":"integer","default":0},"resources":{"description":"CPU and memory resources for each worker node.","type":"object","properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"roles":{"description":"List of node roles.","type":"array","items":{"type":"string"}}}}},"version":{"description":"Kubernetes major.minor version to deploy","type":"string","default":"v1.35","enum":["v1.35","v1.34","v1.33","v1.32","v1.31","v1.30"]},"host":{"description":"External hostname for Kubernetes cluster. Defaults to `.` if empty.","type":"string","default":""},"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"required":["certManager","cilium","coredns","fluxcd","gatewayAPI","gpuOperator","ingressNginx","monitoringAgents","velero","verticalPodAutoscaler"],"properties":{"certManager":{"description":"Cert-manager addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable cert-manager.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"cilium":{"description":"Cilium CNI plugin.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"coredns":{"description":"CoreDNS addon.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"fluxcd":{"description":"FluxCD GitOps operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable FluxCD.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"gatewayAPI":{"description":"Gateway API addon.","type":"object","default":{},"required":["enabled"],"properties":{"enabled":{"description":"Enable Gateway API.","type":"boolean","default":false}}},"gpuOperator":{"description":"NVIDIA GPU Operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable GPU Operator.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"ingressNginx":{"description":"Ingress-NGINX controller.","type":"object","default":{},"required":["enabled","exposeMethod","valuesOverride"],"properties":{"enabled":{"description":"Enable the controller (requires nodes labeled `ingress-nginx`).","type":"boolean","default":false},"exposeMethod":{"description":"Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.","type":"string","default":"Proxied","enum":["Proxied","LoadBalancer"]},"hosts":{"description":"Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.","type":"array","default":[],"items":{"type":"string"}},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"monitoringAgents":{"description":"Monitoring agents.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable monitoring agents.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"velero":{"description":"Velero backup/restore addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable Velero.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"verticalPodAutoscaler":{"description":"Vertical Pod Autoscaler.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}}}},"controlPlane":{"description":"Kubernetes control-plane configuration.","type":"object","default":{},"required":["apiServer","controllerManager","konnectivity","replicas","scheduler"],"properties":{"apiServer":{"description":"API Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for API Server.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"large","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"controllerManager":{"description":"Controller Manager configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Controller Manager.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"konnectivity":{"description":"Konnectivity configuration.","type":"object","default":{},"required":["server"],"properties":{"server":{"description":"Konnectivity Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Konnectivity.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"replicas":{"description":"Number of control-plane replicas.","type":"integer","default":2},"scheduler":{"description":"Scheduler configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Scheduler.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}}}} release: prefix: kubernetes- labels: @@ -40,7 +26,7 @@ spec: tags: - compute icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODFfMjg0NSkiLz4KPHBhdGggZD0iTTcxLjk5NjggMTlDNzAuMzAzOSAxOS4wMDAyIDY4LjkzMTIgMjAuNTMyMiA2OC45MzE0IDIyLjQyMjFDNjguOTMxNCAyMi40NTExIDY4LjkzNzMgMjIuNDc4OCA2OC45Mzc5IDIyLjUwNzZDNjguOTM1NCAyMi43NjQ0IDY4LjkyMzEgMjMuMDczNyA2OC45MzE0IDIzLjI5NzNDNjguOTcxNyAyNC4zODczIDY5LjIwODIgMjUuMjIxNiA2OS4zNTA2IDI2LjIyNThDNjkuNjA4NCAyOC4zNzUyIDY5LjgyNDUgMzAuMTU2OSA2OS42OTEyIDMxLjgxM0M2OS41NjE1IDMyLjQzNzUgNjkuMTAzNyAzMy4wMDg2IDY4LjY5NTYgMzMuNDA1Nkw2OC42MjM1IDM0LjcwODZDNjYuNzgzOSAzNC44NjE3IDY0LjkzMTkgMzUuMTQyMSA2My4wODIxIDM1LjU2NDFDNTUuMTIyNiAzNy4zNzk4IDQ4LjI2OTUgNDEuNDk5MSA0My4wNTIgNDcuMDYwOUM0Mi43MTM0IDQ2LjgyODggNDIuMTIxMSA0Ni40MDE5IDQxLjk0NSA0Ni4yNzEyQzQxLjM5NzcgNDYuMzQ1NCA0MC44NDQ1IDQ2LjUxNTEgNDAuMTI0MSA0Ni4wOTM1QzM4Ljc1MjIgNDUuMTY1NyAzNy41MDI4IDQzLjg4NTEgMzUuOTkxIDQyLjM0MjRDMzUuMjk4MiA0MS42MDQ0IDM0Ljc5NjYgNDAuOTAxOCAzMy45NzM1IDQwLjE5MDRDMzMuNzg2NiA0MC4wMjg5IDMzLjUwMTQgMzkuODEwNCAzMy4yOTIzIDM5LjY0NDJDMzIuNjQ4OSAzOS4xMjg4IDMxLjg5IDM4Ljg2IDMxLjE1NyAzOC44MzQ4QzMwLjIxNDcgMzguODAyNCAyOS4zMDc1IDM5LjE3MjUgMjguNzEzOCAzOS45MjA2QzI3LjY1ODQgNDEuMjUwNiAyNy45OTYzIDQzLjI4MzMgMjkuNDY3MSA0NC40NjE0QzI5LjQ4MiA0NC40NzM0IDI5LjQ5NzkgNDQuNDgyNyAyOS41MTI5IDQ0LjQ5NDNDMjkuNzE1IDQ0LjY1ODkgMjkuOTYyNSA0NC44Njk4IDMwLjE0ODMgNDUuMDA3NkMzMS4wMjE3IDQ1LjY1NTUgMzEuODE5NSA0NS45ODcyIDMyLjY4OTcgNDYuNTAxNUMzNC41MjMxIDQ3LjYzOTEgMzYuMDQzIDQ4LjU4MjMgMzcuMjQ4NiA0OS43MTk2QzM3LjcxOTQgNTAuMjIzNyAzNy44MDE2IDUxLjExMjIgMzcuODY0MyA1MS40OTY0TDM4Ljg0NjggNTIuMzc4MkMzMy41ODcyIDYwLjMzMDggMzEuMTUzIDcwLjE1MzkgMzIuNTkxNSA4MC4xNjI3TDMxLjMwNzcgODAuNTM3OEMzMC45NjkzIDgwLjk3NjggMzAuNDkxMiA4MS42Njc2IDI5Ljk5MTEgODEuODczOEMyOC40MTM4IDgyLjM3MjkgMjYuNjM4NyA4Mi41NTYyIDI0LjQ5NTYgODIuNzgxOUMyMy40ODk0IDgyLjg2NiAyMi42MjEzIDgyLjgxNTggMjEuNTU0NiA4My4wMTg4QzIxLjMxOTggODMuMDYzNSAyMC45OTI3IDgzLjE0OTEgMjAuNzM1OCA4My4yMDk3QzIwLjcyNjkgODMuMjExNiAyMC43MTg2IDgzLjIxNDIgMjAuNzA5NiA4My4yMTYyQzIwLjY5NTYgODMuMjE5NSAyMC42NzcyIDgzLjIyNjMgMjAuNjYzOCA4My4yMjk0QzE4Ljg1NyA4My42NjggMTcuNjk2MyA4NS4zMzY1IDE4LjA2OTkgODYuOTgwNUMxOC40NDM3IDg4LjYyNDggMjAuMjA4NiA4OS42MjQ4IDIyLjAyNjIgODkuMjMxMkMyMi4wMzkzIDg5LjIyODIgMjIuMDU4NCA4OS4yMjc3IDIyLjA3MiA4OS4yMjQ2QzIyLjA5MjYgODkuMjE5OSAyMi4xMTA2IDg5LjIwOTkgMjIuMTMxIDg5LjIwNDlDMjIuMzg0NCA4OS4xNDkgMjIuNzAxOSA4OS4wODY4IDIyLjkyMzYgODkuMDI3MkMyMy45NzIzIDg4Ljc0NTEgMjQuNzMxOCA4OC4zMzA2IDI1LjY3NDYgODcuOTY3N0MyNy43MDI5IDg3LjIzNjggMjkuMzgyOCA4Ni42MjYyIDMxLjAxOTUgODYuMzg4M0MzMS43MDMgODYuMzM0NSAzMi40MjMyIDg2LjgxMiAzMi43ODE0IDg3LjAxMzRMMzQuMTE3NyA4Ni43ODMxQzM3LjE5MjYgOTYuMzYxMyA0My42MzY2IDEwNC4xMDMgNTEuNzk2MyAxMDguOTYxTDUxLjIzOTYgMTEwLjMwM0M1MS40NDAzIDExMC44MjQgNTEuNjYxNiAxMTEuNTMgNTEuNTEyMSAxMTIuMDQ1QzUwLjkxNzEgMTEzLjU5NSA0OS44OTggMTE1LjIzMSA0OC43Mzc0IDExNy4wNTVDNDguMTc1NSAxMTcuODk4IDQ3LjYwMDQgMTE4LjU1MiA0Ny4wOTM0IDExOS41MTZDNDYuOTcyIDExOS43NDcgNDYuODE3NSAxMjAuMTAyIDQ2LjcwMDQgMTIwLjM0NkM0NS45MTI1IDEyMi4wMzkgNDYuNDkwNCAxMjMuOTkgNDguMDAzOCAxMjQuNzIyQzQ5LjUyNjggMTI1LjQ1OSA1MS40MTcxIDEyNC42ODIgNTIuMjM1MiAxMjIuOTg1QzUyLjIzNjQgMTIyLjk4MiA1Mi4yNDA2IDEyMi45OCA1Mi4yNDE3IDEyMi45NzhDNTIuMjQyNiAxMjIuOTc2IDUyLjI0MDkgMTIyLjk3MyA1Mi4yNDE3IDEyMi45NzFDNTIuMzU4MiAxMjIuNzMxIDUyLjUyMzMgMTIyLjQxNSA1Mi42MjE2IDEyMi4xODhDNTMuMDU2IDEyMS4xODkgNTMuMjAwNSAxMjAuMzMyIDUzLjUwNTkgMTE5LjM2NUM1NC4zMTcgMTE3LjMxOCA1NC43NjI2IDExNS4xNyA1NS44NzkxIDExMy44MzJDNTYuMTg0OSAxMTMuNDY2IDU2LjY4MzMgMTEzLjMyNSA1Ny4yMDAxIDExMy4xODZMNTcuODk0NCAxMTEuOTIyQzY1LjAwOCAxMTQuNjY1IDcyLjk3MDUgMTE1LjQwMiA4MC45MjQ1IDExMy41ODdDODIuNzM5MSAxMTMuMTczIDg0LjQ5MDggMTEyLjYzNyA4Ni4xODQzIDExMS45OTRDODYuMzc5NCAxMTIuMzQyIDg2Ljc0MiAxMTMuMDExIDg2LjgzOTMgMTEzLjE3OUM4Ny4zNjQ0IDExMy4zNTEgODcuOTM3NyAxMTMuNDM5IDg4LjQwNDcgMTE0LjEzM0M4OS4yNDAxIDExNS41NjcgODkuODExNCAxMTcuMjYzIDkwLjUwNzMgMTE5LjMxMkM5MC44MTI4IDEyMC4yNzkgOTAuOTYzOCAxMjEuMTM2IDkxLjM5ODEgMTIyLjEzNkM5MS40OTcxIDEyMi4zNjMgOTEuNjYxNCAxMjIuNjg0IDkxLjc3OCAxMjIuOTI1QzkyLjU5NDQgMTI0LjYyOCA5NC40OTA3IDEyNS40MDcgOTYuMDE1OSAxMjQuNjY5Qzk3LjUyOTIgMTIzLjkzNyA5OC4xMDc3IDEyMS45ODYgOTcuMzE5NCAxMjAuMjkzQzk3LjIwMjMgMTIwLjA0OSA5Ny4wNDEyIDExOS42OTUgOTYuOTE5OCAxMTkuNDY0Qzk2LjQxMjcgMTE4LjQ5OSA5NS44Mzc3IDExNy44NTIgOTUuMjc1OCAxMTcuMDA5Qzk0LjExNTIgMTE1LjE4NSA5My4xNTI2IDExMy42NyA5Mi41NTc1IDExMi4xMkM5Mi4zMDg3IDExMS4zMiA5Mi41OTk1IDExMC44MjMgOTIuNzkzMyAxMTAuMzAzQzkyLjY3NzIgMTEwLjE3IDkyLjQyODggMTA5LjQxNCA5Mi4yODI0IDEwOS4wNTlDMTAwLjc2MiAxMDQuMDI5IDEwNy4wMTcgOTUuOTk4NSAxMDkuOTU1IDg2LjcyMzlDMTEwLjM1MSA4Ni43ODY1IDExMS4wNDEgODYuOTA5MSAxMTEuMjY1IDg2Ljk1NDJDMTExLjcyNiA4Ni42NDg3IDExMi4xNDkgODYuMjUwMSAxMTIuOTgxIDg2LjMxNTlDMTE0LjYxNyA4Ni41NTM3IDExNi4yOTcgODcuMTY0NSAxMTguMzI2IDg3Ljg5NTNDMTE5LjI2OCA4OC4yNTgxIDEyMC4wMjggODguNjc5MyAxMjEuMDc3IDg4Ljk2MTRDMTIxLjI5OCA4OS4wMjEgMTIxLjYxNiA4OS4wNzY2IDEyMS44NjkgODkuMTMyNUMxMjEuODg5IDg5LjEzNzUgMTIxLjkwOCA4OS4xNDc1IDEyMS45MjggODkuMTUyMkMxMjEuOTQyIDg5LjE1NTMgMTIxLjk2MSA4OS4xNTU4IDEyMS45NzQgODkuMTU4OEMxMjMuNzkyIDg5LjU1MiAxMjUuNTU3IDg4LjU1MjYgMTI1LjkzIDg2LjkwODFDMTI2LjMwMyA4NS4yNjQxIDEyNS4xNDMgODMuNTk1MiAxMjMuMzM2IDgzLjE1N0MxMjMuMDc0IDgzLjA5NyAxMjIuNzAxIDgyLjk5NSAxMjIuNDQ2IDgyLjk0NjVDMTIxLjM3OSA4Mi43NDM1IDEyMC41MTEgODIuNzkzNSAxMTkuNTA1IDgyLjcwOTVDMTE3LjM2MSA4Mi40ODM5IDExNS41ODYgODIuMzAwNCAxMTQuMDA5IDgxLjgwMTRDMTEzLjM2NiA4MS41NTA3IDExMi45MDggODAuNzgxOSAxMTIuNjg2IDgwLjQ2NTVMMTExLjQ0OCA4MC4xMDM1QzExMi4wOSA3NS40MzggMTExLjkxNyA3MC41ODI1IDExMC44MDYgNjUuNzI0M0MxMDkuNjg1IDYwLjgyMDggMTA3LjcwNCA1Ni4zMzYxIDEwNS4wNjIgNTIuMzg0OEMxMDUuMzc5IDUyLjA5NDggMTA1Ljk3OSA1MS41NjEyIDEwNi4xNDkgNTEuNDA0M0MxMDYuMTk5IDUwLjg1MTcgMTA2LjE1NiA1MC4yNzIyIDEwNi43MjUgNDkuNjYwM0MxMDcuOTMxIDQ4LjUyMyAxMDkuNDUxIDQ3LjU3OTkgMTExLjI4NCA0Ni40NDIzQzExMi4xNTQgNDUuOTI3OSAxMTIuOTU5IDQ1LjU5NjQgMTEzLjgzMiA0NC45NDg0QzExNC4wMyA0NC44MDE5IDExNC4yOTkgNDQuNTY5OSAxMTQuNTA3IDQ0LjQwMjJDMTE1Ljk3NyA0My4yMjM3IDExNi4zMTYgNDEuMTkxMSAxMTUuMjYgMzkuODYxNEMxMTQuMjA0IDM4LjUzMTcgMTEyLjE1OSAzOC40MDY1IDExMC42ODggMzkuNTg1QzExMC40NzkgMzkuNzUxNiAxMTAuMTk1IDM5Ljk2ODggMTEwLjAwNyA0MC4xMzEyQzEwOS4xODQgNDAuODQyNiAxMDguNjc2IDQxLjU0NTIgMTA3Ljk4MyA0Mi4yODMyQzEwNi40NzEgNDMuODI1OSAxMDUuMjIyIDQ1LjExMyAxMDMuODUgNDYuMDQwOUMxMDMuMjU1IDQ2LjM4ODUgMTAyLjM4NSA0Ni4yNjgyIDEwMS45OSA0Ni4yNDQ5TDEwMC44MjQgNDcuMDgwNkM5NC4xNzUzIDQwLjA3NjMgODUuMTIzNSAzNS41OTgyIDc1LjM3NjYgMzQuNzI4M0M3NS4zNDk0IDM0LjMxNzkgNzUuMzEzNyAzMy41NzYxIDc1LjMwNDYgMzMuMzUyOUM3NC45MDU2IDMyLjk2OTMgNzQuNDIzNSAzMi42NDE4IDc0LjMwMjQgMzEuODEzQzc0LjE2OTEgMzAuMTU2OSA3NC4zOTE3IDI4LjM3NTIgNzQuNjQ5NiAyNi4yMjU4Qzc0Ljc5MTkgMjUuMjIxNiA3NS4wMjg0IDI0LjM4NzMgNzUuMDY4OCAyMy4yOTczQzc1LjA3OCAyMy4wNDk1IDc1LjA2MzIgMjIuNjkgNzUuMDYyMiAyMi40MjIxQzc1LjA2MiAyMC41MzIyIDczLjY4OTggMTguOTk5OCA3MS45OTY4IDE5Wk02OC4xNTg1IDQyLjg4ODZMNjcuMjQ4IDU5LjA0NDdMNjcuMTgyNSA1OS4wNzc2QzY3LjEyMTQgNjAuNTIyOSA2NS45Mzc1IDYxLjY3NyA2NC40ODM5IDYxLjY3N0M2My44ODg0IDYxLjY3NyA2My4zMzg4IDYxLjQ4NDkgNjIuODkyMiA2MS4xNTcxTDYyLjg2NiA2MS4xNzAzTDQ5LjY4MDcgNTEuNzc5NEM1My43MzMxIDQ3Ljc3NTkgNTguOTE2NCA0NC44MTcyIDY0Ljg5IDQzLjQ1NDZDNjUuOTgxMiA0My4yMDU2IDY3LjA3MTkgNDMuMDIwOSA2OC4xNTg1IDQyLjg4ODZaTTc1Ljg0MTcgNDIuODg4NkM4Mi44MTU5IDQzLjc1MDQgODkuMjY1NyA0Ni45MjMyIDk0LjIwODEgNTEuNzg2TDgxLjEwOCA2MS4xMTc2TDgxLjA2MjEgNjEuMDk3OUM3OS44OTk0IDYxLjk1MTIgNzguMjYxMSA2MS43Mzk0IDc3LjM1NDggNjAuNTk3OEM3Ni45ODM1IDYwLjEzMDEgNzYuNzg4NyA1OS41ODAxIDc2Ljc2NTMgNTkuMDI0OUw3Ni43NTIyIDU5LjAxODRMNzUuODQxNyA0Mi44ODg2Wk00NC44OTkxIDU3LjgxNEw1Ni45MzgyIDY4LjYzM0w1Ni45MjUxIDY4LjY5ODhDNTguMDExNyA2OS42NDc5IDU4LjE3MiA3MS4yOTQ5IDU3LjI2NTcgNzIuNDM2OEM1Ni44OTQ0IDcyLjkwNDUgNTYuMzk3NSA3My4yMTgyIDU1Ljg2MzkgNzMuMzY0N0w1NS44NTA4IDczLjQxNzNMNDAuNDE4OCA3Ny44OTIzQzM5LjYzMzQgNzAuNjc2NSA0MS4zMjYxIDYzLjY2MjEgNDQuODk5MSA1Ny44MTRaTTk5LjAwOTQgNTcuODIwNkMxMDAuNzk4IDYwLjczMzYgMTAyLjE1MyA2My45ODcxIDEwMi45NTkgNjcuNTE0M0MxMDMuNzU2IDcwLjk5OTEgMTAzLjk1NiA3NC40Nzc4IDEwMy42MjcgNzcuODM5N0w4OC4xMTY2IDczLjM1MTVMODguMTAzNSA3My4yODU3Qzg2LjcxNDUgNzIuOTA0MyA4NS44NjA5IDcxLjQ4NDggODYuMTg0MyA3MC4wNjExQzg2LjMxNjggNjkuNDc3OCA4Ni42MjQ5IDY4Ljk4NDQgODcuMDQyMyA2OC42MTk4TDg3LjAzNTggNjguNTg2OUw5OS4wMDk0IDU3LjgyMDZaTTY5LjUyNzQgNjkuNDY4OEg3NC40NTk2TDc3LjUyNTEgNzMuMzE4Nkw3Ni40MjQ3IDc4LjEyMjZMNzEuOTk2OCA4MC4yNjE0TDY3LjU1NTggNzguMTE2MUw2Ni40NTU0IDczLjMxMkw2OS41Mjc0IDY5LjQ2ODhaTTg1LjMzOTMgODIuNjQzN0M4NS41NDg5IDgyLjYzMzEgODUuNzU3NiA4Mi42NTIgODUuOTYxNiA4Mi42ODk4TDg1Ljk4NzggODIuNjU2OUwxMDEuOTUgODUuMzY4MkM5OS42MTQyIDkxLjk2MjQgOTUuMTQ0IDk3LjY3NSA4OS4xNzExIDEwMS40OThMODIuOTc0NyA4Ni40NjA2TDgyLjk5NDQgODYuNDM0M0M4Mi40MjUyIDg1LjEwNTUgODIuOTk0OCA4My41NDcyIDg0LjMwNDQgODIuOTEzNUM4NC42Mzk3IDgyLjc1MTMgODQuOTkgODIuNjYxNCA4NS4zMzkzIDgyLjY0MzdaTTU4LjUyOTggODIuNzA5NUM1OS43NDggODIuNzI2NyA2MC44NDA2IDgzLjU3NjEgNjEuMTIzNyA4NC44MjJDNjEuMjU2MiA4NS40MDUyIDYxLjE5MTcgODUuOTgzMSA2MC45NzMgODYuNDkzNUw2MS4wMTg5IDg2LjU1MjdMNTQuODg4IDEwMS40MzlDNDkuMTU1OSA5Ny43NDMyIDQ0LjU5MDQgOTIuMjA5OSA0Mi4xNDgxIDg1LjQyMDhMNTcuOTczMSA4Mi43MjI3TDU3Ljk5OTMgODIuNzU1NkM1OC4xNzYzIDgyLjcyMjkgNTguMzU1OCA4Mi43MDcxIDU4LjUyOTggODIuNzA5NVpNNzEuODk4NiA4OS4yMzEyQzcyLjMyMjkgODkuMjE1NSA3Mi43NTM0IDg5LjMwMyA3My4xNjI3IDg5LjUwMUM3My42OTkyIDg5Ljc2MDYgNzQuMTEzNiA5MC4xNjkyIDc0LjM3NDUgOTAuNjU5Mkg3NC40MzM0TDgyLjIzNDYgMTA0LjgyMUM4MS4yMjIxIDEwNS4xNjIgODAuMTgxMyAxMDUuNDU0IDc5LjExNjcgMTA1LjY5N0M3My4xNTA1IDEwNy4wNTggNjcuMjAzMiAxMDYuNjQ1IDYxLjgxOCAxMDQuODAyTDY5LjU5OTUgOTAuNjY1OEg2OS42MTI2QzcwLjA3OTUgODkuNzg4OCA3MC45NjUgODkuMjY1NiA3MS44OTg2IDg5LjIzMTJaIiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIwLjI1Ii8+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfNjgxXzI4NDUiIHgxPSIxMCIgeTE9IjE1LjUiIHgyPSIxNDQiIHkyPSIxMzEuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjNEQ4N0ZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA1NDdEMCIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPgo= - keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "storageClass"], ["spec", "nodeGroups"], ["spec", "nodeGroups", "md0"], ["spec", "nodeGroups", "md0", "minReplicas"], ["spec", "nodeGroups", "md0", "maxReplicas"], ["spec", "nodeGroups", "md0", "instanceType"], ["spec", "nodeGroups", "md0", "ephemeralStorage"], ["spec", "nodeGroups", "md0", "roles"], ["spec", "nodeGroups", "md0", "resources"], ["spec", "nodeGroups", "md0", "gpus"], ["spec", "version"], ["spec", "host"], ["spec", "addons"], ["spec", "addons", "certManager"], ["spec", "addons", "certManager", "enabled"], ["spec", "addons", "certManager", "valuesOverride"], ["spec", "addons", "cilium"], ["spec", "addons", "cilium", "valuesOverride"], ["spec", "addons", "gatewayAPI"], ["spec", "addons", "gatewayAPI", "enabled"], ["spec", "addons", "ingressNginx"], ["spec", "addons", "ingressNginx", "enabled"], ["spec", "addons", "ingressNginx", "exposeMethod"], ["spec", "addons", "ingressNginx", "hosts"], ["spec", "addons", "ingressNginx", "valuesOverride"], ["spec", "addons", "gpuOperator"], ["spec", "addons", "gpuOperator", "enabled"], ["spec", "addons", "gpuOperator", "valuesOverride"], ["spec", "addons", "hami"], ["spec", "addons", "hami", "enabled"], ["spec", "addons", "hami", "valuesOverride"], ["spec", "addons", "fluxcd"], ["spec", "addons", "fluxcd", "enabled"], ["spec", "addons", "fluxcd", "valuesOverride"], ["spec", "addons", "monitoringAgents"], ["spec", "addons", "monitoringAgents", "enabled"], ["spec", "addons", "monitoringAgents", "valuesOverride"], ["spec", "addons", "verticalPodAutoscaler"], ["spec", "addons", "verticalPodAutoscaler", "valuesOverride"], ["spec", "addons", "velero"], ["spec", "addons", "velero", "enabled"], ["spec", "addons", "velero", "valuesOverride"], ["spec", "addons", "coredns"], ["spec", "addons", "coredns", "valuesOverride"], ["spec", "controlPlane"], ["spec", "controlPlane", "replicas"], ["spec", "controlPlane", "apiServer"], ["spec", "controlPlane", "apiServer", "resources"], ["spec", "controlPlane", "apiServer", "resourcesPreset"], ["spec", "controlPlane", "controllerManager"], ["spec", "controlPlane", "controllerManager", "resources"], ["spec", "controlPlane", "controllerManager", "resourcesPreset"], ["spec", "controlPlane", "scheduler"], ["spec", "controlPlane", "scheduler", "resources"], ["spec", "controlPlane", "scheduler", "resourcesPreset"], ["spec", "controlPlane", "konnectivity"], ["spec", "controlPlane", "konnectivity", "server"], ["spec", "controlPlane", "konnectivity", "server", "resources"], ["spec", "controlPlane", "konnectivity", "server", "resourcesPreset"], ["spec", "images"], ["spec", "images", "waitForKubeconfig"]] + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "storageClass"], ["spec", "nodeGroups"], ["spec", "nodeGroups", "md0"], ["spec", "nodeGroups", "md0", "minReplicas"], ["spec", "nodeGroups", "md0", "maxReplicas"], ["spec", "nodeGroups", "md0", "instanceType"], ["spec", "nodeGroups", "md0", "ephemeralStorage"], ["spec", "nodeGroups", "md0", "roles"], ["spec", "nodeGroups", "md0", "resources"], ["spec", "nodeGroups", "md0", "gpus"], ["spec", "version"], ["spec", "host"], ["spec", "addons"], ["spec", "addons", "certManager"], ["spec", "addons", "certManager", "enabled"], ["spec", "addons", "certManager", "valuesOverride"], ["spec", "addons", "cilium"], ["spec", "addons", "cilium", "valuesOverride"], ["spec", "addons", "gatewayAPI"], ["spec", "addons", "gatewayAPI", "enabled"], ["spec", "addons", "ingressNginx"], ["spec", "addons", "ingressNginx", "enabled"], ["spec", "addons", "ingressNginx", "exposeMethod"], ["spec", "addons", "ingressNginx", "hosts"], ["spec", "addons", "ingressNginx", "valuesOverride"], ["spec", "addons", "gpuOperator"], ["spec", "addons", "gpuOperator", "enabled"], ["spec", "addons", "gpuOperator", "valuesOverride"], ["spec", "addons", "fluxcd"], ["spec", "addons", "fluxcd", "enabled"], ["spec", "addons", "fluxcd", "valuesOverride"], ["spec", "addons", "monitoringAgents"], ["spec", "addons", "monitoringAgents", "enabled"], ["spec", "addons", "monitoringAgents", "valuesOverride"], ["spec", "addons", "verticalPodAutoscaler"], ["spec", "addons", "verticalPodAutoscaler", "valuesOverride"], ["spec", "addons", "velero"], ["spec", "addons", "velero", "enabled"], ["spec", "addons", "velero", "valuesOverride"], ["spec", "addons", "coredns"], ["spec", "addons", "coredns", "valuesOverride"], ["spec", "controlPlane"], ["spec", "controlPlane", "replicas"], ["spec", "controlPlane", "apiServer"], ["spec", "controlPlane", "apiServer", "resources"], ["spec", "controlPlane", "apiServer", "resourcesPreset"], ["spec", "controlPlane", "controllerManager"], ["spec", "controlPlane", "controllerManager", "resources"], ["spec", "controlPlane", "controllerManager", "resourcesPreset"], ["spec", "controlPlane", "scheduler"], ["spec", "controlPlane", "scheduler", "resources"], ["spec", "controlPlane", "scheduler", "resourcesPreset"], ["spec", "controlPlane", "konnectivity"], ["spec", "controlPlane", "konnectivity", "server"], ["spec", "controlPlane", "konnectivity", "server", "resources"], ["spec", "controlPlane", "konnectivity", "server", "resourcesPreset"]] secrets: exclude: [] include: diff --git a/packages/system/kubevirt-csi-node/values.yaml b/packages/system/kubevirt-csi-node/values.yaml index 56e28543..a4d51b79 100644 --- a/packages/system/kubevirt-csi-node/values.yaml +++ b/packages/system/kubevirt-csi-node/values.yaml @@ -1,3 +1,3 @@ storageClass: replicated csiDriver: - image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:72154a97054e16cdf3dea6129d962b8d7e86b55cf9386095e8ac2ce7c8b69172 + image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:36e26a6b9063761ca3f5597bbd6272651d8a502abbc1c4e3a20e6b7e45a2875a diff --git a/packages/system/lineage-controller-webhook/Makefile b/packages/system/lineage-controller-webhook/Makefile index cdc1cf01..d5bada31 100644 --- a/packages/system/lineage-controller-webhook/Makefile +++ b/packages/system/lineage-controller-webhook/Makefile @@ -4,13 +4,8 @@ NAMESPACE=cozy-system include ../../../hack/common-envs.mk include ../../../hack/package.mk -.PHONY: test - image: image-lineage-controller-webhook -test: - helm unittest . - image-lineage-controller-webhook: docker buildx build -f images/lineage-controller-webhook/Dockerfile ../../.. \ --tag $(REGISTRY)/lineage-controller-webhook:$(call settag,$(TAG)) \ diff --git a/packages/system/lineage-controller-webhook/README.md b/packages/system/lineage-controller-webhook/README.md deleted file mode 100644 index 1e43c9c8..00000000 --- a/packages/system/lineage-controller-webhook/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# lineage-controller-webhook - -Cozystack system package for the **lineage controller webhook** — a mutating -admission webhook that stamps "lineage" labels onto tenant workloads, linking -each resource back to the Cozystack `Application` that ultimately owns it. - -The webhook intercepts CREATE and UPDATE on `pods`, `secrets`, `services`, -`persistentvolumeclaims`, `ingresses.networking.k8s.io`, and -`workloadmonitors.cozystack.io` outside system namespaces. For each request it -walks the ownership graph upward (Kubernetes `ownerReferences`, then the -`HelmRelease` Flux installed the resource with, then the Cozystack -`Application`-derived CRD that produced the HelmRelease) and writes the -discovered application's group, kind and name as labels -(`apps.cozystack.io/application.{group,kind,name}`) on the incoming object. -Those labels let the aggregated API server, the Cozystack dashboard, and other -lineage-aware consumers reason about which application a resource belongs to. - -The webhook serves TLS on port 9443 with a cert-manager issued certificate, and -runs with `failurePolicy: Fail` — every CREATE/UPDATE on the resources above -is gated on the webhook being reachable. - -## Topology - -The chart ships a single shape, modelled on `cozystack-api`: - -- **Deployment** with two replicas (override via `replicas`). -- **Soft `nodeAffinity`** preferring `node-role.kubernetes.io/control-plane` - (`Exists`, so it matches both Talos's empty value and k3s/kubeadm's `"true"`). - Soft means: the pod lands on a control-plane node when one is reachable, and - on any worker otherwise — no override needed for managed Kubernetes, - Cozy-in-Cozy tenants, or any other cluster where control-plane nodes aren't - visible. -- **Permissive `tolerations`** (`[{operator: Exists}]`) so the pod can land on - tainted control-plane nodes when the soft affinity is satisfiable. -- **Soft `podAntiAffinity`** on `kubernetes.io/hostname` so replicas spread - across nodes when possible (best-effort). -- **`PodDisruptionBudget`** with `maxUnavailable: 1`, unconditional. At - `replicas: 1` it's a useful no-op (allows full drain); at `replicas >= 2` - it caps disruption to one pod. -- **`Service` with `spec.trafficDistribution: PreferClose`** so the apiserver - prefers a webhook endpoint on its own node when one exists, and transparently - falls over to a remote endpoint otherwise. Requires Kubernetes ≥ 1.31; on - older clusters the field is silently ignored and traffic uses default - cluster-wide distribution. - -## Parameters - -All keys live under the top-level `lineageControllerWebhook:` map. - -| Name | Description | Value | -| ----------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------- | -| `image` | Container image (digest-pinned) | `ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.3.0@sha256:e898…6fb0` | -| `debug` | Enable `--zap-log-level=debug` instead of `info` | `false` | -| `replicas` | Deployment replica count | `2` | -| `localK8sAPIEndpoint.enabled` | **Deprecated.** See note below. | `false` | - -### `localK8sAPIEndpoint.enabled` (deprecated) - -When enabled, this injects `KUBERNETES_SERVICE_HOST=status.hostIP` and -`KUBERNETES_SERVICE_PORT=6443` so the webhook talks to the kube-apiserver on -its own node. It was originally added to avoid latency on the -webhook-to-apiserver path, but it is only valid when the pod is actually -scheduled on an apiserver-bearing node — which the chart's soft control-plane -affinity no longer guarantees. With this flag enabled and the pod scheduled -off a control-plane node, the controller will crash-loop dialing a non- -apiserver hostIP. Slated for removal once the latency motivation is addressed -in the webhook itself; **leave disabled**. diff --git a/packages/system/lineage-controller-webhook/templates/workload.yaml b/packages/system/lineage-controller-webhook/templates/daemonset.yaml similarity index 67% rename from packages/system/lineage-controller-webhook/templates/workload.yaml rename to packages/system/lineage-controller-webhook/templates/daemonset.yaml index 097919c6..860aee6e 100644 --- a/packages/system/lineage-controller-webhook/templates/workload.yaml +++ b/packages/system/lineage-controller-webhook/templates/daemonset.yaml @@ -1,11 +1,10 @@ apiVersion: apps/v1 -kind: Deployment +kind: DaemonSet metadata: name: lineage-controller-webhook labels: app: lineage-controller-webhook spec: - replicas: {{ .Values.lineageControllerWebhook.replicas }} selector: matchLabels: app: lineage-controller-webhook @@ -14,25 +13,13 @@ spec: labels: app: lineage-controller-webhook spec: - serviceAccountName: lineage-controller-webhook + {{- with .Values.lineageControllerWebhook.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} tolerations: - operator: Exists - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - preference: - matchExpressions: - - key: node-role.kubernetes.io/control-plane - operator: Exists - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - topologyKey: kubernetes.io/hostname - labelSelector: - matchLabels: - app: lineage-controller-webhook + serviceAccountName: lineage-controller-webhook containers: - name: lineage-controller-webhook image: "{{ .Values.lineageControllerWebhook.image }}" diff --git a/packages/system/lineage-controller-webhook/templates/pdb.yaml b/packages/system/lineage-controller-webhook/templates/pdb.yaml deleted file mode 100644 index 0786c8ff..00000000 --- a/packages/system/lineage-controller-webhook/templates/pdb.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: lineage-controller-webhook -spec: - maxUnavailable: 1 - selector: - matchLabels: - app: lineage-controller-webhook diff --git a/packages/system/lineage-controller-webhook/templates/service.yaml b/packages/system/lineage-controller-webhook/templates/service.yaml index fbb3ad54..c5df90fb 100644 --- a/packages/system/lineage-controller-webhook/templates/service.yaml +++ b/packages/system/lineage-controller-webhook/templates/service.yaml @@ -5,7 +5,7 @@ metadata: labels: app: lineage-controller-webhook spec: - trafficDistribution: PreferClose + internalTrafficPolicy: Local type: ClusterIP ports: - port: 443 diff --git a/packages/system/lineage-controller-webhook/tests/service_test.yaml b/packages/system/lineage-controller-webhook/tests/service_test.yaml deleted file mode 100644 index 3cdbddd8..00000000 --- a/packages/system/lineage-controller-webhook/tests/service_test.yaml +++ /dev/null @@ -1,30 +0,0 @@ -suite: lineage-controller-webhook service -templates: - - templates/service.yaml - -release: - name: lineage-controller-webhook - namespace: cozy-system - -tests: - - it: renders a ClusterIP service on 443 -> 9443 with PreferClose traffic distribution - asserts: - - isKind: - of: Service - - equal: - path: spec.type - value: ClusterIP - - equal: - path: spec.trafficDistribution - value: PreferClose - - notExists: - path: spec.internalTrafficPolicy - - equal: - path: spec.ports[0].port - value: 443 - - equal: - path: spec.ports[0].targetPort - value: 9443 - - equal: - path: spec.selector.app - value: lineage-controller-webhook diff --git a/packages/system/lineage-controller-webhook/tests/workload_test.yaml b/packages/system/lineage-controller-webhook/tests/workload_test.yaml deleted file mode 100644 index bcb24014..00000000 --- a/packages/system/lineage-controller-webhook/tests/workload_test.yaml +++ /dev/null @@ -1,99 +0,0 @@ -suite: lineage-controller-webhook workload + PDB -templates: - - templates/workload.yaml - - templates/pdb.yaml - -release: - name: lineage-controller-webhook - namespace: cozy-system - -tests: - # ---- Default Deployment shape ---------------------------------------------- - - - it: defaults render a 2-replica Deployment with soft control-plane nodeAffinity, soft podAntiAffinity, and Exists tolerations - template: templates/workload.yaml - asserts: - - isKind: - of: Deployment - - equal: - path: spec.replicas - value: 2 - - equal: - path: spec.template.spec.tolerations - value: - - operator: Exists - - equal: - path: spec.template.spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution - value: - - weight: 100 - preference: - matchExpressions: - - key: node-role.kubernetes.io/control-plane - operator: Exists - - notExists: - path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution - - equal: - path: spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey - value: kubernetes.io/hostname - - - it: defaults inject no localK8sAPIEndpoint env vars (knob is opt-in) - template: templates/workload.yaml - asserts: - - notExists: - path: spec.template.spec.containers[0].env - - # ---- PDB -------------------------------------------------------------------- - - - it: PDB renders unconditionally with maxUnavailable=1 at the default replica count - template: templates/pdb.yaml - asserts: - - isKind: - of: PodDisruptionBudget - - equal: - path: spec.maxUnavailable - value: 1 - - notExists: - path: spec.minAvailable - - - it: PDB still renders at replicas=1 (no-op, but consistent shape) - set: - lineageControllerWebhook.replicas: 1 - template: templates/pdb.yaml - asserts: - - isKind: - of: PodDisruptionBudget - - equal: - path: spec.maxUnavailable - value: 1 - - # ---- Replica override ------------------------------------------------------- - - - it: replicas value drives spec.replicas - set: - lineageControllerWebhook.replicas: 5 - template: templates/workload.yaml - asserts: - - equal: - path: spec.replicas - value: 5 - - # ---- Deprecated localK8sAPIEndpoint knob ----------------------------------- - - - it: localK8sAPIEndpoint.enabled=true injects KUBERNETES_SERVICE_HOST and PORT env vars - set: - lineageControllerWebhook.localK8sAPIEndpoint.enabled: true - template: templates/workload.yaml - asserts: - - contains: - path: spec.template.spec.containers[0].env - content: - name: KUBERNETES_SERVICE_HOST - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - contains: - path: spec.template.spec.containers[0].env - content: - name: KUBERNETES_SERVICE_PORT - value: "6443" diff --git a/packages/system/lineage-controller-webhook/values.yaml b/packages/system/lineage-controller-webhook/values.yaml index e56d332d..32439941 100644 --- a/packages/system/lineage-controller-webhook/values.yaml +++ b/packages/system/lineage-controller-webhook/values.yaml @@ -1,13 +1,10 @@ lineageControllerWebhook: - image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.3.0@sha256:e8984709686a5eaf19b89da378d7b8c688ea5607e0783a88d9c9e4ccfca96fb0 + image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.3.0-rc.1@sha256:7e443b9252f0477fe07471f76365edfa28550add51fe8fd4d11312d60a81850e debug: false - replicas: 2 - # DEPRECATED. Injects KUBERNETES_SERVICE_HOST=status.hostIP and - # KUBERNETES_SERVICE_PORT=6443 so the webhook talks to the apiserver on its - # own node — only valid when the pod is actually scheduled on an apiserver- - # bearing node. Now that the chart's nodeAffinity to control-plane is soft - # (preferred, not required), the pod can land off-control-plane and crash- - # loop dialing a non-apiserver hostIP. Slated for removal once webhook - # performance work obviates the locality motivation. Leave disabled. localK8sAPIEndpoint: - enabled: false + enabled: true + # nodeSelector for the DaemonSet + # Talos uses empty value: "node-role.kubernetes.io/control-plane": "" + # Generic k8s (k3s, kubeadm) uses: "node-role.kubernetes.io/control-plane": "true" + nodeSelector: + node-role.kubernetes.io/control-plane: "" diff --git a/packages/system/linstor-gui/Makefile b/packages/system/linstor-gui/Makefile index b408491d..e202f4cc 100644 --- a/packages/system/linstor-gui/Makefile +++ b/packages/system/linstor-gui/Makefile @@ -12,13 +12,18 @@ image: image-linstor-gui image-linstor-gui: docker buildx build images/linstor-gui \ + --provenance false \ + --builder=$(BUILDER) \ + --platform=linux/amd64,linux/arm64 \ --build-arg LINSTOR_GUI_VERSION=$(LINSTOR_GUI_VERSION) \ --tag $(REGISTRY)/linstor-gui:$(call settag,$(LINSTOR_GUI_VERSION)) \ --tag $(REGISTRY)/linstor-gui:$(call settag,$(LINSTOR_GUI_VERSION)-$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/linstor-gui:latest \ --cache-to type=inline \ --metadata-file images/linstor-gui.json \ - $(BUILDX_ARGS) + --push=$(PUSH) \ + --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \ + --load=$(LOAD) REPOSITORY="$(REGISTRY)/linstor-gui" \ yq -i '.image.repository = strenv(REPOSITORY)' values.yaml TAG="$(call settag,$(LINSTOR_GUI_VERSION))@$$(yq e '."containerimage.digest"' images/linstor-gui.json -o json -r)" \ diff --git a/packages/system/linstor-gui/templates/ingress.yaml b/packages/system/linstor-gui/templates/ingress.yaml index c50b0f86..bf950eab 100644 --- a/packages/system/linstor-gui/templates/ingress.yaml +++ b/packages/system/linstor-gui/templates/ingress.yaml @@ -22,7 +22,7 @@ metadata: annotations: cert-manager.io/cluster-issuer: {{ $clusterIssuer }} {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $exposeIngress }} + acme.cert-manager.io/http01-ingress-class: {{ $exposeIngress }} {{- end }} nginx.ingress.kubernetes.io/proxy-body-size: 100m # Keycloak access+refresh+id tokens make the oauth2-proxy session diff --git a/packages/system/linstor/Makefile b/packages/system/linstor/Makefile index 8d566678..2ad4def9 100644 --- a/packages/system/linstor/Makefile +++ b/packages/system/linstor/Makefile @@ -5,7 +5,7 @@ include ../../../hack/common-envs.mk include ../../../hack/package.mk LINSTOR_VERSION ?= 1.33.2 -LINSTOR_CSI_VERSION ?= v1.10.6 +LINSTOR_CSI_VERSION ?= v1.10.5 image: image-piraeus-server image-linstor-csi diff --git a/packages/system/linstor/images/linstor-csi/Dockerfile b/packages/system/linstor/images/linstor-csi/Dockerfile index df5d179d..6cfd44aa 100644 --- a/packages/system/linstor/images/linstor-csi/Dockerfile +++ b/packages/system/linstor/images/linstor-csi/Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.25 AS builder -ARG VERSION=v1.10.6 +ARG VERSION=v1.10.5 ARG LINSTOR_WAIT_UNTIL_VERSION=v0.3.1 ARG TARGETARCH ARG TARGETOS diff --git a/packages/system/linstor/images/linstor-csi/patches/001-relocate-after-clone-restore.diff b/packages/system/linstor/images/linstor-csi/patches/001-relocate-after-clone-restore.diff index 0e272670..ff0aec0c 100644 --- a/packages/system/linstor/images/linstor-csi/patches/001-relocate-after-clone-restore.diff +++ b/packages/system/linstor/images/linstor-csi/patches/001-relocate-after-clone-restore.diff @@ -1,7 +1,25 @@ diff --git a/pkg/client/linstor.go b/pkg/client/linstor.go -index ac4651d..46d565d 100644 +index f544493..98e7fde 100644 --- a/pkg/client/linstor.go +++ b/pkg/client/linstor.go +@@ -181,7 +181,7 @@ func LogLevel(s string) func(*Linstor) error { + func (s *Linstor) ListAllWithStatus(ctx context.Context) ([]volume.VolumeStatus, error) { + var vols []volume.VolumeStatus + +- resourcesByName := make(map[string][]lapi.Resource) ++ resourcesByName := make(map[string][]lapi.ResourceWithVolumes) + + resDefs, err := s.client.ResourceDefinitions.GetAll(ctx, lapi.RDGetAllRequest{WithVolumeDefinitions: true}) + if err != nil { +@@ -194,7 +194,7 @@ func (s *Linstor) ListAllWithStatus(ctx context.Context) ([]volume.VolumeStatus, + } + + for i := range allResources { +- resourcesByName[allResources[i].Name] = append(resourcesByName[allResources[i].Name], allResources[i].Resource) ++ resourcesByName[allResources[i].Name] = append(resourcesByName[allResources[i].Name], allResources[i]) + } + + for _, rd := range resDefs { @@ -462,6 +462,14 @@ func (s *Linstor) Clone(ctx context.Context, vol, src *volume.Info, params *volu return err } @@ -17,7 +35,7 @@ index ac4651d..46d565d 100644 logger.Debug("reconcile extra properties") err = s.client.ResourceDefinitions.Modify(ctx, vol.ID, lapi.GenericPropsModify{OverrideProps: vol.Properties}) -@@ -1297,6 +1305,14 @@ func (s *Linstor) VolFromSnap(ctx context.Context, snap *volume.Snapshot, vol *v +@@ -1280,6 +1288,14 @@ func (s *Linstor) VolFromSnap(ctx context.Context, snap *volume.Snapshot, vol *v return err } @@ -32,7 +50,7 @@ index ac4651d..46d565d 100644 logger.Debug("reconcile extra properties") err = s.client.ResourceDefinitions.Modify(ctx, vol.ID, lapi.GenericPropsModify{OverrideProps: vol.Properties}) -@@ -1487,9 +1503,8 @@ func (s *Linstor) reconcileSnapshotResources(ctx context.Context, snapshot *volu +@@ -1470,9 +1486,8 @@ func (s *Linstor) reconcileSnapshotResources(ctx context.Context, snapshot *volu return fmt.Errorf("snapshot '%s' not deployed on any node", snap.Name) } @@ -44,7 +62,7 @@ index ac4651d..46d565d 100644 for _, snapNode := range snap.Nodes { if err := s.NodeAvailable(ctx, snapNode); err != nil { logger.WithField("selected node candidate", snapNode).WithError(err).Debug("node is not available") -@@ -1497,13 +1512,23 @@ func (s *Linstor) reconcileSnapshotResources(ctx context.Context, snapshot *volu +@@ -1480,13 +1495,23 @@ func (s *Linstor) reconcileSnapshotResources(ctx context.Context, snapshot *volu } if slices.Contains(preferredNodes, snapNode) { @@ -74,7 +92,7 @@ index ac4651d..46d565d 100644 } if selectedNode == "" { -@@ -1696,6 +1721,114 @@ func (s *Linstor) reconcileResourcePlacement(ctx context.Context, vol *volume.In +@@ -1679,6 +1704,114 @@ func (s *Linstor) reconcileResourcePlacement(ctx context.Context, vol *volume.In return nil } @@ -189,8 +207,40 @@ index ac4651d..46d565d 100644 // FindSnapsByID searches the snapshot in the backend func (s *Linstor) FindSnapsByID(ctx context.Context, id string) ([]*volume.Snapshot, error) { snapshotId, err := volume.ParseSnapshotId(id) +@@ -2173,7 +2306,7 @@ func (s *Linstor) Status(ctx context.Context, volId string) ([]string, *csi.Volu + "volume": volId, + }).Debug("getting assignments") + +- ress, err := s.client.Resources.GetAll(ctx, volId) ++ ress, err := s.client.Resources.GetResourceView(ctx, &lapi.ListOpts{Resource: []string{volId}}) + if err != nil { + return nil, nil, fmt.Errorf("failed to list resources for '%s': %w", volId, err) + } +@@ -2261,13 +2394,20 @@ func GetSnapshotRemoteAndReadiness(snap *lapi.Snapshot) (string, bool, error) { + return "", slices.Contains(snap.Flags, lapiconsts.FlagSuccessful), nil + } + +-func NodesAndConditionFromResources(ress []lapi.Resource) ([]string, *csi.VolumeCondition) { ++func NodesAndConditionFromResources(ress []lapi.ResourceWithVolumes) ([]string, *csi.VolumeCondition) { + var allNodes, abnormalNodes []string + + for i := range ress { + res := &ress[i] + +- allNodes = append(allNodes, res.NodeName) ++ // A resource is a CSI publish target if any of its volumes were created ++ // by ControllerPublishVolume, identified by the temporary-diskless-attach property. ++ if slices.ContainsFunc(res.Volumes, func(v lapi.Volume) bool { ++ createdFor, ok := v.Props[linstor.PropertyCreatedFor] ++ return ok && createdFor == linstor.CreatedForTemporaryDisklessAttach ++ }) { ++ allNodes = append(allNodes, res.NodeName) ++ } + + if res.State == nil { + abnormalNodes = append(abnormalNodes, res.NodeName) diff --git a/pkg/volume/parameter.go b/pkg/volume/parameter.go -index 39acd95..54d1dfb 100644 +index 39acd95..aed18ab 100644 --- a/pkg/volume/parameter.go +++ b/pkg/volume/parameter.go @@ -50,6 +50,7 @@ const ( diff --git a/packages/system/linstor/images/linstor-csi/patches/002-protocol-c-override-for-dual-attach.diff b/packages/system/linstor/images/linstor-csi/patches/002-protocol-c-override-for-dual-attach.diff deleted file mode 100644 index 279c636b..00000000 --- a/packages/system/linstor/images/linstor-csi/patches/002-protocol-c-override-for-dual-attach.diff +++ /dev/null @@ -1,132 +0,0 @@ -diff --git a/pkg/client/linstor.go b/pkg/client/linstor.go -index ac4651d..9d75c79 100644 ---- a/pkg/client/linstor.go -+++ b/pkg/client/linstor.go -@@ -653,11 +653,35 @@ func (s *Linstor) Attach(ctx context.Context, volId, node string, rwxBlock bool) - } - - if otherResInUse > 0 && rwxBlock { -- rdPropsModify := lapi.GenericPropsModify{OverrideProps: map[string]string{ -+ rdProps := map[string]string{ - linstor.PropertyAllowTwoPrimaries: "yes", -- }} -+ } - -- err = s.client.ResourceDefinitions.Modify(ctx, volId, rdPropsModify) -+ // DRBD requires Protocol C whenever allow-two-primaries is enabled. -+ // If the resource is configured with Protocol A or B (typically -+ // through its resource-group), drbdadm adjust on the satellites -+ // fails with "Protocol C required" (errno 139) and live migration -+ // cannot proceed. Override Protocol to C on the resource-definition -+ // itself so it applies to every connection (including diskless -+ // peers, e.g. a TieBreaker). The marker lets Detach revert exactly -+ // the override we installed without disturbing operator-set props. -+ proto, protoErr := s.getEffectiveDrbdProtocol(ctx, volId) -+ if protoErr != nil { -+ s.log.WithError(protoErr).WithField("volume", volId). -+ Warn("failed to determine effective DRBD protocol; skipping Protocol=C override for dual-attach") -+ } else if proto == "A" || proto == "B" { -+ s.log.WithFields(logrus.Fields{ -+ "volume": volId, -+ "protocol": proto, -+ }).Info("installing Protocol=C override on resource-definition for dual-attach") -+ -+ rdProps[linstor.PropertyDrbdNetProtocol] = "C" -+ rdProps[linstor.PropertyCsiProtocolOverride] = "yes" -+ } -+ -+ err = s.client.ResourceDefinitions.Modify(ctx, volId, lapi.GenericPropsModify{ -+ OverrideProps: rdProps, -+ }) - if err != nil { - return "", err - } -@@ -774,11 +798,26 @@ func (s *Linstor) Detach(ctx context.Context, volId, node string) error { - } - - if resInUse == 1 { -- rdPropsModify := lapi.GenericPropsModify{DeleteProps: []string{ -- linstor.PropertyAllowTwoPrimaries, -- }} -+ deleteProps := []string{linstor.PropertyAllowTwoPrimaries} -+ -+ // Drop the Protocol=C override only if Attach installed it (gated by -+ // our marker), so an operator-set Protocol property on the -+ // resource-definition is preserved. -+ rd, getErr := s.client.ResourceDefinitions.Get(ctx, volId) -+ if getErr != nil { -+ log.WithError(getErr).Warn("failed to fetch resource-definition props; skipping Protocol=C override removal") -+ } else if rd.Props[linstor.PropertyCsiProtocolOverride] != "" { -+ log.Info("removing Protocol=C override from resource-definition") - -- err = s.client.ResourceDefinitions.Modify(ctx, volId, rdPropsModify) -+ deleteProps = append(deleteProps, -+ linstor.PropertyDrbdNetProtocol, -+ linstor.PropertyCsiProtocolOverride, -+ ) -+ } -+ -+ err = s.client.ResourceDefinitions.Modify(ctx, volId, lapi.GenericPropsModify{ -+ DeleteProps: deleteProps, -+ }) - if err != nil { - return nil404(err) - } -@@ -805,6 +844,33 @@ func (s *Linstor) Detach(ctx context.Context, volId, node string) error { - return nil404(s.client.Resources.Delete(ctx, volId, node)) - } - -+// getEffectiveDrbdProtocol returns the DRBD network protocol ("A", "B" or "C") -+// that LINSTOR will hand to drbdadm for the given resource. Resource-definition -+// properties take precedence; otherwise the value is inherited from the -+// resource-group. An empty string is returned when neither level sets the -+// property (LINSTOR's compiled-in default is "C"). -+func (s *Linstor) getEffectiveDrbdProtocol(ctx context.Context, volId string) (string, error) { -+ rd, err := s.client.ResourceDefinitions.Get(ctx, volId) -+ if err != nil { -+ return "", err -+ } -+ -+ if v, ok := rd.Props[linstor.PropertyDrbdNetProtocol]; ok { -+ return v, nil -+ } -+ -+ if rd.ResourceGroupName == "" { -+ return "", nil -+ } -+ -+ rg, err := s.client.ResourceGroups.Get(ctx, rd.ResourceGroupName) -+ if err != nil { -+ return "", err -+ } -+ -+ return rg.Props[linstor.PropertyDrbdNetProtocol], nil -+} -+ - // CapacityBytes returns the amount of free space in the storage pool specified by the params and topology. - func (s *Linstor) CapacityBytes(ctx context.Context, storagePools []string, overProvision *float64, segments map[string]string) (int64, error) { - log := s.log.WithField("storage-pools", storagePools).WithField("segments", segments) -diff --git a/pkg/linstor/const.go b/pkg/linstor/const.go -index 9a5f79c..c8bc9c3 100644 ---- a/pkg/linstor/const.go -+++ b/pkg/linstor/const.go -@@ -44,6 +44,19 @@ const ( - // PropertyAllowTwoPrimaries is DRBD option to allow second primary. Mainly used for live-migration. - PropertyAllowTwoPrimaries = lc.NamespcDrbdNetOptions + "/allow-two-primaries" - -+ // PropertyDrbdNetProtocol is the DRBD network replication protocol option -+ // (A = async, B = semi-sync, C = sync). DRBD requires Protocol C whenever -+ // allow-two-primaries is enabled, otherwise drbdadm adjust fails with -+ // "Protocol C required" (errno 139). -+ PropertyDrbdNetProtocol = lc.NamespcDrbdNetOptions + "/protocol" -+ -+ // PropertyCsiProtocolOverride marks a resource-connection where this driver -+ // has installed a temporary Protocol=C override to make a Protocol-A/B -+ // resource compatible with allow-two-primaries during live migration. The -+ // marker lets us safely remove only the overrides we set, without touching -+ // connection-level overrides installed by the operator. -+ PropertyCsiProtocolOverride = lc.NamespcAuxiliary + "/csi-protocol-override" -+ - // CreatedForTemporaryDisklessAttach marks a resource as temporary, i.e. it should be removed after it is no longer - // needed. - CreatedForTemporaryDisklessAttach = "temporary-diskless-attach" diff --git a/packages/system/linstor/templates/satellites-cozy.yaml b/packages/system/linstor/templates/satellites-cozy.yaml index e6f877a0..c621126d 100644 --- a/packages/system/linstor/templates/satellites-cozy.yaml +++ b/packages/system/linstor/templates/satellites-cozy.yaml @@ -14,11 +14,6 @@ spec: containers: - name: linstor-satellite image: {{ .Values.piraeusServer.image.repository }}:{{ .Values.piraeusServer.image.tag }} - startupProbe: - tcpSocket: - port: linstor - periodSeconds: 10 - failureThreshold: 30 securityContext: # real-world installations need some debugging from time to time readOnlyRootFilesystem: false diff --git a/packages/system/linstor/values.yaml b/packages/system/linstor/values.yaml index 62dd2cac..57f5f331 100644 --- a/packages/system/linstor/values.yaml +++ b/packages/system/linstor/values.yaml @@ -1,7 +1,7 @@ piraeusServer: image: repository: ghcr.io/cozystack/cozystack/piraeus-server - tag: 1.33.2@sha256:553f313ab35dc2e345ef3683156d29e75c23177e2750e9af3a83aa9e23941cbb + tag: 1.33.2@sha256:e748ea7b2adb285b0387fde4453320155fc03e4470db7d9af1d5447087bf18b4 # Talos-specific workarounds (disable for generic Linux like Ubuntu/Debian) talos: enabled: true @@ -13,4 +13,4 @@ linstor: linstorCSI: image: repository: ghcr.io/cozystack/cozystack/linstor-csi - tag: v1.10.5@sha256:b8f59b5659fb1791cb764d3f37df4cf29920aadcc10637231ba7d857233f377d + tag: v1.10.5@sha256:a80d39f96a988085e84be2d6e896f4b4a008fccd5bbd9eaa2b8534b076429942 diff --git a/packages/system/monitoring-agents/alerts/gpu-recording.rules.yaml b/packages/system/monitoring-agents/alerts/gpu-recording.rules.yaml deleted file mode 100644 index 5e0f9ea0..00000000 --- a/packages/system/monitoring-agents/alerts/gpu-recording.rules.yaml +++ /dev/null @@ -1,172 +0,0 @@ -apiVersion: operator.victoriametrics.com/v1beta1 -kind: VMRule -metadata: - name: alerts-gpu-recording.rules -spec: - groups: - - name: gpu.recording.cluster.1m - interval: 1m - params: {} - rules: - - record: cluster:gpu_count:total - expr: count(group by (UUID) (DCGM_FI_DEV_GPU_UTIL)) - # Kube-allocated GPU count: GPUs requested by *active* pods — Pending - # and Running only. Source of truth for "what tenants asked for" — used - # for capacity planning and billing. Includes system pods so it stays - # consistent with cluster:gpu_count:total when computing :free. - # - # Phase filter via group_left() on kube_pod_status_phase matches the - # canonical pattern from k8s.rules.container_resource.yaml. Without it - # kube-state-metrics keeps series for Failed/Succeeded pods until the - # apiserver garbage-collects them, which inflates billing hours and - # can push :free negative. - - record: cluster:gpu_count:allocated - expr: | - sum( - kube_pod_container_resource_requests{resource="nvidia_com_gpu"} - * on (namespace, pod) group_left() max by (namespace, pod) ( - kube_pod_status_phase{phase=~"Pending|Running"} == 1 - ) - ) - # clamp_min guards against transients at DCGM/kube-state-metrics - # restart where cluster:gpu_count:total dips before :allocated catches - # up, or rare label drift between the two sources. - - record: cluster:gpu_count:free - expr: clamp_min(cluster:gpu_count:total - (cluster:gpu_count:allocated or vector(0)), 0) - # Cluster-layer filter asymmetry — intentional, not a bug: - # - # * cluster:gpu_count:total and cluster:gpu_power_watts:sum do NOT - # filter cozy-*/kube-* namespaces because they describe the - # physical hardware fleet. A GPU draws power and occupies a - # slot regardless of which namespace's pod happens to hold it; - # excluding infra pods would under-report raw capacity and - # break capacity-planning math. - # - # No namespace filter — DCGM exporter metrics carry the exporter's - # own namespace, not the workload namespace. Filtering by namespace - # here would silently drop all series. - - record: cluster:gpu_util:avg - expr: avg(DCGM_FI_DEV_GPU_UTIL) - - record: cluster:gpu_power_watts:sum - expr: sum(DCGM_FI_DEV_POWER_USAGE) - - - name: gpu.recording.node.1m - interval: 1m - params: {} - rules: - # Kube-requested GPU count per namespace — billable/allocation view. - # This is the only namespace-level rule that works correctly because - # kube_pod_container_resource_requests carries the real workload - # namespace, unlike DCGM exporter metrics which carry the exporter's - # own namespace (cozy-gpu-operator). - - record: namespace:gpu_count:allocated - expr: | - sum by (namespace) ( - kube_pod_container_resource_requests{resource="nvidia_com_gpu", namespace!="", namespace!~"cozy-.*|kube-.*"} - * on (namespace, pod) group_left() max by (namespace, pod) ( - kube_pod_status_phase{phase=~"Pending|Running"} == 1 - ) - ) - # Hardware metrics aggregated per node (Hostname). DCGM exporter - # metrics carry a capital-H "Hostname" label identifying the node - # but no usable workload namespace — so hardware telemetry is - # aggregated at node/GPU granularity, not namespace. - - record: node:gpu_util:avg - expr: avg by (Hostname) (DCGM_FI_DEV_GPU_UTIL) - - record: node:tensor_active:avg - expr: avg by (Hostname) (DCGM_FI_PROF_PIPE_TENSOR_ACTIVE) - - record: node:fb_used_bytes:sum - expr: sum by (Hostname) (DCGM_FI_DEV_FB_USED) * 1048576 - - record: node:power_watts:sum - expr: sum by (Hostname) (DCGM_FI_DEV_POWER_USAGE) - - # Known gap: there is no lower-bound sanity alert for under-reporting. - # If DCGM ever switches POWER/THERMAL_VIOLATION counter units the other - # direction — e.g. from the current nanoseconds back to microseconds, - # making rate()/1e9 produce values around 0.001 instead of real - # fractions — the throttle signal would silently collapse to near-zero - # instead of plateauing at 1.0. GPUThrottleFractionOverOne below catches - # the >1 drift; the <<1 drift would require correlation with independent - # signals (power draw vs TDP, clock dips) that we do not yet wire up. - # Documented here so future maintainers know this is a known gap, not - # an oversight. - - name: gpu.recording.efficiency.1m - interval: 1m - params: {} - rules: - # Tensor hardware saturation per GPU — the honest "am I using the GPU" - # metric for AI/LLM workloads. Aggregated at GPU level (Hostname + - # gpu + UUID) because DCGM metrics don't carry workload namespace. - # Stored as a 0..1 ratio; consumers multiply by 100 at display time. - - record: gpu:tensor_saturation:avg5m - expr: | - avg by (Hostname, gpu, UUID) ( - avg_over_time(DCGM_FI_PROF_PIPE_TENSOR_ACTIVE[5m]) - ) - - # Power efficiency per GPU — utilization per watt, reveals - # unoptimized workloads. Explicit on(...) pins the matching set - # to GPU-identifying labels. - - record: gpu:util_per_watt:avg5m - expr: | - max by (Hostname, gpu, UUID) ( - avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m]) - ) - / on (Hostname, gpu, UUID) - clamp_min( - max by (Hostname, gpu, UUID) ( - avg_over_time(DCGM_FI_DEV_POWER_USAGE[5m]) - ), - 1 - ) - - # Fraction of time power-throttled (TDP cap) — 1.0 = fully throttled. - # DCGM_FI_DEV_*_VIOLATION is documented as µs but on A10/DCGM 3.x the - # counter grows in nanoseconds in practice — divide by 1e9 to get a - # 0..1 fraction (verified empirically when /1e6 yielded >100× reality). - # clamp_max protects against rate() artefacts at counter resets. - # - # max by (Hostname, gpu, UUID) collapses duplicate series from - # dcgm-exporter's pod-mapping labels (one physical GPU may appear - # under multiple pod/container labels during restarts or under - # MIG/MPS). Throttling is a physical-GPU property; taking max - # keeps consumer avg(...) honest — a naive avg() would dilute the - # signal by the number of pods sharing the GPU. - - record: gpu:power_throttle_fraction:rate5m - expr: clamp_max(max by (Hostname, gpu, UUID) (rate(DCGM_FI_DEV_POWER_VIOLATION[5m]) / 1e9), 1) - - # Fraction of time thermal-throttled. - - record: gpu:thermal_throttle_fraction:rate5m - expr: clamp_max(max by (Hostname, gpu, UUID) (rate(DCGM_FI_DEV_THERMAL_VIOLATION[5m]) / 1e9), 1) - - # Regression watch — the /1e9 divisor on *_VIOLATION was derived - # empirically against DCGM 3.x on A10. If a future DCGM version - # restores the documented µs units, pre-clamp values would exceed 1.0 - # while clamp_max(..., 1) silently masks the drift — recorded - # throttle fractions would plateau at 1.0 and consumers would think - # every GPU is always throttled. This alert fires on that condition - # so we can rescale to /1e6 before dashboards start lying. - - name: gpu.recording.throttle.validation.5m - interval: 5m - params: {} - rules: - - alert: GPUThrottleFractionOverOne - expr: | - max by (Hostname, gpu, UUID) (rate(DCGM_FI_DEV_POWER_VIOLATION[5m]) / 1e9) > 1 - or - max by (Hostname, gpu, UUID) (rate(DCGM_FI_DEV_THERMAL_VIOLATION[5m]) / 1e9) > 1 - for: 15m - labels: - severity: warning - component: gpu-monitoring - annotations: - summary: "DCGM throttle fraction exceeds 1.0 pre-clamp on {{ $labels.Hostname }}/{{ $labels.gpu }}" - description: | - gpu:{power,thermal}_throttle_fraction:rate5m clamps to 1.0, but the raw - rate(DCGM_FI_DEV_*_VIOLATION)/1e9 value is already >1 on this GPU — the - empirical nanosecond assumption is broken. Likely the DCGM exporter - version changed and the counter now grows in its documented µs units. - Re-verify on the exporter Pod and adjust the divisor (/1e9 → /1e6) in - gpu.recording.efficiency.1m before dashboards plateau at 100% throttle. - verified_on: "NVIDIA A10, DCGM 3.x — other GPU families (H100, L40S) may require a different divisor" - runbook: "If this alert fires, DCGM may have changed POWER_VIOLATION/THERMAL_VIOLATION counter units. Recalibrate by comparing raw counter rate against known throttle events; see gpu-recording.rules.yaml comments." diff --git a/packages/system/monitoring/dashboards-infra.list b/packages/system/monitoring/dashboards-infra.list index 4c7e494d..b5b9f52a 100644 --- a/packages/system/monitoring/dashboards-infra.list +++ b/packages/system/monitoring/dashboards-infra.list @@ -32,8 +32,3 @@ hubble/overview hubble/dns-namespace hubble/l7-http-metrics hubble/network-overview -gpu/gpu-performance -gpu/gpu-efficiency -gpu/gpu-quotas -gpu/gpu-fleet -gpu/gpu-tenants diff --git a/packages/system/monitoring/templates/alerta/alerta.yaml b/packages/system/monitoring/templates/alerta/alerta.yaml index d30e698d..44046d1f 100644 --- a/packages/system/monitoring/templates/alerta/alerta.yaml +++ b/packages/system/monitoring/templates/alerta/alerta.yaml @@ -181,7 +181,7 @@ metadata: app: alerta annotations: {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} spec: diff --git a/packages/system/monitoring/templates/grafana/grafana.yaml b/packages/system/monitoring/templates/grafana/grafana.yaml index d65a7dc4..d7f51e31 100644 --- a/packages/system/monitoring/templates/grafana/grafana.yaml +++ b/packages/system/monitoring/templates/grafana/grafana.yaml @@ -74,7 +74,7 @@ spec: metadata: annotations: {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: "{{ $ingress }}" + acme.cert-manager.io/http01-ingress-class: "{{ $ingress }}" {{- end }} cert-manager.io/cluster-issuer: {{ $clusterIssuer }} spec: diff --git a/packages/system/multus/templates/multus-daemonset-thick.yml b/packages/system/multus/templates/multus-daemonset-thick.yml index cad330ea..2ddc6362 100644 --- a/packages/system/multus/templates/multus-daemonset-thick.yml +++ b/packages/system/multus/templates/multus-daemonset-thick.yml @@ -155,7 +155,7 @@ spec: serviceAccountName: multus containers: - name: kube-multus - image: ghcr.io/cozystack/cozystack/multus-cni:v1.3.0@sha256:6735ffc12e5e660951f5a42943b38c308f33774a55836e94c191001405b58ec0 + image: ghcr.io/cozystack/cozystack/multus-cni:v1.3.0-rc.1@sha256:d76cc81c9ef1521e1317aacdc98360325f4fbecdfc687b97852e2f5c275551b1 command: [ "/usr/src/multus-cni/bin/multus-daemon" ] resources: requests: @@ -201,7 +201,7 @@ spec: fieldPath: spec.nodeName initContainers: - name: install-multus-binary - image: ghcr.io/cozystack/cozystack/multus-cni:v1.3.0@sha256:6735ffc12e5e660951f5a42943b38c308f33774a55836e94c191001405b58ec0 + image: ghcr.io/cozystack/cozystack/multus-cni:v1.3.0-rc.1@sha256:d76cc81c9ef1521e1317aacdc98360325f4fbecdfc687b97852e2f5c275551b1 command: - "/usr/src/multus-cni/bin/install_multus" - "-d" diff --git a/packages/system/objectstorage-controller/values.yaml b/packages/system/objectstorage-controller/values.yaml index a3859194..4def5b26 100644 --- a/packages/system/objectstorage-controller/values.yaml +++ b/packages/system/objectstorage-controller/values.yaml @@ -1,3 +1,3 @@ objectstorage: controller: - image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.3.0@sha256:7a9e4bf9c3f95f364756396815bb51b6c0f58f85db653460574d94b96cd3c7d5" + image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.3.0-rc.1@sha256:50b7eb360538dec3db747c9b28792b207068defc1f630d4bd965015d934d5279" diff --git a/packages/system/postgres-operator/Makefile b/packages/system/postgres-operator/Makefile index 5279f8a7..f6d7ddaa 100644 --- a/packages/system/postgres-operator/Makefile +++ b/packages/system/postgres-operator/Makefile @@ -3,9 +3,6 @@ export NAMESPACE=cozy-$(NAME) include ../../../hack/package.mk -test: - helm unittest . - update: rm -rf charts helm repo add cnpg https://cloudnative-pg.github.io/charts diff --git a/packages/system/postgres-operator/templates/webhook-ready-hook.yaml b/packages/system/postgres-operator/templates/webhook-ready-hook.yaml deleted file mode 100644 index 51a8ba81..00000000 --- a/packages/system/postgres-operator/templates/webhook-ready-hook.yaml +++ /dev/null @@ -1,148 +0,0 @@ -{{- /* - Post-install gate: block the HelmRelease from reporting Ready until the - cnpg admission webhook actually serves through the cluster Service. Helm - --wait on the controller pod passes once its readinessProbe passes, but - EndpointSlice propagation and kube-proxy/cilium data-plane programming - can lag by a second or two — long enough for any HelmRelease that - depends on postgres-operator (e.g. cozy-keycloak, tenant Postgres apps) - to fire its own install and have kube-apiserver hit the mcluster.cnpg.io - mutating webhook with "dial tcp :443: connect: connection refused". - - The Job uses the apiserver service proxy, which exercises the same - endpoint-resolution and apiserver-initiated pod dial that the admission - webhook path uses. Once /readyz answers through the proxy the data-plane - race is resolved. It does not verify the webhook's TLS CA bundle, so - this gate is scoped to reachability regressions, not cert rotation. - - The service name and port name are hardcoded literals. Upstream cnpg - pins the service name in charts/cloudnative-pg/values.yaml with a - comment "DO NOT CHANGE THE SERVICE NAME as it is currently used to - generate the certificate and can not be configured". The port name is - fixed in charts/cloudnative-pg/templates/service.yaml (ports[0].name: - webhook-server). If a future `make update` ever changes either literal - upstream, the sync-check helm-unittest test - (tests/webhook-ready-hook_test.yaml) renders the subchart Service and - fails if the literal drifts — forcing this template to be updated in - the same change. -*/}} -{{- $_ := required "webhookReady.image.repository must be set to the container image providing kubectl for the post-install readiness Job" .Values.webhookReady.image.repository -}} -{{- $_ := required "webhookReady.image.tag must be set for the post-install readiness Job" .Values.webhookReady.image.tag -}} -{{- /* $svcName and $portName are hardcoded literals; see header comment. */ -}} -{{- $svcName := "cnpg-webhook-service" -}} -{{- /* $portName is the service port NAME, not number — matches ports[0].name in the vendored subchart's Service. */ -}} -{{- $portName := "webhook-server" -}} -{{- $resourceName := printf "https:%s:%s" $svcName $portName -}} -{{- $maxAttempts := .Values.webhookReady.maxAttempts | default 60 -}} -{{- $sleepSeconds := .Values.webhookReady.sleepSeconds | default 2 -}} -{{- /* Derive activeDeadlineSeconds from retries + 60s slack so a values override that raises maxAttempts doesn't get silently cut. */ -}} -{{- $deadline := add (mul (int $maxAttempts) (int $sleepSeconds)) 60 -}} -{{- $image := printf "%s:%s" .Values.webhookReady.image.repository .Values.webhookReady.image.tag -}} -{{- if .Values.webhookReady.image.digest }} -{{- $image = printf "%s@%s" $image .Values.webhookReady.image.digest -}} -{{- end }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Release.Name }}-webhook-ready - namespace: {{ .Release.Namespace }} - annotations: - helm.sh/hook: post-install,post-upgrade - helm.sh/hook-weight: "0" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ .Release.Name }}-webhook-ready - namespace: {{ .Release.Namespace }} - annotations: - helm.sh/hook: post-install,post-upgrade - helm.sh/hook-weight: "0" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -rules: - - apiGroups: [""] - resources: ["services/proxy"] - resourceNames: [{{ $resourceName | quote }}] - verbs: ["get"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ .Release.Name }}-webhook-ready - namespace: {{ .Release.Namespace }} - annotations: - helm.sh/hook: post-install,post-upgrade - helm.sh/hook-weight: "0" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ .Release.Name }}-webhook-ready -subjects: - - kind: ServiceAccount - name: {{ .Release.Name }}-webhook-ready - namespace: {{ .Release.Namespace }} ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ .Release.Name }}-webhook-ready - namespace: {{ .Release.Namespace }} - annotations: - helm.sh/hook: post-install,post-upgrade - helm.sh/hook-weight: "10" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -spec: - backoffLimit: {{ .Values.webhookReady.backoffLimit | default 2 }} - activeDeadlineSeconds: {{ $deadline }} - template: - spec: - restartPolicy: Never - serviceAccountName: {{ .Release.Name }}-webhook-ready - securityContext: - runAsNonRoot: true - runAsUser: 65532 - runAsGroup: 65532 - seccompProfile: - type: RuntimeDefault - containers: - - name: wait - image: {{ $image }} - imagePullPolicy: {{ if .Values.webhookReady.image.digest }}IfNotPresent{{ else }}Always{{ end }} - resources: - requests: - cpu: 10m - memory: 32Mi - limits: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: ["ALL"] - command: - - sh - - -c - - | - set -e - ns={{ .Release.Namespace }} - proxy="/api/v1/namespaces/${ns}/services/{{ $resourceName }}/proxy/readyz" - max_attempts={{ $maxAttempts }} - sleep_seconds={{ $sleepSeconds }} - i=0 - last_err="" - until last_err=$(kubectl get --raw "$proxy" 2>&1 >/dev/null); do - i=$((i + 1)) - if [ $i -gt $max_attempts ]; then - echo "timeout: cnpg webhook did not respond through the apiserver proxy after ${max_attempts} attempts (${sleep_seconds}s each)" - echo "last error: ${last_err}" - exit 1 - fi - if [ $((i % 10)) -eq 1 ]; then - echo "attempt $i/${max_attempts}: ${last_err}" - fi - sleep "$sleep_seconds" - done - echo "cnpg webhook is ready" diff --git a/packages/system/postgres-operator/tests/webhook-ready-hook_test.yaml b/packages/system/postgres-operator/tests/webhook-ready-hook_test.yaml deleted file mode 100644 index 3253c663..00000000 --- a/packages/system/postgres-operator/tests/webhook-ready-hook_test.yaml +++ /dev/null @@ -1,328 +0,0 @@ -suite: cnpg webhook post-install readiness gate - -templates: - - templates/webhook-ready-hook.yaml - - charts/cloudnative-pg/templates/service.yaml - -release: - name: postgres-operator - namespace: cozy-postgres-operator - -tests: - - it: renders four hook objects (SA + Role + RoleBinding + Job) - template: templates/webhook-ready-hook.yaml - asserts: - - hasDocuments: - count: 4 - - - it: every rendered object carries post-install and post-upgrade hook annotations - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 0 - equal: - path: metadata.annotations["helm.sh/hook"] - value: post-install,post-upgrade - - documentIndex: 1 - equal: - path: metadata.annotations["helm.sh/hook"] - value: post-install,post-upgrade - - documentIndex: 2 - equal: - path: metadata.annotations["helm.sh/hook"] - value: post-install,post-upgrade - - documentIndex: 3 - equal: - path: metadata.annotations["helm.sh/hook"] - value: post-install,post-upgrade - - - it: RBAC is created before the Job (hook-weight ordering) - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 0 - equal: - path: kind - value: ServiceAccount - - documentIndex: 0 - equal: - path: metadata.annotations["helm.sh/hook-weight"] - value: "0" - - documentIndex: 1 - equal: - path: kind - value: Role - - documentIndex: 1 - equal: - path: metadata.annotations["helm.sh/hook-weight"] - value: "0" - - documentIndex: 2 - equal: - path: kind - value: RoleBinding - - documentIndex: 2 - equal: - path: metadata.annotations["helm.sh/hook-weight"] - value: "0" - - documentIndex: 3 - equal: - path: kind - value: Job - - documentIndex: 3 - equal: - path: metadata.annotations["helm.sh/hook-weight"] - value: "10" - - - it: RBAC resourceName matches the exact proxy URL segment the Job probes - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 1 - equal: - path: rules[0].resources[0] - value: services/proxy - - documentIndex: 1 - equal: - path: rules[0].resourceNames[0] - value: https:cnpg-webhook-service:webhook-server - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: "/api/v1/namespaces/\\$\\{ns\\}/services/https:cnpg-webhook-service:webhook-server/proxy/readyz" - - - it: hardcoded service name in the hook matches the vendored cnpg subchart Service (drift guard for make update) - template: charts/cloudnative-pg/templates/service.yaml - asserts: - - equal: - path: metadata.name - value: cnpg-webhook-service - - equal: - path: spec.ports[0].name - value: webhook-server - - - it: Job calls kubectl get --raw on the proxy path - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: "kubectl get --raw" - - - it: Job image is digest-pinned when webhookReady.image.digest is set - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - digest: sha256:b9ef7d8dbe65bcc81a46c09b8dc7543103055021c4f43287bf59e92a8f4fe05c - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].image - value: docker.io/clastix/kubectl:v1.32@sha256:b9ef7d8dbe65bcc81a46c09b8dc7543103055021c4f43287bf59e92a8f4fe05c - - - it: Job image falls back to tag-only when digest is not configured - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - digest: "" - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].image - value: docker.io/clastix/kubectl:v1.32 - - - it: backoffLimit defaults to 2 so transient pod-level failures retry instead of killing the HelmRelease - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - equal: - path: spec.backoffLimit - value: 2 - - - it: backoffLimit is overridable - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - backoffLimit: 5 - asserts: - - documentIndex: 3 - equal: - path: spec.backoffLimit - value: 5 - - - it: chart render fails when webhookReady.image.repository is empty - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: "" - tag: v1.32 - asserts: - - failedTemplate: - errorMessage: "webhookReady.image.repository must be set to the container image providing kubectl for the post-install readiness Job" - - - it: chart render fails when webhookReady.image.tag is empty - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: "" - asserts: - - failedTemplate: - errorMessage: "webhookReady.image.tag must be set for the post-install readiness Job" - - - it: retry loop bounds default when blanked so a wiped override still produces a working Job - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - maxAttempts: null - sleepSeconds: null - asserts: - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: "max_attempts=60" - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: "sleep_seconds=2" - - - it: Job pod runs non-root with seccomp RuntimeDefault for restricted-PSA clusters - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.securityContext.runAsNonRoot - value: true - - documentIndex: 3 - equal: - path: spec.template.spec.securityContext.seccompProfile.type - value: RuntimeDefault - - - it: wait container declares resource requests and limits for predictable scheduling - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].resources.requests.cpu - value: 10m - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].resources.requests.memory - value: 32Mi - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].resources.limits.cpu - value: 100m - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].resources.limits.memory - value: 64Mi - - - it: Job container drops all capabilities and runs read-only rootfs - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation - value: false - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem - value: true - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].securityContext.capabilities.drop[0] - value: ALL - - - it: imagePullPolicy is IfNotPresent when digest-pinned, Always when tag-only - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - digest: sha256:b9ef7d8dbe65bcc81a46c09b8dc7543103055021c4f43287bf59e92a8f4fe05c - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].imagePullPolicy - value: IfNotPresent - - - it: imagePullPolicy is Always when no digest is configured - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - digest: "" - asserts: - - documentIndex: 3 - equal: - path: spec.template.spec.containers[0].imagePullPolicy - value: Always - - - it: retry loop captures and surfaces the last kubectl error message on timeout - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: 'last_err=\$\(kubectl get --raw' - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: 'last error: \$\{last_err\}' - - - it: retry loop error message stays in sync when maxAttempts is bumped - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - maxAttempts: 90 - sleepSeconds: 3 - asserts: - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: "max_attempts=90" - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: "sleep_seconds=3" - - documentIndex: 3 - matchRegex: - path: spec.template.spec.containers[0].command[2] - pattern: 'after \$\{max_attempts\} attempts' - - - it: activeDeadlineSeconds scales with retry bounds so an override raise does not silently cut - template: templates/webhook-ready-hook.yaml - set: - webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - maxAttempts: 180 - sleepSeconds: 3 - asserts: - - documentIndex: 3 - equal: - path: spec.activeDeadlineSeconds - value: 600 - - - it: activeDeadlineSeconds defaults include 60s slack over the default retry window - template: templates/webhook-ready-hook.yaml - asserts: - - documentIndex: 3 - equal: - path: spec.activeDeadlineSeconds - value: 180 diff --git a/packages/system/postgres-operator/values.yaml b/packages/system/postgres-operator/values.yaml index c408220e..cae3dc53 100644 --- a/packages/system/postgres-operator/values.yaml +++ b/packages/system/postgres-operator/values.yaml @@ -3,30 +3,3 @@ cloudnative-pg: create: true image: tag: "1.27.3" -# Image used by the post-install webhook-readiness Job (see templates/webhook-ready-hook.yaml). -# Any image with kubectl on PATH works; the Job calls the apiserver service proxy with the -# hook ServiceAccount's token to confirm the mcluster.cnpg.io webhook is reachable end-to-end -# before the HelmRelease reports Ready, closing the "connection refused" bootstrap race. -# -# The tag is digest-pinned so an upstream retag does not change what runs on every install -# and upgrade across the fleet. Refresh by resolving the current manifest-list digest -# (`docker manifest inspect docker.io/clastix/kubectl:v1.32`) and updating `digest` below. -# renovate: datasource=docker depName=docker.io/clastix/kubectl -webhookReady: - image: - repository: docker.io/clastix/kubectl - tag: v1.32 - digest: sha256:b9ef7d8dbe65bcc81a46c09b8dc7543103055021c4f43287bf59e92a8f4fe05c - # Retry loop bounds for the readiness probe. Defaults total ~120s wall clock. - # Both are `default`-coerced in the template so an override that blanks them still - # produces a working Job. - maxAttempts: 60 - sleepSeconds: 2 - # Pod-level retry budget for transient node/registry failures (image pull rate limit, - # OOM, CNI hiccup). The shell loop inside the container only covers reachability retries. - # Pod retries and activeDeadlineSeconds (wall-clock bound on the whole Job across all - # pod retries) are ANDed, so activeDeadlineSeconds is the shorter of the two gates with - # the defaults above: the 60*2+60 = 180s deadline cuts the Job before backoffLimit=2 - # ever matters if pod-level failures eat more than ~60s of the budget. Raise - # maxAttempts/sleepSeconds alongside backoffLimit when tuning for slow image pulls. - backoffLimit: 2 diff --git a/packages/system/postgres-rd/cozyrds/postgres.yaml b/packages/system/postgres-rd/cozyrds/postgres.yaml index 72d013f1..c74c5783 100644 --- a/packages/system/postgres-rd/cozyrds/postgres.yaml +++ b/packages/system/postgres-rd/cozyrds/postgres.yaml @@ -8,7 +8,7 @@ spec: singular: postgres plural: postgreses openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"replicas":{"description":"Number of Postgres replicas.","type":"integer","default":2},"resources":{"description":"Explicit CPU and memory configuration for each PostgreSQL replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"10Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"version":{"description":"PostgreSQL major version to deploy","type":"string","default":"v18","enum":["v18","v17","v16","v15","v14","v13"]},"postgresql":{"description":"PostgreSQL server configuration.","type":"object","default":{},"properties":{"parameters":{"description":"PostgreSQL server parameters.","type":"object","default":{},"properties":{"max_connections":{"description":"Maximum number of concurrent connections to the database server.","type":"integer","default":100}}}}},"quorum":{"description":"Quorum configuration for synchronous replication.","type":"object","default":{},"required":["maxSyncReplicas","minSyncReplicas"],"properties":{"maxSyncReplicas":{"description":"Maximum number of synchronous replicas allowed (must be less than total replicas).","type":"integer","default":0},"minSyncReplicas":{"description":"Minimum number of synchronous replicas required for commit.","type":"integer","default":0}}},"users":{"description":"Users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"password":{"description":"Password for the user.","type":"string"},"replication":{"description":"Whether the user has replication privileges.","type":"boolean"}}}},"databases":{"description":"Databases configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"extensions":{"description":"List of enabled PostgreSQL extensions.","type":"array","items":{"type":"string"}},"roles":{"description":"Roles assigned to users.","type":"object","properties":{"admin":{"description":"List of users with admin privileges.","type":"array","items":{"type":"string"}},"readonly":{"description":"List of users with read-only privileges.","type":"array","items":{"type":"string"}}}}}}},"backup":{"description":"Backup configuration.","type":"object","default":{},"required":["enabled"],"properties":{"destinationPath":{"description":"Destination path for backups (e.g. s3://bucket/path/).","type":"string","default":"s3://bucket/path/to/folder/"},"enabled":{"description":"Enable regular backups.","type":"boolean","default":false},"endpointURL":{"description":"S3 endpoint URL for uploads.","type":"string","default":"http://minio-gateway-service:9000"},"retentionPolicy":{"description":"Retention policy (e.g. \"30d\").","type":"string","default":"30d"},"s3AccessKey":{"description":"Access key for S3 authentication.","type":"string","default":""},"s3SecretKey":{"description":"Secret key for S3 authentication.","type":"string","default":""},"schedule":{"description":"Cron schedule for automated backups.","type":"string","default":"0 2 * * * *"}}},"bootstrap":{"description":"Bootstrap configuration.","type":"object","default":{},"required":["enabled","oldName"],"properties":{"enabled":{"description":"Whether to restore from a backup.","type":"boolean","default":false},"oldName":{"description":"Previous cluster name before deletion.","type":"string","default":""},"recoveryTime":{"description":"Timestamp (RFC3339) for point-in-time recovery; empty means latest.","type":"string","default":""},"serverName":{"description":"Barman server name (S3 path prefix) used by the original cluster when writing backups. Set this only when the original cluster had an explicit barmanObjectStore.serverName that differed from its Kubernetes resource name.","type":"string","default":""}}}}} + {"title":"Chart Values","type":"object","properties":{"replicas":{"description":"Number of Postgres replicas.","type":"integer","default":2},"resources":{"description":"Explicit CPU and memory configuration for each PostgreSQL replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"10Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"version":{"description":"PostgreSQL major version to deploy","type":"string","default":"v18","enum":["v18","v17","v16","v15","v14","v13"]},"postgresql":{"description":"PostgreSQL server configuration.","type":"object","default":{},"properties":{"parameters":{"description":"PostgreSQL server parameters.","type":"object","default":{},"properties":{"max_connections":{"description":"Maximum number of concurrent connections to the database server.","type":"integer","default":100}}}}},"quorum":{"description":"Quorum configuration for synchronous replication.","type":"object","default":{},"required":["maxSyncReplicas","minSyncReplicas"],"properties":{"maxSyncReplicas":{"description":"Maximum number of synchronous replicas allowed (must be less than total replicas).","type":"integer","default":0},"minSyncReplicas":{"description":"Minimum number of synchronous replicas required for commit.","type":"integer","default":0}}},"users":{"description":"Users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"password":{"description":"Password for the user.","type":"string"},"replication":{"description":"Whether the user has replication privileges.","type":"boolean"}}}},"databases":{"description":"Databases configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"extensions":{"description":"List of enabled PostgreSQL extensions.","type":"array","items":{"type":"string"}},"roles":{"description":"Roles assigned to users.","type":"object","properties":{"admin":{"description":"List of users with admin privileges.","type":"array","items":{"type":"string"}},"readonly":{"description":"List of users with read-only privileges.","type":"array","items":{"type":"string"}}}}}}},"backup":{"description":"Backup configuration.","type":"object","default":{},"required":["enabled"],"properties":{"destinationPath":{"description":"Destination path for backups (e.g. s3://bucket/path/).","type":"string","default":"s3://bucket/path/to/folder/"},"enabled":{"description":"Enable regular backups.","type":"boolean","default":false},"endpointURL":{"description":"S3 endpoint URL for uploads.","type":"string","default":"http://minio-gateway-service:9000"},"retentionPolicy":{"description":"Retention policy (e.g. \"30d\").","type":"string","default":"30d"},"s3AccessKey":{"description":"Access key for S3 authentication.","type":"string","default":""},"s3SecretKey":{"description":"Secret key for S3 authentication.","type":"string","default":""},"schedule":{"description":"Cron schedule for automated backups.","type":"string","default":"0 2 * * * *"}}},"bootstrap":{"description":"Bootstrap configuration.","type":"object","default":{},"required":["enabled","oldName"],"properties":{"enabled":{"description":"Whether to restore from a backup.","type":"boolean","default":false},"oldName":{"description":"Previous cluster name before deletion.","type":"string","default":""},"recoveryTime":{"description":"Timestamp (RFC3339) for point-in-time recovery; empty means latest.","type":"string","default":""}}}}} release: prefix: postgres- labels: @@ -33,7 +33,7 @@ spec: # labelSelector: # helm.toolkit.fluxcd.io/name: "{reqs[0]['metadata','name']}" - keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "replicas"], ["spec", "resources"], ["spec", "resourcesPreset"], ["spec", "size"], ["spec", "storageClass"], ["spec", "external"], ["spec", "version"], ["spec", "postgresql"], ["spec", "postgresql", "parameters"], ["spec", "postgresql", "parameters", "max_connections"], ["spec", "quorum"], ["spec", "quorum", "minSyncReplicas"], ["spec", "quorum", "maxSyncReplicas"], ["spec", "users"], ["spec", "databases"], ["spec", "backup"], ["spec", "backup", "enabled"], ["spec", "backup", "retentionPolicy"], ["spec", "backup", "destinationPath"], ["spec", "backup", "endpointURL"], ["spec", "backup", "schedule"], ["spec", "backup", "s3AccessKey"], ["spec", "backup", "s3SecretKey"], ["spec", "bootstrap"], ["spec", "bootstrap", "enabled"], ["spec", "bootstrap", "recoveryTime"], ["spec", "bootstrap", "oldName"], ["spec", "bootstrap", "serverName"]] + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "replicas"], ["spec", "resources"], ["spec", "resourcesPreset"], ["spec", "size"], ["spec", "storageClass"], ["spec", "external"], ["spec", "version"], ["spec", "postgresql"], ["spec", "postgresql", "parameters"], ["spec", "postgresql", "parameters", "max_connections"], ["spec", "quorum"], ["spec", "quorum", "minSyncReplicas"], ["spec", "quorum", "maxSyncReplicas"], ["spec", "users"], ["spec", "databases"], ["spec", "backup"], ["spec", "backup", "enabled"], ["spec", "backup", "retentionPolicy"], ["spec", "backup", "destinationPath"], ["spec", "backup", "endpointURL"], ["spec", "backup", "schedule"], ["spec", "backup", "s3AccessKey"], ["spec", "backup", "s3SecretKey"], ["spec", "bootstrap"], ["spec", "bootstrap", "enabled"], ["spec", "bootstrap", "recoveryTime"], ["spec", "bootstrap", "oldName"]] secrets: exclude: [] include: diff --git a/packages/system/seaweedfs/values.yaml b/packages/system/seaweedfs/values.yaml index 3542a77f..daf2c055 100644 --- a/packages/system/seaweedfs/values.yaml +++ b/packages/system/seaweedfs/values.yaml @@ -111,7 +111,7 @@ seaweedfs: nginx.ingress.kubernetes.io/client-body-timeout: "3600" nginx.ingress.kubernetes.io/client-header-timeout: "120" nginx.ingress.kubernetes.io/service-upstream: "true" - acme.cert-manager.io/http01-ingress-ingressclassname: tenant-root + acme.cert-manager.io/http01-ingress-class: tenant-root cert-manager.io/cluster-issuer: letsencrypt-prod tls: - hosts: @@ -177,7 +177,7 @@ seaweedfs: bucketClassName: "seaweedfs" region: "" sidecar: - image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.3.0@sha256:5bcccbdb13979a16cee535eb5fbcdf0d87973689010a10b7b25e55c5be3edaa6" + image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.3.0-rc.1@sha256:5bcccbdb13979a16cee535eb5fbcdf0d87973689010a10b7b25e55c5be3edaa6" certificates: commonName: "SeaweedFS CA" ipAddresses: [] diff --git a/packages/system/velero/templates/backupstrategy-controller-rbac.yaml b/packages/system/velero/templates/backupstrategy-controller-rbac.yaml deleted file mode 100644 index 43c51cd7..00000000 --- a/packages/system/velero/templates/backupstrategy-controller-rbac.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Grants the backupstrategy-controller permission to manage ResourceModifier -# ConfigMaps in the Velero install namespace. Lives here (not in the -# backupstrategy-controller chart) so that the Role is only created when -# velero is actually installed — otherwise the chart would try to create it -# in a namespace that does not exist. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: backups.cozystack.io:strategy-controller:velero-configmaps -rules: -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "delete", "deletecollection", "patch", "update"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: backups.cozystack.io:strategy-controller:velero-configmaps -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: backups.cozystack.io:strategy-controller:velero-configmaps -subjects: -- kind: ServiceAccount - name: backupstrategy-controller - namespace: cozy-backup-controller diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.lock b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.lock index 2868e66f..1b0e2a46 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.lock +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.lock @@ -1,9 +1,9 @@ dependencies: - name: victoria-metrics-common - repository: oci://ghcr.io/victoriametrics/helm-charts - version: 0.3.0 + repository: https://victoriametrics.github.io/helm-charts + version: 0.0.46 - name: crds repository: "" version: 0.0.* -digest: sha256:adec954bf2814f744f5b69fcf67c8b246bf21f416adb0ab37d91c9b42f72d353 -generated: "2026-04-16T10:14:10.795552631Z" +digest: sha256:43d3d210a9d1a2234e6c56518f8c477125a5ad5e8ed08d46209528f19acd9c89 +generated: "2025-12-23T12:58:01.428960334Z" diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml index 030af8f0..bb9253b1 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/Chart.yaml @@ -1,7 +1,7 @@ annotations: artifacthub.io/category: monitoring-logging artifacthub.io/changes: | - - revert change in Deployment's matchLabels, that was introduced in release 0.60.0 + - updates operator to [v0.68.1](https://github.com/VictoriaMetrics/operator/releases/tag/v0.68.1) version artifacthub.io/license: Apache-2.0 artifacthub.io/links: | - name: Sources @@ -16,14 +16,13 @@ annotations: artifacthub.io/readme: | # VictoriaMetrics Operator Helm chart - Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-operator/). - Changelog is [here](https://docs.victoriametrics.com/helm/victoria-metrics-operator/changelog/). + Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-operator/) apiVersion: v2 -appVersion: v0.68.4 +appVersion: v0.68.1 dependencies: - name: victoria-metrics-common - repository: oci://ghcr.io/victoriametrics/helm-charts - version: 0.3.* + repository: https://victoriametrics.github.io/helm-charts + version: 0.0.* - condition: crds.plain name: crds repository: "" @@ -47,4 +46,4 @@ sources: - https://github.com/VictoriaMetrics/helm-charts - https://github.com/VictoriaMetrics/operator type: application -version: 0.61.0 +version: 0.59.1 diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md index 6a080424..49a06de2 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/README.md @@ -1,4 +1,3 @@ # VictoriaMetrics Operator Helm chart -Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-operator/). -Changelog is [here](https://docs.victoriametrics.com/helm/victoria-metrics-operator/changelog/). +Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-operator/) diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES index 3529783a..bf22fd3f 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/RELEASE_NOTES @@ -1,7 +1,7 @@ -# Release notes for version 0.61.0 +# Release notes for version 0.59.1 -**Release date:** 16 Apr 2026 +**Release date:** 03 Mar 2026 -![Helm: v3](https://img.shields.io/badge/Helm-v3.14%2B-informational?color=informational&logo=helm&link=https%3A%2F%2Fgithub.com%2Fhelm%2Fhelm%2Freleases%2Ftag%2Fv3.14.0) ![AppVersion: v0.68.4](https://img.shields.io/badge/v0.68.4-success?logo=VictoriaMetrics&labelColor=gray&link=https%3A%2F%2Fdocs.victoriametrics.com%2Foperator%2Fchangelog%2F%23v0684) +![Helm: v3](https://img.shields.io/badge/Helm-v3.14%2B-informational?color=informational&logo=helm&link=https%3A%2F%2Fgithub.com%2Fhelm%2Fhelm%2Freleases%2Ftag%2Fv3.14.0) ![AppVersion: v0.68.1](https://img.shields.io/badge/v0.68.1-success?logo=VictoriaMetrics&labelColor=gray&link=https%3A%2F%2Fdocs.victoriametrics.com%2Foperator%2Fchangelog%2F%23v0681) -- revert change in Deployment's matchLabels, that was introduced in release 0.60.0 +- updates operator to [v0.68.1](https://github.com/VictoriaMetrics/operator/releases/tag/v0.68.1) version diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/crds/crd.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/crds/crd.yaml index bdf7e8d0..c4138be8 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/crds/crd.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/crds/crd.yaml @@ -6079,7 +6079,6 @@ spec: - spec type: object shardCount: - format: int32 type: integer startupProbe: type: object @@ -6088,14 +6087,6 @@ spec: type: boolean statefulRollingUpdateStrategy: type: string - statefulRollingUpdateStrategyBehavior: - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - type: object statefulStorage: properties: emptyDir: @@ -12335,7 +12326,6 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true shardCount: - format: int32 type: integer startupProbe: type: object @@ -16818,9 +16808,6 @@ spec: type: boolean vmauth: properties: - enabled: - default: true - type: boolean name: type: string spec: @@ -24740,14 +24727,6 @@ spec: type: boolean statefulRollingUpdateStrategy: type: string - statefulRollingUpdateStrategyBehavior: - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - type: object statefulStorage: properties: emptyDir: @@ -28649,14 +28628,6 @@ spec: type: boolean statefulRollingUpdateStrategy: type: string - statefulRollingUpdateStrategyBehavior: - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - type: object statefulStorage: properties: emptyDir: diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/files/crd.yaml.bz2 b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/files/crd.yaml.bz2 index ab7c4d95..7f518a91 100644 Binary files a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/files/crd.yaml.bz2 and b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/crds/files/crd.yaml.bz2 differ diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/Chart.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/Chart.yaml index e8f67b95..04aba91f 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/Chart.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/Chart.yaml @@ -1,7 +1,7 @@ annotations: artifacthub.io/category: monitoring-logging artifacthub.io/changes: | - - reverted usage of `app` label in `vm.selectorLabels` + - allow setting global labels for each resource using `.Values.global.extraLabels`. See [#2607](https://github.com/VictoriaMetrics/helm-charts/issues/2607). artifacthub.io/license: Apache-2.0 artifacthub.io/links: | - name: Sources @@ -11,8 +11,7 @@ annotations: artifacthub.io/readme: | # VictoriaMetrics Common Helm chart - Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-common/). - Changelog is [here](https://docs.victoriametrics.com/helm/victoria-metrics-common/changelog/). + Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-common/) apiVersion: v2 description: VictoriaMetrics Common - contains shared templates for all Victoria Metrics helm charts @@ -30,4 +29,4 @@ name: victoria-metrics-common sources: - https://github.com/VictoriaMetrics/helm-charts type: library -version: 0.3.0 +version: 0.0.46 diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/README.md b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/README.md index c8ee7051..9ba0b4f5 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/README.md +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/README.md @@ -1,4 +1,3 @@ # VictoriaMetrics Common Helm chart -Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-common/). -Changelog is [here](https://docs.victoriametrics.com/helm/victoria-metrics-common/changelog/). +Chart documentation is available [here](https://docs.victoriametrics.com/helm/victoria-metrics-common/) diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/RELEASE_NOTES b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/RELEASE_NOTES index ad0cdfa9..055cd4c5 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/RELEASE_NOTES +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/RELEASE_NOTES @@ -1,7 +1,7 @@ -# Release notes for version 0.3.0 +# Release notes for version 0.0.46 -**Release date:** 16 Apr 2026 +**Release date:** 23 Dec 2025 ![Helm: v3](https://img.shields.io/badge/Helm-v3.14%2B-informational?color=informational&logo=helm&link=https%3A%2F%2Fgithub.com%2Fhelm%2Fhelm%2Freleases%2Ftag%2Fv3.14.0) -- reverted usage of `app` label in `vm.selectorLabels` +- allow setting global labels for each resource using `.Values.global.extraLabels`. See [#2607](https://github.com/VictoriaMetrics/helm-charts/issues/2607). diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_helpers.tpl b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_helpers.tpl index bd945678..99ac30d5 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_helpers.tpl +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_helpers.tpl @@ -125,8 +125,8 @@ If release name contains chart name it will be used as a full name. {{- $ctx := . -}} {{- $values := $Values -}} {{- range $ak := $appKey }} - {{- $values = ternary (dict) (index $values $ak | default dict) (empty $values) -}} - {{- $ctx = ternary (dict) (index $ctx $ak | default dict) (empty $ctx) -}} + {{- $values = ternary (default dict) (index $values $ak | default dict) (empty $values) -}} + {{- $ctx = ternary (default dict) (index $ctx $ak | default dict) (empty $ctx) -}} {{- if and (empty $values) (empty $ctx) -}} {{- fail (printf "No data for appKey %s" (join "->" $appKey)) -}} {{- end -}} @@ -187,9 +187,6 @@ If release name contains chart name it will be used as a full name. {{- include "vm.validate.args" . -}} {{- $Release := (.helm).Release | default .Release -}} {{- $labels := fromYaml (include "vm.selectorLabels" .) -}} - {{- with $labels.app -}} - {{- $_ := set $labels "app.kubernetes.io/component" . -}} - {{- end -}} {{- $labels = mergeOverwrite $labels (.extraLabels | default dict) -}} {{- $_ := set $labels "app.kubernetes.io/managed-by" $Release.Service -}} {{- toYaml $labels -}} @@ -200,7 +197,7 @@ If release name contains chart name it will be used as a full name. {{- include "vm.validate.args" . -}} {{- $Values := (.helm).Values | default .Values -}} {{- $globalLabels := deepCopy (($Values.global).extraLabels | default dict) -}} - {{- $labels := fromYaml (include "vm.commonLabels" .) -}} + {{- $labels := fromYaml (include "vm.selectorLabels" .) -}} {{- $labels = mergeOverwrite $globalLabels $labels (fromYaml (include "vm.metaLabels" .)) -}} {{- with (include "vm.image.tag" .) }} {{- $_ := set $labels "app.kubernetes.io/version" (regexReplaceAll "(.*)(@sha.*)" . "${1}") -}} @@ -234,16 +231,11 @@ If release name contains chart name it will be used as a full name. {{- $_ := set $labels "app.kubernetes.io/name" (include "vm.name" .) -}} {{- $_ := set $labels "app.kubernetes.io/instance" (include "vm.release" .) -}} {{- with (include "vm.app.name" .) -}} - {{- $_ := set $labels "app" . -}} + {{- if eq $.style "managed" -}} + {{- $_ := set $labels "app.kubernetes.io/component" (printf "%s-%s" (include "vm.name" $) .) -}} + {{- else -}} + {{- $_ := set $labels "app" . -}} + {{- end -}} {{- end -}} {{- toYaml $labels -}} {{- end }} - -{{- define "vm.commonLabels" -}} - {{- $labels := fromYaml (include "vm.selectorLabels" . ) -}} - {{- with $labels.app -}} - {{- $_ := set $labels "app.kubernetes.io/component" . -}} - {{- $_ := unset $labels "app" -}} - {{- end -}} - {{- toYaml $labels -}} -{{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_image.tpl b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_image.tpl index 66d019e3..6d30bd03 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_image.tpl +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_image.tpl @@ -42,8 +42,8 @@ Victoria Metrics Image {{- with .appKey -}} {{- $appKey := ternary (list .) . (kindIs "string" .) -}} {{- range $ak := $appKey -}} - {{- $values = ternary (dict) (index $values $ak | default dict) (empty $values) -}} - {{- $ctx = ternary (dict) (index $ctx $ak | default dict) (empty $ctx) -}} + {{- $values = ternary (default dict) (index $values $ak | default dict) (empty $values) -}} + {{- $ctx = ternary (default dict) (index $ctx $ak | default dict) (empty $ctx) -}} {{- if and (empty $values) (empty $ctx) -}} {{- fail (printf "No data for appKey %s" (join "->" $appKey)) -}} {{- end -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_pod.tpl b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_pod.tpl index 62981dfb..7534ae2d 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_pod.tpl +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_pod.tpl @@ -39,9 +39,9 @@ Render probe {{- define "vm.probe" -}} {{- /* undefined value */ -}} {{- $null := (fromYaml "value: null").value -}} - {{- $probe := dig .type (dict) .app.probe -}} + {{- $probe := dig .type (default dict) .app.probe -}} {{- $probeType := "" -}} - {{- $defaultProbe := dict -}} + {{- $defaultProbe := default dict -}} {{- if ne (dig "httpGet" $null $probe) $null -}} {{- /* httpGet probe */ -}} {{- $defaultProbe = dict "path" (include "vm.probe.http.path" .) "scheme" (include "vm.probe.http.scheme" .) "port" (include "vm.probe.port" .) -}} @@ -51,7 +51,7 @@ Render probe {{- $defaultProbe = dict "port" (include "vm.probe.port" .) -}} {{- $probeType = "tcpSocket" -}} {{- end -}} - {{- $defaultProbe = ternary (dict) (dict $probeType $defaultProbe) (empty $probeType) -}} + {{- $defaultProbe = ternary (default dict) (dict $probeType $defaultProbe) (empty $probeType) -}} {{- $probe = mergeOverwrite $defaultProbe $probe -}} {{- range $key, $value := $probe -}} {{- if and (has (kindOf $value) (list "object" "map")) (ne $key $probeType) -}} @@ -100,7 +100,7 @@ Net probe port command line arguments */ -}} {{- define "vm.args" -}} - {{- $args := list -}} + {{- $args := default list -}} {{- range $key, $value := . -}} {{- if not $key -}} {{- fail "Empty key in command line args is not allowed" -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_service.tpl b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_service.tpl index 77cdeee7..77a1365f 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_service.tpl +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/charts/victoria-metrics-common/templates/_service.tpl @@ -37,10 +37,10 @@ {{- $values := $Values -}} {{- $ctx := . -}} {{- range $ak := $appKey -}} - {{- $values = ternary (dict) (index $values $ak | default dict) (empty $values) -}} - {{- $ctx = ternary (dict) (index $ctx $ak | default dict) (empty $ctx) -}} + {{- $values = ternary (default dict) (index $values $ak | default dict) (empty $values) -}} + {{- $ctx = ternary (default dict) (index $ctx $ak | default dict) (empty $ctx) -}} {{- end -}} - {{- $spec := dict -}} + {{- $spec := default dict -}} {{- if $ctx -}} {{- $spec = $ctx -}} {{- else if $values -}} @@ -69,10 +69,10 @@ {{- $values := $Values -}} {{- $ctx := . -}} {{- range $ak := $appKey -}} - {{- $values = ternary (dict) (index $values $ak | default dict) (empty $values) -}} - {{- $ctx = ternary (dict) (index $ctx $ak | default dict) (empty $ctx) -}} + {{- $values = ternary (default dict) (index $values $ak | default dict) (empty $values) -}} + {{- $ctx = ternary (default dict) (index $ctx $ak | default dict) (empty $ctx) -}} {{- end -}} - {{- $spec := dict -}} + {{- $spec := default dict -}} {{- if $values -}} {{- $spec = $values -}} {{- else if $ctx -}} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt index 41f39937..7fb3fbd9 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/NOTES.txt @@ -1,5 +1,5 @@ {{ include "vm.name" . }} has been installed. Check its status by running: - kubectl --namespace {{ include "vm.namespace" . }} get pods -l "app.kubernetes.io/name={{ include "vm.name" . }}" -l "app.kubernetes.io/instance={{ include "vm.release" . }}" + kubectl --namespace {{ include "vm.namespace" . }} get pods -l "app.kubernetes.io/instance={{ $.Release.Name }}" Get more information on https://github.com/VictoriaMetrics/helm-charts/tree/master/charts/victoria-metrics-operator. See "Getting started guide for VM Operator" on https://docs.victoriametrics.com/guides/getting-started-with-vm-operator diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml index 9ec3c2c2..8abd9dea 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/pdb.yaml @@ -18,9 +18,6 @@ spec: {{- with $pdb.maxUnavailable }} maxUnavailable: {{ . }} {{- end }} - {{- with $pdb.unhealthyPodEvictionPolicy }} - unhealthyPodEvictionPolicy: {{ . }} - {{- end }} selector: matchLabels: {{ include "vm.selectorLabels" $ctx | nindent 6 }} {{- end }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/server.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/server.yaml index 9d7fd7ed..e224c074 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/server.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/server.yaml @@ -18,12 +18,9 @@ metadata: annotations: {{ toYaml . | nindent 4 }} {{- end }} spec: - replicas: {{ .Values.replicaCount }} + replicas: {{.Values.replicaCount }} selector: matchLabels: {{ include "vm.selectorLabels" $ctx | nindent 6 }} - {{- with .Values.strategy }} - strategy: {{ toYaml . | nindent 4 }} - {{- end }} template: metadata: {{- with .Values.annotations }} diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml index e38f7448..51039cae 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/templates/webhook.yaml @@ -1,31 +1,22 @@ -{{- $webhooks := .Values.admissionWebhooks }} -{{- if $webhooks.enabled }} +{{- if .Values.admissionWebhooks.enabled }} {{- $ctx := dict "helm" . "extraLabels" .Values.extraLabels }} {{- $tls := fromYaml (include "vm-operator.certs" $ctx) }} {{- $fullname := include "vm.plain.fullname" $ctx }} {{- $domain := ((.Values.global).cluster).dnsDomain }} {{- $ns := include "vm.namespace" $ctx }} -{{- $certManager := $webhooks.certManager }} +{{- $certManager := .Values.admissionWebhooks.certManager }} {{- $files := .Files }} {{- $crds := $files.Get "crd.yaml" | splitList "---" }} -{{- $disabledFor := $webhooks.disabledFor | default list }} +{{- $disabledFor := .Values.admissionWebhooks.disabledFor | default list }} --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: {{ $fullname }}-admission - {{- if or $certManager.enabled $webhooks.annotations }} + {{- if $certManager.enabled }} annotations: - {{- if $certManager.enabled }} certmanager.k8s.io/inject-ca-from: {{ printf "%s/%s-validation" $ns $fullname | quote }} cert-manager.io/inject-ca-from: {{ printf "%s/%s-validation" $ns $fullname | quote }} - {{- end }} - {{- with $certManager.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with $webhooks.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} {{- end }} labels: {{ include "vm.labels" $ctx | nindent 4 }} webhooks: @@ -43,7 +34,7 @@ webhooks: {{- if not $certManager.enabled }} caBundle: {{ $tls.caCert }} {{- end }} - failurePolicy: {{ $webhooks.policy }} + failurePolicy: {{ $.Values.admissionWebhooks.policy }} name: '{{ $crd.metadata.name }}' admissionReviewVersions: - v1 diff --git a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml index 3a1027f2..279ceee9 100644 --- a/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml +++ b/packages/system/victoria-metrics-operator/charts/victoria-metrics-operator/values.yaml @@ -125,7 +125,7 @@ crds: # whenUnsatisfiable: DoNotSchedule # labelSelector: # matchLabels: - # app.kubernetes.io/component: alertmanager + # app: alertmanager # -- Labels to add to the upgrade job labels: {} @@ -276,12 +276,8 @@ service: # -- See `kubectl explain poddisruptionbudget.spec` for more or check [these docs](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) podDisruptionBudget: enabled: false - # -- min number or percentage of pods that can be unavailable - minAvailable: 0 - # -- max number or percentage of pods that can be unavailable - maxUnavailable: 0 - # -- Defines criteria when unhealthy pods should be considered for eviction - unhealthyPodEvictionPolicy: + # minAvailable: 1 + # maxUnavailable: 1 labels: {} # -- Graceful pod termination timeout. See [this article](https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#hook-handler-execution) for details. @@ -303,13 +299,6 @@ resources: # -- Pod's node selector. Details are [here](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) nodeSelector: {} -# -- Deployment strategy, set to standard k8s default -strategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 25% - maxUnavailable: 25% - # -- Name of Priority Class priorityClassName: "" @@ -375,8 +364,6 @@ shareProcessNamespace: false admissionWebhooks: # -- Enables validation webhook. enabled: true - # -- Annotations for webhook. Can be used to define Helm or ArgoCD annotations. - annotations: {} # -- List of CRD names to disable validation for disabledFor: [] # - vmagent diff --git a/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml b/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml index e56bd9dd..e93fa86b 100644 --- a/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml +++ b/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml @@ -8,7 +8,7 @@ spec: singular: vminstance plural: vminstances openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"externalMethod":{"description":"Method to pass through traffic to the VM.","type":"string","default":"PortList","enum":["PortList","WholeIP"]},"externalPorts":{"description":"Ports to forward from outside the cluster.","type":"array","default":[22],"items":{"type":"integer"}},"externalAllowICMP":{"description":"Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect.","type":"boolean","default":true},"runStrategy":{"description":"Requested running state of the VirtualMachineInstance","type":"string","default":"Always","enum":["Always","Halted","Manual","RerunOnFailure","Once"]},"instanceType":{"description":"Virtual Machine instance type.","type":"string","default":"u1.medium"},"instanceProfile":{"description":"Virtual Machine preferences profile.","type":"string","default":"ubuntu","enum":["alpine","centos.7","centos.7.desktop","centos.stream10","centos.stream10.desktop","centos.stream8","centos.stream8.desktop","centos.stream8.dpdk","centos.stream9","centos.stream9.desktop","centos.stream9.dpdk","cirros","fedora","fedora.arm64","opensuse.leap","opensuse.tumbleweed","rhel.10","rhel.10.arm64","rhel.7","rhel.7.desktop","rhel.8","rhel.8.desktop","rhel.8.dpdk","rhel.9","rhel.9.arm64","rhel.9.desktop","rhel.9.dpdk","rhel.9.realtime","sles","ubuntu","windows.10","windows.10.virtio","windows.11","windows.11.virtio","windows.2k16","windows.2k16.virtio","windows.2k19","windows.2k19.virtio","windows.2k22","windows.2k22.virtio","windows.2k25","windows.2k25.virtio",""]},"disks":{"description":"List of disks to attach.","type":"array","default":[],"items":{"type":"object","required":["name"],"properties":{"bus":{"description":"Disk bus type (e.g. \"sata\").","type":"string"},"name":{"description":"Disk name.","type":"string"}}}},"networks":{"description":"Networks to attach the VM to.","type":"array","default":[],"items":{"type":"object","properties":{"name":{"description":"Network attachment name.","type":"string"}}}},"subnets":{"description":"Deprecated: use networks instead.","type":"array","default":[],"items":{"type":"object","properties":{"name":{"description":"Network attachment name.","type":"string"}}}},"gpus":{"description":"List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).","type":"array","default":[],"items":{"type":"object","required":["name"],"properties":{"name":{"description":"The name of the GPU resource to attach.","type":"string"}}}},"cpuModel":{"description":"Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map","type":"string","default":""},"resources":{"description":"Resource configuration for the virtual machine.","type":"object","default":{},"properties":{"cpu":{"description":"Number of CPU cores allocated.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Amount of memory allocated.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"sockets":{"description":"Number of CPU sockets (vCPU topology).","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"sshKeys":{"description":"List of SSH public keys for authentication.","type":"array","default":[],"items":{"type":"string"}},"cloudInit":{"description":"Cloud-init user data.","type":"string","default":""},"cloudInitSeed":{"description":"Seed string to generate SMBIOS UUID for the VM.","type":"string","default":""}}} + {"title":"Chart Values","type":"object","properties":{"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"externalMethod":{"description":"Method to pass through traffic to the VM.","type":"string","default":"PortList","enum":["PortList","WholeIP"]},"externalPorts":{"description":"Ports to forward from outside the cluster.","type":"array","default":[22],"items":{"type":"integer"}},"runStrategy":{"description":"Requested running state of the VirtualMachineInstance","type":"string","default":"Always","enum":["Always","Halted","Manual","RerunOnFailure","Once"]},"instanceType":{"description":"Virtual Machine instance type.","type":"string","default":"u1.medium"},"instanceProfile":{"description":"Virtual Machine preferences profile.","type":"string","default":"ubuntu","enum":["alpine","centos.7","centos.7.desktop","centos.stream10","centos.stream10.desktop","centos.stream8","centos.stream8.desktop","centos.stream8.dpdk","centos.stream9","centos.stream9.desktop","centos.stream9.dpdk","cirros","fedora","fedora.arm64","opensuse.leap","opensuse.tumbleweed","rhel.10","rhel.10.arm64","rhel.7","rhel.7.desktop","rhel.8","rhel.8.desktop","rhel.8.dpdk","rhel.9","rhel.9.arm64","rhel.9.desktop","rhel.9.dpdk","rhel.9.realtime","sles","ubuntu","windows.10","windows.10.virtio","windows.11","windows.11.virtio","windows.2k16","windows.2k16.virtio","windows.2k19","windows.2k19.virtio","windows.2k22","windows.2k22.virtio","windows.2k25","windows.2k25.virtio",""]},"disks":{"description":"List of disks to attach.","type":"array","default":[],"items":{"type":"object","required":["name"],"properties":{"bus":{"description":"Disk bus type (e.g. \"sata\").","type":"string"},"name":{"description":"Disk name.","type":"string"}}}},"networks":{"description":"Networks to attach the VM to.","type":"array","default":[],"items":{"type":"object","properties":{"name":{"description":"Network attachment name.","type":"string"}}}},"subnets":{"description":"Deprecated: use networks instead.","type":"array","default":[],"items":{"type":"object","properties":{"name":{"description":"Network attachment name.","type":"string"}}}},"gpus":{"description":"List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).","type":"array","default":[],"items":{"type":"object","required":["name"],"properties":{"name":{"description":"The name of the GPU resource to attach.","type":"string"}}}},"cpuModel":{"description":"Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map","type":"string","default":""},"resources":{"description":"Resource configuration for the virtual machine.","type":"object","default":{},"properties":{"cpu":{"description":"Number of CPU cores allocated.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Amount of memory allocated.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"sockets":{"description":"Number of CPU sockets (vCPU topology).","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"sshKeys":{"description":"List of SSH public keys for authentication.","type":"array","default":[],"items":{"type":"string"}},"cloudInit":{"description":"Cloud-init user data.","type":"string","default":""},"cloudInitSeed":{"description":"Seed string to generate SMBIOS UUID for the VM.","type":"string","default":""}}} release: prefix: vm-instance- labels: @@ -26,7 +26,7 @@ spec: tags: - compute icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODdfMzQ1NCkiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzY4N18zNDU0KSI+CjxwYXRoIGQ9Ik04OS41MDM5IDExMS43MDdINTQuNDk3QzU0LjE3MjcgMTExLjcwNyA1NC4wMTA4IDExMS4yMjEgNTQuMzM0OSAxMTEuMDU5TDU3LjI1MjIgMTA4Ljk1MkM2MC4zMzE0IDEwNi42ODMgNjEuOTUyMiAxMDIuNjMxIDYwLjk3OTcgOTguNzQxMkg4My4wMjFDODIuMDQ4NSAxMDIuNjMxIDgzLjY2OTMgMTA2LjY4MyA4Ni43NDg1IDEwOC45NTJMODkuNjY1OCAxMTEuMDU5Qzg5Ljk5IDExMS4yMjEgODkuODI3OSAxMTEuNzA3IDg5LjUwMzkgMTExLjcwN1oiIGZpbGw9IiNCMEI2QkIiLz4KPHBhdGggZD0iTTExMy4zMjggOTguNzQxSDMwLjY3MjVDMjcuNTkzMSA5OC43NDEgMjUgOTYuMTQ4IDI1IDkzLjA2ODdWMzMuMTAzMkMyNSAzMC4wMjM5IDI3LjU5MzEgMjcuNDMwNyAzMC42NzI1IDI3LjQzMDdIMTEzLjMyOEMxMTYuNDA3IDI3LjQzMDcgMTE5IDMwLjAyMzcgMTE5IDMzLjEwMzJWOTMuMDY4N0MxMTkgOTYuMTQ4IDExNi40MDcgOTguNzQxIDExMy4zMjggOTguNzQxWiIgZmlsbD0iI0U4RURFRSIvPgo8cGF0aCBkPSJNMTE5IDg0LjE1NDlIMjVWMzMuMTAzMkMyNSAzMC4wMjM5IDI3LjU5MzEgMjcuNDMwNyAzMC42NzI1IDI3LjQzMDdIMTEzLjMyOEMxMTYuNDA3IDI3LjQzMDcgMTE5IDMwLjAyMzcgMTE5IDMzLjEwMzJMMTE5IDg0LjE1NDlaIiBmaWxsPSIjMDBCM0ZGIi8+CjxwYXRoIGQ9Ik05MC42Mzc0IDExNi41NjlINTMuMzYxNkM1Mi4wNjUxIDExNi41NjkgNTAuOTMwNyAxMTUuNDM1IDUwLjkzMDcgMTE0LjEzOEM1MC45MzA3IDExMi44NDEgNTIuMDY1MSAxMTEuNzA3IDUzLjM2MTYgMTExLjcwN0g5MC42Mzc0QzkxLjkzMzkgMTExLjcwNyA5My4wNjg0IDExMi44NDEgOTMuMDY4NCAxMTQuMTM4QzkzLjA2ODQgMTE1LjQzNSA5MS45MzM5IDExNi41NjkgOTAuNjM3NCAxMTYuNTY5WiIgZmlsbD0iI0U4RURFRSIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi41Mjc1IDUzLjgzNjdDNzIuNDQzMSA1My44MzUxIDcyLjM2MDUgNTMuODEyMiA3Mi4yODczIDUzLjc3MDFMNTYuNDY5OSA0NC43OTM0QzU2LjM5ODMgNDQuNzUxOSA1Ni4zMzg4IDQ0LjY5MjMgNTYuMjk3MyA0NC42MjA3QzU2LjI1NTkgNDQuNTQ5IDU2LjIzMzggNDQuNDY3OCA1Ni4yMzM0IDQ0LjM4NUM1Ni4yMzM0IDQ0LjIxNjkgNTYuMzI1OCA0NC4wNjE3IDU2LjQ2OTkgNDMuOTc4NUw3Mi4xOTEyIDM1LjA2MDlDNzIuMjYzNyAzNS4wMjEgNzIuMzQ1IDM1IDcyLjQyNzcgMzVDNzIuNTEwNSAzNSA3Mi41OTE4IDM1LjAyMSA3Mi42NjQzIDM1LjA2MDlMODguNDg3MiA0NC4wMzk1Qzg4LjU1OTEgNDQuMDgwMSA4OC42MTg4IDQ0LjEzOTIgODguNjYgNDQuMjEwN0M4OC43MDEzIDQ0LjI4MjIgODguNzIyNyA0NC4zNjM1IDg4LjcyMTkgNDQuNDQ2Qzg4LjcyMjUgNDQuNTI4NSA4OC43MDEgNDQuNjA5NyA4OC42NTk4IDQ0LjY4MTJDODguNjE4NSA0NC43NTI2IDg4LjU1ODkgNDQuODExOCA4OC40ODcyIDQ0Ljg1MjVMNzIuNzcxNCA1My43NjgzQzcyLjY5NzIgNTMuODExNCA3Mi42MTMzIDUzLjgzNDkgNzIuNTI3NSA1My44MzY3IiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBvcGFjaXR5PSIwLjciIGQ9Ik03MC4yNTUzIDc1LjY1MTdDNzAuMTcxIDc1LjY1MzUgNzAuMDg3OCA3NS42MzE3IDcwLjAxNTEgNzUuNTg4OEw1NC4yNDU4IDY2LjY0MTdDNTQuMTcxNSA2Ni42MDI0IDU0LjEwOTUgNjYuNTQzNiA1NC4wNjYxIDY2LjQ3MTZDNTQuMDIyOCA2Ni4zOTk3IDU0IDY2LjMxNzMgNTQgNjYuMjMzM1Y0OC4yNzhDNTQgNDguMTA4IDU0LjA5MjQgNDcuOTU0NiA1NC4yNDM5IDQ3Ljg2OTZDNTQuMzE3MiA0Ny44MjcxIDU0LjQwMDQgNDcuODA0NyA1NC40ODUxIDQ3LjgwNDdDNTQuNTY5NyA0Ny44MDQ3IDU0LjY1MjkgNDcuODI3MSA1NC43MjYyIDQ3Ljg2OTZMNzAuNDkzNyA1Ni44MTMxQzcwLjU2NDIgNTYuODU2NSA3MC42MjI1IDU2LjkxNyA3MC42NjMyIDU2Ljk4OTFDNzAuNzAzOSA1Ny4wNjEyIDcwLjcyNTcgNTcuMTQyNCA3MC43MjY1IDU3LjIyNTFWNzUuMTgwNUM3MC43MjU5IDc1LjI2MjggNzAuNzA0MiA3NS4zNDM2IDcwLjY2MzUgNzUuNDE1MUM3MC42MjI3IDc1LjQ4NjYgNzAuNTY0MiA3NS41NDY0IDcwLjQ5MzcgNzUuNTg4OEM3MC40MjA2IDc1LjYyOTEgNzAuMzM4NyA3NS42NTA3IDcwLjI1NTMgNzUuNjUxNyIgZmlsbD0id2hpdGUiLz4KPHBhdGggb3BhY2l0eT0iMC40IiBkPSJNNzQuNzE5OCA3NS42NTExQzc0LjYzMzMgNzUuNjUxMiA3NC41NDgyIDc1LjYyOTYgNzQuNDcyMiA3NS41ODgzQzc0LjQwMTYgNzUuNTQ2MSA3NC4zNDMyIDc1LjQ4NjIgNzQuMzAyNyA3NS40MTQ3Qzc0LjI2MjMgNzUuMzQzMSA3NC4yNDExIDc1LjI2MjIgNzQuMjQxMiA3NS4xOFY1Ny4zMzczQzc0LjI0MTIgNTcuMTcxIDc0LjMzMzYgNTcuMDE1OCA3NC40NzIyIDU2LjkyOUw5MC4yMzk3IDQ3Ljk4NTVDOTAuMzExOSA0Ny45NDM4IDkwLjM5MzggNDcuOTIxOSA5MC40NzcxIDQ3LjkyMTlDOTAuNTYwNSA0Ny45MjE5IDkwLjY0MjQgNDcuOTQzOCA5MC43MTQ2IDQ3Ljk4NTVDOTAuNzg3NiA0OC4wMjU1IDkwLjg0ODUgNDguMDg0MiA5MC44OTExIDQ4LjE1NTdDOTAuOTMzNyA0OC4yMjcyIDkwLjk1NjMgNDguMzA4OCA5MC45NTY2IDQ4LjM5MlY2Ni4yMzI4QzkwLjk1NyA2Ni4zMTY0IDkwLjkzNDcgNjYuMzk4NSA5MC44OTIxIDY2LjQ3MDRDOTAuODQ5NSA2Ni41NDI0IDkwLjc4ODEgNjYuNjAxNCA5MC43MTQ2IDY2LjY0MTFMNzQuOTUyNiA3NS41ODgzQzc0Ljg4MjUgNzUuNjMwNyA3NC44MDE4IDc1LjY1MjUgNzQuNzE5OCA3NS42NTExIiBmaWxsPSJ3aGl0ZSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzY4N18zNDU0IiB4MT0iMTYxIiB5MT0iMTgwIiB4Mj0iMy41OTI4NGUtMDciIHkyPSI0Ljk5OTk4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNTk1NjU2Ii8+CjwvbGluZWFyR3JhZGllbnQ+CjxjbGlwUGF0aCBpZD0iY2xpcDBfNjg3XzM0NTQiPgo8cmVjdCB3aWR0aD0iOTQiIGhlaWdodD0iOTQiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNSAyNSkiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K - keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "external"], ["spec", "externalMethod"], ["spec", "externalPorts"], ["spec", "externalAllowICMP"], ["spec", "runStrategy"], ["spec", "instanceType"], ["spec", "instanceProfile"], ["spec", "disks"], ["spec", "networks"], ["spec", "subnets"], ["spec", "gpus"], ["spec", "cpuModel"], ["spec", "resources"], ["spec", "sshKeys"], ["spec", "cloudInit"], ["spec", "cloudInitSeed"]] + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "external"], ["spec", "externalMethod"], ["spec", "externalPorts"], ["spec", "runStrategy"], ["spec", "instanceType"], ["spec", "instanceProfile"], ["spec", "disks"], ["spec", "networks"], ["spec", "subnets"], ["spec", "gpus"], ["spec", "cpuModel"], ["spec", "resources"], ["spec", "sshKeys"], ["spec", "cloudInit"], ["spec", "cloudInitSeed"]] secrets: exclude: [] include: [] diff --git a/pkg/cmd/server/start.go b/pkg/cmd/server/start.go index 7ebbbc89..f7791332 100644 --- a/pkg/cmd/server/start.go +++ b/pkg/cmd/server/start.go @@ -160,34 +160,6 @@ func (o *CozyServerOptions) Complete() error { // Convert to ResourceConfig o.ResourceConfig = &config.ResourceConfig{} for _, crd := range crdList.Items { - release := config.ReleaseConfig{ - Prefix: crd.Spec.Release.Prefix, - Labels: crd.Spec.Release.Labels, - ChartRef: config.ChartRefConfig{ - Kind: crd.Spec.Release.ChartRef.Kind, - Name: crd.Spec.Release.ChartRef.Name, - Namespace: crd.Spec.Release.ChartRef.Namespace, - }, - } - // Per-Application HelmRelease Install/Upgrade timeout. Applications - // whose parent chart contains asynchronously-provisioned resources - // the chart itself depends on (for example, the Kamaji-provisioned - // admin-kubeconfig Secret for Kubernetes tenants) need a longer - // wait budget than the Flux default. Consumed by the REST storage - // layer when building the HelmRelease Spec. The parser rejects - // units Flux would reject at webhook time, so a bad annotation - // surfaces as a loud startup failure instead of a silent drop to - // defaults. - d, err := config.ParseHelmInstallTimeoutAnnotation( - crd.Annotations[config.HelmInstallTimeoutAnnotation], - ) - if err != nil { - return fmt.Errorf( - "ApplicationDefinition %q has invalid %s annotation: %w", - crd.Name, config.HelmInstallTimeoutAnnotation, err, - ) - } - release.HelmInstallTimeout = d resource := config.Resource{ Application: config.ApplicationConfig{ Kind: crd.Spec.Application.Kind, @@ -196,7 +168,15 @@ func (o *CozyServerOptions) Complete() error { ShortNames: []string{}, // TODO: implement shortnames OpenAPISchema: crd.Spec.Application.OpenAPISchema, }, - Release: release, + Release: config.ReleaseConfig{ + Prefix: crd.Spec.Release.Prefix, + Labels: crd.Spec.Release.Labels, + ChartRef: config.ChartRefConfig{ + Kind: crd.Spec.Release.ChartRef.Kind, + Name: crd.Spec.Release.ChartRef.Name, + Namespace: crd.Spec.Release.ChartRef.Namespace, + }, + }, } o.ResourceConfig.Resources = append(o.ResourceConfig.Resources, resource) } diff --git a/pkg/config/config.go b/pkg/config/config.go index 21de27b2..1e123e2c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -16,48 +16,6 @@ limitations under the License. package config -import ( - "fmt" - "regexp" - "time" -) - -// HelmInstallTimeoutAnnotation is the ApplicationDefinition metadata -// annotation key that overrides the Flux HelmRelease Install.Timeout and -// Upgrade.Timeout for a given Application kind. -const HelmInstallTimeoutAnnotation = "release.cozystack.io/helm-install-timeout" - -// helmTimeoutPattern mirrors the CRD validation pattern used by Flux -// helm-controller on HelmReleaseSpec.Install.Timeout (ms/s/m/h units only). -// time.ParseDuration accepts ns/us/µs, but Flux rejects them - parsing here -// with the same shape avoids feeding the controller a value it will later -// reject at webhook time. See -// github.com/fluxcd/helm-controller/api/v2 HelmReleaseSpec.Install.Timeout -// in the go module cache. -var helmTimeoutPattern = regexp.MustCompile(`^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$`) - -// ParseHelmInstallTimeoutAnnotation parses the value of the -// release.cozystack.io/helm-install-timeout annotation. The empty string is -// treated as "unset" and returns (0, nil) so callers can leave -// HelmInstallTimeout zeroed and let flux defaults apply. Values accepted by -// time.ParseDuration but rejected by Flux (ns/us/µs) return a helpful -// error instead of silently parsing and failing later at HelmRelease -// admission. -func ParseHelmInstallTimeoutAnnotation(raw string) (time.Duration, error) { - if raw == "" { - return 0, nil - } - if !helmTimeoutPattern.MatchString(raw) { - return 0, fmt.Errorf("must match %s (Flux accepts ms/s/m/h units only), got %q", - helmTimeoutPattern, raw) - } - d, err := time.ParseDuration(raw) - if err != nil { - return 0, fmt.Errorf("time.ParseDuration(%q): %w", raw, err) - } - return d, nil -} - // ResourceConfig represents the structure of the configuration file. type ResourceConfig struct { Resources []Resource `yaml:"resources"` @@ -83,12 +41,6 @@ type ReleaseConfig struct { Prefix string `yaml:"prefix"` Labels map[string]string `yaml:"labels"` ChartRef ChartRefConfig `yaml:"chartRef"` - // HelmInstallTimeout overrides the Flux HelmRelease Install.Timeout and - // Upgrade.Timeout for this Application kind. When zero, flux defaults - // apply. Populated from the - // release.cozystack.io/helm-install-timeout annotation on the - // ApplicationDefinition at start-up. - HelmInstallTimeout time.Duration `yaml:"helmInstallTimeout,omitempty"` } // ChartRefConfig references a Flux source artifact for the Helm chart. diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go deleted file mode 100644 index eb6990af..00000000 --- a/pkg/config/config_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package config - -import ( - "strings" - "testing" - "time" -) - -// Cover the annotation parser used by cozystack-api at startup. The parser -// is consumed by pkg/cmd/server/start.go on every ApplicationDefinition; a -// typo here silently drops back to flux defaults and the Kubernetes tenant -// race described in cozystack#2412 reappears, so the table must exercise: -// - the unset path (empty string treated as "no override"), -// - every unit Flux accepts (ms, s, m, h), -// - compound forms (the CRD pattern accepts repeats), -// - units time.ParseDuration accepts but Flux rejects (ns, us, µs), -// - outright garbage. -func TestParseHelmInstallTimeoutAnnotation(t *testing.T) { - cases := []struct { - name string - input string - want time.Duration - wantErr bool - errMatch string - }{ - { - name: "empty string leaves flux defaults in place", - input: "", - want: 0, - }, - { - name: "minutes", - input: "15m", - want: 15 * time.Minute, - }, - { - name: "hours", - input: "1h", - want: time.Hour, - }, - { - name: "seconds", - input: "45s", - want: 45 * time.Second, - }, - { - name: "milliseconds", - input: "500ms", - want: 500 * time.Millisecond, - }, - { - name: "compound hour and minutes", - input: "2h30m", - want: 2*time.Hour + 30*time.Minute, - }, - { - name: "decimal minutes", - input: "1.5m", - want: 90 * time.Second, - }, - { - name: "nanoseconds rejected - Flux CRD pattern excludes ns", - input: "500ns", - wantErr: true, - errMatch: "Flux accepts ms/s/m/h units only", - }, - { - name: "microseconds rejected - Flux CRD pattern excludes us", - input: "500us", - wantErr: true, - errMatch: "Flux accepts ms/s/m/h units only", - }, - { - name: "microseconds unicode rejected", - input: "500µs", - wantErr: true, - errMatch: "Flux accepts ms/s/m/h units only", - }, - { - name: "bare digits rejected", - input: "15", - wantErr: true, - errMatch: "Flux accepts ms/s/m/h units only", - }, - { - name: "garbage rejected", - input: "abc", - wantErr: true, - errMatch: "Flux accepts ms/s/m/h units only", - }, - { - name: "negative rejected", - input: "-15m", - wantErr: true, - errMatch: "Flux accepts ms/s/m/h units only", - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - got, err := ParseHelmInstallTimeoutAnnotation(tc.input) - if tc.wantErr { - if err == nil { - t.Fatalf("expected error, got duration=%v", got) - } - if tc.errMatch != "" && !strings.Contains(err.Error(), tc.errMatch) { - t.Errorf("error %q does not contain %q", err.Error(), tc.errMatch) - } - return - } - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if got != tc.want { - t.Errorf("got %v, want %v", got, tc.want) - } - }) - } -} diff --git a/pkg/registry/apps/application/rest.go b/pkg/registry/apps/application/rest.go index d233ecc3..0728ea13 100644 --- a/pkg/registry/apps/application/rest.go +++ b/pkg/registry/apps/application/rest.go @@ -1528,24 +1528,6 @@ func (r *REST) convertApplicationToHelmRelease(app *appsv1alpha1.Application) (* }, } - // Per-Application HelmRelease wait budget. The mechanism is generic: - // an ApplicationDefinition that sets - // release.cozystack.io/helm-install-timeout gets Install.Timeout and - // Upgrade.Timeout populated from ReleaseConfig.HelmInstallTimeout - // (parsed at startup). Applications that leave it unset keep flux - // defaults so their failed installs remediate on the normal cadence. - // Today only kubernetes-rd carries the annotation because the - // Kubernetes Application's parent chart contains CAPI/Kamaji - // resources whose admin-kubeconfig Secret is provisioned - // asynchronously and Kamaji cold-start routinely exceeds flux's - // default wait budget; any future kind with the same shape can opt - // in by setting the same annotation. - if r.releaseConfig.HelmInstallTimeout > 0 { - timeout := metav1.Duration{Duration: r.releaseConfig.HelmInstallTimeout} - helmRelease.Spec.Install.Timeout = &timeout - helmRelease.Spec.Upgrade.Timeout = &timeout - } - return helmRelease, nil } diff --git a/pkg/registry/apps/application/rest_timeout_test.go b/pkg/registry/apps/application/rest_timeout_test.go deleted file mode 100644 index 85ac0b97..00000000 --- a/pkg/registry/apps/application/rest_timeout_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package application - -import ( - "testing" - "time" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - appsv1alpha1 "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1" - "github.com/cozystack/cozystack/pkg/config" -) - -func newRESTForTimeout(kind, prefix string, helmInstallTimeout time.Duration) *REST { - return &REST{ - kindName: kind, - releaseConfig: config.ReleaseConfig{ - Prefix: prefix, - ChartRef: config.ChartRefConfig{ - Kind: "HelmChart", - Name: "x", - Namespace: "cozy-system", - }, - HelmInstallTimeout: helmInstallTimeout, - }, - } -} - -// Table-driven: every Application kind carries a per-CRD HelmRelease wait -// budget. The Kubernetes kind's parent chart contains CAPI/Kamaji resources -// whose admin-kubeconfig Secret is provisioned asynchronously, so its -// ApplicationDefinition sets release.cozystack.io/helm-install-timeout=15m -// (or longer). Other kinds leave the annotation unset and keep flux defaults -// so their failed installs remediate on the normal cadence. The test must -// cover both paths: a kind with the timeout set and one without. -func TestConvertApplicationToHelmRelease_AppliesReleaseConfigTimeout(t *testing.T) { - cases := []struct { - name string - kind string - prefix string - configured time.Duration - wantSet bool - }{ - { - name: "Kubernetes kind with 15m configured gets Install and Upgrade Timeout", - kind: "Kubernetes", - prefix: "kubernetes-", - configured: 15 * time.Minute, - wantSet: true, - }, - { - // Fictional kind on purpose: the test is about the unset path - // regardless of which real Application kind ends up needing a - // timeout override. Using a real kind name would create false - // coupling to that Application's ApplicationDefinition. - name: "unrelated kind without configured timeout keeps flux defaults", - kind: "PlaceholderKindForDefaults", - prefix: "placeholder-", - configured: 0, - wantSet: false, - }, - { - name: "arbitrary future kind with 20m configured gets 20m", - kind: "TalosCluster", - prefix: "talos-", - configured: 20 * time.Minute, - wantSet: true, - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - r := newRESTForTimeout(tc.kind, tc.prefix, tc.configured) - app := &appsv1alpha1.Application{ - ObjectMeta: metav1.ObjectMeta{Name: "example", Namespace: "tenant-root"}, - } - - hr, err := r.convertApplicationToHelmRelease(app) - if err != nil { - t.Fatalf("convertApplicationToHelmRelease returned error: %v", err) - } - - if hr.Spec.Install == nil || hr.Spec.Upgrade == nil { - t.Fatalf("Spec.Install/Upgrade must be non-nil") - } - - if tc.wantSet { - if hr.Spec.Install.Timeout == nil { - t.Fatalf("Spec.Install.Timeout must be set when HelmInstallTimeout=%v", tc.configured) - } - if hr.Spec.Install.Timeout.Duration != tc.configured { - t.Errorf("Spec.Install.Timeout = %v, want %v", hr.Spec.Install.Timeout.Duration, tc.configured) - } - if hr.Spec.Upgrade.Timeout == nil { - t.Fatalf("Spec.Upgrade.Timeout must be set when HelmInstallTimeout=%v", tc.configured) - } - if hr.Spec.Upgrade.Timeout.Duration != tc.configured { - t.Errorf("Spec.Upgrade.Timeout = %v, want %v", hr.Spec.Upgrade.Timeout.Duration, tc.configured) - } - } else { - if hr.Spec.Install.Timeout != nil { - t.Errorf("Spec.Install.Timeout must be nil when HelmInstallTimeout=0, got %v", hr.Spec.Install.Timeout.Duration) - } - if hr.Spec.Upgrade.Timeout != nil { - t.Errorf("Spec.Upgrade.Timeout must be nil when HelmInstallTimeout=0, got %v", hr.Spec.Upgrade.Timeout.Duration) - } - } - - if hr.Spec.Install.Remediation == nil || hr.Spec.Install.Remediation.Retries != -1 { - t.Errorf("Spec.Install.Remediation.Retries must remain -1, got %+v", hr.Spec.Install.Remediation) - } - if hr.Spec.Upgrade.Remediation == nil || hr.Spec.Upgrade.Remediation.Retries != -1 { - t.Errorf("Spec.Upgrade.Remediation.Retries must remain -1, got %+v", hr.Spec.Upgrade.Remediation) - } - }) - } -} diff --git a/pkg/registry/core/tenantnamespace/rest.go b/pkg/registry/core/tenantnamespace/rest.go index 4ee97eb0..f1ed3fab 100644 --- a/pkg/registry/core/tenantnamespace/rest.go +++ b/pkg/registry/core/tenantnamespace/rest.go @@ -17,8 +17,6 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" @@ -26,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/watch" "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" - "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" @@ -126,18 +123,8 @@ func (r *REST) Get( return nil, apierrors.NewNotFound(r.gvr.GroupResource(), name) } - // Check if user has access to this namespace - hasAccess, err := r.hasAccessToNamespace(ctx, name) - if err != nil { - return nil, err - } - if !hasAccess { - // Return Forbidden to follow standard K8s RBAC behavior - return nil, apierrors.NewForbidden(r.gvr.GroupResource(), name, fmt.Errorf("access denied")) - } - ns := &corev1.Namespace{} - err = r.c.Get(ctx, types.NamespacedName{Namespace: "", Name: name}, ns, &client.GetOptions{Raw: opts}) + err := r.c.Get(ctx, types.NamespacedName{Namespace: "", Name: name}, ns, &client.GetOptions{Raw: opts}) if err != nil { return nil, err } @@ -156,33 +143,11 @@ func (r *REST) Get( // ----------------------------------------------------------------------------- func (r *REST) Watch(ctx context.Context, opts *metainternal.ListOptions) (watch.Interface, error) { - // Extract user identity once for the lifetime of the watch — it does not - // change between events and rebuilding it per event is wasteful. - u, ok := request.UserFrom(ctx) - if !ok { - return nil, apierrors.NewUnauthorized("user missing in context") - } - username := u.GetName() - groups := make(map[string]struct{}) - for _, group := range u.GetGroups() { - groups[group] = struct{}{} - } - nsList := &corev1.NamespaceList{} - - // Build upstream watch options with field and label selectors - rawOpts := &metav1.ListOptions{ + nsWatch, err := r.w.Watch(ctx, nsList, &client.ListOptions{Raw: &metav1.ListOptions{ Watch: true, ResourceVersion: opts.ResourceVersion, - } - if opts.FieldSelector != nil { - rawOpts.FieldSelector = opts.FieldSelector.String() - } - if opts.LabelSelector != nil { - rawOpts.LabelSelector = opts.LabelSelector.String() - } - - nsWatch, err := r.w.Watch(ctx, nsList, &client.ListOptions{Raw: rawOpts}) + }}) if err != nil { return nil, err } @@ -224,30 +189,6 @@ func (r *REST) Watch(ctx context.Context, opts *metainternal.ListOptions) (watch continue } - // Apply defensive filtering for field and label selectors - if opts.FieldSelector != nil { - if !opts.FieldSelector.Matches(fields.Set{"metadata.name": ns.Name}) { - continue - } - } - if opts.LabelSelector != nil { - if !opts.LabelSelector.Matches(labels.Set(ns.Labels)) { - continue - } - } - - // Check if user has access to this namespace using the cached - // identity — avoids re-extracting user/groups on every event. - hasAccess, err := r.hasAccessToNamespaceForUser(ctx, ns.Name, username, groups) - if err != nil { - klog.ErrorS(err, "Failed to check access for namespace in watch", "namespace", ns.Name) - continue - } - if !hasAccess { - // User doesn't have access, skip this event - continue - } - out := &corev1alpha1.TenantNamespace{ TypeMeta: metav1.TypeMeta{ APIVersion: corev1alpha1.SchemeGroupVersion.String(), @@ -368,26 +309,6 @@ func (r *REST) makeList(src *corev1.NamespaceList, allowed []string) *corev1alph return out } -// matchesSubject checks if a RoleBinding subject matches the user's identity. -// It handles Group, User, and ServiceAccount subjects with proper namespace fallback. -func matchesSubject(subj rbacv1.Subject, bindingNamespace, username string, groups map[string]struct{}) bool { - switch subj.Kind { - case "Group": - _, ok := groups[subj.Name] - return ok - case "User": - return subj.Name == username - case "ServiceAccount": - saNamespace := subj.Namespace - if saNamespace == "" { - saNamespace = bindingNamespace - } - return username == fmt.Sprintf("system:serviceaccount:%s:%s", saNamespace, subj.Name) - default: - return false - } -} - func (r *REST) filterAccessible( ctx context.Context, names []string, @@ -426,9 +347,22 @@ func (r *REST) filterAccessible( subjectLoop: for j := range rbs.Items[i].Subjects { subj := rbs.Items[i].Subjects[j] - if matchesSubject(subj, rbs.Items[i].Namespace, u.GetName(), groups) { - allowedNameSet[rbs.Items[i].Namespace] = struct{}{} - break subjectLoop + switch subj.Kind { + case "Group": + if _, ok = groups[subj.Name]; ok { + allowedNameSet[rbs.Items[i].Namespace] = struct{}{} + break subjectLoop + } + case "User": + if subj.Name == u.GetName() { + allowedNameSet[rbs.Items[i].Namespace] = struct{}{} + break subjectLoop + } + case "ServiceAccount": + if u.GetName() == fmt.Sprintf("system:serviceaccount:%s:%s", subj.Namespace, subj.Name) { + allowedNameSet[rbs.Items[i].Namespace] = struct{}{} + break subjectLoop + } } } } @@ -439,60 +373,6 @@ func (r *REST) filterAccessible( return allowed, nil } -// hasAccessToNamespace checks if the user has access to a single namespace. -// This is optimized for Get/Watch operations where we check one namespace at a time. -// It lists RoleBindings only in the target namespace instead of all cluster RoleBindings. -func (r *REST) hasAccessToNamespace( - ctx context.Context, - namespace string, -) (bool, error) { - u, ok := request.UserFrom(ctx) - if !ok { - return false, fmt.Errorf("user missing in context") - } - groups := make(map[string]struct{}) - for _, group := range u.GetGroups() { - groups[group] = struct{}{} - } - return r.hasAccessToNamespaceForUser(ctx, namespace, u.GetName(), groups) -} - -// hasAccessToNamespaceForUser is the inner check that does not re-extract user -// identity from context. Use this in hot paths (e.g. the Watch loop) where the -// caller has already cached the user name and groups. -func (r *REST) hasAccessToNamespaceForUser( - ctx context.Context, - namespace, username string, - groups map[string]struct{}, -) (bool, error) { - // Check privileged groups - if _, ok := groups["system:masters"]; ok { - return true, nil - } - if _, ok := groups["cozystack-cluster-admin"]; ok { - return true, nil - } - - // List RoleBindings only in the target namespace - rbs := &rbacv1.RoleBindingList{} - err := r.c.List(ctx, rbs, client.InNamespace(namespace)) - if err != nil { - return false, fmt.Errorf("failed to list rolebindings in %s: %w", namespace, err) - } - - // Check if user is in any RoleBinding subjects - for i := range rbs.Items { - for j := range rbs.Items[i].Subjects { - subj := rbs.Items[i].Subjects[j] - if matchesSubject(subj, rbs.Items[i].Namespace, username, groups) { - return true, nil - } - } - } - - return false, nil -} - // ----------------------------------------------------------------------------- // Boiler-plate // ----------------------------------------------------------------------------- diff --git a/pkg/registry/core/tenantnamespace/rest_test.go b/pkg/registry/core/tenantnamespace/rest_test.go index 52d2a075..7f2979bc 100644 --- a/pkg/registry/core/tenantnamespace/rest_test.go +++ b/pkg/registry/core/tenantnamespace/rest_test.go @@ -3,20 +3,10 @@ package tenantnamespace import ( - "context" "testing" corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/apiserver/pkg/endpoints/request" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" ) func TestMakeListSortsAlphabetically(t *testing.T) { @@ -48,466 +38,3 @@ func TestMakeListSortsAlphabetically(t *testing.T) { } } } - -// Security tests for IDOR fix - -func TestHasAccessToNamespace_WithUserAccess(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "User", Name: "test-user", APIGroup: "rbac.authorization.k8s.io"}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "test-user", - Groups: []string{"system:authenticated"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !hasAccess { - t.Error("expected user to have access, but got false") - } -} - -func TestHasAccessToNamespace_WithoutAccess(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - // RoleBinding for different user - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "User", Name: "other-user", APIGroup: "rbac.authorization.k8s.io"}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "test-user", - Groups: []string{"system:authenticated"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if hasAccess { - t.Error("expected user to NOT have access, but got true") - } -} - -func TestHasAccessToNamespace_WithGroupAccess(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "Group", Name: "test-group", APIGroup: "rbac.authorization.k8s.io"}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "test-user", - Groups: []string{"system:authenticated", "test-group"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !hasAccess { - t.Error("expected user to have access via group, but got false") - } -} - -func TestHasAccessToNamespace_SystemMasters(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "admin", - Groups: []string{"system:masters"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !hasAccess { - t.Error("expected system:masters to have access, but got false") - } -} - -func TestHasAccessToNamespace_CozyAdminGroup(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "cozy-admin", - Groups: []string{"cozystack-cluster-admin"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !hasAccess { - t.Error("expected cozystack-cluster-admin to have access, but got false") - } -} - -func TestHasAccessToNamespace_ServiceAccount(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "ServiceAccount", Name: "test-sa", Namespace: "tenant-test"}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "system:serviceaccount:tenant-test:test-sa", - Groups: []string{"system:authenticated"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !hasAccess { - t.Error("expected service account to have access, but got false") - } -} - -func TestHasAccessToNamespace_ServiceAccountEmptyNamespace(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - // ServiceAccount subject with empty namespace should default to RoleBinding namespace - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "ServiceAccount", Name: "test-sa", Namespace: ""}, // Empty namespace - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "system:serviceaccount:tenant-test:test-sa", - Groups: []string{"system:authenticated"}, - } - ctx := request.WithUser(context.Background(), u) - - hasAccess, err := r.hasAccessToNamespace(ctx, "tenant-test") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !hasAccess { - t.Error("expected service account with empty namespace to have access, but got false") - } -} - -func TestGet_WithAccess(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "User", Name: "test-user", APIGroup: "rbac.authorization.k8s.io"}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "test-user", - Groups: []string{"system:authenticated"}, - } - ctx := request.WithUser(context.Background(), u) - - obj, err := r.Get(ctx, "tenant-test", &metav1.GetOptions{}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - tn, ok := obj.(*corev1alpha1.TenantNamespace) - if !ok { - t.Fatalf("expected *TenantNamespace, got %T", obj) - } - if tn.Name != "tenant-test" { - t.Errorf("expected name %q, got %q", "tenant-test", tn.Name) - } - if tn.Kind != "TenantNamespace" { - t.Errorf("expected Kind=TenantNamespace, got %q", tn.Kind) - } - if tn.APIVersion != corev1alpha1.SchemeGroupVersion.String() { - t.Errorf("expected APIVersion=%q, got %q", corev1alpha1.SchemeGroupVersion.String(), tn.APIVersion) - } -} - -func TestGet_WithoutAccess(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: "tenant-test"}, - } - - // RoleBinding for different user - rb := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-binding", - Namespace: "tenant-test", - }, - Subjects: []rbacv1.Subject{ - {Kind: "User", Name: "other-user", APIGroup: "rbac.authorization.k8s.io"}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "test-role", - }, - } - - client := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(ns, rb). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "test-user", - Groups: []string{"system:authenticated"}, - } - ctx := request.WithUser(context.Background(), u) - - obj, err := r.Get(ctx, "tenant-test", &metav1.GetOptions{}) - if err == nil { - t.Fatal("expected error, got nil") - } - if obj != nil { - t.Errorf("expected nil object, got %v", obj) - } - - // Verify it returns Forbidden to follow standard K8s RBAC behavior - if !apierrors.IsForbidden(err) { - t.Errorf("expected Forbidden error, got %v", err) - } -} - -func TestGet_NonTenantNamespace(t *testing.T) { - scheme := runtime.NewScheme() - _ = corev1.AddToScheme(scheme) - _ = rbacv1.AddToScheme(scheme) - - client := fake.NewClientBuilder(). - WithScheme(scheme). - Build() - - r := &REST{ - c: client, - gvr: schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}, - } - - u := &user.DefaultInfo{ - Name: "test-user", - Groups: []string{"system:masters"}, - } - ctx := request.WithUser(context.Background(), u) - - obj, err := r.Get(ctx, "default", &metav1.GetOptions{}) - if err == nil { - t.Fatal("expected error for non-tenant namespace, got nil") - } - if obj != nil { - t.Errorf("expected nil object, got %v", obj) - } - if !apierrors.IsNotFound(err) { - t.Errorf("expected NotFound error, got %v", err) - } -}