# Kubernetes 1.15.2 部署 Traefik2.0

## Kubernetes 1.15.2 部署 Traefik2.0 <a href="#hkubernetes1152traefik20" id="hkubernetes1152traefik20"></a>

> Ubuntu 16.04\
> Kubernetes 1.15.2\
> Traefik 2.0\
> Kubeadm 1.15.2

`Traefik 2.0 官方文档：https://docs.traefik.io/v2.0/`

## 1.Traefik 介绍 <a href="#h1traefik" id="h1traefik"></a>

`Traefik 最新推出了 v2.0 版本，讲解下如何在 Kubernetes 环境下安装 Traefik v2.0，在 Traefik v2.0 版本后，配置 Ingress 路由规则其使用了自定义 CRD 对象来完成，并不像之前 1.x 版本使用 Kubernetes 自带的 Ingress 对象加注解方式来完成路由配置.`\
`traefik 是一款反向代理、负载均衡服务，使用 golang 实现的。和 nginx 最大的不同是，它支持自动化更新反向代理和负载均衡配置。在微服务架构越来越流行的今天，一个业务恨不得有好几个数据库、后台服务和 webapp，开发团队拥有一款 “智能” 的反向代理服务，为他们简化服务配置，是多么幸福又理所应当的事情呀。traefik 就是为了解决这个问题而诞生的。`

#### 部署 Traefik 2.0 <a href="#htraefik20-1" id="htraefik20-1"></a>

部署NameSpace: `kube-system`

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

**traefik-crd.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
```

部署 CRD 资源

```
kubectl apply -f traefik-crd.yaml
```

#### 创建 RBAC 权限 <a href="#hrbac" id="hrbac"></a>

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

**traefik-rbac.yaml**

```
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
```

#### 创建 Traefik 配置文件 <a href="#htraefik" id="htraefik"></a>

`由于 Traefik 配置很多，使用 CLI 定义操作过于繁琐，尽量使用将其配置选项放到配置文件中，然后存入 ConfigMap，将其挂入 traefik 中。`

**traefik-config.yaml**

```
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
```

#### 设置Label标签 <a href="#hlabel" id="hlabel"></a>

`由于使用的Kubernetes DeamonSet方式部署Traefik，所以需要提前给节点设置Label，当程序部署Pod会自动调度到设置 Label的node节点上。`

节点设置 Label 标签

```
kubectl label nodes k8s-node-1 IngressProxy=true
```

`验证是否成功`

```
root@k8s-m1:/data/traefik#  kubectl get nodes --show-labels
NAME        STATUS   ROLES    AGE   VERSION   LABELS
k8s-m1      Ready    master   8d    v1.15.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-m1,kubernetes.io/os=linux,node-role.kubernetes.io/master=
k8s-m2      Ready    master   8d    v1.15.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-m2,kubernetes.io/os=linux,node-role.kubernetes.io/master=
k8s-node1   Ready    <none>   8d    v1.15.2   IngressProxy=true,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2   Ready    <none>   8d    v1.15.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux
```

节点删除Label标签

```
kubectl label nodes k8s-node-1 IngressProxy-
```

#### Kubernetes 部署 Traefik <a href="#hkubernetestraefik" id="hkubernetestraefik"></a>

`按照以前Traefik1.7部署方式，使用DaemonSet类型部署，以便于在多服务器间扩展，使用 hostport 方式占用服务器 80、443 端口，方便流量进入。`

**traefik-deploy.yaml**

```
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:latest
          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"
```

部署 Traefik

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

## 3.Traefik 路由规则基础配置 <a href="#h3traefik" id="h3traefik"></a>

#### 配置 HTTP 路由规则 （Traefik Dashboard 为例） <a href="#hhttptraefikdashboard" id="hhttptraefikdashboard"></a>

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

**traefik-dashboard-route.yaml**

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

`部署Traefik Dashboard 路由规则对象`

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

`接下来配置dnsmasq，客户端想通过域名访问服务，必须要进行DNS解析，我使用的本地 DNS 服务器进行域名解析，将 Traefik 指定节点的 IP 和自定义 域名 绑定，重启dnsmasq服务即可。`\
`打开任意浏览器输入地址：http://traefik.example.cn进行访问，此处没有配置验证登录，如果想配置验证登录，使用middleware即可。`

![](/files/-Lqjiq_sOeGmS24fO9nX)

#### 配置 HTTPS 路由规则（Kubernetes Dashboard） <a href="#hhttpskubernetesdashboard" id="hhttpskubernetesdashboard"></a>

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

`创建证书文件`

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

# 将证书存储到Kubernetes Secret中，新建的k8dash-sa-tls必须与k8dash-route中的tls: secretName一致。
kubectl create secret tls k8dash-sa-tls --key=tls.key --cert=tls.crt -n kube-system
```

**k8dash-route.yaml**

```
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: k8dash-sa-route
spec:
  entryPoints:
    - websecure
  tls:
    secretName: k8dash-sa-tls
  routes:
    - match: Host(`cloud.example.cn`)
      kind: Rule
      services:
# 此处的services是Kubernetes中的svc name 与 端口 可以使用kubectl get svc --namespace=kube-system获取
        - name: k8dash-svc
          port: 80
```

部署k8dash路由规则对象

```
kubectl apply -f k8dash-route.yaml -n kube-system
```

`与Traefik Dashboard相同，配置dnsmasq服务`

```
### 获取k8dash登录token
kubectl get secrets -n kube-system |grep k8dash-sa-token|awk '{print $1}'| xargs kubectl describe secret -n kube-system
```

`打开任意浏览器输入地址：https://cloud.example.cn进行访问`

![](/files/-LqjicgVAtl6K1LWfPzQ)

![](/files/-LqjijzB7MsfxM6M76u5)

> **至此部署Traefik2.0完成.**


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.k8stech.net/kubernetes-1.15.2-bu-shu-traefik2.0.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
