# Istio Integration Tests
This folder contains Istio integration tests that use the test framework checked in at
[istio.io/istio/pkg/test/framework](https://github.com/istio/istio/tree/master/pkg/test/framework).
## Table of Contents
1. [Overview](#overview)
1. [Writing Tests](#writing-tests)
1. [Adding a Test Suite](#adding-a-test-suite)
1. [Sub-Tests](#sub-tests)
1. [Parallel Tests](#parallel-tests)
1. [Using Components](#using-components)
1. [Writing Components](#writing-components)
1. [Running Tests](#running-tests)
1. [Test Parallelism and Kubernetes](#test-parellelism-and-kubernetes)
1. [Test Selection](#test-selection)
1. [Running Tests on CI](#running-tests-on-ci)
1. [Step 1: Add a Test Script](#step-1-add-a-test-script)
1. [Step 2: Add a Prow Job](#step-2-add-a-prow-job)
1. [Step 3: Update TestGrid](#step-3-update-testgrid)
1. [Environments](#environments)
1. [Diagnosing Failures](#diagnosing-failures)
1. [Working Directory](#working-directory)
1. [Enabling CI Mode](#enabling-ci-mode)
1. [Preserving State (No Cleanup)](#preserving-state-no-cleanup)
1. [Additional Logging](#additional-logging)
1. [Running Tests Under Debugger](#running-tests-under-debugger-goland)
1. [Reference](#reference)
1. [Helm Values Overrides](#helm-values-overrides)
1. [Commandline Flags](#command-line-flags)
1. [Notes](#notes)
1. [Running on a Mac](#running-on-a-mac)
## Overview
The goal of the framework is to make it as easy as possible to author and run tests. In its simplest
case, just typing ```go test ./...``` should be sufficient to run tests.
This guide walks through the basics of writing tests with the Istio test framework. For best
practices, see [Writing Good Integration Tests](https://github.com/istio/istio/wiki/Writing-Good-Integration-Tests).
## Writing Tests
The test framework is designed to work with standard go tooling and allows developers
to write environment-agnostics tests in a high-level fashion.
### Adding a Test Suite
All tests that use the framework, must run as part of a *suite*. Only a single suite can be defined per package, since
it is bootstrapped by a Go `TestMain`, which has the same restriction.
To begin, create a new folder for your suite under
[tests/integration](https://github.com/istio/istio/tree/master/tests/integration).
```console
$ cd ${ISTIO}/tests/integration
$ mkdir mysuite
```
Within that package, create a `TestMain` to bootstrap the test suite:
```go
func TestMain(m *testing.M) {
framework.
NewSuite("mysuite", m).
Run()
}
```
Next, define your tests in the same package:
```go
func TestMyLogic(t *testing.T) {
framework.
NewTest(t).
Run(func(ctx framework.TestContext) {
// Create a component
p := pilot.NewOrFail(ctx, ctx, cfg)
// Use the component.
// Apply Kubernetes Config
ctx.ApplyConfigOrFail(ctx, nil, mycfg)
// Do more stuff here.
}
}
```
The `framework.TestContext` is a wrapper around the underlying `testing.T` and implements the same interface. Test code
should generally not interact with the `testing.T` directly.
In the `TestMain`, you can also restrict the test to particular environment, apply labels, or do test-wide setup, such as
deploying Istio.
```go
func TestMain(m *testing.M) {
framework.
NewSuite("mysuite", m).
// Deploy Istio on the cluster
Setup(istio.Setup(nil, nil)).
// Run your own custom setup
Setup(mySetup).
Run()
}
func mySetup(ctx resource.Context) error {
// Your own setup code
return nil
}
```
### Sub-Tests
Go allows you to run sub-tests with `t.Run()`. Similarly, this framework supports nesting tests with `ctx.NewSubTest()`:
```go
func TestMyLogic(t *testing.T) {
framework.
NewTest(t).
Run(func(ctx framework.TestContext) {
// Create a component
g := galley.NewOrFail(ctx, ctx, cfg)
configs := []struct{
name: string
yaml: string
} {
// Some array of YAML
}
for _, cfg := range configs {
ctx.NewSubTest(cfg.name).
Run(func(ctx framework.TestContext) {
ctx.ApplyConfigOrFail(ctx, nil, mycfg)
// Do more stuff here.
})
}
})
}
```
Under the hood, calling `subtest.Run()` delegates to `t.Run()` in order to create a child `testing.T`.
### Parallel Tests
Many tests can take a while to start up for a variety of reasons, such as waiting for pods to start or waiting
for a particular piece of configuration to propagate throughout the system. Where possible, it may be desirable
to run these sorts of tests in parallel:
```go
func TestMyLogic(t *testing.T) {
framework.
NewTest(t).
RunParallel(func(ctx framework.TestContext) {
// ...
}
}
```
Under the hood, this relies on Go's `t.Parallel()` and will, therefore, have the same behavior.
A parallel test will run in parallel with siblings that share the same parent test. The parent test function
will exit before the parallel children are executed. It should be noted that if the parent test is prevented
from exiting (e.g. parent test is waiting for something to occur within the child test), the test will
deadlock.
Consider the following example:
```go
func TestMyLogic(t *testing.T) {
framework.NewTest(t).
Run(func(ctx framework.TestContext) {
ctx.NewSubTest("T1").
Run(func(ctx framework.TestContext) {
ctx.NewSubTest("T1a").
RunParallel(func(ctx framework.TestContext) {
// Run in parallel with T1b
})
ctx.NewSubTest("T1b").
RunParallel(func(ctx framework.TestContext) {
// Run in parallel with T1a
})
// Exits before T1a and T1b are run.
})
ctx.NewSubTest("T2").
Run(func(ctx framework.TestContext) {
ctx.NewSubTest("T2a").
RunParallel(func(ctx framework.TestContext) {
// Run in parallel with T2b
})
ctx.NewSubTest("T2b").
RunParallel(func(ctx framework.TestContext) {
// Run in parallel with T2a
})
// Exits before T2a and T2b are run.
})
})
}
```
In the example above, non-parallel parents T1 and T2 contain parallel children T1a, T1b, T2a, T2b.
Since both T1 and T2 are non-parallel, they are run synchronously: T1 followed by T2. After T1 exits,
T1a and T1b are run asynchronously with each other. After T1a and T1b complete, T2 is then run in the
same way: T2 exits, then T2a and T2b are run asynchronously to completion.
### Using Components
The framework itself is just a platform for running tests and tracking resources. Without these `resources`, there
isn't much added value. Enter: components.
Components are utilities that provide abstractions for Istio resources. They are maintained in the
[components package](https://github.com/istio/istio/tree/master/pkg/test/framework/components), which defines
various Istio components such as galley, pilot, and namespaces.
Each component defines their own API which simplifies their use from test code, abstracting away the
environment-specific details. This means that the test code can (and should, whe
istio源码20221231
需积分: 0 85 浏览量
更新于2022-12-31
收藏 248.85MB GZ 举报
Istio是一个强大的服务网格平台,它为微服务架构提供了流量管理、安全性和可观测性等核心功能。源码分析可以帮助我们深入理解其工作原理,从而更好地利用和定制这个工具。20221231版本的Istio源码包含了最新的开发成果和改进,以下将对Istio的一些关键组件和功能进行详细阐述。
Istio的核心组件包括:
1. **Envoy代理**:Envoy是Istio的服务间通信代理,作为数据平面的一部分,部署在每个服务旁边。它负责处理服务间的请求,提供负载均衡、熔断、限流、重试和故障注入等功能。Envoy的源码实现了一种高效的网络过滤器架构,使得这些功能可以灵活地添加和扩展。
2. **Pilot**:Pilot是控制平面的一部分,负责生成Envoy代理的配置(xDS协议),以控制服务发现和服务路由规则。Pilot通过与Kubernetes API服务器交互,获取服务元数据,并将这些信息转换为Envoy能理解的配置。
3. **Mixer**:Mixer负责执行策略和遥测数据收集。策略检查确保服务调用遵循预定义的访问控制策略,而遥测收集则包括日志、监控指标和跟踪数据。在较新版本中,Mixer的部分功能已被Envoy内置的Admission Control和Telemetry V2替代,以提高性能。
4. **Citadel**:Citadel是一个安全管理组件,它为服务提供身份验证和证书管理。它自动颁发和更新服务之间的TLS证书,确保服务间通信的安全。
5. **Galley**:Galley负责验证、处理和分发配置信息,它是Istio内部的配置处理器。
6. **Kiali**:Kiali是Istio的可视化工具,它提供了服务网格的图形化界面,帮助用户理解服务之间的依赖关系、流量和健康状况。
7. **Jaeger** 和 **Zipkin**:这些是分布式追踪系统,用于收集和可视化服务之间的调用链路,帮助开发者诊断延迟问题。
在源码中,我们可以看到各种编程语言的使用,如Go用于编写大部分控制平面组件,C++用于Envoy代理,以及Python用于一些工具和脚本。源码还包含了丰富的测试用例,确保了Istio的稳定性和可靠性。
通过深入研究Istio源码,开发者可以了解到如何自定义Envoy配置、实现新的策略或扩展遥测功能。此外,对于想要了解服务网格内部工作原理的系统架构师和运维人员来说,阅读源码也是一个宝贵的资源。例如,你可以探究如何实现服务发现的动态更新,或者如何配置Envoy以实现细粒度的流量管理策略。
Istio源码是学习服务网格、微服务治理和云原生架构的重要资料。通过对20221231版源码的分析,开发者可以更好地掌握Istio的新特性,优化其在生产环境中的应用,同时也可以为社区贡献代码,推动Istio的持续发展。