百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

理解Kubernetes中的Nginx Ingress

off999 2025-01-17 12:34 16 浏览 0 评论

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有很多,读者可以根据需要选择。

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

相关推荐

30s带你使用Python打包exe文件,并修改其图标

在Python中,我们可以使用PyInstaller或cx_Freeze等工具将Python脚本打包成可执行文件(.exe),并且能够修改生成的.exe文件的图标。使用PyInstaller...

Python一键打包为windows的exe文件,无需安装python环境即可执行

一、为什么要将Python打包为exe?在实际应用中,我们希望Python程序能在没有安装Python环境的电脑上直接运行。将Python代码打包为exe可执行文件,不仅能解决环境依赖问题,还便于程...

py2exe实现python文件打包为.exe可执行程序(上篇)

今天分享的内容为:python程序实现发送、读取邮件来控制电脑的关机与重启(作为py2exe打包成.exe可执行程序的基础文件)一、说明:本文介绍的是使用新浪邮箱作为例子进行讲解,代码实现如下:#c...

如何将python程序文件打包生成一个可执行文件(exe文件)

在开发Python程序后,有时我们希望将其打包成一个可执行的exe文件,方便在没有Python环境的计算机上运行。下面将详细介绍使用常见工具实现这一目标的方法。安装PyInstaller...

Python程序打包为EXE的全面指南:从入门到精通

引言在Python开发中,将程序打包成可执行文件(EXE)是分发应用程序的重要环节。通过打包,我们可以创建独立的可执行文件,让没有安装Python环境的用户也能运行我们的程序。本篇文章将详细介绍如何使...

10个你没有充分利用的令人惊叹的 Python 特性

Python的简单性和多功能性使其成为全球开发人员的最爱。每天有超过1000万开发者使用Python进行从网络开发、机器学习到网络脚本等各种开发,Python的功能非常强大。然而,我们中的...

编程语言可以用来做什么

1.web前端你每天浏览的网页,所看到的页面特效,均是由web前端工程师来实现的2.Java大型购物网站有关通信及网络企业大型企业级应用管理系统大型网游后台数据3.C++嵌入式三维游戏领域人工智能领域...

用Python进行机器学习(16)-内容总结

对于用Python进行机器学习的内容,到这里就要做一个阶段性总结啦,后续再写的文章就是关于深度学习的了,算是对该部分内容的进阶版。对于机器学习,我们主要介绍了五个方面的内容:第一个就是分类算法,主要包...

普通人如何利用python做自媒体赚收益

普通人利用Python做自媒体赚收益,最简单的方式是下载某些网站的视频,并利用剪影编辑视频,最后导出发布,每天可以制作个10几条,并设置好定时发布,每天如此坚持下去,一定会有所收获的...

AI能写什么做什么?这些技能已经颠覆你的认知!

在ChatGPT、文心一言等AI工具爆火的今天,人工智能早已不再是科幻电影里的概念,而是实实在在地渗透进我们的生活。**AI到底能写什么?能做什么?它的边界在哪里?**让我们一探究竟!---**1....

Python 3.14 新特性盘点,更新了些什么?

Python3.14.0稳定版将于2025年10月正式发布,目前已进入beta测试阶段。这意味着在往后的几个月里,3.14的新功能已冻结,不再合入新功能(除了修复问题和完善文档)。3...

每天一个Python库:sys模块的5个高频用法(建议收藏)

很多人学Python,一直卡在“写不了实用脚本”。其实,会用标准库,效率直接翻倍。今天分享的是:sys模块。这个模块虽然基础,但非常实用,下面是我亲测常用的5个功能1.获取命令行参数(自动化脚...

Python除了做爬虫抓数据还能做什么?其实还能监视和衡量网站性能

  借助这份对初学者友好的指南,您可以构建自己的自定义Python脚本来自动测量网站的关键速度和性能指标。  在过去的一个月中,Google宣布了许多通过关键速度和性能指标来衡量用户体验的方法。  巧...

python究竟可以用来做些什么

这里就不撰述python的一些像什么“高级语言”之类的比较常规的介绍了,还是老样子,说说一些比较常用的东西吧。python是什么python,一款可编程的开源软件,很多第三方库、框架也是开源的,比如强...

Python 实现 dubbo 协议接口自动化测试

前言python语言也可以实现对dubbo协议的接口进行调用与测试,可以使用python+hessian结合的方式,也可以使用python+telnet结合的方式模拟命令行的模式来实现对...

取消回复欢迎 发表评论: