k8s之HTTP请求负载分发
一、导读
对于基于HTTP的服务来说,不同的URL地址经常对应不同的后端服务或者虚拟服务器,通常的做法是在应用前添加一个反向代理服务器Nginx,进行请求的负载转发,在Spring Cloud这个微服务框架中,使用zuul网关实现此功能。
而对于k8s集群来说,当然也是可以用Nginx实现请求的转发,但对于一个成熟的容器编排工具,k8s内置了一个HTTP请求负载分发的组件,就是Ingress Controll。另外,k8s的Service也是具有负载均衡能力的组件。
二、用法
在定义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: v1
kind: ReplicationController
metadata:
name: nginx-ingress
namespace: ingress
labels:
app: nginx-ingress
spec:
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/v1beta1
kind: Ingress
metadata:
name: myweb-ingress
namespace: ingress
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
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。
三、案例
1、简介
创建一个命名空间:ingress,启动两个服务,一个是user,一个是order,利用Ingress-controller将请求/api/user转发到user服务,将请求/api/order转发到order服务。
2、创建服务
(1)创建简单springboot应用
只有两个api接口,分别是/api/order和/api/user,然后打成jar包上传至服务器
(2)将上述jar包创建为镜像
将jar包、jdk安装包和Dockerfile放在同一个目录
Dockerfile文件内容如下:
FROM centos:7 LABEL author=lsy ENV path=/usr/soft RUN mkdir ${path} WORKDIR ${path} ADD jdk-8u191-linux-x64.tar.gz ${path} ENV JAVA_HOME=${path}/jdk1.8.0_191
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH COPY service-1.0.jar ${path} EXPOSE 8080 CMD 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: v1
kind: ReplicationController
metadata:
name: user-rc
namespace: ingress
labels:
name: user-rc
spec:
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: v1
kind: Service
metadata:
name: user-svc
namespace: ingress
spec:
selector:
name: user-rc
ports:
- port: 8081
targetPort: 8080
order-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: order-rc
namespace: ingress
labels:
name: order-rc
spec:
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: v1
kind: Service
metadata:
name: order-svc
namespace: ingress
spec:
selector:
name: order-rc
ports:
- port: 8082
targetPort: 8080
分别使用kubectl create 命令创建上述资源
(4)在ingress命名空间中创建ServiceAccount
创建ServiceAccount和ClusterRoleBinding,如果不创建的话,Ingress-controller会使用默认名为default的ServiceAccount,default权限很弱,获取不到相应的资源信息,这样Ingress-controller会启动失败。
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
name: ingress-sc
name: ingress-sc
namespace: ingress ---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: ingress
labels:
name: ingress-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: ingress-sc
namespace: ingress
(5)创建Ingress Controller
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-ingress
namespace: ingress
labels:
app: nginx-ingress
spec:
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
创建完后查看:
【注】环境变量POD_NAME和POD_NAMESPACE是必须要设置的,不然会报错。
(6)创建Ingress
也就是规则设置,将请求地址为/api/user转发至user服务,请求地址为/api/order的转发至order服务。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myweb-ingress
namespace: ingress
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
创建完后查看:
可以看到,它的Hosts是myweb.com,物理机地址是192.168.197.120,端口为80.
如果ADDRESS列为空, 则通常说明Nginx未能正确连接到后端Service,需要排错。
【注】为什么只有一个ip,是因为这个RC只有一个Pod,调度到cnode-2这台机运行,如果想要每台机器都有一个,建议使用DaemonSet类型的Controller
此时查看ingress-controller的Pod的日志:
先获取Pod的名字
然后查看日志:
从上图可以看到,当ingress创建之后,ingress-controller会自动去加载,然后生成对应的nginx的conf文件。
进入容器查看nginx的配置文件:文件是/etc/nginx/nginx.conf
(7)测试效果
由于并没有上述设置的myweb.com这个域名,所以需要进行解析。
curl --resolve myweb.com:80:192.168.197.120 http://myweb.com:80/api/order
访问order服务:
查看日志:可以看到是转发到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服务:
查看日志:可以看到是转发到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
===============================
我是Liusy,一个喜欢健身的程序员。
欢迎关注【上古伪神】,一起交流Java技术及健身,一起成为Java大神。
来都来了,关注一波再溜呗。
k8s之HTTP请求负载分发的更多相关文章
- weblogic负载分发
博客分类: weblogic 负载均衡的实现方式有很多种,这里只介绍三种相对来说成本较低的方案(维护成本以及费用成本)weblogic自带的proxy.apache.nginx 1.weblogic自 ...
- Servlet 中 RequestDispacher 请求与分发
RequestDispacher 请求与分发使用HttpServletRequest的getRequestDispatcher()方法取得 Login.java页面 package control; ...
- 一个线上问题的思考:Eureka注册中心集群如何实现客户端请求负载及故障转移?
前言 先抛一个问题给我聪明的读者,如果你们使用微服务SpringCloud-Netflix进行业务开发,那么线上注册中心肯定也是用了集群部署,问题来了: 你了解Eureka注册中心集群如何实现客户端请 ...
- K8s多节点部署+负载均衡+keepalived ——囊萤映雪
K8s多节点部署+负载均衡+keepalived --囊萤映雪 1.多节点master2 部署 2.负载均衡部署+keepalived 1.多节点master2部署: #从master01节点上拷贝证 ...
- k8s服务发现和负载均衡(转)
原文 http://m635674608.iteye.com/blog/2360095 kubernetes中如何发现服务 如何发现pod提供的服务 如何使用kube-dns发现服务 servic ...
- k8s集群Job负载 支持多个 Pod 可靠的并发执行,如何权衡利弊选择适合的并行计算模式?
k8s的Job负载 支持多个 Pod 可靠的并发执行,如何权衡利弊选择适合的并行计算模式? 简单聊聊你对工作负载Job的理解? Job 支持多个 Pod 可靠的并发执行,如何权衡利弊选择适合的并行计算 ...
- nginx 请求负载 转发规则设置
(1)轮询(默认) weight=5; #本机上的Squid开启3128端口,不是必须要squid server 192.168.8.2x:80 weight=1 ...
- Nginx 多进程连接请求/事件分发流程分析
Nginx使用多进程的方法进行任务处理,每个worker进程只有一个线程,单线程循环处理全部监听的事件.本文重点分析一下多进程间的负载均衡问题以及Nginx多进程事件处理流程,方便大家自己写程序的时候 ...
- k8s istio 配置请求的路由规则
使用istio我们可以根据权重和HTTP headers来动态配置请求路由. 基于内容的路由 因为BookInfo示例部署了3个版本的评论微服务,我们需要设置一个默认路由. 否则,当你多次访问应用程序 ...
随机推荐
- 快速理解Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容的区别
<Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容有何不同?>老猿介绍了二者的区别,为了快速理解,老猿在此使用另外一种方式补充说明一下: 1.使用%r是调用objec ...
- PyQt(Python+Qt)学习随笔:利用QWidget部件的palette以及ColorGroup、colorRole局部调整部件的特定范围颜色
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 在<PyQt(Python+Qt)学习随笔:QWidget部件的 ...
- PLSQL Developer 工具应用
用户scott使用: 解锁scott: 第一步:登陆管理员 SQL语句:Sqlplus sys/tiger as sysdba 第二步:解锁scott SQL语句:Alter user scott a ...
- 补:冲刺Day2
每天举行站立式会议照片: 昨天已完成的工作: 各个成员在 Alpha 阶段认领的任务. 今天各个成员的任务安排. 冲刺Day1博客. 今天计划完成的工作: 成员 任务 高嘉淳 完成登陆.注册 覃泽泰 ...
- STL-Vector容量问题:
1.clear,erase ,pop_back() 函数只删除对象,并没有释放vec中的内存,若对象是指针还需要delete:2.在erase,clear,pop_back()删除对象的后,size改 ...
- Dwango Programming Contest 6th E 题解
题目大意 你有一条区间\([0, X)\),并且有一个数组\(L_1, ..., L_n\).对于任意\(1 \leq i \leq n\),你可以指定一个非负整数\(0 \leq j_i \leq ...
- POI2009 KON-Ticket Inspector
题目链接 Description 一辆火车依次经过 \(n\) 个车站,顺序是 \(1, 2, 3, ..., n - 1, n\).给定 \(A_{i, j}\) 表示从 \(i\) 站上车,\(j ...
- rbd锁引起kvm虚拟机无法启动的故障
前言 环境因为一些问题(网络,或者磁盘,或者其它各种异常),引起了集群的状态的一些变化,变化之后,集群的某些虚拟机正常某些虚拟机出现异常,异常现象就是无法启动 特别是win server2008 ,会 ...
- 推荐系统实践 0x11 NeuralCF
前言 这一篇文章我们来谈一下2017年新加坡国立大学提出的基于深度学习的系统过滤模型NeuralCF.我们在之前讲过矩阵分解技术,将协同过滤中的共现矩阵分解成用户向量矩阵以及物品向量矩阵.那么Embe ...
- [打基础]OI/ACM基本功&一些小功能的实现&一些错误(持续更新)
基本功 前导0 如题,有时候需要把3输出成03这样子,可以调用 cout.width(x); ,x表示以几位,用 cout.fill(x); 来给出前导填充的内容,一般x以char的形式给出 例如可以 ...