文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Ingress-Nginx工作原理和实践

2024-12-03 09:09

关注

本文转载自微信公众号「全栈码农画像」,作者小码甲。转载本文请联系全栈码农画像公众号。

本文记录/分享 目前项目的 K8s 部署结构和请求追踪改造方案

 

这个图算是一个通用的前后端分离的 k8s 部署结构:

Nginx Ingress 负责暴露服务(nginx前端静态资源服务), 根据十二要素应用的原 则,将后端 api 作为 nginx 服务的附加动态资源。

Ingress vs Ingress-nginx

Ingress 是一种向 k8s 集群外部的客户端公开服务的方法, Ingress 在网络协议栈的应用层工作,

根据请求的主机名 host 和路径 path 决定请求转发到的服务。

 

在应用Ingress 对象提供的功能之前,必须强调集群中存在Ingress Controller, Ingress资源才能正常工作。

我这里web项目使用的是常见的Ingress-nginx (官方还有其他用途的 Ingress),Ingress-nginx 是使用nginx 作为反向代理和负载均衡器的 K8s Ingress Controller, 作为Pod运行在kube-system 命名空间。

了解 Ingress 工作原理,有利于我们与运维人员打交道。 

下面通过 Ingress-nginx 暴露 Kibana 服务:

  1. --- 
  2. apiVersion: networking.k8s.io/v1beta1 
  3. kind: Ingress 
  4. metadata: 
  5.   name: kibana 
  6.   labels: 
  7.     app: kibana 
  8.   annotations: 
  9.     kubernetes.io/ingress.class: "nginx" 
  10.     nginx.ingress.kubernetes.io/proxy-connect-timeout: "30" 
  11.     nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" 
  12.     nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" 
  13.     nginx.ingress.kubernetes.io/proxy-body-size"8m" 
  14.     nginx.ingress.kubernetes.io/ssl-redirect: "true" 
  15. spec: 
  16.   tls: 
  17.     - hosts: 
  18.       - 'https://logging.internal.gridsum.com/' 
  19.       secretName: tls-cert 
  20.   rules: 
  21.     - host: 'https://logging.internal.gridsum.com' 
  22.       http: 
  23.         paths: 
  24.           - path: / 
  25.             backend: 
  26.               serviceName: kibana 
  27.               servicePort: 5601 

☹️ Ingress-nginx 中最让我困惑的是它的Paths分流与rewrite-target注解。

答:以上面暴露的 kibana 为例, 我们已经可以在https://logging.internal.gridsum.com/ 访问完整的 Kibana, 如果我想利用这个域名暴露 ElasticSearch 站点,怎么操作?这时就可以利用rewrite-target,

  1. --- 
  2. apiVersion: networking.k8s.io/v1beta1 
  3. kind: Ingress 
  4. metadata: 
  5.   name: elasticsearch 
  6.   labels: 
  7.     app: kibana 
  8.   annotations: 
  9.     kubernetes.io/ingress.class: "nginx" 
  10.     nginx.ingress.kubernetes.io/proxy-connect-timeout: "30" 
  11.     nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" 
  12.     nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" 
  13.     nginx.ingress.kubernetes.io/proxy-body-size"8m" 
  14.     nginx.ingress.kubernetes.io/ssl-redirect: "true" 
  15.     nginx.ingress.kubernetes.io/rewrite-target: "/$2" 
  16. spec: 
  17.   tls: 
  18.     - hosts: 
  19.       - 'logging.internal.gridsum.com' 
  20.       secretName: tls-cert 
  21.   rules: 
  22.     - host: 'logging.internal.gridsum.com' 
  23.       http: 
  24.         paths: 
  25.           - path: /es(/|$)(.*) 
  26.             backend: 
  27.               serviceName: elasticsearch 
  28.               servicePort: 9200 

在此 Ingress 定义中,由(.*)捕获的所有字符都将分配给占位符$2,然后将其用作重写目标注解中的参数。这样的话:https://logging.internal.gridsum.com/es 将会重定向到后端 elasticsearch 站点,并且忽略了 es 这个 path

 

Ingress-nginx 到 webapp 的日志追踪

熟悉我的朋友知道, 我写了《一套标准的ASP.NET Core容器化应用日志收集分析方案》,这里面主要是 BackEnd App 的日志,从我上面的结构图看,

Ingress-nginx----> Nginx FrontEnd App--->BackEnd App 需要一个串联的追踪 Id, 便于观察运维网络和业务应用。

幸好 Ingress-nginx, Nginx 强大的配置能力帮助我们做了很多事情:

这样跨越整个结构图的 request_id 思路已经清楚了,最后一步只需要我们在 Backend App 中提取请求中携带的X-Request-ID, 并作为日志的关键输出字段。

☺️ 这就涉及到怎么自定义日志的LayoutRender。

下面为Asp.NETCore NLog 自定义名为x_request_id的 Render,该 Render 从请求的 X-Request-ID 标头中提取值。

① 定义 NLog Render

  1. ///  
  2.     /// Represent a unique identifier to represent a request from the request HTTP header X-Request-Id. 
  3.     ///  
  4.     [LayoutRenderer("x_request_id")] 
  5.     public class XRequestIdLayoutRender : HttpContextLayoutRendererBase 
  6.     { 
  7.         protected override void Append(StringBuilder builder, LogEventInfo logEvent) 
  8.         { 
  9.             var identityName = HttpContextAccessor.HttpContext?.Request?.Headers?["X-Request-Id"].FirstOrDefault(); 
  10.             builder.Append(identityName); 
  11.         } 
  12.     } 
  13.     ///  
  14.     /// Represent a http context layout renderer to access the current http context. 
  15.     ///  
  16.     public abstract class HttpContextLayoutRendererBase : LayoutRenderer 
  17.     { 
  18.         private IHttpContextAccessor _httpContextAccessor; 
  19.         ///  
  20.         /// Gets the "IHttpContextAccessor"/>. 
  21.         ///  
  22.         protected IHttpContextAccessor HttpContextAccessor { get { return _httpContextAccessor ?? (_httpContextAccessor = ServiceLocator.ServiceProvider.GetService()); } } 
  23.     } 
  24.     internal sealed class ServiceLocator 
  25.     { 
  26.         public static IServiceProvider ServiceProvider { get; set; } 
  27.     } 

 

② 从请求中获取 X-Request-Id 依赖 IHttpContextAccessor 组件

这里使用依赖查找的方式获取该组件,故请在Startup ConfigureService 中生成服务

  1. public void ConfigureServices(IServiceCollection services) 
  2.  { 
  3.      // ...... 
  4.      ServiceLocator.ServiceProvider = services.BuildServiceProvider(); 
  5.  } 

③ 最后在 Program 中注册这个NLog Render:

  1.  public static void Main(string[] args) 
  2.      LayoutRenderer.Register("x_request_id"); 
  3.      CreateHostBuilder(args).Build().Run(); 

这样从 Ingress-Nginx 产生的request_id,将会流转到 Backend App, 并在日志分析中起到巨大作用,也便于划清运维/开发的故障责任。

总结

了解了Ingress在应用层工作,根据Host和Path暴露k8s服务。

本文梳理了Ingress和常见的Ingress-nginx的关系。

对于应用了Ingress的应用,梳理了从Ingress-nginx到WebApp的日志追踪id, 便于排查网络/业务故障。

 

来源:全栈码农画像内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯