Skip to content

Commit 0a4c0d8

Browse files
authored
Send pod name/ns to nodeagent (#2790)
* Send pod name/ns to nodeagent * minor nits
1 parent dba87e6 commit 0a4c0d8

File tree

7 files changed

+232
-75
lines changed

7 files changed

+232
-75
lines changed

cmd/routed-eni-cni-plugin/cni.go

+31
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@ import (
4242
"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/cniutils"
4343
"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/logger"
4444
pb "github.com/aws/amazon-vpc-cni-k8s/rpc"
45+
"github.com/aws/amazon-vpc-cni-k8s/utils"
4546
)
4647

4748
const ipamdAddress = "127.0.0.1:50051"
4849

50+
const npAgentAddress = "127.0.0.1:50052"
51+
4952
const dummyInterfacePrefix = "dummy"
5053

5154
var version string
@@ -276,6 +279,34 @@ func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrap
276279
// dummy interface is appended to PrevResult for use during cleanup
277280
result.Interfaces = append(result.Interfaces, dummyInterface)
278281

282+
if utils.IsStrictMode(r.NetworkPolicyMode) {
283+
// Set up a connection to the network policy agent
284+
npConn, err := grpcClient.Dial(npAgentAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
285+
if err != nil {
286+
log.Errorf("Failed to connect to network policy agent: %v", err)
287+
return errors.Wrap(err, "add cmd: failed to connect to network policy agent backend server")
288+
}
289+
defer npConn.Close()
290+
291+
//Make a GRPC call for network policy agent
292+
npc := rpcClient.NewNPBackendClient(npConn)
293+
294+
npr, err := npc.EnforceNpToPod(context.Background(),
295+
&pb.EnforceNpRequest{
296+
K8S_POD_NAME: string(k8sArgs.K8S_POD_NAME),
297+
K8S_POD_NAMESPACE: string(k8sArgs.K8S_POD_NAMESPACE),
298+
})
299+
300+
// No need to cleanup IP and network, kubelet will send delete.
301+
if err != nil || !npr.Success {
302+
log.Errorf("Failed to setup default network policy for Pod Name %s and NameSpace %s: GRPC returned - %v Network policy agent returned - %v",
303+
string(k8sArgs.K8S_POD_NAME), string(k8sArgs.K8S_POD_NAMESPACE), err, npr)
304+
return errors.New("add cmd: failed to setup network policy in strict mode")
305+
}
306+
307+
log.Debugf("Network Policy agent returned Success : %v", npr.Success)
308+
}
309+
279310
return cniTypes.PrintResult(result, conf.CNIVersion)
280311
}
281312

cmd/routed-eni-cni-plugin/cni_test.go

+90-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func TestCmdAdd(t *testing.T) {
9494
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
9595
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)
9696

97-
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum}
97+
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "none"}
9898
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)
9999

100100
v4Addr := &net.IPNet{
@@ -110,6 +110,92 @@ func TestCmdAdd(t *testing.T) {
110110
assert.Nil(t, err)
111111
}
112112

113+
func TestCmdAddWithNPenabled(t *testing.T) {
114+
ctrl, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork := setup(t)
115+
defer ctrl.Finish()
116+
117+
stdinData, _ := json.Marshal(netConf)
118+
119+
cmdArgs := &skel.CmdArgs{ContainerID: containerID,
120+
Netns: netNS,
121+
IfName: ifName,
122+
StdinData: stdinData}
123+
124+
mocksTypes.EXPECT().LoadArgs(gomock.Any(), gomock.Any()).Return(nil)
125+
126+
conn, _ := grpc.Dial(ipamdAddress, grpc.WithInsecure())
127+
128+
mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(conn, nil)
129+
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
130+
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)
131+
132+
npConn, _ := grpc.Dial(npAgentAddress, grpc.WithInsecure())
133+
134+
mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(npConn, nil)
135+
mockNP := mock_rpc.NewMockNPBackendClient(ctrl)
136+
mocksRPC.EXPECT().NewNPBackendClient(npConn).Return(mockNP)
137+
138+
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "strict"}
139+
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)
140+
141+
enforceNpReply := &rpc.EnforceNpReply{Success: true}
142+
mockNP.EXPECT().EnforceNpToPod(gomock.Any(), gomock.Any()).Return(enforceNpReply, nil)
143+
144+
v4Addr := &net.IPNet{
145+
IP: net.ParseIP(addNetworkReply.IPv4Addr),
146+
Mask: net.IPv4Mask(255, 255, 255, 255),
147+
}
148+
mocksNetwork.EXPECT().SetupPodNetwork(gomock.Any(), cmdArgs.IfName, cmdArgs.Netns,
149+
v4Addr, nil, int(addNetworkReply.DeviceNumber), gomock.Any(), gomock.Any()).Return(nil)
150+
151+
mocksTypes.EXPECT().PrintResult(gomock.Any(), gomock.Any()).Return(nil)
152+
153+
err := add(cmdArgs, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork)
154+
assert.Nil(t, err)
155+
}
156+
157+
func TestCmdAddWithNPenabledWithErr(t *testing.T) {
158+
ctrl, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork := setup(t)
159+
defer ctrl.Finish()
160+
161+
stdinData, _ := json.Marshal(netConf)
162+
163+
cmdArgs := &skel.CmdArgs{ContainerID: containerID,
164+
Netns: netNS,
165+
IfName: ifName,
166+
StdinData: stdinData}
167+
168+
mocksTypes.EXPECT().LoadArgs(gomock.Any(), gomock.Any()).Return(nil)
169+
170+
conn, _ := grpc.Dial(ipamdAddress, grpc.WithInsecure())
171+
172+
mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(conn, nil)
173+
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
174+
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)
175+
176+
npConn, _ := grpc.Dial(npAgentAddress, grpc.WithInsecure())
177+
178+
mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(npConn, nil)
179+
mockNP := mock_rpc.NewMockNPBackendClient(ctrl)
180+
mocksRPC.EXPECT().NewNPBackendClient(npConn).Return(mockNP)
181+
182+
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "strict"}
183+
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)
184+
185+
enforceNpReply := &rpc.EnforceNpReply{Success: false}
186+
mockNP.EXPECT().EnforceNpToPod(gomock.Any(), gomock.Any()).Return(enforceNpReply, errors.New("Error on EnforceNpReply"))
187+
188+
v4Addr := &net.IPNet{
189+
IP: net.ParseIP(addNetworkReply.IPv4Addr),
190+
Mask: net.IPv4Mask(255, 255, 255, 255),
191+
}
192+
mocksNetwork.EXPECT().SetupPodNetwork(gomock.Any(), cmdArgs.IfName, cmdArgs.Netns,
193+
v4Addr, nil, int(addNetworkReply.DeviceNumber), gomock.Any(), gomock.Any()).Return(nil)
194+
195+
err := add(cmdArgs, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork)
196+
assert.Error(t, err)
197+
}
198+
113199
func TestCmdAddNetworkErr(t *testing.T) {
114200
ctrl, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork := setup(t)
115201
defer ctrl.Finish()
@@ -129,7 +215,7 @@ func TestCmdAddNetworkErr(t *testing.T) {
129215
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
130216
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)
131217

132-
addNetworkReply := &rpc.AddNetworkReply{Success: false, IPv4Addr: ipAddr, DeviceNumber: devNum}
218+
addNetworkReply := &rpc.AddNetworkReply{Success: false, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "none"}
133219
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, errors.New("Error on AddNetworkReply"))
134220

135221
err := add(cmdArgs, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork)
@@ -156,7 +242,7 @@ func TestCmdAddErrSetupPodNetwork(t *testing.T) {
156242
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
157243
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)
158244

159-
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum}
245+
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "none"}
160246
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)
161247

162248
addr := &net.IPNet{
@@ -292,7 +378,7 @@ func TestCmdAddForPodENINetwork(t *testing.T) {
292378
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)
293379

294380
addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, PodENISubnetGW: "10.0.0.1", PodVlanId: 1,
295-
PodENIMAC: "eniHardwareAddr", ParentIfIndex: 2}
381+
PodENIMAC: "eniHardwareAddr", ParentIfIndex: 2, NetworkPolicyMode: "none"}
296382
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)
297383

298384
addr := &net.IPNet{

pkg/ipamd/ipamd.go

+20
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ const (
176176
// aws error codes for insufficient IP address scenario
177177
INSUFFICIENT_CIDR_BLOCKS = "InsufficientCidrBlocks"
178178
INSUFFICIENT_FREE_IP_SUBNET = "InsufficientFreeAddressesInSubnet"
179+
180+
// envEnableNetworkPolicy is used to enable IPAMD/CNI to send pod create events to network policy agent.
181+
envNetworkPolicyMode = "NETWORK_POLICY_ENFORCING_MODE"
182+
defaultNetworkPolicyMode = "standard"
179183
)
180184

181185
var log = logger.Get()
@@ -219,6 +223,7 @@ type IPAMContext struct {
219223
enableManageUntaggedMode bool
220224
enablePodIPAnnotation bool
221225
maxPods int // maximum number of pods that can be scheduled on the node
226+
networkPolicyMode string
222227
}
223228

224229
// setUnmanagedENIs will rebuild the set of ENI IDs for ENIs tagged as "no_manage"
@@ -350,6 +355,11 @@ func New(k8sClient client.Client) (*IPAMContext, error) {
350355
c.enablePodIPAnnotation = enablePodIPAnnotation()
351356
c.numNetworkCards = len(c.awsClient.GetNetworkCards())
352357

358+
c.networkPolicyMode, err = getNetworkPolicyMode()
359+
if err != nil {
360+
return nil, err
361+
}
362+
353363
err = c.awsClient.FetchInstanceTypeLimits()
354364
if err != nil {
355365
log.Errorf("Failed to get ENI limits from file:vpc_ip_limits or EC2 for %s", c.awsClient.GetInstanceType())
@@ -1735,6 +1745,16 @@ func enablePodENI() bool {
17351745
return utils.GetBoolAsStringEnvVar(envEnablePodENI, false)
17361746
}
17371747

1748+
func getNetworkPolicyMode() (string, error) {
1749+
if value := os.Getenv(envNetworkPolicyMode); value != "" {
1750+
if utils.IsValidNetworkPolicyEnforcingMode(value) {
1751+
return value, nil
1752+
}
1753+
return "", errors.New("invalid Network policy mode, supported modes: none, strict, standard")
1754+
}
1755+
return defaultNetworkPolicyMode, nil
1756+
}
1757+
17381758
func usePrefixDelegation() bool {
17391759
return utils.GetBoolAsStringEnvVar(envEnableIpv4PrefixDelegation, false)
17401760
}

pkg/ipamd/rpc_handler.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -216,17 +216,18 @@ func (s *server) AddNetwork(ctx context.Context, in *rpc.AddNetworkRequest) (*rp
216216
}
217217
}
218218
resp := rpc.AddNetworkReply{
219-
Success: err == nil,
220-
IPv4Addr: ipv4Addr,
221-
IPv6Addr: ipv6Addr,
222-
DeviceNumber: int32(deviceNumber),
223-
UseExternalSNAT: useExternalSNAT,
224-
VPCv4CIDRs: pbVPCV4cidrs,
225-
VPCv6CIDRs: pbVPCV6cidrs,
226-
PodVlanId: int32(vlanID),
227-
PodENIMAC: branchENIMAC,
228-
PodENISubnetGW: podENISubnetGW,
229-
ParentIfIndex: int32(trunkENILinkIndex),
219+
Success: err == nil,
220+
IPv4Addr: ipv4Addr,
221+
IPv6Addr: ipv6Addr,
222+
DeviceNumber: int32(deviceNumber),
223+
UseExternalSNAT: useExternalSNAT,
224+
VPCv4CIDRs: pbVPCV4cidrs,
225+
VPCv6CIDRs: pbVPCV6cidrs,
226+
PodVlanId: int32(vlanID),
227+
PodENIMAC: branchENIMAC,
228+
PodENISubnetGW: podENISubnetGW,
229+
ParentIfIndex: int32(trunkENILinkIndex),
230+
NetworkPolicyMode: s.ipamContext.networkPolicyMode,
230231
}
231232

232233
log.Infof("Send AddNetworkReply: IPv4Addr: %s, IPv6Addr: %s, DeviceNumber: %d, err: %v", ipv4Addr, ipv6Addr, deviceNumber, err)

0 commit comments

Comments
 (0)