百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

理解Kubernetes中的Nginx Ingress

liuian 2024-12-25 14:01 28 浏览

Ingress有什么作用?管理集群外部对集群内服务的访问,典型如HTTP请求。它可以提供负载均衡、SSL终结和基于域名的虚拟主机访问。我们发现这些功能都比较容易实现,将集群内的服务暴露到集群外部,可以使用“NodePort”类型的Service,负载均衡可以使用HAProxy来实现,SSL终结功能部署七层反向代理就可以,基于域名的虚拟主机访问也同样比较容易实现,那为什么Kubernetes要引入Ingress API对象呢?

Ingress的潜力

Ingress的功能如开篇所述,可以使用其他技术实现,但是实际在操作过程中发现并没那么简单。在没有Ingress参与的情况下,将集群内服务暴露到集群外使用“NodePort”类型的Service,那需要给每个微服务都创建此类Service,当服务较多时,排障将非常复杂,协调主机端口使用也会让人抓狂。在集群外部署Nginx或Apache,SSL终结和基于域名的虚拟主机访问可以实现,但是服务发现和配置管理又是个挑战,集群外的Nginx和Apache感知不到集群中服务的增加和减少,需要人为配置,这对集群管理员来说,简直是个噩梦。幸好,Ingress来了。

安装

安装服务到Kubernetes一般都比较容易,使用“kubectl apply”后面跟上yaml文件即可。当然也可以使用Kubernetes的包管理工具-Helm。“nginx ingress”根据环境,可选有三种安装方法:

  • 使用helm
  • kubectl apply + yamlfiles
  • 在minikube或MicroK8s中,插件方式安装

笔者使用这篇文章介绍的方法安装Kubernetes集群,这里选用第二种方式安装“nginx ingress ”,执行下面命令(因版本更新较快,实际部署请参考官网):

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/baremetal/deploy.yaml

安装会从“k8s.gcr.io”镜像仓拉取镜像,如果拉取失败可选择阿里云或其他。

查看增加的集群资源,

[root@master ~]# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS      RESTARTS      AGE
pod/ingress-nginx-admission-create-7k9kt        0/1     Completed   0             14d
pod/ingress-nginx-admission-patch-5bcmq         0/1     Completed   1             14d
pod/ingress-nginx-controller-687578654b-f92bq   1/1     Running     3 (42d ago)   14d

NAME                                         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.1.70.249   <none>        80:30305/TCP,443:31330/TCP   14d
service/ingress-nginx-controller-admission   ClusterIP   10.1.124.31   <none>        443/TCP                      14d

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           14d

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-687578654b   1         1         1       14d

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           5s         14d
job.batch/ingress-nginx-admission-patch    1/1           7s         14d

因为集群是自建的,“ingress-nginx-controller”服务类型为“NodePort”,后面访问服务需要使用这样的方式:NodeIP+30305/31330+Path

使用

上步操作成功执行后,便可以创建Ingress类型的API对象了,笔者集群中提前部署一Web服务,Service信息如下:

[root@master ~]# kubectl get svc
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.1.133.186   <none>        80/TCP    14h

创建Ingress API对象,

1> ---
2> apiVersion: networking.k8s.io/v1
3> kind: Ingress
4> metadata:
5>   name: self-nginx
6>   namespace: test
7>   annotations:
8>     nginx.ingress.kubernetes.io/rewrite-target: /
9> spec:
10>   ingressClassName: nginx
11>   rules:
12>   - host: mynginx.example.com
13>     http:
14>       paths:
15>       - path: /testpath
16>         pathType: Prefix
17>         backend:
18>           service:
19>             name: nginx
20>             port:
21>               number: 80

如果没有将前面安装的nginx ingress配置为默认的Ingress,需要加入第10行。否则即使ingress资源提交到API Server,“nginx ingress controller”也没有反应。获取“ingressClassName”的值,

[root@master ~]# kubectl get ingressclass
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       14d

查看创建的Ingress,

[root@master ~]# kubectl get ingress
NAME         CLASS   HOSTS                 ADDRESS          PORTS   AGE
self-nginx   nginx   mynginx.example.com   192.168.52.132   80      125m

通过Ingress访问Web服务(如果域名没有解析,修改/etc/hosts文件),

[root@master nginx]# curl mynginx.example.com:30305/testpath
hello kubernetes!

原理

Nginx Ingress的部署和使用不难,最重要是熟悉它的工作原理,这样在遇到问题时才能迅速定位。“ingress-nginx-controller” Pod里面仅运行一个容器,但是这个容器里面却有多个守护进程,重要的有两个:controller和nginx。进入Pod执行ps命令查看:

[root@master ~]# kubectl exec -it ingress-nginx-controller-687578654b-f92bq -n ingress-nginx  -- /bin/bash
bash-5.1$ ps 
PID   USER     TIME  COMMAND
    1 www-data  0:00 /usr/bin/dumb-init -- /nginx-ingress-controller --election-id=ingress-controller-leader --controller-class=k8s.io/ingress-nginx --config
    7 www-data 11:28 /nginx-ingress-controller --election-id=ingress-controller-leader --controller-class=k8s.io/ingress-nginx --configmap=ingress-nginx/ingr
   25 www-data  0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
  247 www-data  0:01 nginx: worker process
  248 www-data  0:00 nginx: cache manager process

Controller是管理者,实现服务发现和自动配置功能,见下图(下载自官网),

这幅图看起来很复杂,其实用一句话就可以概括:“Ingress Controller”(即图中的IC)相当于系统管理员,需求者提交Ingress资源到API Server,IC从API Server获取Ingress资源,因为IC既了解Ingress资源又了解Nginx,它完成Ingress的“翻译”,随即更新Nginx的配置文件,并执行reload操作,核心逻辑就是这样。

上面我们给“nginx” Service创建了Ingress资源,访问路径配置为“/testpath”,现在进入“ingress-nginx-controller”Pod看下Nginx的配置文件:/etc/nginx/nginx.conf。

关于虚拟主机“mynginx.example.com”的配置有200多行,删掉无关的,

## start server mynginx.example.com	
server {
		server_name mynginx.example.com ;
		
		listen 80  ;
		listen 443  ssl http2 ;
		
		set $proxy_upstream_name "-";
		
		ssl_certificate_by_lua_block {
			certificate.call()
		}
		
		location ~* "^/testpath" {
			
			set $namespace      "test";
			set $ingress_name   "self-nginx";
			set $service_name   "nginx";
			set $service_port   "80";
			set $location_path  "/testpath";
			set $global_rate_limit_exceeding n;
			
			......
      
			set $balancer_ewma_score -1;
			set $proxy_upstream_name "test-nginx-80";
			set $proxy_host          $proxy_upstream_name;
			set $pass_access_scheme  $scheme;
      
      ......
      
			rewrite "(?i)/testpath" / break;
			proxy_pass http://upstream_balancer;
			
			proxy_redirect                          off;
			
		}
		
		location ~* "^/" {
			
			set $namespace      "test";
			set $ingress_name   "self-nginx";
			set $service_name   "";
			set $service_port   "";
			set $location_path  "/";
			set $global_rate_limit_exceeding n;
			
			......
			
			proxy_pass http://upstream_balancer;
			
			proxy_redirect                          off;
			
		}
		
	}
	## end server mynginx.example.com

从配置文件中可以看到发往“/testpath”的请求完成一次跳转后最终发送给“upstream_balancer”,其在Nginx配置文件中的定义如下,

	upstream upstream_balancer {
		### Attention!!!
		#
		# We no longer create "upstream" section for every backend.
		# Backends are handled dynamically using Lua. If you would like to debug
		# and see what backends ingress-nginx has in its memory you can
		# install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin.
		# Once you have the plugin you can use "kubectl ingress-nginx backends" command to
		# inspect current backends.
		#
		###
		
		server 0.0.0.1; # placeholder
		
		balancer_by_lua_block {
			balancer.balance()
		}
		
		keepalive 320;
		
		keepalive_timeout  60s;
		keepalive_requests 10000;
		
	}

因Nginx配置文件严重依赖Lua,这里看到的信息不直观。为了看到后端服务,按照注释,为kubectl安装“ingress-nginx”插件。在前面Nginx配置文件有下面一行:

set $proxy_upstream_name "test-nginx-80";

指出域名“mynginx.example.com”的backend名为“test-nginx-80”。查看Ingress的backends(省略无关行)。

[root@master ~]# kubectl ingress-nginx backends -n ingress-nginx
[
  {
    "name": "test-nginx-80",
    "service": {
      "metadata": {
        "creationTimestamp": null
      },
      "spec": {
        "ports": [
          {
            "name": "http",
            "protocol": "TCP",
            "port": 80,
            "targetPort": 80
          }
        ],
        "selector": {
          "app": "nginx"
        },
        "clusterIP": "10.1.133.186",
        "clusterIPs": [
          "10.1.133.186"
        ],
        "type": "ClusterIP",
        "sessionAffinity": "None",
        "ipFamilies": [
          "IPv4"
        ],
        "ipFamilyPolicy": "SingleStack",
        "internalTrafficPolicy": "Cluster"
      },
      "status": {
        "loadBalancer": {}
      }
    },
    "port": 80,
    "sslPassthrough": false,
    "endpoints": [
      {
        "address": "10.244.1.26",
        "port": "80"
      }
    ],
    "sessionAffinityConfig": {
      "name": "",
      "mode": "",
      "cookieSessionAffinity": {
        "name": ""
      }
    },
    "upstreamHashByConfig": {
      "upstream-hash-by-subset-size": 3
    },
    "noServer": false,
    "trafficShapingPolicy": {
      "weight": 0,
      "weightTotal": 0,
      "header": "",
      "headerValue": "",
      "headerPattern": "",
      "cookie": ""
    }
  },
  
......
  
]

从输出中可以看到后端其实就是名为“nginx”的Service对应的Endpoints,它的IP是“10.244.1.26”,

[root@master ~]# kb get endpoints
NAME    ENDPOINTS        AGE
nginx   10.244.1.26:80   19h

这里需要强调一点,Nginx Ingress并不将流量转发给nginx service,而是直接转发到后端的Pods,转发策略也完全由Ingress Controller来决定。这样不仅减少了一次DNAT,也能实现更丰富的负载均衡策略。Ingress资源中出现的Service对象只是为了选择后端的Endpoints。

总结

文章对Nginx Ingress做了介绍,Kubernetes中可以选择的Ingress有很多,读者可以根据需要选择。

希望这篇文章能帮到正在努力的你,欢迎点赞、评论!

相关推荐

GANs为何引爆机器学习?这篇基于TensorFlow的实例教程为你解惑!

「机器人圈导览」:生成对抗网络无疑是机器学习领域近三年来最火爆的研究领域,相关论文层出不求,各种领域的应用层出不穷。那么,GAN到底如何实践?本文编译自Medium,该文作者以一朵玫瑰花为例,详细阐...

高丽大学等机构联合发布StarGAN:可自定义表情和面部特征

原文来源:arXiv、GitHub作者:YunjeyChoi、MinjeChoi、MunyoungKim、Jung-WooHa、SungKim、JaegulChoo「雷克世界」编译:嗯~...

TensorFlow和PyTorch相继发布最新版,有何变化

原文来源:GitHub「机器人圈」编译:嗯~阿童木呀、多啦A亮Tensorflow主要特征和改进在Tensorflow库中添加封装评估量。所添加的评估量列表如下:1.深度神经网络分类器(DNNCl...

「2022 年」崔庆才 Python3 爬虫教程 - 深度学习识别滑动验证码缺口

上一节我们使用OpenCV识别了图形验证码躯壳欧。这时候就有朋友可能会说了,现在深度学习不是对图像识别很准吗?那深度学习可以用在识别滑动验证码缺口位置吗?当然也是可以的,本节我们就来了解下使用深度...

20K star!搞定 LLM 微调的开源利器

LLM(大语言模型)微调一直都是老大难问题,不仅因为微调需要大量的计算资源,而且微调的方法也很多,要去尝试每种方法的效果,需要安装大量的第三方库和依赖,甚至要接入一些框架,可能在还没开始微调就已经因为...

大模型DeepSeek本地部署后如何进行自定义调整?

1.理解模型架构a)查看深度求索官方文档或提供的源代码文件,了解模型的结构、输入输出格式以及支持的功能。模型是否为预训练权重?如果是,可以在预训练的基础上进行微调(Fine-tuning)。是否需要...

因配置不当,约5000个AI模型与数据集在公网暴露

除了可访问机器学习模型外,暴露的数据还可能包括训练数据集、超参数,甚至是用于构建模型的原始数据。前情回顾·人工智能安全动态向ChatGPT植入恶意“长期记忆”,持续窃取用户输入数据多模态大语言模型的致...

基于pytorch的深度学习人员重识别

基于pytorch的深度学习人员重识别Torchreid是一个库。基于pytorch的深度学习人员重识别。特点:支持多GPU训练支持图像的人员重识别与视频的人员重识别端到端的训练与评估简单的re...

DeepSeek本地部署:轻松训练你的AI模型

引言:为什么选择本地部署?在AI技术飞速发展的今天,越来越多的企业和个人希望将AI技术应用于实际场景中。然而,对于一些对数据隐私和计算资源有特殊需求的用户来说,云端部署可能并不是最佳选择。此时,本地部...

谷歌今天又开源了,这次是Sketch-RNN

前不久,谷歌公布了一项最新技术,可以教机器画画。今天,谷歌开源了代码。在我们研究其代码之前,首先先按要求设置Magenta环境。(https://github.com/tensorflow/magen...

Tensorflow 使用预训练模型训练的完整流程

前面已经介绍了深度学习框架Tensorflow的图像的标注和训练数据的准备工作,本文介绍一下使用预训练模型完成训练并导出训练的模型。1.选择预训练模型1.1下载预训练模型首先需要在Tensorf...

30天大模型调优学习计划(30分钟训练大模型)

30天大模型调优学习计划,结合Unsloth和Lora进行大模型微调,掌握大模型基础知识和调优方法,熟练应用。第1周:基础入门目标:了解大模型基础并熟悉Unsloth等工具的基本使用。Day1:大模...

python爬取喜马拉雅音频,json参数解析

一.抓包分析json,获取加密方式1.抓包获取音频界面f12打开抓包工具,播放一个(非vip)视频,点击“媒体”单击打开可以复制URL,发现就是我们要的音频。复制“CKwRIJEEXn-cABa0Tg...

五、JSONPath使用(Python)(json数据python)

1.安装方法pipinstalljsonpath2.jsonpath与Xpath下面表格是jsonpath语法与Xpath的完整概述和比较。Xpathjsonpath概述/$根节点.@当前节点...

Python网络爬虫的时候json=就是让你少写个json.dumps()

大家好,我是皮皮。一、前言前几天在Python白银交流群【空翼】问了一个Python网络爬虫的问题,提问截图如下:登录请求地址是这个:二、实现过程这里【甯同学】给了一个提示,如下所示:估计很多小伙伴和...