ingress概念
ingress-Nginx官方部署手册
ingress-nginx国内代码仓库
前言
简单示例
将所有流量都发送到同一 Service 的简单 Ingress 示例
三种常用的部署模式
Deployment+LoadBalancer模式的service
用Deployment部署igress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向改地址,就实现了集群服务的对外暴露
Deployment+NodePort模式的service
同样用deployment模式部署ingress-controller,然后创建对应的ingress svc,type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。改方式一般用于宿主机是相对固定的环境ip地址不变的场景。
NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定的影响
DaemonSet+HostNetwork(+nodeSelector)
用DaemonSet 结合nodeselector来部署ingress-controller到特定的Node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/443端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房的入口nginx服务器。该方式整个请求链路最简单,性能相对nodeport模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。比较适合大并发的生产环境使用。
DaemonSet+HostNetwork方式部署
环境
k8s版本:v1.26.1
容器运行时:containerd.io 1.6.22
ingress-nginx-controller : v1.8.0
下载配置文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/cloud/deploy.yaml
修改配置文件
主要是修改镜像拉取地址、部署方式等
原镜像 | 国内代理镜像 |
---|---|
registry.k8s.io/ingress-nginx/controller:v1.8.0@sha256:744ae2afd433a395eeb13dc03d3313facba92e96ad71d9feaafc85925493fee3 | registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.8.0 |
registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b | registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20230407 |
apiVersion: apps/v1
kind: DaemonSet # 修改Deployment为DaemonSet(每个node只能部署一个,适用于在集群中的每个节点上运行守护进程或系统级别的任务)
metadata:
labels:
.......
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
.......
template:
metadata:
labels:
........
spec:
hostNetwork: true #使用主机网络
nodeSelector:
ingress: "true" #选择节点运行,节点有标签ingress=true
给节点打标签
#新增标签
kubectl label node node02 ingress=true
#移除标签 -代表移除
kubectl label node node02 ingress=true-
#如果想在master节点上部署需要移除污点
#查看master污点
kubectl describe node <master 节点名称> | grep Taints
# 如果是Taints: node-role.kubernetes.io/control-plane:NoSchedule,代表不可调度
#NoSchedule: 一定不能被调度
#PreferNoSchedule: 尽量不要调度
#NoExecute: 不仅不会调度, 还会驱逐Node上已有的Pod
#移除污点
kubectl taint nodes <主节点名称> node-role.kubernetes.io/control-plane:NoSchedule-
#添加污点PreferNoSchedule: 尽量不要调度
kubectl taint nodes <主节点名称> node-role.kubernetes.io/control-plane=:PreferNoSchedule
执行部署
kubectl apply -f deploy.yaml
验证
准备一个nginx服务
kubectl apply -f nginxDeployment.yaml
apiVersion: v1
kind: Namespace
metadata:
name: my-nginx #创建名称空间
---
apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Deployment #该配置的类型,我们使用的是 Deployment
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: nginx-deployment #Deployment 的名称
namespace: my-nginx
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: nginx #为该Deployment设置key为app,value为nginx的标签
spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas: 3 #使用该Deployment创建一个应用程序实例
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数���
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:1.7.9 #使用镜像nginx:1.7.9创建container,该container默认80端口可访问
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service #Service 的名称
namespace: my-nginx
labels: #Service 自己的标签
app: nginx #为该 Service 设置 key 为 app,value 为 nginx 的标签
spec: #这是关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
selector: #标签选择器
app: nginx #选择包含标签 app:nginx 的 Pod
ports:
- name: nginx-port #端口的名字
protocol: TCP #协议类型 TCP/UDP
port: 8081 #集群内的其他容器组可通过 80 端口访问 Service
targetPort: 80 #将请求转发到匹配 Pod 的 80 端口
type: ClusterIP #Serive的类型,ClusterIP/NodePort/LoaderBalancer
执行结果:
配置ingress规则
kubectl apply -f ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: my-nginx #ingress部署到需要转发的namespace
annotations:
kubernetes.io/ingress.class: "nginx" # 指定 Ingress 控制器的类名称,在部署ingress-nginx-controller的yaml中可见- --ingress-class=nginx
nginx.ingress.kubernetes.io/rewrite-target: / #这样可以在转发请求之前修改路径,如将下面的/testNginx, 改为/, 否则nginx-service收到的请求依旧会包含/testNginx
spec:
rules:
- host: www.liang.com #域名,只能是域名,支持通配符(*.foo.com)
http:
paths:
- path: /testNginx
pathType: Prefix #路径匹配类型,可见https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/
backend:
service:
name: nginx-service #要转发到那个service
port:
number: 8081 #service的端口
---
创建成功:
测试
#本地设置域名解析
echo '192.168.1.0 www.liang.com' >> /etc/hosts
可能的报错
创建ingres规则时 Kubernetes 集群中的 Ingress 控制器(例如 Nginx Ingress Controller)无法访问或响应
Error from server (InternalError): error when creating "ingress.yaml": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s": dial tcp 10.106.17.187:443: connect: connection timed out
一般是webhook没有正常启动,测试环境可以通过删除validatingwebhookconfigurations来解决
kubectl get validatingwebhookconfigurations
kubectl delete ValidatingWebhookConfiguration ingress-nginx-admission
#然后重新部署ingress规则
kubectl apply -f ingress.yaml
ingress和需要转发的服务不在同一namespace,
The Ingress "nginx-ingress" is invalid: spec.rules[0].http.paths[0].backend.service.name: Invalid value: "nginx-service.my-nginx": a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is 'a-z?')
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: ingress-nginx
spec:
rules:
- host: www.liang.com
http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx-service.my-nginx # 修改后的后端服务名称[servicename.namespace]
port:
number: 8081
实际使用时报错nginx-service.my-nginx不符合规则
可以通过把ingress部署到需要转发的服务的namespace中