-
Notifications
You must be signed in to change notification settings - Fork 370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 'namespaces' in ACNP for enhanced peer namespace selection #1961
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1961 +/- ##
===========================================
- Coverage 65.40% 41.81% -23.59%
===========================================
Files 197 124 -73
Lines 17192 15367 -1825
===========================================
- Hits 11244 6426 -4818
- Misses 4778 8411 +3633
+ Partials 1170 530 -640
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this is the approach, K8s upstream NetworkPolicy will go?
Yes at least this is what we are proposing |
10e42b4
to
127f790
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some initial comments after taking a quick look
6c8d8bd
to
04916c1
Compare
@Dyanngg I don't recall if this was discussed previously, but does the PR handle stats aggregation when you create individual rules with their own appliedTo for different namespaces? From the user perspective there is a single rule and it should include stats from all the generated rules. Would be good to have an e2e test case for this as well. |
04916c1
to
2935000
Compare
This change should be compatible with rule stats because the controller aggregates rule stats based on rule name, and each per-namespace rule created for the original ingress/egress rule will share the same rule name. /cc @ceclinux |
pkg/apis/security/v1alpha1/types.go
Outdated
// is created for ClusterNetworkPolicy ingress/egress rules. | ||
// Cannot be set with NamespaceSelector. | ||
// +optional | ||
Namespaces *PeerNamespaces `json:"namespaces,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this option has been discussed before: do we consider adding a field SelfNamespace
directly? which is just another way to cooperate with PodSelector and cannot be set together with NamespaceSelector to avoid another sub-struct and the need to deal with the upgrade/deprecation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This particular option has not been discussed I believe, and I agree it might make upgrade a bit easier. For upstream ClusterNetworkPolicy proposal it does not make a big difference because those are new API types to be added anyways. If everyone like the SelfNamespace: bool
approach, I can make the change for this PR and propose the same thing upstream. I think it's perfectly okay if the upstream spec came out a bit different than what we merge in Antrea as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the PR based on k8s-sig-network upstream KEP comments. Instead of a bool
field, changed the Self
keyword to a NamespaceMatchType
for it to be more extensible, as well as keeping the old namespaceSelector semantics exactly as-is.
8016094
to
abb039b
Compare
60365d1
to
042b4a4
Compare
Codecov Report
@@ Coverage Diff @@
## main #1961 +/- ##
==========================================
- Coverage 61.63% 55.42% -6.22%
==========================================
Files 274 274
Lines 20673 20817 +144
==========================================
- Hits 12742 11537 -1205
- Misses 6593 8059 +1466
+ Partials 1338 1221 -117
Flags with carried forward coverage won't be shown. Click here to find out more.
|
/test-all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIts.
2bc2c50
to
0d4af93
Compare
klog.V(2).Infof("Processing Namespace %s ADD event, labels: %v", namespace.Name, namespace.Labels) | ||
affectedACNPs := n.filterPerNamespaceRuleACNPsByNSLabels(namespace.Labels) | ||
for cnpName := range affectedACNPs { | ||
if cnp, err := n.cnpLister.Get(cnpName); err == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the second question in #1961 (comment)?
Can it just enqueue the policy to notify it needs to be processed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I think I missed understood that comment. I thought you were suggesting we enqueue the NP which is already done. The problem is that simply enqueuing the internal NP is not enough... syncInternalNetworkPolicy
only updates the NP span, but for Namespace update events, we need the CNP to be re-processed because the cardinality of per-NS rules might have changed because of Namespace label updates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if using updateCNP
here would introduce some problems: the function was supposed to be called serially and with continuous state changes, but now it may be called concurrently and with some unexpected intermediate state.
For example, before the change it's only possible to receive:
update(A1, A2) => update(A2, A3)
After the change it's possible to receive:
update(A1, A2) => update(A3, A3) => update(A2, A3)
And update(A3, A3)
may be executed at the same as others.
In a corner case, it may add a deleted CNP back after deleteCNP
deletes it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think update(A3, A3) executed with update(A2, A3) will cause any unexpected behaviors. If you look at updateCNP()
, the old CNP is merely used to retrieve the key of the original internalNP, which in turn is only used to preserve span; in addition, the key of the original internalNP is the same as the new CNP, so the oldCNP spec is effectively worthless tbh...
Adding a deleted CNP back does not seem possible to me as well, since before we call update we use the cnpLister to check if the CNP corresponded to the internalNP is still 'alive'.
Nevertheless, for clarity I added a new reprocessCNP
func that does not involve update(CNP, CNP) and checks for internal NP existence before re-processing CNP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think adding a deleted CNP back is possible when the DELETE event is received and Delete(A3)
is executed between the existence check and update(A3, A3)
as there is no mutex to prevent it from happening. There are many yield points in update(A3, A3)
too that can increase the possibility.
Adding a mutex and internal NP existence check may avoid it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mutex and existence check has been added in the latest commit.
/test-all |
Signed-off-by: Yang Ding <[email protected]>
Signed-off-by: Yang Ding <[email protected]>
Signed-off-by: Yang Ding <[email protected]>
Signed-off-by: Yang Ding <[email protected]>
c1672a6
to
291ba89
Compare
/test-all |
Signed-off-by: Yang Ding <[email protected]>
/test-all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -2009,6 +2019,11 @@ spec: | |||
type: string | |||
matchLabels: | |||
x-kubernetes-preserve-unknown-fields: true | |||
namespaces: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any particular reason why we add this in the deprecated version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really... I guess it isn't necessary. This PR was opened before the security api group was deprecated, and the API change was meant for this version of ACNP resource.
The PR partially addresses #1941. It introduces a new
namespaces
field to ingress/egress peers for Antrea ClusterNetworkPolicy (in security/v1alpha1), while still keepingnamespaceSelector
as an optional field. For a given peer, only one ofnamespaces
ornamespaceSelector
can be specified.NamespacesSelector will have the exact same semantics as before.
Self
in peer.Namespaces, on the other hand, is a new special keyword to indicate that the correspondingpodSelector
should be evaluated from within the Namespace of the applied-to workload, for which the ingress/egress rule is currently affected. This enables policy writers to create per-Namespace rules. See #1941 for examples. Note: using ClusterGroups as appliedTo for per-Namespace rules is not yet supported.The implementation is as follows: if there is at least one per-namespace rule in Antrea ClusterNetworkPolicy, then the internal NetworkPolicy object created by the controller will have appliedTo set per-rule, no matter how the ACNP is defined. This is because the appliedTo group for a per-namespace rule will potentially be split into multiple internal rules, depending on the Namespace resolution result.
For cluster-scoped peers (peers whose namespace.match is not set to Self), the appliedTo for its rule will be set as the
spec.appliedTo
, orrule.appliedTo
, if the original ACNP is appliedTo-per-rule. For per-namespace peers, an internal rule will be created by each Namespace which its appliedTo resolves to, with appliedTo and peer for that rule set at Namespace scope.Taking the sample spec as an example:
Suppose there are 2 namespaces,
ns1
andns2
in the cluster. Then for the 2 ingress rules above, 3 internal rules will be created:Three individual appliedToGroups and three individual addressGroups will be created in this case.