k8s(八)Ingress详解

文章目录

  • 前言
  • 一、k8s中的Ingress
    • [1.1 Ingress服务](#1.1 Ingress服务)
      • [1.1.1 为什么需要 Ingress?------ 先理解 k8s 服务暴露的痛点](#1.1.1 为什么需要 Ingress?—— 先理解 k8s 服务暴露的痛点)
      • [1.1.2 Ingress 的核心组成:2 个关键部分](#1.1.2 Ingress 的核心组成:2 个关键部分)
        • [1.1.2.1 Ingress 资源:定义路由规则](#1.1.2.1 Ingress 资源:定义路由规则)
          • [1.1.2.1.1 Ingress 工作原理](#1.1.2.1.1 Ingress 工作原理)
        • [1.1.2.2 Ingress Controller:执行路由规则](#1.1.2.2 Ingress Controller:执行路由规则)
    • [1.2 Ingress 的核心功能](#1.2 Ingress 的核心功能)
      • [1.2.1 关键区别:Ingress vs Service](#1.2.1 关键区别:Ingress vs Service)
    • [1.3 Ingress 的工作流程](#1.3 Ingress 的工作流程)
    • [1.4 部署ingress-nginx-controller(示例)](#1.4 部署ingress-nginx-controller(示例))
        • [1.4.1 准备与获取清单](#1.4.1 准备与获取清单)
        • [1.4.2 修改ClusterRole资源配置](#1.4.2 修改ClusterRole资源配置)
      • [1.5 Ingress暴露服务的三种方式(重点)](#1.5 Ingress暴露服务的三种方式(重点))
        • [1.5.1 方式一:Deployment + Service(type=LoadBalancer)](#1.5.1 方式一:Deployment + Service(type=LoadBalancer))
        • [1.5.2 方式二:DaemonSet + HostNetwork + nodeSelector(示例详解)](#1.5.2 方式二:DaemonSet + HostNetwork + nodeSelector(示例详解))
          • [1.5.2.1 给node打标签,仅在`node02`运行:](#1.5.2.1 给node打标签,仅在node02运行:)
          • [1.5.2.2 将**Deployment**改为**DaemonSet**,启用HostNetwork并指定node:](#1.5.2.2 将Deployment改为DaemonSet,启用HostNetwork并指定node:)
          • [1.5.2.3 在所有node上传镜像并加载:](#1.5.2.3 在所有node上传镜像并加载:)
          • [1.5.2.4 启动Controller,验证监听端口(在node02):](#1.5.2.4 启动Controller,验证监听端口(在node02):)
          • [1.5.2.5 创建ingress规则](#1.5.2.5 创建ingress规则)
          • [1.5.2.6 创建Ingress(两种API示例):](#1.5.2.6 创建Ingress(两种API示例):)
          • [1.5.2.7 测试:](#1.5.2.7 测试:)
        • [1.5.3 方式三:Deployment + Service(type=NodePort)](#1.5.3 方式三:Deployment + Service(type=NodePort))
          • [1.5.3.1 下载nginx-ingress-controller和ingress-nginx暴露端口配置文件](#1.5.3.1 下载nginx-ingress-controller和ingress-nginx暴露端口配置文件)
          • [1.5.3.2 示例:HTTP代理访问](#1.5.3.2 示例:HTTP代理访问)
          • [1.5.3.3 Ingress HTTP代理访问虚拟主机](#1.5.3.3 Ingress HTTP代理访问虚拟主机)
          • [1.5.3.4 示例:HTTPS代理访问](#1.5.3.4 示例:HTTPS代理访问)
          • [1.5.3.5 示例:BasicAuth认证](#1.5.3.5 示例:BasicAuth认证)
          • [1.5.3.6 示例:重写(Rewrite)](#1.5.3.6 示例:重写(Rewrite))
      • [1.6 常见检查与排错要点](#1.6 常见检查与排错要点)
      • [1.7 总结](#1.7 总结)
  • 结尾

前言

在 Kubernetes(k8s)集群的日常运维与服务管理中,"如何安全、高效地将内部服务暴露给外部访问" 是核心需求之一。随着集群内微服务数量增多,传统的 NodePort 端口管理混乱、LoadBalancer 成本高昂等问题逐渐凸显,而 Ingress 作为七层反向代理解决方案,凭借 "统一入口、动态路由、灵活扩展" 的特性,成为解决这一痛点的关键技术。

本文将从 Ingress 的核心概念入手,系统梳理其与 Service 的区别、核心组成与工作原理,再通过详细的部署示例(包括 HostNetwork、NodePort、LoadBalancer 三种暴露方式),带您掌握 Ingress 的实际应用,并提供常见排错思路,为集群外部流量管理提供完整的技术参考。

一、k8s中的Ingress

在 Kubernetes 中:

  • Pod IPService 的 ClusterIP 仅在集群内部可见。
  • 为了让外部应用访问集群内服务,K8s 提供了多种方案:

1)NodePort

  • 将 Service 暴露在节点网络 上(由 kube-proxy 负责连接 service / pod / 节点网络)。
  • 适合测试;当服务数量多,端口管理困难 (端口范围固定为 30000-32767,且每个端口仅服务一种服务)。

2)LoadBalancer

  • 需要云厂商支持,K8s 调用 CloudProvider 在公有云创建 LB,并将后端指向 Pod IP;
  • 通常需要额外费用 ;更适合公有云

3)externalIPs

  • 为 service 分配外部 IP;当该 IP 路由到集群节点,流量将被路由到 Service 的 Endpoints。

4)Ingress(七层反向代理)

  • 仅用一个或少量的公网 IP/LB ,即可同时将多个 HTTP/HTTPS 服务暴露到外网;
  • 可理解为"service 的 service ":基于域名/URL 路径将请求转发到一个或多个 service。

1.1 Ingress服务

在 Kubernetes(k8s)生态中,Ingress 是实现集群外部流量(如来自互联网的 HTTP/HTTPS 请求)路由到集群内部服务(Service)的核心资源,本质是一套"流量入口规则定义"和"统一入口管理"的解决方案。

1.1.1 为什么需要 Ingress?------ 先理解 k8s 服务暴露的痛点

在 Ingress 出现前,k8s 暴露服务到集群外主要依赖 NodePortLoadBalancer,但这两种方式存在明显局限:

  • NodePort:为每个服务分配集群节点的随机端口(30000-32767),端口管理混乱,且无法直接处理域名、HTTPS 等场景;
  • LoadBalancer:依赖云厂商的负载均衡器(如 AWS ELB、阿里云 SLB),每个服务需单独创建一个 LoadBalancer,成本高、资源浪费严重。

Ingress 正是为解决这些痛点而生:它通过一个统一的入口(Ingress Controller) ,集中管理所有外部流量的路由规则,支持域名、路径、HTTPS、负载均衡等高级功能,实现"一个入口管所有服务"。

1.1.2 Ingress 的核心组成:2 个关键部分

Ingress 并非单一组件,而是由"规则定义 "和"规则执行"两部分协同工作:

组成部分 作用 类比场景
Ingress 资源 是 k8s 中的一种 CRD(自定义资源),用于声明式定义路由规则(如"xxx.com/abc 路由到服务 A") 相当于"交通指挥手册"
Ingress Controller 是实际"执行规则"的组件(通常是一个运行在集群内的 Pod),监听 Ingress 资源变化并转发流量 相当于"交通指挥员"
1.1.2.1 Ingress 资源:定义路由规则

Ingress 资源通过 YAML 文件声明路由逻辑,核心配置包括:

  • 域名(host) :指定外部请求的域名(如 example.com);
  • 路径(paths) :指定域名下的具体路径(如 /api/web);
  • 后端服务(backend):对应路径要转发到的集群内 Service 及端口;
  • TLS 配置:用于 HTTPS 加密(指定证书 Secret)。
1.1.2.1.1 Ingress 工作原理
  1. Ingress Controller 与 APIServer 交互,动态的去感知 Ingress 规则变化;
  2. 读取规则并按自定义模板生成 Nginx 配置
  3. 再写到nginx-ingress-controller的pod里,这个ingress-controller的pod里运行着一个Nginx服务,控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中
  4. 执行 reload 使配置生效,实现按域名分流与动态更新。
1.1.2.2 Ingress Controller:执行路由规则

Ingress 资源本身只是"规则文本",必须通过 Ingress Controller 才能生效。它的核心工作流程是:

  1. 监听:通过 k8s API 监听 Ingress 资源、Service、Endpoint 的变化;
  2. 生成配置 :根据 Ingress 规则,动态生成反向代理配置(如 Nginx 的 nginx.conf);
  3. 转发流量:对外暴露一个固定入口(通常是 NodePort 或 LoadBalancer),接收外部流量并按规则转发到内部 Service。

主流 Ingress Controller 实现

  • Nginx Ingress Controller:基于 Nginx 反向代理,最常用、生态最成熟;
  • Traefik:云原生设计,支持自动发现、动态配置,适合微服务场景;
  • HAProxy Ingress:基于 HAProxy,性能优异,适合高并发场景;
  • Istio Ingress Gateway:属于服务网格(Istio)的一部分,支持更复杂的流量治理(如灰度发布、流量镜像)。

1.2 Ingress 的核心功能

Ingress 不仅解决"统一入口"问题,还支持多种高级流量管理能力:

  1. 域名路由 :将不同域名的请求转发到不同服务(如 api.example.com 到 API 服务,web.example.com 到 Web 服务);
  2. 路径路由 :同一域名下,按路径转发到不同服务(如 example.com/api 到 API 服务,example.com/web 到 Web 服务);
  3. HTTPS 终结:在 Ingress Controller 层统一处理 HTTPS 加密/解密(证书存储在 k8s Secret 中),内部服务无需关心加密;
  4. 负载均衡:自动为后端多个 Pod 分配流量(依赖 Service 的 Endpoint 列表);
  5. 路径重写 :将外部路径(如 /v1/api)重写为内部服务期望的路径(如 /api);
  6. 访问控制 :支持基于 IP、HTTP 头的黑白名单(如 Nginx Ingress 的 nginx.ingress.kubernetes.io/whitelist-source-range 注解);
  7. 限流与缓存:部分控制器(如 Nginx Ingress)支持对请求限流、静态资源缓存,减轻后端服务压力。

1.2.1 关键区别:Ingress vs Service

很多初学者会混淆 Ingress 和 Service,两者的核心区别如下:

维度 Ingress Service
作用范围 集群外部流量的"入口路由管理" 集群内部/外部流量的"服务发现与负载均衡"
流量类型 仅支持 HTTP/HTTPS(部分支持 TCP/UDP) 支持 TCP/UDP/HTTP 等所有协议
依赖关系 依赖 Service(路由最终指向 Service) 直接关联 Pod(通过标签选择器)
核心能力 域名、路径路由、HTTPS 等高级规则 固定访问地址(ClusterIP)、负载均衡

简单来说:Service 是"服务的地址",Ingress 是"如何找到这个地址的导航"

1.3 Ingress 的工作流程

以"用户访问 example.com/api"为例,完整流程如下:

  1. 用户在浏览器输入 example.com/api,DNS 将域名解析到 Ingress Controller 的外部 IP(通常是云厂商 LoadBalancer 的 IP,或集群节点的 IP+NodePort);
  2. 流量到达 Ingress Controller(运行在集群内的 Pod);
  3. Ingress Controller 检查已配置的 Ingress 规则,发现 example.com/api 需转发到 api-service:80
  4. Ingress Controller 查询 api-service 对应的 Endpoint(即后端 Pod 的 IP 列表);
  5. Ingress Controller 将流量转发到其中一个 api-service 关联的 Pod;
  6. Pod 处理请求后,将响应通过 Ingress Controller 回传给用户。

1.4 部署ingress-nginx-controller(示例)

以下示例以ingress-nginx为例,展示多种对外暴露方式。

1.4.1 准备与获取清单
bash 复制代码
mkdir -p /opt/ingress && cd /opt/ingress
# 官方:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml
# 国内镜像:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.25.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml

说明:mandatory.yaml文件中包含了很多资源的创建,包括namespace、ConfigMap、role,ServiceAccount等等所有部署ingress-controller需要的资源。

1.4.2 修改ClusterRole资源配置

mandatory.yaml中将Ingress资源权限加入networking.k8s.io(0.25版本开始):

yaml 复制代码
vim mandatory.yaml
......
apiVersion: rbac.authorization.k8s.io/v1
#RBAC相关资源从1.17版本开始改用rbac.authorization.k8s.io/v1,rbac.authorization.k8s.io/v1beta1在1.22版本即将弃用
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"    # (0.25版本)增加 networking.k8s.io Ingress 资源的 api 
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"   # (0.25版本)增加 networking.k8s.io/v1 Ingress 资源的 api 
    resources:
      - ingresses/status
    verbs:
      - update

1.5 Ingress暴露服务的三种方式(重点)

1.5.1 方式一:Deployment + Service(type=LoadBalancer)
  • 适合公有云:LB自动创建并绑定公网;将域名解析指向该地址即可对外暴露。

  • 如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露。

1.5.2 方式二:DaemonSet + HostNetwork + nodeSelector(示例详解)
  • 特定节点DaemonSet 方式部署Controller,并使用HostNetwork与宿主机网络打通;
  • 直接占用宿主机80/443
  • 链路最短、性能最好 ;一个node仅能运行一个Controller Pod;适合大并发生产

详解:DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。

实施步骤:

1.5.2.1 给node打标签,仅在node02运行:
bash 复制代码
kubectl label node node02 ingress=true
kubectl get nodes --show-labels
1.5.2.2 将Deployment 改为DaemonSet,启用HostNetwork并指定node:
yaml 复制代码
vim mandatory.yaml
...
apiVersion: apps/v1
# 修改 kind
# kind: Deployment
kind: DaemonSet
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
# 删除Replicas
# replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      # 使用主机网络
      hostNetwork: true
      # 选择节点运行
      nodeSelector:
        ingress: "true"
      serviceAccountName: nginx-ingress-serviceaccount
......
1.5.2.3 在所有node上传镜像并加载:
bash 复制代码
cd /opt/ingress
# 假设已有压缩包 ingree.contro.tar.gz
tar zxvf ingree.contro.tar.gz
docker load -i ingree.contro.tar
1.5.2.4 启动Controller,验证监听端口(在node02):
bash 复制代码
kubectl get pod -n ingress-nginx -o wide
kubectl get cm,daemonset -n ingress-nginx -o wide
netstat -lntp | grep nginx
# 在node02查看,期望监听:80 / 443 / 8181 / 10254


说明:8181为默认backend端口(未匹配到规则时流量进入此处)。若需高可用,可在多节点部署,并在前面加LVS + keepalived做负载均衡。

1.5.2.5 创建ingress规则
yaml 复制代码
###创建一个 deploy 和 svc
vim service-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
spec:
  type: ClusterIP
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  selector:
    app: nginx
1.5.2.6 创建Ingress(两种API示例):
yaml 复制代码
# 方法一:extensions/v1beta1(1.22 即将弃用)
vim ingress-app.yaml	
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-app-ingress
spec:
  rules:
  - host: www.benet.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-app-svc
          servicePort: 80
# 方法二:networking.k8s.io/v1(推荐)
vim ingress-app.yaml	
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-app-ingress
spec:
  rules:
  - host: www.mgb.com
    http:
      paths:
      - path: /
        pathType: Prefix  # 也可使用 Exact
        backend:
          service:
            name: nginx-app-svc
            port:
              number: 80

路径匹配:

  • Prefix:基于前缀匹配,如/0805可匹配/0805、/0805/yjs/0805/yjs/zjl`。
  • Exact:完全匹配,如/0805只能匹配/0805
1.5.2.7 测试:
bash 复制代码
kubectl apply -f service-nginx.yaml
kubectl apply -f ingress-app.yaml
kubectl get ingress
# /etc/hosts 添加解析:
# 192.168.10.127 www.mgb.com
curl www.mgb.com

可进入Controller Pod查看生成的/etc/nginx/nginx.conf,确认server www.mgb.com段落。

1.5.3 方式三:Deployment + Service(type=NodePort)
  • 以Deployment部署Controller,并创建NodePort类型的 Service暴露;
  • 由于NodePort是随机端口,通常前置一层负载均衡
  • 多一层NAT,大流量场景可能影响性能。

实施步骤:

1.5.3.1 下载nginx-ingress-controller和ingress-nginx暴露端口配置文件
bash 复制代码
mkdir -p /opt/ingress-nodeport && cd /opt/ingress-nodeport
# 清单获取
官方下载地址:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
# 或国内镜像:
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml

# 在所有 node 节点上传镜像包 ingress-controller-0.30.0.tar 到 /opt/ingress-nodeport 目录,并加载镜像
docker load -i ingress-controller-0.30.0.tar

# 启动 Controller 与 NodePort Service
kubectl apply -f mandatory.yaml
kubectl apply -f service-nodeport.yaml

#如果K8S Pod 调度失败,在 kubectl describe pod资源时显示:
# Warning  FailedScheduling  ...  didn't match node selector
# 解决:
# 1) 按 YAML 中的 nodeSelector 给节点加标签
kubectl label nodes <node_name> kubernetes.io/os=linux
# 2) 或删除 YAML 中的 nodeSelector

kubectl get pod,svc -n ingress-nginx
1.5.3.2 示例:HTTP代理访问
yaml 复制代码
vim ingress-nginx.yaml(应用、Service、Ingress)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-test
spec:
  rules:
  - host: www.benet.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

部署与测试:

bash 复制代码
kubectl apply -f ingress-nginx.yaml
kubectl get svc -n ingress-nginx
# 假设 NodePort 为 80:32383/TCP
# hosts 添加:192.168.10.120 www.mgb.com
curl http://www.mgb.com:31905

可以在两个Pod内修改index.html以区分返回:this is web1/web2

1.5.3.3 Ingress HTTP代理访问虚拟主机
bash 复制代码
mkdir /opt/ingress-nodeport/vhost
cd /opt/ingress-nodeport/vhost
yaml 复制代码
# deployment1.yaml(v1)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment1
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx1
  template:
    metadata:
      labels:
        name: nginx1
    spec:
      containers:
        - name: nginx1
          image: soscscs/myapp:v1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-1
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx1
yaml 复制代码
# deployment2.yaml(v2)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment2
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx2
  template:
    metadata:
      labels:
        name: nginx2
    spec:
      containers:
        - name: nginx2
          image: soscscs/myapp:v2
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-2
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx2
yaml 复制代码
# ingress-nginx.yaml(双主机名)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress1
spec:
  rules:
    - host: www1.mgb.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: svc-1
              port:
                number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress2
spec:
  rules:
    - host: www2.mgb.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: svc-2
              port:
                number: 80

测试:

bash 复制代码
# NodePort 假设为 32383
curl www1.mgb.com:32383
curl www2.mgb.com:32383
1.5.3.4 示例:HTTPS代理访问
bash 复制代码
mkdir -p /opt/ingress-nodeport/https && cd /opt/ingress-nodeport/https
# 生成自签证书
openssl req -x509 -sha256 -nodes -days 365 \
  -newkey rsa:2048 -keyout tls.key -out tls.crt \
  -subj "/CN=nginxsvc/O=nginxsvc"
# 创建 secret
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
kubectl get secret tls-secret -o yaml
yaml 复制代码
# ingress-https.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc-01
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-https
spec:
  tls:
    - hosts:
      - www3.mgb.com
      secretName: tls-secret
  rules:
    - host: www3.mgb.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: nginx-svc-01
              port:
                number: 80
bash 复制代码
kubectl apply -f ingress-https.yaml

kubectl get svc -n ingress-nginx

测试:

bash 复制代码
# NodePort 假设 443:32336
# hosts 添加:192.168.10.126 www3.mgb.com
# 浏览器访问:https://www3.mgb.com:32336
1.5.3.5 示例:BasicAuth认证
bash 复制代码
mkdir -p /opt/ingress-nodeport/basic-auth && cd /opt/ingress-nodeport/basic-auth
# 生成 basic auth 文件(文件名需为 auth)
yum -y install httpd
htpasswd -c auth zhangsan
# 存为 secret
kubectl create secret generic basic-auth --from-file=auth
yaml 复制代码
# ingress-auth.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - zhangsan'
spec:
  rules:
  - host: auth.mgb.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

参考:https://kubernetes.github.io/ingress-nginx/examples/auth/basic/

1.5.3.6 示例:重写(Rewrite)
  • 常用注解:
    • nginx.ingress.kubernetes.io/rewrite-target: <字符串>:重定向目标URI(必填)
    • nginx.ingress.kubernetes.io/ssl-redirect: <bool>:是否仅允许SSL(Ingress含证书时默认true
    • nginx.ingress.kubernetes.io/force-ssl-redirect: <bool>:即使未启用TLS也强制跳转HTTPS
    • nginx.ingress.kubernetes.io/app-root: <字符串>:定义应用根路径重定向
    • nginx.ingress.kubernetes.io/use-regex: <bool>:路径是否使用正则
yaml 复制代码
# ingress-rewrite.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-rewrite
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: http://www1.mgb.com:31905
spec:
  rules:
  - host: re.mgb.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          # 仅用于跳转,svc 名可随意
          service:
            name: nginx-svc
            port:
              number: 80

测试:

bash 复制代码
# hosts 添加:192.168.10.126 re.mgb.com
# 浏览器访问:http://re.mgb.com:31905cu

1.6 常见检查与排错要点

  • 查看Controller运行与端口
bash 复制代码
kubectl get pod -n ingress-nginx -o wide
kubectl get cm,daemonset -n ingress-nginx -o wide
netstat -lntp | grep nginx
  • 进入Pod检查Nginx配置
bash 复制代码
kubectl exec -it <controller-pod> -n ingress-nginx -- /bin/bash
more /etc/nginx/nginx.conf
# 查找:start server <host> ... end server <host>
  • 调度失败 (nodeSelector不匹配):
    • 给目标节点加对应标签,或删除YAML中的nodeSelector

1.7 总结

  • Ingress 是K8s集群对外的请求入口,对多个service进行再抽象;
  • 一般所称Ingress 包含两部分:Ingress资源对象 +Ingress Controller
  • Controller有多种实现(社区原生ingress-nginx等),按需求选择;
  • 对外暴露可选LoadBalancer / HostNetwork(DaemonSet)/ NodePort 等方式,需结合基础环境与业务选择;
  • 生产常用方案:DaemonSet + HostNetwork (高性能)或公有云LB(便捷托管)。

建议:在生产中配合多节点部署 + 前置LB / Anycast / eBPF LB 与完善的监控/告警(Prometheus采集10254),并对证书与访问控制(TLS、BasicAuth、WAF/限速)进行加固。

结尾

通过本文的梳理与实践,我们可以清晰地看到:Ingress 并非单一组件,而是 "规则定义(Ingress 资源)+ 规则执行(Ingress Controller)" 的协同体系。它不仅解决了传统服务暴露方式的痛点,更通过域名路由、HTTPS 终结、访问控制等高级功能,为 k8s 集群的外部流量管理提供了灵活且可扩展的方案。

在实际生产环境中,Ingress 的选型与部署需结合业务场景:公有云环境优先选择 LoadBalancer 方式以简化运维,大并发场景推荐 DaemonSet + HostNetwork 以保障性能,测试或小规模集群可使用 NodePort 快速验证。同时,配合多节点部署、前置负载均衡(如 LVS、云厂商 LB)及监控告警(如 Prometheus 采集 Controller metrics),能进一步提升 Ingress 服务的稳定性与安全性。

随着云原生技术的发展,Ingress 也在不断演进(如结合 ServiceMesh 实现更精细的流量治理),掌握其核心原理与实践方法,将为后续集群架构的优化与扩展奠定重要基础。

相关推荐
荣光波比5 小时前
K8S(十三)—— Helm3从入门到实战:简化Kubernetes应用部署与管理
云原生·容器·kubernetes
007php00712 小时前
百度面试题解析:微服务架构、Dubbo、Redis及其一致性问题(一)
redis·百度·docker·微服务·容器·职场和发展·架构
東雪蓮☆12 小时前
K8s 平滑升级
linux·运维·云原生·kubernetes
我狸才不是赔钱货15 小时前
容器:软件世界的标准集装箱
linux·运维·c++·docker·容器
三坛海会大神55517 小时前
k8s(十)Helm详解
云原生·容器·kubernetes
安卓开发者17 小时前
Docker命令大全:从入门到精通
docker·容器·eureka
K_i13418 小时前
Kubernetes流量管理:从Ingress到GatewayAPI演进
云原生·容器·kubernetes
蓝色土耳其love19 小时前
centos 7.9 安装单机版k8s
linux·运维·服务器·kubernetes·centos
七度光阴;21 小时前
Docker入门手册
运维·docker·容器