原文网址:https://www.cnblogs.com/fenggq/p/15061842.html
七、k8s入门系列----Ingress
上节讲到当k8s集群多个业务需要80端口提供业务时,可以使用LoadBlance Service,但是存在一个问题,负载均衡器一般都是云环境中厂商提供的时候才有,以往的经验就是部署一个nginx 代理进行转发,k8s也有相同的功能,就是Ingress,其后端控制器可以选择Nginx、Haproxy等,常见的是Ingress Nginx。
本系列使用kubespray 离线部署时,选择的Ingress后端控制器为nginx,讲解的时候都以此为基础。
创建web001资源配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[root@ylserver10686071 ~] # cat web001.yml
apiVersion: apps /v1
kind: Deployment
metadata:
name: web001
namespace: prod
spec:
replicas: 2
selector:
matchLabels:
k8s-app: web001
template:
metadata:
labels:
k8s-app: web001
spec:
containers:
- name: tomcat
image: tomcat:8.0
ports:
- name: web001-8080
containerPort: 8080
protocol: TCP
---
kind: Service
apiVersion: v1
metadata:
name: web001-svc
namespace: prod
spec:
type : ClusterIP
ports:
- name: web001-svc
protocol: TCP
port: 8080
targetPort: 8080
selector:
k8s-app: web001
|
创建web001 ingress资源配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@ylserver10686071 ~] # cat web001-ingress.yml
kind: Ingress
apiVersion: networking.k8s.io /v1
metadata:
name: web001-ingress
namespace: prod
annotations:
kubernetes.io /ingress .class: nginx
spec:
rules:
- host: web001.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web001-svc
port:
number: 8080
|
- kind: Ingress 指定资源类型为Ingress
- kubernetes.io/ingress.class: nginx Ingress Controller 类型,这里为 nginx,其他的还有haproxy、traefik、Istio等
- host: web001.example.com 匹配的域名,一个IP可以有多个域名
- path: / 结合 pathType: Prefix 表示匹配所有 / 为前缀的 URL
- backend 指定后端地址,这里以service 匹配来作为后端地址
创建web001 相关资源:
1 2 3 4 5 6 |
[root@ylserver10686071 ~] # kubectl apply -f web001.yml
deployment.apps /web001 created
service /web001-svc created
[root@ylserver10686071 ~] # kubectl apply -f web001-ingress.yml
ingress.networking.k8s.io /web001-ingress created
[root@ylserver10686071 ~] #
|
查看资源相关信息,可以看到域名 web001.example.com 直接转发到 POD 对应的端口地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[root@ylserver10686071 ~] # kubectl get pods -n prod -o wide|grep web001
web001-69bd6f8c5f-26hlv 1 /1 Running 0 2m17s 10.233.75.69 ylserver10686071 <none> <none>
web001-69bd6f8c5f-nvgmj 1 /1 Running 0 2m17s 10.233.72.47 ylserver10686073 <none> <none>
[root@ylserver10686071 ~] # kubectl describe ingress web001-ingress -n prod
Warning: extensions /v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io /v1 Ingress
Name: web001-ingress
Namespace: prod
Address: 10.68.60.71,10.68.60.72,10.68.60.73
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
web001.example.com
/ web001-svc:8080 (10.233.72.47:8080,10.233.75.69:8080)
Annotations: kubernetes.io /ingress .class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 2m22s (x2 over 2m27s) nginx-ingress-controller Scheduled for sync
Normal Sync 2m22s (x2 over 2m27s) nginx-ingress-controller Scheduled for sync
Normal Sync 2m22s (x2 over 2m27s) nginx-ingress-controller Scheduled for sync
[root@ylserver10686071 ~] #
|
修改本地电脑hosts表,将域名 web001.example.com 指向k8s集群地址,浏览器进行访问:
1 2 |
###此处本地C:\Windows\System32\drivers\etc\hosts添加以下记录
10.68.60.71 web001.example.com
|
将deployment web001的副本数调为3,可以看到ingress 后端会自动添加新的POD地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@ylserver10686071 ~] # kubectl scale deployment web001 -n prod --replicas=3
deployment.apps /web001 scaled
[root@ylserver10686071 ~] # kubectl describe ingress web001-ingress -n prod
Warning: extensions /v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io /v1 Ingress
Name: web001-ingress
Namespace: prod
Address: 10.68.60.71,10.68.60.72,10.68.60.73
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
web001.example.com
/ web001-svc:8080 (10.233.67.40:8080,10.233.72.47:8080,10.233.75.69:8080)
Annotations: kubernetes.io /ingress .class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 11m (x2 over 11m) nginx-ingress-controller Scheduled for sync
Normal Sync 11m (x2 over 11m) nginx-ingress-controller Scheduled for sync
Normal Sync 11m (x2 over 11m) nginx-ingress-controller Scheduled for sync
[root@ylserver10686071 ~] #
|
Ingress 工作原理如上图所示,分析下其运行原理:
- Ingress Controller 通过跟Ingress 交互得到域名对应的Service,接着通过Kubernetes API 获取Service地址信息,最终将得到的信息写入负载均衡器,负载均衡器reload该规则便可实现服务发现,即动态映射
- 外部请求进来时,负载均衡器拦截请求,比如nginx,最后根据域名相应规则转发到对应的POD地址
- 基于以上原理,负载均衡器都是使用Daemonset部署到每台Node节点上,最后宿主机通过iptables dnat规则转发到负载均衡器POD地址
实验验证一下,查看负载均衡器POD的IP地址:
1 2 3 4 5 6 |
[root@ylserver10686071 ~] # kubectl get pods -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-controller-pnjkj 1 /1 Running 0 14d 10.233.75.33 ylserver10686071 <none> <none>
ingress-nginx-controller-qgwc2 1 /1 Running 0 14d 10.233.72.35 ylserver10686073 <none> <none>
ingress-nginx-controller-ttbxr 1 /1 Running 1 14d 10.233.67.17 ylserver10686072 <none> <none>
[root@ylserver10686071 ~] #
|
查看宿主机iptables dnat转发规则:
1 2 3 4 5 |
[root@ylserver10686071 ingress_nginx] # iptables-save |grep "DNAT"|grep "destination"
-A CNI-DN-a7c2c7254f00d8a8825ce -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.233.75.33:80
-A CNI-DN-a7c2c7254f00d8a8825ce -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.233.75.33:443
-A CNI-DN-a7c2c7254f00d8a8825ce -p tcp -m tcp --dport 10254 -j DNAT --to-destination 10.233.75.33:10254
[root@ylserver10686071 ingress_nginx] #
|
总结一下:
- k8s集群对外提供服务时,80和443端口复用除了使用负载均衡器外,比较常用的是使用Ingress Controller进行转发
- Ingress Controller 规则可以动态加载,不会影响其他业务的正常运行
- Ingress Controller中使用负载均衡器时一些高级用法,例如client_max_body_size、timeout等可以通过相关的配置生效,一般都是在annotations 对象处进行属性声明。