KubeSolo can embed d2k, the Portainer Docker-to-Kubernetes API translator, so a single KubeSolo node exposes a Docker-compatible API endpoint that translates Docker calls into Kubernetes resources scoped to one namespace. With d2k enabled, existing Docker tooling, scripts, and CI pipelines can target a KubeSolo node without manual YAML application or a separate translator deployment.
The integration is gated behind a flag and is off by default. Enabling it does not change any other KubeSolo behaviour.
Two flags drive the integration:
| Flag | Env var | Default |
|---|---|---|
--d2k |
KUBESOLO_D2K |
false |
--d2k-namespace |
KUBESOLO_D2K_NAMESPACE |
d2k |
When --d2k is set, KubeSolo:
- Reuses the existing kubesolo CA at
/var/lib/kubesolo/pki/ca/to mint a d2k server certificate and a d2k client certificate. Both are persisted under/var/lib/kubesolo/pki/d2k/and reused on subsequent starts. - Reconciles all required Kubernetes resources programmatically (Namespace, ServiceAccount, Role/RoleBinding, ClusterRole/ClusterRoleBinding,
d2k-tlsSecret of typekubernetes.io/tls, Deployment, and a LoadBalancer Service on port2376). - Waits for the LoadBalancer Service to receive an external IP.
curl -sfL https://get.kubesolo.io | sudo sh -s -- --d2k=true --d2k-namespace=workloadsArchitecture support: the
portainer/d2kcontainer image is currently published only forlinux/amd64andlinux/arm64. Onarmandriscv64builds, passing--d2klogs a warning at startup and the flag is silently cleared — no PKI material is generated, no image is imported, and no Kubernetes resources are created.
Load-balancer requirement:
--d2krequires--load-balancer(the default). The d2k Service endpoint is populated by the KubeSolo LoadBalancer webhook; without it the endpoint address is never resolved. KubeSolo will exit at startup if--d2k=trueis combined with--load-balancer=false.
Namespace is fixed after first start: the d2k server certificate embeds the in-cluster DNS names for the namespace chosen at first start (e.g.
d2k.workloads.svc.cluster.local). Changing--d2k-namespaceon a subsequent start reuses the existing certificate, whose SANs no longer match — clients that connect via in-cluster DNS will fail TLS verification. To change the namespace, delete/var/lib/kubesolo/pki/d2k/server.crtand/var/lib/kubesolo/pki/d2k/server.keybefore restarting so the certificate is regenerated for the new namespace.
The client certificates are generated on the KubeSolo node under /var/lib/kubesolo/pki/d2k/.
| Path | Purpose |
|---|---|
/var/lib/kubesolo/pki/ca/ca.crt |
CA certificate |
/var/lib/kubesolo/pki/d2k/client.crt |
Client certificate |
/var/lib/kubesolo/pki/d2k/client.key |
Client key |
To find the node IP:
export KUBECONFIG=/var/lib/kubesolo/pki/admin/admin.kubeconfig
kubectl get nodes -o wideCERT_DIR="${HOME}/.config/d2k"
mkdir -p "${CERT_DIR}"
scp user@<NODE_IP>:/var/lib/kubesolo/pki/ca/ca.crt "${CERT_DIR}/ca.crt"
scp user@<NODE_IP>:/var/lib/kubesolo/pki/d2k/client.crt "${CERT_DIR}/client.crt"
scp user@<NODE_IP>:/var/lib/kubesolo/pki/d2k/client.key "${CERT_DIR}/client.key"Once the certificates are available locally, create a named Docker context:
CERT_DIR="${HOME}/.config/d2k"
docker context create d2k \
--docker "host=tcp://<NODE_IP>:2376,ca=${CERT_DIR}/ca.crt,cert=${CERT_DIR}/client.crt,key=${CERT_DIR}/client.key"Switch to it and start issuing Docker commands:
docker context use d2k
docker psCERT_DIR="${HOME}/.config/d2k"
docker -H tcp://<NODE_IP>:2376 \
--tlsverify \
--tlscacert "${CERT_DIR}/ca.crt" \
--tlscert "${CERT_DIR}/client.crt" \
--tlskey "${CERT_DIR}/client.key" \
psdocker ps lists pods in the --d2k-namespace namespace as Docker containers. See the upstream d2k README for the full Docker-to-Kubernetes translation table.
After starting KubeSolo with --d2k=true, confirm the resources have been reconciled:
export KUBECONFIG=/var/lib/kubesolo/pki/admin/admin.kubeconfig
kubectl -n <namespace> get deploy,svc,sa,role,rolebinding,secret/d2k-tls
kubectl get clusterrole,clusterrolebinding | grep d2k-node-readerThe integration intentionally limits itself to a single, mTLS-protected, Swarm-mode-enabled d2k deployment per KubeSolo node:
- Multi-namespace translation. d2k always translates against the namespace passed via
--d2k-namespace. - Authn/authz beyond mTLS. The endpoint is protected by the kubesolo-CA-signed client certificate; no additional bearer-token, OIDC, or RBAC layer is added on top.
- Custom d2k image overrides. The image is pinned to the version baked into the KubeSolo binary. Use
craneandcontainerddirectly if you need to evaluate a different upstream tag.