Skip to content

Commit 06cbb87

Browse files
committed
Add support for VPC mixed mode
1. Add controller for CR Network to maintain the default Network resource in system Namespaces. 2. Add watch in Pod/Namepsace/Service/NetworkPolicy controller to requeue resources when Network type is switch to VPC. 3. Add precheck on if the default Network type is VPC or not in resource create events. 4. Add webhook in NCP owned resource creations to check if the default Network type is VPC or not in a Namespace.
1 parent d1ad217 commit 06cbb87

File tree

18 files changed

+1459
-88
lines changed

18 files changed

+1459
-88
lines changed

build/yaml/webhook/manifests.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,36 @@ webhooks:
3030
resources:
3131
- subnetsets
3232
sideEffects: None
33+
- admissionReviewVersions:
34+
- v1
35+
clientConfig:
36+
service:
37+
name: subnetset
38+
namespace: vmware-system-nsx
39+
path: /validate-vpc-enablement
40+
failurePolicy: Fail
41+
name: vpcnetwork.validating.nsx.vmware.com
42+
rules:
43+
- apiGroups:
44+
- nsx.vmware.com
45+
apiVersions:
46+
- v1alpha1
47+
operations:
48+
- CREATE
49+
resources:
50+
- networkinfos
51+
- nsxserviceaccount
52+
- securitypolicies
53+
- staticroutes
54+
- subnetports
55+
- subnets
56+
- subnetsets
57+
- apiGroups:
58+
- nsx.vmware.com
59+
apiVersions:
60+
- v1alpha2
61+
operations:
62+
- CREATE
63+
resources:
64+
- ippools
65+
sideEffects: None

cmd/main.go

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"sigs.k8s.io/controller-runtime/pkg/healthz"
1818
logf "sigs.k8s.io/controller-runtime/pkg/log"
1919
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
20+
"sigs.k8s.io/controller-runtime/pkg/webhook"
2021

2122
"github.com/vmware-tanzu/nsx-operator/pkg/apis/v1alpha1"
2223
"github.com/vmware-tanzu/nsx-operator/pkg/apis/v1alpha2"
@@ -35,6 +36,7 @@ import (
3536
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/subnet"
3637
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/subnetport"
3738
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/subnetset"
39+
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/vpcnetwork"
3840
"github.com/vmware-tanzu/nsx-operator/pkg/logger"
3941
"github.com/vmware-tanzu/nsx-operator/pkg/metrics"
4042
"github.com/vmware-tanzu/nsx-operator/pkg/nsx"
@@ -133,12 +135,13 @@ func StartNetworkInfoController(mgr ctrl.Manager, vpcService *vpc.VPCService) {
133135
}
134136
}
135137

136-
func StartNamespaceController(mgr ctrl.Manager, cf *config.NSXOperatorConfig, vpcService common.VPCServiceProvider) {
138+
func StartNamespaceController(mgr ctrl.Manager, cf *config.NSXOperatorConfig, vpcService common.VPCServiceProvider, networkProvider vpcnetwork.VPCNetworkProvider) {
137139
nsReconciler := &namespacecontroller.NamespaceReconciler{
138-
Client: mgr.GetClient(),
139-
Scheme: mgr.GetScheme(),
140-
NSXConfig: cf,
141-
VPCService: vpcService,
140+
Client: mgr.GetClient(),
141+
Scheme: mgr.GetScheme(),
142+
NSXConfig: cf,
143+
VPCService: vpcService,
144+
NetworkProvider: networkProvider,
142145
}
143146

144147
if err := nsReconciler.Start(mgr); err != nil {
@@ -149,14 +152,26 @@ func StartNamespaceController(mgr ctrl.Manager, cf *config.NSXOperatorConfig, vp
149152

150153
func main() {
151154
log.Info("starting NSX Operator")
152-
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
155+
mgrOptions := ctrl.Options{
153156
Scheme: scheme,
154157
HealthProbeBindAddress: config.ProbeAddr,
155158
Metrics: metricsserver.Options{BindAddress: config.MetricsAddr},
156159
LeaderElection: cf.HAEnabled(),
157160
LeaderElectionNamespace: nsxOperatorNamespace,
158161
LeaderElectionID: "nsx-operator",
159-
})
162+
}
163+
164+
enableWebhook := true
165+
if _, err := os.Stat(config.WebhookCertDir); errors.Is(err, os.ErrNotExist) {
166+
log.Error(err, "server cert not found, disabling webhook server", "cert", config.WebhookCertDir)
167+
enableWebhook = false
168+
} else {
169+
mgrOptions.WebhookServer = webhook.NewServer(webhook.Options{
170+
Port: config.WebhookServerPort,
171+
CertDir: config.WebhookCertDir,
172+
})
173+
}
174+
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), mgrOptions)
160175
if err != nil {
161176
log.Error(err, "failed to init manager")
162177
os.Exit(1)
@@ -181,6 +196,10 @@ func main() {
181196
var vpcService *vpc.VPCService
182197

183198
if cf.CoeConfig.EnableVPCNetwork {
199+
if !enableWebhook {
200+
log.Error(nil, "Webhook cert is not provided, can't filter out the CRs in a non-VPC namespace")
201+
os.Exit(1)
202+
}
184203
// Check NSX version for VPC networking mode
185204
if !commonService.NSXClient.NSXCheckVersion(nsx.VPC) {
186205
log.Error(nil, "VPC mode cannot be enabled if NSX version is lower than 4.1.1")
@@ -218,28 +237,24 @@ func main() {
218237
os.Exit(1)
219238
}
220239
// Start controllers which only supports VPC
240+
vpcNetworkProvider := vpcnetwork.StartNetworkController(mgr)
221241
StartNetworkInfoController(mgr, vpcService)
222-
StartNamespaceController(mgr, cf, vpcService)
242+
StartNamespaceController(mgr, cf, vpcService, vpcNetworkProvider)
223243
// Start subnet/subnetset controller.
224244
if err := subnet.StartSubnetController(mgr, subnetService, subnetPortService, vpcService); err != nil {
225245
os.Exit(1)
226246
}
227-
enableWebhook := true
228-
if _, err := os.Stat(config.WebhookCertDir); errors.Is(err, os.ErrNotExist) {
229-
log.Error(err, "server cert not found, disabling webhook server", "cert", config.WebhookCertDir)
230-
enableWebhook = false
231-
}
232247
if err := subnetset.StartSubnetSetController(mgr, subnetService, subnetPortService, vpcService, enableWebhook); err != nil {
233248
os.Exit(1)
234249
}
235250

236251
node.StartNodeController(mgr, nodeService)
237252
staticroutecontroller.StartStaticRouteController(mgr, staticRouteService)
238253
subnetport.StartSubnetPortController(mgr, subnetPortService, subnetService, vpcService)
239-
pod.StartPodController(mgr, subnetPortService, subnetService, vpcService, nodeService)
254+
pod.StartPodController(mgr, subnetPortService, subnetService, vpcService, nodeService, vpcNetworkProvider)
240255
StartIPPoolController(mgr, ipPoolService, vpcService)
241-
networkpolicycontroller.StartNetworkPolicyController(mgr, commonService, vpcService)
242-
service.StartServiceLbController(mgr, commonService)
256+
networkpolicycontroller.StartNetworkPolicyController(mgr, commonService, vpcService, vpcNetworkProvider)
257+
service.StartServiceLbController(mgr, commonService, vpcNetworkProvider)
243258
}
244259
// Start controllers which can run in non-VPC mode
245260
securitypolicycontroller.StartSecurityPolicyController(mgr, commonService, vpcService)

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ replace (
66
github.com/vmware-tanzu/nsx-operator/pkg/apis => ./pkg/apis
77
github.com/vmware-tanzu/nsx-operator/pkg/apis/v1alpha1 => ./pkg/apis/v1alpha1
88
github.com/vmware-tanzu/nsx-operator/pkg/apis/v1alpha2 => ./pkg/apis/v1alpha2
9-
github.com/vmware-tanzu/nsx-operator/pkg/client => ./pkg/client
9+
github.com/vmware-tanzu/nsx-operator/pkg/client => ./pkg/client
1010
)
1111

1212
require (
1313
github.com/agiledragon/gomonkey/v2 v2.9.0
1414
github.com/apparentlymart/go-cidr v1.1.0
1515
github.com/deckarep/golang-set v1.8.0
1616
github.com/go-logr/logr v1.3.0
17+
github.com/go-logr/zapr v1.2.4
1718
github.com/golang-jwt/jwt v3.2.2+incompatible
1819
github.com/golang/mock v1.6.0
1920
github.com/google/uuid v1.3.0
@@ -23,6 +24,7 @@ require (
2324
github.com/prometheus/client_golang v1.16.0
2425
github.com/sirupsen/logrus v1.9.0
2526
github.com/stretchr/testify v1.8.4
27+
github.com/vmware-tanzu/net-operator-api v0.0.0-20240529180459-ccac5a20bda1
2628
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20240305035435-c992c623aad3
2729
github.com/vmware-tanzu/nsx-operator/pkg/client v0.0.0-20240102061654-537b080e159f
2830
github.com/vmware-tanzu/vm-operator/api v1.8.2
@@ -53,7 +55,6 @@ require (
5355
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
5456
github.com/fsnotify/fsnotify v1.7.0 // indirect
5557
github.com/gibson042/canonicaljson-go v1.0.3 // indirect
56-
github.com/go-logr/zapr v1.2.4 // indirect
5758
github.com/go-openapi/jsonpointer v0.19.6 // indirect
5859
github.com/go-openapi/jsonreference v0.20.2 // indirect
5960
github.com/go-openapi/swag v0.22.3 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
177177
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
178178
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
179179
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
180-
github.com/vmware-tanzu/nsx-operator/pkg/client v0.0.0-20240102061654-537b080e159f h1:EV4eiUQr3QpUGfTtqdVph0+bmE+3cj0aNJpd9n2qTdo=
181-
github.com/vmware-tanzu/nsx-operator/pkg/client v0.0.0-20240102061654-537b080e159f/go.mod h1:dzob8tUzpAREQPtbbjQs4b1UyQDR37B2TiIdg8WJSRM=
180+
github.com/vmware-tanzu/net-operator-api v0.0.0-20240529180459-ccac5a20bda1 h1:r8RuSJnLEStOdGTfaZeOjH4rvRB4Gm/N1+qtU16VrI0=
181+
github.com/vmware-tanzu/net-operator-api v0.0.0-20240529180459-ccac5a20bda1/go.mod h1:w6QJGm3crIA16ZIz1FVQXD2NVeJhOgGXxW05RbVTSTo=
182182
github.com/vmware-tanzu/vm-operator/api v1.8.2 h1:7cZHVusqAmAMFWvsiU7X5xontxdjasknI/sVfe0p0Z4=
183183
github.com/vmware-tanzu/vm-operator/api v1.8.2/go.mod h1:vauVboD3sQxP+pb28TnI9wfrj+0nH2zSEc9Q7AzWJ54=
184184
github.com/vmware/govmomi v0.27.4 h1:5kY8TAkhB20lsjzrjE073eRb8+HixBI29PVMG5lxq6I=

pkg/controllers/namespace/namespace_controller.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,21 @@ import (
88
"errors"
99
"fmt"
1010

11+
netopv1alpha1 "github.com/vmware-tanzu/net-operator-api/api/v1alpha1"
1112
v1 "k8s.io/api/core/v1"
1213
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1314
apimachineryruntime "k8s.io/apimachinery/pkg/runtime"
15+
apitypes "k8s.io/apimachinery/pkg/types"
1416
"k8s.io/client-go/util/retry"
1517
ctrl "sigs.k8s.io/controller-runtime"
18+
"sigs.k8s.io/controller-runtime/pkg/builder"
1619
"sigs.k8s.io/controller-runtime/pkg/client"
1720
"sigs.k8s.io/controller-runtime/pkg/controller"
1821

1922
"github.com/vmware-tanzu/nsx-operator/pkg/apis/v1alpha1"
2023
"github.com/vmware-tanzu/nsx-operator/pkg/config"
2124
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/common"
25+
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/vpcnetwork"
2226
"github.com/vmware-tanzu/nsx-operator/pkg/logger"
2327
"github.com/vmware-tanzu/nsx-operator/pkg/metrics"
2428
_ "github.com/vmware-tanzu/nsx-operator/pkg/nsx/ratelimiter"
@@ -35,10 +39,11 @@ var (
3539
// Using vpcservice provider instead of vpc service to prevent
3640
// invoking method that should be exposed to other module.
3741
type NamespaceReconciler struct {
38-
Client client.Client
39-
Scheme *apimachineryruntime.Scheme
40-
NSXConfig *config.NSXOperatorConfig
41-
VPCService types.VPCServiceProvider
42+
Client client.Client
43+
Scheme *apimachineryruntime.Scheme
44+
NSXConfig *config.NSXOperatorConfig
45+
VPCService types.VPCServiceProvider
46+
NetworkProvider vpcnetwork.VPCNetworkProvider
4247
}
4348

4449
func (r *NamespaceReconciler) getDefaultNetworkConfigName() (string, error) {
@@ -179,6 +184,10 @@ func (r *NamespaceReconciler) insertNamespaceNetworkconfigBinding(ns string, ann
179184
return nil
180185
}
181186

187+
func (r *NamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
188+
return r.NetworkProvider.ReconcileWithVPCFilters("namespace", ctx, req, r.reconcile)
189+
}
190+
182191
/*
183192
VPC creation strategy:
184193
@@ -193,7 +202,7 @@ We suppose namespace should have following annotations:
193202
- If the ns do not have either of the annotation above, then we believe it is using default VPC, try to search
194203
default VPC in network config CR store. The default VPC network config CR's name is "default".
195204
*/
196-
func (r *NamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
205+
func (r *NamespaceReconciler) reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
197206
obj := &v1.Namespace{}
198207
log.Info("reconciling K8s namespace", "namespace", req.NamespacedName)
199208
metrics.CounterInc(r.NSXConfig, metrics.ControllerSyncTotal, common.MetricResTypeNamespace)
@@ -251,6 +260,14 @@ func (r *NamespaceReconciler) setupWithManager(mgr ctrl.Manager) error {
251260
controller.Options{
252261
MaxConcurrentReconciles: common.NumReconcile(),
253262
}).
263+
Watches(
264+
&netopv1alpha1.Network{},
265+
&vpcnetwork.EnqueueRequestForNetwork{Client: r.Client, Lister: func(namespace string) ([]apitypes.NamespacedName, error) {
266+
obj := apitypes.NamespacedName{Name: namespace, Namespace: namespace}
267+
return []apitypes.NamespacedName{obj}, nil
268+
}},
269+
builder.WithPredicates(vpcnetwork.PredicateFuncsByNetwork),
270+
).
254271
Complete(r)
255272
}
256273

pkg/controllers/namespace/namespace_controller_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"sigs.k8s.io/controller-runtime/pkg/client/fake"
1515

1616
"github.com/vmware-tanzu/nsx-operator/pkg/config"
17+
vpcnetworktesting "github.com/vmware-tanzu/nsx-operator/pkg/controllers/vpcnetwork/testing"
1718
"github.com/vmware-tanzu/nsx-operator/pkg/nsx"
1819
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
1920
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/vpc"
@@ -40,9 +41,10 @@ func createNameSpaceReconciler() *NamespaceReconciler {
4041
}
4142

4243
return &NamespaceReconciler{
43-
Client: fake.NewClientBuilder().Build(),
44-
Scheme: fake.NewClientBuilder().Build().Scheme(),
45-
VPCService: service,
44+
Client: fake.NewClientBuilder().Build(),
45+
Scheme: fake.NewClientBuilder().Build().Scheme(),
46+
VPCService: service,
47+
NetworkProvider: &vpcnetworktesting.FakeVPCNetworkProvider{},
4648
}
4749
}
4850

pkg/controllers/networkpolicy/networkpolicy_controller.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@ import (
1010
"os"
1111
"sync"
1212

13+
"github.com/vmware-tanzu/net-operator-api/api/v1alpha1"
1314
v1 "k8s.io/api/core/v1"
1415
networkingv1 "k8s.io/api/networking/v1"
1516
apimachineryruntime "k8s.io/apimachinery/pkg/runtime"
1617
"k8s.io/apimachinery/pkg/types"
1718
"k8s.io/apimachinery/pkg/util/sets"
1819
"k8s.io/client-go/tools/record"
1920
ctrl "sigs.k8s.io/controller-runtime"
21+
"sigs.k8s.io/controller-runtime/pkg/builder"
2022
"sigs.k8s.io/controller-runtime/pkg/client"
2123
"sigs.k8s.io/controller-runtime/pkg/controller"
2224
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2325

2426
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/common"
27+
"github.com/vmware-tanzu/nsx-operator/pkg/controllers/vpcnetwork"
2528
"github.com/vmware-tanzu/nsx-operator/pkg/logger"
2629
"github.com/vmware-tanzu/nsx-operator/pkg/metrics"
2730
_ "github.com/vmware-tanzu/nsx-operator/pkg/nsx/ratelimiter"
@@ -41,10 +44,11 @@ var (
4144

4245
// NetworkPolicyReconciler reconciles a NetworkPolicy object
4346
type NetworkPolicyReconciler struct {
44-
Client client.Client
45-
Scheme *apimachineryruntime.Scheme
46-
Service *securitypolicy.SecurityPolicyService
47-
Recorder record.EventRecorder
47+
Client client.Client
48+
Scheme *apimachineryruntime.Scheme
49+
Service *securitypolicy.SecurityPolicyService
50+
Recorder record.EventRecorder
51+
NetworkProvider vpcnetwork.VPCNetworkProvider
4852
}
4953

5054
func updateFail(r *NetworkPolicyReconciler, c *context.Context, o *networkingv1.NetworkPolicy, e *error) {
@@ -70,6 +74,10 @@ func deleteSuccess(r *NetworkPolicyReconciler, _ *context.Context, o *networking
7074
func (r *NetworkPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
7175
// Use once.Do to ensure gc is called only once
7276
common.GcOnce(r, &once)
77+
return r.NetworkProvider.ReconcileWithVPCFilters("networkpolicy", ctx, req, r.reconcile)
78+
}
79+
80+
func (r *NetworkPolicyReconciler) reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
7381
networkPolicy := &networkingv1.NetworkPolicy{}
7482
log.Info("reconciling networkpolicy", "networkpolicy", req.NamespacedName)
7583
metrics.CounterInc(r.Service.NSXConfig, metrics.ControllerSyncTotal, MetricResType)
@@ -134,6 +142,11 @@ func (r *NetworkPolicyReconciler) setupWithManager(mgr ctrl.Manager) error {
134142
controller.Options{
135143
MaxConcurrentReconciles: common.NumReconcile(),
136144
}).
145+
Watches(
146+
&v1alpha1.Network{},
147+
&vpcnetwork.EnqueueRequestForNetwork{Client: r.Client, Lister: r.listNetworkPolicies},
148+
builder.WithPredicates(vpcnetwork.PredicateFuncsByNetwork),
149+
).
137150
Complete(r)
138151
}
139152

@@ -180,11 +193,28 @@ func (r *NetworkPolicyReconciler) CollectGarbage(ctx context.Context) {
180193
}
181194
}
182195

183-
func StartNetworkPolicyController(mgr ctrl.Manager, commonService servicecommon.Service, vpcService servicecommon.VPCServiceProvider) {
196+
func (r *NetworkPolicyReconciler) listNetworkPolicies(ns string) ([]types.NamespacedName, error) {
197+
npList := &networkingv1.NetworkPolicyList{}
198+
err := r.Client.List(context.Background(), npList, client.InNamespace(ns))
199+
if err != nil {
200+
return nil, err
201+
}
202+
nsNames := make([]types.NamespacedName, 0)
203+
for _, np := range npList.Items {
204+
nsNames = append(nsNames, types.NamespacedName{
205+
Namespace: np.Namespace,
206+
Name: np.Name,
207+
})
208+
}
209+
return nsNames, nil
210+
}
211+
212+
func StartNetworkPolicyController(mgr ctrl.Manager, commonService servicecommon.Service, vpcService servicecommon.VPCServiceProvider, networkProvider vpcnetwork.VPCNetworkProvider) {
184213
networkPolicyReconcile := NetworkPolicyReconciler{
185-
Client: mgr.GetClient(),
186-
Scheme: mgr.GetScheme(),
187-
Recorder: mgr.GetEventRecorderFor("networkpolicy-controller"),
214+
Client: mgr.GetClient(),
215+
Scheme: mgr.GetScheme(),
216+
Recorder: mgr.GetEventRecorderFor("networkpolicy-controller"),
217+
NetworkProvider: networkProvider,
188218
}
189219
networkPolicyReconcile.Service = securitypolicy.GetSecurityService(commonService, vpcService)
190220
if err := networkPolicyReconcile.Start(mgr); err != nil {

0 commit comments

Comments
 (0)