By Shimian
According to research data, around 70% of production failures are caused by changes. To mitigate risks during the change process, we want to use a small portion of targeted traffic to verify that the newly released application is functioning normally during deployment. Even if issues arise with the new version, they can be detected in time to minimize impact and ensure overall stability. This is the capability of end-to-end canary release under microservices architecture.
Microservices Engine (MSE) offers a suite of mature and out-of-the-box capabilities for end-to-end canary release scenarios in a microservices environment.
With the deepening transformation of enterprise microservices, there are more demands for microservices governance scenarios and applications, such as end-to-end canary release. By default, MSE supports canary routing policies based on content rules and percentage rules. According to canary contents, parameters such as header and params, and multiple matching policies such as exact, prefix, and regular expression are all supported. This meets the requirements of common end-to-end canary scenarios.
However, how can we handle it if the policies provided by MSE cannot meet the requirements in complex scenarios?
Next, we will discuss several complex but reasonable canary requirements.
In fact, there are many other reasonable demands for end-to-end canary release, for example:
Faced with a series of complex but reasonable demands with customized requirements, it is difficult for the product level to fully support them. These demands are very common in practical production, which is faced by enterprise customers. However, it seems that the configuration solution of the current MSE console does not perfectly cope with these diverse practical scenarios. After all, when we turn our attention to the production practices of different enterprise customers, we will find that the change and diversity of complex scenarios will only become more significant. So, how can we effectively meet the demands of end-to-end canary release in complex environments?
What is Wasm? Wasm (WebAssembly) is a portable, high-performance binary instruction set that enables code to run in a web browser. Envoy leverages Wasm as a plugin extension mechanism, allowing developers to create custom feature extensions tailored to specific needs.
The extension mechanism of the cloud-native gateway Wasm plug-in works as follows:
The MSE plug-in marketplace also provides some official platform plug-ins such as default authentication, throttling, and security protection to improve the security and stability of gateways. It also supports multi-language custom extensions to meet the requirements for custom traffic governance on gateways.
The advantages of the MSE Wasm plug-in extension mechanism include:
With its unique lightweight and high performance features, the Wasm plug-in brings innovative scalability to cloud-native gateways without significant performance overhead. The Wasm plug-in runs in a sandbox environment and provides a secure and controllable way to deploy custom logic. This not only ensures the flexibility and scalability of the gateway but also ensures minimal impact on the overall performance.
It seems that the MSE cloud-native gateway Wasm plug-in is indeed an elegant and convenient way to meet various end-to-end canary requirements. Next, I will write the Wasm plug-in to implement end-to-end canary release in complex conditions.
As mentioned above, the Wasm plug-in supports multi-language extensions, so we can choose the language that we are good at for development. This article uses the Go language as an example.
The cloud-native gateway provides wrapper packages and related APIs for us to quickly write Wasm plug-ins.
1. The cloud-native gateway configures canary routing based on x-mse-tag. For more information, see Implement an End-to-End Canary Release by Using MSE Cloud-native Gateways [1].
Configure the service swimlanes as follows:
Configure the cloud-native gateway route as follows:
After we create a canary lane, all the requests with x-mse-tag=gray in the header will be considered canary traffic, and they will first go to the canary environment in subsequent traces. Therefore, in the Wasm plug-in, we can perform any custom calculation and matching on the traffic. As long as it meets canary conditions, we can add an identifier named "x-mse-tag" with a value of "gray" to the request header. In this way, we can label and identify the canary traffic.
2. Define the plug-in extension configuration.
type ParamsRandomConfig struct {
# The switch of parameter ratio function
paramsRandomEnable bool
# The value of the header that the parameter ratio is based on, for example, userId
paramsRandomHeaderKey string
# Percentage value of the parameter ratio,
paramsPercentageRatio int64
}
3. Parse the extension parameters of the plug-in. The YAML configuration that you enter in the plug-in configuration in the console is automatically converted to JSON, so it can parse the configuration directly from the JSON parameter.
// The YAML configuration that you enter in the plug-in configuration in the console is automatically converted to JSON, so it can parse the configuration directly from the JSON parameter.
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
// Parse the configuration and update it to the config file.
config.paramsRandomEnable = json.Get("paramsRandomEnable").Bool()
config.paramsRandomHeaderKey = json.Get("paramsRandomHeaderKey").String()
config.paramsPercentageRatio = json.Get("paramsPercentageRatio").Int()
return nil
}
4. Request processing Filter compilation.
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
if config.paramsRandomEnable {
randomHeaderValue, err := proxywasm.GetHttpRequestHeader(config.paramsRandomHeaderKey)
if err != nil {
proxywasm.LogErrorf("get header enhance error: %v", err)
return types.ActionContinue
}
// Obtain the hash of the target parameter value for percentage calculation.
hash := sha256.Sum256([]byte(randomHeaderValue))
hashInt := new(big.Int)
hashInt.SetBytes(hash[:])
modulo := new(big.Int).Mod(hashInt, big.NewInt(100))
result := modulo.Cmp(big.NewInt(config.paramsPercentageRatio))
if result <= 0 {
// Write x-mse-tag=gray to indicate that the request traffic is marked as gray, and the node in the gray environment will be preferentially used in subsequent traces.
// If the corresponding application does not have a gray environment, it will fall back to the baseline environment.
proxywasm.AddHttpRequestHeader("x-mse-tag", "gray")
} else {
// The traffic that does not meet the canary conditions.
proxywasm.LogInfof("set header false value: %s, hash: %s", randomHeaderValue, hashInt)
}
}
return types.ActionContinue
}
5. Compile and generate Wasm files.
Run the following command to compile the Wasm file.
go mod tidy
tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go
If the compilation is successful, the file main.wasm will be created in the current directory. The main.wasm file is used in the example for local debugging in this topic.
If you use a custom plug-in that is created on the Plug-in Marketplace page in the MSE console, you can directly upload this file.
6. Configure the parameters and verify the parameter ratio function.
As shown in the above figure, we specify userId in the header as the parameter that the percentage is based on, and configure the ratio value of the 10% canary traffic. After we click Save, the configuration takes effect in real time.
In the request process, the header of userId=1 always goes to the canary environment, and the request of userId=11 always goes to the baseline environment.
7. Observe plug-in logs.
So far, we have implemented the parameter ratio requirements based on specific headers by writing the Wasm plug-in.
We can use the Wasm plug-in to meet various requirements of end-to-end canary release, including but not limited to the following aspects:
• Canary Release Based on User ID
Requests from specific users can be routed to the corresponding canary environment based on the user's identity, role, and permissions to implement end-to-end canary releases for individual users.
• Canary Release Based on Geographic Location
Requests can be routed to the canary environment of a specific region based on the user's geographical location information to meet the canary requirements of a specific region.
• Canary Release Based on Traffic Ratio
Requests can be routed to different canary environments based on the traffic ratio to implement end-to-end canary release with proportionally distributed traffic.
• Canary Release Based on Complex Attributes of Request Packages
Requests can be routed to the corresponding canary environment by determining whether specific conditions are met based on the request attributes, such as the request header, request body, and query parameters.
Because of its great adaptability, the Wasm plug-in can be tailored to meet different requirements for end-to-end canary release. This provides unlimited possibilities for customized business scenarios, enabling canary testing and release to be performed flexibly based on unique business requirements. Especially for compute-intensive and stateless tasks, such as authentication, encryption and obfuscation of requests/responses, and content transformation, it is ideal to deploy the logic at the gateway layer. It not only keeps the system simple and flexible but also ensures low performance loss of core gateway functions, which provides significant benefits in optimizing resource usage and maintaining service quality.
At present, the MSE Wasm plug-in supports Redis access. Of course, we should use the Wasm plug-in based on the use case. If the logic needs to connect to the database or multi-threaded processing, it is not suitable to be made into a gateway plug-in. Currently, Wasm plug-in does not support these capabilities.
[1] Implement an End-to-End Canary Release by Using MSE Cloud-native Gateways
https://www.alibabacloud.com/help/en/mse/user-guide/implement-an-end-to-end-canary-release-by-using-mse-cloud-native-gateways
[2] Plug-in Development: Microservices Engine (MSE)
https://www.alibabacloud.com/help/en/mse/user-guide/14/
Alibaba Cloud Observability Episode 6 | How to Use Prometheus for Metrics Monitoring?
204 posts | 12 followers
FollowAlibaba Cloud Native Community - September 12, 2023
feuyeux - May 8, 2021
Alibaba Cloud Native Community - May 17, 2022
Alibaba Cloud Native - May 11, 2022
Xi Ning Wang(王夕宁) - July 21, 2023
OpenAnolis - February 2, 2023
204 posts | 12 followers
FollowAlibaba Cloud Service Mesh (ASM) is a fully managed service mesh platform that is compatible with Istio.
Learn MoreAccelerate and secure the development, deployment, and management of containerized applications cost-effectively.
Learn MoreMSE provides a fully managed registration and configuration center, and gateway and microservices governance capabilities.
Learn MoreMulti-source metrics are aggregated to monitor the status of your business and services in real time.
Learn MoreMore Posts by Alibaba Cloud Native