目录
一、Ingress 和 Ingress Controller 概述
1.4 Ingress 和 Ingress Controller 总结
1.5 使用 Ingress Controller 代理 k8s 内部 pod 的流程
二、创建两个 ingress-controller 高可用的 pod
三、通过 keepalived + nginx 实现 ingress-nginx-controller 高可用
四、测试 Ingress HTTP 代理 k8s 内部 pod
五、测试 Ingress HTTPS 代理 k8s 内部 pod
一、Ingress 和 Ingress Controller 概述
1.1 回顾下 service 四层代理
- 在 k8s 中为什么要做负载均衡?
Pod 漂问题,可以理解成 PodIP 是变化的。Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等。通俗地说,这个 Pod 可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着 Pod 的创建和销毁,PodIP 肯定会动态变化;那么如何把这个动态的PodIP 暴露出去?这里借助于 Kubernetes 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是NodePort模式,即在每个节点上开起一个端口,然后转发到内部 PodIP 上。
Service 可以通过标签选择器找到它所关联的 Pod。但是属于四层代理,只能基于 IP 和端口代理。
- Service 存在一个问题,什么问题呢?
Service 的 type类型有很多,如 NodePort、clusterlp、loadbalancer、externalname,如果Service 想要被 k8s 集群外部访问,需要用 NodePort 类型,但是NodePort 类型的 svc有如下几个问题:
nodeport 会在物理机映射一个端口,绑定到物理机上,这样就导致,每个服务都要映射一个端口端口过多,维护困难,还有就是 Service 底层使用的是iptables 或者 ipvs,仅支持四层代理,无法基于 https 协议做代理,因此我们这次讲解的是 ingress-controller 七层代理。
- 四层负载和七层负载的区别:
1)四层负载:四层的负载均衡就是基于 IP+端口的负载均衡:在三层负载均衡的基础上,通过发布三层的 IP 地址(VIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行 NAT 处理,转发至后台服务器,并记录下这个 TCP 或者 UDP 的流量是由哪台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理。
2)七层的负载均衡就是基于虚拟的 URL 或主机IP 的负载均衡:在四层负载均衡的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比如同一个 Web 服务器的负载均衡,除了根据 VIP 加 80 端口辨别是否需要处理的流量,还可根据七层的 URL、浏览器类别、语言来决定是否要进行负载均衡。举个例子,如果你的 Web 服务器分成两组,一组是中文语言的,一组是英文语言的,那么七层负载均衡就可以当用户来访问你的域名时,自动辨别用户语言,然后选择对应的语言服务器组进行负载均衡处理。
3)四层负载均衡工作在传输层,七层负载均衡工作在应用层。
【云原生 | Kubernetes 实战】12、K8s 四层代理 Service 入门到企业实战应用(上)_Stars.Sky的博客-CSDN博客
1.2 Ingress 介绍
Ingress 官网定义:Ingress可以把进入到集群内部的请求转发到集群中的一些服务上,从而可以把服务映射到集群外部。Ingress 能把集群内Service 配置成外网能够访问的 URL,流量负载均衡,提供基于域名访问的虚拟主机等。
Ingress 简单的理解就是你原来需要改Nginx配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改Nginx 了,直接改yaml然后创建/更新就行了;那么问题来了:”Nginx 该怎么处理?”
Ingress Controller 这东西就是解决 “Nginx 的处理方式” 的;Ingress Controller 通过与 Kubernetes API 交互,动态的去感知集群中Ingress规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下。
Ingress 总结:ingress 是 k8s 中的资源,主要是管理 ingress-controller 这个代理的配置文件。
1.3 Ingress Controller 介绍
Ingress Controller 是一个七层负载均衡调度器,客户端的请求先到达这个七层负载均衡调度器,由七层负载均衡器在反向代理到后端 pod,常见的七层负载均衡器有 nginx、traefik,以我们熟悉的 nginx 为例,假如请求到达 nginx,会通过 upstream 反向代理到后端 pod 应用,但是后端pod 的 ip 地址是一直在变化的,因此在后端 pod 前需要加一个 service,这个 service 只是起到分组的作用,那么我们 upstream 只需要填写 service 地址即可。
Ingress-controller 里面封装就是 nginx,那我直接在物理机上装个 nginx 就行了啊,为啥还弄个 Ingress-controller?
nginx 配置文件一改动,你还需要手动 reload 一下才可以生效,但是如果用 ingress-controller 封装的 nginx,你 ingress 维护配置,ingress 创建好之后,会自动的把配置文件传到ingress-controller 这个 pod 里,会自动进行 reload,然后配置就生效了。
1.4 Ingress 和 Ingress Controller 总结
Ingress Controller 结合 Ingress 定义的规则生成配置,然后动态更新 ingress-controller 里的Nginx 或者 trafik 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。
1.5 使用 Ingress Controller 代理 k8s 内部 pod 的流程
- 部署 Ingress controller,我们 ingress controller 使用的是 nginx;
- 创建 Pod 应用,可以通过控制器创建 pod;
- 创建 Service,用来分组 pod;
- 创建 Ingress http,测试通过 http 访问应用;
- 创建Ingress https,测试通过 https 访问应用。
使用七层负载均衡调度器 ingress controller 时,当客户端访问 kubernetes 集群内部的应用时,数据包走向如下图流程所示:
二、创建两个 ingress-controller 高可用的 pod
Ingress Controller 是集群流量的接入层,对它做高可用非常重要,可以基于 keepalive 实现nginx-ingress-controller 高可用,具体实现如下:
Ingress-controller 根据 Deployment + nodeSeletor + pod 反亲和性方式部署在 k8s 指定的两个 work 节点,nginx-ingress-controller 这个 pod 共享宿主机 ip,然后通过 keepalive + nginx 实现nginx-ingress-controller 高可用。
GitHub 项目地址:GitHub – kubernetes/ingress-nginx: Ingress-NGINX Controller for Kubernetes
ingress-nginx/deploy/static/provider/baremetal at main · kubernetes/ingress-nginx · GitHub
上传 ingress-nginx-controllerv1.1.0.tar.gz 和 kube-webhook-certgen-v1.1.0.tar.gz 相关镜像到 node1 和 node2 并解压:
相关资料下载地址:https://download.csdn.net/download/weixin_46560589/87355471
注意:因为我们现在安装的 k8s 版本是 1.25,那就需要用ctr -n=k8s.io images import 导出镜像,如果 k8s 版本是 1.24 之前的,可以用 docker load -i 解压。
[root@k8s-node1 ~]# ctr -n=k8s.io images import ingress-nginx-controllerv1.1.0.tar.gz
[root@k8s-node1 ~]# ctr -n=k8s.io images import kube-webhook-certgen-v1.1.0.tar.gz
[root@k8s-node2 ~]# ctr -n=k8s.io images import ingress-nginx-controllerv1.1.0.tar.gz
[root@k8s-node2 ~]# ctr -n=k8s.io images import kube-webhook-certgen-v1.1.0.tar.gz
# 把 ingress-deploy.yaml 上传到这,创建 pod
[root@k8s-master01 ~]# mkdir ingress
[root@k8s-master01 ~]# cd ingress/
[root@k8s-master01 ingress]# ls
ingress-deploy.yaml
[root@k8s-master01 ingress]# kubectl apply -f ingress-deploy.yaml
[root@k8s-master01 ingress]# kubectl get pods -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-2hbsq 0/1 Completed 0 27s 10.244.169.144 k8s-node2 <none> <none>
ingress-nginx-admission-patch-vbj8r 0/1 Completed 1 27s 10.244.169.145 k8s-node2 <none> <none>
ingress-nginx-controller-64bdc78c96-6j844 1/1 Running 0 27s 192.168.78.131 k8s-node1 <none> <none>
ingress-nginx-controller-64bdc78c96-9jpsp 1/1 Running 0 27s 192.168.78.132 k8s-node2 <none> <none>
如果执行创建资源命令时报错如下错误:
[root@k8s-master01 ingress]# kubectl apply -f ingress-deploy.yaml
Error from server (InternalError): error when creating "ingress-myapp.yaml": Internal error occurred: failed calling webhook "validate.nginx .inaress kubernetes .io":failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networkina/wl/inaresses ?timeout=10s":context deadline exceeded
# 解决办法
[root@k8s-master01 ingress]# kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
[root@k8s-master01 ingress]# kubectl apply -f ingress-deploy.yaml
三、通过 keepalived + nginx 实现 ingress-nginx-controller 高可用
3.1 安装 nginx 主备
在 node1 和 node2 上做 nginx 主备安装
[root@k8s-node1 ~]# yum install epel-release nginx keepalived nginx-mod-stream -y
[root@k8s-node2 ~]# yum install epel-release nginx keepalived nginx-mod-stream -y
3.2 修改 nginx 配置文件
在 node1 和 node2 上都要修改
vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
# 四层负载均衡,为两台 Master apiserver 组件提供负载均衡
stream {
log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
access_log /var/log/nginx/k8s-access.log main;
upstream k8s-ingress-controller {
server 192.168.78.131:80 weight=5 max_fails=3 fail_timeout=30s; # node1 IP:PORT
server 192.168.78.132:80 weight=5 max_fails=3 fail_timeout=30s; # node2 IP:PORT
}
server {
listen 30080;
proxy_pass k8s-ingress-controller;
}
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
}
注意:nginx 监听端口变成大于 30000 的端口,比方说 30080,这样访问 域名:30080 就可以了,必须是满足大于 30000 以上,才能代理 ingress-controller。
3.3 keepalive 配置
node1 为主 keepalived 配置
[root@k8s-node1 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id NGINX_MASTER
}
# 指定检查 nginx 工作状态脚本(根据 nginx 状态判断是否故障转移)
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
}
vrrp_instance VI_1 {
state MASTER # 主服务器,备服务器设置为 BACKUP
interface ens32 # 修改为实际网卡名
virtual_router_id 51 # VRRP 路由 ID 实例,每个实例是唯一的
priority 100 # 优先级,备服务器设置 90
advert_int 1 # 指定 VRRP 心跳包通告间隔时间,默认 1 秒
authentication {
auth_type PASS
auth_pass 1111
}
# 虚拟 IP
virtual_ipaddress {
192.168.78.199/24 # 虚拟 ip 要和 node 节点物理 ip 同网段,且该 ip 没有被占用
}
track_script {
check_nginx
}
}
# 编写 nginx 检测脚本
[root@k8s-node1 ~]# vim /etc/keepalived/check_nginx.sh
#!/bin/bash
#1、判断 Nginx 是否存活
counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )
if [ $counter -eq 0 ]; then
#2、如果不存活则尝试启动 Nginx
systemctl restart nginx.service
sleep 2
#3、等待 2 秒后再次获取一次 Nginx 状态
counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )
#4、再次进行判断,如 Nginx 还不存活则停止 Keepalived,让地址进行漂移
if [ $counter -eq 0 ]; then
systemctl stop keepalived.service
fi
fi
# 添加可执行权限
[root@k8s-node1 ~]# chmod +x /etc/keepalived/check_nginx.sh
node2 为备 keeplived 配置
[root@k8s-node2 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id NGINX_MASTER
}
# 指定检查 nginx 工作状态脚本(根据 nginx 状态判断是否故障转移)
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
}
vrrp_instance VI_1 {
state BACKUP # 主服务器,备服务器设置为 BACKUP
interface ens32 # 修改为实际网卡名
virtual_router_id 51 # VRRP 路由 ID 实例,每个实例是唯一的
priority 90 # 优先级,备服务器设置 90
advert_int 1 # 指定 VRRP 心跳包通告间隔时间,默认 1 秒
authentication {
auth_type PASS
auth_pass 1111
}
# 虚拟 IP
virtual_ipaddress {
192.168.78.199/24 # 虚拟 ip 要和 node 节点物理 ip 同网段,且该 ip 没有被占用
}
track_script {
check_nginx
}
}
# 编写 nginx 检测脚本
[root@k8s-node2 ~]# vim /etc/keepalived/check_nginx.sh
#!/bin/bash
#1、判断 Nginx 是否存活
counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )
if [ $counter -eq 0 ]; then
#2、如果不存活则尝试启动 Nginx
systemctl restart nginx.service
sleep 2
#3、等待 2 秒后再次获取一次 Nginx 状态
counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )
#4、再次进行判断,如 Nginx 还不存活则停止 Keepalived,让地址进行漂移
if [ $counter -eq 0 ]; then
systemctl stop keepalived.service
fi
fi
# 添加可执行权限
[root@k8s-node2 ~]# chmod +x /etc/keepalived/check_nginx.sh
3.4 启动服务
node1 和 node2 都要启动服务:
systemctl daemon-reload
systemctl enable nginx.service --now
systemctl enable keepalived.service --now
3.5 测试 keeplived
# vip 是在 node1 上,node2 没有,因为 node1 优先级高
[root@k8s-node1 ~]# ip addr
······
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:9c:58:75 brd ff:ff:ff:ff:ff:ff
inet 192.168.78.131/24 brd 192.168.78.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet 192.168.78.199/24 scope global secondary ens32
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe9c:5875/64 scope link
valid_lft forever preferred_lft forever
······
# 在 node1 暂停 keeplived 服务
[root@k8s-node1 ~]# systemctl stop keepalived.service
# vip 会漂移到 node2
[root@k8s-node2 ~]# ip addr
······
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:eb:b1:2b brd ff:ff:ff:ff:ff:ff
inet 192.168.78.132/24 brd 192.168.78.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet 192.168.78.199/24 scope global secondary ens32
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feeb:b12b/64 scope link
valid_lft forever preferred_lft forever
······
# node1 恢复 keeplived 服务
[root@k8s-node1 ~]# systemctl start keepalived.service
# vip 又漂移回来了
[root@k8s-node1 ~]# ip addr
······
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:9c:58:75 brd ff:ff:ff:ff:ff:ff
inet 192.168.78.131/24 brd 192.168.78.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet 192.168.78.199/24 scope global secondary ens32
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe9c:5875/64 scope link
valid_lft forever preferred_lft forever
······
四、测试 Ingress HTTP 代理 k8s 内部 pod
4.1 部署后端 tomcat 服务
[root@k8s-master01 ingress]# vim ingress-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: default
spec:
selector:
app: tomcat
release: canary
ports:
- name: http
targetPort: 8080
port: 8080
- name: ajp
targetPort: 8009
port: 8009
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: tomcat
release: canary
template:
metadata:
labels:
app: tomcat
release: canary
spec:
containers:
- name: tomcat
image: tomcat:8.5.34-jre8-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
name: ajp
containerPort: 8009
[root@k8s-master01 ingress]# kubectl apply -f ingress-demo.yaml
[root@k8s-master01 ingress]# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-deploy-64d6489dd9-l2xlq 1/1 Running 0 39s
tomcat-deploy-64d6489dd9-qc5dc 1/1 Running 0 39s
4.2 编写 ingress 规则
# 编写 ingress 的配置清单
[root@k8s-master01 ingress]# vim ingress-myapp.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-myapp
namespace: default
spec:
ingressClassName: nginx
rules: # 定义后端转发的规则
- host: tomcat.lucky.com # 通过域名进行转发
http:
paths:
- backend: # 配置后端服务
service:
name: tomcat
port:
number: 8080
path: / # 配置访问路径,如果 url 进行转发,需要修改,默认访问的路径为 "/"
pathType: Prefix
[root@k8s-master01 ingress]# kubectl apply -f ingress-myapp.yaml
ingress.networking.k8s.io/ingress-myapp created
[root@k8s-master01 ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-myapp nginx tomcat.lucky.com 192.168.78.131,192.168.78.132 80 92s
[root@k8s-master01 ingress]# kubectl describe ingress ingress-myapp
Name: ingress-myapp
Labels: <none>
Namespace: default
Address: 192.168.78.131,192.168.78.132
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
tomcat.lucky.com
/ tomcat:8080 (10.244.169.147:8080,10.244.36.109:8080)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 16s (x2 over 48s) nginx-ingress-controller Scheduled for sync
Normal Sync 16s (x2 over 47s) nginx-ingress-controller Scheduled for sync
4.3 测试访问 tomcat
修改电脑本地的 C:\Windows\System32\drivers\etc\host 文件,增加如下一行,下面的 ip 是 vip:
192.168.78.199 tomcat.lucky.com
在浏览器访问 http://tomcat.lucky.com
tomcat.lucky.com:30080 -> 192.168.78.199:30080 -> 192.168.40.181:80、192.168.40.182:80 -> svc:tomcat:8080 -> pod:tomcat-deploy-xxx
基于名称的虚拟托管:Ingress | Kubernetes
五、测试 Ingress HTTPS 代理 k8s 内部 pod
5.1 构建 TLS 站点
# 准备证书,在 master1 节点操作
[root@k8s-master01 ~]# openssl genrsa -out tls.key 2048
[root@k8s-master01 ~]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=sky.lucky.com
# 生成 secret
[root@k8s-master01 ~]# kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key
# 查看 secrets
[root@k8s-master01 ~]# kubectl get secrets
NAME TYPE DATA AGE
tomcat-ingress-secret kubernetes.io/tls 2 18s
[root@k8s-master01 ~]# kubectl describe secrets tomcat-ingress-secret
Name: tomcat-ingress-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/tls
Data
====
tls.crt: 1285 bytes
tls.key: 1675 bytes
5.2 创建 Ingress
[root@k8s-master01 ingress]# vim ingress-tomcat-tls.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tomcat-tls
namespace: default
spec:
ingressClassName: nginx
tls:
- hosts:
- sky.lucky.com
secretName: tomcat-ingress-secret
rules:
- host: sky.lucky.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tomcat
port:
number: 8080
[root@k8s-master01 ingress]# kubectl apply -f ingress-tomcat-tls.yaml
[root@k8s-master01 ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-myapp nginx tomcat.lucky.com 192.168.78.131,192.168.78.132 80 37m
ingress-tomcat-tls nginx sky.lucky.com 192.168.78.131,192.168.78.132 80, 443 86s
5.3 测试访问 tomcat
修改电脑本地的 C:\Windows\System32\drivers\etc\host 文件,增加如下一行,下面的 ip 是 vip:
192.168.78.199 sky.lucky.com
在浏览器访问 sky.lucky.com
上一篇文章:【云原生 | Kubernetes 实战】18、K8s 安全实战篇之 RBAC 认证授权(下)_Stars.Sky的博客-CSDN博客
下一篇文章:【云原生 | Kubernetes 实战】20、K8s Ingress 实现业务灰度发布_Stars.Sky的博客-CSDN博客
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/74535.html