Skip to content

feat(anc): use gRPC as the check-hotfix live-patching transport - #9050

Draft
Devinwong wants to merge 1 commit into
mainfrom
devinwong-anc-hotfix-grpc-shared-contract
Draft

feat(anc): use gRPC as the check-hotfix live-patching transport#9050
Devinwong wants to merge 1 commit into
mainfrom
devinwong-anc-hotfix-grpc-shared-contract

Conversation

@Devinwong

@Devinwong Devinwong commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Note: No live-patching-service gRPC endpoint serves this RPC yet. Until one does, check-hotfix is a fail-open no-op on every node -- it stages nothing and never blocks provisioning. This PR lands the client transport so it is ready the moment the service is reachable.

What

Switch the aks-node-controller check-hotfix fetch from an HTTP-over-SNI placeholder to gRPC, and make gRPC the only transport. Single-purpose: transport only. The old HTTP path never ran against a real server, so dropping it carries no compatibility risk.

This is the node/client half of the live-patching path. The proxy/server half (kube-api-proxy Envoy routing to the live-patching service) is already merged separately, so this client is written to match that route.

Flow

flowchart LR
    A[check-hotfix<br/>node client] -->|1. IMDS GET| B[IMDS attested doc]
    A -->|2. GetComponentConfig<br/>SNI = apiserver FQDN + ALPN aks-live-patching<br/>token in gRPC metadata| C[kube-api-proxy envoy]
    C -->|ALPN-routed| D[live-patching service]
    D -->|config bytes| A
    A -->|3. parse + stage pointer| E[on-disk hotfix pointer]
    E -->|read unchanged| F[download-hotfix]
Loading

Key points

  • Shared contract, one source of truth. Reuses the akslivepatching.v1.LivePatchingService stubs from the aks-live-patching module (the agreed cross-team contract), wired in via a local replace directive. No proto or generated code is added in this module.

  • ALPN-based routing (matches the merged proxy route). The client dials the cluster apiserver FQDN as SNI -- riding the existing apiserver egress rule, no special SNI host -- and advertises ALPN ["aks-live-patching", "h2"]. The kube-api-proxy Envoy selects its live-patching filter chain by that ALPN value and forwards the stream to the service. TLS is verified against the on-disk cluster CA.

  • Auth. The IMDS attested-data document rides in gRPC request metadata (the analogue of the old HTTP bearer header).

  • Unchanged. The parse/stage path, the on-disk pointer file read by download-hotfix, and the hotfixConfig type all stay exactly as on main. check-hotfix remains fail-open (always exits 0).

  • Error mapping (gRPC status -> existing taxonomy):

    gRPC status Behavior
    Unauthenticated / PermissionDenied / NotFound Benign no-op (nothing published for this node yet)
    InvalidArgument / ResourceExhausted Authoritative rejection, no cold-start fallback
    Unavailable / DeadlineExceeded / Internal, transport errors Fallback-eligible (cold-start pointer may be staged)

Placeholders pending the finalized service contract

  • ancComponentName (component_name value) -- defaults to aks-node-controller.
  • lpsAttestedMetadataKey (metadata key for the attested-data document).

Tests

checkhotfix_grpc_test.go uses an in-process bufconn mock of the shared LivePatchingService: success, benign codes (no-op), Unavailable (fallback), InvalidArgument (no fallback), and fail-open exit 0. go build ./... and go vet clean. Remaining test failures are pre-existing and environment-specific (need a Linux /etc/os-release + shell); they fail identically on main and pass in Linux CI.

Draft / POC.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

The latest Buf updates on your PR. Results from workflow Buf CI / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJul 27, 2026, 9:31 PM

@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from 93a27f7 to 615f423 Compare July 27, 2026 19:31
@Devinwong
Devinwong changed the base branch from devinwong/anc-check-hotfix-configmap to main July 27, 2026 19:31
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from 91ba500 to 227948c Compare July 27, 2026 19:46
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Windows Unit Test Results

  3 files   12 suites   48s ⏱️
389 tests 389 ✅ 0 💤 0 ❌
392 runs  392 ✅ 0 💤 0 ❌

Results for commit 6dd0bb4.

♻️ This comment has been updated with latest results.

@Devinwong Devinwong changed the title feat(anc): scaffold gRPC hotfix transport and export shared hotfix.Config feat(anc): use gRPC as the check-hotfix live-patching transport Jul 27, 2026
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from c024ebf to 266d036 Compare July 27, 2026 21:19
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from 266d036 to b4f6df3 Compare July 27, 2026 21:31
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from b4f6df3 to df712e0 Compare July 27, 2026 21:39
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from df712e0 to e0e8bd1 Compare July 30, 2026 21:55
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from e0e8bd1 to be7f328 Compare July 30, 2026 22:12
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from be7f328 to 84b0eb3 Compare July 30, 2026 22:21
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from 84b0eb3 to 5207157 Compare July 30, 2026 22:26
…ng contract

Switch the check-hotfix subcommand's live-patching-service fetch from the
HTTP-over-SNI placeholder (which never ran against a real server) to the gRPC
GetComponentConfig contract. Rather than define a second copy of that contract,
reuse the shared akslivepatching.v1.LivePatchingService generated stubs from the
aks-live-patching module (the agreed cross-team contract), wired in via a local
replace directive.

The transport dials the apiserver front on the cluster FQDN with TLS verified
against the on-disk cluster CA and SNI pinned to the live-patching host, carries
the IMDS attested-data document in gRPC request metadata, and maps gRPC status
codes onto the existing benign-vs-fatal taxonomy. check-hotfix remains fail-open
(always exits 0): until a real gRPC endpoint serves, it is a no-op on every node
that stages nothing and never blocks provisioning.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ed2dd633-00bb-4b3b-885b-9741b917a0a0
@Devinwong
Devinwong force-pushed the devinwong-anc-hotfix-grpc-shared-contract branch from 5207157 to 6dd0bb4 Compare July 31, 2026 19:29
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