Skip to content

Commit 0bbce8d

Browse files
Yongli Chentamilmani1989
authored andcommitted
Support k8s DNS & endpoint policy (#127)
* configure dnssuffix & dnsServerList * add dns info to conflist * change case for dns info * remove hardcoding * remove hardcoding * parse k8s pod info * add AdditionalArgs and Dns info to conflist * serialize policies * program route info * start addressign ipam ip leak * fix 1) ip inconsistency in k8s & pod. 2) IP leak in IPAM. * remove comments * separate windows & linux * remove dnsServers * remove comments * address comments * add dns verification * abstract linux policy struct * remove setPolicies
1 parent 5018a36 commit 0bbce8d

File tree

13 files changed

+323
-98
lines changed

13 files changed

+323
-98
lines changed

cni/azure-linux.conflist

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
{
2-
"cniVersion": "0.3.0",
3-
"name": "azure",
4-
"plugins": [{
5-
"type": "azure-vnet",
6-
"mode": "bridge",
7-
"bridge": "azure0",
8-
"ipam": {
9-
"type": "azure-vnet-ipam"
10-
}
11-
},
12-
{
13-
"type": "portmap",
14-
"capabilities": {"portMappings": true},
15-
"snat": true
16-
}
17-
]
18-
}
2+
"cniVersion":"0.3.0",
3+
"name":"azure",
4+
"plugins":[
5+
{
6+
"type":"azure-vnet",
7+
"mode":"bridge",
8+
"bridge":"azure0",
9+
"ipam":{
10+
"type":"azure-vnet-ipam"
11+
}
12+
},
13+
{
14+
"type":"portmap",
15+
"capabilities":{
16+
"portMappings":true
17+
},
18+
"snat":true
19+
}
20+
]
21+
}

cni/azure-windows.conflist

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,43 @@
11
{
2-
"cniVersion": "0.3.0",
3-
"name": "azure",
4-
"plugins": [{
5-
"type": "azure-vnet",
6-
"mode": "bridge",
7-
"bridge": "azure0",
8-
"ipam": {
9-
"type": "azure-vnet-ipam"
10-
}
2+
"cniVersion":"0.3.0",
3+
"name":"azure",
4+
"plugins":[
5+
{
6+
"type":"azure-vnet",
7+
"mode":"bridge",
8+
"bridge":"azure0",
9+
"ipam":{
10+
"type":"azure-vnet-ipam"
11+
},
12+
"dns":{
13+
"Nameservers":[
14+
"168.63.129.16",
15+
"10.0.0.10"
16+
],
17+
"Search":[
18+
"svc.cluster.local"
19+
]
20+
},
21+
"AdditionalArgs":[
22+
{
23+
"Name":"EndpointPolicy",
24+
"Value":{
25+
"Type":"OutBoundNAT",
26+
"ExceptionList":[
27+
"10.240.0.0/16",
28+
"10.0.0.0/8"
29+
]
30+
}
31+
},
32+
{
33+
"Name":"EndpointPolicy",
34+
"Value":{
35+
"Type":"ROUTE",
36+
"DestinationPrefix":"10.0.0.0/8",
37+
"NeedEncap":true
38+
}
1139
}
12-
]
40+
]
41+
}
42+
]
1343
}

cni/netconfig.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,23 @@ package cni
55

66
import (
77
"encoding/json"
8+
"strings"
9+
10+
"github.com/Azure/azure-container-networking/network/policy"
11+
12+
cniTypes "github.com/containernetworking/cni/pkg/types"
813
)
914

15+
const (
16+
PolicyStr string = "Policy"
17+
)
18+
19+
// KVPair represents a K-V pair of a json object.
20+
type KVPair struct {
21+
Name string `json:"name"`
22+
Value json.RawMessage `json:"value"`
23+
}
24+
1025
// NetworkConfig represents Azure CNI plugin network configuration.
1126
type NetworkConfig struct {
1227
CNIVersion string `json:"cniVersion"`
@@ -25,6 +40,26 @@ type NetworkConfig struct {
2540
Address string `json:"ipAddress,omitempty"`
2641
QueryInterval string `json:"queryInterval,omitempty"`
2742
}
43+
DNS cniTypes.DNS `json:"dns"`
44+
AdditionalArgs []KVPair
45+
}
46+
47+
type K8SPodEnvArgs struct {
48+
cniTypes.CommonArgs
49+
K8S_POD_NAMESPACE cniTypes.UnmarshallableString `json:"K8S_POD_NAMESPACE,omitempty"`
50+
K8S_POD_NAME cniTypes.UnmarshallableString `json:"K8S_POD_NAME,omitempty"`
51+
K8S_POD_INFRA_CONTAINER_ID cniTypes.UnmarshallableString `json:"K8S_POD_INFRA_CONTAINER_ID,omitempty"`
52+
}
53+
54+
// ParseCniArgs unmarshals cni arguments.
55+
func ParseCniArgs(args string) (*K8SPodEnvArgs, error) {
56+
podCfg := K8SPodEnvArgs{}
57+
err := cniTypes.LoadArgs(args, &podCfg)
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
return &podCfg, nil
2863
}
2964

3065
// ParseNetworkConfig unmarshals network configuration from bytes.
@@ -43,6 +78,22 @@ func ParseNetworkConfig(b []byte) (*NetworkConfig, error) {
4378
return &nwCfg, nil
4479
}
4580

81+
// GetPoliciesFromNwCfg returns network policies from network config.
82+
func GetPoliciesFromNwCfg(kvp []KVPair) []policy.Policy {
83+
var policies []policy.Policy
84+
for _, pair := range kvp {
85+
if strings.Contains(pair.Name, PolicyStr) {
86+
policy := policy.Policy{
87+
Type: policy.CNIPolicyType(pair.Name),
88+
Data: pair.Value,
89+
}
90+
policies = append(policies, policy)
91+
}
92+
}
93+
94+
return policies
95+
}
96+
4697
// Serialize marshals a network configuration to bytes.
4798
func (nwcfg *NetworkConfig) Serialize() []byte {
4899
bytes, _ := json.Marshal(nwcfg)

cni/network/network.go

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package network
55

66
import (
77
"net"
8+
"strings"
89

910
"github.com/Azure/azure-container-networking/cni"
1011
"github.com/Azure/azure-container-networking/common"
@@ -123,16 +124,46 @@ func (plugin *netPlugin) findMasterInterface(nwCfg *cni.NetworkConfig, subnetPre
123124

124125
// Add handles CNI add commands.
125126
func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
126-
var result *cniTypesCurr.Result
127-
var err error
127+
var (
128+
result *cniTypesCurr.Result
129+
err error
130+
nwCfg *cni.NetworkConfig
131+
ipconfig *cniTypesCurr.IPConfig
132+
epInfo *network.EndpointInfo
133+
iface *cniTypesCurr.Interface
134+
)
128135

129136
log.Printf("[cni-net] Processing ADD command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}.",
130137
args.ContainerID, args.Netns, args.IfName, args.Args, args.Path)
131138

132-
defer func() { log.Printf("[cni-net] ADD command completed with result:%+v err:%v.", result, err) }()
139+
defer func() {
140+
// Add Interfaces to result.
141+
iface = &cniTypesCurr.Interface{
142+
Name: args.IfName,
143+
}
144+
result.Interfaces = append(result.Interfaces, iface)
145+
146+
// Convert result to the requested CNI version.
147+
res, err := result.GetAsVersion(nwCfg.CNIVersion)
148+
if err != nil {
149+
err = plugin.Error(err)
150+
}
151+
152+
// Output the result to stdout.
153+
res.Print()
154+
log.Printf("[cni-net] ADD command completed with result:%+v err:%v.", result, err)
155+
}()
156+
157+
// Parse Pod arguments.
158+
podCfg, err := cni.ParseCniArgs(args.Args)
159+
k8sNamespace := string(podCfg.K8S_POD_NAMESPACE)
160+
if len(k8sNamespace) == 0 {
161+
err = plugin.Errorf("No k8s pod namespace provided.")
162+
return err
163+
}
133164

134165
// Parse network configuration from stdin.
135-
nwCfg, err := cni.ParseNetworkConfig(args.StdinData)
166+
nwCfg, err = cni.ParseNetworkConfig(args.StdinData)
136167
if err != nil {
137168
err = plugin.Errorf("Failed to parse network configuration: %v.", err)
138169
return err
@@ -142,11 +173,31 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
142173

143174
// Initialize values from network config.
144175
networkId := nwCfg.Name
145-
endpointId := plugin.GetEndpointID(args)
176+
endpointId := network.GetEndpointID(args)
177+
178+
nwInfo, nwInfoErr := plugin.nm.GetNetworkInfo(networkId)
179+
180+
/* Handle consecutive ADD calls for infrastructure containers.
181+
* This is a temporary work around for issue #57253 of Kubernetes.
182+
* We can delete this if statement once they fix it.
183+
* Issue link: https://github.com/kubernetes/kubernetes/issues/57253
184+
*/
185+
epInfo, _ = plugin.nm.GetEndpointInfo(networkId, endpointId)
186+
if epInfo != nil {
187+
result, err = handleConsecutiveAdd(args.ContainerID, endpointId, nwInfo, nwCfg)
188+
if err != nil {
189+
return err
190+
}
191+
192+
if result != nil {
193+
return nil
194+
}
195+
}
196+
197+
policies := cni.GetPoliciesFromNwCfg(nwCfg.AdditionalArgs)
146198

147199
// Check whether the network already exists.
148-
nwInfo, err := plugin.nm.GetNetworkInfo(networkId)
149-
if err != nil {
200+
if nwInfoErr != nil {
150201
// Network does not exist.
151202
log.Printf("[cni-net] Creating network %v.", networkId)
152203

@@ -158,7 +209,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
158209
}
159210

160211
// Derive the subnet prefix from allocated IP address.
161-
ipconfig := result.IPs[0]
212+
ipconfig = result.IPs[0]
162213
subnetPrefix := ipconfig.Address
163214
subnetPrefix.IP = subnetPrefix.IP.Mask(subnetPrefix.Mask)
164215

@@ -201,6 +252,11 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
201252
},
202253
},
203254
BridgeName: nwCfg.Bridge,
255+
DNS: network.DNSInfo{
256+
Servers: nwCfg.DNS.Nameservers,
257+
Suffix: strings.Join(nwCfg.DNS.Search, ","),
258+
},
259+
Policies: policies,
204260
}
205261

206262
err = plugin.nm.CreateNetwork(&nwInfo)
@@ -223,7 +279,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
223279
return err
224280
}
225281

226-
ipconfig := result.IPs[0]
282+
ipconfig = result.IPs[0]
227283

228284
// On failure, call into IPAM plugin to release the address.
229285
defer func() {
@@ -235,11 +291,31 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
235291
}
236292

237293
// Initialize endpoint info.
238-
epInfo := &network.EndpointInfo{
294+
var dns network.DNSInfo
295+
if (len(nwCfg.DNS.Search) == 0) != (len(nwCfg.DNS.Nameservers) == 0) {
296+
err = plugin.Errorf("Wrong DNS configuration: %+v", nwCfg.DNS)
297+
return err
298+
}
299+
300+
if len(nwCfg.DNS.Search) > 0 {
301+
dns = network.DNSInfo{
302+
Servers: nwCfg.DNS.Nameservers,
303+
Suffix: strings.Join(nwCfg.DNS.Search, ","),
304+
}
305+
} else {
306+
dns = network.DNSInfo{
307+
Suffix: result.DNS.Domain,
308+
Servers: result.DNS.Nameservers,
309+
}
310+
}
311+
312+
epInfo = &network.EndpointInfo{
239313
Id: endpointId,
240314
ContainerID: args.ContainerID,
241315
NetNsPath: args.Netns,
242316
IfName: args.IfName,
317+
DNS: dns,
318+
Policies: policies,
243319
}
244320

245321
// Populate addresses.
@@ -252,10 +328,6 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
252328
epInfo.Routes = append(epInfo.Routes, network.RouteInfo{Dst: route.Dst, Gw: route.GW})
253329
}
254330

255-
// Populate DNS info.
256-
epInfo.DNS.Suffix = result.DNS.Domain
257-
epInfo.DNS.Servers = result.DNS.Nameservers
258-
259331
// Create the endpoint.
260332
log.Printf("[cni-net] Creating endpoint %v.", epInfo.Id)
261333
err = plugin.nm.CreateEndpoint(networkId, epInfo)
@@ -264,22 +336,6 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
264336
return err
265337
}
266338

267-
// Add Interfaces to result.
268-
iface := &cniTypesCurr.Interface{
269-
Name: epInfo.IfName,
270-
}
271-
result.Interfaces = append(result.Interfaces, iface)
272-
273-
// Convert result to the requested CNI version.
274-
res, err := result.GetAsVersion(nwCfg.CNIVersion)
275-
if err != nil {
276-
err = plugin.Error(err)
277-
return err
278-
}
279-
280-
// Output the result to stdout.
281-
res.Print()
282-
283339
return nil
284340
}
285341

@@ -303,7 +359,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error {
303359

304360
// Initialize values from network config.
305361
networkId := nwCfg.Name
306-
endpointId := plugin.GetEndpointID(args)
362+
endpointId := network.GetEndpointID(args)
307363

308364
// Query the network.
309365
nwInfo, err := plugin.nm.GetNetworkInfo(networkId)

cni/network/network_linux.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package network
2+
3+
import (
4+
cniTypesCurr "github.com/containernetworking/cni/pkg/types/current"
5+
)
6+
7+
// handleConsecutiveAdd is a dummy function for Linux platform.
8+
func handleConsecutiveAdd(containerId, endpointId string, nwInfo *NetworkInfo, nwCfg *NetworkConfig) (*cniTypesCurr.Result, error) {
9+
return nil, nil
10+
}

0 commit comments

Comments
 (0)