Skip to content

Commit

Permalink
Send pod name/ns to nodeagent (#2790)
Browse files Browse the repository at this point in the history
* Send pod name/ns to nodeagent

* minor nits
  • Loading branch information
jayanthvn authored Feb 28, 2024
1 parent dba87e6 commit 0a4c0d8
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 75 deletions.
31 changes: 31 additions & 0 deletions cmd/routed-eni-cni-plugin/cni.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,13 @@ import (
"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/cniutils"
"github.com/aws/amazon-vpc-cni-k8s/pkg/utils/logger"
pb "github.com/aws/amazon-vpc-cni-k8s/rpc"
"github.com/aws/amazon-vpc-cni-k8s/utils"
)

const ipamdAddress = "127.0.0.1:50051"

const npAgentAddress = "127.0.0.1:50052"

const dummyInterfacePrefix = "dummy"

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

if utils.IsStrictMode(r.NetworkPolicyMode) {
// Set up a connection to the network policy agent
npConn, err := grpcClient.Dial(npAgentAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Errorf("Failed to connect to network policy agent: %v", err)
return errors.Wrap(err, "add cmd: failed to connect to network policy agent backend server")
}
defer npConn.Close()

//Make a GRPC call for network policy agent
npc := rpcClient.NewNPBackendClient(npConn)

npr, err := npc.EnforceNpToPod(context.Background(),
&pb.EnforceNpRequest{
K8S_POD_NAME: string(k8sArgs.K8S_POD_NAME),
K8S_POD_NAMESPACE: string(k8sArgs.K8S_POD_NAMESPACE),
})

// No need to cleanup IP and network, kubelet will send delete.
if err != nil || !npr.Success {
log.Errorf("Failed to setup default network policy for Pod Name %s and NameSpace %s: GRPC returned - %v Network policy agent returned - %v",
string(k8sArgs.K8S_POD_NAME), string(k8sArgs.K8S_POD_NAMESPACE), err, npr)
return errors.New("add cmd: failed to setup network policy in strict mode")
}

log.Debugf("Network Policy agent returned Success : %v", npr.Success)
}

return cniTypes.PrintResult(result, conf.CNIVersion)
}

Expand Down
94 changes: 90 additions & 4 deletions cmd/routed-eni-cni-plugin/cni_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func TestCmdAdd(t *testing.T) {
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)

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

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

func TestCmdAddWithNPenabled(t *testing.T) {
ctrl, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork := setup(t)
defer ctrl.Finish()

stdinData, _ := json.Marshal(netConf)

cmdArgs := &skel.CmdArgs{ContainerID: containerID,
Netns: netNS,
IfName: ifName,
StdinData: stdinData}

mocksTypes.EXPECT().LoadArgs(gomock.Any(), gomock.Any()).Return(nil)

conn, _ := grpc.Dial(ipamdAddress, grpc.WithInsecure())

mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(conn, nil)
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)

npConn, _ := grpc.Dial(npAgentAddress, grpc.WithInsecure())

mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(npConn, nil)
mockNP := mock_rpc.NewMockNPBackendClient(ctrl)
mocksRPC.EXPECT().NewNPBackendClient(npConn).Return(mockNP)

addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "strict"}
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)

enforceNpReply := &rpc.EnforceNpReply{Success: true}
mockNP.EXPECT().EnforceNpToPod(gomock.Any(), gomock.Any()).Return(enforceNpReply, nil)

v4Addr := &net.IPNet{
IP: net.ParseIP(addNetworkReply.IPv4Addr),
Mask: net.IPv4Mask(255, 255, 255, 255),
}
mocksNetwork.EXPECT().SetupPodNetwork(gomock.Any(), cmdArgs.IfName, cmdArgs.Netns,
v4Addr, nil, int(addNetworkReply.DeviceNumber), gomock.Any(), gomock.Any()).Return(nil)

mocksTypes.EXPECT().PrintResult(gomock.Any(), gomock.Any()).Return(nil)

err := add(cmdArgs, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork)
assert.Nil(t, err)
}

func TestCmdAddWithNPenabledWithErr(t *testing.T) {
ctrl, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork := setup(t)
defer ctrl.Finish()

stdinData, _ := json.Marshal(netConf)

cmdArgs := &skel.CmdArgs{ContainerID: containerID,
Netns: netNS,
IfName: ifName,
StdinData: stdinData}

mocksTypes.EXPECT().LoadArgs(gomock.Any(), gomock.Any()).Return(nil)

conn, _ := grpc.Dial(ipamdAddress, grpc.WithInsecure())

mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(conn, nil)
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)

npConn, _ := grpc.Dial(npAgentAddress, grpc.WithInsecure())

mocksGRPC.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(npConn, nil)
mockNP := mock_rpc.NewMockNPBackendClient(ctrl)
mocksRPC.EXPECT().NewNPBackendClient(npConn).Return(mockNP)

addNetworkReply := &rpc.AddNetworkReply{Success: true, IPv4Addr: ipAddr, DeviceNumber: devNum, NetworkPolicyMode: "strict"}
mockC.EXPECT().AddNetwork(gomock.Any(), gomock.Any()).Return(addNetworkReply, nil)

enforceNpReply := &rpc.EnforceNpReply{Success: false}
mockNP.EXPECT().EnforceNpToPod(gomock.Any(), gomock.Any()).Return(enforceNpReply, errors.New("Error on EnforceNpReply"))

v4Addr := &net.IPNet{
IP: net.ParseIP(addNetworkReply.IPv4Addr),
Mask: net.IPv4Mask(255, 255, 255, 255),
}
mocksNetwork.EXPECT().SetupPodNetwork(gomock.Any(), cmdArgs.IfName, cmdArgs.Netns,
v4Addr, nil, int(addNetworkReply.DeviceNumber), gomock.Any(), gomock.Any()).Return(nil)

err := add(cmdArgs, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork)
assert.Error(t, err)
}

func TestCmdAddNetworkErr(t *testing.T) {
ctrl, mocksTypes, mocksGRPC, mocksRPC, mocksNetwork := setup(t)
defer ctrl.Finish()
Expand All @@ -129,7 +215,7 @@ func TestCmdAddNetworkErr(t *testing.T) {
mockC := mock_rpc.NewMockCNIBackendClient(ctrl)
mocksRPC.EXPECT().NewCNIBackendClient(conn).Return(mockC)

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

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

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

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

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

addr := &net.IPNet{
Expand Down
20 changes: 20 additions & 0 deletions pkg/ipamd/ipamd.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ const (
// aws error codes for insufficient IP address scenario
INSUFFICIENT_CIDR_BLOCKS = "InsufficientCidrBlocks"
INSUFFICIENT_FREE_IP_SUBNET = "InsufficientFreeAddressesInSubnet"

// envEnableNetworkPolicy is used to enable IPAMD/CNI to send pod create events to network policy agent.
envNetworkPolicyMode = "NETWORK_POLICY_ENFORCING_MODE"
defaultNetworkPolicyMode = "standard"
)

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

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

c.networkPolicyMode, err = getNetworkPolicyMode()
if err != nil {
return nil, err
}

err = c.awsClient.FetchInstanceTypeLimits()
if err != nil {
log.Errorf("Failed to get ENI limits from file:vpc_ip_limits or EC2 for %s", c.awsClient.GetInstanceType())
Expand Down Expand Up @@ -1735,6 +1745,16 @@ func enablePodENI() bool {
return utils.GetBoolAsStringEnvVar(envEnablePodENI, false)
}

func getNetworkPolicyMode() (string, error) {
if value := os.Getenv(envNetworkPolicyMode); value != "" {
if utils.IsValidNetworkPolicyEnforcingMode(value) {
return value, nil
}
return "", errors.New("invalid Network policy mode, supported modes: none, strict, standard")
}
return defaultNetworkPolicyMode, nil
}

func usePrefixDelegation() bool {
return utils.GetBoolAsStringEnvVar(envEnableIpv4PrefixDelegation, false)
}
Expand Down
23 changes: 12 additions & 11 deletions pkg/ipamd/rpc_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,18 @@ func (s *server) AddNetwork(ctx context.Context, in *rpc.AddNetworkRequest) (*rp
}
}
resp := rpc.AddNetworkReply{
Success: err == nil,
IPv4Addr: ipv4Addr,
IPv6Addr: ipv6Addr,
DeviceNumber: int32(deviceNumber),
UseExternalSNAT: useExternalSNAT,
VPCv4CIDRs: pbVPCV4cidrs,
VPCv6CIDRs: pbVPCV6cidrs,
PodVlanId: int32(vlanID),
PodENIMAC: branchENIMAC,
PodENISubnetGW: podENISubnetGW,
ParentIfIndex: int32(trunkENILinkIndex),
Success: err == nil,
IPv4Addr: ipv4Addr,
IPv6Addr: ipv6Addr,
DeviceNumber: int32(deviceNumber),
UseExternalSNAT: useExternalSNAT,
VPCv4CIDRs: pbVPCV4cidrs,
VPCv6CIDRs: pbVPCV6cidrs,
PodVlanId: int32(vlanID),
PodENIMAC: branchENIMAC,
PodENISubnetGW: podENISubnetGW,
ParentIfIndex: int32(trunkENILinkIndex),
NetworkPolicyMode: s.ipamContext.networkPolicyMode,
}

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

0 comments on commit 0a4c0d8

Please sign in to comment.