Skip to content

Conversation

@kartikjoshi21
Copy link
Contributor

@kartikjoshi21 kartikjoshi21 commented Dec 8, 2025

This PR teaches the Docker (KIC) driver about ip-family and IPv6/dual-stack, building on the config/flag plumbing from PR1. It does not yet change kubeadm/CNI templates; those are follow-ups.

Concretely, it:

  • Plumbs IPFamily, StaticIPv6, and Subnetv6 from ClusterConfig into the KIC driver and CreateContainerNode, so nodes can get static IPv4/IPv6 addresses.

  • Replaces CreateNetwork with CreateNetworkWithIPFamily to create:

    • IPv4-only networks (current behaviour),
    • dual-stack bridges (--ipv6, IPv4 + optional --subnet-v6), and
    • IPv6-only bridges (--ipv6, optional v6 subnet),
      and requires --subnet-v6 when --static-ipv6 is used instead of guessing a /64.
  • Assigns container IPs per family and updates GetIP, GetExternalIP, and GetSSHHostname so:

    • IPv6 clusters use the IPv6 container IP and publish on ::1 (or :: for external Docker),
    • IPv4/dual clusters keep returning IPv4 by default.
  • Extends Docker network inspect/gateway helpers and digDNS to understand dual-stack networks:

    • Handles multi-subnet/multi-gateway output, prefers IPv4 when available, and falls back cleanly to IPv6.
  • Updates container run args and port publishing:

    • Adds --ip6 when a static IPv6 is configured and enables IPv4/IPv6 forwarding + bridge netfilter sysctls for IPv6/dual clusters.
    • Brackets IPv6 listen addresses when generating --publish flags (e.g. [::1]::8443).
  • Generalises ServiceClusterIP and DNSIP so they work for both IPv4 and IPv6 service CIDRs by incrementing the base IP generically instead of assuming IPv4.

For --ip-family=ipv4 with no IPv6 flags, behaviour stays the same as today.

Fixes: #8535
Refer to this for testing steps: #22063 (comment)
Tested and verified on:

PS C:\Users\kartikjoshi> wsl --version
WSL version: 2.6.2.0
Kernel version: 6.6.87.2-1
WSLg version: 1.0.71
MSRDC version: 1.2.6353
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.26100.1-240331-1435.ge-release
Windows version: 10.0.26200.7093

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: kartikjoshi21
Once this PR has been reviewed and has the lgtm label, please assign comradeprogrammer for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Dec 8, 2025
@k8s-ci-robot
Copy link
Contributor

Hi @kartikjoshi21. Thanks for your PR.

I'm waiting for a github.com member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Dec 8, 2025
@kartikjoshi21
Copy link
Contributor Author

kartikjoshi21 commented Dec 8, 2025

Logs:

kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ minikube delete --all --purge

./out/minikube start \
  --driver=docker \
  --cni=bridge
🔥  Deleting "minikube" in docker ...
🔥  Removing /home/kartikjoshi/.minikube/machines/minikube ...
💀  Removed all traces of the "minikube" cluster.
🔥  Successfully deleted all profiles
💀  Successfully purged minikube directory located at - [/home/kartikjoshi/.minikube]
📌  Kicbase images have not been deleted. To delete images run:
    ▪ docker rmi gcr.io/k8s-minikube/kicbase:v0.0.48 gcr.io/k8s-minikube/kicbase:v0.0.47
😄  minikube v1.37.0 on Ubuntu 24.04 (kvm/amd64)
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.48-1763789673-21948 ...
💾  Downloading Kubernetes v1.34.1 preload ...
    > preloaded-images-k8s-v18-v1...:  337.01 MiB / 337.01 MiB  100.00% 3.51 Mi
🔥  Creating docker container (CPUs=2, Memory=3072MB) ...
🐳  Preparing Kubernetes v1.34.1 on Docker 29.0.2 ...
🔗  Configuring bridge CNI (Container Networking Interface) ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ kubectl get nodes -o wide
NAME       STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION                     CONTAINER-RUNTIME
minikube   Ready    control-plane   2m37s   v1.34.1   192.168.49.2   <none>        Debian GNU/Linux 12 (bookworm)   6.6.87.2-microsoft-standard-WSL2   docker://29.0.2
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker network inspect minikube -f '{{json .IPAM.Config}}'
[{"Subnet":"192.168.49.0/24","Gateway":"192.168.49.1"}]
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker inspect minikube \
  --format '{{ .NetworkSettings.Networks.minikube.IPAddress }} {{ .NetworkSettings.Networks.minikube.GlobalIPv6Address }}'
192.168.49.2
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ minikube delete --all --purge

./out/minikube start \
  --driver=docker \
  --cni=bridge \
  --ip-family=dual \
  --service-cluster-ip-range=10.96.0.0/12 \
  --service-cluster-ip-range-v6=fd00::/108 \
  --pod-cidr=10.244.0.0/16 \
  --pod-cidr-v6=fd01::/64
🔥  Deleting "minikube" in docker ...
🔥  Removing /home/kartikjoshi/.minikube/machines/minikube ...
💀  Removed all traces of the "minikube" cluster.
🔥  Successfully deleted all profiles
💀  Successfully purged minikube directory located at - [/home/kartikjoshi/.minikube]
📌  Kicbase images have not been deleted. To delete images run:
    ▪ docker rmi gcr.io/k8s-minikube/kicbase:v0.0.48 gcr.io/k8s-minikube/kicbase:v0.0.47
😄  minikube v1.37.0 on Ubuntu 24.04 (kvm/amd64)
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
💡  If Docker daemon IPv6 is disabled, enable it in /etc/docker/daemon.json and restart:
  {"ipv6": true, "fixed-cidr-v6": "fd00:55:66::/64"}
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.48-1763789673-21948 ...
💾  Downloading Kubernetes v1.34.1 preload ...
    > preloaded-images-k8s-v18-v1...:  337.01 MiB / 337.01 MiB  100.00% 3.72 Mi
🔥  Creating docker container (CPUs=2, Memory=3072MB) ...
🐳  Preparing Kubernetes v1.34.1 on Docker 29.0.2 ...
🔗  Configuring bridge CNI (Container Networking Interface) ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker network inspect minikube -f '{{json .IPAM.Config}}'^C
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ ^C
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker network inspect minikube -f '{{json .IPAM.Config}}'
[{"Subnet":"192.168.49.0/24","Gateway":"192.168.49.1"},{"Subnet":"fd00::/64"}]
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker inspect minikube | jq '.[0].NetworkSettings.Networks.minikube | {IPv4Address,GlobalIPv6Address,IPAMConfig}'
./out/minikube ssh -- ip -6 addr show dev eth0
{
  "IPv4Address": null,
  "GlobalIPv6Address": "fd00::2",
  "IPAMConfig": {
    "IPv4Address": "192.168.49.2"
  }
}
3: eth0@if81: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default  link-netnsid 0
    inet6 fd00::2/64 scope global nodad
       valid_lft forever preferred_lft forever
    inet6 fe80::dc83:90ff:feb9:663/64 scope link
       valid_lft forever preferred_lft forever


kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ ./out/minikube start -p dual-net \
  --driver=docker \
  --cni=bridge \
  --ip-family=dual \
  --subnet-v6=fd00:1234:5678::/64
😄  [dual-net] minikube v1.37.0 on Ubuntu 24.04 (kvm/amd64)
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
💡  If Docker daemon IPv6 is disabled, enable it in /etc/docker/daemon.json and restart:
  {"ipv6": true, "fixed-cidr-v6": "fd00:55:66::/64"}
👍  Starting "dual-net" primary control-plane node in "dual-net" cluster
🚜  Pulling base image v0.0.48-1763789673-21948 ...
💾  Downloading Kubernetes v1.34.1 preload ...
    > preloaded-images-k8s-v18-v1...:  337.01 MiB / 337.01 MiB  100.00% 3.53 Mi
🔥  Creating docker container (CPUs=2, Memory=3072MB) ...
🐳  Preparing Kubernetes v1.34.1 on Docker 29.0.2 ...
🔗  Configuring bridge CNI (Container Networking Interface) ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "dual-net" cluster and "default" namespace by default
kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker network inspect dual-net | jq '.[0].IPAM.Config'
[
  {
    "Subnet": "192.168.49.0/24",
    "Gateway": "192.168.49.1"
  },
  {
    "Subnet": "fd00:1234:5678::/64"
  }
]

Expected

IPAM.Config contains two entries:

One IPv4 subnet, something like 192.168.49.0/24 with gateway 192.168.49.1.

One IPv6 subnet fd00:1234:5678::/64 with a v6 gateway.

"EnableIPv6": true is set on the network.

kartikjoshi@kartikjoshiwindows:~/minikube-ipv6-support/minikube$ docker ps --format 'table {{.Names}}\t{{.Networks}}'
docker inspect dual-net | jq '.[0].NetworkSettings.Networks["dual-net"]'
NAMES      NETWORKS
dual-net   dual-net
{
  "IPAMConfig": {
    "IPv4Address": "192.168.49.2"
  },
  "Links": null,
  "Aliases": null,
  "MacAddress": "ea:28:c9:0b:19:c5",
  "DriverOpts": null,
  "GwPriority": 0,
  "NetworkID": "76ac5578c683b582b81a61695769a4f0c5913f76e895ffbe01f72765602cfbef",
  "EndpointID": "bc8c79cd8c45e38dd5528d214d3f62d0fe86d402223122dac9e91bc16bf02310",
  "Gateway": "192.168.49.1",
  "IPAddress": "192.168.49.2",
  "IPPrefixLen": 24,
  "IPv6Gateway": "fd00:1234:5678::1",
  "GlobalIPv6Address": "fd00:1234:5678::2",
  "GlobalIPv6PrefixLen": 64,
  "DNSNames": [
    "dual-net",
    "bfe0b4c2ede6"
  ]
}
Expected

Container has both IPAddress (IPv4) and GlobalIPv6Address in the fd00:1234:5678::/64 range.

minikube ip -p dual-net still returns the IPv4 address (for back-compat; dual keeps preferring v4 in GetIP()).


@minikube-bot
Copy link
Collaborator

Can one of the admins verify this patch?

@kartikjoshi21
Copy link
Contributor Author

Testing Steps :

1. IPv4-only regression
./out/minikube delete --all
docker network rm minikube || true

./out/minikube start \
  --driver=docker \
  --ip-family=ipv4 \
  --alsologtostderr -v=3

kubectl get nodes -o wide
kubectl -n kube-system get svc kube-dns -o wide

docker network inspect minikube \
  --format '{{json .IPAM.Config}}'


Expectations

minikube Docker network has only an IPv4 subnet/gateway.

Node IP is IPv4 as before.

kube-dns ClusterIP is the first IPv4 in the service CIDR.

No behaviour change vs current v1.37.0.
2. Dual-stack (no static IPv6)
./out/minikube delete --all
docker network rm minikube || true

./out/minikube start \
  --driver=docker \
  --ip-family=dual \
  --alsologtostderr -v=3

docker network inspect minikube \
  --format '{{json .IPAM.Config}}'

docker inspect minikube \
  --format '{{.NetworkSettings.Networks.minikube.IPAddress}} {{.NetworkSettings.Networks.minikube.GlobalIPv6Address}}'


Expectations

IPAM.Config for minikube shows both:

One IPv4 subnet (e.g. 192.168.49.0/24), and

One IPv6 subnet (Docker’s chosen IPv6 pool).

Node has an IPv4 address in the IPv4 pool.

Node has an auto-assigned IPv6 address in the IPv6 pool.

Cluster boots successfully.
3. Dual-stack with explicit IPv6 pool + static IPv6

Pick a /64 that does not overlap any existing Docker IPv6 pool (example CIDR):

./out/minikube delete --all
docker network rm minikube || true

./out/minikube start \
  --driver=docker \
  --ip-family=dual \
  --subnet-v6=fd12:3456:789a:1::/64 \
  --static-ipv6=fd12:3456:789a:1::100 \
  --alsologtostderr -v=3

docker inspect minikube \
  --format '{{.NetworkSettings.Networks.minikube.IPAddress}} {{.NetworkSettings.Networks.minikube.GlobalIPv6Address}}'


Expectations

docker network inspect minikube shows an IPv4 subnet and the configured IPv6 /64.

The node container has:

An IPv4 address from the IPv4 pool.

GlobalIPv6Address == fd12:3456:789a:1::100.

No “Pool overlaps with other one on this address space” error from Docker.
4. IPv6-only cluster
./out/minikube delete --all
docker network rm minikube || true

./out/minikube start \
  --driver=docker \
  --ip-family=ipv6 \
  --subnet-v6=fd12:3456:789a:2::/64 \
  --static-ipv6=fd12:3456:789a:2::100 \
  --alsologtostderr -v=3

docker network inspect minikube \
  --format '{{json .IPAM.Config}}'

docker inspect minikube \
  --format '{{.NetworkSettings.Networks.minikube.IPAddress}} {{.NetworkSettings.Networks.minikube.GlobalIPv6Address}}'


Expectations

IPAM.Config shows only an IPv6 subnet (no IPv4 subnet).

Node has no IPv4 address in minikube network (empty or zero IP).

GlobalIPv6Address == fd12:3456:789a:2::100.

API server is published on [::1] on the host, and minikube commands use the IPv6 address.
Expect cluster to not come up successfully 
5. Error case: --static-ipv6 without --subnet-v6
./out/minikube delete --all
docker network rm minikube || true

./out/minikube start \
  --driver=docker \
  --ip-family=dual \
  --static-ipv6=fd00::100 \
  --alsologtostderr -v=3


Expectations

Minikube fails fast with an invalid IPv6 configuration message explaining that --static-ipv6 requires --subnet-v6.

We do not reach the Docker “invalid pool request: Pool overlaps with other one on this address space” error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for IPv6

3 participants