Skip to content

Commit 99a6f76

Browse files
vijayaraghavanr31manoj-nutanixdkoshkin
authored
feat: Add support for deploying K8s Agent as Helm Addon during cluster deployment (#1345)
**What problem does this PR solve?**: This PR introduces support for deploying the Nutanix K8s Agent as a Helm-based addon as part of the cluster deployment workflow in the CAREN repository. Key changes: Added support for HelmAddon strategy in the K8s Registration Agent handler. Updated handler logic to fetch and apply Helm chart configuration dynamically using the provided credentials. Created unit tests to validate HelmAddon flow and error scenarios. Ensured the agent’s credentials are handled securely through Kubernetes Secrets instead of directly passing via values.yaml. This enhancement enables seamless installation of the K8s Agent via HelmReleaseProxy (HRP) and HelmChartProxy (HCP) without manual post-deployment intervention. **Motivation** Previously, the K8s Agent installation was not integrated into the cluster creation process and required manual setup. By integrating it as an addon: The K8s Agent will be automatically deployed during cluster provisioning. Sensitive credentials are now secured using Kubernetes Secrets. This aligns the agent deployment with other addon-based lifecycle management mechanisms. **Which issue(s) this PR fixes**: Fixes # **How Has This Been Tested?**: Verified K8s Agent deployment using the HelmAddon strategy. Confirmed that: Pre-install hooks execute as expected. The secret is created and retained after installation. Post-upgrade hooks are triggered correctly. Added unit tests under k8sregistrationagent/handler_test.go [K8s agent documentation](https://docs.google.com/document/d/1E8qF94EYRX12yCpWDK_NqHHvH5tjqAtrD-DQDwMK7kU/edit?tab=t.0#heading=h.f3fcu3k7nqm) **Special notes for your reviewer**: <!-- Use this to provide any additional information to the reviewers. This may include: - Best way to review the PR. - Where the author wants the most review attention on. - etc. --> Cluster class used for testing with konnector Agent: [ClusterConfigWIthKonnectorAgent.yaml](https://github.com/user-attachments/files/22967186/ClusterConfigWIthKonnectorAgent.yaml) Cluster creation - with konnector agent secret and addon: `(devbox) vijayaraghavan.r@CQGK42CXL4 cluster-api-runtime-extensions-nutanix % kubectl apply -f /Users/vijayaraghavan.r/code/vijay/docs/clusteryamls/test/ClusterConfigWIthKonnectorAgent.yaml secret/nkp-vijay-test-cluster-29-pc-credentials created secret/nkp-vijay-test-cluster-29-pc-credentials-for-csi created secret/nkp-vijay-test-cluster-29-pc-credentials-for-konnector-agent created secret/nkp-vijay-test-cluster-29-image-registry-credentials created secret/global-nutanix-credentials created cluster.cluster.x-k8s.io/nkp-vijay-test-cluster-29 created configmap/kommander-bootstrap-configuration created secret/prism-central-metadata created` HelmChartProxy `(devbox) vijayaraghavan.r@CQGK42CXL4 cluster-api-runtime-extensions-nutanix % kubectl get hcp konnector-agent-0199eb7b-6107-73a5-b257-aa86711fd583 -o yaml apiVersion: addons.cluster.x-k8s.io/v1alpha1 kind: HelmChartProxy metadata: creationTimestamp: "2025-10-17T09:01:06Z" finalizers: - helmchartproxy.addons.cluster.x-k8s.io generation: 1 name: konnector-agent-0199eb7b-6107-73a5-b257-aa86711fd583 namespace: default ownerReferences: - apiVersion: cluster.x-k8s.io/v1beta1 kind: Cluster name: nkp-vijay-test-cluster-29 uid: d3c523c6-f598-4760-9286-ce1e8ae8fcda resourceVersion: "19416" uid: 28266af0-9c08-4f52-be70-4ff7e1473afe spec: chartName: konnector-agent clusterSelector: matchLabels: cluster.x-k8s.io/cluster-name: nkp-vijay-test-cluster-29 namespace: ntnx-system options: enableClientCache: false install: createNamespace: true timeout: 10m0s upgrade: maxHistory: 10 releaseName: konnector-agent repoURL: oci://helm-repository.default.svc/charts tlsConfig: caSecret: name: helm-repository-tls namespace: default valuesTemplate: |- agent: name: konnector-agent image: repository: quay.io/karbon name: k8s-agent pc: port: 9440 insecure: true #set this to true if PC does not have https enabled endpoint: pc.dev.nkp.sh # eg: ip or fqdn k8sClusterName: nkp-vijay-test-cluster-29 k8sDistribution: NKP createSecret: false version: 1.3.0-rc.0 status: conditions: - lastTransitionTime: "2025-10-17T09:03:25Z" status: "True" type: Ready - lastTransitionTime: "2025-10-17T09:03:25Z" status: "True" type: HelmReleaseProxiesReady - lastTransitionTime: "2025-10-17T09:01:06Z" status: "True" type: HelmReleaseProxySpecsUpToDate matchingClusters: - apiVersion: cluster.x-k8s.io/v1beta1 kind: Cluster name: nkp-vijay-test-cluster-29 namespace: default observedGeneration: 1 (devbox) vijayaraghavan.r@CQGK42CXL4 cluster-api-runtime-extensions-nutanix %` Cluster automatically onboarded in PC <img width="1649" height="79" alt="Screenshot 2025-10-17 at 2 35 45 PM" src="https://github.com/user-attachments/assets/57e0192e-7726-4983-a14e-2ed5dc9680f1" /> cluster deletion: `(devbox) vijayaraghavan.r@CQGK42CXL4 cluster-api-runtime-extensions-nutanix % kubectl delete -f /Users/vijayaraghavan.r/code/vijay/docs/clusteryamls/test/1konnectorAgent.yaml secret "nkp-vijay-test-cluster-29-pc-credentials" deleted secret "nkp-vijay-test-cluster-29-pc-credentials-for-csi" deleted secret "nkp-vijay-test-cluster-29-pc-credentials-for-konnector-agent" deleted secret "nkp-vijay-test-cluster-29-image-registry-credentials" deleted secret "global-nutanix-credentials" deleted cluster.cluster.x-k8s.io "nkp-vijay-test-cluster-29" deleted configmap "kommander-bootstrap-configuration" deleted secret "prism-central-metadata" deleted` <img width="691" height="252" alt="Screenshot 2025-10-17 at 2 39 23 PM" src="https://github.com/user-attachments/assets/f482e575-78f6-4ad0-ac49-2835a555e3f9" /> --------- Co-authored-by: Manoj Surudwad <[email protected]> Co-authored-by: Dimitri Koshkin <[email protected]>
1 parent 53680cf commit 99a6f76

File tree

33 files changed

+1625
-0
lines changed

33 files changed

+1625
-0
lines changed

api/v1alpha1/addon_types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ type NutanixAddons struct {
9090

9191
// +kubebuilder:validation:Optional
9292
COSI *NutanixCOSI `json:"cosi,omitempty"`
93+
94+
// +kubebuilder:validation:Optional
95+
KonnectorAgent *NutanixKonnectorAgent `json:"konnectorAgent,omitempty"`
9396
}
9497

9598
type GenericAddons struct {
@@ -371,3 +374,15 @@ type Ingress struct {
371374
// +kubebuilder:validation:Enum="aws-lb-controller"
372375
Provider string `json:"provider"`
373376
}
377+
378+
type NutanixKonnectorAgent struct {
379+
// A reference to the Secret for credential information for the target Prism Central instance
380+
// +kubebuilder:validation:Optional
381+
Credentials *NutanixKonnectorAgentCredentials `json:"credentials,omitempty"`
382+
}
383+
384+
type NutanixKonnectorAgentCredentials struct {
385+
// A reference to the Secret containing the credentials used by the Konnector agent.
386+
// +kubebuilder:validation:Required
387+
SecretRef LocalObjectReference `json:"secretRef"`
388+
}

api/v1alpha1/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const (
3232
ServiceLoadBalancerVariableName = "serviceLoadBalancer"
3333
// RegistryAddonVariableName is the OCI registry config patch variable name.
3434
RegistryAddonVariableName = "registry"
35+
// KonnectorAgentVariableName is the Nutanix konnector-agent addon config patch variable name.
36+
KonnectorAgentVariableName = "konnectorAgent"
3537

3638
// GlobalMirrorVariableName is the global image registry mirror patch variable name.
3739
GlobalMirrorVariableName = "globalImageRegistryMirror"

api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,28 @@ spec:
235235
- defaultStorage
236236
- providers
237237
type: object
238+
konnectorAgent:
239+
properties:
240+
credentials:
241+
description: A reference to the Secret for credential information for the target Prism Central instance
242+
properties:
243+
secretRef:
244+
description: A reference to the Secret containing the credentials used by the Konnector agent.
245+
properties:
246+
name:
247+
description: |-
248+
Name of the referent.
249+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
250+
maxLength: 253
251+
minLength: 1
252+
type: string
253+
required:
254+
- name
255+
type: object
256+
required:
257+
- secretRef
258+
type: object
259+
type: object
238260
nfd:
239261
description: NFD tells us to enable or disable the node feature discovery addon.
240262
properties:

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/variables/aggregate_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ type Addons struct {
6868
COSI *COSI `json:"cosi,omitempty"`
6969

7070
Ingress *Ingress `json:"ingress,omitempty"`
71+
72+
NutanixKonnectorAgent *NutanixKonnectorAgent `json:"konnectorAgent,omitempty"`
73+
}
74+
75+
type NutanixKonnectorAgent struct {
76+
carenv1.NutanixKonnectorAgent `json:",inline"`
7177
}
7278

7379
type CSI struct {

charts/cluster-api-runtime-extensions-nutanix/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ A Helm chart for cluster-api-runtime-extensions-nutanix
9292
| hooks.csi.snapshot-controller.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-snapshot-controller-helm-values-template"` | |
9393
| hooks.ingress.awsLoadBalancerController.defaultValueTemplateConfigMap.create | bool | `true` | |
9494
| hooks.ingress.awsLoadBalancerController.defaultValueTemplateConfigMap.name | string | `"default-aws-load-balancer-controller-helm-values-template"` | |
95+
| hooks.konnectorAgent.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | |
96+
| hooks.konnectorAgent.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-konnector-agent-helm-values-template"` | |
9597
| hooks.nfd.crsStrategy.defaultInstallationConfigMap.name | string | `"node-feature-discovery"` | |
9698
| hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | |
9799
| hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-nfd-helm-values-template"` | |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
agent:
2+
name: {{ .AgentName }}
3+
image:
4+
repository: quay.io/karbon
5+
name: k8s-agent
6+
pc:
7+
port: {{ .PrismCentralPort }}
8+
insecure: {{ .PrismCentralInsecure }} #set this to true if PC does not have https enabled
9+
endpoint: {{ .PrismCentralHost }} # eg: ip or fqdn
10+
k8sClusterName: {{ .ClusterName }}
11+
k8sDistribution: NKP
12+
createSecret: false

charts/cluster-api-runtime-extensions-nutanix/templates/deployment.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ spec:
4545
- --csi.snapshot-controller.helm-addon.default-values-template-configmap-name={{ (index .Values.hooks.csi "snapshot-controller").helmAddonStrategy.defaultValueTemplateConfigMap.name }}
4646
- --ccm.aws.helm-addon.default-values-template-configmap-name={{ .Values.hooks.ccm.aws.helmAddonStrategy.defaultValueTemplateConfigMap.name }}
4747
- --cosi.controller.helm-addon.default-values-template-configmap-name={{ .Values.hooks.cosi.controller.helmAddonStrategy.defaultValueTemplateConfigMap.name }}
48+
- --konnector-agent.helm-addon.default-values-template-configmap-name={{ .Values.hooks.konnectorAgent.helmAddonStrategy.defaultValueTemplateConfigMap.name }}
4849
{{- range $k, $v := .Values.hooks.ccm.aws.k8sMinorVersionToCCMVersion }}
4950
- --ccm.aws.aws-ccm-versions={{ $k }}={{ $v }}
5051
{{- end }}

charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ data:
3535
ChartName: cosi
3636
ChartVersion: 0.0.1-alpha.5
3737
RepositoryURL: '{{ if .Values.helmRepository.enabled }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://mesosphere.github.io/charts/stable/{{ end }}'
38+
konnector-agent: |
39+
ChartName: konnector-agent
40+
ChartVersion: 1.3.0-rc.1
41+
RepositoryURL: '{{ if .Values.helmRepository.enabled }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://mesosphere.github.io/charts/stable{{ end }}'
3842
local-path-provisioner-csi: |
3943
ChartName: local-path-provisioner
4044
ChartVersion: 0.0.32
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright 2025 Nutanix. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
{{- if .Values.hooks.konnectorAgent.helmAddonStrategy.defaultValueTemplateConfigMap.name }}
5+
apiVersion: v1
6+
kind: ConfigMap
7+
metadata:
8+
name: '{{ .Values.hooks.konnectorAgent.helmAddonStrategy.defaultValueTemplateConfigMap.name }}'
9+
data:
10+
values.yaml: |-
11+
{{- .Files.Get "addons/konnector-agent/values-template.yaml" | nindent 4 }}
12+
{{- end -}}

0 commit comments

Comments
 (0)