当前位置: 首页 > news >正文

编排之神-Kubernetes微服务专题--ingress-nginx及金丝雀Canary的演练

7.5 Ingress-nginx

官网:

https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters

7.5.1 ingress-nginx功能

image-20250814103723904
  • 一种全局的、为了代理不同后端 Service 而设置的负载均衡服务,支持7层
  • Ingress由两部分组成:Ingress controller和Ingress服务
  • Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。
  • 业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。
7.5.2 部署ingress
7.5.2.1 下载部署文件
# 建议使用资源包里面的内容# 以下为网络上直接下载的
# [root@k8s-master ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.6.2/deploy/static/provider/baremetal/deploy.yaml

上传ingress所需镜像到harbor

# 上传资源包里面的内容,并在harbor仓库建立新项目
[root@k8s-master mnt]# unzip ingress-1.13.1.zip[root@k8s-master mnt]# docker load -i ingress-nginx-1.13.1.tar
Loaded image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.1
Loaded image: registry.k8s.io/ingress-nginx/controller:v1.13.1[root@k8s-master mnt]# docker tag registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.1 reg.dhj.org/ingress-nginx/kube-webhook-certgen:v1.6.1
[root@k8s-master mnt]# docker tag registry.k8s.io/ingress-nginx/controller:v1.13.1 reg.dhj.org/ingress-nginx/controller:v1.13.1
[root@k8s-master mnt]# docker push reg.dhj.org/ingress-nginx/kube-webhook-certgen:v1.6.1[root@k8s-master mnt]# docker push reg.dhj.org/ingress-nginx/controller:v1.13.1

image-20250814104611468

7.5.2.2 安装ingress
[root@k8s-master ~]# vim deploy.yaml
444         image: ingress-nginx/controller:v1.13.1
547         image: ingress-nginx/kube-webhook-certgen:v1.6.1
603         image: ingress-nginx/kube-webhook-certgen:v1.6.1[root@k8s-master mnt]# kubectl apply -f deploy.yaml[root@k8s-master mnt]# kubectl -n ingress-nginx get pods
NAME                                        READY   STATUS              RESTARTS   AGE
ingress-nginx-admission-create-2k8vn        0/1     ContainerCreating   0          3s			# 这俩是init容器,后续就没了
ingress-nginx-admission-patch-9gqlt         0/1     ContainerCreating   0          3s			# 这俩是init容器,后续就没了
ingress-nginx-controller-7bf698f798-9tqv7   0/1     ContainerCreating   0          3s[root@k8s-master mnt]# kubectl -n ingress-nginx get pods
NAME                                        READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-7bf698f798-9tqv7   0/1     Running   0          8s[root@k8s-master mnt]# kubectl -n ingress-nginx get svc
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.98.27.12     <none>        80:32244/TCP,443:34533/TCP   3m23s
ingress-nginx-controller-admission   ClusterIP   10.96.154.255   <none>        443/TCP                      3m23s# 修改微服务为loadbalancer
[root@k8s-master ~]# kubectl -n ingress-nginx edit svc ingress-nginx-controller
49   type: LoadBalancer[root@k8s-master mnt]# kubectl -n ingress-nginx get services
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.98.27.12     172.25.254.50   80:32244/TCP,443:34533/TCP   5m2s
ingress-nginx-controller-admission   ClusterIP      10.96.154.255   <none>          443/TCP                      5m2s
image-20250814110322566 image-20250814110357944

[!NOTE]

在ingress-nginx-controller中看到的对外IP就是ingress最终对外开放的ip

7.5.2.3 测试ingress
# 生成yaml文件
[root@k8s-master ~]# kubectl create ingress webcluster --rule '*/=dhj-svc:80' --dry-run=client -o yaml > dhj-ingress.yml# 定义路由规则:'*/=dhj-svc:80'
# *:匹配任意主机域名(如 example.com、test.com 等)。
# /:匹配所有路径(根路径及子路径)。
# dhj-svc:80:将流量路由到名为 dhj-svc 的 Kubernetes Service 的 80 端口。[root@k8s-master ~]# vim dhj-ingress.yml
aapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: test-ingress
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: dhj-svcport:number: 80path: /pathType: Prefix	# Exact(精确匹配),ImplementationSpecific(特定实现),Prefix(前缀匹配),Regular expression(正则表达式匹配)# 建立ingress控制器
[root@k8s-master ~]# kubectl apply -f dhj-ingress.yml
ingress.networking.k8s.io/webserver created[root@k8s-master mnt]# kubectl get ingress
NAME         CLASS   HOSTS   ADDRESS         PORTS   AGE
webcluster   nginx   *       172.25.254.20   80      4m57s

[!NOTE]

ingress必须和输出的service资源处于同一namespace

7.5.3 ingress的高级用法
7.5.3.1 基于路径的访问
1.建立用于测试的控制器myapp
[root@k8s-master app]# kubectl create deployment myappv1 --image myapp:v1 --dry-run=client -o yaml > myappv1.yaml[root@k8s-master app]# kubectl create deployment myappv2 --image myapp:v2 --dry-run=client -o yaml > myappv2.yaml[root@k8s-master app]# kubectl expose deployment myappv1 --port 80 --target-port 80 --dry-run=client -o yaml >> myappv1.yaml[root@k8s-master app]# kubectl expose deployment myappv2 --port 80 --target-port 80 --dry-run=client -o yaml >> myappv1.yaml[root@k8s-master app]# vim myappv1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: myappv1name: myappv1
spec:replicas: 1selector:matchLabels:app: myappv1template:metadata:labels:app: myappv1spec:containers:- image: myapp:v1name: myappv1
---
apiVersion: v1
kind: Service
metadata:labels:app: myappv1name: myappv1
spec:ports:- name: myappv1port: 80protocol: TCPtargetPort: 80selector:app: myappv1type: ClusterIP[root@k8s-master app]# vim myappv2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: myappv2name: myappv2
spec:replicas: 1selector:matchLabels:app: myappv2template:metadata:labels:app: myappv2spec:containers:- image: myapp:v2name: myappv2
---
apiVersion: v1
kind: Service
metadata:labels:app: myappv2name: myappv2
spec:ports:- name: myappv2port: 80protocol: TCPtargetPort: 80selector:app: myappv2type: ClusterIP[root@k8s-master mnt]# kubectl get services
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)   AGE
myappv1       ClusterIP      10.102.34.225   <none>          80/TCP    6s
myappv2       ClusterIP      10.110.94.93    <none>          80/TCP    3s
image-20250814113922816
2.建立ingress的yaml
[root@k8s-master app]# vim ingress1.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/rewrite-target: /		# 访问路径后加任何内容都被定向到/name: ingress1
spec:ingressClassName: nginxrules:- host: www.dhj.orghttp:paths:- backend:service:name: myappv1port:number: 80path: /v1pathType: Prefix- backend:service:name: myappv2port:number: 80path: /v2pathType: Prefix[root@k8s-master mnt]# kubectl describe ingress ingress1www.dhj.org/v1   myappv1:80 (10.244.2.6:80)/v2   myappv2:80 (10.244.1.6:80)
Annotations:   nginx.ingress.kubernetes.io/rewrite-target: /# 这个是之前实验使用metllab插件搭建的类似于给微服务做dhcp转发ip的工具
[root@k8s-master mnt]# kubectl -n ingress-nginx get svc
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.98.27.12     172.25.254.50   80:32244/TCP,443:34533/TCP   3h26m
ingress-nginx-controller-admission   ClusterIP      10.96.154.255   <none>          443/TCP                      3h26m# 测试:
[root@reg ~]# echo 172.25.254.50 www.dhj.org >> /etc/hosts[root@k8s-master mnt]# echo 172.25.254.50 www.dhj.org >> /etc/hosts
[root@k8s-master mnt]# curl  www.dhj.org/v1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master mnt]# curl  www.dhj.org/v2
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a># nginx.ingress.kubernetes.io/rewrite-target: / 的功能实现
[root@reg ~]# curl  www.dhj.org/v2/aaaa
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
7.5.3.2 基于域名的访问
# 在测试主机中设定解析
[root@reg ~]# vim /etc/hosts
172.25.254.50   www.dhj.org  myappv1.dhj.org  myappv2.org[root@k8s-master mnt]# cp ingress1.yml ingress2.yml
[root@k8s-master mnt]# vim ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/rewrite-target: /name: ingress2
spec:ingressClassName: nginxrules:- host: myappv1.dhj.orghttp:paths:- backend:service:name: myappv1port:number: 80path: /pathType: Prefix- host: myappv2.dhj.orghttp:paths:- backend:service:name: myappv2port:number: 80path: /pathType: Prefix[root@k8s-master mnt]# kubectl apply -f ingress2.yml[root@k8s-master mnt]# kubectl describe ingress ingress2[root@k8s-master mnt]# kubectl -n ingress-nginx get svc
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.98.27.12     172.25.254.50   80:32244/TCP,443:34533/TCP   3h35m
ingress-nginx-controller-admission   ClusterIP      10.96.154.255   <none>          443/TCP                      3h35m[root@k8s-master mnt]# curl myappv1.dhj.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master mnt]# curl myappv2.dhj.org
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
7.5.3.3 建立tls加密(实现https)
# 建立证书
[root@k8s-master app]# openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -subj "/CN=nginxsvc/O=nginxsvc" -out tls.crt
# 建立加密资源类型secret
[root@k8s-master app]# kubectl create secret tls  web-tls-secret --key tls.key --cert tls.crt
secret/web-tls-secret created
[root@k8s-master app]# kubectl get secrets
NAME             TYPE                DATA   AGE
web-tls-secret   kubernetes.io/tls   2      6s

[!NOTE]

secret通常在kubernetes中存放敏感数据,他并不是一种加密方式,在后面课程中会有专门讲解

# 建立ingress3基于tls认证的yml文件
[root@k8s-master app]# vim ingress3.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/rewrite-target: /name: ingress3
spec:tls:- hosts:- myapp-tls.dhj.orgsecretName: web-tls-secretingressClassName: nginxrules:- host: myapp-tls.dhj.orghttp:paths:- backend:service:name: myappv1port:number: 80path: /pathType: Prefix[root@k8s-master mnt]# vim /etc/hosts
172.25.254.50  myapp-tls.dhj.org# 测试
[root@k8s-master mnt]# curl -k https://myapp-tls.dhj.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
7.5.3.4 建立auth认证
# 建立认证文件
[root@k8s-master app]# dnf install httpd-tools -y
[root@k8s-master app]# htpasswd -cm auth admin
New password:admin
Re-type new password:admin[root@k8s-master mnt]# cat auth
admin:$apr1$Ny8jCT8n$Hiuu0FRvZBN60p1tA3g0Y.# 建立认证类型资源(创建一个名为auth-web的通用型Secret资源)
# generic:# 创建通用型 Secret
# --from-file auth:# 从本地文件系统加载数据到 Secret		# auth:当前目录下的文件名(或目录路径)[root@k8s-master mnt]# kubectl create secret generic auth-web --from-file auth
[root@k8s-master mnt]# kubectl describe secrets auth-web
# 建立ingress4基于用户认证的yaml文件
[root@k8s-master app]# vim ingress4.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/auth-type: basicnginx.ingress.kubernetes.io/auth-secret: auth-webnginx.ingress.kubernetes.io/auth-realm: "Please input username and password"name: ingress4
spec:tls:- hosts:- myapp-tls.dhj.orgsecretName: web-tls-secretingressClassName: nginxrules:- host: myapp-tls.dhj.orghttp:paths:- backend:service:name: myappv1port:number: 80path: /pathType: Prefix# 建立ingress4
[root@k8s-master app]# kubectl apply -f ingress4.yml[root@k8s-master app]# kubectl describe ingress ingress4
TLS:web-tls-secret terminates myapp-tls.dhj.org
Rules:Host               Path  Backendsmyapp-tls.dhj.org/   myappv1:80 (10.244.2.6:80)
Annotations:         nginx.ingress.kubernetes.io/auth-realm: Please input username and passwordnginx.ingress.kubernetes.io/auth-secret: auth-webnginx.ingress.kubernetes.io/auth-type: basic# 测试:
[root@k8s-master mnt]# curl -k https://myapp-tls.dhj.org
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@k8s-master mnt]# curl -k https://myapp-tls.dhj.org -uadmin:admin
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
7.5.3.5 rewrite重定向
# 将默认访问路径重定向到/hostname.html,并启用基础认证
[root@k8s-master app]# vim ingress5.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/app-root: /hostname.html	# 根路径重定向到 hostname.htmlnginx.ingress.kubernetes.io/auth-type: basic			# 启用基础认证nginx.ingress.kubernetes.io/auth-secret: auth-web		# 认证使用的 Secretnginx.ingress.kubernetes.io/auth-realm: "Please input username and password"	# 认证提示name: ingress5
spec:tls:		# TLS配置- hosts:- myapp-tls.dhj.orgsecretName: web-tls-secret		# TLS证书SecretingressClassName: nginxrules:- host: myapp-tls.dhj.orghttp:paths:- backend:service:name: myappv1			# 后端服务port:number: 80path: /pathType: Prefix[root@k8s-master app]# kubectl apply -f ingress5.yml[root@k8s-master app]# kubectl describe ingress ingress5# 测试:
[root@reg ~]# curl -Lk https://myapp-tls.dhj.org -uadmin:admin[root@reg ~]# curl -Lk https://myapp-tls.dhj.org/admin/hostname.html -uadmin:admin
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.10.7.2</center>
</body>
</html>
image-20250814160840511
[root@k8s-master app]# vim ingress5.yml
# 解决重定向路径问题
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/rewrite-target: /$2			# 重写路径:捕获组 $2nginx.ingress.kubernetes.io/use-regex: "true"			# 启用正则匹配# 保留基础认证配置nginx.ingress.kubernetes.io/auth-type: basicnginx.ingress.kubernetes.io/auth-secret: auth-webnginx.ingress.kubernetes.io/auth-realm: "Please input username and password"name: ingress6
spec:tls:- hosts:- myapp-tls.dhj.orgsecretName: web-tls-secretingressClassName: nginxrules:- host: myapp-tls.dhj.orghttp:paths:- backend:service:name: myappv1port:number: 80path: /				# 规则1:根路径pathType: Prefix- backend:service:name: myappv1port:number: 80path: /admin(/|$)(.*)					# 规则2:正则匹配/admin/或/admin开头的路径pathType: ImplementationSpecific# 测试
[root@reg ~]# curl -Lk https://myapp-tls.dhj.org/admin/hostname.html -uadmin:admin
myappv1-5c47495d84-tj4hl

7.6 Canary金丝雀发布

Canary Deployments - Ingress-Nginx Controller

7.6.1 什么是金丝雀发布

金丝雀发布(Canary Release)也称为灰度发布,是一种软件发布策略。

主要目的是在将新版本的软件全面推广到生产环境之前,先在一小部分用户或服务器上进行测试和验证,以降低因新版本引入重大问题而对整个系统造成的影响。

是一种Pod的发布方式。金丝雀发布采取先添加、再删除的方式,保证Pod的总量不低于期望值。并且在更新部分Pod后,暂停更新,当确认新Pod版本运行正常后再进行其他版本的Pod的更新。

image-20250814162030297
7.6.2 Canary发布方式

其中header和weight中的最多

7.6.2.1 基于header(http包头)灰度

  • 通过Annotaion扩展
  • 创建灰度ingress,配置灰度头部key以及value
  • 灰度流量验证完毕后,切换正式ingress到新版本
  • 之前我们在做升级时可以通过控制器做滚动更新,默认25%利用header可以使升级更为平滑,通过key 和vule 测试新的业务体系是否有问题。
1.示例
# 做此实验前将之前的实验ingress文件删除,以防扰乱实验效果
# 建立版本1的ingress
[root@k8s-master app]# vim canary-old.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:name: myapp-v1-ingress
spec:ingressClassName: nginxrules:- host: myapp.dhj.orghttp:paths:- backend:service:name: myappv1port:number: 80path: /pathType: Prefix[root@k8s-master app]# kubectl apply -f canary-old.yml[root@k8s-master app]# kubectl describe ingress myapp-v1-ingressmyapp.dhj.org/   myappv1:80 (10.244.2.6:80)				# v1# 建立基于header的ingress
[root@k8s-master app]# vim canary-new.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-by-header: "version"nginx.ingress.kubernetes.io/canary-by-header-value: "2"name: myapp-v2-ingress
spec:ingressClassName: nginxrules:- host: myapp.dhj.orghttp:paths:- backend:service:name: myappv2port:number: 80path: /pathType: Prefix[root@k8s-master app]# kubectl apply -f canary-new.yml[root@k8s-master mnt]# kubectl describe ingress myapp-v2-ingressmyapp.dhj.org/   myappv2:80 (10.244.1.6:80)				# v2
Annotations:     nginx.ingress.kubernetes.io/canary: truenginx.ingress.kubernetes.io/canary-by-header: versionnginx.ingress.kubernetes.io/canary-by-header-value: 2[root@k8s-master mnt]# vim /etc/hosts
172.25.254.50   myapp.dhj.org# 测试:
[root@reg ~]# curl  myapp.dhj.org
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@reg ~]# curl -H "version: 2" myapp.dhj.org
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
7.6.2.2 基于权重的灰度发布

  • 通过Annotaion拓展
  • 创建灰度ingress,配置灰度权重以及总权重
  • 灰度流量验证完毕后,切换正式ingress到新版本
1.示例
# 基于权重的灰度发布
[root@k8s-master app]# vim canary-new.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-weight: "10"		# 更改权重值nginx.ingress.kubernetes.io/canary-weight-total: "100"name: myapp-v2-ingress
spec:ingressClassName: nginxrules:- host: myapp.dhj.orghttp:paths:- backend:service:name: myappv2port:number: 80path: /pathType: Prefix[root@k8s-master app]# kubectl apply -f canary-new.yml# 测试:
[root@reg ~]# vim check_ingress.sh
#!/bin/bash
v1=0
v2=0for (( i=0; i<100; i++))
doresponse=`curl -s myapp.dhj.org | grep -c v1`v1=`expr $v1 + $response`v2=`expr $v2 + 1 - $response`done
echo "v1:$v1, v2:$v2"[root@k8s-master mnt]# sh check_ingress.sh
v1:88, v2:12# 更改完毕权重后继续测试可观察变化(将权重调为50来看看测试效果)
[root@k8s-master mnt]# sh check_ingress.sh
v1:55, v2:45
image-20250814171142040
http://www.lryc.cn/news/620440.html

相关文章:

  • [Oracle数据库] ORACLE基本DML操作
  • 图论Day2学习心得
  • Pytest本地插件定制及发布指南
  • 代码随想录Day50:图论(图论理论、深度搜索理论、所有可达路径、广度搜索理论)
  • python sqlite3模块
  • 高效解决 pip install 报错 SSLError: EOF occurred in violation of protocol
  • 《贵州棒球百科》体育赛事排名·棒球1号位
  • 视频号主页的企业信息如何设置?
  • 消费级显卡分布式智能体协同:构建高性价比医疗AI互动智能体的理论与实践路径
  • 从理论到落地:分布式事务全解析(原理 + 方案 + 避坑指南)
  • 云原生存储架构设计与性能优化
  • 【java实现一个接口多个实现类通用策略模式】
  • GitHub 仓库代码上传指南
  • Python包性能优化与并发编程:构建高性能应用的核心技术(续)
  • OpenBMC中C++策略模式架构、原理与应用
  • Qt基本控件
  • Elasticsearch:如何使用 Qwen3 来做向量搜索
  • 设计模式-策略模式 Java
  • 设计模式基础概念(行为模式):策略模式
  • Swift 实战:用链表和哈希表写出高性能的贪吃蛇引擎(LeetCode 353)
  • LeetCode 刷题【41. 缺失的第一个正数】
  • linux 主机驱动(SPI)与外设驱动分离的设计思想
  • tomcat 定时重启
  • LeetCode 1780:判断一个数字是否可以表示成3的幂的和-进制转换解法
  • 【Java虚拟机】JVM相关面试题
  • 网页加载缓慢系统排查与优化指南
  • pnpm常用命令;为什么使用pnpm?
  • 【STM32入门教程】stm32简介
  • Day56--图论--108. 冗余的边(卡码网),109. 冗余的边II(卡码网)
  • QLab Pro for Mac —— 专业现场音频与多媒体控制软件