一 要理解一个概念,首先要明白它是干什么用的,然后再去理解它是怎么实现的。Ingress的作用就是提供一个集群外部访问集群内部的入口。那么它是怎么实现的呢,我们知道,集群内部的Cluster IP外部是无法直接访问到的,而在 K8s集群中,集群外部访问内部pod中的应用大概有以下几种形式:
1. 通过开启proxy模式访问Cluster IP。这种方式要求我们运行 kubectl 作为一个未认证的用户,因此我们不能用
这种方式把服务暴露到 internet 或者在生产环境使用。
2. 直接访问pod,pod中定义hostPort,并设置pod级别的hostwork=true,直接将pod中的端口映射到pod所在的物
理主机或者虚拟机上。通过访问主机ip:hostPort即可访问集群内部pod;这种方式只能非常少量使用,否则和直接
使用docker没多大区别。
3. 先访问Service,Service可以直接通过集群内部负载均衡至pod中的应用,而外部访问集群中的Service可以通
过在Service中定义NodePort实现;这种方式在集群中的每台主机上开放一个随机的或指定的端口,且每个端口
只能提供一个服务,它是通过端口不同来区分不同应用,而不是通过域名,管理不便,不适合在大规模集群中部
署。
4. 通过LoadBlancer Service访问Service,这个需要接入云服务,每个服务都会由云服务提供一个IP作为入口,
转发相应的流量,但每个LoadBlancer Service都会产生费用,成本比较高。
5. Ingress,K8s中的API对象,定义了一组规则。Ingress本身只是定义了一组规则,需要配合Ingress controllor
才有意义,不理解Ingress controllor没关系,继续往下。
二 如果不通过Ingress,我们也可以手动在Service前部署一个反向代理,比如nginx或者haproxy。
1. nginx运行在集群中,所以可以访问到集群内部的Service,只需在nginx配置中proxy_pass指向相应的Service
Cluster IP或者dns即可,多一个服务也就是多配置一个nginx中的虚拟机主机。
2. 通过设置hostPort即可从外部访问nginx,再通过nginx反向代理至后端应用的Service;或者不通过hostPort,
再在nginx前端再加一个Service,通过设置Service的NodePort来访问nginx。
三 通过自己部署nginx反向代理这种方式好像就OK了啊,那一直说的Ingress又是什么?
Ingress是K8s中的API对象,定义了一组规则,对应于nginx(或者haproxy,traefik等)的一段配置,可以
近似成一段虚拟主机的配置,其实Ingress和自己部署反向代理思路都是一样的,只不过自己部署反向代理时,
如果新增加一个服务,你自己需要去增加nginx中的配置并重新加载配置,而在Ingress中你增加一个服务,你需
要增加一个Ingress的配置并运行,Ingress会自己去请求K8s的api以获得新增应用的nds或者Cluster Ip,然后将
你写的Ingress规则转换成nginx配置,并修改到ngixn中,然后自动reload nginx。
简单来说,两者的区别就是:当新增后端应用时,一种需要增加nginx配置,另外一种需要增加Ingress规
则。你可以简单的把Ingress理解为一段类似nginx虚拟主机的配置,因为它会自动为你转换。
四 说道这里,部署Ingress就很简单了,不过在Ingress中有它自己的一些术语。一个完整的Ingress有以下几个组件:
1. 反向代理,可以是nginx、traefik、Haproxy等。
2. Ingress controllor,即Ingress控制器,监听apiserver,获取服务新增,删除等变化,并结合ingress规则动
态更新到反向代理负载均衡器上,并重载配置使其生效。
3. Ingress,K8s的一个资源对象,定义了一组规则,你可以简单理解为一段对应nginx虚拟机主机的配置。而
实际上,Ingress controllor和反向代理,也就是上面的1,2两个组件,都是结合在一起的。比如traefik,它同时
具备反向代理和Ingress controllor的功能;如果使用nginx,那么你需要部署专用的nginx,它也集成了Ingress
controllor。
本文采用traefik来部署反向代理和Ingress controllor,有关traefik的详细介绍可以参考官网。
五 实际部署。
本文从开始到现在,已经覆盖了很多的背景和知识。你可能担心现在会是最难的部分,但实际上它最简单,
Ingress之所以比较复杂,唯一原因是因为“其他的一切”,而我们已经很好地学完了这些东西。
1. 如果K8s使用了rbac,而Ingress controllor需要访问apiserver,所以需要先为traefik配置一个Service Account。
cat > traefik-ingress-rbac.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress
subjects:
- kind: ServiceAccount
name: traefik-ingress
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f traefik-ingress-rbac.yaml
第一段配置定义了一个Service Account,第二段配置将定义的Service Account绑定到cluster-admin这个已经
存在的ClusterRole上,cluster-admin是具有访问apiserver的权限的。
2. 然后需要部署一个traefik,并且将它暴露到集群外,它既是反向代理也是Ingress controllor。
cat > traefik-ingress-controller.yaml << EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
serviceAccountName: traefik-ingress
containers:
- image: traefik
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- containerPort: 80
hostPort: 80
- containerPort: 8080
args:
- --web
- --kubernetes
EOF
kubectl apply -f traefik-ingress-controller.yaml
这是traefik官方文档的部署文件,我只是在它里面加了个Service Account,可以看到,它采用设置pod的
hostPort方式来将80端口暴露到集群外,80端口可以看做是反向代理http的端口,接收并转发所有的定义到Ingress
的流量。而它在pod中还对集群内部有一个8080端口,8080端口一个后端应用,提供了traefik-web-ui。8080端口
是traefik默认的webUI端口,8080端口定义为Pod的端口,集群外部是无法直接访问到的,所以我们还需要部署一
个Service+Ingress。
3. 部署Service+Ingress
cat > traefik-web-ui.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik-ui.com
http:
paths:
- backend:
serviceName: traefik-web-ui
servicePort: 80
EOF
kubectl apply -f traefik-web-ui.yaml
当你真正要访问该traefik-ui.com时,你还需要将这个域名绑定到它对应的IP地址,也就是hostPort所在的主
机的IP。配置好hosts文件后,访问traefik-ui.com。OK
1. 可以看到Ingress中,当访问traefik-ui.com这个域名时,对应会访问到名为traefik-web-ui的Service的80
端口中。而Service的80端口对应后端的traefik web UI的8080端口。到此为止,一个完整的Ingress就部署完成
了,它的访问流程是这样的:
集群外部访问traefik-ui.com-->请求会到达traefik所在的主机的IP:hostPort上,也就是IP:80-->由于Ingress规
则此时被转换成traefik中的反向代理配置,根据Ingress规则会被转发往traefik-web-ui这个Service:80上-->
Service转发到后端标签为 traefik-ingress-lb的pod的8080端口中,实际上又回到了traefik,不过是8080端口。
简单来说:请求域名---->traefik:80---->Ingress(只是Ingerss规则,实际还是由traefik完成)---->
后端Service:80---->traefik:8080
2. 部署其他后端服务时也是一样,把上面的后端Service和应用换成相应的就行了。比如部署一个tomcat,那
么 需要再部署3个K8s资源,分别是tomcat-deployment.yaml、tomcat-service.yaml、tomcat-Ingress.yaml,
你请求的域名为Ingress中的host配置的域名,你请求流程为:
请求域名---->traefik:80---->Ingress(只是Ingerss规则,实际还是由traefik完成)---->tomcat-Service
---->tomcat-deployment中的Pod。
3. 上面是通过hostPort暴露traefik,可以直接访问80端口,如果需要在多台node上部署,可以通过给相应
的node 设置lable,然后部署时指定nodeSelector。
我们同样可以通过Service的NodePort暴露traefik,需要在traefik前再加一个Service,默认NodePort端口
范围 为30000-32767,如果想直接暴露80端口,需要修改apiserver的配置,tomcat采用该方式的请求流程为:
请求---->traefik-service的Nodeport---->traefik---->Ingress(只是Ingerss规则,实际还是由traefik完成)
---->tomcat-Service---->tomcat-deployment中的Pod。
原文地址:http://blog.51cto.com/13645243/2118455
时间: 2024-11-08 09:49:56