nginx 请求转发_k8s之HTTP请求负载分发

本文介绍了如何在Kubernetes(k8s)集群中使用Nginx Ingress Controller进行HTTP请求的负载分发。首先,部署Ingress Controller作为Pod监听apiserver,根据Ingress定义生成Nginx配置。接着,创建Ingress资源,通过不同的URL路径转发到不同的Service。例如,将/user请求转发到user-svc,/order请求转发到order-svc。文章还详细阐述了创建Ingress Controller和Ingress资源的步骤,并展示了如何测试转发效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导读

        对于基于HTTP的服务来说,不同的URL地址经常对应不同的后端服务或者虚拟服务器,通常的做法是在应用前添加一个反向代理服务器Nginx,进行请求的负载转发,在Spring Cloud这个微服务框架中,使用zuul网关实现此功能。

        而对于k8s集群来说,当然也是可以用Nginx实现请求的转发,但对于一个成熟的容器编排工具,k8s内置了一个HTTP请求负载分发的组件,就是Ingress Controll。另外,k8s的Service也是具有负载均衡能力的组件。  

38d753a7ebac0f665d6afad39283b3d2.png

用法

        在定义Ingress之前,需要先部署Ingress Controller,以实现所有后端Service提供一个统一的入口。Ingress Controller需要实现基于不同Http URL向后转发的负载分发规则 。

        在K8s中,Ingress Controller将以Pod的形式运行,监控apiserver的/ingress接口后端的backend services,如果service发生变化,则Ingress Controller应自动更新其转发规则。

1、创建Ingress Controller

其实Ingress底层就可以用Nginx实现,Ingress Controller会监听ApiServer,获取全部的Ingress定义,然后根据定义生成Nginx的配置文件。

下面使用nginx-ingress-controller镜像来创建Ingress Controller。

apiVersion: v1kind: ReplicationControllermetadata:  name: nginx-ingress  namespace: ingress  labels:    app: nginx-ingressspec:  replicas: 1  template:    metadata:      name: nginx-ingress      labels:        app: nginx-ingress    spec:      serviceAccountName: ingress-sc      containers:      - name: nginx-ingress        image: imagia/nginx-ingress-controller:0.32.0        imagePullPolicy: IfNotPresent        env:        - name: POD_NAME          valueFrom:            fieldRef:              fieldPath: metadata.name        - name: POD_NAMESPACE          valueFrom:            fieldRef:              fieldPath: metadata.namespace        ports:        - containerPort: 80          hostPort: 80        - containerPort: 443          hostPort: 443

这里为Nginx容器设置了hostPort,将容器应用监听的80和443端口 号映射到物理机上,使得客户端应用可以通过URL地址“http://物理机 IP:80”或“https://物理机IP:443”来访问该Ingress Controller。这使得Nginx 类似于通过NodePort映射到物理机的Service,成为代替kube-proxy的 HTTP层的Load Balancer:

2、创建Ingress

下面的Ingress定义了将/user的请求转发至user-svc的Service上,将/order的请求转发至order-svc的Service上。

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: myweb-ingress  namespace: ingressspec:  rules:  - host: myweb.com    http:      paths:      - path: /api/user        backend:          serviceName: user-svc          servicePort: 8081      - path: /api/order        backend:          serviceName: order-svc          servicePort: 8082

Ingress的策略配置:

(1)所有请求都转发到单个Service上

此时不用配置rules

spec:  backend:    serviceName: user    servicePort: 8080

(2)同一域名,不同url转发到不同的服务上

比如域名都是myweb.com,/api/user转发到user服务,/api/order转发到 order服务。

spec:  rules:  - host: myweb.com    http:      paths:      - path: /api/user        backend:          serviceName: user-svc          servicePort: 8081      - path: /api/order        backend:          serviceName: order-svc          servicePort: 8082

(3)不同域名

域名为myweb1.com的请求转发到user服务,域名为myweb2.com的请求转发到order服务

spec:  rules:  - host: myweb1.com    http:      paths:      - backend:          serviceName: user-svc          servicePort: 8081  - host: myweb2.com    http:      paths:      - backend:          serviceName: order-svc          servicePort: 8082

(4)不使用域名

这种配置用于一个网站不使用域名直接提供服务的场景,此时通过 任意一台运行ingress-controller的Node都能访问到后端的服务。

spec:  rules:  - http:      paths:      - path: /api/user        backend:          serviceName: user-svc          servicePort: 8081

【注】使用无域名的Ingress转发规则时,将默认禁用非安全 HTTP,强制启用HTTPS。

案例

一、简介

创建一个命名空间:ingress,启动两个服务,一个是user,一个是order,利用Ingress-controller将请求/api/user转发到user服务,将请求/api/order转发到order服务。

二、创建服务

(1)创建简单springboot应用

只有两个api接口,分别是/api/order和/api/user,然后打成jar包上传至服务器

02e9a0ea897e70e71444e5e9bcae486d.png

75a201f62d6fdf7948af6da6aa317f3a.png

(2)将上述jar包创建为镜像

将jar包、jdk安装包和Dockerfile放在同一个目录

d730798cb23d66c704c857c5187e05ba.png

Dockerfile文件内容如下:

FROM centos:7LABEL author=lsyENV path=/usr/softRUN mkdir ${path}WORKDIR ${path}ADD jdk-8u191-linux-x64.tar.gz ${path}ENV JAVA_HOME=${path}/jdk1.8.0_191ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarENV PATH=$JAVA_HOME/bin:$PATHCOPY service-1.0.jar ${path}EXPOSE 8080CMD  java -jar service-1.0.jar

使用命令创建镜像:

docker build ./ -t  cnode-1:5000/ingress-service:v1.0

镜像创建完成后记得上传到docker私有仓库

(3)在ingress命名空间启动相应的ReplicationController和Service

user-rc.yaml

apiVersion: v1kind: ReplicationControllermetadata:  name: user-rc  namespace: ingress  labels:    name: user-rcspec:  replicas: 1  selector:    name: user-rc  template:    metadata:      name: user-rc      labels:        name: user-rc    spec:      containers:      - name: user-rc        image: cnode-1:5000/ingress-service:v1.0        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080

user-svc.yaml

apiVersion: v1kind: Servicemetadata:  name: user-svc  namespace: ingressspec:  selector:    name: user-rc  ports:  - port: 8081    targetPort: 8080

order-rc.yaml

apiVersion: v1kind: ReplicationControllermetadata:  name: order-rc  namespace: ingress  labels:    name: order-rcspec:  replicas: 1  selector:    name: order-rc  template:    metadata:      name: order-rc      labels:        name: order-rc    spec:      containers:      - name: order-rc        image: cnode-1:5000/ingress-service:v1.0        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080

order-svc.yaml

apiVersion: v1kind: Servicemetadata:  name: order-svc  namespace: ingressspec:  selector:    name: order-rc  ports:  - port: 8082    targetPort: 8080

分别使用kubectl create 命令创建上述资源

(4)在ingress命名空间中创建ServiceAccount

创建ServiceAccount和ClusterRoleBinding,如果不创建的话,Ingress-controller会使用默认名为default的ServiceAccount,default权限很弱,获取不到相应的资源信息,这样Ingress-controller会启动失败。

---apiVersion: v1kind: ServiceAccountmetadata:  labels:    name: ingress-sc  name: ingress-sc  namespace: ingress---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata:  name: ingress  labels:    name: ingress-crbroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- kind: ServiceAccount  name: ingress-sc  namespace: ingress

(5)创建Ingress Controller

apiVersion: v1kind: ReplicationControllermetadata:  name: nginx-ingress  namespace: ingress  labels:    app: nginx-ingressspec:  replicas: 1  template:    metadata:      name: nginx-ingress      labels:        app: nginx-ingress    spec:      serviceAccountName: ingress-sc      containers:      - name: nginx-ingress        image: imagia/nginx-ingress-controller:0.32.0        imagePullPolicy: IfNotPresent        env:        - name: POD_NAME          valueFrom:            fieldRef:              fieldPath: metadata.name        - name: POD_NAMESPACE          valueFrom:            fieldRef:              fieldPath: metadata.namespace        ports:        - containerPort: 80          hostPort: 80        - containerPort: 443          hostPort: 443

创建完后查看:

182045d87e6f2f5255c2c148172588f2.png

【注】环境变量POD_NAME和POD_NAMESPACE是必须要设置的,不然会报错。

(6)创建Ingress

也就是规则设置,将请求地址为/api/user转发至user服务,请求地址为/api/order的转发至order服务。

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: myweb-ingress  namespace: ingressspec:  rules:  - host: myweb.com    http:      paths:      - path: /api/user        backend:          serviceName: user-svc          servicePort: 8081      - path: /api/order        backend:          serviceName: order-svc          servicePort: 8082

创建完后查看:

8a6513cb301b5f68b959b3df2ab54463.png

可以看到,它的Hosts是myweb.com,物理机地址是192.168.197.120,端口为80.

如果ADDRESS列为空, 则通常说明Nginx未能正确连接到后端Service,需要排错。

【注】为什么只有一个ip,是因为这个RC只有一个Pod,调度到cnode-2这台机运行,如果想要每台机器都有一个,建议使用DaemonSet类型的Controller

此时查看ingress-controller的Pod的日志:

先获取Pod的名字

fc0206613c77460d28a1feb773fac675.png

然后查看日志:

44ed7c79f35efb37066a1587cd2f67c2.png

8b42e2203fa39b158595c772973a4204.png

从上图可以看到,当ingress创建之后,ingress-controller会自动去加载,然后生成对应的nginx的conf文件。

进入容器查看nginx的配置文件:文件是/etc/nginx/nginx.conf

7012cbbe6ba3969d502c810e362fe4d6.png

(7)测试效果

由于并没有上述设置的myweb.com这个域名,所以需要进行解析。

curl --resolve myweb.com:80:192.168.197.120 http://myweb.com:80/api/order

访问order服务:

4cf467da365fed307f2634632c8dab25.png

查看日志:可以看到是转发到order-svc这个Service上了

192.168.197.100 - - [31/Oct/2020:07:40:46 +0000] "GET /api/order HTTP/1.1" 200 21 "-" "curl/7.29.0" 82 0.004 [ingress-order-svc-8082] [] 10.36.0.4:8080 21 0.004 200 0f7dfb1134644ee2ceb7a7d364ddfe45

访问user服务:

0911989160643f5a7cabc1de6130a041.png

查看日志:可以看到是转发到user-svc这个Service上了

192.168.197.100 - - [31/Oct/2020:07:42:16 +0000] "GET /api/user HTTP/1.1" 200 20 "-" "curl/7.29.0" 81 0.011 [ingress-user-svc-8081] [] 10.44.0.3:8080 20 0.010 200 46f66ab540c41590a74bbea66bd65ea8

结尾

秋风吹落叶,天气微凉,注意保暖!

40c8d70a109729c0400ec5e445289c71.png

98a96efd19a22e006df033086c45d7fe.png往期推荐
  • k8s重器之Service

  • k8s之DNS服务器搭建

  • 服务挂掉导致需要对k8s水平扩容

  • k8s基本使用

下期见

    3e9f04ea0d9ef155fa4cc807a2deba0e.png

Liusy01

一个分享Java后端学习日志的公众号

欢迎大家点个在看

分享至朋友圈

好文!点个在看!
<think>好的,我需要帮助用户理解Kubernetes中负载均衡与Nginx的关系,特别是回答他们的问题:“k8s负载均衡是否使用Nginx实现?”首先,我得回顾一下用户提供的四个引用内容,看看里面有哪些信息可以利用。 引用[1]提到在K8S中使用Nginx配置负载均衡,比如修改配置文件、清理注释等。这说明在K8S环境中确实可以手动配置Nginx作为负载均衡器。引用[2]指出k8s默认使用kube-proxy进行Service的负载均衡,但可能涉及SNAT问题,而提到NodePort或LoadBalancer来获取真实IP。这里需要区分内置的负载均衡机制和外部工具如Nginx的作用。引用[3]讨论了基于ingress-nginx的服务发现和负载均衡,通过Ingress资源来定义路由规则,将外部请求分发到不同的Service。引用[4]则是在实验环境中使用Nginxk8s的Service做负载均衡,说明Nginx可以作为外部负载均衡器与k8s集成。 接下来,我需要组织这些信息,明确Kubernetes自身的负载均衡机制和Nginx所扮演的角色。用户的问题核心是确认k8s是否使用Nginx实现负载均衡。根据引用,k8s默认使用kube-proxy和Service来实现内部的负载均衡,而Nginx通常是作为Ingress控制器或外部负载均衡器来补充,特别是在处理HTTP/HTTPS流量时。因此,答案应该是:k8s本身不直接用Nginx,但可以通过集成Nginx作为Ingress控制器或外部LB来实现更高级的负载均衡。 需要注意区分不同类型的负载均衡,比如Service的ClusterIP和NodePort,以及Ingress的作用。同时,要提到如何配置Nginx Ingress,比如引用[3]中的示例,说明如何定义路由规则。可能还需要解释为什么需要Nginx,比如获取真实IP(引用[2])、更灵活的流量管理(引用[3])等。 最后,生成相关问题时要围绕k8s负载均衡的不同实现方式、Ingress控制器的选择、配置方法以及优化场景等,确保问题能引导用户进一步探索。</think>Kubernetes中的负载均衡机制与Nginx的关系可分为**原生实现**和**外部扩展**两种模式,具体如下: --- ### 一、Kubernetes原生负载均衡 1. **Service与kube-proxy** Kubernetes默认通过`kube-proxy`组件实现Service的负载均衡。它支持以下模式: - **iptables模式**:为每个Service生成iptables规则,通过概率轮询(Probability-based)分发流量。 - **IPVS模式**:基于内核级IP虚拟服务器,支持更高效的负载均衡算法(如轮询、加权轮询、最小连接数)[^2]。 - 特点:**无需依赖外部组件**,但无法直接处理L7(HTTP/HTTPS)流量,且默认SNAT会隐藏客户端真实IP。 2. **LoadBalancer类型Service** 在云平台(如AWS、GCP)中,直接创建云厂商的负载均衡器,但**与Nginx无关**。 --- ### 二、Nginx在Kubernetes中的角色 1. **作为Ingress控制器** - **功能**:通过`ingress-nginx`实现L7负载均衡,支持基于域名、路径的路由规则,以及SSL终止、流量拆分等高级功能。 - **配置示例**: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - host: www.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-service port: 80 ``` 此配置将`www.example.com`的流量分发到后端Service `web-service`[^3]。 2. **作为外部负载均衡器** - 在集群外部署Nginx,通过反向代理将流量分发到Kubernetes Node的NodePort或Pod IP[^4]。 - 适用场景:需要精细控制流量策略(如限流、缓存)或混合云环境。 --- ### 三、关键区别与选择 | 特性 | Kubernetes原生负载均衡 | Nginx实现 | |---------------------|--------------------------------|-------------------------| | 协议支持 | L4(TCP/UDP) | L4 + L7(HTTP/HTTPS) | | 客户端IP透传 | 需配置`externalTrafficPolicy: Local` | 默认支持 | | 高级路由功能 | 不支持 | 支持(如路径重写、鉴权) | | 部署复杂度 | 低(内置) | 需单独部署Ingress控制器 | --- ### 回答总结 **Kubernetes的负载均衡不强制依赖Nginx**,但其原生能力有限。Nginx通常以两种形式补充: 1. **Ingress控制器**:用于HTTP/HTTPS流量的高级路由。 2. **外部负载均衡器**:与云厂商LB配合或替代云厂商方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值