Skip to content
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

Pilot scoped namespaces #29802

Merged
merged 32 commits into from
Feb 9, 2021
Merged

Conversation

harveyxia
Copy link
Contributor

Add ability to scope pilot discovery to a specified set of namespaces in order to improve performance on both the control-plane (process fewer services/pods/endpoints) and data-plane (reduce both size and frequency of xDS updates to proxies).

For more context, view the design document(shared in the Istio networking group drive) and the associated issue, #26679.

And to help us figure out who should review this PR, please
put an X in all the areas that this PR affects.

[ ] Configuration Infrastructure
[ ] Docs
[ ] Installation
[X] Networking
[X] Performance and Scalability
[ ] Policies and Telemetry
[ ] Security
[ ] Test and Release
[ ] User Experience
[ ] Developer Infrastructure

Pull Request Attributes

Please check any characteristics that apply to this pull request.

[ ] Does not have any changes that may affect Istio users.


Performance profiles:

The testing methodology consists of generating service churn by creating 100 services in a specified namespace and profiling CPU usage on an envoy proxy.

For Istio 1.8.1:
image

With the changes in this PR, in a namespace not labeled for discovery:
image

We observe that xDS updates are no longer issued for Service events in the omitted namespace.

@harveyxia harveyxia requested review from a team as code owners December 29, 2020 16:12
@istio-testing istio-testing added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Dec 29, 2020
@google-cla
Copy link

google-cla bot commented Dec 29, 2020

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added the cla: no Set by the Google CLA bot to indicate the author of a PR has not signed the Google CLA. label Dec 29, 2020
@istio-testing
Copy link
Collaborator

Hi @harveyxia. Thanks for your PR.

I'm waiting for a istio member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@howardjohn
Copy link
Member

/ok-to-test

@istio-testing istio-testing added ok-to-test Set this label allow normal testing to take place for a PR not submitted by an Istio org member. and removed needs-ok-to-test labels Dec 29, 2020

const (
// PilotDiscoveryLabelName is the name of the label used to indicate a namespace for discovery
PilotDiscoveryLabelName = "istio-discovery"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the current label is istio-injection, its mostly that out of legacy. Any new labels should be *.istio.io/* format to conform to k8s best practice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any opinions on the exact label string? Would discovery.istio.io/enable be conventional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was some discussion about allowing more than one istiod to managed (namespace-filtered) meshes in the same cluster. This implementation doesn't seem to support that. If it is required, the value of this label needs to be a meshId, not just boolean.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the recently proposed discoverySelectors option should enable multiple istiod's to manage mesh in the same cluster with non overlapping selectors.
@harveyxia: NewNamespaceController should also honor this selector configuration and insert istio-ca-root-cert config map to only filtered namespaces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NamespaceController should also use DiscoveryNamespacesFilter
@harveyxia do you plan to update NamespaceController?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@l8huang The original motivation for this implementation was primarily for performance improvement (filtering out irrelevant services, pods, and endpoints) , so we kept the DiscoveryNamespacesFilter scoped to the main service registry controller. With some refactoring (making DiscoveryNamespacesFilter self contained and exposing methods for registering handlers for meshConfig and namespace events) it can be extended for use with other components.

However, before we do any implementation, we should determine whether this feature is the right abstraction for enabling multiple istiod deployments (which is an orthogonal concern to performance), or if there are other designs / existing components that would be better suited for this use case. @howardjohn @costinm any thoughts?

PilotDiscoveryLabelValue = "true"
)

func DiscoveryNamespacesFilterFunc(lister v1.NamespaceLister, enableDiscoveryNamespaces bool) func(obj interface{}) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have any profiles on istiod side? to see if the filtering is taking any noticeable CPU/mem usage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the filter:
image

With the filter:
image

There appears to be less CPU utilization (50ms -> 20ms) by the k8s watch when adding the filter

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the cost is very big, what if we remove the filter when get/list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hzxuzhonghu Can you elaborate on where you're seeing the cost incurred by the filtering itself? Zooming in on the second profile I posted above (the one with the filter applied), it seems the additional cost of the filter consists of map accesses and string equality comparisons. But overall the filter appears to be conserving CPU usage, since there are fewer resources by processed.

image

With respect to removing the filter from get/list, for correctness we want the filter to be applied to all reads, and there are numerous usages of List() and GetByKey() throughout the kube service registry

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the profiler can give accurate numbers at such low load

Copy link
Contributor Author

@harveyxia harveyxia Jan 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I conducted another profile using pilot-load to generate load against pilot. With the cache-backed filter approach implemented in commit a3d6016, the performance impact of the filtering itself should be nominal since each invocation of the filter only requires constant time access into a map (as opposed to the previous implementation which required iteration of all namespaces).

Without filtering:

image

With filtering enabled and no labeled namespaces:

image

With filtering enabled and 10 labeled namespaces:

image

P.S. I have each of these profiles saved, so we can examine in greater detail if needed

@google-cla google-cla bot added cla: yes Set by the Google CLA bot to indicate the author of a PR has signed the Google CLA. and removed cla: no Set by the Google CLA bot to indicate the author of a PR has not signed the Google CLA. labels Dec 29, 2020
Copy link
Member

@hzxuzhonghu hzxuzhonghu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When namespace updated(labels added/removed), a new full push should be triggered.

pilot/cmd/pilot-discovery/main.go Outdated Show resolved Hide resolved
nsInformer cache.SharedIndexInformer
// TODO merge the namespace informers/listers
systemNsInformer cache.SharedIndexInformer
nsInformer coreinformers.NamespaceInformer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to resolve, otherwise very confusing

@harveyxia
Copy link
Contributor Author

When namespace updated(labels added/removed), a new full push should be triggered.

Discussed offline, full pushes will be triggered by the relevant resource event handlers (e.g. service event handler triggers a full push here, pod event handler triggers a full push here. These resource specific event handlers are invoked by the new namespace controller introduced in this PR when namespaces are newly labeled or delabled

@harveyxia harveyxia requested review from a team as code owners December 30, 2020 14:58
)

// On namespace membership change, request a full xDS update since services need to be recomputed
func (c *Controller) initDiscoveryNamespaceHandlers(kubeClient kubelib.Client, endpointMode EndpointMode) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reviewers, this should be closely looked at.

@mfanjie
Copy link
Contributor

mfanjie commented Jan 28, 2021

Writing to every resource in the cluster seems problematic for security, api server load, and latency (delays to add the label). We have a pretty strong assumption of being read-only.

On Wed, Jan 27, 2021, 6:53 PM Jesse Meng @.***> wrote: We need similar feature to support very large scale, but we still facing challenge if using primary-remote deployment as in each cluster, we have 15k~20k pods. Even this PR introduces informer level filter, the client still watch all object changes, which would high possible to cause problem. Is it possible to do it in such way: 1. add some built-in labels in namespace, similar like the service exportTo annotation, e.g. networking.istio.io/managedBy. 2. add a controller to propagate the labels from namespace to all related objects in the namespace, including service, ep, istio networking objects. 3. define the discoverySelector in meshConfig but only accept the predefined keys 4. in Polit code, discover all object by the label filters. With this approach, all the filters are done in server side, then it is possible to setup mesh with controlled scale in any scale of Kubernetes clusters — You are receiving this because your review was requested. Reply to this email directly, view it on GitHub <#29802 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEYGXMN3OJUBQML36TV5T3S4DGUDANCNFSM4VNLTZMA .

Then the label propagation step can be left to users, Isito only to provide a capability to do xDS based on some label filters.

@howardjohn
Copy link
Member

howardjohn commented Jan 28, 2021 via email

@mfanjie
Copy link
Contributor

mfanjie commented Jan 28, 2021

@howardjohn, right, it's a small change in the code, and it resolves the scalability issue we are facing.
We don't want to have different code base with upstream, so I am here to check if upstream can have similar or better solution.

@hzxuzhonghu
Copy link
Member

We can consider this option, but we could not enforce all users do that.

@mfanjie
Copy link
Contributor

mfanjie commented Jan 28, 2021

We can consider this option, but we could not enforce all users do that.

IMHO, we can keep the discoverySelector configuration which is introduced by this PR, by default, no selector is defined, and Isito behaves exactly same with now, which discovery all configuration and status.
If user define discoverySelector in meshConfig, then it indicates user want to filter the objects in the Kubernetes cluster, so the istio objects to be managed must have labels match the selector.
It's all up to mesh configuration and user's operation.

@istio-testing istio-testing added the needs-rebase Indicates a PR needs to be rebased before being merged label Jan 28, 2021
@istio-testing istio-testing removed the needs-rebase Indicates a PR needs to be rebased before being merged label Feb 2, 2021
@harveyxia
Copy link
Contributor Author

/retest

@harveyxia
Copy link
Contributor Author

@howardjohn @hzxuzhonghu The istio/api version has been bumped, this PR is ready for a final review

@christian-posta
Copy link
Contributor

@howardjohn @linsun @nrjpoddar can we get final sign off on this? need one more approval

# release notes.
releaseNotes:
- |
**Added** An option for dynamically restricting the set of namespaces for Services, Pods, and Endpoints that istiod processes when pushing xDS updates to improve performance on the data plane.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you specify the option (DiscoverySelectors?) here?

As a follow up - Would love to have a some doc that teaches user how to use this. The guideline is to put doc on istio wiki for experimental feature (I assume this is).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also wonder if it is useful to ask users to visualize the mesh (like using kiali) to determine the correct configuration for the discovery selectors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to follow up with documentation on how to utilize this feature, I'll follow up offline to discuss


# upgradeNotes is a markdown listing of any changes that will affect the upgrade
# process. This will appear in the release notes.
upgradeNotes:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any consideration for upgrade? I believe this is not enabled by default, but if it is enabled, users would need to ensure the discoverySelectors config is correct else apps could be broken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is indeed disabled by default—should I still include an upgrade note describing usage of discoverySelectors?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it is disabled, no. Would be good to have it in your docs on consideration when enabling this. :)

Copy link
Member

@linsun linsun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't look at code closely but top level changes LGTM

Added some comment for readme, would love to have them addressed or knowing a plan to address them before approving.

@howardjohn
Copy link
Member

howardjohn commented Feb 25, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Set by the Google CLA bot to indicate the author of a PR has signed the Google CLA. ok-to-test Set this label allow normal testing to take place for a PR not submitted by an Istio org member. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants