Skip to content

Commit

Permalink
Merge pull request #15 from manuelbuil/dualStack-patch
Browse files Browse the repository at this point in the history
Update to v3.20.3 and add dualStack support
  • Loading branch information
manuelbuil authored Jan 13, 2022
2 parents f379794 + edc63cc commit 14f970b
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 4 deletions.
10 changes: 7 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG ARCH="amd64"
ARG TAG="v3.20.2"
ARG TAG="v3.20.3"
ARG UBI_IMAGE=registry.access.redhat.com/ubi7/ubi-minimal:latest
ARG GO_IMAGE=rancher/hardened-build-base:v1.16.10b7
ARG GO_IMAGE=rancher/hardened-build-base:v1.17.3b7
ARG CNI_IMAGE=rancher/hardened-cni-plugins:v0.9.1-build20211119

FROM ${UBI_IMAGE} as ubi
Expand All @@ -16,7 +16,8 @@ RUN set -x \
gcc \
git \
linux-headers \
make
make \
patch

### BEGIN K3S XTABLES ###
FROM builder AS k3s_xtables
Expand Down Expand Up @@ -55,6 +56,9 @@ RUN git clone --depth=1 https://github.com/projectcalico/cni-plugin.git $GOPATH/
WORKDIR $GOPATH/src/github.com/projectcalico/cni-plugin
RUN git fetch --all --tags --prune
RUN git checkout tags/${TAG} -b ${TAG}
COPY dualStack-changes.patch .
# Apply the patch only in versions v3.20 and v3.21. It is already part of v3.22
RUN if [[ "${TAG}" =~ "v3.20" || "${TAG}" =~ "v3.21" ]]; then git apply dualStack-changes.patch; fi
ENV GO_LDFLAGS="-linkmode=external -X main.VERSION=${TAG}"
RUN go-build-static.sh -gcflags=-trimpath=${GOPATH}/src -o bin/calico ./cmd/calico
RUN go-build-static.sh -gcflags=-trimpath=${GOPATH}/src -o bin/calico-ipam ./cmd/calico
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ endif

BUILD_META=-build$(shell date +%Y%m%d)
ORG ?= rancher
TAG ?= v3.20.2$(BUILD_META)
TAG ?= v3.20.3$(BUILD_META)

K3S_ROOT_VERSION ?= v0.10.1

Expand Down
219 changes: 219 additions & 0 deletions dualStack-changes.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
From a8eab5d86a7e3fe08636aba6d53f9be6d8dd4c4c Mon Sep 17 00:00:00 2001
From: manuelbuil <[email protected]>
Date: Tue, 11 Jan 2022 11:37:19 +0100
Subject: [PATCH] Dual-stack patch

Signed-off-by: manuelbuil <[email protected]>
---
internal/pkg/utils/utils.go | 57 +++++++++++++++++++++++++------------
pkg/k8s/k8s.go | 55 +++++++++++++++++++++++++++--------
2 files changed, 82 insertions(+), 30 deletions(-)

diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go
index faa8720..e87c61e 100644
--- a/internal/pkg/utils/utils.go
+++ b/internal/pkg/utils/utils.go
@@ -202,16 +202,18 @@ func DeleteIPAM(conf types.NetConf, args *skel.CmdArgs, logger *logrus.Entry) er
// We need to replace "usePodCidr" with a valid, but dummy podCidr string with "host-local" IPAM.
// host-local IPAM releases the IP by ContainerID, so podCidr isn't really used to release the IP.
// It just needs a valid CIDR, but it doesn't have to be the CIDR associated with the host.
- const dummyPodCidr = "0.0.0.0/0"
+ dummyPodCidrv4 := "0.0.0.0/0"
+ dummyPodCidrv6 := "::/0"
var stdinData map[string]interface{}
err := json.Unmarshal(args.StdinData, &stdinData)
if err != nil {
return err
}

- logger.WithField("podCidr", dummyPodCidr).Info("Using a dummy podCidr to release the IP")
- getDummyPodCIDR := func() (string, error) {
- return dummyPodCidr, nil
+ logger.WithFields(logrus.Fields{"podCidrv4": dummyPodCidrv4,
+ "podCidrv6": dummyPodCidrv6}).Info("Using dummy podCidrs to release the IPs")
+ getDummyPodCIDR := func() (string, string, error) {
+ return dummyPodCidrv4, dummyPodCidrv6, nil
}
err = ReplaceHostLocalIPAMPodCIDRs(logger, stdinData, getDummyPodCIDR)
if err != nil {
@@ -286,13 +288,13 @@ func DeleteIPAM(conf types.NetConf, args *skel.CmdArgs, logger *logrus.Entry) er
// }
// ...
// }
-func ReplaceHostLocalIPAMPodCIDRs(logger *logrus.Entry, stdinData map[string]interface{}, getPodCIDR func() (string, error)) error {
+func ReplaceHostLocalIPAMPodCIDRs(logger *logrus.Entry, stdinData map[string]interface{}, getPodCIDRs func() (string, string, error)) error {
ipamData, ok := stdinData["ipam"].(map[string]interface{})
if !ok {
return fmt.Errorf("failed to parse host-local IPAM data; was expecting a dict, not: %v", stdinData["ipam"])
}
// Older versions of host-local IPAM store a single subnet in the top-level IPAM dict.
- err := replaceHostLocalIPAMPodCIDR(logger, ipamData, getPodCIDR)
+ err := replaceHostLocalIPAMPodCIDR(logger, ipamData, getPodCIDRs)
if err != nil {
return err
}
@@ -310,7 +312,7 @@ func ReplaceHostLocalIPAMPodCIDRs(logger *logrus.Entry, stdinData map[string]int
return fmt.Errorf("failed to parse host-local IPAM range set; was expecting a list, not: %v", rs)
}
for _, r := range rs {
- err := replaceHostLocalIPAMPodCIDR(logger, r, getPodCIDR)
+ err := replaceHostLocalIPAMPodCIDR(logger, r, getPodCIDRs)
if err != nil {
return err
}
@@ -320,29 +322,47 @@ func ReplaceHostLocalIPAMPodCIDRs(logger *logrus.Entry, stdinData map[string]int
return nil
}

-func replaceHostLocalIPAMPodCIDR(logger *logrus.Entry, rawIpamData interface{}, getPodCidr func() (string, error)) error {
+func replaceHostLocalIPAMPodCIDR(logger *logrus.Entry, rawIpamData interface{}, getPodCidrs func() (string, string, error)) error {
logrus.WithField("ipamData", rawIpamData).Debug("Examining IPAM data for usePodCidr")
ipamData, ok := rawIpamData.(map[string]interface{})
if !ok {
return fmt.Errorf("failed to parse host-local IPAM data; was expecting a dict, not: %v", rawIpamData)
}
subnet, _ := ipamData["subnet"].(string)
+
if strings.EqualFold(subnet, "usePodCidr") {
- logger.Info("Calico CNI fetching podCidr from Kubernetes")
- podCidr, err := getPodCidr()
+ ipv4Cidr, _, err := getPodCidrs()
+ if err != nil {
+ logger.Errorf("Failed to getPodCidrs")
+ return err
+ }
+ if ipv4Cidr == "" {
+ return errors.New("usePodCidr found but there is no IPv4 CIDR configured")
+ }
+
+ ipamData["subnet"] = ipv4Cidr
+ subnet = ipv4Cidr
+ logger.Infof("Calico CNI passing podCidr to host-local IPAM: %s", ipv4Cidr)
+
+ // updateHostLocalIPAMDataForOS is only required for Windows and only ipv4 is supported
+ err = updateHostLocalIPAMDataForOS(subnet, ipamData)
if err != nil {
- logger.Info("Failed to getPodCidr")
return err
}
- logger.WithField("podCidr", podCidr).Info("Fetched podCidr")
- ipamData["subnet"] = podCidr
- subnet = podCidr
- logger.Infof("Calico CNI passing podCidr to host-local IPAM: %s", podCidr)
}

- err := updateHostLocalIPAMDataForOS(subnet, ipamData)
- if err != nil {
- return err
+ if strings.EqualFold(subnet, "usePodCidrIPv6") {
+ _, ipv6Cidr, err := getPodCidrs()
+ if err != nil {
+ logger.Errorf("Failed to ipv6 getPodCidrs")
+ return err
+ }
+ if ipv6Cidr == "" {
+ return errors.New("usePodCidrIPv6 found but there is no IPv6 CIDR configured")
+ }
+
+ ipamData["subnet"] = ipv6Cidr
+ logger.Infof("Calico CNI passing podCidrv6 to host-local IPAM: %s", ipv6Cidr)
}

return nil
@@ -360,6 +380,7 @@ func UpdateHostLocalIPAMDataForWindows(subnet string, ipamData map[string]interf
return err
}
//process only if we have ipv4 subnet
+ //VXLAN networks on Windows do not support dual-stack https://kubernetes.io/docs/setup/production-environment/windows/intro-windows-in-kubernetes/#ipv6-networking
if ip.To4() != nil {
//get Expected start and end range for given CIDR
expStartRange, expEndRange := getIPRanges(ip, ipnet)
diff --git a/pkg/k8s/k8s.go b/pkg/k8s/k8s.go
index ca11f90..e4170df 100644
--- a/pkg/k8s/k8s.go
+++ b/pkg/k8s/k8s.go
@@ -106,18 +106,24 @@ func CmdAddK8s(ctx context.Context, args *skel.CmdArgs, conf types.NetConf, epID
}

// Defer to ReplaceHostLocalIPAMPodCIDRs to swap the "usePodCidr" value out.
- var cachedPodCidr string
- getRealPodCIDR := func() (string, error) {
- if cachedPodCidr == "" {
+ var cachedPodCidrs []string
+ var cachedIpv4Cidr, cachedIpv6Cidr string
+ getRealPodCIDRs := func() (string, string, error) {
+ if len(cachedPodCidrs) == 0 {
var err error
- cachedPodCidr, err = getPodCidr(client, conf, epIDs.Node)
+ var emptyResult string
+ cachedPodCidrs, err = getPodCidrs(client, conf, epIDs.Node)
if err != nil {
- return "", err
+ return emptyResult, emptyResult, err
+ }
+ cachedIpv4Cidr, cachedIpv6Cidr, err = getIPsByFamily(cachedPodCidrs)
+ if err != nil {
+ return emptyResult, emptyResult, err
}
}
- return cachedPodCidr, nil
+ return cachedIpv4Cidr, cachedIpv6Cidr, nil
}
- err = utils.ReplaceHostLocalIPAMPodCIDRs(logger, stdinData, getRealPodCIDR)
+ err = utils.ReplaceHostLocalIPAMPodCIDRs(logger, stdinData, getRealPodCIDRs)
if err != nil {
return nil, err
}
@@ -892,7 +898,9 @@ func getK8sPodInfo(client *kubernetes.Clientset, podName, podNamespace string) (
return labels, pod.Annotations, ports, profiles, generateName, serviceAccount, nil
}

-func getPodCidr(client *kubernetes.Clientset, conf types.NetConf, nodename string) (string, error) {
+// getPodCidrs returns the podCidrs included in the node manifest
+func getPodCidrs(client *kubernetes.Clientset, conf types.NetConf, nodename string) ([]string, error) {
+ var emptyString []string
// Pull the node name out of the config if it's set. Defaults to nodename
if conf.Kubernetes.NodeName != "" {
nodename = conf.Kubernetes.NodeName
@@ -900,11 +908,34 @@ func getPodCidr(client *kubernetes.Clientset, conf types.NetConf, nodename strin

node, err := client.CoreV1().Nodes().Get(context.Background(), nodename, metav1.GetOptions{})
if err != nil {
- return "", err
+ return emptyString, err
+ }
+ if len(node.Spec.PodCIDRs) == 0 {
+ return emptyString, fmt.Errorf("no podCidr for node %s", nodename)
+ }
+ return node.Spec.PodCIDRs, nil
+}
+
+// getIPsByFamily returns the IPv4 and IPv6 CIDRs
+func getIPsByFamily(cidrs []string) (string, string, error) {
+ var ipv4Cidr, ipv6Cidr string
+ for _, cidr := range cidrs {
+ _, ipNet, err := cnet.ParseCIDR(cidr)
+ if err != nil {
+ return "", "", err
+ }
+ if ipNet.Version() == 4 {
+ ipv4Cidr = cidr
+ }
+
+ if ipNet.Version() == 6 {
+ ipv6Cidr = cidr
+ }
}

- if node.Spec.PodCIDR == "" {
- return "", fmt.Errorf("no podCidr for node %s", nodename)
+ if (len(cidrs) > 1) && (ipv4Cidr == "" || ipv6Cidr == "") {
+ return "", "", errors.New("ClusterCIDR contains two ranges of the same type")
}
- return node.Spec.PodCIDR, nil
+
+ return ipv4Cidr, ipv6Cidr, nil
}
--
2.26.2

0 comments on commit 14f970b

Please sign in to comment.