feat(kubernetes): bootstrap tenant workers with Talos via CABPT#2931
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis PR replaces Ubuntu container-disk/kubeadm worker bootstrap with Talos-based workers, adds the Talos bootstrap provider and Talos hook templates, upgrades the Kamaji provider, extends API and values schemas, updates migrations, and wires a HelmRelease disable-wait annotation into the Go server. ChangesTalos Worker Bootstrap and Provider Upgrades
Sequence Diagram(s)sequenceDiagram
participant Helm as Helm install/upgrade
participant Secrets as talos-secrets.yaml
participant PKI as talos-pki.yaml
participant RecJob as talos-reconcile-job
participant BtJob as bootstrap-token-job
participant KCP as KamajiControlPlane
participant TCPT as TalosConfigTemplate
Helm->>Secrets: create or reuse Talos credentials Secret
Helm->>PKI: render Talos CA and signer TLS cert
Helm->>RecJob: run post-install/post-upgrade hook
RecJob->>RecJob: wait for Service ClusterIP, CA, and kube-dns
RecJob->>KCP: patch certSANs with DNS names and ClusterIP
RecJob->>TCPT: apply TalosConfigTemplate per node group
Helm->>BtJob: run post-install/post-upgrade hook
BtJob->>BtJob: create bootstrap-token Secret and RBAC
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 markdownlint-cli2 (0.22.1)packages/apps/kubernetes/README.mdmarkdownlint-cli2 v0.22.1 (markdownlint v0.40.0) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request implements a significant architectural shift in the Kubernetes worker bootstrap process by migrating from Ubuntu with kubeadm to Talos Linux. The changes include the integration of the Cluster API Bootstrap Provider for Talos (CABPT), the addition of a CSR signer sidecar for secure certificate management, and updated Helm workflows to handle the asynchronous nature of Talos configuration. This transition improves node security and lifecycle management while maintaining compatibility with existing tenant clusters. Highlights
New Features🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request migrates the Kubernetes tenant worker bootstrap from Ubuntu containerDisk + kubeadm to Talos OS, introducing TalosConfigTemplate, Talos PKI infrastructure, a talos-csr-signer sidecar, and post-install reconcile Jobs to resolve asynchronous dependencies. It also upgrades the Kamaji control plane provider to v0.19.0 and adds platform migrations to handle the transition. The review feedback highlights several critical issues: Dockerfiles reference a non-existent Go version 1.26; the talos-reconcile-job incorrectly injects base64 certificates instead of indented PEM certificates and lacks a document separator in its multi-nodeGroup loop; Makefiles contain shell expansion bugs when patches are empty; and both the bootstrap-token and reconcile Jobs require restricted security contexts, resource limits, and minimized service account token mounting.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| # To bump the upstream version, update COMMIT below to the desired master | ||
| # SHA and rerun `make image-talos-csr-signer` in packages/apps/kubernetes; | ||
| # the regenerated images/talos-csr-signer.tag must be committed alongside. | ||
| FROM golang:1.26 AS builder |
| # which our chart relies on for the talos-trustd sidecar port. Once | ||
| # upstream ships a real migration path, drop both this Dockerfile and the | ||
| # patch and consume vanilla upstream images directly. | ||
| FROM golang:1.26 AS builder |
| TALOS_CA_B64=$(kubectl -n "$NS" get secret "${RELEASE}-talos-ca" -o jsonpath='{.data.tls\.crt}' 2>/dev/null || true) | ||
| K8S_CA_B64=$(kubectl -n "$NS" get secret "${RELEASE}-ca" -o jsonpath='{.data.ca\.crt}' 2>/dev/null || true) | ||
| COREDNS_IP=$(kubectl -n kube-system get svc kube-dns -o jsonpath='{.spec.clusterIP}' 2>/dev/null || true) | ||
| if [ -n "$SVC_IP" ] && [ -n "$TALOS_CA_B64" ] && [ -n "$K8S_CA_B64" ] && [ -n "$COREDNS_IP" ]; then | ||
| break | ||
| fi | ||
| sleep 5 | ||
| done | ||
| if [ -z "$SVC_IP" ] || [ -z "$TALOS_CA_B64" ] || [ -z "$K8S_CA_B64" ] || [ -z "$COREDNS_IP" ]; then | ||
| echo "[$(date -u +%H:%M:%S)] timed out waiting for lookup inputs (svc='$SVC_IP' talos-ca=$([ -n "$TALOS_CA_B64" ] && echo ok) k8s-ca=$([ -n "$K8S_CA_B64" ] && echo ok) coredns='$COREDNS_IP')" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
The kubectl get secret command returns the raw base64-encoded certificate from the secret. Injecting this base64 string directly into the Talos machineconfig ca.crt field will fail because Talos expects a PEM-encoded certificate. Additionally, a multi-line PEM certificate must be properly indented to preserve the YAML structure. Decode the certificates using base64 -d and format them with the correct indentation (28 spaces) using sed.
TALOS_CA=$(kubectl -n "$NS" get secret "${RELEASE}-talos-ca" -o jsonpath='{.data.tls\.crt}' 2>/dev/null | base64 -d | sed 's/^/ /' || true)
K8S_CA=$(kubectl -n "$NS" get secret "${RELEASE}-ca" -o jsonpath='{.data.ca\.crt}' 2>/dev/null | base64 -d | sed 's/^/ /' || true)
COREDNS_IP=$(kubectl -n kube-system get svc kube-dns -o jsonpath='{.spec.clusterIP}' 2>/dev/null || true)
if [ -n "$SVC_IP" ] && [ -n "$TALOS_CA" ] && [ -n "$K8S_CA" ] && [ -n "$COREDNS_IP" ]; then
break
fi
sleep 5
done
if [ -z "$SVC_IP" ] || [ -z "$TALOS_CA" ] || [ -z "$K8S_CA" ] || [ -z "$COREDNS_IP" ]; then
echo "[$(date -u +%H:%M:%S)] timed out waiting for lookup inputs (svc='$SVC_IP' talos-ca=$([ -n "$TALOS_CA" ] && echo ok) k8s-ca=$([ -n "$K8S_CA" ] && echo ok) coredns='$COREDNS_IP')"
exit 1
fi| ca: | ||
| crt: ${TALOS_CA_B64} |
| ca: | ||
| crt: ${K8S_CA_B64} |
| containers: | ||
| - name: kubectl | ||
| image: "{{ default (.Files.Get "images/kubectl.tag" | trim) .Values.images.kubectl }}" |
There was a problem hiding this comment.
The kubectl container is running without a restricted securityContext. To adhere to the repository security guidelines, please define a securityContext that drops all capabilities, runs as a non-root user, and disables privilege escalation.
containers:
- name: kubectl
image: "{{ default (.Files.Get "images/kubectl.tag" | trim) .Values.images.kubectl }}"
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 65532
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefaultReferences
- Flag missing securityContext, containers running as root, or other RBAC/SecurityContext issues. (link)
| spec: | ||
| restartPolicy: OnFailure | ||
| serviceAccountName: {{ .Release.Name }}-bootstrap-token-tenant |
There was a problem hiding this comment.
Since this Job only communicates with the tenant cluster using the mounted admin kubeconfig and does not need to access the management cluster's API, we should disable automounting the service account token to follow the principle of least privilege.
spec:
restartPolicy: OnFailure
automountServiceAccountToken: false
serviceAccountName: {{ .Release.Name }}-bootstrap-token-tenantReferences
- Flag missing securityContext, containers running as root, or other RBAC/SecurityContext issues. (link)
| containers: | ||
| - name: kubectl | ||
| image: "{{ default ($.Files.Get "images/kubectl.tag" | trim) $.Values.images.kubectl }}" |
There was a problem hiding this comment.
The kubectl container in the talos-reconcile Job is running without a restricted securityContext. Please define a securityContext to drop all capabilities, run as a non-root user, and disable privilege escalation.
containers:
- name: kubectl
image: "{{ default ($.Files.Get "images/kubectl.tag" | trim) $.Values.images.kubectl }}"
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 65532
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefaultReferences
- Flag missing securityContext, containers running as root, or other RBAC/SecurityContext issues. (link)
| for p in patches/*.diff; do \ | ||
| (cd .update-tmp && patch bootstrap-components.yaml < ../$$p) || exit 1; \ | ||
| done |
There was a problem hiding this comment.
If there are no .diff files in the patches/ directory, the shell expansion patches/*.diff will remain literal, causing the loop to fail. Add a check to ensure the file exists before attempting to apply the patch.
for p in patches/*.diff; do \
[ -e "$$p" ] || continue; \
(cd .update-tmp && patch bootstrap-components.yaml < ../$$p) || exit 1; \
done
| for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \ | ||
| git apply --recount "$$p"; \ | ||
| done |
There was a problem hiding this comment.
If there are no .diff files in the patches/ directory, the shell expansion will remain literal and cause the git apply command to fail. Add a check to ensure the file exists before applying.
for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \
[ -e "$$p" ] || continue; \
git apply --recount "$$p"; \
done
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/apps/kubernetes/images/kubectl.tag`:
- Line 1: Update the kubectl version pinned in the kubectl.tag file from 1.33.4
to a version that supports the full Kubernetes tenant range (v1.31–v1.35). The
current version 1.33.4 violates the Kubernetes Version Skew Policy and breaks
the bootstrap-token job for tenants running v1.31 or v1.35. Update the version
to 1.34 or another version that accommodates the full v1.31–v1.35 window while
maintaining compatibility with the version skew requirements (kubectl must be
within ±1 minor version of kube-apiserver).
In `@packages/apps/kubernetes/templates/cluster.yaml`:
- Around line 608-614: The maxUnhealthy field currently uses the `| int` filter
to coerce non-percentage values to integers, which can silently accept invalid
input and change remediation behavior unexpectedly. Add validation logic that
checks whether non-percentage values (those not ending with "%") are valid
integers before attempting coercion; if the value is not a valid integer and not
a percentage string, the template should fail with a clear error message rather
than silently coercing the invalid input through the `| int` filter.
In `@packages/core/platform/images/migrations/migrations/44`:
- Around line 45-80: The HELM_RELEASE_LABEL constant is set to filter by an
annotation (meta.helm.sh/release-name) instead of a label, causing the kubectl
selector in the list_helm_managed function to return no objects. Update the
HELM_RELEASE_LABEL constant definition to use the standard Helm-managed label
app.kubernetes.io/managed-by=Helm instead, which Helm automatically injects into
all managed resources. This will ensure the kubectl get command in
list_helm_managed properly identifies and returns Helm-managed objects that need
to be annotated with the resource policy.
In
`@packages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yaml`:
- Around line 652-654: The targetPort in the https port definition for the
metrics Service is set to `https`, but the corresponding Deployment container
only exposes a port named `metrics` at port 8443. Change the targetPort value
from `https` to `metrics` in the Service definition so that traffic is correctly
routed to the container port that actually exists.
In `@packages/system/capi-providers-cpprovider/Makefile`:
- Around line 45-48: In the update target, the git commit command at line 45 is
failing when git user.name and user.email are not configured globally, but this
commit is unnecessary for patch application. Remove the `git commit -qm init &&`
portion from the command chain in the update target while keeping the `git init
-q` and `git add .` commands, since only these are required for the subsequent
git apply operations to work correctly.
In `@packages/system/kubernetes-rd/cozyrds/kubernetes.yaml`:
- Line 35: The nodeHealthCheck fields maxUnhealthy and nodeStartupTimeout lack
validation patterns, allowing invalid values to pass API validation and cause
issues during chart rendering. Rather than editing the generated YAML directly,
locate the cozyvalues-gen source input file that defines this schema and add
proper validation patterns there: add a pattern constraint for maxUnhealthy to
enforce integer-or-percent format (e.g., bare integers or percentage strings
like "50%"), and add a duration pattern constraint for nodeStartupTimeout (e.g.,
durations like "10m"). Then regenerate the downstream kubernetes.yaml artifact
from the cozyvalues-gen source to ensure schema consistency across all generated
outputs.
In `@pkg/config/config.go`:
- Around line 74-89: The ParseHelmInstallDisableWaitAnnotation function
documents case-insensitive boolean parsing but only handles specific hardcoded
variations like "true", "True", "TRUE", so mixed-case inputs like "tRue"
incorrectly error. Fix this by converting the input string to lowercase once at
the beginning (using strings.ToLower or similar) and then checking against the
lowercase values "true" and "false", which makes it genuinely case-insensitive.
Also update the TestParseHelmInstallDisableWaitAnnotation test to include
mixed-case test cases and verify they pass with the corrected implementation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e4c773d1-f593-458c-8bbb-94537369f537
⛔ Files ignored due to path filters (2)
packages/system/capi-providers-bootstrap/files/components-talos.gzis excluded by!**/*.gzpackages/system/capi-providers-cpprovider/files/components.gzis excluded by!**/*.gz
📒 Files selected for processing (61)
.github/workflows/pull-requests.yamlMakefileapi/apps/v1alpha1/kubernetes/types.goapi/apps/v1alpha1/kubernetes/zz_generated.deepcopy.gohack/e2e-apps/run-kubernetes.shpackages/apps/kubernetes/Makefilepackages/apps/kubernetes/README.mdpackages/apps/kubernetes/files/versions.yamlpackages/apps/kubernetes/images/kubectl.tagpackages/apps/kubernetes/images/talos-csr-signer.tagpackages/apps/kubernetes/images/talos-csr-signer/Dockerfilepackages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tagpackages/apps/kubernetes/images/ubuntu-container-disk/Dockerfilepackages/apps/kubernetes/templates/_helpers.tplpackages/apps/kubernetes/templates/cluster.yamlpackages/apps/kubernetes/templates/copy-patch-containerd.yamlpackages/apps/kubernetes/templates/helmreleases/cilium.yamlpackages/apps/kubernetes/templates/helmreleases/ouroboros.yamlpackages/apps/kubernetes/templates/talos/bootstrap-token-tenant-job.yamlpackages/apps/kubernetes/templates/talos/talos-pki.yamlpackages/apps/kubernetes/templates/talos/talos-reconcile-job.yamlpackages/apps/kubernetes/templates/talos/talos-secrets.yamlpackages/apps/kubernetes/tests/cluster_test.yamlpackages/apps/kubernetes/tests/containerd-config-path-test.shpackages/apps/kubernetes/tests/fixtures/containerd-1x.tomlpackages/apps/kubernetes/tests/fixtures/containerd-2x.tomlpackages/apps/kubernetes/tests/gpu_node_labels_test.yamlpackages/apps/kubernetes/tests/kubelet-reservation_test.yamlpackages/apps/kubernetes/tests/kubelet_reservation_test.yamlpackages/apps/kubernetes/tests/mhc_rendering_test.yamlpackages/apps/kubernetes/tests/talos_k8s_support_matrix_test.yamlpackages/apps/kubernetes/tests/talos_templates_test.yamlpackages/apps/kubernetes/values.schema.jsonpackages/apps/kubernetes/values.yamlpackages/core/platform/images/migrations/migrations/44packages/core/platform/images/migrations/migrations/45packages/core/platform/values.yamlpackages/system/capi-providers-bootstrap/Makefilepackages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yamlpackages/system/capi-providers-bootstrap/files/metadata-talos.yamlpackages/system/capi-providers-bootstrap/patches/0001-rename-default-sa-to-cabpt-manager.diffpackages/system/capi-providers-bootstrap/templates/configmaps.yamlpackages/system/capi-providers-bootstrap/templates/providers.yamlpackages/system/capi-providers-cpprovider/Makefilepackages/system/capi-providers-cpprovider/files/control-plane-components.yamlpackages/system/capi-providers-cpprovider/files/metadata.yamlpackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji.tagpackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/Dockerfilepackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/patches/0001-backport-additional-service-ports-pr347.diffpackages/system/capi-providers-cpprovider/templates/configmaps.yamlpackages/system/capi-providers-cpprovider/templates/providers.yamlpackages/system/kubernetes-rd/cozyrds/kubernetes.yamlpkg/cmd/server/start.gopkg/config/config.gopkg/config/config_test.gopkg/registry/apps/application/rest.go
💤 Files with no reviewable changes (13)
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tag
- packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tag
- packages/apps/kubernetes/templates/copy-patch-containerd.yaml
- packages/apps/kubernetes/tests/fixtures/containerd-2x.toml
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tag
- packages/apps/kubernetes/tests/containerd-config-path-test.sh
- packages/apps/kubernetes/files/versions.yaml
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tag
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tag
- packages/apps/kubernetes/tests/kubelet-reservation_test.yaml
- packages/apps/kubernetes/tests/fixtures/containerd-1x.toml
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tag
| @@ -0,0 +1 @@ | |||
| docker.io/alpine/k8s:1.33.4@sha256:b0523f0a244ddc4c8e055aa335c040d3d78b3ead5528f4544395f7f9f69c7b68 | |||
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
According to the official Kubernetes Version Skew Policy, which kubectl minor versions are supported against kube-apiserver 1.31 and 1.35?
💡 Result:
According to the official Kubernetes Version Skew Policy, kubectl is supported if its minor version is within one minor version (older or newer) of the kube-apiserver [1][2]. For the specified kube-apiserver versions, the supported kubectl minor versions are as follows: - Against kube-apiserver 1.31: kubectl minor versions 1.30, 1.31, and 1.32 are supported [1][2]. - Against kube-apiserver 1.35: kubectl minor versions 1.34, 1.35, and 1.36 are supported [1][2]. In environments where multiple kube-apiserver instances exist (such as in a highly available cluster), if there is a version skew between the API server instances themselves, the supported range for kubectl is narrowed to the intersection of the supported ranges for all active API server versions [1].
Citations:
- 1: https://kubernetes.io/releases/version-skew-policy/
- 2: https://www.plural.sh/blog/kubernetes-compatibility-matrix/
Update kubectl minor version to support the full Kubernetes tenant range (v1.31–v1.35).
Line 1 pins kubectl to version 1.33.4. However, this violates Kubernetes Version Skew Policy across the chart's supported tenant versions:
kubectl1.33 requireskube-apiserver1.32–1.34 (within ±1 minor)- Against
kube-apiserver1.31: onlykubectl1.30–1.32 are supported - Against
kube-apiserver1.35: onlykubectl1.34–1.36 are supported
This breaks the bootstrap-token job for tenants running Kubernetes v1.31 or v1.35. Update the pinned version to one that spans the supported range (e.g., 1.34 for v1.33–v1.36 compatibility, or prefer a version that accommodates the full v1.31–v1.35 window if tool constraints allow).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/apps/kubernetes/images/kubectl.tag` at line 1, Update the kubectl
version pinned in the kubectl.tag file from 1.33.4 to a version that supports
the full Kubernetes tenant range (v1.31–v1.35). The current version 1.33.4
violates the Kubernetes Version Skew Policy and breaks the bootstrap-token job
for tenants running v1.31 or v1.35. Update the version to 1.34 or another
version that accommodates the full v1.31–v1.35 window while maintaining
compatibility with the version skew requirements (kubectl must be within ±1
minor version of kube-apiserver).
| - name: https | ||
| port: 8443 | ||
| targetPort: https |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify that the metrics Service targetPort resolves to a named container port.
set -euo pipefail
file="packages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yaml"
printf 'Metrics Service port block:\n'
sed -n '650,655p' "$file"
printf '\nDeployment container port block:\n'
sed -n '709,718p' "$file"
# Expected after the fix:
# - Service targetPort is "metrics", or
# - the Deployment exposes a container port named "https".Repository: cozystack/cozystack
Length of output: 461
Update the metrics Service targetPort to match the exposed container port name.
The cabpt-controller-manager-metrics-service specifies targetPort: https, but the Deployment container only exposes a port named metrics (at port 8443). The Service will not route traffic correctly.
Fix
ports:
- name: https
port: 8443
- targetPort: https
+ targetPort: metrics📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: https | |
| port: 8443 | |
| targetPort: https | |
| - name: https | |
| port: 8443 | |
| targetPort: metrics |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yaml`
around lines 652 - 654, The targetPort in the https port definition for the
metrics Service is set to `https`, but the corresponding Deployment container
only exposes a port named `metrics` at port 8443. Change the targetPort value
from `https` to `metrics` in the Service definition so that traffic is correctly
routed to the container port that actually exists.
| cd .update-tmp && git init -q && git add . && git commit -qm init && \ | ||
| for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \ | ||
| git apply --recount "$$p"; \ | ||
| done |
There was a problem hiding this comment.
Remove the local git commit dependency from update target.
At Line 45, git commit -qm init can fail when user.name/user.email are not configured, and patch application here does not require a commit.
🛠️ Proposed fix
- cd .update-tmp && git init -q && git add . && git commit -qm init && \
+ cd .update-tmp && git init -q && \
for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \
git apply --recount "$$p"; \
done📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| cd .update-tmp && git init -q && git add . && git commit -qm init && \ | |
| for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \ | |
| git apply --recount "$$p"; \ | |
| done | |
| cd .update-tmp && git init -q && \ | |
| for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \ | |
| git apply --recount "$$p"; \ | |
| done |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/system/capi-providers-cpprovider/Makefile` around lines 45 - 48, In
the update target, the git commit command at line 45 is failing when git
user.name and user.email are not configured globally, but this commit is
unnecessary for patch application. Remove the `git commit -qm init &&` portion
from the command chain in the update target while keeping the `git init -q` and
`git add .` commands, since only these are required for the subsequent git apply
operations to work correctly.
| plural: kuberneteses | ||
| openAPISchema: |- | ||
| {"title":"Chart Values","type":"object","properties":{"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated","x-kubernetes-validations":[{"rule":"self == oldSelf","message":"storageClass is immutable"}],"x-cozystack-options":{"source":"storageclass"}},"nodeGroups":{"description":"Worker nodes configuration map.","type":"object","default":{"md0":{"diskSize":"20Gi","gpus":[],"instanceType":"u1.medium","kubelet":{},"maxReplicas":10,"minReplicas":0,"resources":{},"roles":["ingress-nginx"],"storageClass":""}},"additionalProperties":{"type":"object","required":["diskSize","instanceType","maxReplicas","minReplicas","resources"],"properties":{"diskSize":{"description":"Persistent disk size for kubelet and containerd data.","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","x-cozystack-options":{"source":"gpu"}}}}},"instanceType":{"description":"Virtual machine instance type.","type":"string","default":"u1.medium","x-cozystack-options":{"source":"instancetype"}},"kubelet":{"description":"Kubelet resource reservations for this node group.","type":"object","properties":{"evictionHardMemory":{"description":"Hard eviction threshold for memory (absolute like 200Mi or percentage like 7%).","type":"string","default":"7%"},"evictionSoftMemory":{"description":"Soft eviction threshold for memory (absolute like 1Gi or percentage like 10%).","type":"string","default":"10%"},"kubeReservedCpu":{"description":"CPU reserved for kubelet and container runtime. Auto-computed from instanceType if empty.","type":"string"},"kubeReservedMemory":{"description":"Memory reserved for kubelet and container runtime. Auto-computed from instanceType if empty.","type":"string"},"systemReservedCpu":{"description":"CPU reserved for host OS. Auto-computed from instanceType if empty.","type":"string"},"systemReservedMemory":{"description":"Memory reserved for host OS. Auto-computed from instanceType if empty.","type":"string"}}},"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"}},"storageClass":{"description":"StorageClass for worker node persistent disks. When empty, uses the management cluster default StorageClass (the one annotated storageclass.kubernetes.io/is-default-class: true). NOTE: deliberately not marked immutable — the field is optional and undefaulted, so a strict `self == oldSelf` rule would block any future attempt to set it on an existing node group.","type":"string","x-cozystack-options":{"source":"storageclass"}}}}},"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 `<cluster-name>.<tenant-host>` if empty.","type":"string","default":""},"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"required":["certManager","cilium","coredns","fluxcd","gatewayAPI","gpuOperator","hami","ingressNginx","monitoringAgents","ouroboros","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}}},"ouroboros":{"description":"Hairpin-NAT fix for ingress-nginx with PROXY-protocol.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable ouroboros. Requires addons.ingressNginx.enabled (chart-render fail otherwise). Only useful when PROXY-protocol is wired on the tenant ingress-nginx via valuesOverride.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides. Operator-key wins over cozystack defaults.","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":"c1.medium","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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":"t1.micro","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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":"t1.micro","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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":"t1.micro","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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","x-kubernetes-validations":[{"rule":"self == oldSelf","message":"storageClass is immutable"}],"x-cozystack-options":{"source":"storageclass"}},"nodeGroups":{"description":"Worker nodes configuration map.","type":"object","default":{"md0":{"diskSize":"20Gi","gpus":[],"instanceType":"u1.medium","kubelet":{},"maxReplicas":10,"minReplicas":0,"resources":{},"roles":["ingress-nginx"],"storageClass":""}},"additionalProperties":{"type":"object","required":["diskSize","instanceType","maxReplicas","minReplicas","resources"],"properties":{"diskSize":{"description":"System disk size for the worker VM. Carries the Talos OS image (factory.talos.dev raw artifact streamed in by CDI), kubelet state, containerd image cache, and any local-path PVCs. Pre-Talos installs used a separate disk-kubelet PVC for kubelet/containerd state; on Talos this is consolidated onto the single system disk imaged from the factory artifact.","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","x-cozystack-options":{"source":"gpu"}}}}},"instanceType":{"description":"Virtual machine instance type.","type":"string","default":"u1.medium","x-cozystack-options":{"source":"instancetype"}},"kubelet":{"description":"Kubelet resource reservations for this node group.","type":"object","properties":{"evictionHardMemory":{"description":"Hard eviction threshold for memory (absolute like 200Mi or percentage like 7%).","type":"string","default":"7%"},"evictionSoftMemory":{"description":"Soft eviction threshold for memory (absolute like 1Gi or percentage like 10%).","type":"string","default":"10%"},"kubeReservedCpu":{"description":"CPU reserved for kubelet and container runtime. Auto-computed from instanceType if empty.","type":"string"},"kubeReservedMemory":{"description":"Memory reserved for kubelet and container runtime. Auto-computed from instanceType if empty.","type":"string"},"systemReservedCpu":{"description":"CPU reserved for host OS. Auto-computed from instanceType if empty.","type":"string"},"systemReservedMemory":{"description":"Memory reserved for host OS. Auto-computed from instanceType if empty.","type":"string"}}},"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"}},"storageClass":{"description":"StorageClass for worker node persistent disks. When empty, uses the management cluster default StorageClass (the one annotated storageclass.kubernetes.io/is-default-class: true). NOTE: deliberately not marked immutable — the field is optional and undefaulted, so a strict `self == oldSelf` rule would block any future attempt to set it on an existing node group.","type":"string","x-cozystack-options":{"source":"storageclass"}}}}},"version":{"description":"Kubernetes major.minor version to deploy","type":"string","default":"v1.35","enum":["v1.35","v1.34","v1.33","v1.32","v1.31"]},"host":{"description":"External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty.","type":"string","default":""},"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"required":["certManager","cilium","coredns","fluxcd","gatewayAPI","gpuOperator","hami","ingressNginx","monitoringAgents","ouroboros","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}}},"ouroboros":{"description":"Hairpin-NAT fix for ingress-nginx with PROXY-protocol.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable ouroboros. Requires addons.ingressNginx.enabled (chart-render fail otherwise). Only useful when PROXY-protocol is wired on the tenant ingress-nginx via valuesOverride.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides. Operator-key wins over cozystack defaults.","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":"c1.medium","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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":"t1.micro","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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":"t1.micro","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","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":"t1.micro","enum":["t1.nano","t1.micro","t1.small","t1.medium","t1.large","t1.xlarge","t1.2xlarge","t1.4xlarge","c1.nano","c1.micro","c1.small","c1.medium","c1.large","c1.xlarge","c1.2xlarge","c1.4xlarge","s1.nano","s1.micro","s1.small","s1.medium","s1.large","s1.xlarge","s1.2xlarge","s1.4xlarge","u1.nano","u1.micro","u1.small","u1.medium","u1.large","u1.xlarge","u1.2xlarge","u1.4xlarge","m1.nano","m1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m1.2xlarge","m1.4xlarge","nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"images":{"description":"Optional image overrides for air-gapped or rate-limited registries.","type":"object","default":{},"properties":{"kubectl":{"description":"Image used by the bootstrap-token tenant Job (kubectl). Empty falls back to images/kubectl.tag.","type":"string","default":""},"talosCsrSigner":{"description":"Image used by the talos-csr-signer sidecar in the Kamaji control plane. Empty falls back to images/talos-csr-signer.tag.","type":"string","default":""},"waitForKubeconfig":{"description":"Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag.","type":"string","default":""}}},"talos":{"description":"Talos worker image configuration.","type":"object","default":{},"required":["schematicID","version"],"properties":{"schematicID":{"description":"Talos image-factory schematic ID. Defaults to the cozystack-tested vanilla schematic. Operators using custom schematics (system extensions, kernel args) override here.","type":"string","default":"ce4c980550dd2ab1b17bbf2b08801c7eb59418eafe8f279833297925d67c7515"},"version":{"description":"Talos release used for worker OS image and installer. Must satisfy the chart's Talos<->Kubernetes support matrix against the chosen `version`.","type":"string","default":"v1.13.0"}}},"nodeHealthCheck":{"description":"MachineHealthCheck tuning for worker node groups.","type":"object","default":{},"required":["maxUnhealthy","nodeStartupTimeout"],"properties":{"maxUnhealthy":{"description":"Maximum number of unhealthy nodes tolerated per node group before remediation is paused. The MHC admission webhook accepts either a bare integer (\"0\", \"1\", ...) or a percentage (\"0%\", \"50%\"); bare numeric strings are rejected, so the safer default is to express the value as a percentage. Default \"50%\" leaves headroom for transient unhealthy nodes during the kubeadm-to-Talos rollover and slow first boots from factory.talos.dev. Drop to \"0%\" once the fleet is stable on Talos workers.","type":"string","default":"50%"},"nodeStartupTimeout":{"description":"Maximum time a Machine is allowed to spend reaching the Ready condition before it is remediated. Raise for slow first boots (Talos image fetch from factory.talos.dev or a busy storage class on the kubevirt-csi PVC populator).","type":"string","default":"10m"}}}}} |
There was a problem hiding this comment.
Add explicit validation for new nodeHealthCheck string fields to prevent silent misconfiguration.
nodeHealthCheck.maxUnhealthy and nodeHealthCheck.nodeStartupTimeout are currently unconstrained strings. Invalid values can pass API validation and then be coerced unexpectedly during chart rendering, which may alter MachineHealthCheck behavior in production.
Please enforce formats at schema source (e.g., maxUnhealthy as integer-or-percent pattern; nodeStartupTimeout as duration pattern), then regenerate downstream artifacts so CRD/type contracts stay aligned.
Based on learnings, this repository expects enum/validation consistency to be driven from cozyvalues-gen inputs rather than hand-editing generated outputs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/system/kubernetes-rd/cozyrds/kubernetes.yaml` at line 35, The
nodeHealthCheck fields maxUnhealthy and nodeStartupTimeout lack validation
patterns, allowing invalid values to pass API validation and cause issues during
chart rendering. Rather than editing the generated YAML directly, locate the
cozyvalues-gen source input file that defines this schema and add proper
validation patterns there: add a pattern constraint for maxUnhealthy to enforce
integer-or-percent format (e.g., bare integers or percentage strings like
"50%"), and add a duration pattern constraint for nodeStartupTimeout (e.g.,
durations like "10m"). Then regenerate the downstream kubernetes.yaml artifact
from the cozyvalues-gen source to ensure schema consistency across all generated
outputs.
Source: Learnings
e46b258 to
1ecbf37
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/system/capi-providers-cpprovider/Makefile (1)
45-45:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDrop the unnecessary
git commitstep fromupdate
git applyhere does not require a commit, andgit commit -qm initcan fail whenuser.name/user.emailare unset in CI or clean dev environments.Suggested fix
- cd .update-tmp && git init -q && git add . && git commit -qm init && \ + cd .update-tmp && git init -q && git add . && \ for p in ../images/cluster-api-control-plane-provider-kamaji/patches/*.diff; do \ [ -e "$$p" ] || continue; \ git apply --recount "$$p"; \ done#!/bin/bash set -euo pipefail rg -n 'git commit -qm init' packages/system/capi-providers-cpprovider/Makefile -n -C2🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/system/capi-providers-cpprovider/Makefile` at line 45, The update target in the Makefile contains an unnecessary git commit step that can fail in CI or clean environments when user.name and user.email are unset. Remove the `git commit -qm init` portion from the command chain while keeping the `git init -q` and `git add .` steps, as these are still needed for the subsequent git apply operation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml`:
- Around line 75-78: The RBAC rule for kamajicontrolplanes in the
talos-reconcile-job ServiceAccount is missing the required `update` verb on the
`finalizers` subresource. When the Job attempts to create TalosConfigTemplate
with blockOwnerDeletion set to true, Kubernetes'
OwnerReferencesPermissionEnforcement admission controller enforces that the
ServiceAccount must have update permissions on the owner resource's finalizers.
Add a new RBAC rule with apiGroup controlplane.cluster.x-k8s.io, resources
kamajicontrolplanes/finalizers, resourceNames matching the release name, and
verbs containing only update. This same pattern needs to be applied to the other
kamajicontrolplanes-related rules mentioned in the also applies to section.
---
Duplicate comments:
In `@packages/system/capi-providers-cpprovider/Makefile`:
- Line 45: The update target in the Makefile contains an unnecessary git commit
step that can fail in CI or clean environments when user.name and user.email are
unset. Remove the `git commit -qm init` portion from the command chain while
keeping the `git init -q` and `git add .` steps, as these are still needed for
the subsequent git apply operation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1844b908-fd83-4a86-bbdd-8d72fee9721e
⛔ Files ignored due to path filters (2)
packages/system/capi-providers-bootstrap/files/components-talos.gzis excluded by!**/*.gzpackages/system/capi-providers-cpprovider/files/components.gzis excluded by!**/*.gz
📒 Files selected for processing (61)
.github/workflows/pull-requests.yamlMakefileapi/apps/v1alpha1/kubernetes/types.goapi/apps/v1alpha1/kubernetes/zz_generated.deepcopy.gohack/e2e-apps/run-kubernetes.shpackages/apps/kubernetes/Makefilepackages/apps/kubernetes/README.mdpackages/apps/kubernetes/files/versions.yamlpackages/apps/kubernetes/images/kubectl.tagpackages/apps/kubernetes/images/talos-csr-signer.tagpackages/apps/kubernetes/images/talos-csr-signer/Dockerfilepackages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tagpackages/apps/kubernetes/images/ubuntu-container-disk/Dockerfilepackages/apps/kubernetes/templates/_helpers.tplpackages/apps/kubernetes/templates/cluster.yamlpackages/apps/kubernetes/templates/copy-patch-containerd.yamlpackages/apps/kubernetes/templates/helmreleases/cilium.yamlpackages/apps/kubernetes/templates/helmreleases/ouroboros.yamlpackages/apps/kubernetes/templates/talos/bootstrap-token-tenant-job.yamlpackages/apps/kubernetes/templates/talos/talos-pki.yamlpackages/apps/kubernetes/templates/talos/talos-reconcile-job.yamlpackages/apps/kubernetes/templates/talos/talos-secrets.yamlpackages/apps/kubernetes/tests/cluster_test.yamlpackages/apps/kubernetes/tests/containerd-config-path-test.shpackages/apps/kubernetes/tests/fixtures/containerd-1x.tomlpackages/apps/kubernetes/tests/fixtures/containerd-2x.tomlpackages/apps/kubernetes/tests/gpu_node_labels_test.yamlpackages/apps/kubernetes/tests/kubelet-reservation_test.yamlpackages/apps/kubernetes/tests/kubelet_reservation_test.yamlpackages/apps/kubernetes/tests/mhc_rendering_test.yamlpackages/apps/kubernetes/tests/talos_k8s_support_matrix_test.yamlpackages/apps/kubernetes/tests/talos_templates_test.yamlpackages/apps/kubernetes/values.schema.jsonpackages/apps/kubernetes/values.yamlpackages/core/platform/images/migrations/migrations/44packages/core/platform/images/migrations/migrations/45packages/core/platform/values.yamlpackages/system/capi-providers-bootstrap/Makefilepackages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yamlpackages/system/capi-providers-bootstrap/files/metadata-talos.yamlpackages/system/capi-providers-bootstrap/patches/0001-rename-default-sa-to-cabpt-manager.diffpackages/system/capi-providers-bootstrap/templates/configmaps.yamlpackages/system/capi-providers-bootstrap/templates/providers.yamlpackages/system/capi-providers-cpprovider/Makefilepackages/system/capi-providers-cpprovider/files/control-plane-components.yamlpackages/system/capi-providers-cpprovider/files/metadata.yamlpackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji.tagpackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/Dockerfilepackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/patches/0001-backport-additional-service-ports-pr347.diffpackages/system/capi-providers-cpprovider/templates/configmaps.yamlpackages/system/capi-providers-cpprovider/templates/providers.yamlpackages/system/kubernetes-rd/cozyrds/kubernetes.yamlpkg/cmd/server/start.gopkg/config/config.gopkg/config/config_test.gopkg/registry/apps/application/rest.go
💤 Files with no reviewable changes (13)
- packages/apps/kubernetes/templates/copy-patch-containerd.yaml
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tag
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tag
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tag
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tag
- packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tag
- packages/apps/kubernetes/tests/fixtures/containerd-1x.toml
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tag
- packages/apps/kubernetes/files/versions.yaml
- packages/apps/kubernetes/tests/fixtures/containerd-2x.toml
- packages/apps/kubernetes/tests/containerd-config-path-test.sh
- packages/apps/kubernetes/tests/kubelet-reservation_test.yaml
✅ Files skipped from review due to trivial changes (10)
- packages/apps/kubernetes/images/kubectl.tag
- packages/system/capi-providers-bootstrap/files/metadata-talos.yaml
- packages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji.tag
- packages/apps/kubernetes/images/talos-csr-signer/Dockerfile
- packages/apps/kubernetes/tests/mhc_rendering_test.yaml
- packages/core/platform/values.yaml
- packages/system/capi-providers-cpprovider/files/metadata.yaml
- packages/apps/kubernetes/README.md
- api/apps/v1alpha1/kubernetes/zz_generated.deepcopy.go
- packages/apps/kubernetes/tests/kubelet_reservation_test.yaml
🚧 Files skipped from review as they are similar to previous changes (28)
- packages/system/capi-providers-cpprovider/templates/providers.yaml
- packages/apps/kubernetes/images/talos-csr-signer.tag
- packages/system/capi-providers-bootstrap/templates/providers.yaml
- .github/workflows/pull-requests.yaml
- packages/apps/kubernetes/tests/talos_k8s_support_matrix_test.yaml
- Makefile
- packages/system/capi-providers-cpprovider/templates/configmaps.yaml
- packages/apps/kubernetes/templates/_helpers.tpl
- pkg/config/config_test.go
- packages/system/capi-providers-bootstrap/templates/configmaps.yaml
- packages/apps/kubernetes/tests/gpu_node_labels_test.yaml
- packages/apps/kubernetes/tests/talos_templates_test.yaml
- pkg/registry/apps/application/rest.go
- packages/apps/kubernetes/values.schema.json
- packages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/Dockerfile
- pkg/config/config.go
- packages/apps/kubernetes/templates/helmreleases/cilium.yaml
- packages/apps/kubernetes/values.yaml
- packages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/patches/0001-backport-additional-service-ports-pr347.diff
- pkg/cmd/server/start.go
- packages/system/kubernetes-rd/cozyrds/kubernetes.yaml
- packages/core/platform/images/migrations/migrations/44
- packages/apps/kubernetes/templates/helmreleases/ouroboros.yaml
- packages/core/platform/images/migrations/migrations/45
- packages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yaml
- packages/system/capi-providers-bootstrap/patches/0001-rename-default-sa-to-cabpt-manager.diff
- api/apps/v1alpha1/kubernetes/types.go
- packages/apps/kubernetes/tests/cluster_test.yaml
| - apiGroups: ["controlplane.cluster.x-k8s.io"] | ||
| resources: ["kamajicontrolplanes"] | ||
| resourceNames: ["{{ .Release.Name }}"] | ||
| verbs: ["get", "patch"] |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Checking ownerReference and RBAC in talos-reconcile hook..."
rg -n 'blockOwnerDeletion:\s*true|resources:\s*\["kamajicontrolplanes"\]|verbs:\s*\["get",\s*"patch"\]' \
packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml -n -C2Repository: cozystack/cozystack
Length of output: 595
🏁 Script executed:
cat -n packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml | sed -n '50,100p'Repository: cozystack/cozystack
Length of output: 2357
🏁 Script executed:
cat -n packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml | sed -n '360,385p'Repository: cozystack/cozystack
Length of output: 1339
🏁 Script executed:
rg -n 'talosconfigtemplates' packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml -B2 -A2Repository: cozystack/cozystack
Length of output: 244
🌐 Web query:
Kubernetes blockOwnerDeletion permission requirements admission controller
💡 Result:
When the OwnerReferencesPermissionEnforcement admission controller is enabled, it enforces specific permission requirements for setting blockOwnerDeletion on an object's ownerReferences [1][2]. To successfully set blockOwnerDeletion to true on an owner reference, the user (or service account) must have update permission on the finalizers subresource of the referenced owner object [1][3][4]. Specifically, the required RBAC rule typically looks like this: - apiGroups: - "the-api-group-of-the-owner" resources: - "owner-resource-name/finalizers" verbs: - "update" If this permission is missing, requests to create or update objects with blockOwnerDeletion set will fail with a forbidden error, often stating: "cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on" [5][6][7]. This requirement ensures that only authorized entities can configure garbage collection behavior that could potentially delay the deletion of owner resources [8][9].
Citations:
- 1: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
- 2: Make the
OwnerReferencesPermissionEnforcementadmission plugin reusable by external extension API server kubernetes/kubernetes#133891 - 3: kubernetes/kubernetes@0ed05f2
- 4: https://github.com/kubernetes/website/blob/main/content/en/docs/reference/access-authn-authz/admission-controllers.md
- 5: "cannot set blockOwnerDeletion" when using OpenShift as management cluster kubernetes-sigs/cluster-api#4880
- 6: Fix set blockOwnerDeletion failures for OwnerReferencesPermissionEnforcement enabled clusters GoogleCloudPlatform/k8s-config-connector#797
- 7: system:kube-scheduler: extend the RBAC with pods/finalizers kubernetes/kubernetes#123512
- 8: https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/
- 9: Extend the gc admission plugin to check ownerReference.blockOwnerDeletion kubernetes/kubernetes#43876
🌐 Web query:
Kubernetes ownerReference blockOwnerDeletion update patch permission validation
💡 Result:
In Kubernetes, the blockOwnerDeletion field within an OwnerReference controls whether a dependent object blocks the deletion of its owner during foreground cascading deletion [1][2][3]. To protect owner resources from unauthorized deletion delays, the Kubernetes OwnerReferencesPermissionEnforcement admission plugin validates changes to this field [4][1][5]. When a user (or controller) attempts to set blockOwnerDeletion to true for an ownerReference, the plugin verifies that the subject has specific update permissions on the owner object [4][2][5]. Specifically, the required permission is the update verb on the finalizers subresource of the referenced owner object [4][2][6]. If the subject lacks this permission, the API server will reject the request with a "forbidden" error [4][7][8]. For developers building operators, this requirement is frequently encountered when using controller-runtime's SetControllerReference or similar utilities, which default blockOwnerDeletion to true [2][8]. If an operator fails to include the necessary RBAC permissions for the owner's finalizers, it will be unable to set this field, often resulting in errors such as "cannot set blockOwnerDeletion if an ownerReference refers to a resource you can’t set finalizers on" [2][8]. In Go-based operators using Kubebuilder, this is typically resolved by adding the following RBAC marker to the code and regenerating manifests [2][8]: // +kubebuilder:rbac:groups=,resources=/finalizers,verbs=update
Citations:
- 1: https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/
- 2: https://www.golinuxcloud.com/kubernetes-operator-owner-references-and-gc/
- 3: https://kubernetes.io/docs/concepts/architecture/garbage-collection/
- 4: humblec/kubernetes@0ed05f2
- 5: Extend the gc admission plugin to check ownerReference.blockOwnerDeletion kubernetes/kubernetes#43876
- 6: kubernetes/kubernetes@0ed05f2
- 7: Error messages make debugging unnecessarily complex kubernetes/kubernetes#130275
- 8: https://sdk.operatorframework.io/docs/faqs/
Missing update permission on finalizers blocks blockOwnerDeletion: true via admission controller
The ServiceAccount lacks the required permission to set blockOwnerDeletion: true. Kubernetes' OwnerReferencesPermissionEnforcement admission controller requires update verb on the owner's finalizers subresource. This causes the hook Job to fail when creating TalosConfigTemplate, blocking worker reconciliation.
Add the missing RBAC rule:
Required fix
- apiGroups: ["controlplane.cluster.x-k8s.io"]
resources: ["kamajicontrolplanes"]
resourceNames: ["{{ .Release.Name }}"]
verbs: ["get", "patch"]
+ - apiGroups: ["controlplane.cluster.x-k8s.io"]
+ resources: ["kamajicontrolplanes/finalizers"]
+ resourceNames: ["{{ .Release.Name }}"]
+ verbs: ["update"]Also applies to: 368-375
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml` around
lines 75 - 78, The RBAC rule for kamajicontrolplanes in the talos-reconcile-job
ServiceAccount is missing the required `update` verb on the `finalizers`
subresource. When the Job attempts to create TalosConfigTemplate with
blockOwnerDeletion set to true, Kubernetes' OwnerReferencesPermissionEnforcement
admission controller enforces that the ServiceAccount must have update
permissions on the owner resource's finalizers. Add a new RBAC rule with
apiGroup controlplane.cluster.x-k8s.io, resources
kamajicontrolplanes/finalizers, resourceNames matching the release name, and
verbs containing only update. This same pattern needs to be applied to the other
kamajicontrolplanes-related rules mentioned in the also applies to section.
…los v0.6.12 Vendor CABPT v0.6.12 as a second BootstrapProvider alongside the existing kubeadm one. The default ServiceAccount is renamed to cabpt-manager via a patch on the upstream bundle. Co-authored-by: IvanHunters <xorokhotnikov@gmail.com> Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
…r (v0.19.0 + additionalServicePorts backport) Rebuild the Kamaji control-plane provider from upstream v0.19.0 with a backport of additionalServicePorts (upstream PR #347), exposing KamajiControlPlane.spec.network.additionalServicePorts so trustd (50001/TCP) can be published on the apiserver Service. Image is built from source and pinned by digest; the 0.17-0.19 release series is registered in metadata. Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Generate Talos PKI (Ed25519 CA + trustd TLS) via cert-manager and stable random Talos secrets (token, clusterId, clusterSecret, bootstrapToken) using the helm lookup-and-reuse pattern. Build the talos-csr-signer sidecar from a pinned source commit, digest-pinned, with resources and securityContext. Co-authored-by: IvanHunters <xorokhotnikov@gmail.com> Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Switch tenant worker bootstrap from Ubuntu+kubeadm to Talos. MachineDeployment.bootstrap moves from KubeadmConfigTemplate to a TalosConfigTemplate produced by a post-install/upgrade reconcile hook, which also materialises the kubeadm-format bootstrap-token Secret in the tenant kube-system. Workers boot from the Talos openstack image via a CDI DataVolume; the system disk is virtio-blk with logical=512/physical=4096 so 4Ki-native backends (LINSTOR/DRBD) and SeaBIOS both work; the separate kubelet disk is dropped. Pod/service CIDRs, dnsDomain, controlPlane endpoint and cilium k8sServiceHost are pinned to the tenant ranges / Kamaji apiserver ClusterIP to survive the DNS chicken-and-egg at bootstrap. Adds a Talos<->Kubernetes support-matrix fail() guard and drops v1.30. Removes the dead ubuntu-container-disk build chain and the orphaned copy-patch-containerd template. Co-authored-by: IvanHunters <xorokhotnikov@gmail.com> Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Parse a new release.cozystack.io/helm-install-disable-wait annotation in start.go and apply it as Install/Upgrade.DisableWait in rest.go, so helm-controller no longer blocks post-install hooks on in-tenant addon readiness. This breaks the reconcile-hook chicken-and-egg where the hook that creates the worker TalosConfigTemplate was gated behind addons that need workers to schedule. Covered by a config table test. Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: IvanHunters <xorokhotnikov@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Migration 44 pins Helm-managed KubeadmConfigTemplates with resource-policy=keep so Helm cannot prune them mid-rollover; migration 45 bumps tenants on spec.version v1.30 to v1.31 ahead of the Talos support-matrix guard. Both stamp cozystack-version with its deletion-protection label. targetVersion is bumped to 46. Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: IvanHunters <xorokhotnikov@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Add helm-unittest suites for the new Talos templates: MHC maxUnhealthy int-vs-percent rendering, the Talos<->Kubernetes support-matrix guard, the talos templates, and the ported kubelet-reservation math; restore the gpu=on node-label assertions. Remove the obsolete containerd-config-path test and fixtures. Raise tenant control-plane wait timeouts in the e2e runner for Talos PKI + sidecar boot. Co-authored-by: Andrei Kvapil <kvapss@gmail.com> Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: IvanHunters <xorokhotnikov@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Use git diff --binary for the PR patch artifact so vendored binary provider bundles (components*.gz) are reviewable. Co-authored-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
- talos-reconcile-job: emit a `---` separator inside the nodeGroups range so a tenant with multiple node groups renders valid multi-document YAML instead of two Jobs concatenated into one doc - talos-reconcile + bootstrap-token jobs: add a restricted securityContext (drop ALL caps, no privilege escalation, read-only root fs) and CPU/memory requests+limits; drop the unused management SA token mount on the bootstrap-token job, which only talks to the tenant apiserver via the mounted admin kubeconfig - migration 44: list Helm-managed resources by the app.kubernetes.io/managed-by=Helm label, not meta.helm.sh/release-name (an annotation, so it never matched as a --selector — the keep annotation was silently never applied) - cluster.yaml: fail fast on a malformed nodeHealthCheck.maxUnhealthy rather than silently coercing it to 0 via `| int` - config: make helm-install-disable-wait parsing genuinely case-insensitive (EqualFold + trim) to match its documented contract - capi-providers bootstrap/cpprovider Makefiles: guard the patches/*.diff loop against an empty glob Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
1ecbf37 to
b5cc2ae
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml (1)
75-78: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winMissing
updateonkamajicontrolplanes/finalizersforblockOwnerDeletion: true.The applied
TalosConfigTemplate(Line 374) setsblockOwnerDeletion: trueon its owner ref. With theOwnerReferencesPermissionEnforcementadmission plugin enabled, the ServiceAccount must holdupdateon the owner'sfinalizerssubresource, or thekubectl applyis rejected and worker reconciliation stalls.Required RBAC rule
- apiGroups: ["controlplane.cluster.x-k8s.io"] resources: ["kamajicontrolplanes"] resourceNames: ["{{ .Release.Name }}"] verbs: ["get", "patch"] + - apiGroups: ["controlplane.cluster.x-k8s.io"] + resources: ["kamajicontrolplanes/finalizers"] + resourceNames: ["{{ .Release.Name }}"] + verbs: ["update"]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml` around lines 75 - 78, The RBAC rule for kamajicontrolplanes is missing the update permission on the finalizers subresource, which is required when blockOwnerDeletion is set to true on owner references. Add a new rule after the existing kamajicontrolplanes rule that specifies apiGroups as controlplane.cluster.x-k8s.io, resources as kamajicontrolplanes/finalizers, resourceNames as {{ .Release.Name }}, and verbs as update. This will allow the ServiceAccount to modify the finalizers subresource, preventing the OwnerReferencesPermissionEnforcement admission plugin from rejecting the kubectl apply operation.
🧹 Nitpick comments (1)
packages/system/capi-providers-bootstrap/Makefile (1)
29-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
--failto the upstreamcurldownload.
curl -sSLexits 0 on HTTP 4xx/5xx (e.g., a renamed/removed release asset), writing the error page intobootstrap-components.yaml. The build then proceeds with a corrupt input instead of failing at the download step.-fmakes the failure explicit.♻️ Fail fast on download errors
- curl -sSL "https://github.com/siderolabs/cluster-api-bootstrap-provider-talos/releases/download/$(CABPT_UPSTREAM_VERSION)/bootstrap-components.yaml" \ + curl -fsSL "https://github.com/siderolabs/cluster-api-bootstrap-provider-talos/releases/download/$(CABPT_UPSTREAM_VERSION)/bootstrap-components.yaml" \ -o .update-tmp/bootstrap-components.yaml🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/system/capi-providers-bootstrap/Makefile` around lines 29 - 30, The curl command downloading bootstrap-components.yaml from the GitHub release is missing the --fail flag, which means it will silently succeed even on HTTP 4xx/5xx errors and write the error page to the file instead of failing the build. Add the --fail (or -f) flag to the curl -sSL command to make curl exit with a non-zero status when the download fails, ensuring the build fails fast at the download step rather than proceeding with corrupted input.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/apps/kubernetes/templates/talos/bootstrap-token-tenant-job.yaml`:
- Around line 85-90: The securityContext configuration in the
bootstrap-token-tenant-job.yaml file is incomplete and missing three security
fields that are present in the sibling talos-csr-signer container defined in
cluster.yaml. In the securityContext block that currently contains
allowPrivilegeEscalation, capabilities drop, and readOnlyRootFilesystem, add the
missing fields runAsNonRoot, runAsUser, and seccompProfile by referencing the
corresponding values from the talos-csr-signer container in cluster.yaml to
ensure consistency and compliance with Kubernetes restricted Pod Security
Standard.
In `@packages/apps/kubernetes/templates/talos/talos-pki.yaml`:
- Around line 67-72: In the talos-pki.yaml file, locate the certificate
configuration with the Ed25519 algorithm. The usages list currently contains
three items including "key encipherment", but Ed25519 is a signature-only
algorithm that does not support key encipherment operations. Remove the "key
encipherment" entry from the usages list, leaving only "digital signature" and
"server auth" as the valid usages for an Ed25519-based TLS certificate.
---
Duplicate comments:
In `@packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml`:
- Around line 75-78: The RBAC rule for kamajicontrolplanes is missing the update
permission on the finalizers subresource, which is required when
blockOwnerDeletion is set to true on owner references. Add a new rule after the
existing kamajicontrolplanes rule that specifies apiGroups as
controlplane.cluster.x-k8s.io, resources as kamajicontrolplanes/finalizers,
resourceNames as {{ .Release.Name }}, and verbs as update. This will allow the
ServiceAccount to modify the finalizers subresource, preventing the
OwnerReferencesPermissionEnforcement admission plugin from rejecting the kubectl
apply operation.
---
Nitpick comments:
In `@packages/system/capi-providers-bootstrap/Makefile`:
- Around line 29-30: The curl command downloading bootstrap-components.yaml from
the GitHub release is missing the --fail flag, which means it will silently
succeed even on HTTP 4xx/5xx errors and write the error page to the file instead
of failing the build. Add the --fail (or -f) flag to the curl -sSL command to
make curl exit with a non-zero status when the download fails, ensuring the
build fails fast at the download step rather than proceeding with corrupted
input.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0c442fd7-7d02-4da6-8c77-945e8aaca765
⛔ Files ignored due to path filters (2)
packages/system/capi-providers-bootstrap/files/components-talos.gzis excluded by!**/*.gzpackages/system/capi-providers-cpprovider/files/components.gzis excluded by!**/*.gz
📒 Files selected for processing (61)
.github/workflows/pull-requests.yamlMakefileapi/apps/v1alpha1/kubernetes/types.goapi/apps/v1alpha1/kubernetes/zz_generated.deepcopy.gohack/e2e-apps/run-kubernetes.shpackages/apps/kubernetes/Makefilepackages/apps/kubernetes/README.mdpackages/apps/kubernetes/files/versions.yamlpackages/apps/kubernetes/images/kubectl.tagpackages/apps/kubernetes/images/talos-csr-signer.tagpackages/apps/kubernetes/images/talos-csr-signer/Dockerfilepackages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tagpackages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tagpackages/apps/kubernetes/images/ubuntu-container-disk/Dockerfilepackages/apps/kubernetes/templates/_helpers.tplpackages/apps/kubernetes/templates/cluster.yamlpackages/apps/kubernetes/templates/copy-patch-containerd.yamlpackages/apps/kubernetes/templates/helmreleases/cilium.yamlpackages/apps/kubernetes/templates/helmreleases/ouroboros.yamlpackages/apps/kubernetes/templates/talos/bootstrap-token-tenant-job.yamlpackages/apps/kubernetes/templates/talos/talos-pki.yamlpackages/apps/kubernetes/templates/talos/talos-reconcile-job.yamlpackages/apps/kubernetes/templates/talos/talos-secrets.yamlpackages/apps/kubernetes/tests/cluster_test.yamlpackages/apps/kubernetes/tests/containerd-config-path-test.shpackages/apps/kubernetes/tests/fixtures/containerd-1x.tomlpackages/apps/kubernetes/tests/fixtures/containerd-2x.tomlpackages/apps/kubernetes/tests/gpu_node_labels_test.yamlpackages/apps/kubernetes/tests/kubelet-reservation_test.yamlpackages/apps/kubernetes/tests/kubelet_reservation_test.yamlpackages/apps/kubernetes/tests/mhc_rendering_test.yamlpackages/apps/kubernetes/tests/talos_k8s_support_matrix_test.yamlpackages/apps/kubernetes/tests/talos_templates_test.yamlpackages/apps/kubernetes/values.schema.jsonpackages/apps/kubernetes/values.yamlpackages/core/platform/images/migrations/migrations/45packages/core/platform/images/migrations/migrations/46packages/core/platform/values.yamlpackages/system/capi-providers-bootstrap/Makefilepackages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yamlpackages/system/capi-providers-bootstrap/files/metadata-talos.yamlpackages/system/capi-providers-bootstrap/patches/0001-rename-default-sa-to-cabpt-manager.diffpackages/system/capi-providers-bootstrap/templates/configmaps.yamlpackages/system/capi-providers-bootstrap/templates/providers.yamlpackages/system/capi-providers-cpprovider/Makefilepackages/system/capi-providers-cpprovider/files/control-plane-components.yamlpackages/system/capi-providers-cpprovider/files/metadata.yamlpackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji.tagpackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/Dockerfilepackages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/patches/0001-backport-additional-service-ports-pr347.diffpackages/system/capi-providers-cpprovider/templates/configmaps.yamlpackages/system/capi-providers-cpprovider/templates/providers.yamlpackages/system/kubernetes-rd/cozyrds/kubernetes.yamlpkg/cmd/server/start.gopkg/config/config.gopkg/config/config_test.gopkg/registry/apps/application/rest.go
💤 Files with no reviewable changes (13)
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tag
- packages/apps/kubernetes/templates/copy-patch-containerd.yaml
- packages/apps/kubernetes/files/versions.yaml
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tag
- packages/apps/kubernetes/tests/fixtures/containerd-1x.toml
- packages/apps/kubernetes/tests/containerd-config-path-test.sh
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tag
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tag
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tag
- packages/apps/kubernetes/tests/kubelet-reservation_test.yaml
- packages/apps/kubernetes/tests/fixtures/containerd-2x.toml
- packages/apps/kubernetes/images/ubuntu-container-disk/Dockerfile
- packages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tag
✅ Files skipped from review due to trivial changes (7)
- packages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji.tag
- packages/system/capi-providers-bootstrap/files/metadata-talos.yaml
- packages/apps/kubernetes/images/talos-csr-signer/Dockerfile
- packages/apps/kubernetes/images/kubectl.tag
- Makefile
- api/apps/v1alpha1/kubernetes/zz_generated.deepcopy.go
- packages/apps/kubernetes/README.md
🚧 Files skipped from review as they are similar to previous changes (28)
- packages/apps/kubernetes/tests/talos_k8s_support_matrix_test.yaml
- packages/apps/kubernetes/images/talos-csr-signer.tag
- packages/apps/kubernetes/templates/helmreleases/cilium.yaml
- packages/system/capi-providers-cpprovider/files/metadata.yaml
- packages/apps/kubernetes/tests/mhc_rendering_test.yaml
- .github/workflows/pull-requests.yaml
- packages/apps/kubernetes/templates/_helpers.tpl
- pkg/config/config_test.go
- packages/system/capi-providers-cpprovider/templates/providers.yaml
- packages/apps/kubernetes/tests/talos_templates_test.yaml
- packages/apps/kubernetes/templates/helmreleases/ouroboros.yaml
- pkg/cmd/server/start.go
- packages/system/capi-providers-bootstrap/templates/providers.yaml
- packages/apps/kubernetes/tests/gpu_node_labels_test.yaml
- packages/apps/kubernetes/values.schema.json
- packages/system/capi-providers-bootstrap/patches/0001-rename-default-sa-to-cabpt-manager.diff
- packages/system/capi-providers-bootstrap/templates/configmaps.yaml
- packages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/patches/0001-backport-additional-service-ports-pr347.diff
- pkg/config/config.go
- api/apps/v1alpha1/kubernetes/types.go
- pkg/registry/apps/application/rest.go
- packages/system/capi-providers-cpprovider/images/cluster-api-control-plane-provider-kamaji/Dockerfile
- packages/system/capi-providers-cpprovider/templates/configmaps.yaml
- packages/apps/kubernetes/values.yaml
- packages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yaml
- packages/apps/kubernetes/tests/kubelet_reservation_test.yaml
- packages/system/kubernetes-rd/cozyrds/kubernetes.yaml
- packages/apps/kubernetes/tests/cluster_test.yaml
Aleksei Sviridkin (lexfrei)
left a comment
There was a problem hiding this comment.
LGTM — Talos worker bootstrap via CABPT is correct and well-guarded. Every substantive automated-reviewer finding is already addressed in the head commit, and the three "critical/P1" items are false positives I verified against source. The remaining items are minor and non-blocking.
Business context: Replace tenant-worker bootstrap from Ubuntu+kubeadm to Talos (driven by cluster-api-bootstrap-provider-talos plus a talos-csr-signer sidecar in the Kamaji control-plane pod), so tenant clusters get immutable, lifecycle-managed workers while existing tenants roll over automatically.
Blockers
None.
Verified and dropped (automated-reviewer false positives)
I checked these against source before dropping them, so they don't get re-litigated:
- "Go 1.26 does not exist" (Dockerfiles) — stale.
golang:1.26is current and is the repo's standard builder tag. Evidence: same tag used across first-party images onmain. No change needed. - "base64 cert must be PEM-decoded before injection" (
talos-reconcile-job.yaml:420,479) — incorrect for Talos.machine.ca.crt/cluster.ca.crtin a Talos machineconfig expect base64-encoded PEM, which is exactly what the secret.data.tls.crt/.data.ca.crtalready hold; the_B64variables are injected verbatim on a single line. Evidence:talos-reconcile-job.yaml:319-320reads.data.*(already base64) and:420,479inject it unmodified — correct. - "the migration annotation will not stop Helm pruning the KubeadmConfigTemplate" — incorrect. Helm's delete path calls
info.Get()to refresh each prune candidate from the live object before readinghelm.sh/resource-policy, and the live object carries the annotation the migration sets. Evidence:helm.sh/helm/v3pkg/kube/client.goUpdate()lines 436-448 (info.Get()thenannotations[ResourcePolicyAnno] == KeepPolicy-> skip delete).
Non-blocking follow-ups
- kubectl pin vs tenant skew —
images/kubectl.tagpinsalpine/k8s:1.33.4, but the bootstrap-token Job runs it against tenant apiservers spanning v1.31-v1.35 (±2 minors at the edges, outside the documented skew window). The calls are basic GA CRUD (Secret + rbac/v1 apply, delete) and work in practice, so this is hardening rather than a break; consider tracking the tenant range or using a per-tenant kubectl. Evidence:packages/apps/kubernetes/templates/talos/bootstrap-token-tenant-job.yaml:60,100-116. - Migration
45is committed non-executable (100644) while siblings44/46are100755. Harmless becauserun-migrations.shrunschmod +xbefore exec, but it's an avoidable inconsistency. Evidence:git ls-files --stage packages/core/platform/images/migrations/migrations/{44,45,46};run-migrations.shchmod line. - blockOwnerDeletion RBAC — the talos-reconcile Role grants get/patch on
kamajicontrolplanesbut notupdateonkamajicontrolplanes/finalizers, while the applied TalosConfigTemplate setsblockOwnerDeletion: true. This only fails if the management apiserver enables the (non-default) OwnerReferencesPermissionEnforcement admission plugin; add the finalizers/update rule defensively if there's any chance of enabling it. Evidence:talos-reconcile-job.yaml:75-78,374. - CABPT metrics Service
targetPort: httpsdoes not match the controller's named container portmetrics(8443), so metrics scraping won't route. This lives in the vendored upstream bundle, so the fix belongs upstream rather than as a local edit. Evidence:packages/system/capi-providers-bootstrap/files/bootstrap-components-talos.yaml:654vs:716-717. - Ed25519 TLS cert lists
key enciphermentusage. RFC 9295 says Ed25519 certs MUST NOT carry keyEncipherment; harmless for the signer's TLS 1.3 listener but worth dropping for correctness. Evidence:packages/apps/kubernetes/templates/talos/talos-pki.yaml:67-72. - Migration comments reference "PR #2610" in shipped files. Internal PR provenance in committed code is best avoided; describe the change, not where it was tracked. Evidence:
migrations/45:4-7,migrations/46:5.
Overlap with the other open PR on the same branch
A second PR with the identical title and the same phase1-talos-migration branch name is still open and is superseded by this one: this PR is that work rebased onto main (to sit on top of the kube-controller-manager VAP fix), with original authorship preserved and history squashed. Two things to note: the PR body's "byte-identical to the other head — no code changes" is now stale, since this head carries an extra fix: address review findings commit (head b5cc2ae) plus a CI commit beyond that tree; and leaving both open races the same branch name. Evidence: git log --oneline shows b5cc2ae fix(kubernetes): address review findings ... on top of the eight squashed commits. Recommend closing the older PR in favor of this one.
Scope verified
Helm prune semantics (against helm source), CABPT TalosConfigTemplate apiVersion (v1alpha3 is served + storage in the vendored CRD), Go disable-wait wiring (Install/Upgrade always non-nil so no nil-deref; invalid annotation fails startup loudly), migration chain (44->45->46->47, targetVersion 47, both new stamps carry the platform.cozystack.io/no-delete label), MHC maxUnhealthy rendering (validates int-or-percent and fails on garbage), README/schema/types regenerated and in sync.
IvanHunters
left a comment
There was a problem hiding this comment.
Review: Request changes
Four MAJOR findings below block merge for the "existing tenants keep working without manual intervention" claim. Minors are listed separately and can be addressed in a follow-up.
MAJOR
1. Air-gapped tenants lose self-healing; <release>-patch-containerd Secret pruned, MHC default flipped to enable remediation
Three changes interact and break tenants that run with _cluster.registries.mirrors set:
packages/apps/kubernetes/templates/copy-patch-containerd.yamlis deleted. The<release>-patch-containerdSecret it rendered is not keep-annotated by migration 45 (onlyKubeadmConfigTemplateandKubeadmConfigare). On chart upgrade Helm prunes the Secret, leaving the still-extant kubeadm-backed MachineSet referencing a missing input.nodeHealthCheck.maxUnhealthydefault flipped from0(integer literal in oldcluster.yaml:591) to"50%"(string in newvalues.yaml:307). The type change is itself a schema break — tenants that previously overrodemaxUnhealthy: 0will now fail render with the new^[0-9]+$|^[0-9]+%$regex guard atcluster.yaml:614-622. The default change enables MHC remediation where it was previously disabled.MachineDeploymentbootstrap ref switches toTalosConfigTemplateand worker images come fromfactory.talos.devvia CDI. For air-gapped tenants the DataVolume fetch hangs.
Combined scenario: previously-stable tenant fleet, transient NotReady on one Ubuntu worker (containerd hiccup, kernel softlockup) → MHC now remediates (didn't before) → CAPI provisions a Talos Machine → factory.talos.dev egress blocked → Machine stuck in Provisioning → nodeStartupTimeout (10m) → rolling update stalls. The migration 45 inline comment explicitly acknowledges this: "In pathological cases (slow Talos image fetch from factory.talos.dev, MachineHealthCheck remediation, etc.) workers can hang in pending state with nothing to bootstrap from." — the mitigation (keep-annotate KCT only) is incomplete.
Required fixes:
- Either keep-annotate
<release>-patch-containerdin migration 45 alongside KCT, OR render-timefail()in the chart when_cluster.registries.mirrorsis non-empty and noimages.talosInstalleroverride is set, so air-gapped tenants get a clear render-time error instead of a partially broken cluster. - Add a "Breaking Changes" entry in
packages/apps/kubernetes/README.mddocumenting the MHC default flip (0→"50%") and the type change (integer → string). Recommend operators pinnodeHealthCheck.maxUnhealthy: "0%"before upgrade if they want legacy behavior.
2. README documents unsupported Kubernetes versions
packages/apps/kubernetes/README.md:15 says "Users can select the supported patch versions from 1.30 to 1.35." but the schema enum in values.schema.json is ["v1.31","v1.32","v1.33","v1.34","v1.35"] and templates/_versions.tpl has a fail() guard for v1.30. An operator following the README to create a fresh tenant with version: v1.30 gets a CRD admission rejection. Update the README to from 1.31 to 1.35 and add a Breaking Changes entry pointing at migration 46.
3. talos-reconcile-job 10-minute polling window is tight for slow cold-starts; chart upgrade fails with no automatic recovery
packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml:317 polls for i in $(seq 1 120); do ... sleep 5; done = 600s. The Job blocks on (a) Kamaji apiserver Service ClusterIP allocation, (b) cert-manager CA Secret issuance, and (c) KamajiControlPlane apiserver readiness. On clusters with slow image pulls or cert-manager cold-start the 10-minute window is insufficient. backoffLimit: 5 + restartPolicy: OnFailure gives ~30 minutes of total retries before permanent fail; the HR ends in Failed state and requires manual kubectl delete job to retrigger.
Pre-PR the chart relied on a lookup race that silently produced empty SANs but didn't gate Helm readiness on it. This PR puts the reconcile-job on the critical path, regressing operator experience for slow clusters.
Fix: widen the per-Job polling window to ~25min (inside the 20min HR install timeout × backoff factor), or document the manual retrigger procedure in the README.
4. GitOps-managed tenant CRs with version: v1.30 in Git get reverted by Flux after migration 46 patches them
Migration 46 patches kuberneteses.apps.cozystack.io spec.version on the live CR from v1.30 to v1.31. For operators using Flux/Argo to manage tenant CRs from Git, the next reconcile will revert the field back to v1.30, hitting the new _versions.tpl fail() guard and breaking the HR after the platform upgrade has already completed.
This is not a code bug but a deployment-flow gap. The PR body claim "existing tenants keep working without manual intervention" does not hold for GitOps-managed clusters.
Fix: add an explicit operator-action note in the release-note block: "Operators managing tenant kubernetes.apps.cozystack.io CRs from Git MUST update spec.version: v1.30 to v1.31 in their source repository before bumping the platform to v1.5.0, otherwise the next GitOps reconcile will revert the migration."
MINOR
packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml:496-501andtemplates/talos/bootstrap-token-tenant-job.yaml:85-90— hook pods missrunAsNonRoot: true/runAsUser. Thetalos-csr-signersidecar atcluster.yaml:294-303already sets these. Mirror the pattern; otherwise the chart fails under PodSecurityrestrictedenforcement on tenant namespaces.packages/apps/kubernetes/templates/talos/talos-secrets.yaml:36-53— whenlookupfinds an existing<release>-talos-secretsSecret missing thebootstrapTokenId/bootstrapTokenSecretkeys (early-Talos-branch tenants), the chart randomizes new ones and leaves the previousbootstrap-token-<old-id>Secret orphaned in tenantkube-system. Add anelsebranch that reconstructs the split keys from the old combined value when present.packages/apps/kubernetes/templates/talos/talos-reconcile-job.yaml:337-341— JSON merge patch onKamajiControlPlane.spec.network.certSANsuses array-replace semantics; any operator-added SANs are wiped on every chart upgrade. Either document the chart-managed contract or switch to a JSON Patchaddop.packages/core/platform/images/migrations/migrations/46— exit 0 on partial failure with a ConfigMap annotation as the only signal. Retry-on-next-upgrade semantics are intentional per the inline comment, but consider emitting akubectl create eventso operators get a dashboard-visible signal instead of having tokubectl describe cm cozystack-version.packages/apps/kubernetes/templates/talos/talos-pki.yaml:76-80— comment claimsspec.ipAddressesis patched in by the reconcile hook; no such patch exists. Remove or rewrite.packages/core/platform/images/migrations/migrations/45:96-97— header comment says the migration annotates "KubeadmConfig instances spawned from them" but theapp.kubernetes.io/managed-by=Helmselector doesn't match CAPI-spawned instances. Update the comment to reflect actual semantics (KubeadmConfigTemplate only).packages/apps/kubernetes/templates/cluster.yaml:94—hasKey .group "ephemeralStorage"is dead code (CRD field-pruning strips the unknown field before Helm sees it). Remove or update the error message to clarify it only fires for manually-injected chart values.
Caveats
- Five prior reviews on this PR were intentionally not read during this independent pass; findings above may overlap with earlier discussion.
kubernetes-<release>-ingress-nginxService/Ingress incozyrdsservices.include/ingresses.includehas no matchingresourceNamesgrant intemplates/dashboard-resourcemap.yaml. This is pre-existing onmain, not introduced by this PR — listed only as context for a future cleanup.
…n-bump caveat Document two behaviour changes from the Phase 1 Talos rollover in the package Breaking Changes: the worker MachineHealthCheck maxUnhealthy moved from a hard-coded 0 (remediation effectively off) to nodeHealthCheck.maxUnhealthy defaulting to "50%" (remediation enabled), and that GitOps-managed tenant Kubernetes CRs must bump spec.version to v1.31 in Git or migration 46's patch is reverted on the next source reconcile. Also fix the supported version range in the intro (1.31-1.35; v1.30 was removed from the support matrix). Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Add runAsNonRoot/runAsUser/seccompProfile to the bootstrap-token and talos-reconcile hook Jobs so they satisfy PodSecurity "restricted" (matching the csr-signer sidecar). Drop the keyEncipherment usage from the Ed25519 trustd Certificate (RFC 9295 - Ed25519 keys cannot do key encipherment). Correct the stale talos-pki comment that claimed the reconcile hook patches spec.ipAddresses: the cert carries DNS SANs only and workers route to trustd via the Service DNS name, as the reconcile job's own routing note explains. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
…refs Set the executable bit on migration 45 to match its siblings (44, 46). Replace "PR #2610" references in migrations 45/46 with a description of the change. Correct migration 45's comment: the KubeadmConfig children CAPI spawns from the template are owned by their Machine (not Helm), so they carry no app.kubernetes.io/managed-by=Helm label, are not matched by the selector, and are never at risk of Helm pruning. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
bf92f3f
|
IvanHunters thanks for the thorough pass. Addressed in Fixed
Declined, with reasoning
MINOR#4 (emit a migration-46 failure Event) and MINOR#7 (the |
IvanHunters
left a comment
There was a problem hiding this comment.
Approving. The 4 MAJOR / 7 MINOR from my prior pass are addressed across 3478ed3 / a4c6a07 / bf92f3f, either by code, by Breaking-Changes docs, or by a defensible counter-argument:
Closed
- MAJOR#2 (README v1.30): fixed (1.31–1.35).
- MAJOR#1/4 (MHC default flip + GitOps
spec.versionrevert): documented as Breaking Changes inpackages/apps/kubernetes/README.md:90-95, with thenodeHealthCheck.maxUnhealthy: "0%"opt-out called out. - MAJOR#3 (10-min poll window): withdrawn — e2e-validated on a real cluster (
hack/e2e-apps/run-kubernetes.sh:148-156), intentional fast-fail design with the 20m HR ceiling, and reverting would mean Flux retries silently for hours instead of surfacing failures. - MINOR#1 / #5 / #6: fixed.
- MINOR#2 (orphan bootstrap-token): only reachable from an intermediate dev build of this branch, not from a released-
mainupgrade. Withdrawn. - MINOR#3 (certSANs JSON-merge): intentional per inline doc; Kamaji owns the SAN list. Withdrawn.
Non-blocking residuals — follow-ups, not merge gates
-
packages/core/platform/images/migrations/migrations/45:22-24— comment overstates GC:KubeadmConfigTemplatepinned withhelm.sh/resource-policy: keepis not owned by anyMachineSet(CAPI references templates by name, not viametadata.ownerReferences). After the Talos rollover Helm leaves them alone, nothing else GCs them, and they sit in tenant namespaces indefinitely. Same applies to the keep-annotatedKubeadmConfigchildren. A follow-up migration that drops the keep-annotated KCT/KubeadmConfig (plus the orphaned<release>-patch-containerdSecret) once the Talos MachineSet has been stable for N reconciles would close out the cleanup story. -
Narrow race during the rollover window: keep-annotated KCT still carries
contentFrom.secret.name: <release>-patch-containerd, and that Secret is unconditionally pruned on the upgrade (its template was removed). If MHC remediates an old kubeadm-backed Machine BEFOREMachineDeploymentfinishes scaling the old MachineSet down, the old MachineSet's controller can spawn a replacement from the keep'd KCT and thecontentFromlookup fails → bootstrap hangs. Documented mitigation isnodeHealthCheck.maxUnhealthy: "0%". The follow-up migration in #1 closes this by removing the dangling reference entirely; until then the"0%"opt-out is the safety net. -
packages/core/platform/sources/capi-provider-bootstrap-kubeadm.yaml— filename is now misleading since the wrapped package installs both kubeadm and TalosBootstrapProvider. Rename or split per-provider while the area is fresh. -
PR body / release-note: "existing tenants keep working without manual intervention" is now technically contradicted by the three Breaking-Changes entries (MHC
"0%"opt-out, GitOpsspec.versionbump, air-gapped Phase-2 wait). Consider softening to "API/dashboard-managed tenants need no action; see Breaking Changes for GitOps and air-gapped operators." -
packages/apps/kubernetes/templates/talos/bootstrap-token-tenant-job.yamlcreates a namespacedtalos:node-apiserver-endpoint-discoveryRole + RoleBinding in the tenantdefaultnamespace granting thesystem:nodesgroupget/list/watchon endpoints / endpointslices. Read-only and tightly scoped, but lands on every kubernetes-chart install/upgrade — worth a line in the tenant RBAC surface so operators auditing tenant clusters know to expect it. -
hack/e2e-apps/run-kubernetes.sh:43—local port="$3"declared but never used (SC2034). Pre-existing onmain, but the change set rewrites enough of this file that dropping it here is low-cost. -
Migration 46 failed-tenants signal (already acknowledged as a follow-up): wire the
cozystack.io/migration-46-failed-tenantsannotation oncozystack-versioninto a dashboard alert or release-notes runbook entry so operators don't need tokubectl describe cmto find stuck tenants.
#3118) ## What this PR does Migrations 45 and 46 (added by #2931) stamp the `cozystack-version` ConfigMap with an inline `kubectl apply` heredoc instead of sourcing `lib/cozystack-version.sh` and calling `stamp_cozystack_version`, the way migrations 42/43/44 do. The `cozystack-version-stamp.bats` guard forbids any migration ≥42 from bypassing the helper, so `make bats-unit-tests` fails on migration 45. This only surfaces in PR CI (`make unit-tests`) — `main`-push CI does not run the bats suite — so #2931 landed red on this test and now blocks every PR that merges current `main`. This routes both stamps through the helper. The helper renders a byte-identical labeled manifest (golden-pinned in the bats suite), so the change is behaviour-preserving: it just restores the no-label-drift guarantee the heredoc form could silently lose. Verified: `make bats-unit-tests` passes (was failing on migration 45), bash syntax-check clean on both scripts. ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved platform version stamping to keep the version record correctly labeled and consistent during upgrades. * Updated tenant Kubernetes resources to move from v1.30 to v1.31 as part of the migration flow. * **Chores** * Standardized migration behavior by using a shared version-stamping helper for more reliable updates. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Migrations 45 and 46 (added by cozystack#2931) stamp the cozystack-version ConfigMap with an inline `kubectl apply` heredoc instead of sourcing lib/cozystack-version.sh and calling stamp_cozystack_version, the way 42/43/44 do. The cozystack-version-stamp.bats guard forbids any migration >= 42 from bypassing the helper, so `make bats-unit-tests` fails on migration 45. This only surfaces in PR CI (make unit-tests); main-push CI does not run the bats suite, so cozystack#2931 landed red on this test and now blocks every PR that merges current main. Route both stamps through the helper. The helper renders a byte-identical labeled manifest (golden-pinned in the bats suite), so this is behaviour- preserving — it just restores the no-label-drift guarantee the heredoc form could silently lose. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
What this PR does
Phase 1 of the Kubernetes-app split design (see cozystack/community#8): replace the Ubuntu+kubeadm worker bootstrap path with Talos, driven by
cluster-api-bootstrap-provider-talos(CABPT) and aclastix/talos-csr-signersidecar embedded in the Kamaji control-plane pod. Existing tenants keep working — old machines roll out and get replaced by Talos workers without manual intervention.Highlights:
BootstrapProvideralongside the existing kubeadm one incapi-providers-bootstrap.KamajiControlPlane.spec.network.additionalServicePorts, used to publish trustd (50001/TCP) on the apiserver service.token,clusterId,clusterSecret,bootstrapToken) using the helm lookup-and-reuse pattern.bootstrap-token-<id>Secret inside the tenantkube-systemvia a Helm post-install/upgrade Job.TalosConfigTemplate(worker machineconfig,generateType: none) and switch theMachineDeployment.bootstrapreference fromKubeadmConfigTemplatetoTalosConfigTemplate, gated on Talos secrets and the Kamaji apiserver service being ready.DataVolume(source.http.url→factory.talos.dev), expose the system disk as virtio-blk withblockSize.custom: logical=512, physical=4096so 4Ki-native block storage backends (LINSTOR/DRBD) play nicely with QEMU's O_DIRECT writes and SeaBIOS still boots, drop the separate kubelet disk (Talos lays out EPHEMERAL itself).10.243.0.0/16/10.95.0.0/16) to avoid Talos's address-overlap diagnostic against the host pod CIDR.cluster.controlPlane.endpointandcilium.k8sServiceHostto the Kamaji apiserver Service ClusterIP (looked up at render time), so bootstrap survives the chicken-and-egg moment where tenant DNS does not exist yet and the host CoreDNS does not serve the tenant zone.End-to-end on a dev cluster: a fresh tenant brings up a Talos worker, kubelet CSRs get approved (apiserver-client by Kamaji, kubelet-serving by the talos-csr-signer sidecar), Cilium initialises with hostNetwork against the apiserver ClusterIP, CoreDNS comes up, and the node transitions to
Ready.Release note
Summary by CodeRabbit
Release Notes
New Features
talos.versionandtalos.schematicIDnodeHealthCheck(maxUnhealthy,nodeStartupTimeout) for worker remediation tuningkubectlandtalosCsrSignerBreaking Changes
nodeGroups.ephemeralStorage→nodeGroups.diskSizewith consolidated Talos system-disk semanticsRemovals
Documentation