Skip to content

Commit 476c66d

Browse files
Add EAS api implementation
1. add a new eas service in nsx-operator 2. register eas service to k8s api server 3. start a http service on 9553 port 4. add eas service implentations for ip usages api yamls
1 parent 73f6e84 commit 476c66d

32 files changed

Lines changed: 3912 additions & 19 deletions

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ build-clean: generate fmt vet ## Build clean binary.
9797
@mkdir -p $(BINDIR)
9898
GOOS=linux go build -o $(BINDIR)/clean $(GOFLAGS) -ldflags '$(LDFLAGS)' cmd_clean/main.go
9999

100+
.PHONY: build-eas
101+
build-eas: generate fmt vet ## Build EAS (Extension API Server) binary.
102+
@mkdir -p $(BINDIR)
103+
GOOS=linux go build -o $(BINDIR)/eas $(GOFLAGS) -ldflags '$(LDFLAGS)' cmd_eas/main.go
104+
100105
.PHONY: run
101106
run: manifests generate fmt vet ## Run a controller from your host.
102107
go run ./cmd/main.go
@@ -113,6 +118,10 @@ docker-push: ## Push docker image with the manager.
113118
photon:
114119
docker build -t github.com/vmware-tanzu/nsx-operator -f build/image/photon/Dockerfile .
115120

121+
.PHONY: eas
122+
eas:
123+
docker build -t github.com/vmware-tanzu/nsx-eas -f build/image/eas/Dockerfile .
124+
116125
.PHONY: clean
117126
clean:
118127
@rm -rf $(BINDIR)

build/image/eas/Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM golang:1.25.7 as golang-build
2+
3+
WORKDIR /source
4+
5+
COPY . /source
6+
RUN CGO_ENABLED=0 go build -o eas cmd_eas/main.go
7+
8+
FROM photon
9+
10+
RUN tdnf -y install shadow && \
11+
useradd -s /bin/bash eas
12+
13+
COPY --from=golang-build /source/eas /usr/local/bin/
14+
15+
USER eas
16+
17+
ENTRYPOINT ["/usr/local/bin/eas"]

build/yaml/eas/apiservice.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ spec:
1010
service:
1111
name: nsx-eas
1212
namespace: vmware-system-nsx
13-
insecureSkipTLSVerify: true
13+
insecureSkipTLSVerify: false

build/yaml/eas/clusterrole.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ rules:
99
- ipblockusages
1010
- subnetippools
1111
- subnetdhcpserverstats
12-
verbs: ["get", "list"]
12+
verbs: ["get", "list", "update"]
13+
- apiGroups: ["apiregistration.k8s.io"]
14+
resources: ["apiservices"]
15+
verbs: ["get", "create", "update", "patch"]
1316
---
1417
apiVersion: rbac.authorization.k8s.io/v1
1518
kind: ClusterRoleBinding

build/yaml/eas/eas-service.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: nsx-eas
5+
namespace: vmware-system-nsx
6+
labels:
7+
app.kubernetes.io/name: service
8+
app.kubernetes.io/instance: eas-service
9+
app.kubernetes.io/component: eas
10+
app.kubernetes.io/created-by: nsx-operator
11+
app.kubernetes.io/part-of: nsx-operator
12+
app.kubernetes.io/managed-by: kustomize
13+
spec:
14+
ports:
15+
- port: 443
16+
targetPort: 9553
17+
protocol: TCP
18+
selector:
19+
component: nsx-ncp

build/yaml/eas/service.yaml

Lines changed: 0 additions & 12 deletions
This file was deleted.

cmd_eas/main.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* Copyright © 2026 Broadcom, Inc. All Rights Reserved.
2+
SPDX-License-Identifier: Apache-2.0 */
3+
4+
package main
5+
6+
import (
7+
"flag"
8+
"fmt"
9+
"os"
10+
11+
"k8s.io/apimachinery/pkg/runtime"
12+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
13+
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
14+
ctrl "sigs.k8s.io/controller-runtime"
15+
"sigs.k8s.io/controller-runtime/pkg/healthz"
16+
logf "sigs.k8s.io/controller-runtime/pkg/log"
17+
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
18+
19+
easv1alpha1 "github.com/vmware-tanzu/nsx-operator/pkg/apis/eas/v1alpha1"
20+
vpcv1alpha1 "github.com/vmware-tanzu/nsx-operator/pkg/apis/vpc/v1alpha1"
21+
"github.com/vmware-tanzu/nsx-operator/pkg/config"
22+
"github.com/vmware-tanzu/nsx-operator/pkg/eas"
23+
"github.com/vmware-tanzu/nsx-operator/pkg/eas/server"
24+
"github.com/vmware-tanzu/nsx-operator/pkg/logger"
25+
"github.com/vmware-tanzu/nsx-operator/pkg/nsx"
26+
pkgutil "github.com/vmware-tanzu/nsx-operator/pkg/util"
27+
)
28+
29+
var (
30+
scheme = runtime.NewScheme()
31+
configFilePath string
32+
)
33+
34+
func init() {
35+
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
36+
utilruntime.Must(easv1alpha1.AddToScheme(scheme))
37+
utilruntime.Must(vpcv1alpha1.AddToScheme(scheme))
38+
}
39+
40+
func main() {
41+
var logLevel int
42+
flag.StringVar(&configFilePath, "nsxconfig", "/etc/nsx-ujo/ncp.ini", "NSX Operator configuration file path")
43+
flag.IntVar(&logLevel, "log-level", 0, "Log verbosity level (0=info, 1=debug, 2=trace)")
44+
flag.StringVar(&config.ProbeAddr, "health-probe-bind-address", ":8384", "The address the probe endpoint binds to.")
45+
flag.Parse()
46+
47+
config.UpdateConfigFilePath(configFilePath)
48+
cf, err := config.NewNSXOperatorConfigFromFile()
49+
if err != nil {
50+
fmt.Fprintf(os.Stderr, "Failed to read config: %v\n", err)
51+
os.Exit(1)
52+
}
53+
54+
log := logger.ZapCustomLogger(cf.DefaultConfig.Debug, logLevel)
55+
logger.Log = log
56+
// Register logger with controller-runtime to suppress "log.SetLogger(...) was never called" warning.
57+
logf.SetLogger(log.Logger)
58+
59+
log.Info("Starting NSX Extension API Server")
60+
61+
// Initialize NSX client.
62+
nsxClient := nsx.GetClient(cf)
63+
if nsxClient == nil {
64+
log.Error(nil, "Failed to get NSX client")
65+
os.Exit(1)
66+
}
67+
log.Info("NSX client initialized")
68+
69+
// Get k8s config and create a manager.
70+
// EAS is read-only so all replicas serve concurrently (no leader election).
71+
cfg, err := pkgutil.GetConfig()
72+
if err != nil {
73+
log.Error(err, "Failed to get rest config for manager")
74+
os.Exit(1)
75+
}
76+
77+
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
78+
Scheme: scheme,
79+
Metrics: metricsserver.Options{BindAddress: "0"}, // disable metrics, shares container with nsx-ncp
80+
HealthProbeBindAddress: config.ProbeAddr,
81+
})
82+
if err != nil {
83+
log.Error(err, "Failed to create manager")
84+
os.Exit(1)
85+
}
86+
87+
vpcProvider := eas.NewK8sVPCInfoProvider(mgr.GetClient())
88+
srv := server.NewEASServer(nsxClient, vpcProvider, mgr.GetClient(), cfg)
89+
if err := mgr.Add(srv); err != nil {
90+
log.Error(err, "Failed to add EAS server to manager")
91+
os.Exit(1)
92+
}
93+
94+
if err := mgr.AddHealthzCheck("healthz", nsxClient.NSXChecker.CheckNSXHealth); err != nil {
95+
log.Error(err, "Failed to set up health check")
96+
os.Exit(1)
97+
}
98+
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
99+
log.Error(err, "Failed to set up ready check")
100+
os.Exit(1)
101+
}
102+
103+
log.Info("Starting manager")
104+
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
105+
log.Error(err, "Failed to start manager")
106+
os.Exit(1)
107+
}
108+
}

0 commit comments

Comments
 (0)