Fix P2 provider status semantics#32
Merged
Merged
Conversation
Start the Virtual Kubelet node controller from cmd/macvz-kubelet around the existing apple/container runtime driver, without registering Pods yet. - pkg/config: add Config.RestConfig to build a Kubernetes REST config from an explicit kubeconfig path, KUBECONFIG/default rules, or in-cluster config. A missing or unparseable kubeconfig fails loudly at startup rather than silently falling back. - cmd/macvz-kubelet: build the kube client, construct the provider over the runtime driver, and run a node.NewNodeController with NaiveNodeProvider on a minimal Node object. Capacity/conditions (#14), lease/heartbeat (#15), and the Pod lifecycle (#16) build on this loop. - Graceful shutdown via signal.NotifyContext (SIGINT/SIGTERM); runtime readiness remains visible on startup. - Tests cover missing, invalid, and valid kubeconfig wiring. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#14) Advertise a coherent, configurable node shape through Virtual Kubelet so the scheduler can target the Mac intentionally. - pkg/config: add a `node:` block (cpu/memory/pods, os/arch, internalIP, labels, annotations, taints). Capacity defaults stay conservative (2 CPU / 4Gi / 20 pods) until P1 density data is recorded. Capacity() and Taints() parse to k8s core types and are validated at load time (bad quantity or taint effect fails fast). Default taint is the well-known virtual-kubelet.io/provider=macvz:NoSchedule so only tolerating Pods land. - pkg/provider: BuildNode assembles the corev1.Node — capacity == allocatable (no MVP reservation), workload-platform OS/arch labels and node info, merged user labels/annotations, taints, addresses, and a coherent condition set. The Ready condition reflects live runtime readiness via the optional runtime.Pinger; pressure conditions report False. - cmd/macvz-kubelet: resolve the configured node shape, auto-detect the host InternalIP when unset, and register the assembled node. Ongoing heartbeat/lease updates remain #15. - config.example.yaml documents the new node block; tests cover capacity/taint parsing, validation, label override/merge, readiness mapping, and address handling. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the MacVz virtual node alive and surface runtime readiness over time. - pkg/config: add heartbeat tuning to the node block — enableLease (default true), leaseDurationSeconds (40), pingInterval (10s), statusUpdateInterval (1m), mirroring Virtual Kubelet's defaults. HeartbeatIntervals() parses and validates the durations; Validate() rejects bad intervals and a non-positive lease duration when leases are enabled. - pkg/provider: add NodeStatusProvider implementing node.NodeProvider. Ping reports process liveness (driving the lease/heartbeat); NotifyNodeStatus runs a watch loop that re-probes the runtime each status interval and pushes a refreshed node only when the Ready condition flips, so runtime failures show up as NotReady without removing the node. The loop exits on context cancel. - cmd/macvz-kubelet: wire the status provider plus WithNodePingInterval, WithNodeStatusUpdateInterval, WithNodeEnableLeaseV1 (lease in kube-node-lease), and a status-update error handler that logs and returns nil so the control loop and client-go retry/backoff handle transient API errors. - config.example.yaml documents the heartbeat block; tests cover interval parsing/validation, lease-duration validation, Ping semantics, push-on-change (both directions), and clean shutdown (race-clean). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the P0 not-implemented skeleton with a real PodLifecycleHandler backed by the runtime abstraction and an in-memory pod/workload state store. - pkg/provider/provider.go: add the podState store mapping namespace/name to the runtime workload IDs backing each container, with a sync.RWMutex for concurrent reconcile/CRUD access. - pkg/provider/pod.go: implement CreatePod/UpdatePod/DeletePod/GetPod/ GetPodStatus/GetPods. CreatePod pulls+creates+starts a workload per container, is a no-op for an already-tracked Pod, and rolls back started workloads on partial failure so retries start clean. DeletePod stops+destroys and is idempotent (unknown Pod -> errdefs.NotFound). Missing Pods return errdefs.NotFound so Virtual Kubelet reconciliation behaves correctly. - pkg/provider/status.go: reconcile observed runtime state into container statuses and aggregate the Pod phase (Pending/Running/Succeeded/Failed); a runtime ErrNotFound maps to a terminated "Lost" container rather than failing the whole status read. - pkg/provider/translate.go: minimal Pod->ContainerSpec translation (image, command/args, literal env, CPU/memory). Richer translation is #17. - Tests with a recording fake runtime cover create/get/list/status/delete, idempotent create+delete retries, rollback, phase mapping, lost workloads, and ErrNotReady propagation (race-clean). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build out the MVP translation layer from Kubernetes Pod/container fields to types.ContainerSpec, with clear rejection of unsupported shapes. - pkg/provider/translate.go: translatePod validates a Pod is a supported shape and translates its single container. workloadID derives a stable, DNS-safe (RFC 1123) name from namespace/name/container, hash-truncated when it would exceed 63 chars, so the driver gets a deterministic --name. Image, command, args, literal env, and CPU/memory (limit, falling back to request) are translated. unsupportedReasons reports multi-container, init/ephemeral containers, user volumes (the auto-mounted service-account token is tolerated), pod/container securityContext, host namespaces, envFrom, and env valueFrom — each with an actionable message. - pkg/provider/pod.go: CreatePod now translates a single container. Unsupported specs and arch-incompatible images (the P1 ErrIncompatibleArch signal) are recorded as a sticky terminal Failed status with a clear reason/message and return nil, so Virtual Kubelet surfaces it to Kubernetes instead of retrying forever. provider/status.go honors the sticky status during reconciliation. - Table-driven tests cover the kubectl-run shape, command/args/env/resource sizing, request fallback, every unsupported feature, SA-token tolerance, and workload-ID stability/DNS-safety/truncation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expose the Virtual Kubelet log and exec paths on the provider, delegating to runtime.Logs and runtime.Exec for running micro-VM workloads. - pkg/provider/logs_exec.go: GetContainerLogs maps Virtual Kubelet ContainerLogOpts (follow/tail) onto runtime.LogOptions; RunInContainer wires AttachIO stdin/stdout/stderr and TTY into runtime.ExecIO, drains the resize channel for TTY sessions (the runtime has no resize), and converts a clean non-zero command exit into a utilexec.ExitError so kubectl reports the exit status. A workloadID helper resolves container -> runtime workload ID, and runtime ErrNotFound/ErrNotRunning map to clear Kubernetes-facing errors (errdefs.NotFound / "not running"). Compile-time assertions pin the method signatures to the VK handler function types. - Fake-runtime tests cover log streaming + tail propagation, exec stream wiring, non-zero exit-code mapping, and unknown pod/container errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st (#19) Tie the virtual node together end-to-end and document the P2 acceptance path. Serving (the code needed for the smoke test to actually work): - cmd/macvz-kubelet/serve.go: start the Virtual Kubelet pod controller with pod (node-filtered) / configmap / secret / service informers and an event recorder, so scheduled Pods become micro-VMs via the provider. Start an HTTPS kubelet API server (api.PodHandler) routing kubectl logs/exec to the provider; it is a no-op with a clear warning when no serving cert is configured, so Pods still run without logs/exec. - main.go starts both after the node becomes Ready and tears them down on shutdown. - pkg/config: add node.kubeletPort (default 10250) and servingTLSCertFile/ servingTLSKeyFile, validated (port range; cert+key set together). - pkg/provider: advertise the kubelet endpoint port in node DaemonEndpoints so the API server knows where to reach logs/exec. Manifests and docs: - deployments/rbac.yaml: ServiceAccount + ClusterRole/Binding scoped to the MVP (nodes/status, pods/status, configmaps/secrets/services read, events, leases). - deployments/alpine-smoke.yaml: single-container Alpine Pod tolerating the provider taint and targeting the virtual node. - docs/P2_SMOKE_TEST.md: build/configure/run, kubectl get nodes + describe, run Alpine, verify logs/exec (incl. non-zero exit and error cases), cleanup, and troubleshooting. Linked as P2 acceptance evidence from MASTER_TASKS. Dependency: bump google.golang.org/genproto to resolve an ambiguous-import conflict pulled in by the kubelet API server packages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1e21a95 to
badb4bd
Compare
This was referenced Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Verification