当前位置: 首页 > news >正文

链路追踪--使用nginx-ingress-controller记录后端pod真实ip

前言

常见的nginx做反向代理架构,nginx转发到后端的多台服务

                 ┌─────────┐│backend-1│└─────────┘┌─────────┐
┌─────┐          │backend-2│
│nginx│  ────►   └─────────┘
└─────┘...┌─────────┐│backend-n│└─────────┘

在传统的部署,如直接部署在nginx上,或者部署在docker中,nginx转发到后面的的backend是固定在nginx的配置文件中的,这也很方便排查问题节点在哪儿:直接看access_log中的upstream_addr即可

该部署的优点非常明显,简单高效易维护,每一条链路,每一个状态都非常清晰。但是缺点也很明显,扩缩容艰难,一旦需要扩容backend,就非常麻烦了,需要首先部署backend,修改nginx转发配置,最后重启nginx

为了提高扩缩容效率,将该架构搬到k8s中

                                        ┌─────────┐│backend-1│└─────────┘┌─────────┐
┌─────┐       ┌───────────────┐         │backend-2│
│nginx│ ────► │backend-service│ ────►   └─────────┘
└─────┘       └───────────────┘            ...┌─────────┐│backend-n│└─────────┘

通过k8s-service的能力,自动做服务发现,每当上/下线一个backend,就会动态发现backend的个数,从此之后,扩缩容就会变得非常简单

但是新的问题来了,问题出现时,比如某个backend出现问题,导致从nginx的日志出现了502,在access_log中显示的upstream_addr并不是后端backend的地址,而是backend-service的地址,无法立刻知道到底是哪个backend 出问题

问题出现了,如何跟踪一条request,能够明确知道它进入了哪一个pod,就是本文需要探索的内容

nginx-ingress

如果架构迁移还在方案验证阶段,那么恭喜,这个方法可以一劳永逸的解决nginx的问题,那就是利用nginx-ingress-controller来作为入口

安装

这个就不班门弄斧了,直接祭出官网

  • github仓库地址
  • 安装脚本地址

这一步需要注意的点不多,就是镜像的问题,镜像有可能拉不下来,至于怎么解决,大家可以看我之前的文章,关于如何拉镜像

安装完成之后

▶ kubectl -n ingress-nginx get pod
NAME                                        READY   STATUS    RESTARTS       AGE
ingress-nginx-controller-78f7f8bd46-tqjm4   1/1     Running   0              1m

nginx-ingress-controller本质和其他的nginx没有什么区别,只不过有一些额外的功能来辅助nginx提供更好的服务,这个一会再讨论

backend后端服务

接着创建一个backend服务,使用最简单的python tornado作为web容器

test.py

from tornado.ioloop import IOLoop
import tornado.httpserver as httpserver
import tornado.web
import osclass TestFlow(tornado.web.RequestHandler):def get(self):ret = 'i am backend in {}'.format(os.environ['HOSTNAME'])self.write(ret)def post(self, *args, **kwargs):print(self.request.body.decode('utf-8'))def applications():urls = []urls.append([r'/', TestFlow])urls.append([r'/test', TestFlow])return tornado.web.Application(urls)def main():app = applications()server = httpserver.HTTPServer(app)server.bind(10000, '0.0.0.0')server.start(1)IOLoop.current().start()if __name__ == "__main__":try:main()except KeyboardInterrupt as e:IOLoop.current().stop()finally:IOLoop.current().close()

将其打包成镜像

Dockerfile

FROM python:3.11-alpineWORKDIR /opt
RUN pip3 install tornado  -i https://mirrors.aliyun.com/pypi/simple/
ADD test.py /opt/test.pyCMD ["python3", "test.py"]
docker build . -t backend-service:v1

制作完成之后将其放入k8s,并且使用一个service作为访问入口

apiVersion: apps/v1
kind: Deployment
metadata:name: backendnamespace: default
spec:replicas: 1selector:matchLabels:app: backendtemplate:metadata:labels:app: backendspec:containers:- image: backend-service:v1imagePullPolicy: Nevername: backendports:- containerPort: 10000protocol: TCP
---
apiVersion: v1
kind: Service
metadata:name: backend-servicenamespace: default
spec:ports:- port: 10000protocol: TCPtargetPort: 10000selector:app: backendtype: ClusterIP
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
backend-6d4cdd4c68-mqzgj      1/1     Running   0          2m      10.244.0.40   wilson   <none>           <none>
backend-6d4cdd4c68-qjp9m      1/1     Running   0          2m      10.244.0.60   wilson   <none>           <none>

大功告成

创建ingress

继续创建ingress,ingress其实就是nginx转发到后端服务的配置

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-test-ingressnamespace: default
spec:rules:- host: wilsonchai.comhttp:paths:- backend:service:name: backend-serviceport:number: 10000path: /pathType: Prefix

测试结果

折腾了半天,先捋一下整个的路径,我们创建了nginx-ingress-controller,它是整个系统的入口,其次创建了后端服务backend,请求的终点是该服务,还创建了一系列的service以及ingress,他们的关系如图所示

watermarked-nginx-ingress_1

  • 请求通过nodePort进来进入nginx-ingress。
    ▶ kubectl -n ingress-nginx get svc
    NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
    ingress-nginx-controller             LoadBalancer   10.98.224.124   <pending>     80:30296/TCP,443:31592/TCP   30m
    
  • nginx-ingress检查ingress规则,将请求转发至backend-service
    ▶ kubectl  get svc backend-service
    NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
    backend-service   ClusterIP   10.105.148.194   <none>        10000/TCP   30m
    
  • backend-service随机转发该流量进入一个pod
    ▶ kubectl  get pod -owide
    NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
    backend-6d4cdd4c68-mqzgj      1/1     Running   0          30m     10.244.0.40   wilson   <none>           <none>
    backend-6d4cdd4c68-qjp9m      1/1     Running   0          30m     10.244.0.60   wilson   <none>           <none>
    

访问集群: curl -H "host: wilsonchai.com" 127.0.0.1:30296

▶ curl -H "host: wilsonchai.com" 127.0.0.1:30296
i am backend in backend-6d4cdd4c68-qjp9m

请求顺利到达了backend,再检查一下nginx-ingress的日志

10.244.0.1 - - [28/Nov/2025:09:28:45 +0000] "GET / HTTP/1.1" 200 40 "-" "curl/7.81.0" 78 0.001 [default-backend-service-10000] [] 10.244.0.60:10000 40 0.001 200 1896b48d60ef31861478e713d65c9660

upstream_addr上面,显示的就是后端pod的ip: 10.244.0.60

至此,终于解决了开篇提出的问题,如果有request报错502、503等,可以精准的定位到时哪个pod出现了问题

小结

Nginx Ingress Controller 能够直接记录后端 Pod IP,是因为它在转发流量时,绕过了 Service 的 Cluster IP,直接与后端 Pod 建立连接,Nginx Ingress Controller 并不是一个普通的客户端,而是一个特殊的 K8s Controller

  • Service 与 Endpoints: 当创建一个 Service 时,K8s 会自动创建一个相应的 Endpoints 对象(或 EndpointSlice)。这个 Endpoints 对象会实时记录所有与 Service 标签匹配的 后端 Pod 的实际 IP 地址和端口
  • Controller 实时同步: Nginx Ingress Controller 会持续监听 K8s API Server 中所有 Service 对应的 Endpoints 对象的变化(即 Pod 的创建、删除、就绪状态改变)

检验一下,再次访问: curl -H "host: wilsonchai.com" 127.0.0.1:30296

登录到nginx-ingress-controller容器,使用netstat检查连接状态

ingress-nginx-controller-78f7f8bd46-tqjm4:/etc/nginx$ netstat -anpt | grep ESTABLISH
tcp        0      0 10.244.0.16:36074       10.244.0.40:10000       ESTABLISHED -

果然直接与后端的pod建立了连接

后记

盲目的搬进k8s真的是完全错误的,解决了新的问题,又带来更多不可控的问题,所以架构迁移真的需要做好调研:新架构能够满足需求,并且新架构的缺点也能够克服或者忍受,方可行动

有位兄弟说了,如果没有使用nginx-ingress-controller,而是直接把nginx直接搬迁到k8s,那怎么办?并且该文只是解决了nginx访问后端的问题,如果是服务之间的访问,又该怎么办呢?并且这是http协议,如果是其他协议, 比如gRPC,又该怎么办呢?

大家稍安勿躁,本文只是一个引子,后面会把这些问题统统说清楚,敬请期待

联系我

  • 联系我,做深入的交流


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

http://www.jsqmd.com/news/66370/

相关文章:

  • vue vxe-gantt table 甘特图实现任务可拖拽自动调整日期
  • 2025源头地道肠厂家TOP5权威推荐:甄选诚信商家,原味地
  • 2025年度设备安全锁推荐厂商TOP5:专业供应商实力解析与
  • 2025年geo优化监控系统推荐:AI驱动下的流量突围利器
  • 2025 年 12 月食堂送菜服务商权威推荐榜:新鲜直达、高效配送与智慧供应链管理口碑之选
  • AO3401-ASEMI低压控制领域核芯组件AO3401
  • 基于BP_Adaboost分类器与RBF神经网络的回归实现
  • 2025 年 12 月精品包装盒,礼盒包装盒厂家最新推荐,产能、专利、环保三维数据透视!
  • MoonBit Pearls Vol.15: 启用 MoonBit 和 Wassette 构建安全的 WebAssembly 工具
  • Gartner发布2026年战略趋势:当AI重塑一切,你的业务流程还跟得上吗?(附报告原文下载)
  • 紧急!Next.js高危漏洞致服务器被黑,我已经中招了!附解决方案
  • 2025年GEO优化系统公司推荐:AI流量时代的掘金伙伴
  • 2025年东莞智能开关品牌权威推荐榜单:好光时代‌/轻智能品牌‌/智能家居‌‌品牌精选
  • SpringBoot整合OpenAI
  • CISA速通(二)IT治理与管理
  • 2025新加坡出国留学机构哪家好
  • 事倍功半是蠢蛋63 cursor一直卡在planning next move
  • 2025 年 12 月玉米加工设备,全自动面粉加工设备厂家最新推荐,产能、专利、环保三维数据透视
  • 护发素男士专用!25年五大柔顺护发素推荐,烫染干枯毛躁发质闭眼入不踩雷
  • 2025年市面上排行前列的石笼网厂商哪个好,柔韧抗压石笼网/双隔板石笼网/锌铝合金石笼网/镀锌低碳钢丝石笼网/六角石笼网厂商推荐
  • 实力强的空气能十大品牌排名解读,商用空气能厂家推荐
  • awk查看第几列等于某某值
  • 本地消息表(可靠消息服务化)与outbox的区别
  • Dism++下载安装教程:图文讲解与系统优化全攻略
  • 2026最新短视频去水印接口支持抖音/快手/小红书/西瓜等多平台去水印API聚合接口
  • 2026短视频去水印接口支持抖音/快手/小红书/西瓜等多平台去水印API聚合接口
  • Linux 跨进程内存交互技术详解及实践
  • 上周热点回顾(12.1
  • 科研与实验室的得力助手:全自动基因扩增仪知名品牌推荐
  • 2025 OK 镜十大品牌推荐!5000-19800 元价格表 + 科普,家长选镜不踩坑