Kubernetes Traefik Ingress
由于traefik 2.x和traefik 1.x的版本配置改动的比较多,这里先介绍1.x版本的配置。目前来说traefik 2.0是2019年12月份发布的,大部分企业还是使用1.x。我们跳槽去人家公司不能说光会2.x不会1.x版本,所以traefik会出2个版本的文档。目前我们使用的版本的1.7.20,为1.x版本的最后一个版本,更新时间为2019年12月10日
https://docs.traefik.io/migration/v1-to-v2/
ngress 其实就是集群外部访问的一个入口,将外部的请求转发到不同的Server上,其实就相当于Nginx、Haproxy等负载均衡器。
Ingress实际上是通过服务发现的功能进行实现,通过Ingress controller来提供路由信息的刷新
Ingress controller可以理解为一个监视器,不断监听kube-apiserver,实时感知service、Pod的变化,Ingress controller再结合Ingress的配置,更新反向代理负载均衡器,达到服务发现的作用。
目前可以提供Ingress controller有很多,比如traefik、nginx-ingress、Kubernetes Ingress Cpmtrper for Kong、HAProxy Ingress controller等。
目前常见的负载均衡有Nginx-Ingress和traefik
这里使用traefik进行演示,主要是目前traefik已经成为主流。并且traefik有漂亮的dashboard界面,配置简单,已经已经深入和prometheus集成,nginx-ingress需要有3个组件镜像,traefik只有2个
Traefik
traefik是一款开源的反向代理和负载均衡工具,最大的优点是能够和常见的微服务系统直接整合,可以实现自动化动态配置。目前支持Docker、Swarm、Mesos、Mesos、Kubernetes、Consul、ETCD、Zookeeper等等后端模型
![image_1e08sgoti1ne5u8516p8n986e9.png-790kB](http://images.ukx.cn/abcdocker/oadstq31o0dbu54mm6bvpnyv/image_1e08sgoti1ne5u8516p8n986e9.png)
左边的是我们用户访问的域名,当请求到达traefik上,traefik会去监听API(kube-apiserver)监听访问的更新,这个简单的可以理解为Nginx的后端健康检查,实时监控Pod的状态。
核心概念
当启动Traefik时,需要定义entrypoints,然后通过entrypoints的路由来分析传入的请求,来查看他们是否是一组规则匹配,如果匹配,则路由可能将请求通过一系列的转换过来在发送到服务上去。
![image_1e08t24ls1hb0o46kv11apr4mrm.png-513.4kB](http://images.ukx.cn/abcdocker/1p5tvi8cl5hwy95rluit8za4/image_1e08t24ls1hb0o46kv11apr4mrm.png)
[√] Providers用来自动发现平台上的服务,可以是编排工具、容器引擎
[√] Entrypoints监听传入的流量,是网络的入口点,定义了接受请求的端口(HTTP或者TCP)
[√] Routers分析请求(host,path,headers,SSL等),负责将传入的请求连接到可以处理这些请求的服务上去
[√] Service将请求转发给应用,负责配置如何最终将处理传入请求的实际服务
[√] Middlewares中间件,用来修改请求或者根据请求来做出判断,中间件被附件到路由上,是一种在请求发送到服务之前调整请求的一种方法
Traefik Install
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
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:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
tolerations:
- operator: "Exists"
nodeSelector:
kubernetes.io/hostname: kubernetes-m
containers:
- image: traefik:v1.7.17
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
- name: admin
containerPort: 8080
args:
- --api
- --kubernetes
- --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
type: NodePort
[root@kubernetes-m mnt]# kubectl create -f pod.yaml
serviceaccount/traefik-ingress-controller created
clusterrole.rbac.authorization.k8s.io/traefik-ingress-controller created
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-controller created
deployment.apps/traefik-ingress-controller created
service/traefik-ingress-service created
[root@kubernetes-m mnt]# kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7ff77c879f-rmf7p 1/1 Running 1 8d
kube-system coredns-7ff77c879f-xsm54 1/1 Running 1 8d
kube-system etcd-kubernetes-m 1/1 Running 1 13d
kube-system kube-apiserver-kubernetes-m 1/1 Running 1 13d
kube-system kube-controller-manager-kubernetes-m 1/1 Running 1 13d
kube-system kube-flannel-ds-amd64-42lg9 1/1 Running 1 13d
kube-system kube-flannel-ds-amd64-bxr5c 1/1 Running 1 13d
kube-system kube-flannel-ds-amd64-wvr6d 1/1 Running 2 13d
kube-system kube-proxy-89plc 1/1 Running 1 13d
kube-system kube-proxy-9554v 1/1 Running 1 13d
kube-system kube-proxy-n4mrg 1/1 Running 1 13d
kube-system kube-scheduler-kubernetes-m 1/1 Running 1 13d
kube-system traefik-ingress-controller-56b7f444f9-4gpgq 1/1 Running 0 4s
[root@kubernetes-m mnt]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 100.1.0.1 <none> 443/TCP 13d
kube-system kube-dns ClusterIP 100.1.0.10 <none> 53/UDP,53/TCP,9153/TCP 13d
kube-system traefik-ingress-service NodePort 100.1.56.142 <none> 80:31209/TCP,8080:31021/TCP 15s
Ingress 对象
现在我们是通过 NodePort 来访问 traefik 的 Dashboard 的,那怎样通过 ingress 来访问呢? 首先,需要创建一个 ingress 对象:(ingress.yaml)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: traefik.duxt.com
http:
paths:
- backend:
serviceName: traefik-ingress-service
servicePort: 8080
要注意上面的 ingress 对象的规则,特别是 rules 区域,我们这里是要为 traefik 的 dashboard 建立一个 ingress 对象,所以这里的 serviceName 对应的是上面我们创建的 traefik-ingress-service,端口也要注意对应 8080 端口,为了避免端口更改,这里的 servicePort 的值也可以替换成上面定义的 port 的名字:admin
创建完成后,我们应该怎么来测试呢?
第一步,在本地的/etc/hosts里面添加上 traefik.duxt.com 与 master 节点外网 IP 的映射关系
第二步,在浏览器中访问:http://traefik.haimaxy.com 我们会发现并没有得到我们期望的 dashboard 界面,这是因为我们上面部署 traefik 的时候使用的是 NodePort 这种 Service 对象,所以我们只能通过上面的 31021 端口访问到我们的目标对象:
http://traefik.duxt.com:31021/dashboard/
加上端口后我们发现可以访问到 dashboard 了,而且在 dashboard 当中多了一条记录,正是上面我们创建的 ingress 对象的数据,我们还可以切换到 HEALTH 界面中,可以查看当前 traefik 代理的服务的整体的健康状态
第三步,上面我们可以通过自定义域名加上端口可以访问我们的服务了,但是我们平时服务别人的服务是不是都是直接用的域名啊,http 或者 https 的,几乎很少有在域名后面加上端口访问的吧?为什么?太麻烦啊,端口也记不住,要解决这个问题,怎么办,我们只需要把我们上面的 traefik 的核心应用的端口隐射到 master 节点上的 80 端口,是不是就可以了,因为 http 默认就是访问 80 端口,但是我们在 Service 里面是添加的一个 NodePort 类型的服务,没办法映射 80 端口,怎么办?这里就可以直接在 Pod 中指定一个 hostPort 即可,更改上面的 traefik.yaml 文件中的容器端口:
containers:
- image: traefik
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8080
添加以后hostPort: 80,然后更新应用:
[root@kubernetes-m mnt]# kubectl apply -f traefik-ingress.yaml
ingress.extensions/traefik-web-ui created
第四步,正常来说,我们如果有自己的域名,我们可以将我们的域名添加一条 DNS 记录,解析到 master 的外网 IP 上面,这样任何人都可以通过域名来访问我的暴露的服务了。
如果你有多个边缘节点的话,可以在每个边缘节点上部署一个 ingress-controller 服务,然后在边缘节点前面挂一个负载均衡器,比如 nginx,将所有的边缘节点均作为这个负载均衡器的后端,这样就可以实现 ingress-controller 的高可用和负载均衡了。
到这里我们就通过 ingress 对象对外成功暴露了一个服务