效能平台研发篇(二)—— 基于KtEnv的路由染色方案

449 阅读5分钟

简介

传统开发模式会常备多套测试环境,但如果开发者想独立拉起一套专用测试环境,不仅费时费力,而且资源成本也是难以招架的,无人使用时产生数倍资源浪费。

  • 传统方案1. 常备多套测试环境

优点:环境随时可用

缺点:治标不治本,太多项目并行依然会不够用;无人使用时产生数倍资源浪费;额外的资源分配和管理问题

  • 传统方案2. 用helm等工具“快速”创建一套环境,用完就删

优点:空闲时资源浪费最少

缺点:批量拉起所有服务,整个环境就绪等待时间可能长达几分钟到几十分钟;有时候为了测试一个服务拉一套环境,运行时资源消耗高,带来极高的维护成本****

  • 今天我们将借助 virtual-environment(KtEnv) 工具实现环境复用与灵活的隔离,解决资源效能问题。

    • 实现每位开发者都可以低成本创建属于自己的开发环境;
  • 实现当多人协作研发软件时,可灵活联调,每位开发者同一时刻只能属于同一个隔离域,同一个隔离域里面的服务相互可见,并且当出现服务调用的时候,会优先调用隔离域里面的服务。不同隔离域里面的服务相互之间不可见,是互不影响的;

一、服务部署

开始前要确保集群内部署了 istio 服务,如果没有可以参考 Istio / Getting Started 进行部署

下面我们开始部署 KtEnv 相关组件

部署 KtEnv 组件

KtEnv 系统包含 Operator CRD 和 Admission Webhook 两个组件。

  • Webhook 组件用于将 Pod 的虚拟环境标签写入到其 Sidecar 容器的运行时环境变量内;
  • CRD 组件用于创建监听集群服务变化并动态生成路由规则的 VirtualEnvironmen t资源实例。
wget https://github.com/alibaba/virtual-environment/releases/download/v0.6.0/kt-virtual-environment-v0.6.0.zip 

unzip kt-virtual-environment-v0.6.0.zip && cd v0.6.0/

kubectl apply -f global/ktenv_crd.yaml kubectl apply -f global/ktenv_webhook.yaml

检查部署结果

Webhook 组件默认被部署到名为kt-virtual-environment 的 Namespace 中,包含一个 Service 和一个 Deployment 对象,以及它们创建的子资源对象,可用以下命令查看:

kubectl -n kt-virtual-environment get all

kubectl get crd virtualenvironments.env.alibaba.com

若分别输出类似以下信息,则表明 KtEnv 组件已经部署且正常运行。

NAME READY STATUS RESTARTS AGE pod/webhook-server-5dd55c79b5-rf6dl 1/1 Running 0 86s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/webhook-server ClusterIP 172.21.0.254 <none> 443/TCP 109s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/webhook-server 1/1 1 1 109s NAME DESIRED CURRENT READY AGE replicaset.apps/webhook-server-5dd55c79b5 1 1 1 86s

NAME CREATED AT virtualenvironments.env.alibaba.com 2020-04-21T13:20:35Z

部署 KtEnv Operator

Operator 是由 CRD 组件定义的虚拟环境管理器实例,需要在每个使用虚拟环境的 Namespace 里单独部署。同时为了让 Webhook 组件对目标 Namespace 起作用,还应该为其添加值为enabledenvironment-tag-injection标签。

以使用default Namespace为例,通过以下命令完成部署。

kubectl apply -n default -f ktenv_operator.yaml 

kubectl label namespace default environment-tag-injection=enabled

如果集群开启了RBAC,还需要部署相应的Role和ServiceAccount。

kubectl apply -n default -f ktenv_service_account.yaml

现在,Kubernetes集群就已经具备使用虚拟环境能力了。

二、创建虚拟环境

创建类型为 VirtualEnvironment 的资源定义文件,使用 kubectl apply 命令添加到Kubernetes 集群的目标 Namespace 中

参数介绍

无法复制加载中的内容

注意:VirtualEnvironment 实例只对其所在的 Namespace 有效。如有需要,可以通过在多个Namespace 分别创建相同配置的实例,实现跨 Namespace 和跨集群的隔离。

示例配置

如下配置我们以 dev 作为兜底环境,使用 "-" 划分不同环境,根据请求头 X-Virtual-Env 来进行路由。

apiVersion: env.alibaba.com/v1alpha2

kind: VirtualEnvironment

metadata:

  name: demo-virtualenv

spec:

  envHeader:

    name: X-Virtual-Env

    autoInject: true

  envLabel:

    name: virtual-env

    splitter: "-"

    defaultSubset: dev

    

# kubectl apply -n default -f path-to-virtual-environment-cr.yaml

实例创建后,会自动监听所在 Namespace 中的所有 Service、Deployment 和 StatefulSet 对象并自动生成路由隔离规则,形成虚拟环境。

现在虚拟环境规则已经配置完成,在集群中启动服务就可以享受到环境动态隔离带来的便利了,但需要注意下面应用适配的几个点。

三、Spring Cloud 应用程序适配

为应用Pod添加虚拟环境标签,并让服务在调用链上透传虚拟环境标签。

运维配置

  1. 为Deployment定义的Pod模板增加标识虚拟环境名称的Label(默认为 virtual-env
  2. 为应用程序添加透传标签Header的功能(默认请求头键为 X-Virtual-Env

开发配置

  1. 在向Spring Cloud服务注册中心注册实例时,使用服务相应的Kubernetes Service资源名称作为目标地址,具体做法为在程序的 application.propertiesapplication.yaml 文件中,根据所用的服务注册中心类型,将相应的注册地址改为Service资源名字。

这样一来,实际上是使用Kubernetes的服务发现机制替代了Spring Cloud原有的相应能力。

假设Service资源在Kubernetes里的spec.name值为app-js

若使用Nacos作为服务注册中心,则配置为:

spring.cloud.nacos.discovery.ip = app-js
  1. 由于Spring Cloud的RibbonClient组件在发送HTTP请求时默认不会携带Istio路由所需的Host请求头,还需要自行添加HTTP Client的拦截器来在请求发出前添加内容为Host: <当前服务名>的Header,使得请求能被Istio Sidecar处理。

总结

本期通过 kt-virtual-environment 工具为动态环境隔离提供了基础设施。关于服务适配代码改动细节会在本系列分享的第三章内容中讲述。