Skip to content

Commit ba83940

Browse files
authored
[NPM] Caching ability for Pods and NS (#814)
* First pass at implementing pod cache * handling namedports in case of pod update * Correcting print error * Cleaning up pod cache update event. moving pod cache to nsMAP * Correcting namespace prefix * Adding in checks on protlists and Podips * changing some variable names * changing some variable names * Adding resource versions checks for Pod, NS and netpols * fixing some tests * changing ResourceVersion to uint64 and cleaning up oldpodobj references * rearranging hostneptol and correcting a UT failure * Fixing the hostnet pod UT * Addressing comments * fixing UT * Fixing UTs * correcting pod delete failure bug * Fixing clean up bug * Handling hostnet pods in Delete pod * Addressing comments and ficing a panic error
1 parent bfbd945 commit ba83940

File tree

10 files changed

+626
-197
lines changed

10 files changed

+626
-197
lines changed

.pipelines/npm/npm-conformance-tests.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,13 @@ jobs:
173173
chmod +x $(Pipeline.Workspace)/Test/e2e.test
174174
KUBERNETES_SERVICE_HOST="$FQDN" KUBERNETES_SERVICE_PORT=443 $(Pipeline.Workspace)/Test/e2e.test --provider=local --ginkgo.focus="NetworkPolicy" --ginkgo.skip="SCTP" --kubeconfig=./kubeconfig
175175
displayName: "Run Test Suite"
176+
- bash: |
177+
ls -al
178+
npmPodList=`ksgp | grep npm | awk '{print $1}'`
179+
mkdir -p $(System.DefaultWorkingDirectory)/npmLogs
180+
for npm in $npmPodList; do kubectl logs -n kube-system $npm > $(System.DefaultWorkingDirectory)/npmLogs/$npm ;done
181+
displayName: "Gather NPM Logs"
182+
- publish: $(System.DefaultWorkingDirectory)/npmLogs
176183

177184
- job: Clean_up
178185
displayName: "Cleanup"

npm/namespace.go

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ import (
99
"github.com/Azure/azure-container-networking/npm/ipsm"
1010
"github.com/Azure/azure-container-networking/npm/iptm"
1111
"github.com/Azure/azure-container-networking/npm/util"
12-
"k8s.io/apimachinery/pkg/types"
1312

1413
corev1 "k8s.io/api/core/v1"
1514
networkingv1 "k8s.io/api/networking/v1"
1615
)
1716

1817
type namespace struct {
19-
name string
20-
labelsMap map[string]string
21-
setMap map[string]string
22-
podMap map[types.UID]*corev1.Pod
23-
rawNpMap map[string]*networkingv1.NetworkPolicy
24-
processedNpMap map[string]*networkingv1.NetworkPolicy
25-
ipsMgr *ipsm.IpsetManager
26-
iptMgr *iptm.IptablesManager
18+
name string
19+
labelsMap map[string]string // NameSpace labels
20+
setMap map[string]string
21+
podMap map[string]*npmPod // Key is PodUID
22+
rawNpMap map[string]*networkingv1.NetworkPolicy
23+
processedNpMap map[string]*networkingv1.NetworkPolicy
24+
ipsMgr *ipsm.IpsetManager
25+
iptMgr *iptm.IptablesManager
26+
resourceVersion uint64 // NameSpace ResourceVersion
2727
}
2828

2929
// newNS constructs a new namespace object.
@@ -32,16 +32,24 @@ func newNs(name string) (*namespace, error) {
3232
name: name,
3333
labelsMap: make(map[string]string),
3434
setMap: make(map[string]string),
35-
podMap: make(map[types.UID]*corev1.Pod),
35+
podMap: make(map[string]*npmPod),
3636
rawNpMap: make(map[string]*networkingv1.NetworkPolicy),
3737
processedNpMap: make(map[string]*networkingv1.NetworkPolicy),
3838
ipsMgr: ipsm.NewIpsetManager(),
3939
iptMgr: iptm.NewIptablesManager(),
40+
// resource version is converted to uint64
41+
// so make sure it is initialized to "0"
42+
resourceVersion: 0,
4043
}
4144

4245
return ns, nil
4346
}
4447

48+
// setResourceVersion setter func for RV
49+
func setResourceVersion(nsObj *namespace, rv string) {
50+
nsObj.resourceVersion = util.ParseResourceVersion(rv)
51+
}
52+
4553
func isSystemNs(nsObj *corev1.Namespace) bool {
4654
return nsObj.ObjectMeta.Name == util.KubeSystemFlag
4755
}
@@ -56,10 +64,22 @@ func isInvalidNamespaceUpdate(oldNsObj, newNsObj *corev1.Namespace) (isInvalidUp
5664
}
5765

5866
func (ns *namespace) policyExists(npObj *networkingv1.NetworkPolicy) bool {
59-
if np, exists := ns.rawNpMap[npObj.ObjectMeta.Name]; exists {
60-
if isSamePolicy(np, npObj) {
61-
return true
62-
}
67+
np, exists := ns.rawNpMap[npObj.ObjectMeta.Name]
68+
if !exists {
69+
return false
70+
}
71+
72+
if !util.CompareResourceVersions(np.ObjectMeta.ResourceVersion, npObj.ObjectMeta.ResourceVersion) {
73+
log.Logf("Cached Network Policy has larger ResourceVersion number than new Obj. Name: %s Cached RV: %d New RV: %d\n",
74+
npObj.ObjectMeta.Name,
75+
np.ObjectMeta.ResourceVersion,
76+
npObj.ObjectMeta.ResourceVersion,
77+
)
78+
return true
79+
}
80+
81+
if isSamePolicy(np, npObj) {
82+
return true
6383
}
6484

6585
return false
@@ -103,7 +123,7 @@ func (npMgr *NetworkPolicyManager) UninitAllNsList() error {
103123
func (npMgr *NetworkPolicyManager) AddNamespace(nsObj *corev1.Namespace) error {
104124
var err error
105125

106-
nsName, nsLabel := "ns-"+nsObj.ObjectMeta.Name, nsObj.ObjectMeta.Labels
126+
nsName, nsLabel := util.GetNSNameWithPrefix(nsObj.ObjectMeta.Name), nsObj.ObjectMeta.Labels
107127
log.Logf("NAMESPACE CREATING: [%s/%v]", nsName, nsLabel)
108128

109129
ipsMgr := npMgr.nsMap[util.KubeAllNamespacesFlag].ipsMgr
@@ -121,14 +141,14 @@ func (npMgr *NetworkPolicyManager) AddNamespace(nsObj *corev1.Namespace) error {
121141
// Add the namespace to its label's ipset list.
122142
nsLabels := nsObj.ObjectMeta.Labels
123143
for nsLabelKey, nsLabelVal := range nsLabels {
124-
labelKey := "ns-" + nsLabelKey
144+
labelKey := util.GetNSNameWithPrefix(nsLabelKey)
125145
log.Logf("Adding namespace %s to ipset list %s", nsName, labelKey)
126146
if err = ipsMgr.AddToList(labelKey, nsName); err != nil {
127147
log.Errorf("Error: failed to add namespace %s to ipset list %s", nsName, labelKey)
128148
return err
129149
}
130150

131-
label := "ns-" + nsLabelKey + ":" + nsLabelVal
151+
label := util.GetNSNameWithPrefix(nsLabelKey + ":" + nsLabelVal)
132152
log.Logf("Adding namespace %s to ipset list %s", nsName, label)
133153
if err = ipsMgr.AddToList(label, nsName); err != nil {
134154
log.Errorf("Error: failed to add namespace %s to ipset list %s", nsName, label)
@@ -140,6 +160,7 @@ func (npMgr *NetworkPolicyManager) AddNamespace(nsObj *corev1.Namespace) error {
140160
if err != nil {
141161
log.Errorf("Error: failed to create namespace %s", nsName)
142162
}
163+
setResourceVersion(ns, nsObj.GetObjectMeta().GetResourceVersion())
143164

144165
// Append all labels to the cache NS obj
145166
ns.labelsMap = util.AppendMap(ns.labelsMap, nsLabel)
@@ -155,8 +176,8 @@ func (npMgr *NetworkPolicyManager) UpdateNamespace(oldNsObj *corev1.Namespace, n
155176
}
156177

157178
var err error
158-
oldNsNs, oldNsLabel := "ns-"+oldNsObj.ObjectMeta.Name, oldNsObj.ObjectMeta.Labels
159-
newNsNs, newNsLabel := "ns-"+newNsObj.ObjectMeta.Name, newNsObj.ObjectMeta.Labels
179+
oldNsNs, oldNsLabel := util.GetNSNameWithPrefix(oldNsObj.ObjectMeta.Name), oldNsObj.ObjectMeta.Labels
180+
newNsNs, newNsLabel := util.GetNSNameWithPrefix(newNsObj.ObjectMeta.Name), newNsObj.ObjectMeta.Labels
160181
log.Logf(
161182
"NAMESPACE UPDATING:\n old namespace: [%s/%v]\n new namespace: [%s/%v]",
162183
oldNsNs, oldNsLabel, newNsNs, newNsLabel,
@@ -189,6 +210,16 @@ func (npMgr *NetworkPolicyManager) UpdateNamespace(oldNsObj *corev1.Namespace, n
189210
return nil
190211
}
191212

213+
newRv := util.ParseResourceVersion(newNsObj.ObjectMeta.ResourceVersion)
214+
if !util.CompareUintResourceVersions(curNsObj.resourceVersion, newRv) {
215+
log.Logf("Cached NameSpace has larger ResourceVersion number than new Obj. NameSpace: %s Cached RV: %d New RV:\n",
216+
oldNsNs,
217+
curNsObj.resourceVersion,
218+
newRv,
219+
)
220+
return nil
221+
}
222+
192223
//if no change in labels then return
193224
if reflect.DeepEqual(curNsObj.labelsMap, newNsLabel) {
194225
log.Logf(
@@ -199,45 +230,32 @@ func (npMgr *NetworkPolicyManager) UpdateNamespace(oldNsObj *corev1.Namespace, n
199230
}
200231

201232
//If the Namespace is not deleted, delete removed labels and create new labels
202-
toAddNsLabels, toDeleteNsLabels := util.CompareMapDiff(curNsObj.labelsMap, newNsLabel)
233+
addToIPSets, deleteFromIPSets := util.GetIPSetListCompareLabels(curNsObj.labelsMap, newNsLabel)
203234

204235
// Delete the namespace from its label's ipset list.
205236
ipsMgr := npMgr.nsMap[util.KubeAllNamespacesFlag].ipsMgr
206-
for nsLabelKey, nsLabelVal := range toDeleteNsLabels {
207-
labelKey := "ns-" + nsLabelKey
237+
for _, nsLabelVal := range deleteFromIPSets {
238+
labelKey := util.GetNSNameWithPrefix(nsLabelVal)
208239
log.Logf("Deleting namespace %s from ipset list %s", oldNsNs, labelKey)
209240
if err = ipsMgr.DeleteFromList(labelKey, oldNsNs); err != nil {
210241
log.Errorf("Error: failed to delete namespace %s from ipset list %s", oldNsNs, labelKey)
211242
return err
212243
}
213-
214-
label := "ns-" + nsLabelKey + ":" + nsLabelVal
215-
log.Logf("Deleting namespace %s from ipset list %s", oldNsNs, label)
216-
if err = ipsMgr.DeleteFromList(label, oldNsNs); err != nil {
217-
log.Errorf("Error: failed to delete namespace %s from ipset list %s", oldNsNs, label)
218-
return err
219-
}
220244
}
221245

222246
// Add the namespace to its label's ipset list.
223-
for nsLabelKey, nsLabelVal := range toAddNsLabels {
224-
labelKey := "ns-" + nsLabelKey
247+
for _, nsLabelVal := range addToIPSets {
248+
labelKey := util.GetNSNameWithPrefix(nsLabelVal)
225249
log.Logf("Adding namespace %s to ipset list %s", oldNsNs, labelKey)
226250
if err = ipsMgr.AddToList(labelKey, oldNsNs); err != nil {
227251
log.Errorf("Error: failed to add namespace %s to ipset list %s", oldNsNs, labelKey)
228252
return err
229253
}
230-
231-
label := "ns-" + nsLabelKey + ":" + nsLabelVal
232-
log.Logf("Adding namespace %s to ipset list %s", oldNsNs, label)
233-
if err = ipsMgr.AddToList(label, oldNsNs); err != nil {
234-
log.Errorf("Error: failed to add namespace %s to ipset list %s", oldNsNs, label)
235-
return err
236-
}
237254
}
238255

239256
// Append all labels to the cache NS obj
240257
curNsObj.labelsMap = util.ClearAndAppendMap(curNsObj.labelsMap, newNsLabel)
258+
setResourceVersion(curNsObj, newNsObj.GetObjectMeta().GetResourceVersion())
241259
npMgr.nsMap[newNsNs] = curNsObj
242260

243261
return nil
@@ -247,26 +265,27 @@ func (npMgr *NetworkPolicyManager) UpdateNamespace(oldNsObj *corev1.Namespace, n
247265
func (npMgr *NetworkPolicyManager) DeleteNamespace(nsObj *corev1.Namespace) error {
248266
var err error
249267

250-
nsName, nsLabel := "ns-"+nsObj.ObjectMeta.Name, nsObj.ObjectMeta.Labels
268+
nsName, nsLabel := util.GetNSNameWithPrefix(nsObj.ObjectMeta.Name), nsObj.ObjectMeta.Labels
251269
log.Logf("NAMESPACE DELETING: [%s/%v]", nsName, nsLabel)
252270

253-
_, exists := npMgr.nsMap[nsName]
271+
cachedNsObj, exists := npMgr.nsMap[nsName]
254272
if !exists {
255273
return nil
256274
}
257275

276+
log.Logf("NAMESPACE DELETING cached labels: [%s/%v]", nsName, cachedNsObj.labelsMap)
258277
// Delete the namespace from its label's ipset list.
259278
ipsMgr := npMgr.nsMap[util.KubeAllNamespacesFlag].ipsMgr
260-
nsLabels := nsObj.ObjectMeta.Labels
279+
nsLabels := cachedNsObj.labelsMap
261280
for nsLabelKey, nsLabelVal := range nsLabels {
262-
labelKey := "ns-" + nsLabelKey
281+
labelKey := util.GetNSNameWithPrefix(nsLabelKey)
263282
log.Logf("Deleting namespace %s from ipset list %s", nsName, labelKey)
264283
if err = ipsMgr.DeleteFromList(labelKey, nsName); err != nil {
265284
log.Errorf("Error: failed to delete namespace %s from ipset list %s", nsName, labelKey)
266285
return err
267286
}
268287

269-
label := "ns-" + nsLabelKey + ":" + nsLabelVal
288+
label := util.GetNSNameWithPrefix(nsLabelKey + ":" + nsLabelVal)
270289
log.Logf("Deleting namespace %s from ipset list %s", nsName, label)
271290
if err = ipsMgr.DeleteFromList(label, nsName); err != nil {
272291
log.Errorf("Error: failed to delete namespace %s from ipset list %s", nsName, label)

npm/namespace_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1717
)
1818

19-
func TestnewNs(t *testing.T) {
19+
func TestNewNs(t *testing.T) {
2020
if _, err := newNs("test"); err != nil {
2121
t.Errorf("TestnewNs failed @ newNs")
2222
}
@@ -165,6 +165,7 @@ func TestAddNamespaceLabel(t *testing.T) {
165165
Labels: map[string]string{
166166
"app": "old-test-namespace",
167167
},
168+
ResourceVersion: "0",
168169
},
169170
}
170171

@@ -175,6 +176,8 @@ func TestAddNamespaceLabel(t *testing.T) {
175176
"app": "old-test-namespace",
176177
"update": "true",
177178
},
179+
180+
ResourceVersion: "1",
178181
},
179182
}
180183

@@ -225,6 +228,7 @@ func TestDeleteandUpdateNamespaceLabel(t *testing.T) {
225228
"update": "true",
226229
"group": "test",
227230
},
231+
ResourceVersion: "0",
228232
},
229233
}
230234

@@ -235,6 +239,7 @@ func TestDeleteandUpdateNamespaceLabel(t *testing.T) {
235239
"app": "old-test-namespace",
236240
"update": "false",
237241
},
242+
ResourceVersion: "1",
238243
},
239244
}
240245

npm/npm.go

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ type NetworkPolicyManager struct {
5050

5151
nodeName string
5252
nsMap map[string]*namespace
53-
podMap map[string]string // Key: Pod uuid, Value: PodIp
5453
isAzureNpmChainCreated bool
5554
isSafeToCleanUpAzureNpmChain bool
5655

@@ -118,14 +117,13 @@ func (npMgr *NetworkPolicyManager) SendClusterMetrics() {
118117
for {
119118
<-heartbeat
120119
npMgr.Lock()
121-
podCount.Value = float64(len(npMgr.podMap))
120+
podCount.Value = 0
122121
//Reducing one to remove all-namespaces ns obj
123122
nsCount.Value = float64(len(npMgr.nsMap) - 1)
124-
nwPolCount := 0
125123
for _, ns := range npMgr.nsMap {
126-
nwPolCount = nwPolCount + len(ns.rawNpMap)
124+
nwPolicyCount.Value += float64(len(ns.rawNpMap))
125+
podCount.Value += float64(len(ns.podMap))
127126
}
128-
nwPolicyCount.Value = float64(nwPolCount)
129127
npMgr.Unlock()
130128

131129
metrics.SendMetric(podCount)
@@ -234,7 +232,6 @@ func NewNetworkPolicyManager(clientset *kubernetes.Clientset, informerFactory in
234232
npInformer: npInformer,
235233
nodeName: os.Getenv("HOSTNAME"),
236234
nsMap: make(map[string]*namespace),
237-
podMap: make(map[string]string),
238235
isAzureNpmChainCreated: false,
239236
isSafeToCleanUpAzureNpmChain: false,
240237
clusterState: telemetry.ClusterState{
@@ -251,7 +248,7 @@ func NewNetworkPolicyManager(clientset *kubernetes.Clientset, informerFactory in
251248
npMgr.nsMap[util.KubeAllNamespacesFlag] = allNs
252249

253250
// Create ipset for the namespace.
254-
kubeSystemNs := "ns-" + util.KubeSystemFlag
251+
kubeSystemNs := util.GetNSNameWithPrefix(util.KubeSystemFlag)
255252
if err := allNs.ipsMgr.CreateSet(kubeSystemNs, append([]string{util.IpsetNetHashFlag})); err != nil {
256253
metrics.SendErrorLogAndMetric(util.NpmID, "Error: failed to create ipset for namespace %s.", kubeSystemNs)
257254
}
@@ -269,19 +266,14 @@ func NewNetworkPolicyManager(clientset *kubernetes.Clientset, informerFactory in
269266
npMgr.AddPod(podObj)
270267
npMgr.Unlock()
271268
},
272-
UpdateFunc: func(old, new interface{}) {
273-
oldPodObj, ok := old.(*corev1.Pod)
274-
if !ok {
275-
metrics.SendErrorLogAndMetric(util.NpmID, "UPDATE Pod: Received unexpected old object type: %v", oldPodObj)
276-
return
277-
}
269+
UpdateFunc: func(_, new interface{}) {
278270
newPodObj, ok := new.(*corev1.Pod)
279271
if !ok {
280272
metrics.SendErrorLogAndMetric(util.NpmID, "UPDATE Pod: Received unexpected new object type: %v", newPodObj)
281273
return
282274
}
283275
npMgr.Lock()
284-
npMgr.UpdatePod(oldPodObj, newPodObj)
276+
npMgr.UpdatePod(newPodObj)
285277
npMgr.Unlock()
286278
},
287279
DeleteFunc: func(obj interface{}) {

npm/nwpolicy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (npMgr *NetworkPolicyManager) AddNetworkPolicy(npObj *networkingv1.NetworkP
3333
err error
3434
ns *namespace
3535
exists bool
36-
npNs = "ns-" + npObj.ObjectMeta.Namespace
36+
npNs = util.GetNSNameWithPrefix(npObj.ObjectMeta.Namespace)
3737
npName = npObj.ObjectMeta.Name
3838
allNs = npMgr.nsMap[util.KubeAllNamespacesFlag]
3939
timer = metrics.StartNewTimer()
@@ -153,7 +153,7 @@ func (npMgr *NetworkPolicyManager) DeleteNetworkPolicy(npObj *networkingv1.Netwo
153153
allNs = npMgr.nsMap[util.KubeAllNamespacesFlag]
154154
)
155155

156-
npNs, npName := "ns-"+npObj.ObjectMeta.Namespace, npObj.ObjectMeta.Name
156+
npNs, npName := util.GetNSNameWithPrefix(npObj.ObjectMeta.Namespace), npObj.ObjectMeta.Name
157157
log.Logf("NETWORK POLICY DELETING: Namespace: %s, Name:%s", npNs, npName)
158158

159159
var exists bool

0 commit comments

Comments
 (0)