traefik ingress反向代理部署
Traefik介绍
Traefik是一个现代HTTP反向代理和负载均衡器,可以轻松部署微服务。Traefik与您现有的基础架构组件(Docker,Swarm模式,Kubernetes,Marathon,Consul,Etcd,Rancher,Amazon ECS ……)集成,并自动和动态地配置自身。在您的协调器上指向Traefik应该是您需要的唯一配置步骤。同 nginx 等相比,traefik 能够自动感知后端容器变化,从而实现自动服务发现。

功能
- 不断更新其配置(无重启!)
- 支持多种负载均衡算法
- 利用Let’s Encrypt(通配符证书支持)为您的微服务提供HTTPS
- 断路器,重试
- Websocket,HTTP / 2,GRPC
- 提供指标(Rest,Prometheus,Datadog,Statsd,InfluxDB)
- Keeps access logs (JSON, CLF)
- Exposes a Rest API
原理
虽然k8s集群内部署的pod、server都有自己的IP,但是却无法提供外网访问,以前我们可以通过监听NodePort的方式暴露服务,但是这种方式并不灵活,生产环境也不建议使用。Ingresss是k8s集群中的一个API资源对象,扮演边缘路由器(edge router)的角色,也可以理解为集群防火墙、集群网关,我们可以自定义路由规则来转发、管理、暴露服务(一组pod),非常灵活,生产环境建议使用这种方式。另外LoadBlancer也可以暴露服务,不过这种方式需要向云平台申请负载均衡器。
特性配置
traefik支持强大的annotations配置,需要添加到kubernetes相应资源对象的annotations下面。至于具体配置到的哪个对象,先弄清楚三个概念:
- EntryPoint(入口点)
顾名思义,这是外部网络进入traefik的入口,我们上面就是通过监听主机端口拦截请求。 - FrontEnd(前端)
traefik拦截请求后,会转发给FrontEnd。前端定义EntryPoint映射到BackEnd的路由规则集,字段包括Host,Path,Headers等,匹配请求后,默认通过加权轮询负载算法路由到一个可用的BackEnd,然后进入指定的微服务,这就是服务发现。备注:这些路由规则可以来自不同的后端存储,如
Kubernetes、zookeeper、eureka、consul等,Kubernetes使用的Ingress资源对象定义路由规则集。建议大家自行去官网学习Kubernetes Ingress Backend。 - BackEnd(后端)
一组http服务集,kubernetes中对应一个service对象下的一组pod地址。对于后端的服务发现,可配置负载均衡策略、熔断器等特性。

部署Traefik
首先以 DaemonSet 的方式在每个 node 上启动一个 traefik,并使用 hostPort 的方式让其监听每个 node 的 80 、443端口
mkdir $HOME/traefik ; cd $HOME/traefik
vi Traefik-DaemonSet.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
hostNetwork: true
restartPolicy: Always
volumes:
- name: ssl
secret:
secretName: traefik-cert
- name: config
configMap:
name: traefik-conf
containers:
- image: traefik
name: traefik-ingress-lb
volumeMounts:
- mountPath: "/ssl"
name: "ssl"
- mountPath: "/config"
name: "config"
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
- name: public1
containerPort: 8888
hostPort: 8888
- name: public2
containerPort: 9999
hostPort: 9999
- name: admin
containerPort: 8080
hostPort: 8080
#securityContext:
# capabilities:
# drop:
# - ALL
# add:
# - NET_BIND_SERVICE
args:
- --configfile=/config/traefik.toml
- --web
- --web.address=:8080
- --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: 443
name: https
- protocol: TCP
port: 8080
name: admin
- protocol: TCP
port: 8888
name: public1
- protocol: TCP
port: 9999
name: public2
创建rbac文件
vi traefik-rbac.yaml
---
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
导入域名证书到集群的secret中
kubectl create secret tls traefik-cert --cert=1537424366118.pem --key=1537424366118.key
创建traefik.toml配置文件
vi traefik.toml
insecureSkipVerify = true
defaultEntryPoints = ["http","https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
regex = "^http://kubernetes.srv-slb.flybycs.com/(.*)"
replacement = "https://kubernetes.srv-slb.flybycs.com/$1"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]
[[entryPoints.https.tls.certificates]]
CertFile = "/ssl/kubernetes.srv-slb.flybycs.com.pem"
KeyFile = "/ssl/kubernetes.srv-slb.flybycs.com.key"
以configmap方式创建配置文件
kubectl create configmap traefik-conf --from-file=traefik.toml -n kube-system
启动Traefik-DaemonSet.yaml
kubectl apply -f Traefik-DaemonSet.yaml serviceaccount/traefik-ingress-controller changed daemonset.extensions/traefik-ingress-controller changed service/traefik-ingress-service changed
[root@feiba-k8s-master1-192-168-1-16 traefik]# kubectl get pod,svc -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE pod/coredns-5579c78574-dgrsp 1/1 Running 1 2d 10.96.32.2 192.168.1.17 pod/coredns-5579c78574-ss4xb 1/1 Running 1 2d 10.96.66.4 192.168.1.18 pod/coredns-5579c78574-v4bw9 1/1 Running 0 2d 10.96.66.8 192.168.1.18 pod/kubernetes-dashboard-d6cc8d98f-ngbls 1/1 Running 1 2d 10.96.66.2 192.168.1.18 pod/traefik-ingress-controller-8d4vz 1/1 Running 1 2d 10.96.66.6 192.168.1.18 pod/traefik-ingress-controller-8twpd 1/1 Running 1 2d 10.96.20.4 192.168.1.19 pod/traefik-ingress-controller-vs5nf 1/1 Running 1 2d 10.96.32.5 192.168.1.17 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/kube-dns ClusterIP 10.96.0.114 53/UDP,53/TCP 2d k8s-app=kube-dns service/kubelet ClusterIP None 10250/TCP 5d service/kubernetes-dashboard NodePort 10.96.44.102 443:31072/TCP 2d k8s-app=kubernetes-dashboard service/traefik-ingress-service ClusterIP 10.96.76.48 80/TCP,443/TCP,8080/TCP,8888/TCP,9999/TCP 2d k8s-app=traefik-ingress-lb service/traefik-web-ui ClusterIP 10.96.17.109 80/TCP 2d k8s-app=traefik-ingress-lb
其中 traefik 监听 node 的 80 和 443 端口,80 提供正常服务,8080 是其自带的 UI 界面
vi traefik-web-ui.yaml #为traefik创建ingress代理
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: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik.srv-slb.flybycs.com
http:
paths:
- path: /
backend:
serviceName: traefik-web-ui
servicePort: web
#~ kubectl create -f traefik-web-ui.yaml
测试ingress-nginx是否安装成功
将域名解析到任意node节点即可。 生产环境建议将traefik部署到kubernetes边缘节点, 并使用keepalived保证业务高可用。


部署kubernetes dashboard样例:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dashboard
namespace: kube-system
annotations:
#ingress.kubernetes.io/ssl-passthrough: "true"
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: kubernetes.srv-slb.ziji.work
http:
paths:
- path: /
backend:
serviceName: kubernetes-dashboard
servicePort: 443
#tls:
#- secretName: ziji-ui-tls-cert
kubectl apply -f kubernetes.srv-slb.ziji.work.yaml
注意: 如不使用生成默认证书, 需要手动创建、 并打开tls: – secretName参数选项
创建证书, 多个证书后面请使用–from-file指定文件路径
kubectl create secret generic ziji-ui-tls-cert --from-file=kubernetes.srv-slb.ziji.work.pem --from-file=kubernetes.srv-slb.ziji.work.key -n kube-system

延伸阅读
https://docs.traefik.io/
https://docs.traefik.io/configuration/entrypoints/
https://docs.traefik.io/user-guide/kubernetes/#disable-per-ingress