Skip to content

Commit fe0b6b9

Browse files
committed
feat: Implement Node Manager Controller, APIs, and update Vendor
1 parent 3c0ad5f commit fe0b6b9

File tree

1,881 files changed

+556246
-356168
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,881 files changed

+556246
-356168
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
bazel-*
22
cluster/bin
33
MERGED_LICENSES
4+
go.work
5+
go.work.sum
6+
vendor/
7+
cloud-controller-manager
8+
!cmd/cloud-controller-manager/

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ COPY cmd/ cmd/
1414
COPY pkg/ pkg/
1515
COPY providers/ providers/
1616

17-
RUN CGO_ENABLED=0 go build -o /go/bin/cloud-controller-manager ./cmd/cloud-controller-manager
17+
RUN CGO_ENABLED=0 GOFLAGS=-mod=mod go build -o /go/bin/cloud-controller-manager ./cmd/cloud-controller-manager
1818

1919
FROM registry.k8s.io/build-image/go-runner:v2.4.0-go1.24.10-bookworm.0
2020
COPY --from=builder --chown=root:root /go/bin/cloud-controller-manager /cloud-controller-manager

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Alternatively, you can run [push-images tool](https://github.com/kubernetes/clou
2626
IMAGE_REPO=us-central1-docker.pkg.dev/my-project/my-repo IMAGE_TAG=v0 ./tools/push-images
2727
```
2828

29+
IMAGE_REPO=us-central1-docker.pkg.dev/panpr-gke-dev/cloud-controller-manager IMAGE_TAG=test-p4sa ./tools/push-images
30+
31+
2932
# Cross-compiling
3033

3134
Selecting the target platform is done with the `--platforms` option with `bazel`.

cmd/cloud-controller-manager/gkenetworkparamsetcontroller.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
networkinformers "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions"
1111
cloudprovider "k8s.io/cloud-provider"
1212
gkenetworkparamsetcontroller "k8s.io/cloud-provider-gcp/pkg/controller/gkenetworkparamset"
13+
nodeipam "k8s.io/cloud-provider-gcp/pkg/controller/nodeipam"
1314
"k8s.io/cloud-provider-gcp/pkg/controller/nodeipam/ipam"
1415
"k8s.io/cloud-provider-gcp/providers/gce"
1516
"k8s.io/cloud-provider/app"
@@ -73,7 +74,7 @@ func startGkeNetworkParamsController(ccmConfig *cloudcontrollerconfig.CompletedC
7374
// with stack type and returns a list of typed cidrs and error
7475
func validClusterCIDR(clusterCIDRFromFlag string) ([]*net.IPNet, error) {
7576
// failure: bad cidrs in config
76-
clusterCIDRs, dualStack, err := processCIDRs(clusterCIDRFromFlag)
77+
clusterCIDRs, dualStack, err := nodeipam.ProcessCIDRs(clusterCIDRFromFlag)
7778
if err != nil {
7879
return nil, err
7980
}
Lines changed: 16 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2018 The Kubernetes Authors.
2+
Copyright 2019 The Kubernetes Authors.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -14,23 +14,16 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
// This file holds the code related with the sample nodeipamcontroller
18-
// which demonstrates how cloud providers add external controllers to cloud-controller-manager
19-
// This file is copied from k8s.io/kubernetes/cmd/cloud-controller-manager/nodeipamcontroller.go@v1.22
20-
2117
package main
2218

2319
import (
2420
"context"
25-
"errors"
26-
"fmt"
27-
"net"
28-
"strings"
2921
"time"
3022

3123
networkclientset "github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versioned"
3224
networkinformers "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions"
3325
nodetopologyclientset "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned"
26+
"k8s.io/apimachinery/pkg/util/wait"
3427
cloudprovider "k8s.io/cloud-provider"
3528
nodeipamcontrolleroptions "k8s.io/cloud-provider-gcp/cmd/cloud-controller-manager/options"
3629
nodeipamcontroller "k8s.io/cloud-provider-gcp/pkg/controller/nodeipam"
@@ -41,14 +34,6 @@ import (
4134
genericcontrollermanager "k8s.io/controller-manager/app"
4235
"k8s.io/controller-manager/controller"
4336
"k8s.io/klog/v2"
44-
netutils "k8s.io/utils/net"
45-
)
46-
47-
const (
48-
// defaultNodeMaskCIDRIPv4 is default mask size for IPv4 node cidr
49-
defaultNodeMaskCIDRIPv4 = 24
50-
// defaultNodeMaskCIDRIPv6 is default mask size for IPv6 node cidr
51-
defaultNodeMaskCIDRIPv6 = 64
5237
)
5338

5439
type nodeIPAMController struct {
@@ -69,68 +54,9 @@ func (nodeIpamController *nodeIPAMController) startNodeIpamControllerWrapper(ini
6954
}
7055

7156
func startNodeIpamController(ccmConfig *cloudcontrollerconfig.CompletedConfig, nodeIPAMConfig nodeipamconfig.NodeIPAMControllerConfiguration, ctx genericcontrollermanager.ControllerContext, cloud cloudprovider.Interface) (controller.Interface, bool, error) {
72-
var serviceCIDR *net.IPNet
73-
var secondaryServiceCIDR *net.IPNet
74-
var clusterCIDRs []*net.IPNet
75-
var nodeCIDRMaskSizes []int
76-
77-
// should we start nodeIPAM
78-
if !ccmConfig.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs {
79-
return nil, false, fmt.Errorf("the AllocateNodeCIDRs is not enabled")
80-
}
81-
82-
// failure: bad cidrs in config
83-
cidrs, dualStack, err := processCIDRs(ccmConfig.ComponentConfig.KubeCloudShared.ClusterCIDR)
84-
if err != nil {
85-
return nil, false, err
86-
}
87-
clusterCIDRs = cidrs
88-
89-
// failure: more than one cidr but they are not configured as dual stack
90-
if len(clusterCIDRs) > 1 && !dualStack {
91-
return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and they are not configured as dual stack (at least one from each IPFamily", len(clusterCIDRs))
92-
}
93-
94-
// failure: more than 2 cidrs is not allowed even with dual stack
95-
if len(clusterCIDRs) > 2 {
96-
return nil, false, fmt.Errorf("len of clusters cidrs is:%v > more than max allowed of 2", len(clusterCIDRs))
97-
}
98-
99-
// service cidr processing
100-
if len(strings.TrimSpace(nodeIPAMConfig.ServiceCIDR)) != 0 {
101-
_, serviceCIDR, err = net.ParseCIDR(nodeIPAMConfig.ServiceCIDR)
102-
if err != nil {
103-
klog.Warningf("Unsuccessful parsing of service CIDR %v: %v", nodeIPAMConfig.ServiceCIDR, err)
104-
}
105-
}
106-
107-
if len(strings.TrimSpace(nodeIPAMConfig.SecondaryServiceCIDR)) != 0 {
108-
_, secondaryServiceCIDR, err = net.ParseCIDR(nodeIPAMConfig.SecondaryServiceCIDR)
109-
if err != nil {
110-
klog.Warningf("Unsuccessful parsing of service CIDR %v: %v", nodeIPAMConfig.SecondaryServiceCIDR, err)
111-
}
112-
}
113-
114-
// the following checks are triggered if both serviceCIDR and secondaryServiceCIDR are provided
115-
if serviceCIDR != nil && secondaryServiceCIDR != nil {
116-
// should be dual stack (from different IPFamilies)
117-
dualstackServiceCIDR, err := netutils.IsDualStackCIDRs([]*net.IPNet{serviceCIDR, secondaryServiceCIDR})
118-
if err != nil {
119-
return nil, false, fmt.Errorf("failed to perform dualstack check on serviceCIDR and secondaryServiceCIDR error:%v", err)
120-
}
121-
if !dualstackServiceCIDR {
122-
return nil, false, fmt.Errorf("serviceCIDR and secondaryServiceCIDR are not dualstack (from different IPfamiles)")
123-
}
124-
}
125-
126-
// get list of node cidr mask sizes
127-
nodeCIDRMaskSizes, err = setNodeCIDRMaskSizes(nodeIPAMConfig, clusterCIDRs)
128-
if err != nil {
129-
return nil, false, err
130-
}
131-
13257
kubeConfig := ccmConfig.Complete().Kubeconfig
13358
kubeConfig.ContentType = "application/json" // required to serialize Networks to json
59+
13460
networkClient, err := networkclientset.NewForConfig(kubeConfig)
13561
if err != nil {
13662
return nil, false, err
@@ -139,120 +65,27 @@ func startNodeIpamController(ccmConfig *cloudcontrollerconfig.CompletedConfig, n
13965
if err != nil {
14066
return nil, false, err
14167
}
68+
14269
nwInfFactory := networkinformers.NewSharedInformerFactory(networkClient, 30*time.Second)
14370
nwInformer := nwInfFactory.Networking().V1().Networks()
14471
gnpInformer := nwInfFactory.Networking().V1().GKENetworkParamSets()
145-
nodeIpamController, err := nodeipamcontroller.NewNodeIpamController(
72+
73+
go nwInfFactory.Start(ctx.Stop)
74+
75+
return nodeipamcontroller.StartNodeIpamController(
76+
wait.ContextForChannel(ctx.Stop),
14677
ccmConfig.SharedInformers.Core().V1().Nodes(),
147-
cloud,
14878
ccmConfig.ClientBuilder.ClientOrDie("node-controller"),
79+
cloud,
80+
ccmConfig.ComponentConfig.KubeCloudShared.ClusterCIDR,
81+
ccmConfig.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs,
82+
nodeIPAMConfig.ServiceCIDR,
83+
nodeIPAMConfig.SecondaryServiceCIDR,
84+
nodeIPAMConfig,
14985
nwInformer,
15086
gnpInformer,
15187
nodeTopologyClient,
152-
nodeIPAMConfig.EnableMultiSubnetCluster,
153-
nodeIPAMConfig.EnableMultiNetworking,
154-
clusterCIDRs,
155-
serviceCIDR,
156-
secondaryServiceCIDR,
157-
nodeCIDRMaskSizes,
15888
ipam.CIDRAllocatorType(ccmConfig.ComponentConfig.KubeCloudShared.CIDRAllocatorType),
89+
ctx.ControllerManagerMetrics,
15990
)
160-
if err != nil {
161-
return nil, false, err
162-
}
163-
nwInfFactory.Start(ctx.Stop)
164-
go nodeIpamController.Run(ctx.Stop, ctx.ControllerManagerMetrics)
165-
return nil, true, nil
166-
}
167-
168-
// processCIDRs is a helper function that works on a comma separated cidrs and returns
169-
// a list of typed cidrs
170-
// a flag if cidrs represents a dual stack
171-
// error if failed to parse any of the cidrs
172-
func processCIDRs(cidrsList string) ([]*net.IPNet, bool, error) {
173-
cidrsSplit := strings.Split(strings.TrimSpace(cidrsList), ",")
174-
175-
cidrs, err := netutils.ParseCIDRs(cidrsSplit)
176-
if err != nil {
177-
return nil, false, err
178-
}
179-
180-
// if cidrs has an error then the previous call will fail
181-
// safe to ignore error checking on next call
182-
dualstack, _ := netutils.IsDualStackCIDRs(cidrs)
183-
184-
return cidrs, dualstack, nil
185-
}
186-
187-
// setNodeCIDRMaskSizes returns the IPv4 and IPv6 node cidr mask sizes to the value provided
188-
// for --node-cidr-mask-size-ipv4 and --node-cidr-mask-size-ipv6 respectively. If value not provided,
189-
// then it will return default IPv4 and IPv6 cidr mask sizes.
190-
func setNodeCIDRMaskSizes(cfg nodeipamconfig.NodeIPAMControllerConfiguration, clusterCIDRs []*net.IPNet) ([]int, error) {
191-
192-
sortedSizes := func(maskSizeIPv4, maskSizeIPv6 int) []int {
193-
nodeMaskCIDRs := make([]int, len(clusterCIDRs))
194-
195-
for idx, clusterCIDR := range clusterCIDRs {
196-
if netutils.IsIPv6CIDR(clusterCIDR) {
197-
nodeMaskCIDRs[idx] = maskSizeIPv6
198-
} else {
199-
nodeMaskCIDRs[idx] = maskSizeIPv4
200-
}
201-
}
202-
return nodeMaskCIDRs
203-
}
204-
205-
// --node-cidr-mask-size flag is incompatible with dual stack clusters.
206-
ipv4Mask, ipv6Mask := defaultNodeMaskCIDRIPv4, defaultNodeMaskCIDRIPv6
207-
isDualstack := len(clusterCIDRs) > 1
208-
209-
// case one: cluster is dualstack (i.e, more than one cidr)
210-
if isDualstack {
211-
// if --node-cidr-mask-size then fail, user must configure the correct dual-stack mask sizes (or use default)
212-
if cfg.NodeCIDRMaskSize != 0 {
213-
return nil, errors.New("usage of --node-cidr-mask-size is not allowed with dual-stack clusters")
214-
}
215-
216-
if cfg.NodeCIDRMaskSizeIPv4 != 0 {
217-
ipv4Mask = int(cfg.NodeCIDRMaskSizeIPv4)
218-
}
219-
if cfg.NodeCIDRMaskSizeIPv6 != 0 {
220-
ipv6Mask = int(cfg.NodeCIDRMaskSizeIPv6)
221-
}
222-
return sortedSizes(ipv4Mask, ipv6Mask), nil
223-
}
224-
225-
maskConfigured := cfg.NodeCIDRMaskSize != 0
226-
maskV4Configured := cfg.NodeCIDRMaskSizeIPv4 != 0
227-
maskV6Configured := cfg.NodeCIDRMaskSizeIPv6 != 0
228-
isSingleStackIPv6 := netutils.IsIPv6CIDR(clusterCIDRs[0])
229-
230-
// original flag is set
231-
if maskConfigured {
232-
// original mask flag is still the main reference.
233-
if maskV4Configured || maskV6Configured {
234-
return nil, errors.New("usage of --node-cidr-mask-size-ipv4 and --node-cidr-mask-size-ipv6 is not allowed if --node-cidr-mask-size is set. For dual-stack clusters please unset it and use IPFamily specific flags")
235-
}
236-
237-
mask := int(cfg.NodeCIDRMaskSize)
238-
return sortedSizes(mask, mask), nil
239-
}
240-
241-
if maskV4Configured {
242-
if isSingleStackIPv6 {
243-
klog.Info("--node-cidr-mask-size-ipv4 should not be used for a single-stack IPv6 cluster")
244-
}
245-
246-
ipv4Mask = int(cfg.NodeCIDRMaskSizeIPv4)
247-
}
248-
249-
// !maskV4Configured && !maskConfigured && maskV6Configured
250-
if maskV6Configured {
251-
if !isSingleStackIPv6 {
252-
klog.Info("--node-cidr-mask-size-ipv6 should not be used for a single-stack IPv4 cluster")
253-
}
254-
255-
ipv6Mask = int(cfg.NodeCIDRMaskSizeIPv6)
256-
}
257-
return sortedSizes(ipv4Mask, ipv6Mask), nil
25891
}

deploy/cloud-controller-manager.manifest

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"--also-stdout=false",
3838
"--redirect-stderr=true",
3939
"/cloud-controller-manager",
40+
"--enable-multi-project=true",
4041
{{params}}
4142
],
4243
{{container_env}}

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ require (
3333

3434
require (
3535
github.com/GoogleCloudPlatform/gke-networking-api v0.1.2-0.20240904205008-bc15495fd43f
36+
github.com/go-ini/ini v1.67.0
3637
github.com/hashicorp/go-multierror v1.1.1
3738
github.com/natefinch/atomic v1.0.1
3839
k8s.io/cloud-provider v0.34.2
@@ -145,7 +146,7 @@ require (
145146
gopkg.in/yaml.v3 v3.0.1 // indirect
146147
k8s.io/apiextensions-apiserver v0.34.2 // indirect
147148
k8s.io/kms v0.34.2 // indirect
148-
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
149+
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
149150
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
150151
sigs.k8s.io/yaml v1.6.0 // indirect
151152
)
@@ -159,6 +160,7 @@ replace (
159160
k8s.io/client-go => k8s.io/client-go v0.34.2
160161
k8s.io/cloud-provider => k8s.io/cloud-provider v0.34.2
161162

163+
k8s.io/cloud-provider-gcp => ./
162164
k8s.io/cloud-provider-gcp/providers => ./providers
163165
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.34.2
164166
k8s.io/code-generator => k8s.io/code-generator v0.34.2

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
5858
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
5959
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
6060
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
61+
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
62+
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
6163
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
6264
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
6365
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
package providerconfig
16+
17+
var (
18+
GroupName = "cloud.gke.io"
19+
)

pkg/apis/providerconfig/v1/doc.go

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

0 commit comments

Comments
 (0)