Skip to content

Commit a4d3382

Browse files
committed
Add more configuration flexibility to Egress for user
Added an immutable FailurePolicy field to the Egress spec. If this field is set to "NodeSNAT" then if the egress node is not available due to any reason then the packet transfer or we can say the traffic will go via normal Node SNAT, while in the second case where this field is set to "Drop", and if egress node is not available packet won't go out and traffic will be stuck because of unavailability of egress node. Signed-off-by: Pulkit Jain <[email protected]>
1 parent eb7ce24 commit a4d3382

File tree

12 files changed

+116
-30
lines changed

12 files changed

+116
-30
lines changed

build/charts/antrea/crds/egress.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ spec:
2020
type: object
2121
required:
2222
- appliedTo
23+
- failurePolicy
2324
oneOf:
2425
- anyOf:
2526
- required:
@@ -118,6 +119,9 @@ spec:
118119
type: string
119120
burst:
120121
type: string
122+
failurePolicy:
123+
type: string
124+
enum: ['Drop', 'NodeSNAT']
121125
status:
122126
type: object
123127
properties:

build/yamls/antrea-aks.yml

+4
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ spec:
14141414
type: object
14151415
required:
14161416
- appliedTo
1417+
- failurePolicy
14171418
oneOf:
14181419
- anyOf:
14191420
- required:
@@ -1512,6 +1513,9 @@ spec:
15121513
type: string
15131514
burst:
15141515
type: string
1516+
failurePolicy:
1517+
type: string
1518+
enum: ['Drop', 'NodeSNAT']
15151519
status:
15161520
type: object
15171521
properties:

build/yamls/antrea-crds.yml

+4
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,7 @@ spec:
14031403
type: object
14041404
required:
14051405
- appliedTo
1406+
- failurePolicy
14061407
oneOf:
14071408
- anyOf:
14081409
- required:
@@ -1501,6 +1502,9 @@ spec:
15011502
type: string
15021503
burst:
15031504
type: string
1505+
failurePolicy:
1506+
type: string
1507+
enum: ['Drop', 'NodeSNAT']
15041508
status:
15051509
type: object
15061510
properties:

build/yamls/antrea-eks.yml

+4
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ spec:
14141414
type: object
14151415
required:
14161416
- appliedTo
1417+
- failurePolicy
14171418
oneOf:
14181419
- anyOf:
14191420
- required:
@@ -1512,6 +1513,9 @@ spec:
15121513
type: string
15131514
burst:
15141515
type: string
1516+
failurePolicy:
1517+
type: string
1518+
enum: ['Drop', 'NodeSNAT']
15151519
status:
15161520
type: object
15171521
properties:

build/yamls/antrea-gke.yml

+4
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ spec:
14141414
type: object
14151415
required:
14161416
- appliedTo
1417+
- failurePolicy
14171418
oneOf:
14181419
- anyOf:
14191420
- required:
@@ -1512,6 +1513,9 @@ spec:
15121513
type: string
15131514
burst:
15141515
type: string
1516+
failurePolicy:
1517+
type: string
1518+
enum: ['Drop', 'NodeSNAT']
15151519
status:
15161520
type: object
15171521
properties:

build/yamls/antrea-ipsec.yml

+4
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ spec:
14141414
type: object
14151415
required:
14161416
- appliedTo
1417+
- failurePolicy
14171418
oneOf:
14181419
- anyOf:
14191420
- required:
@@ -1512,6 +1513,9 @@ spec:
15121513
type: string
15131514
burst:
15141515
type: string
1516+
failurePolicy:
1517+
type: string
1518+
enum: ['Drop', 'NodeSNAT']
15151519
status:
15161520
type: object
15171521
properties:

build/yamls/antrea.yml

+4
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ spec:
14141414
type: object
14151415
required:
14161416
- appliedTo
1417+
- failurePolicy
14171418
oneOf:
14181419
- anyOf:
14191420
- required:
@@ -1512,6 +1513,9 @@ spec:
15121513
type: string
15131514
burst:
15141515
type: string
1516+
failurePolicy:
1517+
type: string
1518+
enum: ['Drop', 'NodeSNAT']
15151519
status:
15161520
type: object
15171521
properties:

pkg/agent/controller/egress/egress_controller.go

+39-27
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ var emptyWatch = watch.NewEmptyWatch()
8888

8989
var newIPAssigner = ipassigner.NewIPAssigner
9090

91+
var egressNodeAvailability = hasEgressNode
92+
9193
// egressState keeps the actual state of an Egress that has been realized.
9294
type egressState struct {
9395
// The actual egress IP of the Egress. If it's different from the desired IP, there is an update to EgressIP, and we
@@ -989,6 +991,12 @@ func (c *EgressController) updateEgressStatus(egress *crdv1b1.Egress, egressIP s
989991
return nil
990992
}
991993

994+
func hasEgressNode(egress *crdv1b1.Egress) bool {
995+
if egress.Status.EgressNode == "" {
996+
return false
997+
}
998+
return true
999+
}
9921000
func (c *EgressController) syncEgress(egressName string) error {
9931001
startTime := time.Now()
9941002
defer func() {
@@ -1024,6 +1032,7 @@ func (c *EgressController) syncEgress(egressName string) error {
10241032
desiredNode = egressNode
10251033
} else {
10261034
scheduleErr = err
1035+
desiredEgressIP = egress.Spec.EgressIP
10271036
}
10281037
} else {
10291038
desiredEgressIP = egress.Spec.EgressIP
@@ -1118,39 +1127,42 @@ func (c *EgressController) syncEgress(egressName string) error {
11181127
}()
11191128

11201129
egressIP := net.ParseIP(eState.egressIP)
1121-
// Install SNAT flows for desired Pods.
1122-
for pod := range pods {
1123-
eState.pods.Insert(pod)
1124-
stalePods.Delete(pod)
1130+
failurePolicy := egress.Spec.FailurePolicy
1131+
if failurePolicy == crdv1b1.FailurePolicyDrop || egressNodeAvailability(egress) {
1132+
// Install SNAT flows for desired Pods.
1133+
for pod := range pods {
1134+
eState.pods.Insert(pod)
1135+
stalePods.Delete(pod)
1136+
1137+
// If the Egress is not the effective one for the Pod, do nothing.
1138+
if !c.bindPodEgress(pod, egressName) {
1139+
continue
1140+
}
11251141

1126-
// If the Egress is not the effective one for the Pod, do nothing.
1127-
if !c.bindPodEgress(pod, egressName) {
1128-
continue
1129-
}
1142+
// Get the Pod's openflow port.
1143+
parts := strings.Split(pod, "/")
1144+
podNamespace, podName := parts[0], parts[1]
1145+
ifaces := c.ifaceStore.GetContainerInterfacesByPod(podName, podNamespace)
1146+
if len(ifaces) == 0 {
1147+
klog.Infof("Interfaces of Pod %s/%s not found", podNamespace, podName)
1148+
continue
1149+
}
11301150

1131-
// Get the Pod's openflow port.
1132-
parts := strings.Split(pod, "/")
1133-
podNamespace, podName := parts[0], parts[1]
1134-
ifaces := c.ifaceStore.GetContainerInterfacesByPod(podName, podNamespace)
1135-
if len(ifaces) == 0 {
1136-
klog.Infof("Interfaces of Pod %s/%s not found", podNamespace, podName)
1137-
continue
1151+
ofPort := ifaces[0].OFPort
1152+
if eState.ofPorts.Has(ofPort) {
1153+
staleOFPorts.Delete(ofPort)
1154+
continue
1155+
}
1156+
if err := c.ofClient.InstallPodSNATFlows(uint32(ofPort), egressIP, mark); err != nil {
1157+
return err
1158+
}
1159+
eState.ofPorts.Insert(ofPort)
11381160
}
11391161

1140-
ofPort := ifaces[0].OFPort
1141-
if eState.ofPorts.Has(ofPort) {
1142-
staleOFPorts.Delete(ofPort)
1143-
continue
1144-
}
1145-
if err := c.ofClient.InstallPodSNATFlows(uint32(ofPort), egressIP, mark); err != nil {
1162+
// Uninstall SNAT flows for stale Pods.
1163+
if err := c.uninstallPodFlows(egressName, eState, staleOFPorts, stalePods); err != nil {
11461164
return err
11471165
}
1148-
eState.ofPorts.Insert(ofPort)
1149-
}
1150-
1151-
// Uninstall SNAT flows for stale Pods.
1152-
if err := c.uninstallPodFlows(egressName, eState, staleOFPorts, stalePods); err != nil {
1153-
return err
11541166
}
11551167
return nil
11561168
}

pkg/agent/controller/egress/egress_controller_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,15 @@ func TestSyncEgress(t *testing.T) {
11011101
},
11021102
},
11031103
}
1104+
1105+
egressNodeAvailability = func(egress *crdv1b1.Egress) bool {
1106+
return true
1107+
}
1108+
1109+
defer func() {
1110+
egressNodeAvailability = hasEgressNode
1111+
}()
1112+
11041113
for _, tt := range tests {
11051114
t.Run(tt.name, func(t *testing.T) {
11061115
initObjects := []runtime.Object{tt.existingEgress}
@@ -1195,6 +1204,15 @@ func TestPodUpdateShouldSyncEgress(t *testing.T) {
11951204
{Pod: &cpv1b2.PodReference{Name: "pendingPod", Namespace: "ns1"}},
11961205
},
11971206
}
1207+
1208+
egressNodeAvailability = func(egress *crdv1b1.Egress) bool {
1209+
return true
1210+
}
1211+
1212+
defer func() {
1213+
egressNodeAvailability = hasEgressNode
1214+
}()
1215+
11981216
c := newFakeController(t, []runtime.Object{egress})
11991217
stopCh := make(chan struct{})
12001218
defer close(stopCh)
@@ -1327,6 +1345,15 @@ func TestSyncOverlappingEgress(t *testing.T) {
13271345
{Pod: &cpv1b2.PodReference{Name: "pod4", Namespace: "ns4"}},
13281346
},
13291347
}
1348+
1349+
egressNodeAvailability = func(egress *crdv1b1.Egress) bool {
1350+
return true
1351+
}
1352+
1353+
defer func() {
1354+
egressNodeAvailability = hasEgressNode
1355+
}()
1356+
13301357
c := newFakeController(t, []runtime.Object{egress1, egress2, egress3})
13311358
stopCh := make(chan struct{})
13321359
defer close(stopCh)

pkg/apis/crd/v1beta1/types.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -1004,9 +1004,17 @@ type EgressSpec struct {
10041004
// Cannot be set with ExternalIPPool.
10051005
ExternalIPPools []string `json:"externalIPPools,omitempty"`
10061006
// Bandwidth specifies the rate limit of north-south egress traffic of this Egress.
1007-
Bandwidth *Bandwidth `json:"bandwidth,omitempty"`
1007+
Bandwidth *Bandwidth `json:"bandwidth,omitempty"`
1008+
FailurePolicy FailurePolicyType `json:"failurePolicy"`
10081009
}
10091010

1011+
type FailurePolicyType string
1012+
1013+
const (
1014+
FailurePolicyDrop FailurePolicyType = "Drop"
1015+
FailurePolicyNodeSNAT FailurePolicyType = "NodeSNAT"
1016+
)
1017+
10101018
type Bandwidth struct {
10111019
// Rate specifies the maximum traffic rate. e.g. 300k, 10M
10121020
Rate string `json:"rate"`

pkg/apiserver/openapi/zz_generated.openapi.go

+9-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/egress/validate.go

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func (c *EgressController) ValidateEgress(review *admv1.AdmissionReview) *admv1.
6565
return false, fmt.Sprintf("Burst %s in Egress %s is invalid: %v", newEgress.Spec.Bandwidth.Burst, newEgress.Name, err)
6666
}
6767
}
68+
// Don't Allow if the FailurePolicy is updated.
69+
if oldEgress.Spec.FailurePolicy != "" && newEgress.Spec.FailurePolicy != oldEgress.Spec.FailurePolicy {
70+
return false, fmt.Sprint("Field FailurePolicy in Egress Spec is immutable. If you want to update kindly delete and re apply Egress.")
71+
}
6872
// Allow it if EgressIP and ExternalIPPool don't change.
6973
if newEgress.Spec.EgressIP == oldEgress.Spec.EgressIP && newEgress.Spec.ExternalIPPool == oldEgress.Spec.ExternalIPPool {
7074
return true, ""

0 commit comments

Comments
 (0)