手摸手教你把Ingress Nginx集成进Skywalking

背景

在微服务大行其道的今天,如何观测众多微服务、快速理清服务间的依赖、如何对服务之间的调用性能进行衡量,成了摆在大家面前的难题。对此,Skywalking应运而生,它是托管在 Apache 基金会下的开源项目,旨在帮助开发者监控分布式程序的性能、了解各个服务的调用关系和运行情况。

Skywalking支持多种语言和框架,包含Java、Golang、Python等,功能强大、界面友好等特点使其迅速成为业界最流行的APM软件之一。然而在运用Skywalking的过程中,我们常常更关注服务之间的调用链路、性能数据,往往会忽略流量入口(网关)到服务之间的Trace串联,导致我们经常在网关层面观测到一个错误调用后,无法通过TraceID快速查看本次调用的链路,从而白白浪费宝贵的排障时间。

本文重点介绍如何将 Ingress Nginx 集成进 Skywalking,将其作为 Skywalking 的一个节点,并且在access log 中打印TraceID,从而在出现故障的时候,可以通过日志中的TraceID快速找到调用链路,达到快速故障定位的效果。

注:本文使用的 Kubernetes 版本是 1.24.15,Ingress Nginx controller 版本是 v1.8.1,Skywalking版本是9.2.0。

方案

在介绍方案之前,我们先了解一下相关的背景知识,用于更好的理解集成方案。

  1. Ingress Nginx Configmap:Ingress Nginx 的各种配置存放地,可以通过该Configmap配置logformat、所开启的插件等。
  2. Skywalking Nginx Lua:Skywalking 官方提供的 Lua 版本 lib,提供了一系列的操作,自己可以在Nginx的配置文件中编写Lua脚本,适时创建Span、结束Span,从而把 Nginx 当作Skywalking中的一个服务节点集成进Skywalking。
  3. Ingress Nginx 自定义插件:Lua脚本编写的插件,用于对 Ingress Nginx 做编程,想要使用插件必须要将插件放到 Ingress Controller 容器的 /etc/nginx/lua/plugins/插件名称 目录中,且需要在 Ingress Controller 的configmap中开启它。自定义插件支持以下几个钩子:
  • a. init_worker: 用于对Nginx Worker做一些初始化。
  • b. rewrite: 用于修改请求、更改标头、重定向、丢弃请求、进行身份验证等。
  • c. header_filter: 当接收到后端response header 时调用此函数,通常用来记录和修改后端的response header。
  • d. body_filter: 这是在收到后端response body 时调用的,一般用来记录response body。
  • e. log: 当请求处理完成并将响应传递给客户端时,会调用此函数。

    4.  sw8:SkyWalking 跨进程传播的Header Key,它的格式是 1-TRACEID-SEGMENTID-3-PARENT_SERVICE-PARENT_INSTANCE-PARENT_ENDPOINT-IPPORT(其中TraceID、SpanID等都通过base64进行编码),我们可以通过此Header解析出对应的 TraceID。

了解了上述原理后,我们的方案就显而易见了,就是将 Skywalking Nginx Lua 集成进 Ingress Nginx中,并编写插件,在不同阶段执行相关操作:

  • a. 在 rewrite 阶段生成新Span并解析出TraceID将其放在新Header中(方便access log 打印)
  • b. 在 body_filter 阶段结束该Span
  • c. 在log阶段提交对应的数据到Skywalking服务端
  • d. 修改 Nginx log format,将存储 TraceID 的Header 打印出来

步骤

1. 集成Skywalking Nginx Lua进Ingress Nginx

Skywalking Nginx Lua 的核心是它的 lib 目录,里边包含了所有需要用到的函数操作,所以我们需要将该 lib 目录的内容放到 Ingress Nginx 的Pod 中,让我们编写的插件能够调用到它。具体我们可以将 lib 目录放到网盘中,然后通过 Volume 的形式挂载进去,也可以将 lib 的内容写入configmap,然后挂载Volume到Pod中。本文选择第二种方式,将 lib 的内容放到 configmap 中,然后挂载进去,虽说这种方式不够优雅,但好在不用依赖网盘。

我们先clone Skywalking Nginx Lua 这个库,然后将 lib 下的所有.lua文件打平放到同一个目录中

git clone https://github.com/apache/skywalking-nginx-lua.git
mkdir sk-lua-cm
cp skywalking-nginx-lua/lib/skywalking/*.lua sk-lua-cm/
cp skywalking-nginx-lua/lib/skywalking/dependencies/*.lua sk-lua-cm/
cp skywalking-nginx-lua/lib/resty/*.lua sk-lua-cm/

再通过 kubectl 命令将sk-lua-cm中的所有文件创建到一个configmap中,注意将 -n 后边的参数换成你自己Ingress Nginx 所在的 namespace。

kubectl create cm skywalking-nginx-lua-agent --from-file=./sk-lua-cm/ -n ingress-nginx
2. 编写Ingress Nginx 的插件

引入了 Skywalking 的 lib 后就可以编写对应的 Ingress Nginx 自定义插件了,代码比较简单,以下是代码详情(命名为main.lua)。

local _M = {}

function _M.init_worker()
  local metadata_buffer = ngx.shared.tracing_buffer
  require("skywalking.util").set_randomseed()
  local serviceName = os.getenv("SKY_SERVICE_NAME")
  if not serviceName then
    serviceName="ingress-nginx"
  end
  metadata_buffer:set('serviceName', serviceName)

  local serviceInstanceName = os.getenv("SKY_INSTANCE_NAME")
  if not serviceInstanceName then
    serviceName="ingress-nginx"
  end
  metadata_buffer:set('serviceInstanceName', serviceName)
  metadata_buffer:set('includeHostInEntrySpan', false)

  require("skywalking.client"):startBackendTimer(os.getenv("SKY_OAP_ADDR"))
  skywalking_tracer = require("skywalking.tracer")

end


function _M.rewrite()
  local upstreamName = ngx.var.proxy_upstream_name
  skywalking_tracer:start(upstreamName)
  if ngx.var.http_sw8 ~= "" then
    local sw8Str = ngx.var.http_sw8
    local sw8Item = require('skywalking.util').split(sw8Str, "-")
    if #sw8Item >= 2 then
      ngx.req.set_header("trace_id", ngx.decode_base64(sw8Item[2]))
    end
  end
end

function _M.body_filter()

  if ngx.arg[2] then
    skywalking_tracer:finish()
  end

end

function _M.log()
  skywalking_tracer:prepareForReport()
end

return _M

划重点:在上述代码中获取了几个环境变量,需要记住,后边需要用到。

  • i. SKY_SERVICE_NAME:Ingress Nginx 在 Skywalking 中的 Service 名称
  • ii. SKY_INSTANCE_NAME:Ingress Nginx 实例在 Skywalking 中的实例名称
  • iii. SKY_OAP_ADDR:Skywalking后端地址

编写好插件代码后就可以基于此创建configmap了,依然需要注意 -n 后边的namespace,需要改成你实际Ingress Nginx所在的 namespace。

kubectl create cm skywalking-lua-plug --from-file=main.lua -n ingress-nginx
3. 挂载相关 Lua 脚本进 Ingress Nginx Controller 的 Pod 中

修改 Ingress Nginx Controller 的 Deployment 配置,主要修改以下几点:

a. 环境变量

- name: SKY_OAP_ADDR
  value: http://skywalking-oap.skywalking.svc.cluster.local:12800
- name: SKY_SERVICE_NAME
  value: ingress-nginx
- name: SKY_INSTANCE_NAME
  value: ingress-nginx

b. volumes 声明

- name: sky-nginx-plugin
  configMap:
    name: skywalking-lua-plug
- name: skywalking-nginx-lua-agent
  configMap:
    name: skywalking-nginx-lua-agent

c. volumeMounts 声明

- mountPath: /etc/nginx/lua/plugins/skywalking/main.lua
  subPath: "main.lua"
  name: sky-nginx-plugin
- mountPath: /etc/nginx/lua/resty/http.lua
  subPath: "http.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/tablepool.lua
  subPath: "tablepool.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/resty/http_headers.lua
  subPath: "http_headers.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/resty/jit-uuid.lua
  subPath: "jit-uuid.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/client.lua
  subPath: "client.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/constants.lua
  subPath: "constants.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/correlation_context.lua
  subPath: "correlation_context.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/dependencies/base64.lua
  subPath: "base64.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/management.lua
  subPath: "management.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/segment.lua
  subPath: "segment.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/segment_ref.lua
  subPath: "segment_ref.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/span.lua
  subPath: "span.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/span_layer.lua
  subPath: "span_layer.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/tracer.lua
  subPath: "tracer.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/tracing_context.lua
  subPath: "tracing_context.lua"
  name: skywalking-nginx-lua-agent
- mountPath: /etc/nginx/lua/skywalking/util.lua
  subPath: "util.lua"
  name: skywalking-nginx-lua-agent
4. 修改 Ingress Nginx Controller 所使用的configmap配置
plugins: "skywalking"
lua-shared-dicts: "tracing_buffer: 100m"
main-snippet: |
  env SKY_SERVICE_NAME;
  env SKY_INSTANCE_NAME;
  env SKY_OAP_ADDR;
log-format-upstream: |
  $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $request_id $http_trace_id

该配置中配置了如下几个信息:

  • a. plugins:开启skywalking插件
  • b. lua-shared-dicts:声明 trace 使用的变量和大小
  • c. main-snippet:其中声明了需要使用到的环境变量,切记在插件中使用的环境变量必须放到这里来
  • d. log-format-upstream:log 格式,我们在这个里添加了一个 http_trace_id 这个header的打印(上一步解析出来的TraceID)
5. 重启 Pod 生效

把下列的 xxx 换成 Ingress Nginx Controller 的 Pod 名称

kubectl delete pod xxxx -n=ingress-nginx

效果展示

本节展示最终在Skywalking UI 上的展示效果。

  1. 可以在 Skywalking 的拓扑图中看到有一个 Ingress Nginx 的服务节点加入

20240416162438

  1. 在Trace查询页面可以看到有一个 Nginx 的 Span

20240416162807

  1. 如下是打印出来的TraceID

20240416162824

如何更好使用Trace?

通过上述介绍,我们已经把 Ingress Nginx 集成进了Skywalking,接下来介绍一下如何更好的使用Trace数据来快速定位故障。

数据建设

  1. 将Skywalking数据源接入Flashcat,接入的方法很简单,只需要填写对应的地址、账号、密码,然后起一个名字即可 

    20240416162901

  2. 采集 Ingress Nginx 日志到 kafka 中,这里可以使用 categraf 的 log 采集器

  3. 将日志接入 Flashcat 的日志分析子系统生成报表,在这张报表中可以看到对应的域名、接口、流量、成功率等(当然,这些维度都可以自定义),在创建报表的时候设置好日志中哪个字段是TraceID字段。

20240416162945

  1. 通过日志报表生成灭火图(IT系统健康度一览表),例如下图就是典型的电商系统核心API健康度一览表。

20240416163003

  1. 通过数据库、Metrics、日志等不同来源建立北极星指标(核心业务指标),例如:电商系统的下单量、支付量等

20240416163030

串联打通

通过Flashcat的串联能力,建立北极星和灭火图的串联。

20240416163059

故障定位路径

当建设好对应的指标和关联后,就可以开启我们的故障定位之旅了。

  1. 当北极星指标故障(核心业务受损)时,北极星页面上对应的指标会飘红且发送报警,例如下图中的商品实时下单量掉底了,该业务卡片会飘红

20240416163134

  1. 此时我们点击曲线上掉底时刻的数据点,可以打开关联的灭火图,一眼就可以看到是订单子系统在飘红(可能发生了故障)

20240416163207

  1. 我们点击飘红的灭火图路径,可以下钻到具体的卡片组中去

20240416163228

  1. 然后可以看到灭火图卡片组中的订单更新DB接口成功率为0,我们点击旁边的详情可以打开对应的详情曲线(通过上一步中的日志报表生成)

20240416163302

  1. 通过详情可以看到,这个时候的成功率已经掉底了,那么我们同样可以点击曲线上掉底的时间点打开日志详情

20240416163324

  1. 在这个页面中,我们可以直接查看异常日志的日志详情,也可以点击右侧的 trace 按钮打开该调用的Trace链路

20240416163342

通过Trace链路可以看到Redis的端口不通导致更新失败了,这个时候我们就需要去排查依赖的Redis是否正常了。

当然,以上只是Flashcat在整合可观测性三大支柱(Metrics、Log、Trace)方面的一个小例子,如果您对Flashcat这套产品感兴趣,可以随时与我们交流:联系销售 - 快猫星云。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/567391.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue element-ui 表格横向滚动条在合计项下方

目前效果 需求效果 1.隐藏bodyWrapper滚动条,显示footerWrapper滚动条 css代码如下: div ::v-deep .el-table--scrollable-x .el-table__body-wrapper{overflow-x: hidden!important;z-index: 2!important;} div ::v-deep .el-table__footer-wrapper …

git的安装与配置教程--超详细版

一、git的安装 1. 官网下载git git官网地址:https://git-scm.com/download/win/ 选择需要的版本进行下载 2、下载完成之后,双击下载好的exe文件进行安装。 3、默认是C盘,推荐修改一下路径,然后点击下一步 4、Git配置&#xff…

电子邮箱是什么?电子邮箱怎么申请注册?

虽然通过电子邮箱收发邮件办公已经成为常态,但是很多人不清楚电子邮箱是什么?电子邮箱是指通过网络传递的“邮局”,可以用来收发电子邮件。每个人的电子邮箱地址都是唯一的,确保他人的邮件能准确送到我们的电子邮箱之中。电子邮箱…

CRMEB pro版/多门店商城系统客服配置教程

客服功能配置介绍 功能提示: Pro v2.0系统采用swoole框架,客服不需要单独配置,按照正常安装流程配置好程序即可使用! 如出现客服无法使用,请检查: 1.消息队列是否正常 2.重启swoole 一、功能介绍 CRMEB商城…

刷课必备!用Python实现网上自动做题

前言 开学少不了老师会布置一些 软件上面的作业,今天教大家用python制作自动答题脚本,100%准确率哦喜欢的同学记得关注、收藏哦 环境使用 Python3.8Pycharm 模块使用 import requests —> 数据请求模块 pip install requestsimport parsel —>…

GPU 之争:训练大模型的显卡规格大比拼

训练大模型有多烧钱?(含常用GPU规格比较) 训练大模型有多烧钱? 解锁大型语言模型的运行秘诀大型语言模型 (LLM) 对硬件要求很高,其中显卡内存至关重要。Meta 的 LLaMA 2 模型提供了规模不等的选项:* 70B 模…

C++/Qt 小知识记录5

工作中遇到的一些小问题,总结的小知识记录:C/Qt 小知识5 Windows下查看端口占用情况C调用Python三方库测试库有没有被加上的测试方法初始化使用Python的env环境,用Py_SetPythonHome设置GDAL相关的,需要把osgeo、rasterio的路径加入…

js some对比forEach

some&#xff1a;return true可以停止循环 forEach&#xff1a;return true无法停止循环 <!DOCTYPE html> <html ng-app"my_app"><head><script type"text/javascript">const array [10, 20, 30];const targetValue 10;// 检测…

分析 MyBatis/MyBatis-Plus 慢 SQL 的分析组件 --SQL 慢镜️‍♀️

大家好&#xff01;我是聪ζ&#x1f331;我做了一个分析 MyBatis/MyBatis-Plus 慢 SQL 的分析组件 --SQL 慢镜&#x1f575;️‍♀️ GitHub仓库地址&#x1f680;: https://github.com/lhccong/sql-slow-mirror 点点 star 我的朋友们✨ 背景&#x1f9ca;&#xff1a; 大家…

yolov8 区域声光报警+计数

yolov8 区域报警计数 1. 基础2. 报警功能2. 1声音报警代码2. 2画面显示报警代码 3. 完整代码4. 源码 1. 基础 本项目是在 yolov8 区域多类别计数 的基础上实现的&#xff0c;具体区域计数原理可见上边文章 2. 报警功能 设置一个区域region_points&#xff0c;当行人这一类别…

SpringBoot整合Swagger2

SpringBoot整合Swagger2 1.什么是Swagger2&#xff1f;&#xff08;应用场景&#xff09;2.项目中如何使用2.1 导入依赖2.2 编写配置类2.3 注解使用2.3.1 controller注解&#xff1a;2.3.2 方法注解2.3.3 实体类注解2.3.4 方法返回值注解2.3.5 忽略的方法 3.UI界面 1.什么是Swa…

FPGA组合逻辑电路设计之译码器

在数字电路中可以根据电路功能的不同分为&#xff0c;组合逻辑电路与时序逻辑电路。组合逻辑 电路在逻辑功能上的特点是任意时刻的输出仅仅取决于该时刻的输入&#xff0c;与电路原来的状态无 关。而时序逻辑从电路特征上看来&#xff0c;其特点为任意时刻的输出不仅取决于该…

全网人气排行第一的免费开源ERP:Odoo电商功能应用亮点介绍

Odoo E-Commerce是一款创新型电子商务管理系统&#xff0c;旨在帮助企业建立以客户为中心的B2B与B2C电子商务平台&#xff0c;提高电商业务敏捷性&#xff0c;保障利润&#xff0c;并确保客户体验战略与时俱进。 —— 开源智造Odoo老杨 什么是Odoo免费开源电商管理系统&#xf…

Vue3引入高德地图js API 2.0

文章目录 前言一、地图加载1.本文准备环境2.引入库3.加载地图4.加载地图控件 二、POI搜索1.什么是poi搜索2.如何使用 三、绘制点标记与信息窗体1.场景描述2.案例3.信息窗体-链接路由跳转4.进阶-通过Marker自动触发标记点&#xff08;非鼠标手动点击&#xff09; 四、jsApi地图事…

文献速递:深度学习胶质瘤诊断---空间细胞结构预测胶质母细胞瘤的预后

Title 题目 Spatial cellular architecture predicts prognosis in glioblastoma 空间细胞结构预测胶质母细胞瘤的预后 01文献速递介绍 胶质母细胞瘤的治疗耐药性的关键驱动因素是肿瘤内的异质性和细胞状态的可塑性。在这里&#xff0c;我们调查了空间细胞组织与胶质母细胞瘤…

聚道云一键打通金蝶宁波银行,财务效率暴涨10倍!

客户介绍&#xff1a; 某农资有限公司是一家集农资贸易、仓储物流、农机服务为一体的大型企业。随着业务规模的不断扩大&#xff0c;传统的手动财务操作模式已难以满足其需求。公司急需寻找一种方法&#xff0c;将金蝶财务软件与宁波银行对接&#xff0c;实现资金流转自动化和…

深入解析YOLOv2

深入解析YOLOv2 引言 目标检测是计算机视觉中的一个核心问题&#xff0c;它旨在识别图像中所有感兴趣的目标&#xff0c;并给出它们的类别和位置。近年来&#xff0c;随着深度学习技术的发展&#xff0c;目标检测领域取得了巨大的进步。YOLO&#xff08;You Only Look Once&a…

Ozone V3.32a Jlink显示变量波形

目录 前言 Ozone 配合Jlink显示变量波形 导出数组查看高频变量波形 总结 前言 Ozone V3.32a使用总结-CSDN博客 前面介绍了Ozone的安装和使用&#xff0c;因为调试需要&#xff0c;要看一些数据的波形。这里总结两种用Ozone查看变量波形的方法。 Ozone 配合Jlink显示变量波…

CCF-A类!狂涨6.131分,中科院2区,无版面费的王者刊物!

计算机领域 顶级好刊解析 今天解析的是一本Springer期刊&#xff0c;2022JCR发布后影响因子由13.369涨至19.5&#xff0c;年底升区可能性很大&#xff0c;究竟期刊实力如何呢&#xff1f;详情请看下文&#xff1a; 01 期刊简介 International Journal of Computer Vision ✅…

JSON Web Token 入门

JSON Web Token&#xff08;缩写 JWT&#xff09;是目前最流行的跨域认证解决方案&#xff0c;本文介绍它的原理和用法。 一、跨域认证的问题 互联网服务离不开用户认证。一般流程是下面这样。 1、用户向服务器发送用户名和密码。 2、服务器验证通过后&#xff0c;在当前对话&…