07_在k8s集群中安装ingress-nginx

文章目录

  • [0 背景与架构](#0 背景与架构)
    • [0.1 为什么需要ingress-nginx](#0.1 为什么需要ingress-nginx)
    • [0.2 环境架构](#0.2 环境架构)
    • [0.3 镜像拉取方案](#0.3 镜像拉取方案)
  • [1 安装前准备](#1 安装前准备)
    • [1.1 下载ingress-nginx部署文件](#1.1 下载ingress-nginx部署文件)
    • [1.2 替换镜像地址](#1.2 替换镜像地址)
    • [1.3 修复DNS解析问题](#1.3 修复DNS解析问题)
      • [1.3.1 问题现象](#1.3.1 问题现象)
      • [1.3.2 修复方法](#1.3.2 修复方法)
  • [2 安装ingress-nginx](#2 安装ingress-nginx)
    • [2.1 应用部署文件](#2.1 应用部署文件)
    • [2.2 验证部署](#2.2 验证部署)
  • [3 测试Ingress](#3 测试Ingress)
    • [3.1 部署测试应用](#3.1 部署测试应用)
    • [3.2 验证Ingress](#3.2 验证Ingress)
    • [3.3 从宿主机访问](#3.3 从宿主机访问)
  • [4 常见问题与解决](#4 常见问题与解决)
    • [4.1 镜像拉取失败(ImagePullBackOff)](#4.1 镜像拉取失败(ImagePullBackOff))
    • [4.2 DNS解析问题](#4.2 DNS解析问题)
    • [4.3 EXTERNAL-IP一直pending](#4.3 EXTERNAL-IP一直pending)
  • [5 总结](#5 总结)
  • 感谢阅读

0 背景与架构

0.1 为什么需要ingress-nginx

在 《06_在k8s集群中安装MetalLB实现LoadBalancer》 中,我们通过 MetalLB 让裸金属集群的 LoadBalancer Service 获得了外部 IP。但 MetalLB 只解决了四层负载均衡 的问题,当我们需要基于域名或路径进行七层路由 (例如 foo.com 转发到 foo-service,bar.com 转发到 bar-service),就需要用到 Kubernetes 的 Ingress 资源。

然而,Ingress 本身只是一个声明式的规则对象,它需要 Ingress Controller 来真正解析这些规则并转发流量。ingress-nginx 是 Kubernetes 社区最流行的 Ingress Controller 实现,它以 Nginx 作为数据平面,能够动态监听 Ingress 资源变化并自动生成 Nginx 配置。

0.2 环境架构

IP 虚拟机名称 角色 说明
192.168.56.101 rockylinux10-1 control-plane k8s master 节点
192.168.56.102 rockylinux10-2 worker k8s worker 节点
192.168.56.103 rockylinux10-3 worker k8s worker 节点

0.3 镜像拉取方案

由于国内网络限制,我们采用以下镜像源:

原始仓库 替换地址 用途
registry.k8s.io k8s.m.daocloud.io DaoCloud 的 k8s 镜像代理

1 安装前准备

1.1 下载ingress-nginx部署文件

根据官方的文档 https://kubernetes.github.io/ingress-nginx/deploy/ 可知:

If you don't have Helm or if you prefer to use a YAML manifest, you can run the following command instead:

bash 复制代码
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/cloud/deploy.yaml

由于虚拟机内直接访问 raw.githubusercontent.com 会超时,我们在 Mac 宿主机 上下载 YAML 文件,然后传输到虚拟机。

在 Mac 上执行:

bash 复制代码
curl -L -o ingress-nginx-deploy.yaml https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/cloud/deploy.yaml

传输到 master 节点:

bash 复制代码
scp ingress-nginx-deploy.yaml root@192.168.56.101:/root/

在 master 节点上创建目录并移动文件:

bash 复制代码
# 在 rockylinux10-1 上执行
mkdir -p /root/ingress-nginx
mv /root/ingress-nginx-deploy.yaml /root/ingress-nginx/
cd /root/ingress-nginx

1.2 替换镜像地址

ingress-nginx-deploy.yaml 中的镜像默认来自 registry.k8s.io,国内拉取会超时。根据 DaoCloud 镜像加速 https://gitee.com/daocloud/public-image-mirror 的说明,将 registry.k8s.io 替换为 k8s.m.daocloud.io:

bash 复制代码
sed -i 's/registry.k8s.io/k8s.m.daocloud.io/g' ingress-nginx-deploy.yaml

验证替换结果:

bash 复制代码
grep "image:" ingress-nginx-deploy.yaml

期望输出:

yaml 复制代码
image: k8s.m.daocloud.io/ingress-nginx/controller:v1.15.1@sha256:594ceea76b01c592858f803f9ff4d2cb40542cae2060410b2c95f75907d659e1
image: k8s.m.daocloud.io/ingress-nginx/kube-webhook-certgen:v1.6.9@sha256:01038e7de14b78d702d2849c3aad72fd25903c4765af63cf16aa3398f5d5f2dd
image: k8s.m.daocloud.io/ingress-nginx/kube-webhook-certgen:v1.6.9@sha256:01038e7de14b78d702d2849c3aad72fd25903c4765af63cf16aa3398f5d5f2dd

注意:kube-webhook-certgen 镜像出现了两次,分别用于 admission-create 和 admission-patch 两个 Job,这是正常的。

1.3 修复DNS解析问题

1.3.1 问题现象

完成镜像地址替换后,执行 kubectl apply 时 Pod 报 ErrImagePull:

text 复制代码
failed to pull image "k8s.m.daocloud.io/ingress-nginx/kube-webhook-certgen:v1.6.9@sha256:..."
failed to resolve reference "...": dial tcp: lookup m.daocloud.io on 192.168.1.1:53: no such host

但此时在节点上执行 ping k8s.m.daocloud.io 却可以成功解析。这是因为 glibc 和 Go 的 DNS 解析器行为不同 :ping 使用 glibc 解析器,遇到 NXDOMAIN 会继续尝试下一个 DNS;而 containerd 使用 Go 解析器,遇到 NXDOMAIN 直接放弃。节点的 /etc/resolv.conf 中 192.168.1.1 无法解析公网域名,containerd 在第一个 DNS 就失败了。

1.3.2 修复方法

在 所有 K8s 节点 (rockylinux10-1、10-2、10-3)上,为 NAT 网卡 enp0s9 配置可解析公网域名的 DNS:

bash 复制代码
# 配置 DNS,将公共 DNS 放在最前面
nmcli connection modify "enp0s9" \
  ipv4.dns "114.114.114.114 8.8.8.8 192.168.1.1 192.168.0.1" \
  ipv4.ignore-auto-dns yes

# 重启网卡使配置生效
nmcli connection down "enp0s9" && nmcli connection up "enp0s9"

验证 DNS 配置:

bash 复制代码
cat /etc/resolv.conf

期望输出:

text 复制代码
# Generated by NetworkManager
nameserver 114.114.114.114
nameserver 8.8.8.8
nameserver 192.168.1.1
# NOTE: the libc resolver may not support more than 3 nameservers.
# The nameservers listed below may not be recognized.
nameserver 192.168.0.1
nameserver fd17:625c:f037:3::3

说明 :114.114.114.114 和 8.8.8.8 已经排在最前面,containerd 使用 Go 解析器时会优先用它们解析公网域名,因此无需重启 containerd ,直接执行 kubectl apply 即可成功拉取镜像。

2 安装ingress-nginx

2.1 应用部署文件

在 master 节点(rockylinux10-1)上执行:

bash 复制代码
cd /root/ingress-nginx
kubectl apply -f ingress-nginx-deploy.yaml

2.2 验证部署

在 master 节点(rockylinux10-1)上执行:

bash 复制代码
kubectl get all -n ingress-nginx

期望输出(刚执行完 kubectl apply 几秒后的状态):

text 复制代码
NAME                                                 READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-psjcd             0/1     Completed   0          8s
pod/ingress-nginx-admission-patch-hjxn2              0/1     Completed   0          6s
pod/ingress-nginx-controller-6c9bd4845d-dfcvr        1/1     Running     0          10s

NAME                                         TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   10.1.47.212    192.168.56.240   80:31922/TCP,443:32639/TCP   10s
service/ingress-nginx-controller-admission   ClusterIP      10.1.192.23    <none>           443/TCP                      10s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           10s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-6c9bd4845d   1         1         1       10s

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           5s         8s
job.batch/ingress-nginx-admission-patch    1/1           4s         6s

关键点说明:

  • ingress-nginx-admission-create 和 ingress-nginx-admission-patch 是两个 Job,COMPLETIONS 为 1/1,对应的 Pod 状态为 Completed,表示它们已经成功执行完成。
  • ingress-nginx-controller 的 Pod 状态为 Running,Service 类型为 LoadBalancer,EXTERNAL-IP 由 MetalLB 分配。
  • 这两个 Job 生成的 Pod 会在执行完成后保留一段时间,随后会被自动清理,因此过一段时间再执行 kubectl get all 可能就看不到它们了。届时可以用 kubectl get events 确认它们曾经执行成功。

查看 Job 相关的 events 记录的命令:

bash 复制代码
kubectl get events -n ingress-nginx | grep ingress-nginx-admission

3 测试Ingress

3.1 部署测试应用

创建文件 kiada-ingress.yaml:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kiada
spec:
  replicas: 2
  selector:
    matchLabels:
      app: kiada
  template:
    metadata:
      labels:
        app: kiada
    spec:
      containers:
      - name: kiada
        # 这个镜像要自己用 k8s in action 相关的代码打镜像
        image: m.daocloud.io.localcache.registry:55000/kiada:0.5
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: kiada
spec:
  selector:
    app: kiada
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kiada-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: kiada.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kiada
            port:
              number: 80

应用:

bash 复制代码
kubectl apply -f kiada-ingress.yaml

3.2 验证Ingress

bash 复制代码
kubectl get ingress

期望输出:

text 复制代码
NAME           CLASS   HOSTS               ADDRESS         PORTS   AGE
kiada-ingress  nginx   kiada.example.com   192.168.56.240  80      30s

3.3 从宿主机访问

由于 kiada.example.com 是虚构域名,需要在 Mac 的 /etc/hosts 中添加解析,将域名指向 Ingress Controller 的外部 IP。

在 Mac 上执行:

bash 复制代码
echo "192.168.56.240 kiada.example.com" | sudo tee -a /etc/hosts

192.168.56.240 就是前面通过 MetalLB 分配给 ingress-nginx-controller 的 EXTERNAL-IP,可以通过 kubectl get svc -n ingress-nginx 查看实际值。

然后在 Safari 浏览器 中访问 http://kiada.example.com,应该能看到 Kiada 页面。

注意:Chrome 浏览器可能因安全策略无法访问,推荐使用 Safari。

4 常见问题与解决

4.1 镜像拉取失败(ImagePullBackOff)

现象 :Pod 处于 ImagePullBackOff,错误信息包含 no such host。

排查:

bash 复制代码
kubectl describe pod -n ingress-nginx <pod-name> | grep -E "Image:|Failed"

解决 :确认 registry.k8s.io 已替换为 k8s.m.daocloud.io,并检查所有节点的 DNS 配置是否正确。

4.2 DNS解析问题

现象 :ping 能通,但 containerd 拉取镜像时报 no such host。

原因 :glibc 和 Go DNS 解析器对 NXDOMAIN 的处理不同。

解决 :参考第 1.3 节,在所有节点上通过 nmcli 配置公共 DNS。

4.3 EXTERNAL-IP一直pending

现象 :ingress-nginx-controller 的 EXTERNAL-IP 始终为 <pending>。

原因:裸金属集群缺少 LoadBalancer 实现。

解决 :参考 《06_在k8s集群中安装MetalLB实现LoadBalancer》,安装 MetalLB 并配置 IP 地址池。

5 总结

通过本文,我们完成了以下工作:

  1. 下载了 ingress-nginx 部署文件:从 Mac 宿主机下载并传输到 master 节点
  2. 替换了镜像地址 :将 registry.k8s.io 替换为 k8s.m.daocloud.io
  3. 修复了 DNS 解析问题 :理解了 glibc 和 Go 解析器的差异,通过 nmcli 配置公共 DNS
  4. 成功安装了 ingress-nginx:验证了 Pod、Service 和 IngressClass 正常创建
  5. 测试了 Ingress 路由 :通过 /etc/hosts 解析,验证了域名路由功能

感谢阅读

相关推荐
零基础1233 小时前
Docker 部署实战:从入门到精通
docker·容器
承渊政道3 小时前
自建服务越来越多怎么管理?Docker部署Flare,搭一个自己的数字入口
运维·docker·容器·内网穿透·cpolar·nas·flare
芷栀夏4 小时前
极空间部署Photopea:Docker运行、网页修图与多设备使用
运维·docker·容器
百度一下吧14 小时前
Nginx 使用手册:从安装配置到实战部署
运维·nginx
谢亮_vipxieliang17 小时前
Kubernetes 1.36 深度解读:从 kubelet 安全到 GPU 原生调度的 70 项改进
安全·kubernetes·kubelet
wzq11_66620 小时前
kubernetes集群——灰度发布
云原生·容器·kubernetes
灯澜忆梦1 天前
【docker】#1 | Docker 初识
运维·docker·容器
骑着蜗牛撵大象3271 天前
穿越 Docker 内核迷雾:镜像分层的叠加态与卷挂载的空间穿梭
运维·docker·容器·联合文件系统·卷挂载·镜像分层·存储驱动
吴声子夜歌1 天前
Docker入门与实战——Docker数据管理
docker·容器