Skip to content

[feat][WIP] : copy nodeipam from upstream k8s to ccm #364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cloud/linode/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
NodeBalancerBackendIPv4Subnet string
GlobalStopChannel chan<- struct{}
EnableIPv6ForLoadBalancers bool
AllocateNodeCIDRs bool
ClusterCIDRIPv4 string
NodeCIDRMaskSizeIPv4 int
}

type linodeCloud struct {
Expand Down Expand Up @@ -187,6 +190,10 @@
serviceInformer := sharedInformer.Core().V1().Services()
nodeInformer := sharedInformer.Core().V1().Nodes()

if err := startNodeIpamController(stopCh, c, nodeInformer, kubeclient); err != nil {
klog.Fatal("starting of node ipam controller failed", err)
}

Check warning on line 195 in cloud/linode/cloud.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/cloud.go#L193-L195

Added lines #L193 - L195 were not covered by tests

if c.linodeTokenHealthChecker != nil {
go c.linodeTokenHealthChecker.Run(stopCh)
}
Expand Down
161 changes: 161 additions & 0 deletions cloud/linode/nodeipamcontroller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// This file holds the code related with the sample nodeipamcontroller
// which demonstrates how cloud providers add external controllers to cloud-controller-manager

package linode

import (
"fmt"
"net"
"strings"

"k8s.io/apimachinery/pkg/util/wait"
v1 "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
cloudprovider "k8s.io/cloud-provider"
netutils "k8s.io/utils/net"

nodeipamcontroller "github.com/linode/linode-cloud-controller-manager/cloud/nodeipam"
"github.com/linode/linode-cloud-controller-manager/cloud/nodeipam/ipam"
)

const (
// defaultNodeMaskCIDRIPv4 is default mask size for IPv4 node cidr
defaultNodeMaskCIDRIPv4 = 24
// defaultNodeMaskCIDRIPv6 is default mask size for IPv6 node cidr
defaultNodeMaskCIDRIPv6 = 64
)

func startNodeIpamController(stopCh <-chan struct{}, cloud cloudprovider.Interface, nodeInformer v1.NodeInformer, kubeclient kubernetes.Interface) error {
var serviceCIDR *net.IPNet
var secondaryServiceCIDR *net.IPNet

// should we start nodeIPAM
if !Options.AllocateNodeCIDRs {
return nil
}

Check warning on line 51 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L44-L51

Added lines #L44 - L51 were not covered by tests

// failure: bad cidrs in config
clusterCIDRs, dualStack, err := processCIDRs(Options.ClusterCIDRIPv4)
if err != nil {
return fmt.Errorf("processCIDRs failed: %v", err)
}

Check warning on line 57 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L54-L57

Added lines #L54 - L57 were not covered by tests

// failure: more than one cidr but they are not configured as dual stack
if len(clusterCIDRs) > 1 && !dualStack {
return fmt.Errorf("len of ClusterCIDRs==%v and they are not configured as dual stack (at least one from each IPFamily", len(clusterCIDRs))
}

Check warning on line 62 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L60-L62

Added lines #L60 - L62 were not covered by tests

// failure: more than cidrs is not allowed even with dual stack
if len(clusterCIDRs) > 2 {
return fmt.Errorf("len of clusters is:%v > more than max allowed of 2", len(clusterCIDRs))
}

Check warning on line 67 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L65-L67

Added lines #L65 - L67 were not covered by tests

/* TODO: uncomment and fix if we want to support service cidr overlap with nodecidr
// service cidr processing
if len(strings.TrimSpace(nodeIPAMConfig.ServiceCIDR)) != 0 {
_, serviceCIDR, err = netutils.ParseCIDRSloppy(nodeIPAMConfig.ServiceCIDR)
if err != nil {
klog.ErrorS(err, "Unsuccessful parsing of service CIDR", "CIDR", nodeIPAMConfig.ServiceCIDR)
}
}

if len(strings.TrimSpace(nodeIPAMConfig.SecondaryServiceCIDR)) != 0 {
_, secondaryServiceCIDR, err = netutils.ParseCIDRSloppy(nodeIPAMConfig.SecondaryServiceCIDR)
if err != nil {
klog.ErrorS(err, "Unsuccessful parsing of service CIDR", "CIDR", nodeIPAMConfig.SecondaryServiceCIDR)
}
}

// the following checks are triggered if both serviceCIDR and secondaryServiceCIDR are provided
if serviceCIDR != nil && secondaryServiceCIDR != nil {
// should be dual stack (from different IPFamilies)
dualstackServiceCIDR, err := netutils.IsDualStackCIDRs([]*net.IPNet{serviceCIDR, secondaryServiceCIDR})
if err != nil {
return nil, false, fmt.Errorf("failed to perform dualstack check on serviceCIDR and secondaryServiceCIDR error:%v", err)
}
if !dualstackServiceCIDR {
return nil, false, fmt.Errorf("serviceCIDR and secondaryServiceCIDR are not dualstack (from different IPfamiles)")
}
}
*/

nodeCIDRMaskSizes, err := setNodeCIDRMaskSizes(clusterCIDRs)
if err != nil {
return fmt.Errorf("setNodeCIDRMaskSizes failed: %v", err)
}

Check warning on line 101 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L98-L101

Added lines #L98 - L101 were not covered by tests

ctx := wait.ContextForChannel(stopCh)

nodeIpamController, err := nodeipamcontroller.NewNodeIpamController(
ctx,
nodeInformer,
cloud,
kubeclient,
clusterCIDRs,
serviceCIDR,
secondaryServiceCIDR,
nodeCIDRMaskSizes,
ipam.CIDRAllocatorType(ipam.RangeAllocatorType),
)
if err != nil {
return err
}

Check warning on line 118 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L103-L118

Added lines #L103 - L118 were not covered by tests

go nodeIpamController.Run(ctx)
return nil

Check warning on line 121 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L120-L121

Added lines #L120 - L121 were not covered by tests
}

// processCIDRs is a helper function that works on a comma separated cidrs and returns
// a list of typed cidrs
// a flag if cidrs represents a dual stack
// error if failed to parse any of the cidrs
func processCIDRs(cidrsList string) ([]*net.IPNet, bool, error) {
cidrsSplit := strings.Split(strings.TrimSpace(cidrsList), ",")

cidrs, err := netutils.ParseCIDRs(cidrsSplit)
if err != nil {
return nil, false, err
}

Check warning on line 134 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L128-L134

Added lines #L128 - L134 were not covered by tests

// if cidrs has an error then the previous call will fail
// safe to ignore error checking on next call
dualstack, _ := netutils.IsDualStackCIDRs(cidrs)

return cidrs, dualstack, nil

Check warning on line 140 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L138-L140

Added lines #L138 - L140 were not covered by tests
}

func setNodeCIDRMaskSizes(clusterCIDRs []*net.IPNet) ([]int, error) {
sortedSizes := func(maskSizeIPv4, maskSizeIPv6 int) []int {
nodeMaskCIDRs := make([]int, len(clusterCIDRs))

for idx, clusterCIDR := range clusterCIDRs {
if netutils.IsIPv6CIDR(clusterCIDR) {
nodeMaskCIDRs[idx] = maskSizeIPv6
} else {
nodeMaskCIDRs[idx] = maskSizeIPv4
}

Check warning on line 152 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L143-L152

Added lines #L143 - L152 were not covered by tests
}
return nodeMaskCIDRs

Check warning on line 154 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L154

Added line #L154 was not covered by tests
}

if Options.NodeCIDRMaskSizeIPv4 != 0 {
return sortedSizes(Options.NodeCIDRMaskSizeIPv4, defaultNodeMaskCIDRIPv6), nil
}
return sortedSizes(defaultNodeMaskCIDRIPv4, defaultNodeMaskCIDRIPv6), nil

Check warning on line 160 in cloud/linode/nodeipamcontroller.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/nodeipamcontroller.go#L157-L160

Added lines #L157 - L160 were not covered by tests
}
19 changes: 19 additions & 0 deletions cloud/nodeipam/config/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// +k8s:deepcopy-gen=package

package config
34 changes: 34 additions & 0 deletions cloud/nodeipam/config/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package config

// NodeIPAMControllerConfiguration contains elements describing NodeIPAMController.
type NodeIPAMControllerConfiguration struct {
// serviceCIDR is CIDR Range for Services in cluster.
ServiceCIDR string
// secondaryServiceCIDR is CIDR Range for Services in cluster. This is used in dual stack clusters. SecondaryServiceCIDR must be of different IP family than ServiceCIDR
SecondaryServiceCIDR string
// NodeCIDRMaskSize is the mask size for node cidr in single-stack cluster.
// This can be used only with single stack clusters and is incompatible with dual stack clusters.
NodeCIDRMaskSize int32
// NodeCIDRMaskSizeIPv4 is the mask size for IPv4 node cidr in dual-stack cluster.
// This can be used only with dual stack clusters and is incompatible with single stack clusters.
NodeCIDRMaskSizeIPv4 int32
// NodeCIDRMaskSizeIPv6 is the mask size for IPv6 node cidr in dual-stack cluster.
// This can be used only with dual stack clusters and is incompatible with single stack clusters.
NodeCIDRMaskSizeIPv6 int32
}
40 changes: 40 additions & 0 deletions cloud/nodeipam/config/v1alpha1/conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"github.com/linode/linode-cloud-controller-manager/cloud/nodeipam/config"

Check failure on line 20 in cloud/nodeipam/config/v1alpha1/conversion.go

View workflow job for this annotation

GitHub Actions / build-test

File is not properly formatted (gci)
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/kube-controller-manager/config/v1alpha1"
)

// Important! The public back-and-forth conversion functions for the types in this package
// with NodeIPAMControllerConfiguration types need to be manually exposed like this in order for
// other packages that reference this package to be able to call these conversion functions
// in an autogenerated manner.
// TODO: Fix the bug in conversion-gen so it automatically discovers these Convert_* functions
// in autogenerated code as well.

// Convert_v1alpha1_NodeIPAMControllerConfiguration_To_config_NodeIPAMControllerConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_NodeIPAMControllerConfiguration_To_config_NodeIPAMControllerConfiguration(in *v1alpha1.NodeIPAMControllerConfiguration, out *config.NodeIPAMControllerConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_NodeIPAMControllerConfiguration_To_config_NodeIPAMControllerConfiguration(in, out, s)
}

// Convert_config_NodeIPAMControllerConfiguration_To_v1alpha1_NodeIPAMControllerConfiguration is an autogenerated conversion function.
func Convert_config_NodeIPAMControllerConfiguration_To_v1alpha1_NodeIPAMControllerConfiguration(in *config.NodeIPAMControllerConfiguration, out *v1alpha1.NodeIPAMControllerConfiguration, s conversion.Scope) error {
return autoConvert_config_NodeIPAMControllerConfiguration_To_v1alpha1_NodeIPAMControllerConfiguration(in, out, s)
}
35 changes: 35 additions & 0 deletions cloud/nodeipam/config/v1alpha1/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
kubectrlmgrconfigv1alpha1 "k8s.io/kube-controller-manager/config/v1alpha1"
)

// RecommendedDefaultNodeIPAMControllerConfiguration defaults a pointer to a
// NodeIPAMControllerConfiguration struct. This will set the recommended default
// values, but they may be subject to change between API versions. This function
// is intentionally not registered in the scheme as a "normal" `SetDefaults_Foo`
// function to allow consumers of this type to set whatever defaults for their
// embedded configs. Forcing consumers to use these defaults would be problematic
// as defaulting in the scheme is done as part of the conversion, and there would
// be no easy way to opt-out. Instead, if you want to use this defaulting method
// run it in your wrapper struct of this type in its `SetDefaults_` method.
func RecommendedDefaultNodeIPAMControllerConfiguration(obj *kubectrlmgrconfigv1alpha1.NodeIPAMControllerConfiguration) {
// The default mask size is not set here because we need to determine the cluster cidr family before setting the
// appropriate mask size.
}
21 changes: 21 additions & 0 deletions cloud/nodeipam/config/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/controller/nodeipam/config
// +k8s:conversion-gen-external-types=k8s.io/kube-controller-manager/config/v1alpha1

package v1alpha1
31 changes: 31 additions & 0 deletions cloud/nodeipam/config/v1alpha1/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"k8s.io/apimachinery/pkg/runtime"
)

var (
// SchemeBuilder is the scheme builder with scheme init functions to run for this API package
SchemeBuilder runtime.SchemeBuilder
// localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package,
// defaulting and conversion init funcs are registered as well.
localSchemeBuilder = &SchemeBuilder
// AddToScheme is a global function that registers this API group & version to a scheme
AddToScheme = localSchemeBuilder.AddToScheme
)
Loading
Loading