Skip to content

Traefik2.2安装

Traefik 2.2 新增的功能如下

  1. 支持了 udp

  2. traefik2.2 支持使用 K/V 存储做为动态配置的源,分别是 consul, etcd, Redis, zookeeper

  3. 能够使用 kubernetes CRD 自定义资源定义 UDP 负载平衡 IngressRouteUDP

  4. 能够使用 rancherconsul catalogdockermarathon中的标签定义 UDP 的负载平衡

  5. 增加了对 ingress 注解的主持

  6. 将 TLS 存储功能 TLSStores添加到 Kubernetes CRD 中,使 kubernetes 用户无需使用配置文件和安装证书即可提供默认证书。

  7. 在日志中增加了 http 的请求方式,是 http 还是 https

  8. 因为 TLS 的配置可能会影响 CPU 的使用率,因此增加了 TLS versionTLS cipher使用的指标信息

  9. 当前的 WRR 算法对于权重不平衡端点存在严重的偏差问题,将 EDF 调度算法用于 WeightedRoundRobin, Envoy也是使用了 EOF调度算法

  10. 支持请求主体用于流量镜像

  11. 增加了 ElasticAPM作为 traefik 的 tracing 系统。

  12. Traefik 的 Dashboard 增加了 UDP 的页面

  13. Traefik 也增加了黑暗主题


下面进行安装过程。

注:我们这里是将 traefik 部署在 ingress-traefik 命名空间,如果你需要部署在其他命名空间,需要更改资源清单,如果你是部署在和我同样的命令空间中,你需要创建该命名空间。

创建命名空间:

yaml
# kubectl create ns ingress-traefik

1、创建 CRD 资源

Traefik 2.0 版本后开始使用 CRD 来对资源进行管理配置,所以我们需要先创建 CRD 资源。

traefik-crd.yaml

yaml
## 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
---
## TraefikService
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: traefikservices.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TraefikService
    plural: traefikservices
    singular: traefikservice

---
## TraefikTLSStore
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsstores.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSStore
    plural: tlsstores
    singular: tlsstore

---
## IngressRouteUDP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressrouteudps.traefik.containo.us
spec:
  scope: Namespaced
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteUDP
    plural: ingressrouteudps
    singular: ingressrouteudp

创建资源清单:

yaml
# kubectl apply -f traefik-crd.yaml
# kubectl get crd
NAME                                    CREATED AT
ingressroutes.traefik.containo.us       2019-12-13T05:40:30Z
ingressroutetcps.traefik.containo.us    2019-12-13T05:40:30Z
middlewares.traefik.containo.us         2019-12-13T05:40:30Z

2、创建 RBAC 权限

traefik-rbac.yaml

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: ingress-traefik
  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", "traefikservices"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["ingressroutetcps", "ingressrouteudps"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["traefik.containo.us"]
    resources: ["tlsoptions", "tlsstores"]
    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: ingress-traefik

创建 RBAC 资源清单:

yaml
# kubectl apply -f traefik-rbac.yaml

3、创建 traefik 配置文件

traefik-config.yaml

yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: traefik-config
  namespace: ingress-traefik
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

创建 ConfigMap:

yaml
# kubectl apply -f traefik-config.yaml

4、给节点打标签

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

节点设置 Label 标签

  • 格式:kubectl label nodes [节点名] [key=value]
yaml
kubectl label nodes 172.16.0.33 IngressProxy=true

查看节点标签:

yaml
# kubectl get nodes --show-labels
NAME          STATUS                     ROLES    AGE   VERSION   LABELS
172.16.0.33   Ready,SchedulingDisabled   master   20d   v1.15.0   IngressProxy=true,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.16.0.33,kubernetes.io/os=linux,kubernetes.io/role=master
172.16.0.52   Ready                      node     20d   v1.15.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.16.0.52,kubernetes.io/os=linux,kubernetes.io/role=node

5、部署 traefik

很多时候我们会采用 DS 方式部署,并且设置网络为 hostNetwork=True,这样方便流量进入。但是在这里我采用的是 service 的 nodeport 进行暴露。

(1)、Service 的配置清单

traefik-svc.yaml

yaml
apiVersion: v1
kind: Service
metadata:
  name: traefik
  namespace: ingress-traefik
spec:
  type: NodePort
  ports:
    - name: web
      port: 80
    - name: websecure
      port: 443
    - name: admin
      port: 8080
  selector:
    app: traefik

(2)、DS 的配置清单

traefik-ds.yaml

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: traefik-ingress-controller
  namespace: ingress-traefik
  labels:
    app: traefik
spec:
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      name: traefik
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 1
      containers:
        - image: registry.cn-hangzhou.aliyuncs.com/rookieops/traefik:v2.2.0
          name: traefik-ingress-lb
          ports:
            - name: web
              containerPort: 80
            - name: websecure
              containerPort: 443
            - 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"

3) 配置 traefik 路由规则

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

然后创建资源:

yaml
# kubectl apply -f traefik-svc.yaml
# kubectl apply -f traefik-ds.yaml
# kubectl get svc -n ingress-traefik
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                                     AGE
traefik   NodePort   10.102.225.66   <none>        80:30161/TCP,443:30629/TCP,8080:32359/TCP   31m
# kubectl get pod -n ingress-traefik
NAME                               READY   STATUS    RESTARTS   AGE
traefik-ingress-controller-whbjm   1/1     Running   0          22m


然后本地配置 hosts

yaml
10.1.10.128 traefik.coolops.cn

由于我们 ingress 是通过 svc 的 nodeport 暴露的,所以输入以下访问

dcc51e5d367d39a9c38f95c0d1ac4643 MD5

并且可以看到我配置的 HTTP

a11e2b4fe6fe1e9ef14511d303dcbeeb MD5

6、配置 SSL

这里使用 Let's Encrypt 来进行自动化 HTTPS。

修改配置文件,新增如下内容:

python
    certificatesresolvers:
      default:
        acme:
          tlsChallenge: {}
          email: "coolops@163.com"
          storage: "acme.json"

更新配置文件。

新增一个 https 的 ingressRoute,如下:

python
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-webui-tls
  namespace: ingress-traefik
spec:
  entryPoints:
  - websecure  # 注意这里是websecure这个entryPoint,监控443端口
  routes:
  - match: Host(`traefik.coolops.cn`)
    kind: Rule
    services:
    - name: traefik
      port: 8080
  tls:
    certResolver: default

查看 pod 的日志信息,报错如下:

python
{"level":"error","msg":"Unable to obtain ACME certificate for domains \"traefik.coolops.cn\": cannot get ACME client get directory at 'https://acme-v02.api.letsencrypt.org/directory': Get \"https://acme-v02.api.letsencrypt.org/directory\": dial tcp 172.65.32.248:443: connect: connection refused","providerName":"default.acme","routerName":"ingress-traefik-traefik-webui-tls-fcde00a088d29eefb3a6@kubernetescrd","rule":"Host(`traefik.coolops.cn`)","time":"2020-05-26T02:49:49Z"}

这是因为 pod 里的网络和https://acme-v02.api.letsencrypt.org/directory  不通造成的。

部署成功后可以使用 HTTPS 访问了。

f857dd210ec23ae10926de70c27b0f21 MD5

a598ed6aca0482bbaaef5f9a94b02cea MD5

上面是自动生成证书,如果有自己的域名证书,那么一切都简单了,你只需要配置一个 secret,然后在 ingressRoute 中引用即可,比如下面来自官方的例子:

python
apiVersion: v1
kind: Secret
metadata:
  name: supersecret
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=

---

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`foo.com`) && PathPrefix(`/bar`)
    kind: Rule
    services:
    - name: whoami
      port: 443
  tls:
    secretName: supersecret

用 Let's Encrypt 的话,虽然免费,用起来还是有坑,这就需要自己去踩了~~!

最近更新