Skip to content

Commit 802087c

Browse files
authored
Merge branch 'master' into statelessCNI-ACI
2 parents 1ee2e15 + b5a7f14 commit 802087c

File tree

18 files changed

+455
-88
lines changed

18 files changed

+455
-88
lines changed

.pipelines/pipeline.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,17 @@ stages:
261261
k8sVersion: ""
262262
dependsOn: "containerize"
263263

264+
# Cilium Nodesubnet E2E tests
265+
- template: singletenancy/cilium-nodesubnet/cilium-nodesubnet-e2e-job-template.yaml
266+
parameters:
267+
name: "cilium_nodesubnet_e2e"
268+
displayName: Cilium NodeSubnet
269+
clusterType: nodesubnet-byocni-nokubeproxy-up
270+
clusterName: "cilndsubnete2e"
271+
vmSize: Standard_B2s
272+
k8sVersion: ""
273+
dependsOn: "containerize"
274+
264275
# Cilium Overlay E2E tests
265276
- template: singletenancy/cilium-overlay/cilium-overlay-e2e-job-template.yaml
266277
parameters:
@@ -405,6 +416,7 @@ stages:
405416
- azure_overlay_stateless_e2e
406417
- aks_swift_e2e
407418
- cilium_e2e
419+
- cilium_nodesubnet_e2e
408420
- cilium_overlay_e2e
409421
- cilium_h_overlay_e2e
410422
- aks_ubuntu_22_linux_e2e
@@ -425,6 +437,10 @@ stages:
425437
cilium_e2e:
426438
name: cilium_e2e
427439
clusterName: "ciliume2e"
440+
region: $(REGION_AKS_CLUSTER_TEST)
441+
cilium_nodesubnet_e2e:
442+
name: cilium_nodesubnet_e2e
443+
clusterName: "cilndsubnete2e"
428444
region: $(REGION_AKS_CLUSTER_TEST)
429445
cilium_overlay_e2e:
430446
name: cilium_overlay_e2e

.pipelines/singletenancy/cilium-nodesubnet/cilium-nodesubnet-e2e-job-template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ stages:
7171
os: ${{ parameters.os }}
7272
datapath: true
7373
dns: true
74+
cni: cilium
7475
portforward: true
7576
service: true
76-
hostport: true
7777
dependsOn: ${{ parameters.name }}
7878

7979
- job: failedE2ELogs

.pipelines/singletenancy/cilium-nodesubnet/cilium-nodesubnet-e2e-step-template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ steps:
5858
kubectl cluster-info
5959
kubectl get po -owide -A
6060
echo "install Cilium ${CILIUM_VERSION_TAG}"
61-
export DIR=${CILIUM_VERSION_TAG%.*}
61+
export DIR=$(echo ${CILIUM_VERSION_TAG#v} | cut -d. -f1,2)
6262
echo "installing files from ${DIR}"
6363
echo "deploy Cilium ConfigMap"
6464
kubectl apply -f test/integration/manifests/cilium/v${DIR}/cilium-config/cilium-config.yaml

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,8 @@ cni-image: ## build cni container image.
436436
TARGET=$(OS) \
437437
OS=$(OS) \
438438
ARCH=$(ARCH) \
439-
OS_VERSION=$(OS_VERSION)
439+
OS_VERSION=$(OS_VERSION) \
440+
EXTRA_BUILD_ARGS='--build-arg CNI_AI_PATH=$(CNI_AI_PATH) --build-arg CNI_AI_ID=$(CNI_AI_ID)'
440441

441442
cni-image-push: ## push cni container image.
442443
$(MAKE) container-push \

cni/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ FROM --platform=linux/${ARCH} mcr.microsoft.com/cbl-mariner/base/core@sha256:a49
1212
FROM go AS azure-vnet
1313
ARG OS
1414
ARG VERSION
15+
ARG CNI_AI_PATH
16+
ARG CNI_AI_ID
1517
WORKDIR /azure-container-networking
1618
COPY . .
1719
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/network/plugin/main.go
18-
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-telemetry -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/telemetry/service/telemetrymain.go
20+
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-telemetry -trimpath -ldflags "-X main.version="$VERSION" -X "$CNI_AI_PATH"="$CNI_AI_ID"" -gcflags="-dwarflocationlists=true" cni/telemetry/service/telemetrymain.go
1921
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-ipam -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/ipam/plugin/main.go
2022
RUN GOOS=$OS CGO_ENABLED=0 go build -a -o /go/bin/azure-vnet-stateless -trimpath -ldflags "-X main.version="$VERSION"" -gcflags="-dwarflocationlists=true" cni/network/stateless/main.go
2123

cni/telemetry/service/telemetrymain.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ func main() {
167167
GetEnvRetryWaitTimeInSecs: config.GetEnvRetryWaitTimeInSecs,
168168
}
169169

170-
if tb.CreateAITelemetryHandle(aiConfig, config.DisableAll, config.DisableTrace, config.DisableMetric) != nil {
171-
logger.Error("AI Handle creation error", zap.Error(err))
170+
if err := tb.CreateAITelemetryHandle(aiConfig, config.DisableAll, config.DisableTrace, config.DisableMetric); err != nil { // nolint
171+
logger.Error("AI Handle creation error:", zap.Error(err))
172172
}
173173
logger.Info("Report to host interval", zap.Duration("seconds", config.ReportToHostIntervalInSeconds))
174174
tb.PushData(context.Background())

cns/fakes/nmagentclientfake.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ import (
1414

1515
// NMAgentClientFake can be used to query to VM Host info.
1616
type NMAgentClientFake struct {
17-
SupportedAPIsF func(context.Context) ([]string, error)
18-
GetNCVersionListF func(context.Context) (nmagent.NCVersionList, error)
19-
GetHomeAzF func(context.Context) (nmagent.AzResponse, error)
17+
SupportedAPIsF func(context.Context) ([]string, error)
18+
GetNCVersionListF func(context.Context) (nmagent.NCVersionList, error)
19+
GetHomeAzF func(context.Context) (nmagent.AzResponse, error)
20+
GetInterfaceIPInfoF func(ctx context.Context) (nmagent.Interfaces, error)
2021
}
2122

2223
func (n *NMAgentClientFake) SupportedAPIs(ctx context.Context) ([]string, error) {
@@ -30,3 +31,7 @@ func (n *NMAgentClientFake) GetNCVersionList(ctx context.Context) (nmagent.NCVer
3031
func (n *NMAgentClientFake) GetHomeAz(ctx context.Context) (nmagent.AzResponse, error) {
3132
return n.GetHomeAzF(ctx)
3233
}
34+
35+
func (n *NMAgentClientFake) GetInterfaceIPInfo(ctx context.Context) (nmagent.Interfaces, error) {
36+
return n.GetInterfaceIPInfoF(ctx)
37+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package restserver
2+
3+
import (
4+
"context"
5+
"net/netip"
6+
"testing"
7+
8+
"github.com/Azure/azure-container-networking/cns"
9+
"github.com/Azure/azure-container-networking/cns/common"
10+
"github.com/Azure/azure-container-networking/cns/fakes"
11+
"github.com/Azure/azure-container-networking/cns/nodesubnet"
12+
acn "github.com/Azure/azure-container-networking/common"
13+
"github.com/Azure/azure-container-networking/nmagent"
14+
"github.com/Azure/azure-container-networking/store"
15+
)
16+
17+
// GetRestServiceObjectForNodeSubnetTest creates a new HTTPRestService object for use in nodesubnet unit tests.
18+
func GetRestServiceObjectForNodeSubnetTest(t *testing.T, generator CNIConflistGenerator) *HTTPRestService {
19+
config := &common.ServiceConfig{
20+
Name: "test",
21+
Version: "1.0",
22+
ChannelMode: "AzureHost",
23+
Store: store.NewMockStore("test"),
24+
}
25+
interfaces := nmagent.Interfaces{
26+
Entries: []nmagent.Interface{
27+
{
28+
MacAddress: nmagent.MACAddress{0x00, 0x0D, 0x3A, 0xF9, 0xDC, 0xA6},
29+
IsPrimary: true,
30+
InterfaceSubnets: []nmagent.InterfaceSubnet{
31+
{
32+
Prefix: "10.0.0.0/24",
33+
IPAddress: []nmagent.NodeIP{
34+
{
35+
Address: nmagent.IPAddress(netip.AddrFrom4([4]byte{10, 0, 0, 4})),
36+
IsPrimary: true,
37+
},
38+
{
39+
Address: nmagent.IPAddress(netip.AddrFrom4([4]byte{10, 0, 0, 52})),
40+
IsPrimary: false,
41+
},
42+
{
43+
Address: nmagent.IPAddress(netip.AddrFrom4([4]byte{10, 0, 0, 63})),
44+
IsPrimary: false,
45+
},
46+
{
47+
Address: nmagent.IPAddress(netip.AddrFrom4([4]byte{10, 0, 0, 45})),
48+
IsPrimary: false,
49+
},
50+
},
51+
},
52+
},
53+
},
54+
},
55+
}
56+
57+
svc, err := cns.NewService(config.Name, config.Version, config.ChannelMode, config.Store)
58+
if err != nil {
59+
return nil
60+
}
61+
62+
svc.SetOption(acn.OptCnsURL, "")
63+
svc.SetOption(acn.OptCnsPort, "")
64+
err = svc.Initialize(config)
65+
if err != nil {
66+
return nil
67+
}
68+
69+
t.Cleanup(func() { svc.Uninitialize() })
70+
71+
return &HTTPRestService{
72+
Service: svc,
73+
cniConflistGenerator: generator,
74+
state: &httpRestServiceState{},
75+
PodIPConfigState: make(map[string]cns.IPConfigurationStatus),
76+
PodIPIDByPodInterfaceKey: make(map[string][]string),
77+
nma: &fakes.NMAgentClientFake{
78+
GetInterfaceIPInfoF: func(_ context.Context) (nmagent.Interfaces, error) {
79+
return interfaces, nil
80+
},
81+
},
82+
wscli: &fakes.WireserverClientFake{},
83+
}
84+
}
85+
86+
// GetNodesubnetIPFetcher gets the nodesubnetIPFetcher from the HTTPRestService.
87+
func (service *HTTPRestService) GetNodesubnetIPFetcher() *nodesubnet.IPFetcher {
88+
return service.nodesubnetIPFetcher
89+
}

cns/restserver/nodesubnet.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package restserver
2+
3+
import (
4+
"context"
5+
"net/netip"
6+
7+
"github.com/Azure/azure-container-networking/cns"
8+
"github.com/Azure/azure-container-networking/cns/logger"
9+
nodesubnet "github.com/Azure/azure-container-networking/cns/nodesubnet"
10+
"github.com/Azure/azure-container-networking/cns/types"
11+
"github.com/pkg/errors"
12+
)
13+
14+
var _ nodesubnet.IPConsumer = &HTTPRestService{}
15+
16+
// UpdateIPsForNodeSubnet updates the IP pool of HTTPRestService with newly fetched secondary IPs
17+
func (service *HTTPRestService) UpdateIPsForNodeSubnet(secondaryIPs []netip.Addr) error {
18+
secondaryIPStrs := make([]string, len(secondaryIPs))
19+
for i, ip := range secondaryIPs {
20+
secondaryIPStrs[i] = ip.String()
21+
}
22+
23+
networkContainerRequest := nodesubnet.CreateNodeSubnetNCRequest(secondaryIPStrs)
24+
25+
code, msg := service.saveNetworkContainerGoalState(*networkContainerRequest)
26+
if code != types.Success {
27+
return errors.Errorf("failed to save fetched ips. code: %d, message %s", code, msg)
28+
}
29+
30+
logger.Debugf("IP change processed successfully")
31+
32+
// saved NC successfully. UpdateIPsForNodeSubnet is called only when IPs are fetched from NMAgent.
33+
// We now have IPs to serve IPAM requests. Generate conflist to indicate CNS is ready
34+
service.MustGenerateCNIConflistOnce()
35+
return nil
36+
}
37+
38+
// InitializeNodeSubnet prepares CNS for serving NodeSubnet requests.
39+
// It sets the orchestrator type to KubernetesCRD, reconciles the initial
40+
// CNS state from the statefile, then creates an IP fetcher.
41+
func (service *HTTPRestService) InitializeNodeSubnet(ctx context.Context, podInfoByIPProvider cns.PodInfoByIPProvider) error {
42+
// set orchestrator type
43+
orchestrator := cns.SetOrchestratorTypeRequest{
44+
OrchestratorType: cns.KubernetesCRD,
45+
}
46+
service.SetNodeOrchestrator(&orchestrator)
47+
48+
if podInfoByIPProvider == nil {
49+
logger.Printf("PodInfoByIPProvider is nil, this usually means no saved endpoint state. Skipping reconciliation")
50+
} else if _, err := nodesubnet.ReconcileInitialCNSState(ctx, service, podInfoByIPProvider); err != nil {
51+
return errors.Wrap(err, "reconcile initial CNS state")
52+
}
53+
// statefile (if any) is reconciled. Initialize the IP fetcher. Start the IP fetcher only after the service is started,
54+
// because starting the IP fetcher will generate conflist, which should be done only once we are ready to respond to IPAM requests.
55+
service.nodesubnetIPFetcher = nodesubnet.NewIPFetcher(service.nma, service, 0, 0, logger.Log)
56+
57+
return nil
58+
}
59+
60+
// StartNodeSubnet starts the IP fetcher for NodeSubnet. This will cause secondary IPs to be fetched periodically.
61+
// After the first successful fetch, conflist will be generated to indicate CNS is ready.
62+
func (service *HTTPRestService) StartNodeSubnet(ctx context.Context) {
63+
service.nodesubnetIPFetcher.Start(ctx)
64+
}

0 commit comments

Comments
 (0)