阿里巴巴雲原生應用安全防禦實踐與 OpenKruise 的新領域

頭圖.png

做者 | 王思宇(酒祝)
來源|阿里巴巴雲原生公衆號node

得益於 Kubernetes 面向終態的理念,雲原生架構自然具有高度自動化的能力。然而,面向終態的自動化是一把「雙刃劍」,它既爲應用帶來了聲明式的部署能力,同時也潛在地會將一些誤操做行爲被終態化放大。
所以,充分了解雲原生環境下那些潛在的影響應用安全的問題,提早掌握多方位的安全防禦、攔截、限流、熔斷等技術手段來保障雲原生應用的運行時穩定性相當重要。git

本文整理自做者阿里雲容器服務技術專家,OpenKruise 做者 & 初創人員之一,Kubernetes、OAM 社區貢獻者王思宇(酒祝)於 1 月 19 日在阿里雲開發者社區「週二開源日」的直播分享,介紹了雲原生環境下應用安全與可用性的「到處危機」,分享阿里巴巴保障雲原生應用運行時穩定性經驗,而且詳細解讀了後續這些能力將如何經過 OpenKruise 賦能給開源。github

點擊回看完整視頻:https://developer.aliyun.com/live/246065後端

雲原生環境應用安全「危機」

1. 阿里巴巴雲原生應用部署結構

這裏的雲原生應用部署結構是在阿里巴巴原生環境最簡化的抽象圖,以下圖所示。api

1.jpg

首先咱們來看幾個 CRD。CloneSet CRD 能夠理解成 deployment 的一個 workload,也就是給應用部署 Pod 的模板。有了 CloneSet CRD 以後,不一樣的業務以及不一樣的應用會創建對應的 CloneSet,在 CloneSet 下面再創建對應的 Pod,以及對 Pod 作一些部署、發佈相關的管理。安全

除了 CloneSet 以外,還提供了 SidecarSet CRD,這個 CRD 作的事情是在業務 Pod 建立階段注入 SidecarSetCRD 中定義的 Sidecar 容器。也就是說,在 CloneSet 中業務只須要定義 Pod 中的 app 容器,也就是業務容器。在 Pod 建立過程當中,經過 SidecarSet 在其中定義業務中要注入哪些 sidecar 容器。網絡

2. OpenKruise:阿里巴巴應用部署基座

開源的 OpenKruise 是阿里巴巴應用部署的基座。OpenKruise 提供了多種的 workload。其中包括:CloneSet、Advanced StatefulSet、SidecarSet、Advanced DaemonSet。架構

2.jpg

  • CloneSet:是面向無狀態應用部署的工具,也是阿里巴巴中使用規模最大的部分,絕大部分泛電商業務都是經過 CloneSet 來部署發佈,包括 UC 神馬、餓了麼、電商業務等。併發

  • Advanced StatefulSet:針對一個原生 StatefulSet 兼容的加強版本,是面向有狀態應用部署的工具,目前主要是用於中間件在雲原生環境的部署。app

  • SidecarSet:是在阿里巴巴環境中 sidecar 生命週期管理的工具。阿里巴巴的運維容器,以及阿里內部的 Mesh 容器,都是經過 SidecarSet 定義、部署以及注入到業務 Pod 中的。

  • Advanced DaemonSet:是針對原生 DaemonSet 兼容加強版本。將宿主機級別的守護進程部署到全部節點上,包括各類用於給業務容器配置網絡、存儲的基礎組件。

介紹完基礎環境以後,咱們已經對雲原生部署結構有了一個基本的瞭解。下面,咱們來了解在雲原生部署結構之下存在哪些雲原生應用安全危機。

3. 雲原生應用安全危機

1)workload 級聯刪除

Workload 級聯刪除,這一點不僅針對於 Kruise 的 CloneSet,對於 Deployment,對於原生的 StatefulSet 都存在相似的問題。指的是當咱們刪除一個 Workload 以後,假設使用採用默認刪除,沒有使用 orphan 刪除這種策略的話,底下的 Pod 都會被刪掉,這裏存在一種誤刪風險。也就是說,一旦某個 Deployment 被誤刪,那麼它底下的全部 Pod 都會級聯被刪掉,致使整個應用不可用。若是有多個 Workload 被刪掉,就可能致使不少個業務出現不可用的狀況,這是一個對可用性形成的風險。以下圖所示:

3.jpg

2)namespace 級聯刪除

那麼咱們再往上看,若是 Namespace 被刪掉,那麼整個 Namespace 底下的全部資源,包括 Deployment、CloneSet 這些 Workload,也包括 Pod、Service 等全部資源都會被刪除,這是一種很高的誤刪風險。

4.jpg

3)CRD 級聯刪除

若是有用 Helm 部署的同窗可能會遇到過相似的狀況,也就是若是你的 Helm 中包含了一些 CRD,這些 CRD 都被定義在 template 中, 那麼當 Helm uninstall 的時候,基本上這些 CRD 都會被 Helm 包級聯刪除掉,包括有人手動誤刪了某個 CRD,那麼 CRD 底下對應的 CR 都會被清理。這是一個很高的風險。

若是 CRD 是 CloneSet 這種 Workload 級別的 CRD,那麼一旦刪除這個 CRD 以後,會致使全部 CRD 底下的 CloneSet 的 CR 對象所有被刪掉,從而致使全部的業務 Pod 所有被刪掉。也就是說,刪除一個 Workload,只是這個 Workload 底下的 Pod 被刪掉;刪除一個 Namespace 可能只是 Namespace 底下的 Pod 被刪掉。但若是像阿里巴巴這種場景下,若是有人把 CloneSet 或者一些很關鍵的 CRD 刪掉的話 ,其實極可能致使整個集羣環境全部 NameSpace 底下的 Pod 都會被級聯刪掉,或者說都會處於應用不可用的狀態,形成雲原生環境對於應用可用性的風險。以下圖所示:

5.jpg

從上文能夠看出來,雲原生這種理念架構爲咱們帶來的好處是面向終態,也就是說咱們定義終態,從而整個 Kubernetes 集羣就會向終態靠攏。而一旦出現一些誤操做致使定義了一種錯誤的終態,那麼 Kubernetes 也會向錯誤的終態靠攏,致使出現錯誤的結果,從而影響到整個應用的可用性。所以咱們說,面向終態是一把「雙刃劍」。 

4)併發 Pod 更新/驅逐/刪除

除了幾種誤刪的狀況,還有更多針對可用性的風險。以下圖所示,假設左邊 CloneSetA 部署了兩個 Pod,這兩個 Pod 中又被 SidecarSet 注入了對應的 sidecar 容器。在這種狀況下,若是經過 CloneSet 作應用發佈,假設說咱們設置的 Max Available 是 50%,也就是說,兩個 Pod 是逐個升級,前一個升級完成,後一個才能開始升級,默認狀況下這種發佈策略是沒有問題的。

可是若是 Pod 有多個 Owner,好比 CloneSet 是其中一個 Owner,CloneSet 對上面的 Pod 開始作原地升級,SidecarSet 對第二個 Pod 作 sidecar 的原地升級,那麼同一時刻可能這個應用的兩個 Pod 都在被升級。由於在 CloneSet 定義了 Max Unavailable 是 50%,從它的視角來看,只要選取兩個 Pod 中的一個開始作升級。CloneSet 自己是沒法感知到其它控制器甚至其餘人爲的行爲去對其它 Pod 作操做,缺少全局視角,每個控制器都認爲本身在升級的 Pod 是符合升級策略,符合最大不可用測略。但當多個控制器同時開始工做的時候,可能會致使整個應用 100% 不可用。

6.jpg

如上圖右邊的狀況,CloneSetC 底下有 3 個 Pod,若是它開始作升級的時候只升級其中一個 Pod,假設是重建升級,它會把舊版本 Pod 刪掉,先建新版本 Pod。在這過程當中,假設另外兩個 Pod 一個可能被 Kubelet,或者 kube-controller-manager 中的 node lifecycle controller 驅逐,這時候已經有兩個 Pod 不可用,已經超過 Workload 中定義的最大不可用發佈策略。在這個過程當中,還可能有一些 Pod 被其餘一些控制器其餘有人工手動刪除。種種可能性致使一個 Workload 下 Pod 的不可用數量,極可能是超過自己 workload 中定義的不可用發佈策略的。

也就是說,在 Deployment 中定義了 Max Unavailable 是 25%,那麼 Deployment 在發佈的時候,從它自身角度來看保證 25% 的 Pod 在被髮布。其餘 75% 的 Pod 並不保證徹底可用,這 75% 的 Pod 可能被 Kubelet 驅逐、可能被人爲手動刪除、可能被 SidecarSet 外部熱升級等等,種種狀況可能會致使 Deployment 超過 50% 不可用,甚至更高,使整個應用受到影響。

雲原生應用安全防禦實踐

針對以上種種危機,咱們能採起怎麼樣的措施,保證原生環境下應用安全的可用性、安全性。下面介紹一些實踐的經驗。

1. 防禦實踐 - 防級聯刪除

因爲級聯刪除對應用可用性危害很是大,包括了刪除 CRD 節點,刪除 Namespace 節點,以及刪除 Workload 節點。防級聯刪除定義了針對多種資源,包括 CRD、Namespace、包括原生 Deployment 在內的各類 Workload 等,對這些資源提供了針對的 labels 定義。

7.jpg

下面是針對各類重要節點防級聯刪除的語名:

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  labels:
    policy.kruise.io/disable-cascading-deletion: true

---

apiVersion: v1
kind: Namespace
metadata:
  labels:
    policy.kruise.io/disable-cascading-deletion: true

---

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    policy.kruise.io/disable-cascading-deletion: true

---

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
  labels:
    policy.kruise.io/disable-cascading-deletion: true

labels 定義是關閉級聯刪除,用戶的任何 CRD、Namespace、workload 裏帶有防級聯刪除標識以後,kruise 就會保證資源防級聯刪除校驗。也就是說,當用戶刪除一個 CRD 時,若是這個 CRD 裏帶有防級聯刪除這個 label,那麼 kruise 就會去查看 CRD 底下是否還有存量 CR,若是有存量 CR 那麼 kruise 會禁止 CRD 刪除。

同理,在 Namespace 刪除時,也會校驗 Namespace 底下是否還有存量的運行狀態的 Pod,若是有,會禁止用戶直接刪除 Namespace。

對於 workload 邏輯相對簡單,就對於 Deployment、CloneSet、SidecarSet,當用戶去刪除 workload 時,若是 workload 中用戶已經定義了防級聯刪除的 label,那麼 kruise 會檢查 workload 的 replica 是否爲 0,若是 replica 大於 0,那麼 kruise 是禁止用戶直接刪除帶有防級聯刪除標識的 workload。也就是說,當一個存量 Deployment,若是 replicas 大於 0 的狀況下,若是 Deployment 中存在帶有防級聯刪除標識,kruise 禁止用戶直接刪除。

若是真的須要刪除 Deployment 有兩種辦法:

  • 第一,先把 replica 調爲 「0」,這時底下 Pod 開始被刪除,這時刪除 Deployment 是沒問題的。

  • 第二,能夠把 Deployment 中防級聯刪除標識去掉。

以上是關於防級聯刪除的介紹,你們應該將防級聯刪除理解成安全防禦最基礎的一個策略,由於級聯刪除是 Kubernetes 中很是危險的一個面向終態的能力。

2. 防禦實踐 – Pod 刪除流控 & 熔斷

針對 Pod 刪除流控 & 熔斷的策略,指的是用戶調用、或用控制器用 K8s 去作 Pod 驅逐時,一旦出現誤操做或者出現邏輯異常,極可能致使在整個 K8s 集羣範圍內出現 Pod 大規模刪除的狀況。針對這種狀況作了 Pod 刪除留空策略,或者說是一個 CRD。這個 CRD 用戶能夠定義在一個集羣中,不一樣的時間窗口內,最多有多少 Pod 容許被刪除。

apiVersion: policy.kruise.io/v1alpha1
kind: PodDeletionFlowControl
metadata:
  # ...
spec:
  limitRules:
  - interval: 10m
    limit: 100
  - interval: 1h
    limit: 500
  - interval: 24h
    limit: 5000
  whiteListSelector:
    matchExpressions:
    - key: xxx
      operator: In
      value: foo

如上面這個例子,10 分鐘以內最多容許 100 個 Pod 被刪除,1 小時以內最多容許 500 個 Pod 被刪除,24 小時內最多容許 5000 個 Pod 被刪除。固然也能夠定義一些白名單,好比有些測試應用,天天頻繁地巡檢、測試,頻繁刪除會影響整個流控,能夠提供一個白名單,符合白名單的應用不計算在窗口內。

除了白名單以外,可能 90% 的常規應用或者核心應用,是受到刪除流控保護的。一旦存在規模性誤刪除操做,就會被刪除流控以及熔斷機制保護。包括在保護以後或者觸發閾值以後,最好提供這種報警機制、監控機制,讓集羣的管理者能快速的感知到線上出現的熔斷事件。還包括幫助管理者去判斷熔斷事件是一個正常的事件,仍是一個異常的事件。

若是在這段時間內,須要存在不少刪除請求,能夠把對應策略值相應放大。若是真的是一些誤刪除,攔截到以後,及時根據請求來源作溯源,及時在搜索層面作熔斷,拒絕這些請求。

3. 防禦實踐 - 應用維度不可用數量保護

對應用維度不可用數量保護,對於 K8s 原生,原生的 Kubernetes 提供了 PDB(PodDisruptionBudge) 策略,可是 PDB 只能攔截 Pod eviction 驅逐操做,也就是 Pod 驅逐操做。

8.jpg

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: xxx
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: xxx

上面的這個例子,假設其中有 5 個 Pod,這時定義了 minAvailable=2,就保證最少有 2 個 Pod 處於可用。一旦有 3 個 Pod 不可用,還剩下 2 個 Pod 可用,這時候若是 Pod eviction 針對存量 2 個 Pod 作驅逐,這個時候 PDB 會保護 Pod 可用性,拒絕此次驅逐操做。可是相應的若是對存量 2 個 Pod 作刪除或者原地升級,或者去作其餘致使 Pod 不可用的事情,PDB 是沒有辦法攔截,尤爲是針對 Pod 刪除請求,比 Pod 驅逐更爲常見,可是 PDB 是沒辦法攔截刪除等請求。

對於這些問題,阿里巴巴作了 PodUnavailableBudget 攔截操做,也就是 PUB。這裏的 Unavailable 能作的操做就更多了,基本上全部可能致使 Pod 不可用的操做,都在 PodUnavailableBudget 保護範圍內,包括了驅逐請求、Pod 刪除請求,應用原地升級、Sidecar 原地升級、容器重啓等,全部致使應用不可用的操做都會被 PUB 攔截。

以下面這個例子:

apiVersion: policy.kruise.io/v1alpha1
kind: PodUnavailableBudget
spec:
  #selector:
  #  app: xxx
  targetRef:
    apiVersion: apps.kruise.io
    kind: CloneSet
    name: app-xxx
  maxUnavailable: 25%
  # minAvailable: 15
status:
  deletedPods:
    pod-uid-xxx: "116894821"
  unavailablePods:
    pod-name-xxx: "116893007"
  unavailableAllowed: 2
  currentAvailable: 17
  desiredAvailable: 15
  totalReplicas: 20

定義了一個 PUB,這個 PUB 能夠像原生 PDB 同樣寫一個 selector 範圍,也能夠經過 targetRef 直接關聯到某一個 Workload,保護範圍就是在 Workload 底下的全部 Pod,一樣也能夠定義最大不可用數量,以及最小可用數量。

假設對於 CloneSet 底下總共 20 個 Pod,當定義了 maxUnavailable:25% 時,必定要保證至少有 15 個 Pod 處於可用狀態。也就是說,PUB 會保證這 20 個 Pod 中最多有 5 個處於不可用狀態。回到咱們以前在「危機」部分講到的一個例子,若是這 20 個 Pod 同時在被 Cloneset 發佈,以及被 Kubelet 驅逐,或是人工手動刪除,一旦 Pod 不可用數量超過 5 個,無論是 Kubelet 對剩餘 15 個 Pod 作驅逐,仍是人爲手動刪除剩餘的某些 Pod,這些操做都會被 PUB 所攔截,這種策略能徹底保證應用在部署過程當中的可用性。PUB 能夠保護的範圍比 PDB 大不少,包括在實際使用過程當中預期以外的一些刪除請求、升級請求,從而保證整個應用在運行時的穩定性和可用性。

4. 防禦實踐 - PUB/PDB 自動生成

對於真正的 Depoyment 應用開發者、運維人員來講,通常而言,只須要定義自身 workload 中 template,業務方只關心 Depoyment templatek 中業務的版本、環境變量、端口、提供的服務,但咱們很難去強制每個業務方在定義應用時,另外寫一個 PUB 或者 PDB 保護策略的 CR。那麼,咱們怎樣對每個應用提供自動保護呢?

在阿里巴巴內部,咱們針對每一個 Workload 提供自動生成 PUB/PDB 的能力。好比說,若是用戶此時新建立了一個 Deployment,會經過控制器自動爲該 Deployment 生成一個匹配的 PUB。這個自動生成的功能即能支持原生 Deployment/StatefulSet,也支持 Kruise 的 CloneSet / Advanced StatefulSet / UnitedDeployment。第二,默認根據 strategy 中 maxUnavailable 策略。第三,容許 annotation 中單獨定義保護策略。以下面的語句所示:

apiVersion: apps
kind: Deployment
metadata:
  name: deploy-foo
  annotations:
    policy.kruise.io/generate-pub: "true"
    policy.kruise.io/generate-pub-maxUnavailable: "20%"
    # policy.kruise.io/generate-pub-minAvailable: "80%"
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  # ...

---
# auto generate:
apiVersion: policy.kruise.io/v1alpha1
kind: PodUnavailableBudget
spec:
  targetRef:
    apiVersion: apps
    kind: Deployment
    name: deploy-foo
  maxUnavailable: 20%

自動生成的 PUB/PDB 內部填寫的 maxUnavailable,既可讓用戶在 kruise 中指定定義。好比用戶能夠直接把 kruise.io/generate-pub:"true",也能夠 kruise.io/generate-pub-maxUnavailable:"20%",可讓用戶指定應用最多容許有多少個不可用。這是用戶指定的策略。

若是用戶沒有指定策略,會根據在發佈策略中存在的maxUnavailable生成 PUB。就是指在發佈的階段,有多少個不可用數量,作爲應用運行時最大不可能數量。這是容許單獨定義策略。

OpenKruise 的新領域

1. OpenKruise 介紹

最後,和你們介紹上述開放的能力在 OpenKruise 新領域如何去開放,以及怎麼拓展對 OpenKruise 的認知。OpenKruise 是阿里雲開源的 Kubernetes 擴展應用負載項目,本質上是圍繞 Kubernetes 雲原生應用去作一系列自動化能力的引擎,同時也是阿里巴巴經濟體上雲全面使用的部署基座。

OpenKruise 的定位,作的不是一個完整的平臺,更相似因而 Kubernetes 中一個拓展的產品。這個拓展的產品做爲一個 add on 的組件,提供了一系列針對在 Kubernetes 中部署應用,以及後續保護防禦應用可用、圍繞雲原生應用的一些自動化的能力,這些拓展能力或者加強能力,是原生 Kubernetes 所不具有,但也是迫切須要它所擁有這些能力,是阿里巴巴內部在雲原生逐漸演進過程當中去沉澱的一些通用能力。

目前,Kruise 提供瞭如下 workload 控制器:

  • CloneSet:提供了更加高效、肯定可控的應用管理和部署能力,支持優雅原地升級、指定刪除、發佈順序可配置、並行/灰度發佈等豐富的策略,能夠知足更多樣化的應用場景。

  • Advanced StatefulSet:基於原生 StatefulSet 之上的加強版本,默認行爲與原生徹底一致,在此以外提供了原地升級、並行發佈(最大不可用)、發佈暫停等功能。

  • SidecarSet:對 sidecar 容器作統一管理,在知足 selector 條件的 Pod 中注入指定的 sidecar 容器。

  • UnitedDeployment:經過多個 subset workload 將應用部署到多個可用區。

  • BroadcastJob:配置一個 job 在集羣中全部知足條件的 Node 上都跑一個 Pod 任務。

  • Advanced DaemonSet:基於原生 DaemonSet 之上的加強版本,默認行爲與原生一致,在此以外提供了灰度分批、按 Nodelabel 選擇、暫停、熱升級等發佈策略。

  • AdvancedCronJob:一個擴展的 CronJob 控制器,目前 template 模板支持配置使用 Job 或 BroadcastJob。

2. 原生 workload 能力缺陷

9.jpg

根據 Deployment 去 CloneSet、AdcancedStatefulSet 是由於原生 workload 能力缺陷有不少。你們能夠看到,基本上從 Kubernetes 1.10 版本以後,其實其餘的功能,包括 pod 裏面,它的字段仍是在不斷豐富,包括更多的 pod 的能力支持、更多的策略等,可是對於 workload 層面,就是 deployment 和 StatefulSet 層面,已經不傾向於作任何改動。社區在這背後的考慮是由於在不一樣公司、不一樣業務場景下,應用部署發佈層面需求不少。

Kubernetes 原生提供的 Deployment,是面向一些最通用最基礎的一些環境,沒辦法用它去知足全部的業務場景,但實際上社區是很是鼓勵有更高需求,更大更復雜場景規模需求的用戶,自行經過 CRD 去拓展編寫,利用更強大的 workload,來知足不一樣的業務的場景需求。

3. OpenKruise與原生能力對比

10.jpg

橙色:開源中  /  綠色:已開源

那麼,對於這場景而言,Kruise 已經作了比較完備的一個無狀態以及有狀態應用的部署,經過上圖表格能看到 Kruise 提供的 workload 和原生 deployment、StatefulSet、DaemonSet 的對比。

4. OpenKruise 2021 規劃

11.jpg

如上圖所示,OpenKruise 是一個雲原生應用自動化引擎,目前提供的 workload 能力在應用部署,但不會僅侷限於應用部署這一個領域的。

1)風險防控

在 2021 年上半年的規劃中,咱們會針對上面講到的雲原生應用的風險和防控的策略,會經過 OpenKruise 輸出給社區。包括 CRD 刪除防禦、級聯刪除防禦、全局 Pod 刪除流控、Pod 刪除/驅逐/原地升級防禦、自動爲 workload 生成 PDB/PUB 等。

2)Kruise-daemo

除此以外以前 OpenKruise 只是做爲一箇中心的控制器部署,下個版本中會提供一個 Kruise-daemon 經過 daemon set 部署到每一個節點上,能夠幫用戶去作一些鏡像預熱,發佈加速,容器重啓 ,單機調度優化的一些策略。

3)ControllerMesh

ControllerMesh 是 OpenKruise 提供出來幫助用戶管理用戶集羣中其餘運行時的一些控制器運行時的能力,經過流量控制等方式解決傳統控制器單住模式帶來的種種問題。

 最後,在 OpenKruise 項目社區建設方面,已經在 2020 年 11 月 11 號經 CNCF 技術監督委員會全體成員投票,一致贊成正式進入 CNCF Sanbox,在整個過程當中也獲得了 CNCF 積極的迴應,表示 OpenKruise 項目與 CNCF 倡導的理念很契合,鼓勵有更多像 OpenKruise 這樣能作一些通用化的,面向更復雜的場景,更大規模的一些這種自主的 Workload 能力的項目出現。

如今已經有不少公司在使用 OpenKruise 的這些能力,好比:

  • 基於原地升級、灰度發佈等需求,攜程在生產環境使用CloneSet、AdvancedStatefulSet 來分別管理無狀態、有狀態應用的服務,單集羣 Kruise workload 數量達到萬級別。

  • OPPO 公司不只大規模使用了 OpenKruise,還在下游配合其定製化的 Kubernetes 進一步增強了原地升級的能力,普遍應用在多個業務的後端運行服務中,經過原地更新覆蓋了 87% 左右的升級部署需求。

  • 此外,國內的用戶還有蘇寧、鬥魚 TV、有贊、比心、Boss 直聘、申通、小紅書、VIPKID、掌門教育、杭銀消費、萬翼 科技、多點 Dmall、佐疆科技、享住智慧、艾佳生活、永輝科技中心、跟誰學,國外的用戶有 Lyft、Bringg、 Arkane Systems 等。

  • Maintainer 5 位成員來自阿里巴巴、騰訊、Lyft

  • 51 位貢獻者

    • 國內:阿里雲、螞蟻集團、攜程、騰訊、拼多多...

    • 國外:微軟、Lyft、Spectro Cloud、Dsicord...
  • 2000+ GitHub Stars

  • 300+ Forks

若是你們對 OpenKruise 項目感興趣,有任何但願交流的話題,歡迎你們訪問 OpenKruise 官網GitHub

相關文章
相關標籤/搜索