-
Notifications
You must be signed in to change notification settings - Fork 376
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 support for Namespaced Group CRD #2438
Conversation
4077845
to
351f7b0
Compare
Codecov Report
@@ Coverage Diff @@
## main #2438 +/- ##
==========================================
+ Coverage 64.72% 67.17% +2.45%
==========================================
Files 297 298 +1
Lines 44988 45940 +952
==========================================
+ Hits 29119 30862 +1743
+ Misses 13536 12690 -846
- Partials 2333 2388 +55
*This pull request uses carry forward flags. Click here to find out more.
|
c506c6c
to
6bceb6b
Compare
Namespace: "", | ||
Name: "acnpA", | ||
}, | ||
out: "AntreaClusterNetworkPolicy:acnpA", |
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.
Just curious: why do we have a space between resource type and name for cg/group ToString(), but not for ANP?
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.
you mean the difference in NP.ToString() and Group/CG.ToTypedString() ?
The ToTypedString for groups is introduced for logging and other purposes. However the ToString for both objects is the same( no whitespace)
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 asked the same question as @Dyanngg above
4eee880
to
5002f59
Compare
Switching milestone to v1.4 as I see this PR is not up-to-date and still needs to go through more reviews |
16d4cb7
to
aa49d6e
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.
2 high level questions:
- Does it make sense to allow IPBlocks for (namespaced) Groups?
- A similar question for child Groups: what if I select child Groups defined in a different Namespace?
Namespace: "", | ||
Name: "acnpA", | ||
}, | ||
out: "AntreaClusterNetworkPolicy:acnpA", |
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 asked the same question as @Dyanngg above
I don't want to, but K8s NetworkPolicies allow IPBlocks so for parity I kept it as is..
the childGroup only accepts string, so it will be considered as a Name of the group and looked for in its own namespace. So even if childGroup child-0 exists in ns2, it should not be added as part of ns1/parentGroup-0 which references childGroup ns1/child-0. |
I meant Group in ANP appliedTo that have Namespace selector (but empty Namespace selector means all Namespaces according to the PR). I think the PR doesn't support ANP to use ClusterGroup. |
Ok. The strategy works for me too. But I feel sharing Group for address and appliedTo is not very useful, so we may decide based on implementation complexity. |
This makes sense to me, it is possible to implement in this way. I do have some questions:
|
I think documenting it is good enough. It should be a common sense that a namespace scoped policy can not apply to other namespaces.
I don't think of an use case yet given that validating webhook should already reject "unrealizable" policies, we could discuss it separately when it's needed. |
@tnqn @qiyueyao sorry I'm late to the party. I'm a bit worried about the semantical meaning of Group with namespaceSelector in appliedTo based on your suggestion (or at least want some clarification). The ClusterRole + RoleBinding example from K8s makes perfect sense because ClusterRole does not have a namespaceSelector: when scoped down to a specific Namespace, its subjects are still unambiguous. Group with namespaceSelector in appliedTo, on the other hand, is a bit more complicated. Do we first check if the Group selection actually intersect with the Namespace in which the policy is created? In other words, if the policy's Namespace labels match the namespaceSelector of the Group? If they do not match, then essentially we should have an empty appliedTo, instead of simply disregard namespaceSelector when we process such case. Also, this would be any Namespace label change events will lead to ANP reprocessing. |
@Dyanngg thanks for your comment.
Yes, I think it should check the group's NamespaceSelector should select this Namespace because it should be a common sense that using a group in AddressGroup or AppliedToGroup should not expand its selection. The change in my mind was that Namespace label change triggers Group reprocessing; if the Group changes, it triggers corresponding AppliedToGroup reprocessing; if AppliedToGroup's span changes, it triggers ANP reprocessing. When calculating AppliedToGroups inherited from Groups, it first get members of this group from But now I don't have strong preference of using the above approach. I happened to have a discussion with @reachjainrahul and @wenyingd today about a case in cloud that a policy may be unrealizable if it's set with an action that is not supported by cloud like "Reject" while it's impossible to detect it when creating the NetworkPolicy because we don't know whether it applies to cloud instances or not at that time. So for @qiyueyao's question that "Will we in the future need Unrealizable status response", I think the answer would be yes.
Then we could set |
f83436b
to
f1cad44
Compare
ObservedGeneration: internalNP.Generation, | ||
Conditions: GenerateNetworkPolicyCondition(internalNP.RealizableMessage), | ||
} | ||
internalNP.SpanMeta.NodeNames = 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.
I didn't mean here. StatusController should not become another writer of internalNP
, which makes the process more complicated and introduces a race condition. And setting to nil
will cause the policy is updated to Pending without Unrealizable condition at next round of update, see L273.
I meant when NetworkPolicyController calculates internalNP's span in syncInternalNetworkPolicy
, the span should be empty (not nil) if the policy is unrealizable. But actually we don't even need to make any change to syncInternalNetworkPolicy
because we already set its AppliedToGroups
to empty slices, so it spans no node anyway.
nodeNames := sets.String{}
// Lock the internal NetworkPolicy store as we may have a case where in the
// same internal NetworkPolicy is being updated in the NetworkPolicy UPDATE
// handler.
n.internalNetworkPolicyMutex.Lock()
internalNPObj, found, _ := n.internalNetworkPolicyStore.Get(key)
if !found {
// Make sure to unlock the store before returning.
n.internalNetworkPolicyMutex.Unlock()
return fmt.Errorf("internal NetworkPolicy %s not found", key)
}
internalNP := internalNPObj.(*antreatypes.NetworkPolicy)
// Maintain a copy of old SpanMeta Nodenames so we can later enqueue Groups
// only if it is updated.
oldNodeNames := internalNP.SpanMeta.NodeNames
// Do no send NetworkPolicy with realization error to any Node.
if internalNP.RealizationError == nil {
// Calculate the set of Node names based on the span of the
// AppliedToGroups referenced by this NetworkPolicy.
for _, appliedToGroupName := range internalNP.AppliedToGroups {
appGroupObj, found, _ := n.appliedToGroupStore.Get(appliedToGroupName)
if !found {
continue
}
appGroup := appGroupObj.(*antreatypes.AppliedToGroup)
utilsets.MergeString(nodeNames, appGroup.SpanMeta.NodeNames)
}
}
...
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.
Understood, thanks! So no change in syncInternalNetworkPolicy
for this commit.
Status: v1.ConditionTrue, | ||
LastTransitionTime: v1.Now(), | ||
}) | ||
case ErrNetworkPolicyAppliedToUnsupportedGroup.Error(): |
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 it's more natural to check the type of the error. Since we only need to add the field to "types.NetworkPolicy", it could be error like "RealizationError", not having to be string?
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.
Created an ErrNetworkPolicyAppliedToUnsupportedGroup
struct that implements error
.
Add Group CRD which is responsible for collecting Pods and Namespaces in the Group's Namespace based on labelselectors defined in the Group definition. It also allows setting an IPBlock and ChildGroups (cannot be set with other Selectors) in the Group. The purpose of a Group is to allow grouping of resources and then be referenced in AntreaNetworkPolicies without having to add the same selectors in every ANP when the group of resources are meant to be shared. This allows for greater sharing and decouples the job of reconciling effective group members from that of enforcing security policies. This PR adds the following: -Group API types -Group CRD YAML -Controller changes to reconcile effective members of a Group -Controller changes to trigger ANP update introduced by a Group -Validation webhook to validate a GroupSpec -NetworkPolicyStatus refactored with Conditions Signed-off-by: Qiyue Yao <[email protected]> Co-authored-by: abhiraut <[email protected]>
NetworkPolicyStatus refactor Signed-off-by: Qiyue Yao <[email protected]>
Signed-off-by: Qiyue Yao <[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
/skip-conformance test succeeded but failed to collect codecov. |
@qiyueyao all tests succeeded, I'm going to merge this PR. Thanks for your hard work! |
Thanks for all the insightful and prompt reviews! 🚀 |
Add Group CRD which is responsible for collecting Pods and Namespaces in the Group's Namespace based on
labelselectors defined in the Group definition. It also allows setting an IPBlock and ChildGroups (cannot be set with other
Selectors) in the Group. The purpose of a Group is to allow grouping of resources and then be referenced in
AntreaNetworkPolicies without having to add the same selectors in every ANP when the group of resources are meant to be
shared. This allows for greater sharing and decouples the job of reconciling effective group members from that of enforcing
security policies.
This PR adds the following: