我们知道service的表现形式为IP:PORT,即工作在第四层传输层(TCP/IP层),那么对于不同的URL地址经常对应用不同的后端服务或者虚拟服务器,这些应用层的转发机制仅通过kubernetes的service机制是无法实现的,这种情况我们可以使用ingress策略定义和一个具体的ingress Controller,两者结合实现一个完整的Ingress 负载均衡,这个负载均衡是基于nginx七层反向代理来实现。
k8s 对外暴露服务(service)主要有两种方式:NotePort, LoadBalance, 此外externalIPs也可以使各类service对外提供服务,但是当集群服务很多的时候,NodePort方式最大的缺点是会占用很多集群机器的端口;LB方式最大的缺点则是每个service一个LB又有点浪费和麻烦,并且需要k8s之外的支持; 而ingress则只需要一个NodePort或者一个LB就可以满足所有service对外服务的需求。工作机制大致可以用下图表示:
一种全局的、为了代理不同后端 Service 而设置的负载均衡服务,就是 Kubernetes 里的Ingress 服务。
Ingress由两部分组成:Ingress controller和Ingress服务
Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。
实际上,ingress相当于一个7层的负载均衡器,是k8s对反向代理的一个抽象。大概的工作原理也确实类似于Nginx,可以理解成在 Ingress 里建立一个个映射规则 , ingress Controller 通过监听 Ingress这个api对象里的配置规则并转化成 Nginx 的配置(kubernetes声明式API和控制循环) , 然后对外部提供服务。ingress包括:ingress controller和ingress resources
ingress controller: 核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。
ingress resources: 这个就是一个类型为Ingress的k8s api对象了,这部分则是面向开发人员。
Kubernetes给出的方案就是Ingress,Ingress包含了两大主件Ingress Controller和Ingress。
Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。
Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.(注意:写入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 在增加一层负载均衡转发)
从上图中可以很清晰的看到,实际上请求进来还是被负载均衡器拦截,比如 nginx,然后 Ingress Controller 通过跟 Ingress 交互得知某个域名对应哪个 service,再通过跟 kubernetes API 交互得知 service 地址等信息;综合以后生成配置文件实时写入负载均衡器,然后负载均衡器 reload 该规则便可实现服务发现,即动态映射
了解了以上内容以后,这也就很好的说明了我为什么喜欢把负载均衡器部署为 Daemon Set;因为无论如何请求首先是被负载均衡器拦截的,所以在每个 node 上都部署一下,同时 hostport 方式监听 80 端口;那么就解决了其他方式部署不确定 负载均衡器在哪的问题,同时访问每个 node 的 80 都能正确解析请求;如果前端再 放个 nginx 就又实现了一层负载均衡。
Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。
官网:https://kubernetes.github.io/ingress-nginx/
应用ingress controller定义文件
$ kubectl apply -fhttps://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
应用ingress-service定义文件
$ kubectl apply -fhttps://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
首先拉取 ingress-controller镜像至harbor仓库
编辑此文件,把镜像的位置换成本地仓库中镜像的位置
应用ingress controller定义文件
应用ingress-service定义文件
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-demo
spec:
backend:
serviceName: ingress-nginx
servicePort: 80
创建 service.yaml文件
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
[kubeadm@server1 ingress]$ \vi ingress.yaml
[kubeadm@server1 ingress]$ vim ingress.yaml
[kubeadm@server1 ingress]$ vim service.yaml
[kubeadm@server1 ingress]$ kubectl apply -f service.yaml
service/myservice created
[kubeadm@server1 ingress]$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/ingress-demo created
[kubeadm@server1 ingress]$
ingress-demo调度ingress-nginx这个服务,服务后端pod的ip为10.244.1.61和10.244.2.34
[kubeadm@server1 ingress]$ kubectl -n ingress-nginx get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.99.32.59 <none> 80:30016/TCP,443:31941/TCP 31m
[kubeadm@server1 ingress]$
实现service服务中的负载均衡,因为ingress-nginx也是通过nodeport模式的端口暴露,实现外部访问
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: reg.westos.org/k8s/myapp:v2
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: myapp
type: ClusterIP
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-example
spec:
rules:
- host: www2.westos.org
http:
paths:
- path: /
backend:
serviceName: myservice
servicePort: 80
[kubeadm@server1 ingress]$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-demo <none> www1.westos.org 10.99.32.59 80 36m
ingress-example <none> www2.westos.org 10.99.32.59 80 3m22s
[kubeadm@server1 ingress]$
访问www1.westos.org时访问到v1
访问不同的域名,访问到的后端service不同,负载到不同的pod后端
kind: Ingress
metadata:
name: ingress-hello
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: www3.westos.org
http:
paths:
- path: /1
backend:
serviceName: ingress-nginx
servicePort: 80
paths:
- path: /2
backend:
serviceName: myservice
servicePort: 80