@@ -89,6 +89,8 @@ func (d *Driver) Create() error {
8989 OCIBinary : d .NodeConfig .OCIBinary ,
9090 APIServerPort : d .NodeConfig .APIServerPort ,
9191 GPUs : d .NodeConfig .GPUs ,
92+ IPFamily : strings .ToLower (d .NodeConfig .IPFamily ),
93+ IPv6 : d .NodeConfig .StaticIPv6 ,
9294 }
9395 if params .Memory != "0" {
9496 params .Memory += "mb"
@@ -99,40 +101,93 @@ func (d *Driver) Create() error {
99101 networkName = d .NodeConfig .ClusterName
100102 }
101103 staticIP := d .NodeConfig .StaticIP
102- if gateway , err := oci .CreateNetwork (d .OCIBinary , networkName , d .NodeConfig .Subnet , staticIP ); err != nil {
104+ // NEW: create network with IPv6/dual awareness
105+ gateway , err := oci .CreateNetworkWithIPFamily (
106+ d .OCIBinary ,
107+ networkName ,
108+ d .NodeConfig .Subnet ,
109+ d .NodeConfig .Subnetv6 , // NEW
110+ staticIP ,
111+ d .NodeConfig .StaticIPv6 , // NEW
112+ params .IPFamily , // NEW
113+ )
114+ if err != nil {
103115 msg := "Unable to create dedicated network, this might result in cluster IP change after restart: {{.error}}"
104116 args := out.V {"error" : err }
105117 if staticIP != "" {
106118 exit .Message (reason .IfDedicatedNetwork , msg , args )
107119 }
108120 out .WarningT (msg , args )
109- } else if gateway != nil && staticIP != "" {
110- params .Network = networkName
111- params .IP = staticIP
112- } else if gateway != nil {
113- params .Network = networkName
114- ip := gateway .To4 ()
115- // calculate the container IP based on guessing the machine index
116- index := driver .IndexFromMachineName (d .NodeConfig .MachineName )
117- if int (ip [3 ])+ index > 253 { // reserve last client ip address for multi-control-plane loadbalancer vip address in ha cluster
118- return fmt .Errorf ("too many machines to calculate an IP" )
121+ }
122+ // Always attach to the created user network (even if gateway is nil in IPv6-only)
123+ params .Network = networkName
124+
125+ // Now decide static IPs per family
126+ switch params .IPFamily {
127+ case "ipv6" :
128+ if d .NodeConfig .StaticIPv6 != "" {
129+ params .IPv6 = d .NodeConfig .StaticIPv6
130+ }
131+ case "dual" :
132+ // IPv4 part (only if Docker reported a v4 gateway)
133+ if g4 := gateway .To4 (); g4 != nil {
134+ if staticIP != "" {
135+ params .IP = staticIP
136+ } else {
137+ ip := make (net.IP , len (g4 ))
138+ copy (ip , g4 )
139+ index := driver .IndexFromMachineName (d .NodeConfig .MachineName )
140+ if int (ip [3 ])+ index > 253 {
141+ return fmt .Errorf ("too many machines to calculate an IPv4" )
142+ }
143+ ip [3 ] += byte (index )
144+ klog .Infof ("calculated static IPv4 %q for the %q container" , ip .String (), d .NodeConfig .MachineName )
145+ params .IP = ip .String ()
146+ }
147+ }
148+ if d .NodeConfig .StaticIPv6 != "" {
149+ params .IPv6 = d .NodeConfig .StaticIPv6
150+ }
151+ default : // ipv4
152+ if staticIP != "" {
153+ params .IP = staticIP
154+ } else if gateway != nil {
155+ if g4 := gateway .To4 (); g4 != nil {
156+ ip := make (net.IP , len (g4 ))
157+ copy (ip , g4 )
158+ index := driver .IndexFromMachineName (d .NodeConfig .MachineName )
159+ if int (ip [3 ])+ index > 253 {
160+ return fmt .Errorf ("too many machines to calculate an IP" )
161+ }
162+ ip [3 ] += byte (index )
163+ klog .Infof ("calculated static IP %q for the %q container" , ip .String (), d .NodeConfig .MachineName )
164+ params .IP = ip .String ()
165+ }
119166 }
120- ip [3 ] += byte (index )
121- klog .Infof ("calculated static IP %q for the %q container" , ip .String (), d .NodeConfig .MachineName )
122- params .IP = ip .String ()
123167 }
124168 drv := d .DriverName ()
125-
169+ // Default listen address: v4 localhost for ipv4, v6 localhost for ipv6-only
126170 listAddr := oci .DefaultBindIPV4
171+ // IPv6-only clusters must publish on IPv6 loopback so the host can reach them
172+ if params .IPFamily == "ipv6" {
173+ listAddr = "::1"
174+ }
175+
127176 if d .NodeConfig .ListenAddress != "" && d .NodeConfig .ListenAddress != listAddr {
128177 out .Step (style .Tip , "minikube is not meant for production use. You are opening non-local traffic" )
129178 out .WarningT ("Listening to {{.listenAddr}}. This is not recommended and can cause a security vulnerability. Use at your own risk" ,
130179 out.V {"listenAddr" : d .NodeConfig .ListenAddress })
131180 listAddr = d .NodeConfig .ListenAddress
132181 } else if oci .IsExternalDaemonHost (drv ) {
133- out .WarningT ("Listening to 0.0.0.0 on external docker host {{.host}}. Please be advised" ,
134- out.V {"host" : oci .DaemonHost (drv )})
135- listAddr = "0.0.0.0"
182+ if params .IPFamily == "ipv6" {
183+ out .WarningT ("Listening to :: on external docker host {{.host}}. Please be advised" ,
184+ out.V {"host" : oci .DaemonHost (drv )})
185+ listAddr = "::"
186+ } else {
187+ out .WarningT ("Listening to 0.0.0.0 on external docker host {{.host}}. Please be advised" ,
188+ out.V {"host" : oci .DaemonHost (drv )})
189+ listAddr = "0.0.0.0"
190+ }
136191 }
137192
138193 // control plane specific options
@@ -293,18 +348,38 @@ func (d *Driver) DriverName() string {
293348
294349// GetIP returns an IP or hostname that this host is available at
295350func (d * Driver ) GetIP () (string , error ) {
296- ip , _ , err := oci .ContainerIPs (d .OCIBinary , d .MachineName )
297- return ip , err
351+ ip4 , ip6 , err := oci .ContainerIPs (d .OCIBinary , d .MachineName )
352+ if err != nil {
353+ return "" , err
354+ }
355+ switch strings .ToLower (d .NodeConfig .IPFamily ) {
356+ case "ipv6" :
357+ if ip6 != "" {
358+ return ip6 , nil
359+ }
360+ }
361+ // default / dual prefers IPv4 for backward compat
362+ return ip4 , nil
298363}
299364
300365// GetExternalIP returns an IP which is accessible from outside
301366func (d * Driver ) GetExternalIP () (string , error ) {
302- return oci .DaemonHost (d .DriverName ()), nil
367+ host := oci .DaemonHost (d .DriverName ())
368+ // For local daemons and IPv6-only clusters, ports are published on ::1
369+ if strings .ToLower (d .NodeConfig .IPFamily ) == "ipv6" && ! oci .IsExternalDaemonHost (d .DriverName ()) {
370+ return "::1" , nil
371+ }
372+ return host , nil
303373}
304374
305375// GetSSHHostname returns hostname for use with ssh
306376func (d * Driver ) GetSSHHostname () (string , error ) {
307- return oci .DaemonHost (d .DriverName ()), nil
377+ host := oci .DaemonHost (d .DriverName ())
378+ // For local daemons and IPv6-only clusters, ports are published on ::1
379+ if strings .ToLower (d .NodeConfig .IPFamily ) == "ipv6" && ! oci .IsExternalDaemonHost (d .DriverName ()) {
380+ return "::1" , nil
381+ }
382+ return host , nil
308383}
309384
310385// GetSSHPort returns port for use with ssh
0 commit comments