@@ -17,10 +17,10 @@ limitations under the License.
1717package cni
1818
1919import (
20- "bytes "
20+ "encoding/json "
2121 "fmt"
2222 "os/exec"
23- "text/template "
23+ "strings "
2424
2525 "github.com/pkg/errors"
2626 "k8s.io/minikube/pkg/minikube/assets"
@@ -32,38 +32,73 @@ import (
3232// ref: https://www.cni.dev/plugins/current/meta/portmap/
3333// ref: https://www.cni.dev/plugins/current/meta/firewall/
3434
35- // note: "cannot set hairpin mode and promiscuous mode at the same time"
36- // ref: https://github.com/containernetworking/plugins/blob/7e9ada51e751740541969e1ea5a803cbf45adcf3/plugins/main/bridge/bridge.go#L424
37- var bridgeConf = template .Must (template .New ("bridge" ).Parse (`
38- {
39- "cniVersion": "0.4.0",
40- "name": "bridge",
41- "plugins": [
42- {
43- "type": "bridge",
44- "bridge": "bridge",
45- "addIf": "true",
46- "isDefaultGateway": true,
47- "forceAddress": false,
48- "ipMasq": true,
49- "hairpinMode": true,
50- "ipam": {
51- "type": "host-local",
52- "subnet": "{{.PodCIDR}}"
53- }
54- },
55- {
56- "type": "portmap",
57- "capabilities": {
58- "portMappings": true
59- }
60- },
61- {
62- "type": "firewall"
63- }
64- ]
35+ // renderBridgeConflist builds a bridge CNI config that supports IPv4-only, IPv6-only, or dual-stack.
36+ func renderBridgeConflist (k8s config.KubernetesConfig ) ([]byte , error ) {
37+ // minimal structs for JSON marshal
38+ type rng struct {
39+ Subnet string `json:"subnet"`
40+ }
41+ type ipam struct {
42+ Type string `json:"type"`
43+ Subnet string `json:"subnet,omitempty"` // single-stack (v4 or v6)
44+ Ranges [][]rng `json:"ranges,omitempty"` // dual-stack
45+ }
46+ type bridge struct {
47+ Type string `json:"type"`
48+ Bridge string `json:"bridge"`
49+ IsDefaultGateway bool `json:"isDefaultGateway"`
50+ HairpinMode bool `json:"hairpinMode"`
51+ IPMasq bool `json:"ipMasq"`
52+ IPAM ipam `json:"ipam"`
53+ }
54+ type plugin struct {
55+ Type string `json:"type"`
56+ Capabilities map [string ]bool `json:"capabilities,omitempty"`
57+ }
58+ type conflist struct {
59+ CNIVersion string `json:"cniVersion"`
60+ Name string `json:"name"`
61+ Plugins []interface {} `json:"plugins"`
62+ }
63+
64+ v4 := k8s .PodCIDR != ""
65+ v6 := k8s .PodCIDRv6 != ""
66+
67+ cfgIPAM := ipam {Type : "host-local" }
68+ switch {
69+ case v4 && v6 :
70+ cfgIPAM .Ranges = [][]rng {{{Subnet : k8s .PodCIDR }}, {{Subnet : k8s .PodCIDRv6 }}}
71+ case v6 :
72+ cfgIPAM .Subnet = k8s .PodCIDRv6
73+ default :
74+ // fall back to previous default if unset upstream
75+ cidr := k8s .PodCIDR
76+ if cidr == "" {
77+ cidr = DefaultPodCIDR
78+ }
79+ cfgIPAM .Subnet = cidr
80+ }
81+
82+ // NAT generally not desired for IPv6; keep masquerade only for v4
83+ ipMasq := v4 && ! v6
84+
85+ br := bridge {
86+ Type : "bridge" , Bridge : "cni0" ,
87+ IsDefaultGateway : true ,
88+ HairpinMode : true ,
89+ IPMasq : ipMasq ,
90+ IPAM : cfgIPAM ,
91+ }
92+ portmap := plugin {Type : "portmap" , Capabilities : map [string ]bool {"portMappings" : true }}
93+ firewall := plugin {Type : "firewall" }
94+
95+ out := conflist {
96+ CNIVersion : "1.0.0" ,
97+ Name : "k8s-pod-network" ,
98+ Plugins : []interface {}{br , portmap , firewall },
99+ }
100+ return json .MarshalIndent (out , "" , " " )
65101}
66- ` ))
67102
68103// Bridge is a simple CNI manager for single-node usage
69104type Bridge struct {
@@ -76,14 +111,11 @@ func (c Bridge) String() string {
76111}
77112
78113func (c Bridge ) netconf () (assets.CopyableFile , error ) {
79- input := & tmplInput {PodCIDR : DefaultPodCIDR }
80-
81- b := bytes.Buffer {}
82- if err := bridgeConf .Execute (& b , input ); err != nil {
114+ cfgBytes , err := renderBridgeConflist (c .cc .KubernetesConfig )
115+ if err != nil {
83116 return nil , err
84117 }
85-
86- return assets .NewMemoryAssetTarget (b .Bytes (), "/etc/cni/net.d/1-k8s.conflist" , "0644" ), nil
118+ return assets .NewMemoryAssetTarget (cfgBytes , "/etc/cni/net.d/1-k8s.conflist" , "0644" ), nil
87119}
88120
89121// Apply enables the CNI
@@ -110,5 +142,15 @@ func (c Bridge) Apply(r Runner) error {
110142
111143// CIDR returns the default CIDR used by this CNI
112144func (c Bridge ) CIDR () string {
145+
146+ // Prefer explicitly-set CIDRs from the cluster config.
147+ k := c .cc .KubernetesConfig
148+ if k .PodCIDRv6 != "" && (strings .ToLower (k .IPFamily ) == "ipv6" || k .PodCIDR == "" ) {
149+ return k .PodCIDRv6
150+ }
151+
152+ if k .PodCIDR != "" {
153+ return k .PodCIDR
154+ }
113155 return DefaultPodCIDR
114156}
0 commit comments