一、简介

    Træfik是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。 它支持多种后台 (Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, ...) 来自动化、动态的应用它的配置文件设置。

    Træfɪk 可以监听你的服务发现、管理API,并且每当你的微服务被添加、移除、杀死或更新都会被感知,并且可以自动生成它们的配置文件,指向到你服务的路由将会被直接创建出来。

traefik.png

如上图所示,kubernetes部署了一堆service,这里我们就可以通过在kubernetes上部署Træfik监听API,使用vhosts或者前缀路径配置反代:

  • 域名api.domain.com将指向您的私有网络中微服务api

  • 路径domain.com/web将指向您的私有网络的微服务Web

  • 域名backoffice.domain.com将指向您的私有网络中的微服务backoffice,并在您的多个实例之间负载

让我们放大Træfik并查看其内部架构:

internal.png

  • 顾名思义,传入的请求在入口点结束,它们是Træfik的网络入口点(监听端口,SSL,流量重定向...)。

  • 之后流量会被转发到匹配的前端。 前端定义从入口点到后端的路由。 路由是使用请求字段(Host, Path, Headers...)创建的,可以匹配或不匹配请求。

  • 前端会将请求发送到后端。 后端可以由一台或经由负载均衡策略配置的多台服务器组成。

  • 最后,服务器会将请求转发到私有网络中相应的微服务。

详细内容请查看官方文档:

https://docs.traefik.io/

二、Kubernetes安装Træfik

1.下载Træfik的yaml文件

# wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml# wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-ds.yaml# wget https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/ui.yaml

2.更改DaemonSet文件中的端口

# cat traefik-ds.yaml ---apiVersion: v1kind: ServiceAccountmetadata:  name: traefik-ingress-controller  namespace: kube-system---kind: DaemonSetapiVersion: extensions/v1beta1metadata:  name: traefik-ingress-controller  namespace: kube-system  labels:    k8s-app: traefik-ingress-lbspec:  template:    metadata:      labels:        k8s-app: traefik-ingress-lb        name: traefik-ingress-lb    spec:      serviceAccountName: traefik-ingress-controller      terminationGracePeriodSeconds: 60      hostNetwork: true      containers:      - image: 192.168.100.100/traefik/traefik:1.6.2        name: traefik-ingress-lb        ports:        - name: http          containerPort: 80          hostPort: 80        - name: admin          containerPort: 8081        securityContext:          capabilities:            drop:            - ALL            add:            - NET_BIND_SERVICE        args:        #- --api        - --web.address=:8081        - --kubernetes        - --logLevel=INFO---kind: ServiceapiVersion: v1metadata:  name: traefik-ingress-service  namespace: kube-systemspec:  selector:    k8s-app: traefik-ingress-lb  ports:    - protocol: TCP      port: 80      name: web    - protocol: TCP      port: 8081      name: admin  type: NodePort

注:由于我的master节点同时也是node,而8080端口是kube-apiserver的端口,这产生了冲突,这里我将该端口改为8081端口。

   同时去掉- --api选项并添加- --web.address=:8081选项。

3.更改镜像为私有镜像仓库(根据情况配置)并配置Træfik Web UI域名

# sed -i "s/image: traefik/image: 192.168.100.100\/traefik\/traefik:1.6.2/g" traefik-ds.yaml# sed -i "s/traefik-ui.minikube/traefik-ui.io/g" ui.yaml

4.运行yaml文件并查看

# kubectl create -f .serviceaccount "traefik-ingress-controller" createddaemonset "traefik-ingress-controller" createdservice "traefik-ingress-service" createdclusterrole "traefik-ingress-controller" createdclusterrolebinding "traefik-ingress-controller" createdservice "traefik-web-ui" createdingress "traefik-web-ui" created# kubectl get pod -n kube-system | grep traefiktraefik-ingress-controller-sjmp2    1/1     Running   0     3dtraefik-ingress-controller-t5rgg    1/1     Running   0     3dtraefik-ingress-controller-tltvm    1/1     Running   0     3d# kubectl exec -it traefik-ingress-controller-sjmp2 -n kube-system /traefik versionVersion:      v1.6.2Codename:     tetedemoineGo version:   go1.10.2Built:        2018-05-22_03:19:06PMOS/Arch:      linux/amd64

4.登陆Træfik Web UI

# kubectl get service -n kube-system | grep traefiktraefik-ingress-service   NodePort    10.244.46.110    
        80:29484/TCP,8081:13879/TCP   3dtraefik-web-ui            ClusterIP   10.244.87.207    
        80/TCP                        3d# kubectl get ing -n kube-systemNAME             HOSTS           ADDRESS   PORTS     AGEtraefik-web-ui   traefik-ui.io             80        3d

注:

80 对应服务端口,8080 对应 UI 端口

浏览器登陆http://<node_ip>:<node_port>访问Træfik

这里我们在客户端添加相应host来访问Træfik Web UI,如:

192.168.100.103   traefik-ui.io

现在我们可以使用traefik-ui.io来登陆查看

01.PNG

5.配置访问Prometheus

# cat prom.yaml apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: grafana  namespace: monitoring       ##根据情况配置namespacespec:  rules:  - host: prom.zhi.io      ##替换为您集群默认的服务访问域名    http:      paths:      - path:         backend:          serviceName: grafana          servicePort: 3000# kubectl get ing -n monitoringNAME      HOSTS         ADDRESS   PORTS     AGEgrafana   prom.zhi.io             80        3d

查看Traefik Web UI

02.PNG

配置hosts后使用相应域名登陆Prometheus

03.PNG

三、配置Basic身份验证

1.使用htpasswd创建一个包含用户名和MD5密码文件

# yum -y install httpd# htpasswd -c auth admin       ###创建秘钥文件auth并添加用户adminNew password: Re-type new password: Adding password for user admin# cat auth admin:$apr1$h0.DZ9TF$6JN.FSka4Wdy5eUL4t1ut0

2.创建secret

# kubectl create secret generic mysecret --from-file auth --namespace=monitoringsecret "mysecret" created

3.将下面的注释附加到 Ingress对象:

  • kubernetes.io/ingress.class: traefik             ----->声明ingress后端采用traefik实现

  • ingress.kubernetes.io/auth-type: "basic"         ----->声明认证模式为basic模式

  • ingress.kubernetes.io/auth-secret: "mysecret"    ----->声明namespace里对应的secret

4.配置运行并确认

# cat prom.yaml apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: grafana  namespace: monitoring  annotations:    kubernetes.io/ingress.class: traefik    ingress.kubernetes.io/auth-type: "basic"    ingress.kubernetes.io/auth-secret: "mysecret"spec:  rules:  - host: prom.zhi.io     http:      paths:      - path:         backend:          serviceName: grafana          servicePort: 3000# kubectl apply -f prom.yaml ingress "grafana" configured

浏览器输入prom.zhi.io,弹出身份验证窗口,这里输入htpasswd命令创建的用户名和密码登录

01.PNG

输入用户名和密码并点击登录后即可进入该域名

02.PNG

四、Træfik添加TLS认证

1.使用openssl生成证书和密钥

# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=traefik-ui.io"Generating a 2048 bit RSA private key.................+++................................................................+++writing new private key to 'tls.key'-----# ls tls*tls.crt  tls.key

2.创建Secret

# kubectl -n kube-system create secret tls traefik-ui-tls-cert --key=tls.key --cert=tls.crtsecret "traefik-ui-tls-cert" created# kubectl get secret -n kube-system traefik-ui-tls-certNAME                  TYPE                DATA      AGEtraefik-ui-tls-cert   kubernetes.io/tls   2         1h

3.配置Entrypoints

Entrypoints是Træfɪk的网络入口。它们可以通过以下方式来定义:

a.一个端口 (80, 443...)

b.SSL (证书, 密钥, 由受信任的CA签名的客户端证书的身份验证...)

c.重定向到其他的入口点 (重定向 HTTP 到 HTTPS)

# cat traefik.toml defaultEntryPoints = ["http","https"]insecureskipverify = true[entryPoints]  [entryPoints.http]  address = ":80"    [entryPoints.http.redirect]      entryPoint = "https"  [entryPoints.https]  address = ":443"    [entryPoints.https.tls]      [[entryPoints.https.tls.certificates]]      CertFile = "/ssl/tls.crt"      KeyFile = "/ssl/tls.key"

注:

a.如上定义了两个入口点,http 和 https  

b.http 监听 80 端口, https 监听 443 端口

c.通过提供一个证书和一个密钥在 https 中开启SSL

d.转发所有的 http 入口点请求到 https 入口点

e.insecureSkipVerify :

  如果设置为true,则后端将接受无效的SSL证书。

  这将禁用中间人×××的检测,因此只能用于安全的后端网络。

  由于这里我希望traefik能代理Kubernetes dashboard(启用了https),所以启用了该选项

4.创建ConfigMap  

# kubectl -n kube-system create configmap traefik --from-file=traefik.tomlconfigmap "traefik" created# kubectl get configmap -n kube-system traefikNAME      DATA      AGEtraefik   1         1h# kubectl get configmap  -n kube-system traefik -o yamlapiVersion: v1data:  traefik.toml: |+    defaultEntryPoints = ["http","https"]    insecureskipverify = true    [entryPoints]      [entryPoints.http]      address = ":80"        [entryPoints.http.redirect]        entryPoint = "https"      [entryPoints.https]      address = ":443"        [entryPoints.https.tls]          [[entryPoints.https.tls.certificates]]          certFile = "/ssl/tls.crt"          keyFile = "/ssl/tls.key"kind: ConfigMapmetadata:  creationTimestamp: 2018-06-04T05:55:44Z  name: traefik  namespace: kube-system  resourceVersion: "10549957"  selfLink: /api/v1/namespaces/kube-system/configmaps/traefik  uid: eb9b845a-67bb-11e8-b7ff-000c297aff5d

5.配置DaemonSet

# cat traefik-ds.yaml ---apiVersion: v1kind: ServiceAccountmetadata:  name: traefik-ingress-controller  namespace: kube-system---kind: DaemonSetapiVersion: extensions/v1beta1metadata:  name: traefik-ingress-controller  namespace: kube-system  labels:    k8s-app: traefik-ingress-lbspec:  template:    metadata:      labels:        k8s-app: traefik-ingress-lb        name: traefik-ingress-lb    spec:      serviceAccountName: traefik-ingress-controller      terminationGracePeriodSeconds: 60      hostNetwork: true      volumes:      - name: ssl        secret:          secretName: traefik-ui-tls-cert      - name: config        configMap:          name: traefik      containers:      - image: 192.168.100.100/traefik/traefik:1.6.2        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: admin          containerPort: 8081        securityContext:          capabilities:            drop:            - ALL            add:            - NET_BIND_SERVICE        args:        #- --api        - --configfile=/config/traefik.toml        - --web.address=:8081        - --kubernetes        - --logLevel=INFO---kind: ServiceapiVersion: v1metadata:  name: traefik-ingress-service  namespace: kube-systemspec:  selector:    k8s-app: traefik-ingress-lb  ports:    - protocol: TCP      port: 80      name: web    - protocol: TCP      port: 8081      name: admin  type: NodePort# kubectl create -f traefik-ds.yaml serviceaccount "traefik-ingress-controller" createddaemonset "traefik-ingress-controller" createdservice "traefik-ingress-service" created

6.配置UI

# cat ui.yaml ---apiVersion: v1kind: Servicemetadata:  name: traefik-web-ui  namespace: kube-systemspec:  selector:    k8s-app: traefik-ingress-lb  ports:  - name: web    port: 80    targetPort: 8081---apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: traefik-web-ui  namespace: kube-system  annotations:    kubernetes.io/ingress.class: traefikspec:  rules:  - host: traefik-ui.io    http:      paths:      - path: /        backend:          serviceName: traefik-web-ui          servicePort: web  tls:   - secretName: traefik-ui-tls-cert# kubectl create -f ui.yaml service "traefik-web-ui" createdingress "traefik-web-ui" created# kubectl get ing -n kube-system traefik-web-uiNAME             HOSTS           ADDRESS   PORTS     AGEtraefik-web-ui   traefik-ui.io             80, 443   1h

7.进行测试

浏览器输入traefik-ui.io会自动跳转至https://traefik-ui.io

01.PNG

浏览器输入prom.zhi.io自动跳转至https://prom.zhi.io,输入用户名、密码即可进入

01.PNG

01.PNG

8.配置traefik代理kubernetes dashboard

a.配置并运行ingress

# cat k8s.yaml apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubernetes-dashboard  namespace: kube-system  annotations:    kubernetes.io/ingress.class: traefikspec:  rules:  - host: "k8s.zhi.io"    http:      paths:      - backend:          serviceName: kubernetes-dashboard          servicePort: 443# kubectl create -f k8s.yaml ingress "kubernetes-dashboard" created# kubectl -n kube-system get ing kubernetes-dashboardNAME                   HOSTS        ADDRESS   PORTS     AGEkubernetes-dashboard   k8s.zhi.io             80        6m

b.进行测试

01.PNG

01.PNG

01.PNG

注:

a.在配置TLS中我参考了该篇博文:

b.在配置中可参考官方文档: