Kubernetes Ingress 服务发布进阶
一、概述
在 Kubernetes 集群中,服务暴露是集群与外部通信的核心环节。Ingress 作为一种灵活且强大的服务暴露方案,通过定义基于域名、URL 路径的转发规则,实现了七层反向代理、负载均衡、SSL 终结等高级功能,成为生产环境中管理大量服务和域名的首选方案。
与其他服务暴露方式相比,Ingress 具有明显优势:
服务暴露方式 | 特点 | 适用场景 |
---|---|---|
NodePort | 暴露在节点端口(30000-32767),依赖 Kube-Proxy | 测试环境,少量服务 |
LoadBalancer | 依赖云厂商负载均衡器,可能产生额外费用 | 公有云环境,简单服务暴露 |
Ingress | 通过统一入口暴露多个 HTTP/HTTPS 服务,支持复杂规则 | 生产环境,微服务架构,多域名 / 路径管理 |
二、基本概念
1. Service 的核心作用
- 内部服务发现:跟踪 Pod 变化,更新 Endpoint,解决 Pod IP 动态变化问题。
- 外部访问入口:类似负载均衡器,提供集群内外对 Pod 的访问能力。
2. Ingress 核心组成
(1)Ingress 对象
- 是 Kubernetes 的 API 对象,通过 YAML 配置定义请求转发规则(域名、URL 路径与 Service 的映射关系)。
- 仅为配置模板,需依赖 Ingress Controller 实现具体功能。
(2)Ingress Controller
- 具体实现反向代理和负载均衡的组件,需单独部署(非 K8s 内置组件)。
- 常见实现:Ingress Nginx(官方维护)、Traefik、HAProxy、Istio 等。
- 工作机制:通过与 K8s APIServer 交互感知规则变化,动态生成反向代理配置(如 Nginx 配置)并生效。
三、Ingress 工作原理
ngress 的工作原理主要通过 Ingress Controller 与 Kubernetes 集群的交互及请求转发流程实现,具体如下:
- 规则监控与感知:Ingress Controller 持续与 Kubernetes APIServer 进行交互,动态感知集群中 Ingress 规则的变化。
- 配置生成与应用:当感知到 Ingress 规则变化后,Ingress Controller 会按照规则(即哪个域名对应哪个 Service 的映射关系)生成相应的反向代理配置,例如 Ingress Nginx 会动态生成 Nginx 配置。生成的配置会被写入到 Ingress Controller 所在 Pod 内的反向代理程序配置文件中(如 Nginx 的
/etc/nginx.conf
),并在需要时重新加载程序使新配置生效。 - 请求转发流程:外部客户端的请求首先到达 Ingress Controller,Ingress Controller 根据生成的配置规则,将请求转发到对应的 Service,最终由 Service 将请求路由到后端的 Pod 上。
四、安装 Ingress Nginx Controller
1. 环境准备:安装 Helm
Helm 是 Kubernetes 包管理工具,用于简化 Ingress Nginx 的部署。
# 下载 Helm 二进制包(注意:原文档中"he1m"为笔误,正确为"helm")
wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz
# 解压包
tar zxvf helm-v3.9.4-linux-amd64.tar.gz
# 将 helm 二进制文件移动到全局路径,确保可执行
mv linux-amd64/helm /usr/local/bin/
2. 添加 Helm 仓库并更新
# 添加 Ingress Nginx 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# 更新仓库索引
helm repo update
3. 下载并修改配置(values.yaml)
# 拉取 Ingress Nginx Chart 包
helm pull ingress-nginx/ingress-nginx --version 4.7.1
# 解压包
tar xvf ingress-nginx-4.7.1.tgz
# 编辑配置文件(核心配置如下)
vim ingress-nginx/values.yaml
核心配置修改说明:
# 1. 修改镜像仓库为国内地址(加速拉取)
controller:
image:
registry: registry.cn-hangzhou.aliyuncs.com # 国内仓库
image: tanzu/controller
tag: "v1.6.4"
# 注释掉 digest 信息(避免镜像拉取冲突)
# 2. 修改 opentelemetry 镜像地址(可选,按需启用)
opentelemetry:
enabled: false # 关闭追踪功能
image: registry.cn-hangzhou.aliyuncs.com/tanzu/opentelemetry:v20230107
# 3. 修改 admissionWebhook 镜像地址
patch:
image:
registry: registry.cn-hangzhou.aliyuncs.com
image: tanzu/kube-webhook-certgen
tag: v20220916-gd32f8c343
# 4. 启用主机网络(使 Pod 使用节点网络,便于外部访问)
hostNetwork: true
# 5. 配置 DNS 策略(适配 hostNetwork 模式)
dnsPolicy: ClusterFirstWithHostNet
# 6. 指定部署节点(通过节点标签筛选)
nodeSelector:
ingress: "true" # 仅部署到带有 ingress=true 标签的节点
kubernetes.io/os: linux
# 7. 部署模式改为 DaemonSet(每个节点部署一个副本,提高可用性)
kind: DaemonSet # 原文档"DeamonSet"为笔误,正确为"DaemonSet"
4. 部署 Ingress Nginx
# 1. 为目标节点打标签(与 values.yaml 中 nodeSelector 匹配)
kubectl label node k8s-node01 ingress=true
# 2. 创建命名空间
kubectl create ns ingress-nginx
# 3. 安装 Ingress Nginx(注意最后一个点表示当前目录的 Chart 包)
cd ingress-nginx
helm install ingress-nginx -n ingress-nginx .
# 4. 验证部署(查看 Pod 状态)
kubectl get po -n ingress-nginx -o wide
# 输出示例:ingress-nginx-controller-2t6qh 1/1 Running 0 17s 192.168.10.102 k8s-node01
五、Ingress Nginx 使用入门
1. 部署测试服务
# 1. 创建命名空间
kubectl create ns study-ingress
# 2. 部署 Nginx 应用
kubectl create deployment nginx --image=nginx:1.7.9 -n study-ingress
# 3. 暴露 Service
kubectl expose deployment nginx --port 80 -n study-ingress
2. 创建 Ingress 规则
创建 web-ingress.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress # Ingress 名称
namespace: study-ingress # 与服务同命名空间
spec:
ingressClassName: nginx # 指定使用的 Ingress Controller 类型
rules:
- host: nginx.test.com # 绑定域名
http:
paths:
- backend:
service:
name: nginx # 目标 Service 名称
port:
number: 80 # Service 端口
path: / # 匹配路径
pathType: ImplementationSpecific # 路径匹配类型
路径类型说明:
ImplementationSpecific
:由 IngressClass 决定匹配规则(可视为 Prefix 或 Exact)。Exact
:精确匹配 URL 路径(区分大小写)。Prefix
:前缀匹配(区分大小写,按/
分割的元素匹配,如/foo/bar
匹配/foo/bar/baz
但不匹配/foo/barbaz
)。
3. 应用并测试
# 创建 Ingress 规则
kubectl create -f web-ingress.yaml
# 测试访问(需将 nginx.test.com 解析到 Ingress Controller 所在节点 IP)
# 在客户端 hosts 文件添加:<节点 IP> nginx.test.com
# 访问 http://nginx.test.com,应看到 Nginx 欢迎页
六、高级功能实现
1. 域名重定向(Redirect)
场景:旧域名平滑过渡到新域名,将旧域名请求重定向到新域名。
创建 redirect.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-redirect
namespace: study-ingress
annotations:
# 核心注解:指定重定向目标(新域名)
nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
spec:
ingressClassName: nginx
rules:
- host: nginx.redirect.com # 旧域名
http:
paths:
- backend:
service:
name: nginx # 临时绑定的服务(可不实际使用)
port:
number: 80
path: /
pathType: ImplementationSpecific
应用并测试:
kubectl create -f redirect.yaml
# 客户端 hosts 添加:<节点 IP> nginx.redirect.com
# 访问 http://nginx.redirect.com 应跳转到 https://www.baidu.com
2. 前后端分离(Rewrite)
场景:前端访问根路径,后端接口路径 /api-a
转发到后端服务,并去除路径前缀。
创建 rewrite.yaml
(原文档 “rewirte” 为笔误,正确为 “rewrite”):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend-api
namespace: study-ingress
annotations:
# 核心注解:重写路径(将匹配的第二个捕获组作为新路径)
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: nginx.test.com
http:
paths:
- backend:
service:
name: backend-api # 后端服务名称
port:
number: 80
# 路径规则:匹配 /api-a 开头的路径,捕获后续内容
path: /api-a(/|$)(.*) # 第一个组匹配 / 或结尾,第二个组匹配后续路径
pathType: ImplementationSpecific
部署后端服务并测试:
# 部署后端服务
kubectl create deployment backend-api --image=nginx:1.7.9 -n study-ingress
kubectl expose deployment backend-api --port 80 -n study-ingress
# 应用 Ingress 规则
kubectl create -f rewrite.yaml
# 测试:访问 http://nginx.test.com/api-a 或 http://nginx.test.com/api-a/index.html
# 应看到 Nginx 欢迎页(路径被重写为 /)
3. SSL 配置(HTTPS)
场景:为服务配置 HTTPS 加密访问。
(1)生成测试证书(生产环境需使用权威证书)
# 生成自签名证书(有效期 365 天,CN 为目标域名)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=nginx.test.com"
(2)创建证书 Secret
kubectl create secret tls ca-secret \
--cert=tls.crt \ # 证书文件
--key=tls.key \ # 私钥文件
-n study-ingress
(3)创建 SSL 配置的 Ingress
创建 ingress-ssl.yaml
(原文档 “ingress-ss1.yaml” 为笔误):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress-ssl
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx.test.com # 与证书 CN 匹配
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
tls: # SSL 配置
- hosts:
- nginx.test.com # 证书生效的域名
secretName: ca-secret # 引用证书 Secret
应用并测试:
kubectl create -f ingress-ssl.yaml
# 客户端访问 https://nginx.test.com(忽略证书警告),应看到 Nginx 欢迎页
4. 基本认证(Basic Auth)
场景:限制服务访问,需输入用户名密码验证。
(1)安装工具并创建用户密码
# 安装 httpd 工具包(含 htpasswd)
yum -y install httpd
# 创建密码文件(用户名 zhangsan,会生成 auth 文件)
htpasswd -c auth zhangsan
# 输入密码并确认
(2)创建认证 Secret
kubectl create secret generic basic-auth \
--from-file=auth \ # 引用密码文件
-n study-ingress
(3)创建带认证的 Ingress
创建 ingress-with-auth.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-auth
namespace: study-ingress
annotations:
nginx.ingress.kubernetes.io/auth-realm: "Please Input Your Username and Password" # 认证提示
nginx.ingress.kubernetes.io/auth-secret: basic-auth # 引用认证 Secret
nginx.ingress.kubernetes.io/auth-type: basic # 认证类型
spec:
ingressClassName: nginx
rules:
- host: auth.test.com # 认证域名
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
应用并测试:
kubectl create -f ingress-with-auth.yaml
# 客户端 hosts 添加:<节点 IP> auth.test.com
# 访问 http://auth.test.com,应弹出用户名密码输入框,输入 zhangsan 和密码后可访问
5. 灰度发布 / 金丝雀发布
场景:将部分流量路由到新版本服务,验证稳定后逐步扩大流量比例。
(1)部署生产环境(V1 版本)
# 创建命名空间
kubectl create ns production
# 部署 V1 版本应用
kubectl create deployment canary-v1 \
--image=registry.cn-beijing.aliyuncs.com/dotbalo/canary:v1 -n production
# 暴露服务
kubectl expose deployment canary-v1 --port 8080 -n production
# 创建 V1 版本 Ingress
cat > v1-ingress.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-v1
namespace: production
spec:
ingressClassName: nginx
rules:
- host: canary.com # 统一访问域名
http:
paths:
- backend:
service:
name: canary-v1
port:
number: 8080
path: /
pathType: ImplementationSpecific
EOF
kubectl create -f v1-ingress.yaml
(2)部署灰度环境(V2 版本)
# 创建命名空间
kubectl create ns canary
# 部署 V2 版本应用
kubectl create deployment canary-v2 \
--image=registry.cn-beijing.aliyuncs.com/dotbalo/canary:v2 -n canary
# 暴露服务
kubectl expose deployment canary-v2 --port 8080 -n canary
(3)配置灰度流量规则
创建 canary-v2.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-v2
namespace: canary
annotations:
nginx.ingress.kubernetes.io/canary: "true" # 启用金丝雀模式
nginx.ingress.kubernetes.io/canary-weight: "10" # 灰度流量比例(10% 到 V2)
spec:
ingressClassName: nginx
rules:
- host: canary.com # 与 V1 版本相同的访问域名
http:
paths:
- backend:
service:
name: canary-v2 # 灰度服务
port:
number: 8080
path: /
pathType: ImplementationSpecific
应用并测试:
kubectl create -f canary-v2.yaml
# 测试:多次访问 canary.com,观察返回结果
for i in $(seq 10); do curl -s canary.com; done
# 预期:约 10% 返回 "<h1>Canary v2</h1>",90% 返回 "<h1>Canary v1</h1>"
# 调整权重:编辑 Ingress 规则,将 canary-weight 改为 50,重复测试
kubectl edit ingress canary-v2 -n canary
# 预期:约 50% 流量到 V2 版本
六、总结
Ingress 作为 Kubernetes 服务发布的核心方案,通过 Ingress Controller 实现了灵活的流量管理。本文涵盖了 Ingress 基本概念、工作原理、安装部署及高级功能(重定向、HTTPS、认证、灰度发布)的实战配置。掌握这些内容可帮助在生产环境中高效、安全地管理服务发布,适应微服务架构的复杂需求。