简介
传统开发模式会常备多套测试环境,但如果开发者想独立拉起一套专用测试环境,不仅费时费力,而且资源成本也是难以招架的,无人使用时产生数倍资源浪费。
- 传统方案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 起作用,还应该为其添加值为enabled
的environment-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添加虚拟环境标签,并让服务在调用链上透传虚拟环境标签。
运维配置
- 为Deployment定义的Pod模板增加标识虚拟环境名称的Label(默认为
virtual-env
) - 为应用程序添加透传标签Header的功能(默认请求头键为
X-Virtual-Env
)
开发配置
- 在向Spring Cloud服务注册中心注册实例时,使用服务相应的Kubernetes Service资源名称作为目标地址,具体做法为在程序的
application.properties
或application.yaml
文件中,根据所用的服务注册中心类型,将相应的注册地址改为Service资源名字。
这样一来,实际上是使用Kubernetes的服务发现机制替代了Spring Cloud原有的相应能力。
假设Service资源在Kubernetes里的spec.name
值为app-js
若使用Nacos作为服务注册中心,则配置为:
spring.cloud.nacos.discovery.ip = app-js
- 由于Spring Cloud的
RibbonClient
组件在发送HTTP请求时默认不会携带Istio路由所需的Host
请求头,还需要自行添加HTTP Client的拦截器来在请求发出前添加内容为Host: <当前服务名>
的Header,使得请求能被Istio Sidecar处理。
总结
本期通过 kt-virtual-environment 工具为动态环境隔离提供了基础设施。关于服务适配代码改动细节会在本系列分享的第三章内容中讲述。