做者 | 张杰(冰羽)
来源 | 阿里巴巴云原生公众号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 能力,在继承模板的配置的同时还能提供更灵活的差别化配置,基本上已经能够知足大部分客户在边缘场景下特殊的需求。