Skip to content

feat: Profile for AKS - #161

Open
AdminTurnedDevOps wants to merge 10 commits into
kagent-dev:mainfrom
AdminTurnedDevOps:feat/installer-profiles
Open

AdminTurnedDevOps wants to merge 10 commits into
kagent-dev:mainfrom
AdminTurnedDevOps:feat/installer-profiles

Conversation

@AdminTurnedDevOps

@AdminTurnedDevOps AdminTurnedDevOps commented Nov 8, 2026 •

Copy link
Copy Markdown

Resolves #160

The goal is a universal installer.

As people use the universal installer, however, they will need the ability to specify certain configurations for where they are installing. For example, if someone is installing on Azure Kubernetes Service (AKS), they may want to point to Azure Container Registry (ACR) or managed grafana (it's the primary monitoring option when you're creating an AKS cluster).

Therefore, the Profiles feature works if you want to have specific configurations for certain cluster types (like AKS).

Right now, this is just for AKS. However, if the proposed design/architecture is approved, we can use it as a "standard" to create profiles for other types of clusters as well (GKE, EKS, etc.).

2026-11-08_16-53-25.mp4

This PR also contains a fix for the installer.

image
  • Tests pass
  • Docs updated

@AdminTurnedDevOps
AdminTurnedDevOps marked this pull request as draft November 8, 2026 22:22
Add a profile field to the install config and a --profile flag on
install, upgrade and uninstall. generic keeps the current behavior. aks
adds an aks section. Its acr field pulls every image install deploys from
an Azure Container Registry: it sets global.imageRegistry on the charts
and renames the bundled PostgreSQL image.

The wizard asks for the cluster type unless --profile is given.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
An AKS cluster created without --network-policy accepts NetworkPolicy
objects and ignores them, which leaves the ate-system policies and the
per-WorkerPool policies without effect. With profile: aks, install and
upgrade now fail unless a cilium, azure-npm or calico-node DaemonSet
exists.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
storageClass sets the StorageClass of the bundled PostgreSQL and RustFS
volumes, which otherwise use the cluster's default. The substrate chart
gets a rustfs.storageClassName value for it. On AKS the wizard suggests
managed-csi-premium.

An existing PostgreSQL keeps its StorageClass, since a StatefulSet's
volumeClaimTemplates can't change.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
aks.nodePool restricts atelet to one node pool through its
kubernetes.azure.com/agentpool label. Install checks that the pool has
nodes, and with microvm enabled, that one of them advertises
ate.dev/kvm, which needs a VM size with nested virtualization.
WorkerPools need the same node selector, and install prints a note
saying so.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
aks.acrCredentialProvider lets atelet pull actor images from Azure
Container Registry. atelet runs the node's acr-credential-provider with
the kubelet's own config. The provider reads /etc/kubernetes/azure.json,
which the charts now mount through a new
atelet.imageCredentialProviderHostFiles value.

It is off by default, since atelet can then pull from every registry the
kubelet identity can. With profile aks, turning it off resets those
values, so an earlier install's access goes away.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
otelEndpoint points atelet and the control plane at an existing OTLP
collector by setting otel.endpoint on the atelet and substrate releases.
The wizard asks for it. Install doesn't deploy a collector.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
aks.managedPrometheus has Azure Managed Prometheus scrape atelet and the
control plane. It enables a new podMonitors chart value with the
azmonitoring.coreos.com/v1 API. The charts then render PodMonitors for the
/metrics endpoints of atelet, ate-api-server, ate-controller,
atenet-router and atenet-egress.

Preflight fails if the cluster doesn't serve that API.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
Install's cluster check only looked for podcertificaterequests in
certificates.k8s.io/v1beta1. Kubernetes 1.37 clusters like AKS serve it
only at v1, so install failed there, though the certificate controller
already prefers v1. The check now accepts either version.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
@AdminTurnedDevOps
AdminTurnedDevOps marked this pull request as ready for review November 8, 2026 22:39
Comment thread charts/substrate-atelet/values.yaml Outdated
Comment on lines +59 to +61
# Other host files the providers read, mounted read-only at the same path
# (AKS: /etc/kubernetes/azure.json).
imageCredentialProviderHostFiles: []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just expose extra volumes + extra volume mounts for this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

limitations under the License.
*/}}

{{- /* atelet's PodMonitor is in atelet.yaml, so substrate-atelet renders it too. */}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Atelet should be installed via substrate-atelet chart. this is just here for compatibility for one release

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The substrate chart's atelet template is back to upstream's version, and extraVolumes/extraVolumeMounts and the atelet PodMonitor are now only in substrate-atelet.

Comment thread charts/substrate/values.yaml Outdated
Comment on lines +93 to +95
# Other host files the providers read, mounted read-only at the same path
# (AKS: /etc/kubernetes/azure.json).
imageCredentialProviderHostFiles: []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@EItanya

EItanya commented Nov 8, 2026

Copy link
Copy Markdown

Thanks for this. Direction I'd like: a profile is just a well-known install config file that we embed, and profile: aks / --profile aks layers it under the user's config. No profile-specific code paths.

So for AKS:

  • profiles/aks.yaml sets the static AKS bits: the credential provider paths plus an extraVolumes/extraVolumeMounts entry for azure.json on the atelet release (commented out, with the service principal caveat), podMonitors.apiVersion: azmonitoring.coreos.com/v1, and storageClass: managed-csi-premium, with comments for the az setup steps.
  • ACR and node pool are per-cluster, so users set global.imageRegistry and atelet.nodeSelector themselves.
  • Drop aks.go, the AKS config struct, the ProfileAKS branches in install/upgrade/wizard, and the AKS help text. If we want KVM or NetworkPolicy checks, let's add them as generic checks separately.
  • The profile list comes from the embedded directory. Releases values from the profile deep-merge under the user's. Add a test that every embedded profile parses and validates.

Could you also split out the generic pieces as their own PRs first: the PodCertificateRequest v1 fix, storageClass/rustfs.storageClassName, a top-level imageRegistry (postgres needs it), the PodMonitor templates, and atelet extraVolumes/extraVolumeMounts?

Comment left by Claude on behalf of @EItanya

@AdminTurnedDevOps

Copy link
Copy Markdown
Author

@EItanya Gotcha, makes sense! So you're thinking more of like a config file/YAML that someone points to with the specific configs they need for the cluster they're targeting vs having it has a flag/sub-command like --profile?

atelet.extraVolumes and atelet.extraVolumeMounts add any volume to the
atelet pod, so the charts don't need a value just for credential
provider files. With aks.acrCredentialProvider on, install now mounts
/etc/kubernetes/azure.json through them, after any the config sets.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
The substrate chart's atelet template stays only for one release, for
compatibility. It goes back to upstream, and atelet.extraVolumes,
atelet.extraVolumeMounts and the atelet PodMonitor stay in the
substrate-atelet chart. The installer already installs atelet with that
chart.

Signed-off-by: adminturneddevops <mlevan1992@gmail.com>
@EItanya

EItanya commented Nov 9, 2026

Copy link
Copy Markdown

Sort of, i was imagining profiles are just shortcuts for a well known set of yaml configs that we bake in at build time. Like istioctl

@AdminTurnedDevOps

AdminTurnedDevOps commented Nov 10, 2026 •

Copy link
Copy Markdown
Author

Sort of, i was imagining profiles are just shortcuts for a well known set of yaml configs that we bake in at build time. Like istioctl

@EItanya - let me know if you like this approach to simplifying the profiles:

  • Profiles are embedded files. pkg/kagent/install/profiles/aks.yaml is the only one, and it sets storageClass: managed-csi-premium. Adding a profile means adding a YAML file there.
  • Layering happens at read time. --profile aks deep-merges the user's config over the profile, then decodes it over the defaults. The config file has no profile key.
  • Config has no Profile field. The profile is consumed while reading, so installer code cannot branch on it. The wizard's printed config is therefore fully resolved and doesn't mention the profile.
  • aks.acr becomes a generic imageRegistry. It sets global.imageRegistry on the releases and renames the bundled PostgreSQL image on any cluster.
  • The KVM check is generic. With microvm.enabled, install now waits for a node to advertise ate.dev/kvm on every cluster. A microvm install on nodes without /dev/kvm (for example a local kind cluster) now fails after two minutes where it used to succeed.
  • AKS code is gone. aks.go, the AKS config section, the NetworkPolicy, node pool and Managed Prometheus checks, the "Check AKS" upgrade step and the wizard's AKS questions are all removed. upgrade.go matches upstream again.
  • The wizard asks for a profile first, then pre-fills the remaining questions from it.

@EItanya

EItanya commented Nov 10, 2026

Copy link
Copy Markdown

We shouldn't need profile: aks. Profile is a hint a layer above the config

@AdminTurnedDevOps

Copy link
Copy Markdown
Author

We shouldn't need profile: aks. Profile is a hint a layer above the config

Are you saying it shouldn't be a key inside the config file? If so, the workflow would be that the profile is chosen by --profile aks or the wizard, and the file holds only settings. Or are you saying it shouldn't be specified at all?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

kubectl ate install: add cluster profiles, starting with AKS

2 participants