Skip to content

Commit

Permalink
Merge pull request #512 from axel7born/dualstack-wip
Browse files Browse the repository at this point in the history
Generate dual-stack configuration.
  • Loading branch information
axel7born authored Nov 5, 2024
2 parents 4f0fad6 + 695d176 commit b1f9801
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ data:
"mtu": __CNI_MTU__,
"ipam": {
"type": "{{ .Values.config.ipam.type }}",
{{- with .Values.config.ipam.subnet }}
"subnet": "{{ . }}",
{{- end }}
{{- with .Values.config.ipam.ranges }}
"ranges": {{ . | toJson }},
{{- end }}
"assign_ipv4": "{{ .Values.config.ipam.assign_ipv4 }}",
"assign_ipv6": "{{ .Values.config.ipam.assign_ipv6 }}"
{{- if .Values.config.ipam.subnet }},
"subnet": "{{ .Values.config.ipam.subnet }}"
{{- end }}
},
"policy": {
"type": "k8s"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ spec:
# chosen from this range. Changing this value after installation will have
# no effect. This should fall within `--cluster-cidr`.
- name: CALICO_IPV6POOL_CIDR
value: "{{ .Values.global.podCIDR }}"
value: "{{ .Values.global.podCIDRv6 }}"
# Auto-detect the BGP IP address.
{{- if .Values.config.ipv6.autoDetectionMethod }}
# On metal the ip is bound to the lo interface (routing to the host).
Expand Down
74 changes: 62 additions & 12 deletions pkg/charts/charts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ var _ = Describe("Chart package test", func() {
func(config func() *calicov1alpha1.NetworkConfig, configResult func() *calicov1alpha1.NetworkConfig, wantsVPA bool,
kubeProxyEnabled bool, mtu string, ipinip bool, bpf bool, pool string,
modeFunc func() string, detectionMethodFunc func() *string, nodesFunc func() *string, additionalGlobalOptions map[string]string) {
values, err := chartspkg.ComputeCalicoChartValues(network, config(), kubernetesVersion, wantsVPA, kubeProxyEnabled, false, nodesFunc())
values, err := chartspkg.ComputeCalicoChartValues(network, config(), kubernetesVersion, wantsVPA, kubeProxyEnabled, false, nodesFunc(), []string{network.Spec.PodCIDR})
Expect(err).To(BeNil())
expected := map[string]interface{}{
"images": map[string]interface{}{
Expand All @@ -211,6 +211,7 @@ var _ = Describe("Chart package test", func() {
"assign_ipv6": false,
"type": configResult().IPAM.Type,
"subnet": string(*configResult().IPAM.CIDR),
"ranges": nil,
},
"typha": map[string]interface{}{
"enabled": trueVar,
Expand Down Expand Up @@ -318,7 +319,7 @@ var _ = Describe("Chart package test", func() {
var podCIDR = "12.0.0.0/8"
DescribeTable("should correctly compute calico chart values with non-privileged mode enabled",
func(config func() *calicov1alpha1.NetworkConfig, expectedResult bool) {
values, err := chartspkg.ComputeCalicoChartValues(network, config(), kubernetesVersion, true, true, true, &nodeCIDR)
values, err := chartspkg.ComputeCalicoChartValues(network, config(), kubernetesVersion, true, true, true, &nodeCIDR, nil)
Expect(err).To(BeNil())

actual, err := utils.GetFromValuesMap(values, "config", "nonPrivileged")
Expand All @@ -331,7 +332,7 @@ var _ = Describe("Chart package test", func() {
)

It("should error on invalid config value", func() {
_, err := chartspkg.ComputeCalicoChartValues(network, networkConfigInvalid, kubernetesVersion, true, true, false, &nodeCIDR)
_, err := chartspkg.ComputeCalicoChartValues(network, networkConfigInvalid, kubernetesVersion, true, true, false, &nodeCIDR, nil)
Expect(err).To(Equal(fmt.Errorf("error when generating calico config: unsupported value for backend: invalid")))
})

Expand All @@ -349,7 +350,7 @@ var _ = Describe("Chart package test", func() {
It("should correctly configure for IPv4 networks", func() {
values, err := chartspkg.ComputeCalicoChartValues(
network,
nil, "", false, false, false, nil,
nil, "", false, false, false, nil, nil,
)
Expect(err).NotTo(HaveOccurred())

Expand All @@ -359,6 +360,7 @@ var _ = Describe("Chart package test", func() {
"subnet": "usePodCidr",
"assign_ipv4": true,
"assign_ipv6": false,
"ranges": nil,
})),
HaveKeyWithValue("ipv4", Equal(map[string]interface{}{
"enabled": true,
Expand All @@ -385,7 +387,7 @@ var _ = Describe("Chart package test", func() {
}
values, err := chartspkg.ComputeCalicoChartValues(
network, config,
"", false, false, false, nil,
"", false, false, false, nil, nil,
)
Expect(err).NotTo(HaveOccurred())

Expand All @@ -395,6 +397,7 @@ var _ = Describe("Chart package test", func() {
"subnet": "usePodCidr",
"assign_ipv4": true,
"assign_ipv6": false,
"ranges": nil,
})),
HaveKeyWithValue("ipv4", Equal(map[string]interface{}{
"enabled": true,
Expand All @@ -417,7 +420,7 @@ var _ = Describe("Chart package test", func() {
}
values, err := chartspkg.ComputeCalicoChartValues(
network, config,
"", false, false, false, nil,
"", false, false, false, nil, nil,
)
Expect(err).NotTo(HaveOccurred())

Expand All @@ -427,6 +430,7 @@ var _ = Describe("Chart package test", func() {
"subnet": "usePodCidr",
"assign_ipv4": true,
"assign_ipv6": false,
"ranges": nil,
})),
HaveKeyWithValue("ipv4", Equal(map[string]interface{}{
"enabled": true,
Expand All @@ -451,14 +455,13 @@ var _ = Describe("Chart package test", func() {
IPFamilies: []extensionsv1alpha1.IPFamily{
extensionsv1alpha1.IPFamilyIPv6,
},
PodCIDR: podCIDR,
},
}
})
It("should correctly configure for IPv6 networks", func() {
values, err := chartspkg.ComputeCalicoChartValues(
network,
nil, "", false, false, false, nil,
nil, "", false, false, false, nil, []string{"2001:0db8:85a3:0000::/56"},
)
Expect(err).NotTo(HaveOccurred())

Expand All @@ -468,6 +471,7 @@ var _ = Describe("Chart package test", func() {
"subnet": "usePodCidrIPv6",
"assign_ipv4": false,
"assign_ipv6": true,
"ranges": nil,
})),
HaveKeyWithValue("ipv4",
HaveKeyWithValue("enabled", false),
Expand All @@ -482,7 +486,7 @@ var _ = Describe("Chart package test", func() {
})),
))
Expect(values["global"]).To(
HaveKeyWithValue("podCIDR", "12.0.0.0/8"),
HaveKeyWithValue("podCIDRv6", "2001:0db8:85a3:0000::/56"),
)
})
It("should use overrides from the config", func() {
Expand All @@ -495,7 +499,7 @@ var _ = Describe("Chart package test", func() {
}
values, err := chartspkg.ComputeCalicoChartValues(
network, config,
"", false, false, false, nil,
"", false, false, false, nil, []string{"2001:0db8:85a3:0000::/56"},
)
Expect(err).NotTo(HaveOccurred())

Expand All @@ -505,6 +509,7 @@ var _ = Describe("Chart package test", func() {
"subnet": "usePodCidrIPv6",
"assign_ipv4": false,
"assign_ipv6": true,
"ranges": nil,
})),
HaveKeyWithValue("ipv4",
HaveKeyWithValue("enabled", false),
Expand All @@ -519,10 +524,55 @@ var _ = Describe("Chart package test", func() {
})),
))
Expect(values["global"]).To(
HaveKeyWithValue("podCIDR", "12.0.0.0/8"),
HaveKeyWithValue("podCIDRv6", "2001:0db8:85a3:0000::/56"),
)
})
})
Context("Dual-stack", func() {
BeforeEach(func() {
network = &extensionsv1alpha1.Network{
Spec: extensionsv1alpha1.NetworkSpec{
IPFamilies: []extensionsv1alpha1.IPFamily{
extensionsv1alpha1.IPFamilyIPv6,
extensionsv1alpha1.IPFamilyIPv4,
},
PodCIDR: podCIDR,
},
}
})
It("should correctly configure for Dual-stack networks", func() {
values, err := chartspkg.ComputeCalicoChartValues(
network,
nil, "", false, false, false, nil, []string{"2001:0db8:85a3:0000::/56", podCIDR},
)
Expect(err).NotTo(HaveOccurred())

Expect(values["config"]).To(And(
HaveKeyWithValue("ipam", Equal(map[string]interface{}{
"type": "host-local",
"subnet": "",
"assign_ipv4": true,
"assign_ipv6": true,
"ranges": []interface{}{[]interface{}{map[string]interface{}{"subnet": "usePodCidrIPv6"}}, []interface{}{map[string]interface{}{"subnet": "usePodCidr"}}},
})),
HaveKeyWithValue("ipv4",
HaveKeyWithValue("enabled", true),
),
HaveKeyWithValue("ipv6", Equal(map[string]interface{}{
"enabled": true,
"pool": "vxlan",
"mode": "Never",
"autoDetectionMethod": nil,
"natOutgoing": true,
"wireguard": false,
})),
))
Expect(values["global"]).To(And(
HaveKeyWithValue("podCIDR", podCIDR),
HaveKeyWithValue("podCIDRv6", "2001:0db8:85a3:0000::/56"),
))
})
})
})

Describe("#RenderCalicoChart", func() {
Expand All @@ -549,7 +599,7 @@ var _ = Describe("Chart package test", func() {
},
}, nil)

_, err := chartspkg.RenderCalicoChart(mockChartRenderer, network, networkConfigNil, kubernetesVersion, false, true, false, nodes)
_, err := chartspkg.RenderCalicoChart(mockChartRenderer, network, networkConfigNil, kubernetesVersion, false, true, false, nodes, nil)
Expect(err).NotTo(HaveOccurred())

},
Expand Down
43 changes: 32 additions & 11 deletions pkg/charts/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package charts
import (
"encoding/json"
"fmt"
"net"
"strconv"

extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
Expand Down Expand Up @@ -75,10 +76,15 @@ type ipv6 struct {
}

type ipam struct {
IPAMType string `json:"type"`
Subnet string `json:"subnet"`
AssignIPv4 bool `json:"assign_ipv4"`
AssignIPv6 bool `json:"assign_ipv6"`
IPAMType string `json:"type"`
Subnet string `json:"subnet"`
Ranges [][]ipamRange `json:"ranges"`
AssignIPv4 bool `json:"assign_ipv4"`
AssignIPv6 bool `json:"assign_ipv6"`
}

type ipamRange struct {
Subnet string `json:"subnet"`
}

type kubeControllers struct {
Expand Down Expand Up @@ -155,6 +161,7 @@ func ComputeCalicoChartValues(
kubeProxyEnabled bool,
nonPrivileged bool,
nodeCIDR *string,
podCIDRs []string,
) (map[string]interface{}, error) {
typedConfig, err := generateChartValues(network, config, kubeProxyEnabled, nonPrivileged)
if err != nil {
Expand Down Expand Up @@ -182,6 +189,16 @@ func ComputeCalicoChartValues(
"config": calicoConfig,
}

for _, podCIDR := range podCIDRs {
_, cidr, err := net.ParseCIDR(podCIDR)
if err != nil {
return nil, err
}
if cidr.IP.To4() == nil {
calicoChartValues["global"].(map[string]string)["podCIDRv6"] = podCIDR
}
}

if nodeCIDR != nil {
calicoChartValues["global"].(map[string]string)["nodeCIDR"] = *nodeCIDR
}
Expand Down Expand Up @@ -210,14 +227,9 @@ func ComputeCalicoChartValues(
}

func generateChartValues(network *extensionsv1alpha1.Network, config *calicov1alpha1.NetworkConfig, kubeProxyEnabled bool, nonPrivileged bool) (*calicoConfig, error) {
// by default assume IPv4 (dual-stack is not supported, yet)
ipFamilies := sets.New[extensionsv1alpha1.IPFamily](network.Spec.IPFamilies...)
isIPv4 := true
isIPv6 := false
if ipFamilies.Has(extensionsv1alpha1.IPFamilyIPv6) {
isIPv4 = false
isIPv6 = true
}
isIPv4 := ipFamilies.Has(extensionsv1alpha1.IPFamilyIPv4)
isIPv6 := ipFamilies.Has(extensionsv1alpha1.IPFamilyIPv6)

c := newCalicoConfig()
if isIPv4 {
Expand Down Expand Up @@ -245,6 +257,15 @@ func generateChartValues(network *extensionsv1alpha1.Network, config *calicov1al
c.Felix.IPInIP.Enabled = false
}

if isIPv4 && isIPv6 {
c.IPAM.Subnet = "" // drop it for dualstack

c.IPAM.Ranges = append(c.IPAM.Ranges,
[]ipamRange{{Subnet: usePodCIDRv6}},
[]ipamRange{{Subnet: usePodCIDR}},
)
}

if !kubeProxyEnabled {
c.Felix.BPFKubeProxyIptablesCleanup.Enabled = true
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/charts/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ func RenderCalicoChart(
kubeProxyEnabled bool,
nonPrivileged bool,
nodeCIDR *string,
podCidrs []string,
) ([]byte, error) {
values, err := ComputeCalicoChartValues(network, config, kubernetesVersion, wantsVPA, kubeProxyEnabled, nonPrivileged, nodeCIDR)
values, err := ComputeCalicoChartValues(network, config, kubernetesVersion, wantsVPA, kubeProxyEnabled, nonPrivileged, nodeCIDR, podCidrs)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit b1f9801

Please sign in to comment.