在前面的文章中详细解读了 SMI 规范,以及我们引入可编程代理 Pipy 对 OSM 进行扩展。在替换了 sidecar 代理之后,不能影响服务网格已有的功能。OSM 代码库中有提供端到端的测试用例,我们通过其来验证以 Pipy 为代理的 OSM 的各项功能。
阅读本文您将收获:
端到端测试的介绍
服务网格端到端测试的关注点
借助测试深入了解 SMI 规范
端到端测试
什么是端到端测试
端到端测试(End-to-End Testing,e2e testing) 是软件的一种测试方法,通过模拟真实用户场景来测试和验证系统及其集成和数据完整性组件。通过从头到尾(执行产品所有可以完成的操作)对整个软件产品的测试,确保应用按预期运行。
如今的软件系统很复杂,与众多的子系统相互连接。比如 Kubernetes 中的多个组件共同完成对象真实状态与期望状态相匹配。
端到端测试的好处
由于以下好处,使得端到端测试被广泛采用:
扩大测试覆盖率
确保应用程序的正确性
所选发布时间
降低成本
检测错误
端到端测试的步骤
分析需求,清楚了解应用的各方面如何工作
根据需求设置测试环境
分析硬件和软件需求
列出每个系统的期望响应
列出测试这些响应的测试方法
设计测试用例
运行测试和保存结果
服务网格的端到端测试
OSM 运行在 Kubernetes 之上,实现了 SMI API 还有自定义的 API,比如 IngressBackend
、Egress
、UpstreamTrafficSetting
。测试时要覆盖功能性的测试,对这些 API 进行一一的测试,以及不同网格配置对功能的影响;同时还会有非功能性的测试,测试网格的容错性、可替换组件等等。
下面列出非功能性测试和功能性测试的部分测试用例,并进行说明。
非功能性测试
测试使用不同的证书管理器实现:cert-manager、Vault
测试控制面重启对数据面的影响
控制面配置:动态修改网格的 enableDebugServer
配置,测试能否开启控制面的 debug 端口
控制面配置:动态修改网格的 enableEgress
配置,检查 egress 流量
控制面配置:开启/关闭宽松模式的影响
控制平面的升级对系统的影响
对 Kubernetes 版本的检查和支持
......
功能性测试
访问控制
在 tests/e2e/e2e_deployment_client_server_test.go
中模拟了多个 Deployment 作为客户端,配合 TrafficTarget
来访问同一个目标服务。
下面访问策略中配置了源服务和目标服务的 service account,同时通过 HTTPRouteGroup
的流量规格匹配所有的 HTTP 请求。在测试用例中,每个客户端(Deployment)都使用各自的 service account 进行部署,并配置独立的 TrafficTarget
:
apiVersion: specs.smi-spec.io/v1alpha4
kind: HTTPRouteGroup
metadata:
name: client4
namespace: server
spec:
matches:
- methods:
- '*'
name: all
pathRegex: .*
---
apiVersion: access.smi-spec.io/v1alpha3
kind: TrafficTarget
metadata:
name: client4
namespace: server
spec:
destination:
kind: ServiceAccount
name: server
namespace: server
rules:
- kind: HTTPRouteGroup
matches:
- all
name: client4
sources:
- kind: ServiceAccount
name: client4
namespace: client4
复制代码
流量分流
在 tests/e2e/e2e_trafficsplit_test.go
中一共包含了三个测试用例,使用同样的分流策略进行验证:
apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
creationTimestamp: "2022-05-19T08:20:20Z"
generation: 1
name: traffic-split
namespace: server
resourceVersion: "1797"
uid: db28de4b-3088-4377-90cd-775574afb876
spec:
backends:
- service: server0
weight: 20
- service: server1
weight: 20
- service: server2
weight: 20
- service: server3
weight: 20
- service: server4
weight: 20
service: traffic-split
复制代码
a. 禁用宽松模式(网格配置 enablePermissiveTrafficPolicyMode
为 false)下,添加访问策略 TrafficTarget
,以及分流策略 TrafficSplit
后,服务的所有后端实例(通过 TrafficSplit.Spec.Backends
指定)都可以提供 HTTP 服务,完成 HTTP 流量的分流。
apiVersion: access.smi-spec.io/v1alpha3
kind: TrafficTarget
metadata:
name: client0-server4
namespace: server
spec:
destination:
kind: ServiceAccount
name: server4
namespace: server
rules:
- kind: HTTPRouteGroup
matches:
- all
name: client0-server4
sources:
- kind: ServiceAccount
name: client0
namespace: client0
---
apiVersion: specs.smi-spec.io/v1alpha4
kind: HTTPRouteGroup
metadata:
name: client1-server4
namespace: server
spec:
matches:
- methods:
- '*'
name: all
pathRegex: .*
复制代码
b. 同样是禁用宽松模式,对于 TCP 的流量需要配置 TCP 的访问控制策略(通过 TCPRoute
匹配目标服务的端口来匹配)。
apiVersion: access.smi-spec.io/v1alpha3
kind: TrafficTarget
metadata:
creationTimestamp: "2022-05-19T08:26:31Z"
generation: 1
name: client1-server4
namespace: server
resourceVersion: "5337"
uid: ae1662a1-1abb-4f9b-90f0-3fb5b42d6af1
spec:
destination:
kind: ServiceAccount
name: server4
namespace: server
rules:
- kind: TCPRoute
name: client1-server4
sources:
- kind: ServiceAccount
name: client1
namespace: client1
---
apiVersion: specs.smi-spec.io/v1alpha4
kind: TCPRoute
metadata:
name: client1-server4
namespace: server
spec:
matches:
ports:
- 14001
复制代码
c. 在宽松模式下,只需配置 TrafficSplit
即可实现流量分流,而无需设置 TrafficTarget
。
Ingress
在 tests/e2e/e2e_ingressbackend.go
中,验证在只有 Ingress
的情况下,是无法访问到目标服务的。只有在添加了从(src)Ingress
到(dst)目标服务的 IngressBackend
之后才会允许访问,否则会被 backend 服务拒绝。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: service-dede0003-31db-49fe-ad90-6e2c8d1f6e1a
namespace: server-d71ba86b-eebc-44ff-90d3-109a3ab0f08b
spec:
ingressClassName: nginx
rules:
- http:
paths:
- backend:
service:
name: service-dede0003-31db-49fe-ad90-6e2c8d1f6e1a
port:
number: 80
path: /status/200
pathType: ImplementationSpecific
---
apiVersion: policy.openservicemesh.io/v1alpha1
kind: IngressBackend
metadata:
name: httpbin-http
namespace: server-d71ba86b-eebc-44ff-90d3-109a3ab0f08b
spec:
backends:
- name: service-dede0003-31db-49fe-ad90-6e2c8d1f6e1a
port:
protocol: http
number: 80
sources:
- kind: Service
name: ingress-nginx-controller
namespace: ingress-ns
复制代码
Egress
在 tests/e2e/e2e_egress_policy_test.go
中对 Egress 的功能进行的测试。下面的策略中配置 Egress 访问策略的使用范围:
因此访问 http://httpbin.org:80/status/200
的请求是被允许的,而访问 https://httpbin.org:443/status/403
的请求被拒绝。
apiVersion: specs.smi-spec.io/v1alpha4
kind: HTTPRouteGroup
metadata:
name: httpbin-status
namespace: client
spec:
matches:
- name: status
pathRegex: /status.*
---
apiVersion: policy.openservicemesh.io/v1alpha1
kind: Egress
metadata:
name: httpbin-80
namespace: client
spec:
hosts:
- httpbin.org
matches:
- apiGroup: specs.smi-spec.io/v1alpha4
kind: HTTPRouteGroup
name: httpbin-status
ports:
- number: 80
protocol: http
sources:
- kind: ServiceAccount
name: serviceaccount-435e6b64-43e2-4095-988e-fad107a65304
namespace: client
复制代码
实施
OSM 中使用 Ginkgo 作为测试框架。Ginkgo 是个为 Go 设计的 BDD 风格的测试框架,可与匹配器 Gomega 配合使用,帮助开发人员编写富有表现力的全方位测试。
接下来,我们看下如何为 Flomesh OSM 执行 e2e 测试。
操作
下面的步骤展示了从克隆源码到执行 e2e 测试的整个流程,运行环境:
下载源码:
$ git clone https://github.com/flomesh-io/osm.git -b v1.1.0-arm
复制代码
安装环境:Docker、K8s、Go 等:
$ cd osm/pipy/
#安装docker和k8s工具等基础环境
$ make k8s-tools
#安装golang
$ make golang
复制代码
初始化 osm 的编译环境,并缓存依赖的镜像。
#初始化osm编译环境,只需执行一次
$ make once
#缓存相关依赖的镜像
$ make cache
复制代码
将 OSM 的 sidecar 镜像替换为 Pipy,并构建 OSM 组件镜像和 CLI:
#将sidecar切换为pipy
$ make pipy
#编译osm的images和cli
$ make build
#无需在 e2e 中再次构建镜像
$ make disable-test-e2e-docker-build
复制代码
回到项目根目录,使用 kind 创建集群:
$ cd ../
# 使用 kind 创建集群,测试结束后通过 make kind-reset 销毁集群
$ make kind-up
# 设置节点可以调度 ingress
$ kubectl label node osm-worker ingress-ready=true
复制代码
接下来就可以运行测试用例了,由于 Pipy 在本月底(5 月)支持 HTTP/2 以及不需要 WASM 来对 sidecar 进行扩展,如果直接执行命令 make test-e2e
,相关的测试会失败。这时我们可以通过指定用例来逐个运行:
E2E_FLAGS="xxxx" make test-e2e
复制代码
在 wiki E2E TEST REPORT 中,可以下载完整的测试报告,从中可以找到用例的名字来手动运行测试。
总结
相信通过本文您应该对服务网格的端到端测试有一定的了解。当前 OSM 一共有 50 多个测试用例,但是对于复杂的服务网格系统来说,不一定能覆盖所有的功能场景(比如上面提到的 UpstreamTrafficSetting
API),这也是端到端测试需要不断完善以增加覆盖率的原因。
评论