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

理解Kubernetes中的Nginx Ingress

nanshan 2024-10-09 12:55 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有很多,读者可以根据需要选择。

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

相关推荐

0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)

文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...

ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes

为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...

生产环境starrocks 3.1存算一体集群部署

集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...

在CentOS上添加swap虚拟内存并设置优先级

现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...

国产深度(deepin)操作系统优化指南

1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...

postgresql-15.4 多节点主从(读写分离)

1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...

Docker 容器 Java 服务内存与 GC 优化实施方案

一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...

虚拟内存设置、解决linux内存不够问题

虚拟内存设置(解决linux内存不够情况)背景介绍  Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...

Elasticsearch性能调优(5):服务器配置选择

在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...

Es如何落地

一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...

针对Linux内存管理知识学习总结

现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...

MySQL进阶之性能优化

概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...

Linux Cgroups(Control Groups)原理

LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...

linux 常用性能优化参数及理解

1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...

如何在 Linux 中使用 Sysctl 命令?

sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...

取消回复欢迎 发表评论: