### 一、Kubernetes 服务暴露介绍
**从 kubernetes 1.2 版本开始,kubernetes提供了 Ingress 对象来实现对外暴露服务;到目前为止 kubernetes 总共有三种暴露服务的方式:**
* LoadBlancer Service
* NodePort Service
* Ingress
#### 1.1、LoadBlancer Service
LoadBlancer Service 是 kubernetes 深度结合云平台的一个组件;当使用 LoadBlancer Service 暴露服务时,实际上是通过向底层云平台申请创建一个负载均衡器来向外暴露服务;目前 LoadBlancer Service 支持的云平台已经相对完善,比如国外的 GCE、DigitalOcean,国内的 阿里云,私有云 Openstack 等等,由于 LoadBlancer Service 深度结合了云平台,所以只能在一些云平台上来使用
#### 1.2、NodePort Service
NodePort Service 顾名思义,实质上就是通过在集群的每个 node 上暴露一个端口,然后将这个端口映射到某个具体的 service 来实现的,虽然每个 node 的端口有很多(0~65535),但是由于安全性和易用性(服务多了就乱了,还有端口冲突问题)实际使用可能并不多
#### 1.3、Ingress
Ingress 这个东西是 1.2 后才出现的,通过 Ingress 用户可以实现使用 nginx 等开源的反向代理负载均衡器实现对外暴露服务,以下详细说一下 Ingress,毕竟 traefik 用的就是 Ingress
**使用 Ingress 时一般会有三个组件:**
* 反向代理负载均衡器
* Ingress Controller
* Ingress
#### 1.3.1、反向代理负载均衡器
反向代理负载均衡器很简单,说白了就是 nginx、apache 什么的;在集群中反向代理负载均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等,不过个人喜欢以 DaemonSet 的方式部署,感觉比较方便
#### 1.3.2、Ingress Controller
Ingress Controller 实质上可以理解为是个监视器,Ingress Controller 通过不断地跟 kubernetes API 打交道,实时的感知后端 service、pod 等变化,比如新增和减少 pod,service 增加与减少等;当得到这些变化信息后,Ingress Controller 再结合下文的 Ingress 生成配置,然后更新反向代理负载均衡器,并刷新其配置,达到服务发现的作用
#### 1.3.3、Ingress
Ingress 简单理解就是个规则定义;比如说某个域名对应某个 service,即当某个域名的请求进来时转发给某个 service;这个规则将与 Ingress Controller 结合,然后 Ingress Controller 将其动态写入到负载均衡器配置中,从而实现整体的服务发现和负载均衡
懵逼就看图
![](https://box.kancloud.cn/f1e6822e2085eff60a572c7dc1a9621b_1598x898.jpg)
从上图中可以很清晰的看到,实际上请求进来还是被负载均衡器拦截,比如 nginx,然后 Ingress Controller 通过跟 Ingress 交互得知某个域名对应哪个 service,再通过跟 kubernetes API 交互得知 service 地址等信息;综合以后生成配置文件实时写入负载均衡器,然后负载均衡器 reload 该规则便可实现服务发现,即动态映射
了解了以上内容以后,这也就很好的说明了我为什么喜欢把负载均衡器部署为 Daemon Set;因为无论如何请求首先是被负载均衡器拦截的,所以在每个 node 上都部署一下,同时 hostport 方式监听 80 端口;那么就解决了其他方式部署不确定 负载均衡器在哪的问题,同时访问每个 node 的 80 都能正确解析请求;如果前端再 放个 nginx 就又实现了一层负载均衡
### 二、Traefik 使用
由于微服务架构以及 Docker 技术和 kubernetes 编排工具最近几年才开始逐渐流行,所以一开始的反向代理服务器比如 nginx、apache 并未提供其支持,毕竟他们也不是先知;所以才会出现 Ingress Controller 这种东西来做 kubernetes 和前端负载均衡器如 nginx 之间做衔接;即 Ingress Controller 的存在就是为了能跟 kubernetes 交互,又能写 nginx 配置,还能 reload 它,这是一种折中方案;而最近开始出现的 traefik 天生就是提供了对 kubernetes 的支持,也就是说 traefik 本身就能跟 kubernetes API 交互,感知后端变化,因此可以得知: 在使用 traefik 时,Ingress Controller 已经无卵用了,所以整体架构如下
![](https://box.kancloud.cn/0b24a2889db44efb4290d37a719f15e2_1940x1206.png)
![](https://box.kancloud.cn/0b22e31e241630adc199a31a694f1ff5_1818x888.jpg)
从上图可以看出,在我们日常业务开发中,我们会部署一系列微服务,外部网络要通过 domain、path、负载均衡等转发到后端私有网络中,微服务之所以称为微,是因为它是动态变化的,它会经常被增加、删除、干掉或者被更新。而且传统的反向代理对服务动态变化的支持不是很方便,也就是服务变更后,我们不是很容易立马改变配置和热加载。traefik 的出现就是为了解决这个问题,它可以时刻监听服务注册或服务编排 API,随时感知后端服务变化,自动重新更改配置并热重新加载,期间服务不会暂停或停止,这对于用户来说是无感知的。
Traefik 还有很多特性如下:
* 速度快
* 不需要安装其他依赖,使用 GO 语言编译可执行文件
* 支持最小化官方 Docker 镜像
* 支持多种后台,如 Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS 等等
* 支持 REST API
* 配置文件热重载,不需要重启进程
* 支持自动熔断功能
* 支持轮训、负载均衡
* 提供简洁的 UI 界面
* 支持 Websocket, HTTP/2, GRPC
* 自动更新 HTTPS 证书
* 支持高可用集群模式
### 2.1、部署 Traefik
#### 2.1.1、部署 Daemon Set
首先以 Daemon Set 的方式在每个 node 上启动一个 traefik,并使用 hostPort 的方式让其监听每个 node 的 80 端口(有没有感觉这就是个 NodePort? 不过区别就是这个 Port 后面有负载均衡器 )
```
cd /mnt
git clone https://github.com/containous/traefik.git
ls
-rw-r--r--. 1 root root 1805 11月 9 16:23 cheese-deployments.yaml
-rw-r--r--. 1 root root 1805 11月 9 16:23 cheese-default-ingress.yaml
-rw-r--r--. 1 root root 519 11月 9 16:23 cheese-ingress.yaml
-rw-r--r--. 1 root root 509 11月 9 16:23 cheese-services.yaml
-rw-r--r--. 1 root root 504 11月 9 16:23 cheeses-ingress.yaml
-rw-r--r--. 1 root root 978 11月 9 16:23 traefik-deployment.yaml
-rw-r--r--. 1 root root 1128 11月 9 16:23 traefik-ds.yaml
-rw-r--r--. 1 root root 694 11月 9 16:23 traefik-rbac.yaml
-rw-r--r--. 1 root root 466 11月 9 16:43 ui.yaml
```
* 官网一共给出了九个yaml文件,这里我们只需要最下面4个配置文件,
* traefik-deployment.yaml ------以deployment方式部署traefik
* traefik-ds.yaml----------以Daemon set 方式部署traefik
* traefik-rbac.yaml---------rbac授权
* ui.yaml------web-ui 的配置文件
以deployment和deamon方式部署,只需要选取一个配置文件
官网给出的配置文件可能会有端口冲突,这里我修改了以下
```
[root@localhost tk]# cat Depeloyment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: traefik-ingress-lb
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
hostNetwork: true
restartPolicy: Always
serviceAccountName: ingress
containers:
- image: traefik
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8580
hostPort: 8580
args:
- --web
- --web.address=:8580
- --kubernetes
```
```
[root@localhost tk]# cat ingress-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ingress
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: ingress
subjects:
- kind: ServiceAccount
name: ingress
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
```
```
[root@localhost tk]# cat Traefik-ui.yaml
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- name: web
port: 80
targetPort: 8580
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik-ui.local
http:
paths:
- path: /
backend:
serviceName: traefik-web-ui
servicePort: web
```
下面我们来部署这个三个程序
```
kubectl create -f .
[root@localhost tk]# kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
default aa-tqv77 1/1 Running 54 6d
default frontend-7mfsh 1/1 Running 3 10d
default frontend-m8fkw 1/1 Running 3 10d
default frontend-x4tzj 1/1 Running 3 10d
default mc-deployment-2805008544-bn05x 1/1 Running 57 6d
default my-nginx-543887649-4gh28 1/1 Running 17 29d
default my-nginx-543887649-lxxcw 1/1 Running 17 29d
default my-nginx-pod-2945913857-88lml 1/1 Running 17 29d
default my-nginx-pod-2945913857-nwrlv 1/1 Running 17 29d
default redis-master-r04fz 1/1 Running 3 10d
default redis-slave-w3zr1 1/1 Running 3 10d
default redis-slave-xq3pf 1/1 Running 3 10d
kube-system heapster-2315332064-xhtf5 1/1 Running 11 19d
kube-system kube-dns-3574069718-19d9v 3/3 Running 42 5d
kube-system kubernetes-dashboard-1211493743-c6pzc 1/1 Running 577 32d
kube-system monitoring-grafana-3319647107-7zrrw 1/1 Running 10 19d
kube-system monitoring-influxdb-3480804314-0d7dd 1/1 Running 12 19d
kube-system traefik-ingress-lb-4237248072-xtfpd 1/1 Running 0 1h
monitoring alertmanager-1970416631-psl30 1/1 Running 8 16d
monitoring grafana-core-83531447-8dc8d 1/1 Running 8 16d
monitoring grafana-import-dashboards-cj7l2 0/1 ImagePullBackOff 0 15d
monitoring kube-state-metrics-2949788559-m707v 1/1 Running 168 16d
monitoring kube-state-metrics-2949788559-qm500 1/1 Running 168 16d
monitoring node-directory-size-metrics-6c8vn 2/2 Running 16 16d
monitoring prometheus-core-3718210518-plh5b 1/1 Running 8 16d
monitoring prometheus-node-exporter-hx204 1/1 Running 8 16d
[root@localhost tk]# kubectl get svc --all-namespaces
NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default aa 10.254.110.166 <nodes> 8081:30002/TCP 6d
default frontend 10.254.198.99 <nodes> 80:30001/TCP 10d
default kubernetes 10.254.0.1 <none> 443/TCP 41d
default mc 10.254.226.32 <nodes> 8081:30008/TCP 6d
default my-nginx 10.254.78.8 <none> 80/TCP 29d
default redis-master 10.254.211.158 <none> 6379/TCP 10d
default redis-slave 10.254.160.65 <none> 6379/TCP 10d
kube-system heapster 10.254.108.150 <none> 80/TCP 19d
kube-system kube-dns 10.254.0.2 <none> 53/UDP,53/TCP 5d
kube-system kubernetes-dashboard 10.254.31.8 <nodes> 80:30946/TCP 32d
kube-system monitoring-grafana 10.254.195.244 <none> 80/TCP 19d
kube-system monitoring-influxdb 10.254.81.32 <none> 8086/TCP 19d
kube-system traefik-web-ui 10.254.169.196 <none> 80/TCP 1h
monitoring alertmanager 10.254.35.245 <nodes> 9093:32006/TCP 16d
monitoring grafana 10.254.125.218 <nodes> 3000:30474/TCP 16d
monitoring kube-state-metrics 10.254.67.171 <none> 8080/TCP 16d
monitoring prometheus 10.254.158.209 <nodes> 9090:31023/TCP 16d
monitoring prometheus-node-exporter None <none> 9100/TCP 16d
[root@localhost tk]# kubectl get endpoints --all-namespaces
NAMESPACE NAME ENDPOINTS AGE
default aa 172.30.72.18:8081 6d
default frontend 172.30.72.14:80,172.30.72.17:80,172.30.72.9:80 10d
default kubernetes 172.16.168.129:6443 41d
default mc <none> 6d
default my-nginx 172.30.72.20:80,172.30.72.23:80 29d
default redis-master 172.30.72.22:6379 10d
default redis-slave 172.30.72.21:6379,172.30.72.24:6379 10d
kube-system heapster 172.30.72.4:8082 19d
kube-system kube-controller-manager <none> 15h
kube-system kube-dns 172.30.72.6:53,172.30.72.6:53 5d
kube-system kube-scheduler <none> 15h
kube-system kubernetes-dashboard 172.30.72.8:9090 32d
kube-system monitoring-grafana 172.30.72.16:3000 19d
kube-system monitoring-influxdb 172.30.72.11:8086 19d
kube-system traefik-web-ui 172.16.168.129:8580 1h
monitoring alertmanager 172.30.72.10:9093 16d
monitoring grafana 172.30.72.15:3000 16d
monitoring kube-state-metrics 172.30.72.13:8080,172.30.72.7:8080 16d
monitoring prometheus 172.30.72.5:9090 16d
monitoring prometheus-node-exporter 172.16.168.129:9100 16d
```
下面我们做测试,看我们后端的服务是否可以通过dns服务发现,被ingress负载到
由于我之前在集群中部署过redis-frontend的留言版程序,还有nginx程序,这里就直接
创建ingress的yaml文件
```
[root@localhost tk]# cat frontend.ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-ingress
spec:
rules:
- host: traefik.nginx.io
http:
paths:
- path: /
backend:
serviceName: my-nginx
servicePort: 80
- host: traefik.frontend.io
http:
paths:
- path: /
backend:
serviceName: frontend
servicePort: 80
```
注意,server一定要写对应的服务,serviceport就写服务原始自带的端口,比如nginx就是80端口。
```
kubectl create -f frontend.ingress.yaml
kubectl get ingress --all-namespaces
NAMESPACE NAME HOSTS ADDRESS PORTS AGE
default traefik-ingress traefik.nginx.io,traefik.frontend.io 80 1h
kube-system traefik-web-ui traefik-ui.local 80 1h
```
上图可以看到,我们创建的ingress都创建成功了。
我们现在可以通过域名访问我们的服务了
访问之前一定要把host记录编辑好,这里的主机可以填写任意的node节点
·```
172.16.168.129 traefik.frontend.io
172.16.168.129 traefik.nginx.io
```
![](https://box.kancloud.cn/4c3495439c424cbbcdf5419fd0bb7d1a_2162x1796.png)
![](https://box.kancloud.cn/a609453b7b2995bdf4b71b545dbc5e4f_2028x1646.png)
![](https://box.kancloud.cn/5154b724079e9499b121634e7809096e_2124x1094.png)