Kubernetes Integration
Summary
Add Kubernetes as a supported workload provider in Manager alongside Proxmox, Docker, and Dummy nodes.
The goal is to allow Manager to communicate directly with a local or remote Kubernetes API and provision and manage workloads through the existing node-provider abstraction.
This will also make local development and testing easier because Kubernetes can run through Docker Desktop or kind, while Proxmox normally requires physical hardware.
This issue will serve as the parent tracking issue for the complete Kubernetes integration. The implementation should be divided into smaller child issues and focused pull requests.
Background
The Docker Node API work in #375 and #394 added Docker as another provider behind the existing Node API abstraction.
The Kubernetes integration should follow the same general design:
Manager
|
+-- ProxmoxApi
|
+-- DockerApi
|
+-- DummyApi
|
+-- KubernetesApi
Provider selection should remain centralized in Node.api() or another single provider-dispatch location.
Provider-specific checks such as:
if (nodeType === 'kubernetes')
should not be spread throughout the jobs, routers, and business logic.
Proposed Kubernetes resource mapping
This mapping should be confirmed before implementation.
Manager concept | Kubernetes concept
-- | --
Manager Node | Kubernetes cluster/context
Manager Container | Kubernetes Deployment
Running instance | Pod created by the Deployment
Provider container ID | Stable namespaced Deployment identifier
Start | Scale Deployment to one replica
Stop | Scale Deployment to zero replicas
Reconfigure | Patch Deployment pod template
Delete | Delete Deployment
Live status | Deployment availability and replica status
Manager should not store a Pod name or Pod UID as the permanent provider ID because Pods are temporary and may be replaced during restarts, failures, or rollouts.
A possible provider ID format is:
namespace/deployment-name
Example:
default/example-container
Proposed Manager labels
Kubernetes resources created by Manager should include labels that allow Manager to identify and list only the resources it owns.
Example:
org.mieweb.opensource-server.managed=true
org.mieweb.opensource-server.node-id=<manager-node-id>
org.mieweb.opensource-server.container-id=<manager-container-id>
The exact label names can be finalized during implementation.
Proposed configuration
A Kubernetes-backed Manager node represents access to a Kubernetes cluster and context rather than a single Kubernetes worker node.
The initial implementation may require:
The kubeconfig file should be mounted or otherwise available to the Manager process.
Sensitive kubeconfig contents, bearer tokens, certificates, and private keys must not be returned through node serialization or written to logs.
Support for in-cluster authentication may be added later or included if it fits naturally into the initial design.
Main requirements
Kubernetes API client
Communicate with Kubernetes through its native API.
Use the official Kubernetes Node.js client where practical.
Do not shell out to kubectl.
Support local and remote Kubernetes clusters.
Validate authentication and connectivity.
Workload creation
Manager should be able to create a Kubernetes Deployment using the existing container creation flow.
The Deployment should support:
Kubernetes and its container runtime should handle image pulling and image-layer caching.
Lifecycle operations
The integration should support:
Create
Start
Stop
Live status
Reconfigure
Delete
Proposed lifecycle behavior:
Start -> scale Deployment to 1
Stop -> scale Deployment to 0
Status -> inspect Deployment replicas and conditions
Reconfigure -> patch Deployment and wait for rollout
Delete -> delete Deployment
Status handling
A Kubernetes workload should be considered running when its Deployment has the required available replica.
Possible mappings:
available replica present -> running
desired replicas = 0 -> offline
rollout in progress -> creating or updating
Deployment missing -> missing
API unavailable -> unknown
Deployment failed -> failed
The final mapping should remain compatible with Manager’s existing status values where possible.
Networking
The current provisioning flow assumes that every provider returns a MAC address and IP address.
That assumption does not work cleanly for Kubernetes:
Kubernetes Pods do not provide a stable Manager-level MAC address.
Pod IP addresses are ephemeral.
A Pod IP may change after a restart or rollout.
The shared provider abstraction should be updated so network information is based on provider capabilities rather than being mandatory.
For the initial Kubernetes implementation:
MAC address may be null.
The current Pod IP may be stored or displayed as informational data.
Pod IP must be treated as ephemeral.
Workload creation must not fail only because a MAC address is unavailable.
Stable networking through Services, Ingress, LoadBalancer, or NodePort may be handled in a later issue.
Provider abstraction work
The current jobs and provider APIs still contain Proxmox-specific terminology and assumptions such as:
The Kubernetes integration may require introducing a more provider-neutral workload lifecycle interface.
Possible interface direction:
createWorkload()
updateWorkload()
startWorkload()
stopWorkload()
deleteWorkload()
getWorkloadStatus()
getWorkloadNetwork()
listWorkloads()
waitForOperation()
Compatibility wrappers may temporarily preserve existing LXC-named methods while the shared flow is migrated.
The exact abstraction should be designed before or during the first child issue.
Local development workflow
The integration should be testable without Proxmox physical hardware.
Supported development options may include:
Expected local test flow:
Start a local Kubernetes cluster.
Mount or configure a kubeconfig for Manager.
Add a Kubernetes node in Manager.
Validate Kubernetes API connectivity.
Create an nginx:latest workload.
Confirm a Deployment and Ready Pod are created.
Confirm Manager reports the workload as running.
Stop it and confirm the Deployment scales to zero.
Start it and confirm a new Pod becomes Ready.
Change an environment variable or resource request.
Confirm Kubernetes performs a successful rollout.
Delete the workload.
Confirm the Deployment and owned Pods are removed.
Security requirements
TLS verification should remain enabled by default.
Kubeconfig credentials must not be logged.
Kubernetes tokens, certificates, and private keys must not be exposed through API responses.
Manager should not require cluster-admin.
Document a least-privilege RBAC configuration.
Prefer namespace-scoped permissions.
Only request the resource types and operations needed by Manager.
Do not read or list Kubernetes Secrets unless a future feature explicitly requires it.
Proposed child issues
1. Refactor Node API for provider-neutral workload lifecycle
Identify Proxmox- and Docker-specific assumptions.
Define the provider-neutral lifecycle contract.
Make network metadata optional and provider-aware.
Reduce provider-specific branching outside dispatch.
Add abstraction-level tests.
2. Add Kubernetes node configuration and authentication
Add the kubernetes node type.
Add migrations for Kubernetes configuration.
Add kubeconfig path, context, and namespace support.
Add backend validation.
Add Kubernetes connection testing.
Update OpenAPI.
Update TypeScript types.
Update node form and node list UI.
3. Implement Kubernetes workload provisioning
Add KubernetesApi.
Connect through the Kubernetes API.
Create labeled Deployments.
Apply image, CPU, memory, environment variables, and entrypoint.
Store a stable Deployment-based provider ID.
Wait for Deployment readiness.
4. Implement Kubernetes workload lifecycle
Live status
Start
Stop
Delete
Deployment discovery
Error handling
Timeout handling
5. Implement Kubernetes reconfiguration, networking, tests, and documentation
Patch Deployment pod templates.
Wait for rollout completion.
Handle ephemeral Pod IP addresses.
Support nullable MAC addresses.
Add mocked unit tests.
Document local-cluster testing.
Document Kubernetes RBAC.
Complete end-to-end testing.
Child issue scope may be adjusted after maintainers confirm the architecture.
Non-goals for the initial integration
The first Kubernetes integration does not need to support:
Creating Kubernetes clusters
Deleting Kubernetes clusters
Managing control-plane components
Arbitrary YAML manifest application
Helm charts
StatefulSets
PersistentVolumeClaims
Multi-container Pods
Horizontal Pod Autoscaling
Multiple replicas beyond the start/stop mapping
Ingress management
LoadBalancer management
NodePort management
Pod exec
Pod log streaming
Kubernetes dashboard functionality
Importing unmanaged Kubernetes workloads
Full kubectl replacement
These can be implemented through later issues.
Acceptance criteria
The proposed Deployment-based resource mapping is reviewed and approved.
The Kubernetes integration is divided into focused child issues.
Manager supports kubernetes as a node type.
Manager can authenticate with a local Kubernetes cluster.
Manager communicates through the Kubernetes API without invoking kubectl.
Manager can create a labeled single-replica Deployment.
The permanent provider ID refers to the Deployment rather than a Pod.
Start works by scaling the Deployment to one replica.
Stop works by scaling the Deployment to zero replicas.
Live status reflects actual Kubernetes Deployment state.
Reconfiguration updates the Deployment and waits for rollout.
Delete removes the Deployment and its owned Pods.
Kubernetes workloads are not required to provide a MAC address.
Pod IP addresses are treated as ephemeral.
Provider-specific Kubernetes branching is not scattered throughout shared code.
Existing Proxmox, Docker, and Dummy functionality continues to work.
OpenAPI, UI, tests, local setup documentation, and RBAC documentation are updated.
Open design questions
Before beginning implementation, maintainers should confirm:
Should a Manager Container map to a Kubernetes Deployment?
Should the provider ID use namespace/deployment-name?
Should kubeconfig configuration be stored as a mounted file path?
Should Kubernetes namespaces be configured per node or per container?
Should Pod IP be stored in the existing ipv4Address field or only returned dynamically?
Should the first implementation create a Kubernetes Service, or should service exposure remain out of scope?
How much of the existing LXC-named API should be refactored before adding KubernetesApi?
Should the work be delivered through the proposed five child issues and PRs?
Related work
Kubernetes Integration
Summary
Add Kubernetes as a supported workload provider in Manager alongside Proxmox, Docker, and Dummy nodes.
The goal is to allow Manager to communicate directly with a local or remote Kubernetes API and provision and manage workloads through the existing node-provider abstraction.
This will also make local development and testing easier because Kubernetes can run through Docker Desktop or
kind, while Proxmox normally requires physical hardware.This issue will serve as the parent tracking issue for the complete Kubernetes integration. The implementation should be divided into smaller child issues and focused pull requests.
Background
The Docker Node API work in #375 and #394 added Docker as another provider behind the existing Node API abstraction.
The Kubernetes integration should follow the same general design:
Provider selection should remain centralized in
Node.api()or another single provider-dispatch location.Provider-specific checks such as:
should not be spread throughout the jobs, routers, and business logic.
Proposed Kubernetes resource mapping
This mapping should be confirmed before implementation.
Manager concept | Kubernetes concept -- | -- Manager Node | Kubernetes cluster/context Manager Container | Kubernetes Deployment Running instance | Pod created by the Deployment Provider container ID | Stable namespaced Deployment identifier Start | Scale Deployment to one replica Stop | Scale Deployment to zero replicas Reconfigure | Patch Deployment pod template Delete | Delete Deployment Live status | Deployment availability and replica statusManager should not store a Pod name or Pod UID as the permanent provider ID because Pods are temporary and may be replaced during restarts, failures, or rollouts.
A possible provider ID format is:
Example:
Proposed Manager labels
Kubernetes resources created by Manager should include labels that allow Manager to identify and list only the resources it owns.
Example:
The exact label names can be finalized during implementation.
Proposed configuration
A Kubernetes-backed Manager node represents access to a Kubernetes cluster and context rather than a single Kubernetes worker node.
The initial implementation may require:
Kubeconfig path
Optional kubeconfig context
Default namespace
TLS verification
Kubernetes API connection validation
The kubeconfig file should be mounted or otherwise available to the Manager process.
Sensitive kubeconfig contents, bearer tokens, certificates, and private keys must not be returned through node serialization or written to logs.
Support for in-cluster authentication may be added later or included if it fits naturally into the initial design.
Main requirements
Kubernetes API client
Communicate with Kubernetes through its native API.
Use the official Kubernetes Node.js client where practical.
Do not shell out to
kubectl.Support local and remote Kubernetes clusters.
Validate authentication and connectivity.
Workload creation
Manager should be able to create a Kubernetes Deployment using the existing container creation flow.
The Deployment should support:
OCI container image
Hostname or Kubernetes-safe workload name
CPU request or limit
Memory request or limit
Environment variables
Entrypoint or command
One desired replica
Manager ownership labels
Configured namespace
Kubernetes and its container runtime should handle image pulling and image-layer caching.
Lifecycle operations
The integration should support:
Create
Start
Stop
Live status
Reconfigure
Delete
Proposed lifecycle behavior:
Status handling
A Kubernetes workload should be considered running when its Deployment has the required available replica.
Possible mappings:
The final mapping should remain compatible with Manager’s existing status values where possible.
Networking
The current provisioning flow assumes that every provider returns a MAC address and IP address.
That assumption does not work cleanly for Kubernetes:
Kubernetes Pods do not provide a stable Manager-level MAC address.
Pod IP addresses are ephemeral.
A Pod IP may change after a restart or rollout.
The shared provider abstraction should be updated so network information is based on provider capabilities rather than being mandatory.
For the initial Kubernetes implementation:
MAC address may be
null.The current Pod IP may be stored or displayed as informational data.
Pod IP must be treated as ephemeral.
Workload creation must not fail only because a MAC address is unavailable.
Stable networking through Services, Ingress, LoadBalancer, or NodePort may be handled in a later issue.
Provider abstraction work
The current jobs and provider APIs still contain Proxmox-specific terminology and assumptions such as:
VMID allocation
LXC method names
Storage resolution
Proxmox task IDs
Mandatory MAC and IP discovery
Docker-specific task parsing
Direct
nodeTypechecksThe Kubernetes integration may require introducing a more provider-neutral workload lifecycle interface.
Possible interface direction:
Compatibility wrappers may temporarily preserve existing LXC-named methods while the shared flow is migrated.
The exact abstraction should be designed before or during the first child issue.
Local development workflow
The integration should be testable without Proxmox physical hardware.
Supported development options may include:
Docker Desktop Kubernetes
kindAnother local Kubernetes cluster
Expected local test flow:
Start a local Kubernetes cluster.
Mount or configure a kubeconfig for Manager.
Add a Kubernetes node in Manager.
Validate Kubernetes API connectivity.
Create an
nginx:latestworkload.Confirm a Deployment and Ready Pod are created.
Confirm Manager reports the workload as running.
Stop it and confirm the Deployment scales to zero.
Start it and confirm a new Pod becomes Ready.
Change an environment variable or resource request.
Confirm Kubernetes performs a successful rollout.
Delete the workload.
Confirm the Deployment and owned Pods are removed.
Security requirements
TLS verification should remain enabled by default.
Kubeconfig credentials must not be logged.
Kubernetes tokens, certificates, and private keys must not be exposed through API responses.
Manager should not require
cluster-admin.Document a least-privilege RBAC configuration.
Prefer namespace-scoped permissions.
Only request the resource types and operations needed by Manager.
Do not read or list Kubernetes Secrets unless a future feature explicitly requires it.
Proposed child issues
1. Refactor Node API for provider-neutral workload lifecycle
Identify Proxmox- and Docker-specific assumptions.
Define the provider-neutral lifecycle contract.
Make network metadata optional and provider-aware.
Reduce provider-specific branching outside dispatch.
Add abstraction-level tests.
2. Add Kubernetes node configuration and authentication
Add the
kubernetesnode type.Add migrations for Kubernetes configuration.
Add kubeconfig path, context, and namespace support.
Add backend validation.
Add Kubernetes connection testing.
Update OpenAPI.
Update TypeScript types.
Update node form and node list UI.
3. Implement Kubernetes workload provisioning
Add
KubernetesApi.Connect through the Kubernetes API.
Create labeled Deployments.
Apply image, CPU, memory, environment variables, and entrypoint.
Store a stable Deployment-based provider ID.
Wait for Deployment readiness.
4. Implement Kubernetes workload lifecycle
Live status
Start
Stop
Delete
Deployment discovery
Error handling
Timeout handling
5. Implement Kubernetes reconfiguration, networking, tests, and documentation
Patch Deployment pod templates.
Wait for rollout completion.
Handle ephemeral Pod IP addresses.
Support nullable MAC addresses.
Add mocked unit tests.
Document local-cluster testing.
Document Kubernetes RBAC.
Complete end-to-end testing.
Child issue scope may be adjusted after maintainers confirm the architecture.
Non-goals for the initial integration
The first Kubernetes integration does not need to support:
Creating Kubernetes clusters
Deleting Kubernetes clusters
Managing control-plane components
Arbitrary YAML manifest application
Helm charts
StatefulSets
PersistentVolumeClaims
Multi-container Pods
Horizontal Pod Autoscaling
Multiple replicas beyond the start/stop mapping
Ingress management
LoadBalancer management
NodePort management
Pod exec
Pod log streaming
Kubernetes dashboard functionality
Importing unmanaged Kubernetes workloads
Full
kubectlreplacementThese can be implemented through later issues.
Acceptance criteria
The proposed Deployment-based resource mapping is reviewed and approved.
The Kubernetes integration is divided into focused child issues.
Manager supports
kubernetesas a node type.Manager can authenticate with a local Kubernetes cluster.
Manager communicates through the Kubernetes API without invoking
kubectl.Manager can create a labeled single-replica Deployment.
The permanent provider ID refers to the Deployment rather than a Pod.
Start works by scaling the Deployment to one replica.
Stop works by scaling the Deployment to zero replicas.
Live status reflects actual Kubernetes Deployment state.
Reconfiguration updates the Deployment and waits for rollout.
Delete removes the Deployment and its owned Pods.
Kubernetes workloads are not required to provide a MAC address.
Pod IP addresses are treated as ephemeral.
Provider-specific Kubernetes branching is not scattered throughout shared code.
Existing Proxmox, Docker, and Dummy functionality continues to work.
OpenAPI, UI, tests, local setup documentation, and RBAC documentation are updated.
Open design questions
Before beginning implementation, maintainers should confirm:
Should a Manager Container map to a Kubernetes Deployment?
Should the provider ID use
namespace/deployment-name?Should kubeconfig configuration be stored as a mounted file path?
Should Kubernetes namespaces be configured per node or per container?
Should Pod IP be stored in the existing
ipv4Addressfield or only returned dynamically?Should the first implementation create a Kubernetes Service, or should service exposure remain out of scope?
How much of the existing LXC-named API should be refactored before adding
KubernetesApi?Should the work be delivered through the proposed five child issues and PRs?
Related work
Docker-type Node API #375 — Docker-type Node API
feat(nodes): add Docker API backend #394 — Add Docker API backend