
文章目录0 背景与架构0.1 为什么需要ingress-nginx0.2 环境架构0.3 镜像拉取方案1 安装前准备1.1 下载ingress-nginx部署文件1.2 替换镜像地址1.3 修复DNS解析问题1.3.1 问题现象1.3.2 修复方法2 安装ingress-nginx2.1 应用部署文件2.2 验证部署3 测试Ingress3.1 部署测试应用3.2 验证Ingress3.3 从宿主机访问4 常见问题与解决4.1 镜像拉取失败ImagePullBackOff4.2 DNS解析问题4.3 EXTERNAL-IP一直pending5 总结感谢阅读0 背景与架构0.1 为什么需要ingress-nginx在 《06_在k8s集群中安装MetalLB实现LoadBalancer》 中我们通过 MetalLB 让裸金属集群的LoadBalancerService 获得了外部 IP。但 MetalLB 只解决了四层负载均衡的问题当我们需要基于域名或路径进行七层路由例如foo.com转发到foo-servicebar.com转发到bar-service就需要用到 Kubernetes 的Ingress资源。然而Ingress本身只是一个声明式的规则对象它需要Ingress Controller来真正解析这些规则并转发流量。ingress-nginx是 Kubernetes 社区最流行的 Ingress Controller 实现它以 Nginx 作为数据平面能够动态监听Ingress资源变化并自动生成 Nginx 配置。0.2 环境架构IP虚拟机名称角色说明192.168.56.101rockylinux10-1control-planek8s master 节点192.168.56.102rockylinux10-2workerk8s worker 节点192.168.56.103rockylinux10-3workerk8s worker 节点0.3 镜像拉取方案由于国内网络限制我们采用以下镜像源原始仓库替换地址用途registry.k8s.iok8s.m.daocloud.ioDaoCloud 的 k8s 镜像代理1 安装前准备1.1 下载ingress-nginx部署文件由于虚拟机内直接访问raw.githubusercontent.com会超时我们在Mac 宿主机上下载 YAML 文件然后传输到虚拟机。在 Mac 上执行curl-L-oingress-nginx-deploy.yaml https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/cloud/deploy.yaml传输到 master 节点scpingress-nginx-deploy.yaml root192.168.56.101:/root/在 master 节点上创建目录并移动文件# 在 rockylinux10-1 上执行mkdir-p/root/ingress-nginxmv/root/ingress-nginx-deploy.yaml /root/ingress-nginx/cd/root/ingress-nginx1.2 替换镜像地址ingress-nginx-deploy.yaml中的镜像默认来自registry.k8s.io国内拉取会超时。根据 DaoCloud 镜像加速 https://gitee.com/daocloud/public-image-mirror 的说明将registry.k8s.io替换为k8s.m.daocloud.iosed-is/registry.k8s.io/k8s.m.daocloud.io/gingress-nginx-deploy.yaml验证替换结果grepimage:ingress-nginx-deploy.yaml期望输出image:k8s.m.daocloud.io/ingress-nginx/controller:v1.15.1sha256:594ceea76b01c592858f803f9ff4d2cb40542cae2060410b2c95f75907d659e1image:k8s.m.daocloud.io/ingress-nginx/kube-webhook-certgen:v1.6.9sha256:01038e7de14b78d702d2849c3aad72fd25903c4765af63cf16aa3398f5d5f2ddimage:k8s.m.daocloud.io/ingress-nginx/kube-webhook-certgen:v1.6.9sha256:01038e7de14b78d702d2849c3aad72fd25903c4765af63cf16aa3398f5d5f2dd注意kube-webhook-certgen镜像出现了两次分别用于admission-create和admission-patch两个 Job这是正常的。1.3 修复DNS解析问题1.3.1 问题现象完成镜像地址替换后执行kubectl apply时 Pod 报ErrImagePullfailed to pull image k8s.m.daocloud.io/ingress-nginx/kube-webhook-certgen:v1.6.9sha256:... 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# 配置 DNS将公共 DNS 放在最前面nmcli connection modifyenp0s9\ipv4.dns114.114.114.114 8.8.8.8 192.168.1.1 192.168.0.1\ipv4.ignore-auto-dnsyes# 重启网卡使配置生效nmcli connection downenp0s9nmcli connection upenp0s9验证 DNS 配置cat/etc/resolv.conf期望输出# 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-nginx2.1 应用部署文件在 master 节点rockylinux10-1上执行cd/root/ingress-nginx kubectl apply-fingress-nginx-deploy.yaml2.2 验证部署在 master 节点rockylinux10-1上执行kubectl get all-ningress-nginx期望输出刚执行完kubectl apply几秒后的状态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是两个 JobCOMPLETIONS 为1/1对应的 Pod 状态为Completed表示它们已经成功执行完成。ingress-nginx-controller的 Pod 状态为RunningService 类型为LoadBalancerEXTERNAL-IP由 MetalLB 分配。这两个 Job 生成的 Pod 会在执行完成后保留一段时间随后会被自动清理因此过一段时间再执行kubectl get all可能就看不到它们了。届时可以用kubectl get events确认它们曾经执行成功。查看 Job 相关的 events 记录的命令kubectl get events-ningress-nginx|grepingress-nginx-admission3 测试Ingress3.1 部署测试应用创建文件kiada-ingress.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:kiadaspec:replicas:2selector:matchLabels:app:kiadatemplate:metadata:labels:app:kiadaspec:containers:-name:kiada# 这个镜像要自己用 k8s in action 相关的代码打镜像image:m.daocloud.io.localcache.registry:55000/kiada:0.5ports:-containerPort:8080---apiVersion:v1kind:Servicemetadata:name:kiadaspec:selector:app:kiadaports:-port:80targetPort:8080---apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:kiada-ingressspec:ingressClassName:nginxrules:-host:kiada.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:kiadaport:number:80应用kubectl apply-fkiada-ingress.yaml3.2 验证Ingresskubectl get ingress期望输出NAME CLASS HOSTS ADDRESS PORTS AGE kiada-ingress nginx kiada.example.com 192.168.56.240 80 30s3.3 从宿主机访问由于kiada.example.com是虚构域名需要在 Mac 的/etc/hosts中添加解析将域名指向 Ingress Controller 的外部 IP。在 Mac 上执行echo192.168.56.240 kiada.example.com|sudotee-a/etc/hosts192.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。排查kubectl describe pod-ningress-nginxpod-name|grep-EImage:|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 总结通过本文我们完成了以下工作下载了 ingress-nginx 部署文件从 Mac 宿主机下载并传输到 master 节点替换了镜像地址将registry.k8s.io替换为k8s.m.daocloud.io修复了 DNS 解析问题理解了 glibc 和 Go 解析器的差异通过nmcli配置公共 DNS成功安装了 ingress-nginx验证了 Pod、Service 和 IngressClass 正常创建测试了 Ingress 路由通过/etc/hosts解析验证了域名路由功能感谢阅读