In this section, we will continue the previous task [Deploy Dubbo-go application in Istio environment].
In the previous task, we deployed a set of Dubbo-go Server and Client applications in the cluster, and verified the success of service discovery and invocation. In this section, we will create a new version of the server-side application. By configuring VirtualService and DestinationRule, routing management and traffic transfer capabilities are realized
$ dubbogo-cli newApp .
func (s *GreeterServerImpl) SayHello(ctx context.Context, in *api.HelloRequest) (*api.User, error) {
return &api.User{Name: "Hello " + in.Name, Id: "v2.0.0"}, nil
}
Modify the following configuration file, use the xds protocol as the registration center, and load the service structure named GreeterServerImpl.
conf/dubbogo.yaml
dubbo:
registries:
xds:
protocol: xds
address: istiod.istio-system.svc.cluster.local:15010
protocols:
triple:
name: tri
port: 20000
provider:
services:
GreeterServerImpl:
interface: "" # read from stub
At this point, the application development is complete.
Specify the image to be built:
Modify the following fields in the Makefile, specify the address and version of the image to be built, and change the image tag to 2.0.0.
Specify the name that needs to be installed through helm.
IMAGE = xxx/dubbo-go-server
TAG = 2.0.0
HELM_INSTALL_NAME = dubbo-go-server
Specify the application and image to be deployed:
Modify the following fields in chart/app/Chart.yaml, and specify the current application name as dubbo-go-server
. When we created the v1 version of the service, we already had the service of the application. The template will not be created during this deployment service.
apiVersion: v1
name: dubbo-go-server
description: dubbo-go-server
Modify the following fields in chart/app/values.yaml, specify the image to be deployed as 2.0.0, and the currently developed application version dubbogoAppVersion as v2.
The deployed image needs to be consistent with the image built above. The current application version is used for mesh traffic rule control.
image:
repository: xxx/dubbo-go-server
pullPolicy: Always
tag: "2.0.0"
# Dubbo-go-mesh version control labels
version:
labels:
dubbogoAppVersion: v2
At this point, the build parameters and release parameters have been specified, ready to build and deploy.
Build and push images
$ make build
(locally for amd64 machines)
or
$ make buildx-publish
(Local is arm64 machine, depends on docker buildx command)
Publish Dubbo-go Server v2 to the cluster
$ make deploy
NAME: dubbo-go-server-v2
LAST DEPLOYED: Thu Apr 7 12:29:28 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART dubbo-go-client default 1 2022-04-07 11:49:55.517898 +0800 CST deployed dubbo-go-client-0.0.1 1.16.0
dubbo-go-server-v1 default 1 2022-04-07 11:23:18.397658 +0800 CST deployed dubbo-go-server-0.0.1 1.16.0
dubbo-go-server-v2 default 1 2022-04-07 12:29:28.497476 +0800 CST deployed dubbo-go-client-0.0.1 1.16.0
It can be seen that the deployment through helm is successful, and there is already a Client application and two versions of Server in the cluster.
Looking at the deployed deployment, the server contains two versions.
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
dubbo-go-client-v1 1/1 1 1 40m
dubbo-go-server-v2 1/1 1 1 77s
dubbo-go-server-v1 1/1 1 1 67m
View the deployed service. Two versions of the deployment share the same service.
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dubbo-go-client ClusterIP 192.168.8.176 <none> 20000/TCP 41m
dubbo-go-server ClusterIP 192.168.216.253 <none> 20000/TCP 67m
Check the Client application log to verify that the request is called to two versions of the application.
$ kubectl get pods | grep client | awk '{print $1}' | xargs kubectl logs
...
2022-04-07T05:06:40.384Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:06:41.386Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:06:42.388Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:06:43.389Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:06:44.390Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:06:45.392Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:06:46.393Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:06:47.394Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:06:48.396Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:06:49.397Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
So far, we have successfully developed and deployed multi-version applications.
Execute the following command to create a target rule that subdivides dubbo-go-server into two subsets. v1 and v2
$ kubectl apply -f destinationrule.yaml
destinationrule.yaml content:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: dubbo-go-server
spec:
host: dubbo-go-server
subsets:
- name: v1
labels:
dubbogoAppVersion: v1 # corresponds to the version label specified in chart/app/values.yaml in the application template
- name: v2
labels:
dubbogoAppVersion: v2
Execute the following command to create a route that routes all traffic to the v1 application.
$ kubectl apply -f virtualservice.yaml
virtualservice.yaml content
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: dubbo-go-server
spec:
hosts:
- dubbo-go-server
http:
- route:
-destination:
host: dubbo-go-server
subset: v1
All traffic will go to the v1 app.
$ kubectl get pods | grep client | awk '{print $1}' | xargs kubectl logs
...
2022-04-07T05:40:44.353Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:45.354Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:46.356Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:47.357Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:48.359Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:49.361Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
With the above foundation of multi-version application routing, we can implement flexible traffic management through some strategies.
We hope that traffic with the user: admin identifier can experience the new v2 version of the application.
Go back to the previously created dubbo-go-client project, modify the main function of cmd/app.go, and add the calling identifier: user: admin
.
func main() {
client := &api. GreeterClientImpl{}
config. SetConsumerService(client)
if err := config.Load(); err != nil {
panic(err)
}
request := &api.HelloRequest{
Name: "Laurence",
}
for {
ctx := context. Background()
ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]string{
"user":"admin", // Use the context context to add identity to the call
})
if rsp, err := client.SayHello(ctx, request); err != nil{
logger.Errorf("call server error = %s", err)
}else{
logger.Infof("call server response = %+v", rsp)
}
time. Sleep(time. Second)
}
}
Build and push mirrors, overwriting previous commits. You can also upgrade the released image version.
$ make build
(locally for amd64 machines)
or
$ make buildx-publish
(Local is arm64 machine, depends on docker buildx command)
Remove dubbo-go-client application
$ make remove
helm uninstall dubbo-go-client
release "dubbo-go-client" uninstalled
Republish the app.
$ make deploy
After publishing, the verification call is successful because of the previous routing configuration. All traffic goes to the v1 version.
$ kubectl get pods | grep client | awk '{print $1}' | xargs kubectl logs
...
2022-04-07T05:40:44.353Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:45.354Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:46.356Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:47.357Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:48.359Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:40:49.361Z INFO cmd/app.go:29 call server response = name:"Hello laurence" id:"v1.0.0"
Execute the following command to modify/create a route that routes all traffic with the user: admin identifier in the request header to the v2 version.
$ kubectl apply -f virtualservice.yaml
virtualservice.yaml content
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: dubbo-go-server
spec:
hosts:
- dubbo-go-server
http:
- match:
- headers:
user:
exact: admin
route:
-destination:
host: dubbo-go-server
subset: v2
- route:
-destination:
host: dubbo-go-server
subset: v1
All traffic will go to the v2 app.
$ kubectl get pods | grep client | awk '{print $1}' | xargs kubectl logs
...
2022-04-07T05:52:18.714Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:52:19.716Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:52:20.717Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:52:21.718Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:52:22.720Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:52:23.722Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:52:24.723Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
Continuing the above tasks, we execute the following commands to modify/create a route that imports 10% of the traffic into the new version of the application for grayscale testing.
$ kubectl apply -f virtualservice.yaml
virtualservice.yaml content
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: dubbo-go-server
spec:
hosts:
- dubbo-go-server
http:
- route:
-destination:
host: dubbo-go-server
subset: v1
weight: 90
-destination:
host: dubbo-go-server
subset: v2
weight: 10
A small amount of traffic will go to the v2 release.
$ kubectl get pods | grep client | awk '{print $1}' | xargs kubectl logs
...
2022-04-07T05:55:52.035Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:53.036Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:54.037Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:55.039Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:56.041Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:57.043Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:58.045Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:55:59.047Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:56:00.049Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:56:01.050Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v2.0.0"
2022-04-07T05:56:02.053Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"
2022-04-07T05:56:03.055Z INFO cmd/app.go:35 call server response = name:"Hello laurence" id:"v1.0.0"