使用Jaeger追踪Envoy Mesh
环境信息
##### Envoy Mesh使用的网络: 172.31.88.0/24
##### 8个Service:
- front-envoy:Front Proxy,地址为172.31.88.10
- 6个后端服务
- service_a_envoy和service_a:对应于Envoy中的service_a集群,会调用service_b和service_c;
- service_b_envoy和service_b:对应于Envoy中的service_b集群;
- service_c_envoy和service_c:对应于Envoy中的service_c集群;
- zipkin:Jaeger all-in-one服务
[root@k8s-master jaeger-tracing]# tree ../jaeger-tracing/
../jaeger-tracing/
├── docker-compose.yml
├── front_envoy
│ └── envoy-config.yaml
├── images
│ ├── jaeger-tracing-001.png
│ ├── jaeger-tracing-002.png
│ ├── jaeger-tracing-003.png
│ ├── jaeger-tracing-abort.png
│ └── jaeger-tracing-delay.png
├── README.md
├── service_a
│ ├── Dockerfile
│ ├── envoy-config.yaml
│ └── main.go
├── service_b
│ ├── Dockerfile
│ ├── envoy-config.yaml
│ └── main.go
└── service_c
├── Dockerfile
├── envoy-config.yaml
└── main.go
启动
docker-compose up
# cat docker-compose.yml
# Author: MageEdu <mage@magedu.com>
# www.magedu.com
version: '3.3'
services:
front-envoy:
image: envoyproxy/envoy-alpine:v1.21-latest
environment:
- ENVOY_UID=0
- ENVOY_GID=0
volumes:
- "./front_envoy/envoy-config.yaml:/etc/envoy/envoy.yaml"
networks:
envoymesh:
ipv4_address: 172.31.88.10
aliases:
- front-envoy
- front
ports:
- 8080:80
- 9901:9901
service_a_envoy:
image: envoyproxy/envoy-alpine:v1.20.0
volumes:
- "./service_a/envoy-config.yaml:/etc/envoy/envoy.yaml"
networks:
envoymesh:
aliases:
- service_a_envoy
- service-a-envoy
ports:
- 8786
- 8788
- 8791
service_a:
build: service_a/
network_mode: "service:service_a_envoy"
#ports:
#- 8081
depends_on:
- service_a_envoy
service_b_envoy:
image: envoyproxy/envoy-alpine:v1.20.0
volumes:
- "./service_b/envoy-config.yaml:/etc/envoy/envoy.yaml"
networks:
envoymesh:
aliases:
- service_b_envoy
- service-b-envoy
ports:
- 8789
service_b:
build: service_b/
network_mode: "service:service_b_envoy"
#ports:
#- 8082
depends_on:
- service_b_envoy
service_c_envoy:
image: envoyproxy/envoy-alpine:v1.20.0
volumes:
- "./service_c/envoy-config.yaml:/etc/envoy/envoy.yaml"
networks:
envoymesh:
aliases:
- service_c_envoy
- service-c-envoy
ports:
- 8790
service_c:
build: service_c/
network_mode: "service:service_c_envoy"
#ports:
#- 8083
depends_on:
- service_c_envoy
jaeger:
image: jaegertracing/all-in-one:1.27
environment:
- COLLECTOR_ZIPKIN_HOST_PORT=9411
networks:
envoymesh:
ipv4_address: 172.31.88.15
aliases:
- zipkin
ports:
- "9411:9411"
- "16686:16686"
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.88.0/24
# cat front_envoy/envoy-config.yaml
# Author: MageEdu <mage@magedu.com>
# Site: www.magedu.com
node:
id: front-envoy
cluster: front-envoy
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- name: http_listener-service_a
address:
socket_address:
address: 0.0.0.0
port_value: 80
traffic_direction: OUTBOUND
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
generate_request_id: true
tracing:
provider:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: jaeger
collector_endpoint: "/api/v2/spans"
shared_span_context: false
collector_endpoint_version: HTTP_JSON
codec_type: AUTO
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: service_a
decorator:
operation: checkAvailability
response_headers_to_add:
- header:
key: "x-b3-traceid"
value: "%REQ(x-b3-traceid)%"
- header:
key: "x-request-id"
value: "%REQ(x-request-id)%"
http_filters:
- name: envoy.filters.http.router
clusters:
- name: jaeger
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: jaeger
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: jaeger
port_value: 9411
- name: service_a
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_a
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: service_a_envoy
port_value: 8786
[root@k8s-master jaeger-tracing]# cat service_a/Dockerfile
FROM golang:alpine
COPY main.go main.go
CMD go run main.go
# cat service_a/envoy-config.yaml
node:
id: service-a
cluster: service-a
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- name: service-a-svc-http-listener
address:
socket_address:
address: 0.0.0.0
port_value: 8786
traffic_direction: INBOUND
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
tracing:
provider:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: jaeger
collector_endpoint: "/api/v2/spans"
shared_span_context: false
collector_endpoint_version: HTTP_JSON
route_config:
name: service-a-svc-http-route
virtual_hosts:
- name: service-a-svc-http-route
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: local_service
decorator:
operation: checkAvailability
http_filters:
- name: envoy.filters.http.router
- name: service-b-svc-http-listener
address:
socket_address:
address: 0.0.0.0
port_value: 8788
traffic_direction: OUTBOUND
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: egress_http_to_service_b
codec_type: AUTO
tracing:
provider:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: jaeger
collector_endpoint: "/api/v2/spans"
shared_span_context: false
collector_endpoint_version: HTTP_JSON
route_config:
name: service-b-svc-http-route
virtual_hosts:
- name: service-b-svc-http-route
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: service_b
decorator:
operation: checkStock
http_filters:
- name: envoy.filters.http.router
- name: service-c-svc-http-listener
address:
socket_address:
address: 0.0.0.0
port_value: 8791
traffic_direction: OUTBOUND
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: egress_http_to_service_c
codec_type: AUTO
tracing:
provider:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: jaeger
collector_endpoint: "/api/v2/spans"
shared_span_context: false
collector_endpoint_version: HTTP_JSON
route_config:
name: service-c-svc-http-route
virtual_hosts:
- name: service-c-svc-http-route
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: service_c
decorator:
operation: checkStock
http_filters:
- name: envoy.filters.http.router
clusters:
- name: jaeger
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: jaeger
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: jaeger
port_value: 9411
- name: local_service
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8081
- name: service_b
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_b
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: service_b_envoy
port_value: 8789
- name: service_c
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_c
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: service_c_envoy
port_value: 8790
# cat service_a/main.go
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Calling Service B: ")
req, err := http.NewRequest("GET", "http://localhost:8788/", nil)
if err != nil {
fmt.Printf("%s", err)
}
req.Header.Add("x-request-id", r.Header.Get("x-request-id"))
req.Header.Add("x-b3-traceid", r.Header.Get("x-b3-traceid"))
req.Header.Add("x-b3-spanid", r.Header.Get("x-b3-spanid"))
req.Header.Add("x-b3-parentspanid", r.Header.Get("x-b3-parentspanid"))
req.Header.Add("x-b3-sampled", r.Header.Get("x-b3-sampled"))
req.Header.Add("x-b3-flags", r.Header.Get("x-b3-flags"))
req.Header.Add("x-ot-span-context", r.Header.Get("x-ot-span-context"))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("%s", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("%s", err)
}
fmt.Fprintf(w, string(body))
fmt.Fprintf(w, "Hello from service A.\n")
req, err = http.NewRequest("GET", "http://localhost:8791/", nil)
if err != nil {
fmt.Printf("%s", err)
}
req.Header.Add("x-request-id", r.Header.Get("x-request-id"))
req.Header.Add("x-b3-traceid", r.Header.Get("x-b3-traceid"))
req.Header.Add("x-b3-spanid", r.Header.Get("x-b3-spanid"))
req.Header.Add("x-b3-parentspanid", r.Header.Get("x-b3-parentspanid"))
req.Header.Add("x-b3-sampled", r.Header.Get("x-b3-sampled"))
req.Header.Add("x-b3-flags", r.Header.Get("x-b3-flags"))
req.Header.Add("x-ot-span-context", r.Header.Get("x-ot-span-context"))
client = &http.Client{}
resp, err = client.Do(req)
if err != nil {
fmt.Printf("%s", err)
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("%s", err)
}
fmt.Fprintf(w, string(body))
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8081", nil))
}
# cat service_b/Dockerfile
FROM golang:alpine
COPY main.go main.go
CMD go run main.go
# cat service_b/envoy-config.yaml
node:
id: service-b
cluster: service-b
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- name: service-b-svc-http-listener
address:
socket_address:
address: 0.0.0.0
port_value: 8789
traffic_direction: INBOUND
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
tracing:
provider:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: jaeger
collector_endpoint: "/api/v2/spans"
shared_span_context: false
collector_endpoint_version: HTTP_JSON
route_config:
name: service-b-svc-http-route
virtual_hosts:
- name: service-b-svc-http-route
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: local_service
decorator:
operation: checkAvailability
http_filters:
- name: envoy.filters.http.fault
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
max_active_faults: 100
abort:
http_status: 503
percentage:
numerator: 15
denominator: HUNDRED
- name: envoy.filters.http.router
typed_config: {}
clusters:
- name: jaeger
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: jaeger
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: jaeger
port_value: 9411
- name: local_service
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8082
# cat service_b/main.go
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from service B.\n")
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8082", nil))
}
# cat service_c/Dockerfile
FROM golang:alpine
COPY main.go main.go
CMD go run main.go
# cat service_c/envoy-config.yaml
node:
id: service-c
cluster: service-c
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- name: service-c-svc-http-listener
address:
socket_address:
address: 0.0.0.0
port_value: 8790
traffic_direction: INBOUND
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
tracing:
provider:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: jaeger
collector_endpoint: "/api/v2/spans"
shared_span_context: false
collector_endpoint_version: HTTP_JSON
route_config:
name: service-c-svc-http-route
virtual_hosts:
- name: service-c-svc-http-route
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: local_service
decorator:
operation: checkAvailability
http_filters:
- name: envoy.filters.http.fault
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
max_active_faults: 100
delay:
fixed_delay: 3s
percentage:
numerator: 10
denominator: HUNDRED
- name: envoy.filters.http.router
typed_config: {}
clusters:
- name: jaeger
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: jaeger
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: jaeger
port_value: 9411
- name: local_service
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8083
# cat service_c/main.go
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from service C.\n")
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8083", nil))
}
发起请求
curl -vv 172.31.88.10
Jaeger会记录到该请求相关的Trace。访问宿主机的16686端口,即可通过浏览器访问Jaeger UI
以下响应内容中,fault filter abort,表示service-a调用service-b遇到了abort故障;
如下响应内容中的x-envoy-upstream-service-time标头的3006毫秒的响应时长,