首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes生态Ingress组件Traefik v2.0浅析

Kubernetes生态Ingress组件Traefik v2.0浅析

作者头像
云爬虫技术研究笔记
发布2020-02-19 10:38:12
7180
发布2020-02-19 10:38:12
举报
2020年2月5日

小编:Lateautumn4lin(逆向小小小学生)

前言

上一篇文章简单介绍了下Kubernetes生态的几个组件,这篇文章重点讲解下其中的Traefik组件,Traefik组件类似与Nginx,可以为整个集群做服务暴露、域名控制等等的作用,目前Traefik主要分为两个版本,v1.x与v2.x,这两个版本之间差距较大,让人感觉在使用不同的软件。本篇文章是以v2.x版本为基础来演示的,相关脚本代码都在Github仓库https://github.com/lateautumn4lin/KubernetesResearch里面,大家使用的时候可以切换目录到ClusterEcology/initTraefik下面。

1

Traefik v2.x升级升了哪些点

我们先来看看Traefik v2.x相对于v1.x版本有哪些新的特性以及升级了哪些旧特性。

1. 支持 SNI 路由和多协议端口的 TCP

Traefik v2.x第一个值得关注的功能就是支持SNI路由和多协议端口的 TCP,这样我们就可以在配置路由的时候指定Service的名称即可,针对与v1.x 版本只支持http(s)协议的路由,v2.x版本增加了对于TCP协议的支持,这样我们还可以把某些数据库的服务暴露出来。

下面是一个简单的示例配置 - 使用最新支持的 YAML 文件格式,将请求路由到一个数据库上面去:

tcp:
  routers:
    to-database:
      entrypoints:
      - database-entrypoint
      rule: HostSNI(`*`)
      service: database-service
  services:
    database-service:
      loadBalancer:
        servers:
        - address: xx.xx.xx.xx:xx

上面这个配置示例表示每个以 database-entrypoint 结尾的请求都将被路由到 database-service 这个服务上去。

此外通过TLS,Traefik 还可以根据 SNI 来路由 TCP 请求。在下面示例中,Traefik 就将根据 SNI 将请求路由到两个数据库:

tcp:
  routers:
    to-db-1:
      entrypoints:
      - web-secure
      rule: "HostSNI(`db1.domain`)"
      service: "db1"
      tls: {}
    to-db-2:
      entrypoints:
      - web-secure
      rule: "HostSNI(`db2.domain`)"
      service: "db2"
      tls: {}

另外 Traefik 还是支持 HTTP 和 TCP 在同一个端口上,如果你希望获得相同的入口的同时获取 HTTP 和 TCP 请求,那么 Traefik 可以很完美的来处理它。

tcp:
  routers:
    to-db-1:
      entrypoints:
      - web-secure
      rule: "HostSNI(`db1.domain`)"
      service: "db-1"
      tls: {}
http:
  routers:
    to-db1-dashboard:
      entrypoints:
      - web-secure
      rule: "Host(`dashboard.db1.domain`)"
      service: "db1-dashboard"
      tls: {}

比如上面这个示例中,dashboard.db1.domain 上的 HTTP 请求将路由到数据库的 Dashboard 服务上,而上面的 db1.domain 上的 TCP 请求将路由到数据库上面去。

2. 使用中间件完全自定义路由

在 Traefik 2.0 中还引入了中间件功能,可以用于将请求路由到目的地之前或之后来调整请求,相比于之前的单纯做服务暴露的功能,新版本无论是在软件架构设计和长远发展来看,都更偏向于Nginx的生态设计。

首先我们可以声明一个中间件,在任意数量的路由上面都可以重用它们。下面我们来演示下如何配置中间件,声明一个 BasicAuth 中间件来控制对我们服务的访问(这次使用 TOML 来配置):

# 为两个用户声明一个 basicauth 的中间件
[http.middlewares.test-auth.basicAuth]
  users = ["user1:hashed", "user2:hashed"]
# 将上面的中间件应用到路由上面去
[http.routers.my-router.to-service]
  rule = "host(`my-protected.domain`)"
  middlewares = ["test-auth"]
  service = "service1"

此外可以声明一个链来组合绑定这些中间件,并反复使用它们,对于 Kubernetes 用户来说,还可以使用 Traefik 的新 CRD 来进行更加清晰明了的配置,而不需要复杂的注解。(可以在文档中找到有关 IngressRoute 对象的更多信息。)如下所示:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test
  namespace: default
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`mydomain`)
      kind: Rule
      services:
        - name: whoami
          port: 80
      middlewares:
        - name: secured
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: secured
spec:
  chain:
    middlewares:
    - name: https-only
    - name: known-ips
    - name: auth-users
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: auth-users
spec:
  basicAuth:
    secret: secretUsers # 兼容 K8S secrets 对象
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: https-only
spec:
  redirectScheme:
    scheme: https
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: known-ips
spec:
  ipWhiteList:
    sourceRange:
    - 192.168.1.7
    - 127.0.0.1/32

上面示例中 secured 这个中间件就是有 https-only、know-ips、auth-users 这3个中间件组成的一个链式中间件。

而且在 Traefik 中内置了许多中间件:路径操作、多种身份验证机制、缓冲、断路器、重试、压缩、错误处理、headers、IP 白名单、限速、重定向等。此外官方还重新设计了代码架构,可以让开发者更加容易提供第三方的中间件。

3. 全新的 Dashboard

新版本设计了全新的 WebUI,目标是向用户一目了然地展示集群上信息,还希望显示可以启用的哪些功能特性。界面上的巨大差异也是让人感觉使用了不同的两款软件。

除了上面的几个大的特性之外,Traefik v2.0还支持了类似于金丝雀发布,流量控制的功能,感觉上算是集成了部分Service Mesh(微服务网关)的功能,更多的特性就不多介绍了,可以去看看官网文档来详细了解https://docs.traefik.io/v2.0/

2

Traefik v2.x安装实践

关于Traefik v2.x安装实践主要分为两个大部分,第一部分是安装Traefik v2.x服务,第二部分是配置好对应的服务路由。

1. Traefik v2.x服务安装

1.1 创建 CRD 资源

在 traefik v2.0 版本后,开始使用 CRD(Custom Resource Definition)来完成路由配置等,所以需要提前创建 CRD 资源。

查看具体的代码

## IngressRoute
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutes.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRoute
    plural: ingressroutes
    singular: ingressroute
---
## IngressRouteTCP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutetcps.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteTCP
    plural: ingressroutetcps
    singular: ingressroutetcp
---
## Middleware
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: middlewares.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: Middleware
    plural: middlewares
    singular: middleware
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsoptions.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSOption
    plural: tlsoptions
    singular: tlsoption

创建 Traefik CRD 资源

kubectl apply -f traefik-crd.yaml

1.2 创建 RBAC 权限

Kubernetes 在 1.6 版本中引入了基于角色的访问控制(RBAC)策略,方便对 Kubernetes 资源和 API 进行细粒度控制。Traefik 需要一定的权限,所以这里提前创建好 Traefik ServiceAccount 并分配一定的权限。

查看具体的代码

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: kube-system
  name: traefik-ingress-controller
---
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"]
  - apiGroups: ["extensions"]
    resources: ["ingresses/status"]
    verbs: ["update"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["middlewares"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["ingressroutes"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["ingressroutetcps"]
    verbs: ["get","list","watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["tlsoptions"]
    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

创建 Traefik RBAC 资源

kubectl apply -f traefik-rbac.yaml -n kube-system

1.3 创建 Traefik 配置文件

由于 Traefik 配置很多,通过 CLI 定义不是很方便,一般时候选择将其配置选项放到配置文件中,然后存入 ConfigMap,将其挂入 traefik 中。

查看具体的代码

kind: ConfigMap
apiVersion: v1
metadata:
  name: traefik-config
data:
  traefik.yaml: |-
    serversTransport:
      insecureSkipVerify: true
    api:
      insecure: true
      dashboard: true
      debug: true
    metrics:
      prometheus: ""
    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"
    providers:
      kubernetesCRD: ""
    log:
      filePath: ""
      level: error
      format: json
    accessLog:
      filePath: ""
      format: json
      bufferingSize: 0
      filters:
        retryAttempts: true
        minDuration: 20
      fields:
        defaultMode: keep
        names:
          ClientUsername: drop
        headers:
          defaultMode: keep
          names:
            User-Agent: redact
            Authorization: drop
            Content-Type: keep

创建 Traefik ConfigMap 资源

kubectl apply -f traefik-config.yaml -n kube-system

1.4 节点设置 Label 标签

由于是 Kubernetes DeamonSet 这种方式部署 Traefik,所以需要提前给节点设置 Label,这样当程序部署时 Pod 会自动调度到设置 Label 的节点上。

节点设置 Label 标签

格式:kubectl label nodes [节点名] [key=value]

kubectl label nodes k8s-node-2-12 IngressProxy=true

查看节点是否设置 Label 成功

[root@master1 initTraefik]# kubectl get nodes --show-labels
NAME      STATUS   ROLES    AGE   VERSION   LABELS
master1   Ready    master   26h   v1.17.2   IngressProxy=true,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,edgenode=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=ydzs-master,kubernetes.io/os=linux,node-role.kubernetes.io/master=

如果想删除标签,可以使用 kubectl label nodes k8s-node-2-12 IngressProxy- 命令

1.5 Kubernetes 部署 Traefik

这里还是按以前部署 Traefik 1.7 一样,用 DaemonSet 方式部署,便于在多服务器间扩展,用 hostport 方式占用服务器 80、443 端口,方便流量进入。

查看具体的代码

apiVersion: v1
kind: Service
metadata:
  name: traefik
spec:
  ports:
    - name: web
      port: 80
    - name: websecure
      port: 443
    - name: admin
      port: 8080
  selector:
    app: traefik
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: traefik-ingress-controller
  labels:
    app: traefik
spec:
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      name: traefik
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 1
      containers:
        - image: traefik:v2.0.5
          name: traefik-ingress-lb
          ports:
            - name: web
              containerPort: 80
              hostPort: 80           #hostPort方式,将端口暴露到集群节点
            - name: websecure
              containerPort: 443
              hostPort: 443          #hostPort方式,将端口暴露到集群节点
            - name: admin
              containerPort: 8080
          resources:
            limits:
              cpu: 2000m
              memory: 1024Mi
            requests:
              cpu: 1000m
              memory: 1024Mi
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
          args:
            - --configfile=/config/traefik.yaml
          volumeMounts:
            - mountPath: "/config"
              name: "config"
      volumes:
        - name: config
          configMap:
            name: traefik-config
      tolerations:              #设置容忍所有污点,防止节点被设置污点
        - operator: "Exists"
      nodeSelector:             #设置node筛选器,在特定label的节点上启动
        IngressProxy: "true"

Kubernetes 部署 Traefik

kubectl apply -f traefik-deploy.yaml -n kube-system

到此 Traefik v2.0 应用已经部署完成。

2. 服务路由配置

2.1 配置 HTTP 路由规则 (Traefik Dashboard 为例)

Traefik 应用已经部署完成,但是想让外部访问 Kubernetes 内部服务,还需要配置路由规则,这里开启了 Traefik Dashboard 配置,所以首先配置 Traefik Dashboard 看板的路由规则,使外部能够访问 Traefik Dashboard。

查看具体的代码

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard-route
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`traefik.lateautumn4lin.dashboard`)
      kind: Rule
      services:
        - name: traefik
          port: 8080

创建 Traefik Dashboard 路由规则对象

kubectl apply -f traefik-dashboard-route.yaml -n kube-system

接下来配置 Hosts,客户端想通过域名访问服务,必须要进行 DNS 解析,由于这里没有 DNS 服务器进行域名解析,所以修改 hosts 文件将 Traefik 指定节点的 IP 和自定义 host 绑定。打开电脑的 Hosts 配置文件,往其加入下面配置:

192.144.152.23  traefik.lateautumn4lin.dashboard

配置完成后,打开浏览器输入地址:http://traefik.lateautumn4lin.dashboard 打开 Traefik Dashboard。

2.2 配置 HTTPS 路由规则(Kubernetes Dashboard 为例)

这里我们创建 Kubernetes 的 Dashboard 看板,它是 Https 协议方式,由于它是需要使用 Https 请求,所以我们配置基于 Https 的路由规则并指定证书。

创建证书文件

# 创建自签名证书
$ openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=cloud.lateautumn4lin.dashboard"

# 将证书存储到 Kubernetes Secret 中
$ kubectl create secret generic cloud-mydlq-tls --from-file=tls.crt --from-file=tls.key -n kube-system

查看具体的代码

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: kubernetes-dashboard-route
spec:
  entryPoints:
    - websecure
  tls:
    secretName: cloud-mydlq-tls
  routes:
    - match: Host(`cloud.lateautumn4lin.dashboard`)
      kind: Rule
      services:
        - name: kubernetes-dashboard
          port: 443

创建 Kubernetes Dashboard 路由规则对象

kubectl apply -f kubernetes-dashboard-route.yaml -n kube-system

跟上面一样,配置 Hosts 文件

192.144.152.23  cloud.lateautumn4lin.dashboard

配置完成后,打开浏览器输入地址:https://cloud.lateautumn4lin.dashboard/ 打开 Dashboard,和我们上篇文章看到的效果相同,表示Traefik已经代理好HTTPS的请求了。

2.3 配置 TCP 路由规则(Redis 为例)

为了演示方便,我们这里只部署单节点的 Redis,对于 Redis 集群模式并不是我们这里的重点,下面是我们部署使用的资源清单文件:(redis.yaml)

查看具体的代码

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:3.2.11
        ports:
        - containerPort: 6379
          protocol: TCP

---

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis

创建 Redis服务

kubectl apply -f redis.yaml

暴露 TCP 服务

由于 Traefik 中使用 TCP 路由配置需要 SNI,而 SNI 又是依赖 TLS 的,所以我们需要配置证书才行,但是如果没有证书的话,我们可以使用通配符 * 进行配置,我们这里创建一个 IngressRouteTCP 类型的 CRD 对象(前面我们就已经安装了对应的 CRD 资源):(ingressroute-redis.yaml)

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
  name: redis
spec:
  entryPoints:
    - redis
  routes:
  - match: HostSNI(`*`)
    services:
    - name: redis
      port: 6379

创建上面的 IngressRouteTCP 对象

kubectl apply -f ingressroute-redis.yaml

创建完成后,同样我们可以去 Traefik 的 Dashboard 页面上查看是否生效:

如图可见,虽然路由导出成功,但是却提示错误,这是因为我们要把Redis 服务和IngressRouteTCP 对象部署在相同的namespace下面它们才会彼此可见,所以我们在apply创建服务的同时,可以使用-n指定namespace。

然后我们配置一个域名解析到 Traefik 所在的节点,然后通过 6379 端口来连接 Redis 服务:

$ redis-cli -h redis.lateautumn4lin.com -p 6379
redis.lateautumn4lin.com:6379> ping
PONG
redis.lateautumn4lin.com:6379> set hello world
OK
redis.lateautumn4lin.com:6379> get hello
"world"
redis.lateautumn4lin.com:6379>

到此 Traefik v2.0 服务路由配置已经部署完成。

3

更多Traefik v2.x生产实战

目前市面上的实战较少,主要还是关于Traefik v2.x的某些特性的测试案例,之后有待补充。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云爬虫技术研究笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档