Skip to content

Commit 41232c1

Browse files
authored
CNI using CNS IPAM (#597)
* Configure CNI to use CNS IPAM
1 parent edb2833 commit 41232c1

Some content is hidden

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

62 files changed

+1240
-228
lines changed

.pipelines/e2e-step-template.yaml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,3 @@ steps:
9393
name: DeployAKSEngine
9494
displayName: Run AKS-Engine E2E Tests
9595
workingDirectory: "$(modulePath)"
96-
97-
- bash: |
98-
mkdir -p $(Build.ArtifactStagingDirectory)/kube-${{ parameters.name }}
99-
cp -r _output/k*/kubeconfig/kubeconfig.$REGIONS.json $(Build.ArtifactStagingDirectory)/kube-${{ parameters.name }}
100-
cp -r _output/kubernetes-*-ssh $(Build.ArtifactStagingDirectory)/kube-${{ parameters.name }}
101-
cp -r test/e2e/kubernetes/junit.xml $(Build.ArtifactStagingDirectory)/kube-${{ parameters.name }}
102-
name: CopyKubeConfigsAKSEngine
103-
displayName: Save cluster configs
104-
workingDirectory: "$(modulePath)"
105-
condition: always()
106-
107-
- task: PublishBuildArtifacts@1
108-
inputs:
109-
artifactName: "kube-${{ parameters.name }}"
110-
pathtoPublish: "$(Build.ArtifactStagingDirectory)/kube-${{ parameters.name }}"
111-
displayName: "Publish cluster configs"
112-
condition: always()

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ CNM_PLUGIN_ROOTFS = azure-vnet-plugin-rootfs
133133
# Azure network policy manager parameters.
134134
AZURE_NPM_IMAGE = containernetworking.azurecr.io/public/containernetworking/azure-npm
135135

136+
# Azure CNI installer parameters
137+
AZURE_CNI_IMAGE = containernetworking.azurecr.io/public/containernetworking/azure-cni-installer
138+
136139
# Azure vnet telemetry image parameters.
137140
AZURE_VNET_TELEMETRY_IMAGE = containernetworking.azurecr.io/public/containernetworking/azure-vnet-telemetry
138141

@@ -231,6 +234,17 @@ all-containerized:
231234
docker rm $(BUILD_CONTAINER_NAME)
232235
docker rmi $(BUILD_CONTAINER_IMAGE):$(VERSION)
233236

237+
# Make both linux and windows binaries
238+
.PHONY: all-binaries-platforms
239+
all-binaries-platforms:
240+
export GOOS=linux; make all-binaries
241+
export GOOS=windows; make all-binaries
242+
243+
# CNI Installer
244+
.PHONY: cni-installer
245+
cni-installer: all-binaries-platforms
246+
docker build -f ./cni/installer/Dockerfile --build-arg VERSION=$(VERSION) -t $(AZURE_CNI_IMAGE):$(VERSION) .
247+
234248
# Build the Azure CNM plugin image, installable with "docker plugin install".
235249
.PHONY: azure-vnet-plugin-image
236250
azure-vnet-plugin-image: azure-cnm-plugin

aitelemetry/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"sync"
55

66
"github.com/Azure/azure-container-networking/common"
7-
"github.com/Microsoft/ApplicationInsights-Go/appinsights"
7+
"github.com/microsoft/ApplicationInsights-Go/appinsights"
88
)
99

1010
// Application trace/log structure

aitelemetry/telemetrywrapper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"github.com/Azure/azure-container-networking/common"
99
"github.com/Azure/azure-container-networking/log"
1010
"github.com/Azure/azure-container-networking/store"
11-
"github.com/Microsoft/ApplicationInsights-Go/appinsights"
11+
"github.com/microsoft/ApplicationInsights-Go/appinsights"
1212
)
1313

1414
const (

cni/installer/Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM golang as build
2+
WORKDIR /go/src/github.com/Azure/azure-container-networking/
3+
ADD . .
4+
ARG VERSION
5+
RUN cd ./cni/installer && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /go/installer -ldflags "-X main.version=${VERSION} -s -w"
6+
RUN mv ./output /output
7+
RUN chmod +x /go/installer
8+
RUN find /output -name "*.zip" -type f -delete
9+
RUN find /output -name "*.tgz" -type f -delete
10+
11+
FROM golang
12+
COPY --from=build /go/installer .
13+
COPY --from=build /output /output
14+
CMD ["sleep", "1000000"]

cni/installer/install.go

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
11+
ccn "github.com/Azure/azure-container-networking/cni"
12+
)
13+
14+
const (
15+
binPerm = 755
16+
conflistPerm = 644
17+
18+
linux = "linux"
19+
windows = "windows"
20+
amd64 = "amd64"
21+
22+
azureCNIBin = "azure-vnet"
23+
azureTelemetryBin = "azure-vnet-telemetry"
24+
azureCNSIPAM = "azure-cns"
25+
auzureVNETIPAM = "azure-vnet-ipam"
26+
conflistExtension = ".conflist"
27+
cni = "cni"
28+
multitenancy = "multitenancy"
29+
singletenancy = "singletenancy"
30+
defaultSrcDirLinux = "/output/"
31+
defaultBinDirLinux = "/opt/cni/bin/"
32+
defaultConflistDirLinux = "/etc/cni/net.d/"
33+
34+
envCNIOS = "CNI_OS"
35+
envCNITYPE = "CNI_TYPE"
36+
envCNISourceDir = "CNI_SRC_DIR"
37+
envCNIDestinationBinDir = "CNI_DST_BIN_DIR"
38+
envCNIDestinationConflistDir = "CNI_DST_CONFLIST_DIR"
39+
envCNIIPAMType = "CNI_IPAM_TYPE"
40+
envCNIExemptBins = "CNI_EXCEMPT_BINS"
41+
)
42+
43+
type environmentalVariables struct {
44+
srcDir string
45+
dstBinDir string
46+
dstConflistDir string
47+
ipamType string
48+
exemptBins map[string]bool
49+
}
50+
51+
type rawConflist struct {
52+
Name string `json:"name"`
53+
CniVersion string `json:"cniVersion"`
54+
Plugins []interface{} `json:"plugins"`
55+
}
56+
57+
var (
58+
version string
59+
)
60+
61+
func main() {
62+
envs, err := getDirectoriesFromEnv()
63+
if err != nil {
64+
fmt.Printf("Failed to get environmental variables with err: %v", err)
65+
os.Exit(1)
66+
}
67+
68+
if _, err := os.Stat(envs.dstBinDir); os.IsNotExist(err) {
69+
os.MkdirAll(envs.dstBinDir, binPerm)
70+
}
71+
if err != nil {
72+
fmt.Printf("Failed to create destination bin %v directory: %v", envs.dstBinDir, err)
73+
os.Exit(1)
74+
}
75+
76+
if _, err := os.Stat(envs.dstConflistDir); os.IsNotExist(err) {
77+
os.MkdirAll(envs.dstConflistDir, conflistPerm)
78+
}
79+
if err != nil {
80+
fmt.Printf("Failed to create destination conflist %v directory: %v with err %v", envs.dstConflistDir, envs.dstBinDir, err)
81+
os.Exit(1)
82+
}
83+
84+
binaries, conflists, err := getFiles(envs.srcDir)
85+
if err != nil {
86+
fmt.Printf("Failed to get CNI related file paths with err: %v", err)
87+
os.Exit(1)
88+
}
89+
90+
err = copyBinaries(binaries, envs, binPerm)
91+
if err != nil {
92+
fmt.Printf("Failed to copy CNI binaries with err: %v", err)
93+
os.Exit(1)
94+
}
95+
96+
for _, conf := range conflists {
97+
err = modifyConflists(conf, envs, conflistPerm)
98+
if err != nil {
99+
fmt.Println(err)
100+
os.Exit(1)
101+
}
102+
}
103+
104+
if version == "" {
105+
version = "[No version set]"
106+
}
107+
108+
fmt.Printf("Successfully installed Azure CNI %s and binaries to %s and conflist to %s\n", version, envs.dstBinDir, envs.dstConflistDir)
109+
}
110+
111+
func modifyConflists(conflistpath string, envs environmentalVariables, perm os.FileMode) error {
112+
jsonFile, err := os.Open(conflistpath)
113+
if err != nil {
114+
return err
115+
}
116+
defer jsonFile.Close()
117+
118+
var conflist rawConflist
119+
byteValue, err := ioutil.ReadAll(jsonFile)
120+
if err != nil {
121+
return err
122+
}
123+
124+
err = json.Unmarshal(byteValue, &conflist)
125+
if err != nil {
126+
return err
127+
}
128+
129+
// if we need to modify the conflist from env's do it here
130+
if envs.ipamType != "" {
131+
confmap, err := modifyConf(conflist.Plugins[0], envs)
132+
if err != nil {
133+
return err
134+
}
135+
136+
conflist.Plugins[0] = confmap
137+
138+
pretty, _ := json.MarshalIndent(conflist, "", " ")
139+
fmt.Printf("Modified conflist from envs:\n-------\n%+v\n-------\n", string(pretty))
140+
}
141+
142+
// get target path
143+
dstFile := envs.dstConflistDir + filepath.Base(conflistpath)
144+
filebytes, err := json.MarshalIndent(conflist, "", "\t")
145+
if err != nil {
146+
return err
147+
}
148+
149+
fmt.Printf("Installing %v...\n", dstFile)
150+
return ioutil.WriteFile(dstFile, filebytes, perm)
151+
}
152+
153+
func modifyConf(conf interface{}, envs environmentalVariables) (interface{}, error) {
154+
mapbytes, err := json.Marshal(conf)
155+
if err != nil {
156+
return nil, err
157+
}
158+
159+
netconfig := ccn.NetworkConfig{}
160+
if err := json.Unmarshal(mapbytes, &netconfig); err != nil {
161+
return nil, err
162+
}
163+
164+
// change the netconfig from passed envs
165+
netconfig.Ipam.Type = envs.ipamType
166+
167+
netconfigbytes, _ := json.Marshal(netconfig)
168+
var rawConfig interface{}
169+
if err := json.Unmarshal(netconfigbytes, &rawConfig); err != nil {
170+
return nil, err
171+
}
172+
173+
return rawConfig, nil
174+
}
175+
176+
func getDirectoriesFromEnv() (environmentalVariables, error) {
177+
osVersion := os.Getenv(envCNIOS)
178+
cniType := os.Getenv(envCNITYPE)
179+
srcDirectory := os.Getenv(envCNISourceDir)
180+
dstBinDirectory := os.Getenv(envCNIDestinationBinDir)
181+
dstConflistDirectory := os.Getenv(envCNIDestinationConflistDir)
182+
ipamType := os.Getenv(envCNIIPAMType)
183+
envCNIExemptBins := os.Getenv(envCNIExemptBins)
184+
185+
envs := environmentalVariables{
186+
exemptBins: make(map[string]bool),
187+
}
188+
189+
// only allow windows and linux binaries
190+
if strings.EqualFold(osVersion, linux) || strings.EqualFold(osVersion, windows) {
191+
osVersion = fmt.Sprintf("%s_%s", osVersion, amd64)
192+
} else {
193+
return envs, fmt.Errorf("No target OS version supplied, please set %q env and try again", envCNIOS)
194+
}
195+
196+
// get paths for singletenancy and multitenancy
197+
switch {
198+
case strings.EqualFold(cniType, multitenancy):
199+
cniType = fmt.Sprintf("%s-%s", cni, multitenancy)
200+
case strings.EqualFold(cniType, singletenancy):
201+
cniType = cni
202+
default:
203+
return envs, fmt.Errorf("No CNI type supplied, please set %q env to either %q or %q and try again", envCNITYPE, singletenancy, multitenancy)
204+
}
205+
206+
// set the source directory where bins and conflist(s) are
207+
if srcDirectory == "" {
208+
srcDirectory = defaultSrcDirLinux
209+
}
210+
envs.srcDir = fmt.Sprintf("%s%s/%s/", srcDirectory, osVersion, cniType)
211+
212+
// set the destination directory to install binaries
213+
if dstBinDirectory == "" {
214+
dstBinDirectory = defaultBinDirLinux
215+
}
216+
envs.dstBinDir = dstBinDirectory
217+
218+
// set the destination directory to install conflists
219+
if dstConflistDirectory == "" {
220+
dstConflistDirectory = defaultConflistDirLinux
221+
}
222+
envs.dstConflistDir = dstConflistDirectory
223+
224+
// set exempt binaries to skip installing
225+
// convert to all lower case, strip whitespace, and split on comma
226+
exempt := strings.Split(strings.Replace(strings.ToLower(envCNIExemptBins), " ", "", -1), ",")
227+
for _, binName := range exempt {
228+
envs.exemptBins[binName] = true
229+
}
230+
231+
// set custom conflist settings
232+
envs.ipamType = ipamType
233+
234+
return envs, nil
235+
}
236+
237+
func getFiles(path string) (binaries []string, conflists []string, err error) {
238+
err = filepath.Walk(path,
239+
func(path string, info os.FileInfo, err error) error {
240+
if err != nil {
241+
return fmt.Errorf("Failed to traverse path %s with err %s", path, err)
242+
}
243+
244+
if !info.IsDir() {
245+
ext := filepath.Ext(path)
246+
if ext == conflistExtension {
247+
conflists = append(conflists, path)
248+
} else {
249+
binaries = append(binaries, path)
250+
}
251+
252+
}
253+
254+
return nil
255+
})
256+
257+
return
258+
}
259+
260+
func copyBinaries(filePaths []string, envs environmentalVariables, perm os.FileMode) error {
261+
for _, path := range filePaths {
262+
fileName := filepath.Base(path)
263+
264+
if exempt, ok := envs.exemptBins[fileName]; ok && exempt {
265+
fmt.Printf("Skipping %s, marked as exempt\n", fileName)
266+
} else {
267+
err := copyFile(path, envs.dstBinDir+fileName, perm)
268+
fmt.Printf("Installing %v...\n", envs.dstBinDir+fileName)
269+
if err != nil {
270+
return err
271+
}
272+
}
273+
274+
}
275+
276+
return nil
277+
}
278+
279+
func copyFile(src string, dst string, perm os.FileMode) error {
280+
data, err := ioutil.ReadFile(src)
281+
if err != nil {
282+
return err
283+
}
284+
285+
err = ioutil.WriteFile(dst, data, perm)
286+
if err != nil {
287+
return err
288+
}
289+
290+
return nil
291+
}

0 commit comments

Comments
 (0)