如何为服务网格做端到端测试

在前面的文章中详细解读了 SMI 规范,以及我们引入可编程代理 Pipy 对 OSM 进行扩展。在替换了 sidecar 代理之后,不能影响服务网格已有的功能。OSM 代码库中有提供端到端的测试用例,我们通过其来验证以 Pipy 为代理的 OSM 的各项功能。

阅读本文您将收获:

端到端测试的介绍服务网格端到端测试的关注点借助测试深入了解 SMI 规范

端到端测试

什么是端到端测试

端到端测试(End-to-End Testing,e2e testing) 是软件的一种测试方法,通过模拟真实用户场景来测试和验证系统及其集成和数据完整性组件。通过从头到尾(执行产品所有可以完成的操作)对整个软件产品的测试,确保应用按预期运行。

如今的软件系统很复杂,与众多的子系统相互连接。比如 Kubernetes 中的多个组件共同完成对象真实状态与期望状态相匹配。

端到端测试的好处

由于以下好处,使得端到端测试被广泛采用:

扩大测试覆盖率确保应用程序的正确性所选发布时间降低成本检测错误

端到端测试的步骤

1.分析需求,清楚了解应用的各方面如何工作2.根据需求设置测试环境3.分析硬件和软件需求4.列出每个系统的期望响应5.列出测试这些响应的测试方法6.设计测试用例7.运行测试和保存结果

服务网格的端到端测试

OSM 运行在 Kubernetes 之上,实现了 SMI API[1] 还有自定义的 API,比如 IngressBackendEgressUpstreamTrafficSetting。测试时要覆盖功能性的测试,对这些 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 访问策略的使用范围:

使用指定 service account 部署的源服务访问目标的 host 为 httpbin.org访问目标的端口为 80,且是 HTTP 协议满足 httpbin-status 中的流量匹配条件,即访问的路径是 /status

因此访问 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[2] 作为测试框架。Ginkgo 是个为 Go 设计的 BDD 风格的测试框架,可与匹配器 Gomega[3] 配合使用,帮助开发人员编写富有表现力的全方位测试。

在每一个用例开始时,都要进行环境的初始化,保证各个测试用例的独立性;同样,在测试结束都要对数据进行清理,防止影响后续的测试。用例中的每一步操作,比如启动集群、创建 Deployment、模拟请求的结果等,都要对操作的结果借助 Gomega 进行断言。

接下来,我们看下如何为 Flomesh OSM 执行 e2e 测试。

操作

下面的步骤展示了从克隆源码到执行 e2e 测试的整个流程,运行环境:

Ubuntu 20.04Go 1.17

下载源码:

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[4] 中,可以下载完整的测试报告,从中可以找到用例的名字来手动运行测试。

总结

相信通过本文您应该对服务网格的端到端测试有一定的了解。当前 OSM 一共有50 多个测试用例,但是对于复杂的服务网格系统来说,不一定能覆盖所有的功能场景(比如上面提到的 UpstreamTrafficSetting API),这也是端到端测试需要不断完善以增加覆盖率的原因。

引用链接

[1] SMI API: https://smi-spec.io
[2] Ginkgo: https://onsi.github.io/ginkgo/
[3] Gomega: https://onsi.github.io/gomega/
[4] E2E TEST REPORT: https://github.com/flomesh-io/osm/wiki/E2E-TEST-REPORT-FOR-TAG:v1.1.0-arm


原文始发于微信公众号(Flomesh):如何为服务网格做端到端测试

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/59587.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!