Skip to content

Commit b1ded13

Browse files
author
Rahul Sharma
committed
initial implementation of ipv6 ipam
1 parent 8764780 commit b1ded13

9 files changed

Lines changed: 943 additions & 140 deletions

File tree

cloud/linode/nodeipamcontroller.go

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,21 @@ import (
2828
v1 "k8s.io/client-go/informers/core/v1"
2929
"k8s.io/client-go/kubernetes"
3030
cloudprovider "k8s.io/cloud-provider"
31-
nodeipamcontroller "k8s.io/kubernetes/pkg/controller/nodeipam"
32-
"k8s.io/kubernetes/pkg/controller/nodeipam/ipam"
3331
netutils "k8s.io/utils/net"
32+
33+
nodeipamcontroller "github.com/linode/linode-cloud-controller-manager/cloud/nodeipam"
34+
"github.com/linode/linode-cloud-controller-manager/cloud/nodeipam/ipam"
3435
)
3536

3637
const (
37-
maxAllowedNodeCIDRs = 2
38+
maxAllowedNodeCIDRsIPv4 = 1
3839
)
3940

4041
var (
4142
// defaultNodeMaskCIDRIPv4 is default mask size for IPv4 node cidr
4243
defaultNodeMaskCIDRIPv4 = 24
4344
// defaultNodeMaskCIDRIPv6 is default mask size for IPv6 node cidr
44-
defaultNodeMaskCIDRIPv6 = 64
45+
defaultNodeMaskCIDRIPv6 = 112
4546
)
4647

4748
func startNodeIpamController(stopCh <-chan struct{}, cloud cloudprovider.Interface, nodeInformer v1.NodeInformer, kubeclient kubernetes.Interface) error {
@@ -54,19 +55,13 @@ func startNodeIpamController(stopCh <-chan struct{}, cloud cloudprovider.Interfa
5455
}
5556

5657
// failure: bad cidrs in config
57-
clusterCIDRs, dualStack, err := processCIDRs(Options.ClusterCIDRIPv4)
58+
clusterCIDRs, err := processCIDRs(Options.ClusterCIDRIPv4)
5859
if err != nil {
5960
return fmt.Errorf("processCIDRs failed: %w", err)
6061
}
6162

62-
// failure: more than one cidr but they are not configured as dual stack
63-
if len(clusterCIDRs) > 1 && !dualStack {
64-
return fmt.Errorf("len of ClusterCIDRs==%v and they are not configured as dual stack (at least one from each IPFamily", len(clusterCIDRs))
65-
}
66-
67-
// failure: more than cidrs is not allowed even with dual stack
68-
if len(clusterCIDRs) > maxAllowedNodeCIDRs {
69-
return fmt.Errorf("len of clusters is:%v > more than max allowed of %d", len(clusterCIDRs), maxAllowedNodeCIDRs)
63+
if len(clusterCIDRs) > maxAllowedNodeCIDRsIPv4 {
64+
return fmt.Errorf("too many clusterCIDRs specified for ipv4, max allowed is %d", maxAllowedNodeCIDRsIPv4)
7065
}
7166

7267
/* TODO: uncomment and fix if we want to support service cidr overlap with nodecidr
@@ -98,7 +93,7 @@ func startNodeIpamController(stopCh <-chan struct{}, cloud cloudprovider.Interfa
9893
}
9994
*/
10095

101-
nodeCIDRMaskSizes := setNodeCIDRMaskSizes(clusterCIDRs)
96+
nodeCIDRMaskSizes := setNodeCIDRMaskSizes()
10297

10398
ctx := wait.ContextForChannel(stopCh)
10499

@@ -111,7 +106,7 @@ func startNodeIpamController(stopCh <-chan struct{}, cloud cloudprovider.Interfa
111106
serviceCIDR,
112107
secondaryServiceCIDR,
113108
nodeCIDRMaskSizes,
114-
ipam.RangeAllocatorType,
109+
ipam.CloudAllocatorType,
115110
)
116111
if err != nil {
117112
return err
@@ -121,47 +116,25 @@ func startNodeIpamController(stopCh <-chan struct{}, cloud cloudprovider.Interfa
121116
return nil
122117
}
123118

124-
// processCIDRs is a helper function that works on a comma separated cidrs and returns
125-
// a list of typed cidrs
126-
// a flag if cidrs represents a dual stack
127-
// error if failed to parse any of the cidrs
128-
func processCIDRs(cidrsList string) ([]*net.IPNet, bool, error) {
119+
// processCIDR is a helper function that works on cidr and returns a list of typed cidrs
120+
// error if failed to parse the cidr
121+
func processCIDRs(cidrsList string) ([]*net.IPNet, error) {
129122
cidrsSplit := strings.Split(strings.TrimSpace(cidrsList), ",")
130123

131124
cidrs, err := netutils.ParseCIDRs(cidrsSplit)
132125
if err != nil {
133-
return nil, false, err
134-
}
135-
136-
// if cidrs has an error then the previous call will fail
137-
// safe to ignore error checking on next call
138-
dualstack, err := netutils.IsDualStackCIDRs(cidrs)
139-
if err != nil {
140-
return nil, false, fmt.Errorf("failed to perform dualstack check on cidrs: %w", err)
126+
return nil, err
141127
}
142128

143-
return cidrs, dualstack, nil
129+
return cidrs, nil
144130
}
145131

146-
func setNodeCIDRMaskSizes(clusterCIDRs []*net.IPNet) []int {
147-
sortedSizes := func(maskSizeIPv4, maskSizeIPv6 int) []int {
148-
nodeMaskCIDRs := make([]int, len(clusterCIDRs))
149-
150-
for idx, clusterCIDR := range clusterCIDRs {
151-
if netutils.IsIPv6CIDR(clusterCIDR) {
152-
nodeMaskCIDRs[idx] = maskSizeIPv6
153-
} else {
154-
nodeMaskCIDRs[idx] = maskSizeIPv4
155-
}
156-
}
157-
return nodeMaskCIDRs
158-
}
159-
132+
func setNodeCIDRMaskSizes() []int {
160133
if Options.NodeCIDRMaskSizeIPv4 != 0 {
161134
defaultNodeMaskCIDRIPv4 = Options.NodeCIDRMaskSizeIPv4
162135
}
163136
if Options.NodeCIDRMaskSizeIPv6 != 0 {
164137
defaultNodeMaskCIDRIPv6 = Options.NodeCIDRMaskSizeIPv6
165138
}
166-
return sortedSizes(defaultNodeMaskCIDRIPv4, defaultNodeMaskCIDRIPv6)
139+
return []int{defaultNodeMaskCIDRIPv4, defaultNodeMaskCIDRIPv6}
167140
}

cloud/linode/nodeipamcontroller_test.go

Lines changed: 15 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -33,65 +33,22 @@ import (
3333

3434
func Test_setNodeCIDRMaskSizes(t *testing.T) {
3535
type args struct {
36-
clusterCIDRs []*net.IPNet
37-
ipv4NetMask int
38-
ipv6NetMask int
36+
ipv4NetMask int
37+
ipv6NetMask int
3938
}
40-
_, ipv4Net, _ := net.ParseCIDR("10.192.0.0/10")
41-
_, ipv6Net, _ := net.ParseCIDR("fd00::/56")
4239
tests := []struct {
4340
name string
4441
args args
4542
want []int
4643
}{
4744
{
48-
name: "empty cluster cidrs",
49-
args: args{
50-
clusterCIDRs: []*net.IPNet{},
51-
},
52-
want: []int{},
53-
},
54-
{
55-
name: "single cidr",
56-
args: args{
57-
clusterCIDRs: []*net.IPNet{
58-
{
59-
IP: ipv4Net.IP,
60-
Mask: ipv4Net.Mask,
61-
},
62-
},
63-
},
64-
want: []int{defaultNodeMaskCIDRIPv4},
65-
},
66-
{
67-
name: "two cidrs",
68-
args: args{
69-
clusterCIDRs: []*net.IPNet{
70-
{
71-
IP: ipv4Net.IP,
72-
Mask: ipv4Net.Mask,
73-
},
74-
{
75-
IP: ipv6Net.IP,
76-
Mask: ipv6Net.Mask,
77-
},
78-
},
79-
},
45+
name: "default cidr mask sizes",
46+
args: args{},
8047
want: []int{defaultNodeMaskCIDRIPv4, defaultNodeMaskCIDRIPv6},
8148
},
8249
{
8350
name: "two cidrs with custom mask sizes",
8451
args: args{
85-
clusterCIDRs: []*net.IPNet{
86-
{
87-
IP: ipv4Net.IP,
88-
Mask: ipv4Net.Mask,
89-
},
90-
{
91-
IP: ipv6Net.IP,
92-
Mask: ipv6Net.Mask,
93-
},
94-
},
9552
ipv4NetMask: 25,
9653
ipv6NetMask: 80,
9754
},
@@ -112,7 +69,7 @@ func Test_setNodeCIDRMaskSizes(t *testing.T) {
11269
if tt.args.ipv6NetMask != 0 {
11370
Options.NodeCIDRMaskSizeIPv6 = tt.args.ipv6NetMask
11471
}
115-
got := setNodeCIDRMaskSizes(tt.args.clusterCIDRs)
72+
got := setNodeCIDRMaskSizes()
11673
if !reflect.DeepEqual(got, tt.want) {
11774
t.Errorf("setNodeCIDRMaskSizes() = %v, want %v", got, tt.want)
11875
}
@@ -125,22 +82,19 @@ func Test_processCIDRs(t *testing.T) {
12582
cidrsList string
12683
}
12784
_, ipv4Net, _ := net.ParseCIDR("10.192.0.0/10")
128-
_, ipv6Net, _ := net.ParseCIDR("fd00::/56")
12985
tests := []struct {
130-
name string
131-
args args
132-
want []*net.IPNet
133-
ipv6Enabled bool
134-
wantErr bool
86+
name string
87+
args args
88+
want []*net.IPNet
89+
wantErr bool
13590
}{
13691
{
13792
name: "empty cidr list",
13893
args: args{
13994
cidrsList: "",
14095
},
141-
want: nil,
142-
ipv6Enabled: false,
143-
wantErr: true,
96+
want: nil,
97+
wantErr: true,
14498
},
14599
{
146100
name: "valid ipv4 cidr",
@@ -153,41 +107,19 @@ func Test_processCIDRs(t *testing.T) {
153107
Mask: ipv4Net.Mask,
154108
},
155109
},
156-
ipv6Enabled: false,
157-
wantErr: false,
158-
},
159-
{
160-
name: "valid ipv4 and ipv6 cidrs",
161-
args: args{
162-
cidrsList: "10.192.0.0/10,fd00::/56",
163-
},
164-
want: []*net.IPNet{
165-
{
166-
IP: ipv4Net.IP,
167-
Mask: ipv4Net.Mask,
168-
},
169-
{
170-
IP: ipv6Net.IP,
171-
Mask: ipv6Net.Mask,
172-
},
173-
},
174-
ipv6Enabled: true,
175-
wantErr: false,
110+
wantErr: false,
176111
},
177112
}
178113
for _, tt := range tests {
179114
t.Run(tt.name, func(t *testing.T) {
180-
got, got1, err := processCIDRs(tt.args.cidrsList)
115+
got, err := processCIDRs(tt.args.cidrsList)
181116
if (err != nil) != tt.wantErr {
182117
t.Errorf("processCIDRs() error = %v, wantErr %v", err, tt.wantErr)
183118
return
184119
}
185120
if !reflect.DeepEqual(got, tt.want) {
186121
t.Errorf("processCIDRs() got = %v, want %v", got, tt.want)
187122
}
188-
if got1 != tt.ipv6Enabled {
189-
t.Errorf("processCIDRs() got1 = %v, want %v", got1, tt.ipv6Enabled)
190-
}
191123
})
192124
}
193125
}
@@ -232,26 +164,14 @@ func Test_startNodeIpamController(t *testing.T) {
232164
wantErr: true,
233165
},
234166
{
235-
name: "more than one ipv4 cidrs specified",
236-
args: args{
237-
stopCh: make(<-chan struct{}),
238-
cloud: nil,
239-
nodeInformer: nil,
240-
kubeclient: nil,
241-
allocateNodeCIDRs: true,
242-
clusterCIDR: "10.192.0.0/10,192.168.0.0/16",
243-
},
244-
wantErr: true,
245-
},
246-
{
247-
name: "more than two cidrs specified",
167+
name: "more than one cidr specified",
248168
args: args{
249169
stopCh: make(<-chan struct{}),
250170
cloud: nil,
251171
nodeInformer: nil,
252172
kubeclient: nil,
253173
allocateNodeCIDRs: true,
254-
clusterCIDR: "10.192.0.0/10,fd00::/80,192.168.0.0/16",
174+
clusterCIDR: "10.192.0.0/10,fd00::/80",
255175
},
256176
wantErr: true,
257177
},

cloud/nodeipam/doc.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
Copyright 2014 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package nodeipam contains code for syncing cloud instances with
18+
// node registry
19+
package nodeipam

0 commit comments

Comments
 (0)