一、概述
traefik
与 nginx
一样,是一款优秀的反向代理工具,或者叫 Edge Router
。至于使用它的原因则基于以下几点
- 无须重启即可更新配置
- 自动的服务发现与负载均衡
- 与
docker
的完美集成,基于container label
的配置 - 漂亮的
dashboard
界面 metrics
的支持,对prometheus
和k8s
的集成
接下来讲一下它的安装,基本功能以及配置。traefik
在 v1
与 v2
版本间差异过大,本篇文章采用了 v2
traefik官方文档:https://docs.traefik.io/
注意:Traefikv2.0之后的版本在修改了很多bug之后也增加了新的特性,比如增加了TCP的支持,并且更换了新的WEB UI界面
二、快速开始
环境介绍
操作系统:centos7.6
数量:1台
docker版本:19.03.6
docker版本:1.24.1
ip地址:192.168.28.218
docker-compose启动
新建yaml文件
vi traefik-v2.1.yaml
内容如下:
version: '3' services:reverse-proxy:image: traefik:2.1.6# Enables the web UI and tells Traefik to listen to docker# 启用webUI 并告诉Traefile去监听docker的容器实例command: --api.insecure=true --providers.dockerports:# traefik暴露的http端口- "80:80"# webUI暴露的端口(必须制定--api.insecure=true才可以访问)- "8080:8080"volumes:# 指定docker的sock文件来让traefik获取docker的事件,从而实现动态负载均衡- /var/run/docker.sock:/var/run/docker.sock
使用docker-compose创建集群
# docker-compose -f traefik-v2.1.yaml up -d reverse-proxy Creating network "opt_default" with the default driver Creating opt_reverse-proxy_1 ... done
查看使用docker-compose启动的应用
# docker-compose -f traefik-v2.1.yaml psName Command State Ports --------------------------------------------------------------------------------------------------------- opt_reverse-proxy_1 /entrypoint.sh --api.insec ... Up 0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp
直接访问traefik对外暴露的http接口
curl -s "http://localhost:8080/api/rawdata" | python -m json.tool
输出如下:
{"middlewares": {"dashboard_redirect@internal": {"redirectRegex": {"permanent": true,"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$","replacement": "${1}/dashboard/"},"status": "enabled","usedBy": ["dashboard@internal"]},"dashboard_stripprefix@internal": {"status": "enabled","stripPrefix": {"prefixes": ["/dashboard/","/dashboard"]},"usedBy": ["dashboard@internal"]}},"routers": {"api@internal": {"entryPoints": ["traefik"],"priority": 2147483646,"rule": "PathPrefix(`/api`)","service": "api@internal","status": "enabled","using": ["traefik"]},"dashboard@internal": {"entryPoints": ["traefik"],"middlewares": ["dashboard_redirect@internal","dashboard_stripprefix@internal"],"priority": 2147483645,"rule": "PathPrefix(`/`)","service": "dashboard@internal","status": "enabled","using": ["traefik"]},"reverse-proxy-opt@docker": {"rule": "Host(`reverse-proxy-opt`)","service": "reverse-proxy-opt","status": "enabled","using": ["http","traefik"]}},"services": {"api@internal": {"status": "enabled","usedBy": ["api@internal"]},"dashboard@internal": {"status": "enabled","usedBy": ["dashboard@internal"]},"reverse-proxy-opt@docker": {"loadBalancer": {"passHostHeader": true,"servers": [{"url": "http://172.18.0.2:80"}]},"serverStatus": {"http://172.18.0.2:80": "UP"},"status": "enabled","usedBy": ["reverse-proxy-opt@docker"]}} }
查看Traefik官方Dashboard
http://192.168.28.218:8080/
效果如下:
三、创建一个路由
Traefik来检测新服务并为你创建一个路由
创建一个新服务
vi test-service.yaml
内容如下:
version: '3' services:whoami:image: containous/whoamilabels:- "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
创建服务
# docker-compose -f test-service.yaml up -d whoami WARNING: Found orphan containers (opt_reverse-proxy_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. Creating opt_whoami_1 ... done
查看新创建的服务
# docker-compose -f test-service.yaml psName Command State Ports --------------------------------------- opt_whoami_1 /whoami Up 80/tcp
再次查看traefik中的路由信息(就会发现服务自动加载进去了)
其实有点儿类似kong 的路由,只是traefik会自动监听docker的事件
curl -s "http://localhost:8080/api/rawdata" | python -m json.tool
输出如下:
{"middlewares": {"dashboard_redirect@internal": {"redirectRegex": {"permanent": true,"regex": "^(http:\\/\\/[^:\\/]+(:\\d+)?)\\/$","replacement": "${1}/dashboard/"},"status": "enabled","usedBy": ["dashboard@internal"]},"dashboard_stripprefix@internal": {"status": "enabled","stripPrefix": {"prefixes": ["/dashboard/","/dashboard"]},"usedBy": ["dashboard@internal"]}},"routers": {"api@internal": {"entryPoints": ["traefik"],"priority": 2147483646,"rule": "PathPrefix(`/api`)","service": "api@internal","status": "enabled","using": ["traefik"]},"dashboard@internal": {"entryPoints": ["traefik"],"middlewares": ["dashboard_redirect@internal","dashboard_stripprefix@internal"],"priority": 2147483645,"rule": "PathPrefix(`/`)","service": "dashboard@internal","status": "enabled","using": ["traefik"]},"reverse-proxy-opt@docker": {"rule": "Host(`reverse-proxy-opt`)","service": "reverse-proxy-opt","status": "enabled","using": ["http","traefik"]},"whoami@docker": {"rule": "Host(`whoami.docker.localhost`)","service": "whoami-opt","status": "enabled","using": ["http","traefik"]}},"services": {"api@internal": {"status": "enabled","usedBy": ["api@internal"]},"dashboard@internal": {"status": "enabled","usedBy": ["dashboard@internal"]},"reverse-proxy-opt@docker": {"loadBalancer": {"passHostHeader": true,"servers": [{"url": "http://172.19.0.2:80"}]},"serverStatus": {"http://172.19.0.2:80": "UP"},"status": "enabled","usedBy": ["reverse-proxy-opt@docker"]},"whoami-opt@docker": {"loadBalancer": {"passHostHeader": true,"servers": [{"url": "http://172.19.0.3:80"}]},"serverStatus": {"http://172.19.0.3:80": "UP"},"status": "enabled","usedBy": ["whoami@docker"]}} }
查看http反向代理记录
查看Traefik中的http反向代理记录,点击HTTP
测试traefik相关功能
测试访问
# curl -H Host:whoami.docker.localhost http://localhost Hostname: c334de4bc3c8 IP: 127.0.0.1 IP: 172.19.0.3 RemoteAddr: 172.19.0.2:57632 GET / HTTP/1.1 Host: whoami.docker.localhost User-Agent: curl/7.29.0 Accept: */* Accept-Encoding: gzip X-Forwarded-For: 172.19.0.1 X-Forwarded-Host: whoami.docker.localhost X-Forwarded-Port: 80 X-Forwarded-Proto: http X-Forwarded-Server: 1ee8d25b3aac X-Real-Ip: 172.19.0.1
单机扩容
# docker-compose -f test-service.yaml up -d --scale whoami=2 WARNING: Found orphan containers (opt_reverse-proxy_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. Starting opt_whoami_1 ... done Creating opt_whoami_2 ... done
再次访问(就会发现自动负载到两个不同的实例上去了)
# curl -H Host:whoami.docker.localhost http://localhost Hostname: c334de4bc3c8 IP: 127.0.0.1 IP: 172.19.0.3 RemoteAddr: 172.19.0.2:57632 GET / HTTP/1.1 Host: whoami.docker.localhost User-Agent: curl/7.29.0 Accept: */* Accept-Encoding: gzip X-Forwarded-For: 172.19.0.1 X-Forwarded-Host: whoami.docker.localhost X-Forwarded-Port: 80 X-Forwarded-Proto: http X-Forwarded-Server: 1ee8d25b3aac X-Real-Ip: 172.19.0.1
查看Traefike后端每个service的详情信息:
就会看到2个service
四、Traefik配置介绍
traefik配置结构图
在traefik中的配置,会涉及到两方面内容:
- 动态的路由配置(即由k8s-api或docker相关api来自动发现服务的endpoint而进行路由的配置描述)
- 静态的启动配置(即traefik标准的启动配置参数)
注意:使用docker run traefik[:version] --help可查看traefik的配置参数
五、k8s部署Traefik
环境介绍
操作系统 | ip | 主机名 | 配置 | 备注 |
centos 7.6 | 192.168.31.150 | k8s-master | 2核4G | Kubernetes1.16.3 |
centos 7.6 | 192.168.31.178 | k8s-node01 | 2核8G | Kubernetes1.16.3 |
yaml文件介绍
mkdir /opt/traefik
目录结构如下:
./ ├── traefik-config.yaml ├── traefik-ds-v2.1.6.yaml ├── traefik-rbac.yaml └── ui.yaml
traefik-config.yaml
apiVersion: v1 kind: ConfigMap metadata:name: traefik-confignamespace: kube-system data:traefik.toml: |defaultEntryPoints = ["http","https"]debug = falselogLevel = "INFO"# Do not verify backend certificates (use https backends)InsecureSkipVerify = true[entryPoints][entryPoints.http]address = ":80"compress = true[entryPoints.https]address = ":443"[entryPoints.https.tls]#Config to redirect http to https#[entryPoints]# [entryPoints.http]# address = ":80"# compress = true# [entryPoints.http.redirect]# entryPoint = "https"# [entryPoints.https]# address = ":443"# [entryPoints.https.tls][web]address = ":8080"[kubernetes][metrics][metrics.prometheus]buckets=[0.1,0.3,1.2,5.0]entryPoint = "traefik"[ping]entryPoint = "http"
traefik-ds-v2.1.6.yaml
--- apiVersion: v1 kind: ServiceAccount metadata:name: traefik-ingress-controllernamespace: kube-system --- kind: DaemonSet apiVersion: apps/v1 #apiVersion: extensions/v1beta1 metadata:name: traefik-ingress-controller-v2namespace: kube-systemlabels:k8s-app: traefik-ingress-lb spec:selector:matchLabels:name: traefik-ingress-lb-v2template:metadata:labels:k8s-app: traefik-ingress-lbname: traefik-ingress-lb-v2spec:serviceAccountName: traefik-ingress-controllerterminationGracePeriodSeconds: 60containers:- image: traefik:2.1.6name: traefik-ingress-lb-v2ports:- name: httpcontainerPort: 80hostPort: 80- name: admincontainerPort: 8080hostPort: 8080securityContext:capabilities:drop:- ALLadd:- NET_BIND_SERVICEargs:- --api- --api.insecure=true- --providers.kubernetesingress=true- --log.level=INFO#- --configfile=/config/traefik.toml#volumeMounts:#- mountPath: /config# name: configvolumes:- configMap:name: traefik-configname: config --- kind: Service apiVersion: v1 metadata:name: traefik-ingress-service-v2namespace: kube-systemlabels:k8s-app: traefik-ingress-lb-v2 spec:selector:k8s-app: traefik-ingress-lb-v2ports:- protocol: TCPport: 80name: web- protocol: TCPport: 8080name: admin
traefik-rbac.yaml
--- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata:name: traefik-ingress-controller rules:- apiGroups:- ""resources:- services- endpoints- secretsverbs:- get- list- watch- apiGroups:- extensionsresources:- ingressesverbs:- get- list- watch- apiGroups:- extensionsresources:- ingresses/statusverbs:- update --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata:name: traefik-ingress-controller roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: traefik-ingress-controller subjects: - kind: ServiceAccountname: traefik-ingress-controllernamespace: kube-system
ui.yaml
--- apiVersion: v1 kind: Service metadata:name: traefik-web-uinamespace: kube-system spec:selector:k8s-app: traefik-ingress-lbports:- name: webport: 80targetPort: 8080 --- apiVersion: extensions/v1beta1 kind: Ingress metadata:name: traefik-web-uinamespace: kube-system spec:rules:- host: prod-traefik-ui.bgbiao.cnhttp:paths:- path: /backend:serviceName: traefik-web-uiservicePort: web
部署
cd /opt/traefik
kubectl apply -f .
查看pod
# kubectl get pods -n kube-system | grep traefik traefik-ingress-controller-v2-hz82b 1/1 Running 0 8m4s
查看svc
# kubectl get svc -n kube-system | grep traefik traefik-ingress-service-v2 ClusterIP 10.1.188.71 <none> 80/TCP,8080/TCP 8m56s traefik-web-ui ClusterIP 10.1.239.107 <none> 80/TCP 46m
查看ingresses
# kubectl get ingresses.extensions -n kube-system NAME HOSTS ADDRESS PORTS AGE traefik-web-ui prod-traefik-ui.bgbiao.cn 80 48m
查看traefik的dashboard
域名访问
由于没有dns服务器,这里直接修改hosts来测试。windows 10添加一条hosts记录
192.168.31.178 prod-traefik-ui.bgbiao.cn
注意:这里的192.168.31.178是node节点ip
效果如下:
ip方式
直接通过node ip+8080方式,比如:
http://192.168.31.178:8080
效果同上!
点击http
查看 http service
效果如下:
注意:虽然traefikv2.x改动了很多,但是还是向下兼容一些内容的,比如我重新创建traefik-v2.0.1之后,之前创建的ingress规则会自动导入
本文参考链接:
https://www.jianshu.com/p/0fc6df85d00d
https://zhuanlan.zhihu.com/p/97420459