做者 | 張傑(冰羽)
來源 | 阿里巴巴雲原生公衆號node
在正文開始以前,咱們先回顧一下單元化部署的概念和設計理念。在邊緣計算場景下,計算節點具備很明顯的地域分佈屬性,相同的應用可能須要部署在不一樣地域下的計算節點上。以 Deployment 爲例,以下圖所示,傳統的作法是先將相同地域的計算節點設置成相同的標籤,而後建立多個 Deployment,不一樣 Deployment 經過 NodeSelectors 選定不一樣的標籤,從而實現將相同的應用部署到不一樣地域的需求。nginx
可是隨着地域分佈愈來愈多,使得運維變得愈來愈複雜,具體表如今如下幾個方面:git
基於以上需求和問題,openyurt 的 yurt-app-manager 組件提供的單元化部署(UnitedDeployment)經過更上層次的抽象,對這些子的 Deployment 進行統一管理:自動建立/更新/刪除,從而大幅簡化了運維複雜度的問題。github
yurt-app-manager 組件:
https://github.com/openyurtio/yurt-app-managerapi
以下圖所示:服務器
單元化部署(UnitedDeployment)對這些 Workload 進行了更高層次的抽象,UnitedDeployment 包含兩個主要配置:WorkloadTemplate 和 Pools。workloadTemplate 格式能夠是Deployment 也能夠是Statefulset。Pools 是一個列表,每一個列表都有一個 Pool 的配置,每一個 Pool 都有它的 name、replicas 和 nodeSelector 配置。經過 nodeSelector 能夠選擇一組機器, 所以在邊緣場景下 Pool 咱們能夠簡單的認爲它表明了某個地域下的一組機器。使用WorkloadTemplate + Pools 的定義,咱們能夠很容易的將一個 Deployment 或者 Statefulset 應用分發到不一樣的地域中去。app
下面是一個具體的 UnitedDeployment 例子:運維
apiVersion: apps.openyurt.io/v1alpha1 kind: UnitedDeployment metadata: name: test namespace: default spec: selector: matchLabels: app: test workloadTemplate: deploymentTemplate: metadata: labels: app: test spec: selector: matchLabels: app: test template: metadata: labels: app: test spec: containers: - image: nginx:1.18.0 imagePullPolicy: Always name: nginx topology: pools: - name: beijing nodeSelectorTerm: matchExpressions: - key: apps.openyurt.io/nodepool operator: In values: - beijing replicas: 1 - name: hangzhou nodeSelectorTerm: matchExpressions: - key: apps.openyurt.io/nodepool operator: In values: - hangzhou replicas: 2
UnitedDeployment 控制器的具體邏輯以下:ide
用戶定義了一個 UnitedDeployment CR , CR 裏定義了一個 DeploymentTemplate 和兩個 Pool。spa
UnitedDeployment 控制器檢測到 name 爲 test 的 UnitedDeployment CR 實例被建立後,會首先根據 DeploymentTemplate 裏的配置生成一個 Deployment 的模板對象,根據 Pool1 和 Pool2 的配置和 Deployment 的模板對象,分別生成 name 前綴爲 test-hangzhou- 和 test-beijing- 的兩個 deployment 資源對象,這兩個 Deployment 資源對象有本身的 nodeselector 和 replica 配置。這樣經過使用 workloadTemplate+Pools 的形式,能夠將 workload 分發到不一樣的地域,而無需用戶維護大量的 Deployment 資源。
UnitedDeployment 經過一個單元化部署實例就能夠自動維護多個 Deployment 或者 Statefulset 資源,每一個 Deployment 或者 Statefulset 資源都遵循統一的命名規範。同時還能實現 Name、NodeSelectors 和 Replicas 等的差別化配置。能極大地簡化用戶在邊緣場景下的運維複雜度。
UnitedDeployment 能知足用戶的大部分需求,可是在咱們進行推廣和客戶落地以及在與社區同窗討論的過程當中,逐漸發如今一些特殊場景下,UnitedDeployment 提供的功能還顯得有點不足,例如以下場景:
這些需求促使了 UnitedDeployment 須要提供針對每一個 Pool 作一些個性化配置的功能,容許用戶根據不一樣節點池下的實際狀況作一些個性化的配置,好比鏡像、pod 的 request 和 limit 等等。爲了最大化的提供靈活性,通過討論咱們決定在 Pool 裏增長 Patch 的字段,容許用戶自定義 Patch 內容,可是須要遵循Kubernetes 的 strategic merge patch規範,其行爲與咱們經常使用的 kubectl patch 有點相似。
pool 裏新增 patch,示例以下:
pools: - name: beijing nodeSelectorTerm: matchExpressions: - key: apps.openyurt.io/nodepool operator: In values: - beijing replicas: 1 patch: spec: template: spec: containers: - image: nginx:1.19.3 name: nginx
patch 裏定義的內容,須要遵循Kubernetes 的 strategic merge patch 規範, 若是用過 kubectl patch 的同窗就很容易的知道 patch 內容如何書寫,具體能夠參照使用 kubectl patch 更新 Kubernetest api 對象。
接下來咱們演示一下 UnitedDeployment patch 的使用。
yurt-app-manager 組件:
https://github.com/openyurtio/yurt-app-manager
cat <<EOF | kubectl apply -f - apiVersion: apps.openyurt.io/v1alpha1 kind: UnitedDeployment metadata: name: test namespace: default spec: selector: matchLabels: app: test workloadTemplate: deploymentTemplate: metadata: labels: app: test spec: selector: matchLabels: app: test template: metadata: labels: app: test spec: containers: - image: nginx:1.18.0 imagePullPolicy: Always name: nginx topology: pools: - name: beijing nodeSelectorTerm: matchExpressions: - key: apps.openyurt.io/nodepool operator: In values: - beijing replicas: 1 - name: hangzhou nodeSelectorTerm: matchExpressions: - key: apps.openyurt.io/nodepool operator: In values: - hangzhou replicas: 2 EOF
實例中 workloadTemplate 使用了 Deployment 模板, 其中 name 爲 nginx 的鏡像爲 nginx:1.18.0。同時拓撲裏定義了兩個 pool:beijing 和 hangzhou,replicas 數目分別爲 1 和 2。
# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE test-beijing-rk8g8 1/1 1 1 6m4s test-hangzhou-kfhvj 2/2 2 2 6m4s
能夠看到 yurt-app-manager 控制器建立了兩個 Deployment,分佈對應 beijing 和 hangzhou 的 pool,Deployment 的命名規範以 {UnitedDeployment name}-{pool name} 爲前綴。查看這兩個 Deployment 配置咱們能夠發現,Replicas 和 Nodeselector 繼承了對應的每一個 Pool 的配置,而其餘的配置則繼承了 workloadTemplate 模板的配置。
# kubectl get pod NAME READY STATUS RESTARTS AGE test-beijing-rk8g8-5df688fbc5-ssffj 1/1 Running 0 3m36s test-hangzhou-kfhvj-86d7c64899-2fqdj 1/1 Running 0 3m36s test-hangzhou-kfhvj-86d7c64899-8vxqk 1/1 Running 0 3m36s
能夠看到建立了 1 個 name 前綴爲 test-beijing 的 pod,2 個 name 前綴爲 test-hangzhou 的 pod。
使用 kubectl edit ud test 命令爲 beijing 的 pool 增長 patch 字段,patch 裏的內容是修改 name 爲 nginx 的 container 鏡像版本爲:nginx:1.19.3。
格式以下:
- name: beijing nodeSelectorTerm: matchExpressions: - key: apps.openyurt.io/nodepool operator: In values: - beijing replicas: 1 patch: spec: template: spec: containers: - image: nginx:1.19.3 name: nginx
從新查看前綴爲 test-beijing 的 Deployment,能夠看到 container 的鏡像配置已經變成了 1.19.3。
kubectl get deployments test-beijing-rk8g8 -o yaml
經過 UnitedDeployment 的 workloadTemplate + Pools 的形式,能夠將 workload 經過繼承的模板的方式快速分發到不一樣的地域。在加上 Pool 的 patch 能力,在繼承模板的配置的同時還能提供更靈活的差別化配置,基本上已經能夠知足大部分客戶在邊緣場景下特殊的需求。