Skip to content

Commit af43d45

Browse files
committed
feat: Add CNI-telemtry sidecar in CNS pod
1 parent 25ea345 commit af43d45

File tree

7 files changed

+465
-30
lines changed

7 files changed

+465
-30
lines changed

.pipelines/pipeline.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ stages:
158158
arch: amd64
159159
name: npm
160160
os: windows
161+
cni_telemetry_sidecar_linux_amd64:
162+
arch: amd64
163+
name: cni-telemetry-sidecar
164+
os: linux
165+
cni_telemetry_sidecar_windows_amd64:
166+
arch: amd64
167+
name: cni-telemetry-sidecar
168+
os: windows
161169
steps:
162170
- template: containers/container-template.yaml
163171
parameters:
@@ -199,6 +207,10 @@ stages:
199207
arch: arm64
200208
name: npm
201209
os: linux
210+
cni_telemetry_sidecar_linux_arm64:
211+
arch: arm64
212+
name: cni-telemetry-sidecar
213+
os: linux
202214
steps:
203215
- template: containers/container-template.yaml
204216
parameters:

Makefile

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ ACN_PACKAGE_PATH = github.com/Azure/azure-container-networking
8888
CNI_AI_PATH=$(ACN_PACKAGE_PATH)/telemetry.aiMetadata
8989
CNS_AI_PATH=$(ACN_PACKAGE_PATH)/cns/logger.aiMetadata
9090
NPM_AI_PATH=$(ACN_PACKAGE_PATH)/npm.aiMetadata
91+
CNI_TELEMETRY_SIDECAR_DIR = $(REPO_ROOT)/cns/cni-telemetry-sidecar
92+
CNI_TELEMETRY_SIDECAR_BUILD_DIR = $(BUILD_DIR)/cni-telemetry-sidecar
93+
CNI_TELEMETRY_SIDECAR_AI_ID = $(CNI_AI_ID) # Reuse CNI AI ID
94+
CNI_TELEMETRY_SIDECAR_VERSION = $(CNS_VERSION) # Version follows CNS
9195

9296
# Tool paths
9397
CONTROLLER_GEN := $(TOOLS_BIN_DIR)/controller-gen
@@ -235,6 +239,10 @@ azure-vnet-ipamv6-binary:
235239
azure-vnet-telemetry-binary:
236240
cd $(CNI_TELEMETRY_DIR) && CGO_ENABLED=0 go build -v -o $(CNI_BUILD_DIR)/azure-vnet-telemetry$(EXE_EXT) -ldflags "-X main.version=$(CNI_VERSION) -X $(CNI_AI_PATH)=$(CNI_AI_ID) $(LD_BUILD_FLAGS)" -gcflags="-dwarflocationlists=true"
237241

242+
# Build the Azure CNI Telemetry Sidecar binary.
243+
cni-telemetry-sidecar-binary:
244+
cd $(CNI_TELEMETRY_SIDECAR_DIR) && CGO_ENABLED=0 go build -v -o $(CNI_TELEMETRY_SIDECAR_BUILD_DIR)/azure-cni-telemetry-sidecar$(EXE_EXT) -ldflags "-X main.version=$(CNI_TELEMETRY_SIDECAR_VERSION) -X $(CNI_AI_PATH)=$(CNI_TELEMETRY_SIDECAR_AI_ID)" -gcflags="-dwarflocationlists=true"
245+
238246
# Build the Azure CLI network binary.
239247
acncli-binary:
240248
cd $(ACNCLI_DIR) && CGO_ENABLED=0 go build -v -o $(ACNCLI_BUILD_DIR)/acn$(EXE_EXT) -ldflags "-X main.version=$(ACN_VERSION) $(LD_BUILD_FLAGS)" -gcflags="-dwarflocationlists=true"
@@ -596,6 +604,35 @@ npm-image-pull: ## pull cns container image.
596604
IMAGE=$(NPM_IMAGE) \
597605
TAG=$(NPM_PLATFORM_TAG)
598606

607+
# cni-telemetry-sidecar
608+
609+
cni-telemetry-sidecar-image-name: # util target to print the CNI telemetry sidecar image name
610+
@echo $(CNI_TELEMETRY_SIDECAR_IMAGE)
611+
612+
cni-telemetry-sidecar-image-name-and-tag: # util target to print the CNI telemetry sidecar image name and tag.
613+
@echo $(IMAGE_REGISTRY)/$(CNI_TELEMETRY_SIDECAR_IMAGE):$(CNI_TELEMETRY_SIDECAR_PLATFORM_TAG)
614+
615+
cni-telemetry-sidecar-image: ## build cni-telemetry-sidecar container image.
616+
$(MAKE) container \
617+
DOCKERFILE=cns/cni-telemetry-sidecar/Dockerfile \
618+
IMAGE=$(CNI_TELEMETRY_SIDECAR_IMAGE) \
619+
EXTRA_BUILD_ARGS='--build-arg CNI_AI_PATH=$(CNI_AI_PATH) --build-arg CNI_AI_ID=$(CNI_TELEMETRY_SIDECAR_AI_ID)' \
620+
PLATFORM=$(PLATFORM) \
621+
TAG=$(CNI_TELEMETRY_SIDECAR_PLATFORM_TAG) \
622+
TARGET=$(OS) \
623+
OS=$(OS) \
624+
ARCH=$(ARCH)
625+
626+
cni-telemetry-sidecar-image-push: ## push cni-telemetry-sidecar container image.
627+
$(MAKE) container-push \
628+
IMAGE=$(CNI_TELEMETRY_SIDECAR_IMAGE) \
629+
TAG=$(CNI_TELEMETRY_SIDECAR_PLATFORM_TAG)
630+
631+
cni-telemetry-sidecar-image-pull: ## pull cni-telemetry-sidecar container image.
632+
$(MAKE) container-pull \
633+
IMAGE=$(CNI_TELEMETRY_SIDECAR_IMAGE) \
634+
TAG=$(CNI_TELEMETRY_SIDECAR_PLATFORM_TAG)
635+
599636
## Reusable targets for building multiplat container image manifests.
600637

601638
IMAGE_ARCHIVE_DIR ?= $(shell pwd)
@@ -751,6 +788,21 @@ npm-skopeo-archive: ## export tar archive of multiplat container manifest.
751788
IMAGE=$(NPM_IMAGE) \
752789
TAG=$(NPM_VERSION)
753790

791+
cni-telemetry-sidecar-manifest-build: ## build cni-telemetry-sidecar multiplat container manifest.
792+
$(MAKE) manifest-build \
793+
PLATFORMS="$(PLATFORMS)" \
794+
IMAGE=$(CNI_TELEMETRY_SIDECAR_IMAGE) \
795+
TAG=$(CNI_TELEMETRY_SIDECAR_VERSION)
796+
797+
cni-telemetry-sidecar-manifest-push: ## push cni-telemetry-sidecar multiplat container manifest
798+
$(MAKE) manifest-push \
799+
IMAGE=$(CNI_TELEMETRY_SIDECAR_IMAGE) \
800+
TAG=$(CNI_TELEMETRY_SIDECAR_VERSION)
801+
802+
cni-telemetry-sidecar-skopeo-archive: ## export tar archive of cni-telemetry-sidecar multiplat container manifest.
803+
$(MAKE) manifest-skopeo-archive \
804+
IMAGE=$(CNI_TELEMETRY_SIDECAR_IMAGE) \
805+
TAG=$(CNI_TELEMETRY_SIDECAR_VERSION)
754806

755807
########################### Archives ################################
756808

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Azure CNI Telemetry Sidecar Dockerfile
2+
# Based on proven CNI Dockerfile pattern from azure-container-networking
3+
ARG ARCH
4+
ARG OS_VERSION
5+
ARG OS
6+
7+
# Use the same proven base images as CNI
8+
# mcr.microsoft.com/oss/go/microsoft/golang:1.23-azurelinux3.0
9+
FROM --platform=linux/${ARCH} mcr.microsoft.com/oss/go/microsoft/golang@sha256:8f60e85f4b2f567c888d0b3a4cd12dc74bee534d94c528655546452912d90c74 AS go
10+
11+
# mcr.microsoft.com/azurelinux/base/core:3.0
12+
FROM --platform=linux/${ARCH} mcr.microsoft.com/azurelinux/base/core@sha256:9948138108a3d69f1dae62104599ac03132225c3b7a5ac57b85a214629c8567d AS mariner-core
13+
14+
FROM go AS azure-cni-telemetry-sidecar
15+
ARG OS
16+
ARG VERSION
17+
ARG CNI_AI_PATH
18+
ARG CNI_AI_ID
19+
20+
WORKDIR /azure-container-networking
21+
COPY . .
22+
23+
# Debug: Check if the source file exists and show Go version
24+
RUN ls -la cns/cni-telemetry-sidecar/ && go version
25+
26+
# Build the Azure CNI telemetry sidecar binary for Linux
27+
RUN CGO_ENABLED=0 GOOS=linux go build \
28+
-a \
29+
-o /go/bin/azure-cni-telemetry-sidecar \
30+
-trimpath \
31+
-ldflags "-X main.version=${VERSION:-unknown} -X ${CNI_AI_PATH:-main.aiMetadata}=${CNI_AI_ID:-unknown}" \
32+
-gcflags="-dwarflocationlists=true" \
33+
./cns/cni-telemetry-sidecar/
34+
35+
# Build the Azure CNI telemetry sidecar binary for Windows
36+
RUN CGO_ENABLED=0 GOOS=windows go build \
37+
-a \
38+
-o /go/bin/azure-cni-telemetry-sidecar.exe \
39+
-trimpath \
40+
-ldflags "-X main.version=${VERSION:-unknown} -X ${CNI_AI_PATH:-main.aiMetadata}=${CNI_AI_ID:-unknown}" \
41+
-gcflags="-dwarflocationlists=true" \
42+
./cns/cni-telemetry-sidecar/
43+
44+
# Verify both binaries were built
45+
RUN ls -la /go/bin/azure-cni-telemetry-sidecar*
46+
47+
FROM scratch AS bins
48+
COPY --from=azure-cni-telemetry-sidecar /go/bin/* /
49+
50+
FROM scratch AS linux
51+
COPY --from=azure-cni-telemetry-sidecar /go/bin/azure-cni-telemetry-sidecar /azure-cni-telemetry-sidecar
52+
ENTRYPOINT [ "/azure-cni-telemetry-sidecar" ]
53+
54+
# Windows support following CNI pattern
55+
FROM --platform=windows/${ARCH} mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image@sha256:b4c9637e032f667c52d1eccfa31ad8c63f1b035e8639f3f48a510536bf34032b AS hpc
56+
57+
FROM hpc AS windows
58+
COPY --from=azure-cni-telemetry-sidecar /go/bin/azure-cni-telemetry-sidecar.exe /azure-cni-telemetry-sidecar.exe
59+
ENTRYPOINT [ "/azure-cni-telemetry-sidecar.exe" ]
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"time"
8+
9+
"github.com/Azure/azure-container-networking/cns/configuration"
10+
"github.com/Azure/azure-container-networking/cns/logger"
11+
)
12+
13+
// ConfigManager handles Azure CNS configuration loading and validation
14+
type ConfigManager struct {
15+
configPath string
16+
}
17+
18+
// NewConfigManager creates a new configuration manager for Azure CNS
19+
func NewConfigManager(configPath string) *ConfigManager {
20+
return &ConfigManager{
21+
configPath: configPath,
22+
}
23+
}
24+
25+
// LoadConfig loads and validates the Azure CNS configuration
26+
func (cm *ConfigManager) LoadConfig() (*configuration.CNSConfig, error) {
27+
logger.Printf("Loading Azure CNS configuration from: %s", cm.configPath)
28+
29+
// Wait for configuration file to become available (Kubernetes ConfigMap mount)
30+
if err := cm.waitForConfigFile(); err != nil {
31+
return nil, fmt.Errorf("Azure CNS configuration file not available: %w", err)
32+
}
33+
34+
// Read the configuration file from mounted volume
35+
data, err := os.ReadFile(cm.configPath)
36+
if err != nil {
37+
return nil, fmt.Errorf("failed to read Azure CNS configuration file: %w", err)
38+
}
39+
40+
// Parse JSON configuration into CNS config structure
41+
var config configuration.CNSConfig
42+
if err := json.Unmarshal(data, &config); err != nil {
43+
return nil, fmt.Errorf("failed to parse Azure CNS configuration: %w", err)
44+
}
45+
46+
// Validate configuration for Azure telemetry requirements
47+
if err := cm.validateConfig(&config); err != nil {
48+
return nil, fmt.Errorf("Azure CNS configuration validation failed: %w", err)
49+
}
50+
51+
logger.Printf("Azure CNS configuration loaded and validated successfully")
52+
return &config, nil
53+
}
54+
55+
// waitForConfigFile waits for the configuration file to become available
56+
// This is important in Kubernetes environments where ConfigMaps are mounted asynchronously
57+
func (cm *ConfigManager) waitForConfigFile() error {
58+
const maxRetries = 30
59+
const retryInterval = 2 * time.Second
60+
61+
for i := 0; i < maxRetries; i++ {
62+
if _, err := os.Stat(cm.configPath); err == nil {
63+
return nil
64+
}
65+
66+
if i == 0 {
67+
logger.Printf("Waiting for Azure CNS configuration file to become available...")
68+
}
69+
70+
time.Sleep(retryInterval)
71+
}
72+
73+
return fmt.Errorf("Azure CNS configuration file not available after %d attempts (%v total wait time)",
74+
maxRetries, time.Duration(maxRetries)*retryInterval)
75+
}
76+
77+
// validateConfig performs Azure-specific validation of the CNS configuration
78+
func (cm *ConfigManager) validateConfig(config *configuration.CNSConfig) error {
79+
// Validate that telemetry settings are properly configured
80+
if config.TelemetrySettings.AppInsightsInstrumentationKey == "" && !config.TelemetrySettings.DisableAll {
81+
logger.Printf("Warning: No Application Insights instrumentation key configured and telemetry not disabled")
82+
}
83+
84+
// Validate batch size settings for Azure Application Insights
85+
if config.TelemetrySettings.TelemetryBatchSizeBytes <= 0 {
86+
logger.Printf("Warning: Invalid telemetry batch size, using default")
87+
}
88+
89+
// Validate batch interval for optimal Azure ingestion
90+
if config.TelemetrySettings.TelemetryBatchIntervalInSecs <= 0 {
91+
logger.Printf("Warning: Invalid telemetry batch interval, using default")
92+
}
93+
94+
// Log configuration summary for Azure monitoring and debugging
95+
logger.Printf("Azure CNS Configuration Summary:")
96+
logger.Printf(" - Telemetry DisableAll: %t", config.TelemetrySettings.DisableAll)
97+
logger.Printf(" - Application Insights Key Present: %t",
98+
config.TelemetrySettings.AppInsightsInstrumentationKey != "")
99+
logger.Printf(" - Batch Size: %d bytes", config.TelemetrySettings.TelemetryBatchSizeBytes)
100+
logger.Printf(" - Batch Interval: %d seconds", config.TelemetrySettings.TelemetryBatchIntervalInSecs)
101+
logger.Printf(" - Disable Trace: %t", config.TelemetrySettings.DisableTrace)
102+
logger.Printf(" - Disable Metric: %t", config.TelemetrySettings.DisableMetric)
103+
logger.Printf(" - Disable Event: %t", config.TelemetrySettings.DisableEvent)
104+
logger.Printf(" - Debug Mode: %t", config.TelemetrySettings.DebugMode)
105+
106+
return nil
107+
}

cns/cni-telemetry-sidecar/main.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"os"
7+
"os/signal"
8+
"syscall"
9+
10+
"github.com/Azure/azure-container-networking/cns/logger"
11+
)
12+
13+
var (
14+
version = "unknown"
15+
configPath = flag.String("config", "/etc/cns/cns-config.json", "Path to CNS configuration file")
16+
)
17+
18+
func main() {
19+
flag.Parse()
20+
21+
// Initialize logging for the CNI telemetry sidecar
22+
logger.InitLogger("azure-cns-cni-telemetry-sidecar", 1, 1, "/var/log/azure-cns-telemetry")
23+
defer logger.Close()
24+
25+
logger.Printf("Starting Azure CNI Telemetry Sidecar v%s", version)
26+
27+
// Create telemetry sidecar service
28+
sidecar := NewTelemetrySidecar(*configPath)
29+
30+
// Setup graceful shutdown context
31+
ctx, cancel := context.WithCancel(context.Background())
32+
defer cancel()
33+
34+
// Handle OS signals for graceful shutdown
35+
sigCh := make(chan os.Signal, 1)
36+
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
37+
38+
go func() {
39+
sig := <-sigCh
40+
logger.Printf("Received shutdown signal %v, initiating graceful shutdown", sig)
41+
cancel()
42+
}()
43+
44+
// Run the telemetry sidecar
45+
if err := sidecar.Run(ctx); err != nil {
46+
logger.Errorf("Azure CNI Telemetry Sidecar failed: %v", err)
47+
os.Exit(1)
48+
}
49+
50+
logger.Printf("Azure CNI Telemetry Sidecar stopped gracefully")
51+
}

0 commit comments

Comments
 (0)