Skip to content

feat(infra): Allow node-role labeling for system nodes#348

Open
amdove wants to merge 3 commits into
mainfrom
allow-system-node-role-labels
Open

feat(infra): Allow node-role labeling for system nodes#348
amdove wants to merge 3 commits into
mainfrom
allow-system-node-role-labels

Conversation

@amdove

@amdove amdove commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description

Refresh of the closed #100 for the current Go codebase (the original targeted the removed Python/Pulumi code).

Adds a system_nodes option to managed node groups (additional_node_groups.<name>) and Karpenter node pools (karpenter_config.node_pools[]). When set, nodes are labeled posit.team/node-role=system, enabling node affinity rules — the motivating case being to keep the Team Operator image prepull daemonset off system nodes.

This PR only adds the labeling (the enabler). The matching affinity rule lives in team-operator and is a separate change; until it lands, prepull still runs everywhere.

Code Flow

  • lib/types/workload.go: new SystemNodes bool (system_nodes) on NodeGroupConfig and KarpenterNodePool.
  • Managed node groups (lib/aws/eks_cluster.go, lib/steps/eks_aws.go): sets the real k8s node label via awseks.NodeGroupArgs.Labels. Note the existing Labels field maps to AWS tags, which affinity can't match — so the label goes on the k8s labels field instead. Non-system groups are untouched (no state churn).
  • Karpenter (lib/steps/helm_aws.go): merges posit.team/node-role=system into the NodePool's template.metadata.labels.

Category of change

  • New feature (non-breaking change which adds functionality)

Testing

TestSystemNodesConfigFromYAML covers the yaml round-trip for both configs; just test-lib passes and just cli builds.

🤖 Generated with Claude Code

amdove and others added 2 commits July 10, 2026 14:29
…stem

Add a `system_nodes` option to both managed node groups
(additional_node_groups) and Karpenter node pools. When set, the node
group / pool labels its Kubernetes nodes with `posit.team/node-role=system`,
enabling node affinity / anti-affinity rules to be built on the node-role
label — for example so the Team Operator image prepull daemonset can be
kept off system nodes.

For the managed node group path this sets the real Kubernetes node label
(NodeGroupArgs.Labels) rather than only an AWS resource tag, which the
existing `labels` field maps to.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
.claude/settings.local.json is a personal, machine-local file and should
not be tracked; it was staged inadvertently by `git add -A`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@amdove amdove marked this pull request as ready for review July 15, 2026 16:21
@amdove amdove requested a review from a team as a code owner July 15, 2026 16:21
@claude

claude Bot commented Jul 15, 2026

Copy link
Copy Markdown

Claude finished @amdove's task in 1m 59s —— View job


Review

  • Read review guidelines
  • Review changed files
  • Post inline comments
  • Post summary

The change is small, additive, and the intent is clear. The implementation is correct for the common case. One structural concern worth addressing before merge:

template.metadata overwrite in Karpenter path (lib/steps/helm_aws.go:1499)

The system-nodes block assigns directly to nodepoolSpec["template"]["metadata"], replacing whatever was there. Today nothing else writes template.metadata for a NodePool, so it works — but it's a silent clobber waiting to happen. The analogous template.metadata.annotations or a second label would silently lose data. I've left an inline comment with a merge-safe alternative.

Everything else looks good:

  • lib/consts/consts.go: constants are clean and shared correctly between both paths.
  • lib/types/workload.go: SystemNodes bool placement is correct on both NodeGroupConfig and KarpenterNodePool. The doc comment is accurate.
  • lib/aws/eks_cluster.go: the nodeLabels block is nil when SystemNode is false, so existing node groups see no state change. This is the right approach.
  • lib/steps/eks_aws.go: one-liner thread-through of ng.SystemNodes → SystemNode. Correct.
  • lib/types/workload_test.go: TestSystemNodesConfigFromYAML covers decode + round-trip for both surfaces. Good coverage.
  • docs/infrastructure/kubernetes.md: the system_nodes description is accurate and cross-references both config surfaces.

One nit not worth blocking on: the Labels field doc comment on NodeGroupConfig (line 135, outside the diff) says "Labels applied as tags on this node group" — easy to misread as Kubernetes labels. Worth clarifying to "AWS resource tags" in a follow-up to make the contrast with SystemNodes explicit.

Comment thread lib/steps/helm_aws.go Outdated
…d of overwriting

The system-node label assignment overwrote template.metadata wholesale.
That is safe today (single writer), but a footgun: a future field that
sets template.metadata (annotations, another label) would be silently
discarded. Ensure metadata and metadata.labels exist and set only the
one key, matching the ngTags merge pattern in WithNodeGroup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@amdove amdove requested a review from stevenolen July 15, 2026 21:17
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.

1 participant