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

Allow control plane components to specify concurrency #12643

Merged
merged 1 commit into from
May 23, 2024

Conversation

mateiidavid
Copy link
Member

@mateiidavid mateiidavid commented May 23, 2024

Concurrency in Linkerd is configured globally through a proxy.cores value or it can be configured through the injector. Control plane components cannot be configured through the injector since they come with the proxy pre-configured. In certain cases, it is necessary for proxies to specify their concurrency. Even though a global value exists, that directly influences all workloads in the cluster which can have other implications.

Each control plane component has a <component>ProxyResources field that is used to configure limits and requests. We overload this field and allow cores to be specified. We do not expect this value to be used often since directly specifying the number of cores might not make a lot of sense -- this does offer an escape hatch when the control plane components can't scale up to meet bursty workloads.

Note for reviewers

Click me for dig function docs

Overloading the operator with an additional field does not lead to failures. I have a couple of scenarios I tested and instructions on how to test locally.

To test:

  1. bin/docker-build
  2. Create a k3d cluster and import the images, bin/image-import --k3d --cluster <name>
  3. Install through Helm (or CLI)
$ helm install linkerd \
       --namespace linkerd \
       --set destinationProxyResources.cores="2" \
       --set destinationProxyResources.memory.request="250Mi" \
       --set-file identityTrustAnchorsPEM=ca.crt \
       --set-file identity.issuer.tls.crtPEM=issuer.crt \
       --set-file identity.issuer.tls.keyPEM=issuer.key \
       --set linkerdVersion=(bin/root-tag) \
       charts/linkerd-control-plane/

I tested the following scenarios:

(1) Per-component default is applied

 $ helm install linkerd \
          --namespace linkerd \
          --set destinationProxyResources.cores="2" \
          --set destinationProxyResources.cpu.limit="3" \
          --set destinationProxyResources.memory.request="250Mi" \
          --set-file identityTrustAnchorsPEM=ca.crt \
          --set-file identity.issuer.tls.crtPEM=issuer.crt \
          --set-file identity.issuer.tls.keyPEM=issuer.key \
          --set linkerdVersion=(bin/root-tag) \
          charts/linkerd-control-plane/

$ k get po -n linkerd linkerd-destination-fc4bcdfb7-g7hfg -o yaml | yq '.spec.containers[] | select ( .name == "linkerd-proxy")' | rg 'CORES' -A 1
  - name: LINKERD2_PROXY_CORES
    value: "2"

$ k get po -n linkerd linkerd-destination-fc4bcdfb7-g7hfg -o yaml | yq '.spec.containers[] | select ( .name == "linkerd-proxy").resources'
limits:
  cpu: "3"
requests:
  cpu: "3"
  memory: 250Mi

(2) When nothing is specified (globally or per-component) we roll with the default.

$ helm install linkerd \
       --namespace linkerd \
       --set-file identityTrustAnchorsPEM=ca.crt \
       --set-file identity.issuer.tls.crtPEM=issuer.crt \
       --set-file identity.issuer.tls.keyPEM=issuer.key \
       --set linkerdVersion=(bin/root-tag) \
       charts/linkerd-control-plane/

$ k get po -n linkerd linkerd-destination-7bb9687899-8k7gf -o yaml |  yq '.spec.containers[] | select ( .name == "linkerd-proxy")' | rg 'CORES' -A 1
<nothing>

(3) When choosing between global and per-component, per-component is the override

$ helm install linkerd \
       --namespace linkerd \
       --set destinationProxyResources.cores="2" \
       --set proxy.cores="3" \
       --set destinationProxyResources.memory.request="250Mi" \
       --set-file identityTrustAnchorsPEM=ca.crt \
       --set-file identity.issuer.tls.crtPEM=issuer.crt \
       --set-file identity.issuer.tls.keyPEM=issuer.key \
       --set linkerdVersion=(bin/root-tag) \
       charts/linkerd-control-plane/

$  k get po -n linkerd linkerd-destination-6d7f86fd48-v7zkz -o yaml | yq '.spec.containers[] | select ( .name == "linkerd-proxy")' | rg 'CORES' -A 1
  - name: LINKERD2_PROXY_CORES
    value: "2"

(4) Specifying only a global means components respect the global

$ helm install linkerd \
       --namespace linkerd \
       --set proxy.cores="3" \
       --set destinationProxyResources.memory.request="250Mi" \
       --set-file identityTrustAnchorsPEM=ca.crt \
       --set-file identity.issuer.tls.crtPEM=issuer.crt \
       --set-file identity.issuer.tls.keyPEM=issuer.key \
       --set linkerdVersion=(bin/root-tag) \
       charts/linkerd-control-plane/

$ k get po -n linkerd linkerd-destination-56c786ff49-kl6r7 -o yaml | yq '.spec.containers[] | select ( .name == "linkerd-proxy")' | rg 'CORES' -A 1
  - name: LINKERD2_PROXY_CORES
    value: "3"

(5) We can upgrade and specify a per-component value to override the global

 $ helm upgrade linkerd \
       --namespace linkerd \
       --set destinationProxyResources.cores="1" \
       --set destinationProxyResources.memory.request="250Mi" \
       --set-file identityTrustAnchorsPEM=ca.crt \
       --set-file identity.issuer.tls.crtPEM=issuer.crt \
       --set-file identity.issuer.tls.keyPEM=issuer.key \
       --set linkerdVersion=(bin/root-tag) \
       charts/linkerd-control-plane/

$ k get po -n linkerd linkerd-destination-74968c6999-q6kwn -o yaml |  yq '.spec.containers[] | select ( .name == "linkerd-proxy")' | rg 'CORES' -A 1
  - name: LINKERD2_PROXY_CORES
    value: "1"

The tests show some of the basic install / upgrade flows that people would follow. Since the value will override only when specified (and is not documented) it should not affect existing installations unless users explicitly opt-in.

Concurrency in Linkerd is configured globally through a `proxy.cores`
value or it can be configured through the injector. Control plane
components cannot be configured through the injector since they come
with the proxy pre-configured. In certain cases, it is necessary for
proxies to specify their concurrency. Even though a global value exists,
that directly influences all workloads in the cluster which can have
other implications.

Each control plane component has a `<component>ProxyResources` field
that is used to configure limits and requests. We overload this field
and allow `cores` to be specified. We do not expect this value to be
used often since directly specifying the number of cores might not make
a lot of sense -- this does offer an escape hatch when the control plane
components can't scale up to meet bursty workloads.

Signed-off-by: Matei David <matei@buoyant.io>
@mateiidavid mateiidavid requested a review from a team as a code owner May 23, 2024 17:36
Copy link
Member

@alpeb alpeb left a comment

Choose a reason for hiding this comment

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

LGTM. The <component>ProxyResources docs only make reference to "proxy.resources for sub-fields". Do we want to leave this new option undocumented?

@mateiidavid
Copy link
Member Author

Yeah, I think so. Since this might be subject to change, we should maybe document it only when it's polished.

@mateiidavid mateiidavid merged commit d17e718 into main May 23, 2024
36 checks passed
@mateiidavid mateiidavid deleted the matei/concurrent-plane branch May 23, 2024 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants