找回密码
 立即注册
首页 业界区 业界 追踪链路--使用envoy来记录后端pod真实ip

追踪链路--使用envoy来记录后端pod真实ip

零幸 2 小时前
前言

之前使用了iptables、ipvs,在数据包的必经之路(POSTROUTING)上拦截并且记录日志,本文使用一个比较成熟的组件envoy来记录后端pod的真实ip
环境准备

环境准备如同之前
  1. ▶ kubectl get pod  -owide
  2. NAME                          READY   STATUS    RESTARTS        AGE    IP            NODE     NOMINATED NODE   READINESS GATES
  3. backend-6d4cdd4c68-mqzgj      1/1     Running   4               8d     10.244.0.73   wilson   <none>           <none>
  4. backend-6d4cdd4c68-qjp9m      1/1     Running   4               7d3h   10.244.0.74   wilson   <none>           <none>
  5. nginx-test-54d79c7bb8-zmrff   1/1     Running   2               23h    10.244.0.75   wilson   <none>           <none>
复制代码
  1. ▶ kubectl get svc
  2. NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                          AGE
  3. backend-service   ClusterIP   10.105.148.194   <none>        10000/TCP                        8d
  4. nginx-test        NodePort    10.110.71.55     <none>        80:30785/TCP                     14d
复制代码
1.png

envoy

如同之前所说,需要有一个做负载均衡的组件来转发到后端的多pod,之前使用的是iptables/ipvs,它们对于链路追踪比较困难,那就要有一个组件来代替它们做负载均衡,所以该组件要么在backend之前,要么在nginx之后,那我们选择在nginx之后
2.png

创建envoy configmap
  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4.   name: envoy-config
  5. data:
  6.   envoy.yaml: |
  7.     static_resources:
  8.       listeners:
  9.         - name: ingress_listener
  10.           address:
  11.             socket_address:
  12.               address: 0.0.0.0
  13.               port_value: 10000
  14.           filter_chains:
  15.             - filters:
  16.                 - name: envoy.filters.network.http_connection_manager
  17.                   typed_config:
  18.                     "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
  19.                     stat_prefix: ingress_http
  20.                     http_protocol_options:
  21.                       accept_http_10: true
  22.                     common_http_protocol_options:
  23.                       idle_timeout: 300s
  24.                     codec_type: AUTO
  25.                     route_config:
  26.                       name: local_route
  27.                       virtual_hosts:
  28.                         - name: app
  29.                           domains: ["*"]
  30.                           routes:
  31.                             - match: { prefix: "/test" }
  32.                               route:
  33.                                 cluster: app_service
  34.                     http_filters:
  35.                       - name: envoy.filters.http.router
  36.                         typed_config:
  37.                           "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  38.                     access_log:
  39.                     - name: envoy.access_loggers.stdout
  40.                       typed_config:
  41.                         "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
  42.                         log_format:
  43.                           text_format: "[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %BYTES_SENT% %DURATION% %REQ(X-REQUEST-ID)% "%REQ(USER-AGENT)%" "%REQ(X-FORWARDED-FOR)%" %UPSTREAM_HOST% %UPSTREAM_CLUSTER% %RESPONSE_FLAGS%\n"
  44.       clusters:
  45.         - name: app_service
  46.           connect_timeout: 1s
  47.           type: STRICT_DNS
  48.           lb_policy: ROUND_ROBIN
  49.           load_assignment:
  50.             cluster_name: app_service
  51.             endpoints:
  52.               - lb_endpoints:
  53.                   - endpoint:
  54.                       address:
  55.                         socket_address:
  56.                           address: "backend-service"
  57.                           port_value: 10000
  58.     admin:
  59.       access_log_path: "/tmp/access.log"
  60.       address:
  61.         socket_address:
  62.           address: 0.0.0.0
  63.           port_value: 9901
复制代码
创建sidecar

与nginx-test同pod,通过patch的方式添加container
  1. kubectl patch deployment nginx-test --type='json' -p='
  2. [
  3.   {
  4.     "op": "add",
  5.     "path": "/spec/template/spec/volumes/-",
  6.     "value": {
  7.       "configMap": {
  8.         "defaultMode": 420,
  9.         "name": "envoy-config"
  10.       },
  11.       "name": "envoy-config"
  12.     }
  13.   },
  14.   {
  15.     "op": "add",
  16.     "path": "/spec/template/spec/containers/-",
  17.     "value": {
  18.       "args": [
  19.         "-c",
  20.         "/etc/envoy/envoy.yaml"
  21.       ],
  22.       "image": "registry.cn-beijing.aliyuncs.com/wilsonchai/envoy:v1.32-latest",
  23.       "imagePullPolicy": "IfNotPresent",
  24.       "name": "envoy",
  25.       "ports": [
  26.         {
  27.           "containerPort": 10000,
  28.           "protocol": "TCP"
  29.         },
  30.         {
  31.           "containerPort": 9901,
  32.           "protocol": "TCP"
  33.         }
  34.       ],
  35.       "volumeMounts": [
  36.         {
  37.           "mountPath": "/etc/envoy",
  38.           "name": "envoy-config"
  39.         }
  40.       ]
  41.     }
  42.   }
  43. ]'
复制代码
  1. ▶ kubectl get pod -owide -l app=nginx-test
  2. NAME                          READY   STATUS    RESTARTS       AGE    IP            NODE     NOMINATED NODE   READINESS GATES
  3. nginx-test-6df974c9f9-qksd4   2/2     Running   0              1d     10.244.0.80   wilson   <none>           <none>
复制代码
在nginx-test pod中额外创建了envoy container,envoy打开了10000端口,并且envoy将访问/test的请求都转发到了backend-service:10000,现在需要将nginx-test的出流量转发至envoy,让envoy做负载均衡
修改nginx-test的upstream

将backend-service改成127.0.0.1,由于在同一个pod,同一个net namespace,直接用127即可
  1. upstream backend_ups {
  2.     # server backend-service:10000;
  3.     server 127.0.0.1:10000;
  4. }
  5. server {
  6.     listen       80;
  7.     listen  [::]:80;
  8.     server_name  localhost;
  9.     location /test {
  10.         proxy_pass http://backend_ups;
  11.     }
  12. }
复制代码
重启后生效
验证

curl 10.22.12.178:30785/test,并且监控envoy的日志kubectl logs -f -l app=nginx-test -c envoy
  1. [2025-12-16T09:45:56.365Z] "GET /test HTTP/1.0" 200 40 0 99032619-a060-481d-8f0d-9d773fad9b12 "curl/7.81.0" "-" 10.105.148.194:10000 app_service -
复制代码
咦?upstream_host怎么显示得还是10.105.148.194,这是service ip,并不是后端pod的真实ip,这是怎么回事??
问题解决

仔细回想一下负载均衡的工作原理:根据不同的算法(如:rr,wlc等)转发到后端的real server,但是当前提供的后端,依然是k8s的service:backend-service,所以这种配置方式,虽然加了一层envoy,但是本质依然还是使用k8s service作为负载均衡
k8s service不但提供了负载均衡的作用,还有个重要的功能,就是服务发现,所以必须要使用service来做服务发现,又不能使用service的负载均衡
所幸k8s提供了headless service来满足这种需求,访问headless service,返回一组running的pod列表,让访问者自定义做负载均衡,ok,那就使用headless试试
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4.   name: backend-headless-service
  5. spec:
  6.   clusterIP: None
  7.   selector:
  8.     app: backend
  9.   ports:
  10.     - name: http
  11.       port: 10000
  12.       targetPort: 10000
复制代码
这里的clusterIP: None是创建headless service的关键
再修改envoy的配置文件,将转发修改为headless service
  1. ...
  2.       clusters:
  3.         - name: app_service
  4.           connect_timeout: 1s
  5.           type: STRICT_DNS
  6.           lb_policy: ROUND_ROBIN
  7.           load_assignment:
  8.             cluster_name: app_service
  9.             endpoints:
  10.               - lb_endpoints:
  11.                   - endpoint:
  12.                       address:
  13.                         socket_address:
  14.                           address: "backend-headless-service"
  15.                           port_value: 10000
  16. ...
复制代码
  1. [2025-12-16T10:05:56.365Z] "GET /test HTTP/1.0" 200 40 0 2b029187-cddb-4278-99b8-2953a7e841a0 "curl/7.81.0" "-" 10.244.0.81:10000 app_service -
  2. [2025-12-16T10:05:57.453Z] "GET /test HTTP/1.0" 200 40 1 384f9394-7ff9-4abb-b0f8-f9b69f2ba992 "curl/7.81.0" "-" 10.244.0.82:10000 app_service -
复制代码
确实已经转发到后端真实pod ip去了
小结

当前的架构:
3.png

每个pod都有一个envoy sidecar,想要节约envoy资源,可以多个pod使用一个envoy,将envoy部署为daemonset,每个节点一个,然后调度到该节点的pod都转发到该envoy即可
联系我


  • 联系我,做深入的交流
4.bmp

至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册