Linkerd 2.10(Step by Step)之配置代理并發(fā)
Linkerd 2.10 中文手冊(cè)持續(xù)修正更新中:
- https://linkerd.hacker-linner.com
Linkerd 數(shù)據(jù)平面的代理是多線程(multithreaded)的, 并且能夠運(yùn)行可變數(shù)量的工作線程, 以便它們的資源使用(resource usage)與應(yīng)用程序工作負(fù)載(application workload)相匹配。
當(dāng)然,在真空(vacuum)中,當(dāng)允許使用盡可能多的 CPU 內(nèi)核時(shí), 代理將表現(xiàn)出最佳的吞吐量(throughput)和最低的延遲(latency)。但是,在實(shí)踐中,還需要考慮其他因素。
真實(shí)世界的部署不是一個(gè)負(fù)載測(cè)試(load test), 在這個(gè)測(cè)試中,客戶端和服務(wù)器除了用請(qǐng)求使代理飽和之外,沒(méi)有其他工作要做。相反,服務(wù)網(wǎng)格模型將代理實(shí)例部署為應(yīng)用程序容器的 sidecar。每個(gè)代理只處理進(jìn)出它注入的 pod 的流量。這意味著吞吐量和延遲受應(yīng)用程序工作負(fù)載的限制。如果應(yīng)用程序容器實(shí)例每秒只能處理這么多請(qǐng)求,那么代理可以處理更多的請(qǐng)求可能并不重要。事實(shí)上,給代理提供比它需要的更多 CPU 內(nèi)核來(lái)跟上應(yīng)用程序可能會(huì)損害整體性能, 因?yàn)閼?yīng)用程序可能不得不與代理競(jìng)爭(zhēng)有限的系統(tǒng)資源。
因此,單個(gè)代理有效處理其流量比配置所有代理以處理最大可能負(fù)載更為重要。調(diào)整代理資源使用的主要方法是限制代理用于轉(zhuǎn)發(fā)流量的工作線程數(shù)。有多種方法可以做到這一點(diǎn)。
使用 proxy-cpu-limit Annotation
配置代理線程池的最簡(jiǎn)單方法是使用 config.linkerd.io/proxy-cpu-limit annotation。此 annotation 配置代理注入器以設(shè)置一個(gè)環(huán)境變量,該變量控制代理將使用的 CPU 核數(shù)。
使用 linkerd install CLI 命令安裝 Linkerd 時(shí), --proxy-cpu-limit 參數(shù)會(huì)為 Linkerd 安裝注入的所有代理全局設(shè)置此 annotation。例如,
linkerd install --proxy-cpu-limit 2 | kubectl apply -f -
對(duì)于更細(xì)粒度(fine-grained)的配置,可以將 annotation 添加到 任何可注入的 Kubernetes 資源,例如 namespace、pod 或 deployment。
例如,以下將配置 my-deployment 部署中的代理使用1個(gè) CPU 內(nèi)核:
- kind: Deployment
- apiVersion: apps/v1
- metadata:
- name: my-deployment
- # ...
- spec:
- template:
- metadata:
- annotations:
- config.linkerd.io/proxy-cpu-limit: '1'
- # ...
與 Kubernetes CPU 限制和請(qǐng)求可以用 milliCPUs 表示不同, proxy-cpu-limit 注解應(yīng)該用 CPU 內(nèi)核的整數(shù)來(lái)表示。小數(shù)值將四舍五入到最接近的整數(shù)。
使用 Kubernetes CPU Limits 與 Requests
Kubernetes 提供 CPU limits and CPU requests 來(lái)配置分配給任何 pod 或容器的資源。這些也可用于配置 Linkerd 代理的 CPU 使用率。但是,根據(jù) kubelet 的配置方式, 使用 Kubernetes 資源限制 而不是 proxy-cpu-limit annotation 可能并不理想。
kubelet 使用兩種機(jī)制之一來(lái)強(qiáng)制執(zhí)行 pod CPU 限制。這由 --cpu-manager-policy kubelet 選項(xiàng) 決定。使用默認(rèn)的 CPU 管理器策略 none, kubelet 使用 CFS 配額 來(lái)強(qiáng)制執(zhí)行 CPU limits。這意味著 Linux 內(nèi)核被配置為限制屬于給定進(jìn)程的線程被調(diào)度的時(shí)間量?;蛘撸珻PU 管理器策略可以設(shè)置為 static。在這種情況下,kubelet 將使用 Linux cgroups 對(duì)滿足特定條件的容器實(shí)施 CPU limits。
當(dāng) proxy-cpu-limit annotation 配置的環(huán)境變量未設(shè)置時(shí), 代理將運(yùn)行與可用 CPU 內(nèi)核數(shù)相等的工作線程數(shù)。這意味著使用默認(rèn)的 noneCPU 管理器策略,代理可能會(huì)產(chǎn)生大量工作線程, 但 Linux 內(nèi)核會(huì)限制它們的調(diào)度頻率。這比簡(jiǎn)單地減少工作線程的數(shù)量效率更低,就像 proxy-cpu-limit 所做的那樣:更多的時(shí)間花在上下文切換上,每個(gè)工作線程的運(yùn)行頻率將降低,這可能會(huì)影響延遲。
另一方面,使用 cgroup cpusets 將限制進(jìn)程可用的 CPU 核數(shù)。從本質(zhì)上講,代理會(huì)認(rèn)為系統(tǒng)的 CPU 內(nèi)核數(shù)比實(shí)際少。這將導(dǎo)致與 proxy-cpu-limit annotation 類似的行為。
但是,值得注意的是,要使用此機(jī)制,必須滿足某些條件:
- kubelet 必須配置 static CPU 管理器策略
- Pod 必須屬于有 Guaranteed QoS class。這意味著 pod 中的所有容器都必須同時(shí)具有內(nèi)存和 CPU 的 limit 和 request,并且每個(gè)的 limit 必須與 request 具有相同的值。
- CPU limit 和 CPU request 必須是大于或等于 1 的整數(shù)。
如果您不確定是否會(huì)全部滿足這些條件,除了任何 Kubernetes CPU limits 和 requests 之外, 最好使用 proxy-cpu-limit annotation。
使用 Helm
使用 Helm 時(shí),如果不滿足上述基于 cgroup 的 CPU 限制條件, 用戶必須注意設(shè)置 proxy.cores Helm 變量和 proxy.cpu.limit 之外的變量。