traefik篇- 理论介绍、安装配置以及使用详解

    技术2022-07-11  120

    1 traefik理论概览

    https://docs.traefik.io/ https://docs.traefik.cn/user-guide/kubernetes

    假设你已经在你的基础设施上部署了一堆微服务。你可能使用了一个服务发现系统(例如 etcd 或 consul)或者一个资源管理框架(swarm,Mesos/Marathon)来管理所有这些服务。

    如果你想让你的用户去从互联网访问你的某些微服务, 你就必需使用虚拟hosts或前缀路径来配置一个反向代理:

    域名 api.domain.com 将指向你的私有网络中的微服务 api路径 domain.com/web 将指向你的私有网络中的微服务 web域名 backoffice.domain.com 将指向你的私有网络中的微服务 backoffice ,在你的多台实例之间负载均衡

    但是,微服务在会经常被添加、移除、杀死或更新,可能一天之内就会发生许多次。 传统的反向代理原生不支持动态配置。你不可能轻易的通过热更新更改它们的配置。 这时,Træfɪk就诞生了。

    2 安装配置

    https://docs.traefik.io/getting-started/install-traefik/#use-the-binary-distribution

    2.1 二进制安装

    wget https://github.com/containous/traefik/releases/download/v2.2.8/traefik_v2.2.8_linux_amd64.tar.gz tar xvfz traefik_v2.2.8_linux_amd64.tar.gz ./traefik --help

    2.2 docker安装

    docker run -d -p 8080:8080 -p 80:80 \ -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik:v2.2

    2.3 helm3安装traefik v1

    前提:k8s集群1.14+,helm 3.X helm repo add stable https://kubernetes-charts.storage.googleapis.com/ helm repo update helm install traefik stable/traefik --set dashboard.enabled=true,serviceType=NodePort,dashboard.domain=dashboard.traefik,rbac.enabled=true --namespace kube-system

    查看service的端口 在本机的/etc/hosts中添加解析 172.16.212.11 dashboard.traefik 访问 http://dashboard.traefik:12577即可!

    此时,无法访问https

    2.4 helm3安装traefik v2

    安装 helm repo add traefik https://containous.github.io/traefik-helm-chart helm repo update helm install traefik traefik/traefik 修改service端口暴露方式 kubectl edit service traefik spec: clusterIP: 192.168.255.168 externalTrafficPolicy: Cluster ports: - name: web nodePort: 30080 port: 80 protocol: TCP targetPort: web - name: websecure nodePort: 30443 port: 443 protocol: TCP targetPort: websecure selector: app.kubernetes.io/instance: traefik app.kubernetes.io/name: traefik sessionAffinity: None type: NodePort 转发dashboard # dashboard.yaml apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: dashboard spec: entryPoints: - web routes: - match: Host(`traefik.guici.com`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`)) kind: Rule services: - name: api@internal kind: TraefikService kubectl apply -f dashboard.yaml

    在本机的/etc/hosts中添加解析 172.16.212.11 traefik.guici.com 访问 http://traefik.guici.com:30080/dashboard/ 即可!

    此时无法访问https

    2.5 yaml方式部署traefik v2

    详见https://www.qikqiak.com/post/traefik-2.1-101/

    crd.yaml apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: ingressroutes.traefik.containo.us spec: group: traefik.containo.us version: v1alpha1 names: kind: IngressRoute plural: ingressroutes singular: ingressroute scope: Namespaced --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: ingressroutetcps.traefik.containo.us spec: group: traefik.containo.us version: v1alpha1 names: kind: IngressRouteTCP plural: ingressroutetcps singular: ingressroutetcp scope: Namespaced --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: middlewares.traefik.containo.us spec: group: traefik.containo.us version: v1alpha1 names: kind: Middleware plural: middlewares singular: middleware scope: Namespaced --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: tlsoptions.traefik.containo.us spec: group: traefik.containo.us version: v1alpha1 names: kind: TLSOption plural: tlsoptions singular: tlsoption scope: Namespaced --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: traefikservices.traefik.containo.us spec: group: traefik.containo.us version: v1alpha1 names: kind: TraefikService plural: traefikservices singular: traefikservice scope: Namespaced rbac.yaml kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: traefik rules: - apiGroups: - "" resources: - pods - 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: - ingressroutes - ingressroutetcps - middlewares - tlsoptions - traefikservices verbs: - get - list - watch --- kind: ServiceAccount apiVersion: v1 metadata: name: traefik namespace: kube-system --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: traefik roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: traefik subjects: - kind: ServiceAccount name: traefik namespace: kube-system deployment.yaml (使用了下面提到的使用阿里云dns作为获取证书的途径,需要创建secret) apiVersion: apps/v1 kind: Deployment metadata: name: traefik namespace: kube-system labels: app: traefik spec: selector: matchLabels: app: traefik strategy: type: Recreate template: metadata: labels: app: traefik spec: serviceAccountName: traefik tolerations: - operator: "Exists" nodeSelector: kubernetes.io/hostname: node-name volumes: - name: acme hostPath: path: /data/k8s/traefik/acme containers: - image: traefik:2.2.1 name: traefik ports: - name: web containerPort: 80 hostPort: 80 - name: websecure containerPort: 443 hostPort: 443 - name: mongo hostPort: 27017 containerPort: 27017 - name: postgres hostPort: 5432 containerPort: 5432 - name: redis hostPort: 6379 containerPort: 6379 args: - --entryPoints.web.address=:80 - --entryPoints.websecure.address=:443 - --entryPoints.mongo.address=:27017 - --entryPoints.postgres.address=:5432 - --entryPoints.redis.address=:6379 - --api=true - --api.dashboard=true - --ping=true - --providers.kubernetesingress - --providers.kubernetescrd - --serversTransport.insecureSkipVerify=true # - --providers.file.filename=/config/traefik-tls.toml - --log.level=INFO - --accesslog # 使用 dns 验证方式 - --certificatesResolvers.ali.acme.dnsChallenge.provider=alidns # 邮箱配置 - --certificatesResolvers.ali.acme.email=ych_1024@163.com # 保存 ACME 证书的位置 - --certificatesResolvers.ali.acme.storage=/etc/acme/acme.json # 下面是用于测试的ca服务,如果https证书生成成功了,则移除下面参数 # - --certificatesresolvers.ali.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory envFrom: - secretRef: name: traefik-alidns-secret #这个secret是需要手动创建的,详见2.6.1 # ALICLOUD_ACCESS_KEY # ALICLOUD_SECRET_KEY # ALICLOUD_REGION_ID volumeMounts: - name: acme mountPath: /etc/acme # - name: config # mountPath: /config # - name: certs # mountPath: /certs resources: requests: cpu: "50m" memory: "50Mi" limits: cpu: "200m" memory: "100Mi" securityContext: allowPrivilegeEscalation: true capabilities: drop: - ALL add: - NET_BIND_SERVICE readinessProbe: httpGet: path: /ping port: 8080 failureThreshold: 1 initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 2 livenessProbe: httpGet: path: /ping port: 8080 failureThreshold: 3 initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 2 dashboard.yaml apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard spec: routes: - match: Host(`traefik.guici.com`) kind: Rule services: - name: api@internal kind: TraefikService --- apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard-tls spec: entryPoints: - websecure routes: - match: Host(`traefik.qikqiak.com`) kind: Rule services: - name: api@internal kind: TraefikService tls: certResolver: ali domains: - main: "*.qikqiak.com" # tls: # secretName: who-tls # --- # apiVersion: traefik.containo.us/v1alpha1 # kind: Middleware # metadata: # name: auth # spec: # basicAuth: # secret: secretName # Kubernetes secret named "secretName"

    2.6 配置支持https访问

    用 HTTPS 访问应用必然就需要证书

    2.6.1 使用阿里云的dns提供商获取证书——这种方式是生产常用方式

    准备工作

    需要api接口的accesskey,secretkey和阿里云区域名称;

    1)创建secret kubectl -n default create secret generic traefik-alidns-secret \ --from-literal=ALICLOUD_ACCESS_KEY=<your-access-key> \ --from-literal=ALICLOUD_SECRET_KEY=<your-secret-key> \ --from-literal=ALICLOUD_REGION_ID=<aliyun-region> 2)编辑deploy template: metadata: labels: app: traefik spec: serviceAccountName: traefik tolerations: - operator: "Exists" nodeSelector: traefik: "true" containers: - image: traefik:v2.1.9 name: traefik ports: - name: web containerPort: 80 hostPort: 80 - name: websecure containerPort: 443 hostPort: 443 - name: metrics hostPort: 8082 containerPort: 8082 args: - --entryPoints.web.address=:80 - --entryPoints.websecure.address=:443 - --api=true - --api.dashboard=true - --ping=true - --providers.kubernetesingress - --providers.kubernetescrd - --log.level=INFO - --accesslog - --accesslog.filepath=/logs/access.log - --log - --log.filepath=/logs/traefik.log - --serverstransport.insecureskipverify=true - --certificatesResolvers.ali.acme.dnsChallenge.provider=alidns #1 - --certificatesResolvers.ali.acme.email=example@qq.com #2 - --certificatesResolvers.ali.acme.storage=/etc/acme/acme.json #3 - --entryPoints.metrics.address=:8082 - --metrics.prometheus=true - --metrics.prometheus.buckets=0.100000, 0.300000, 1.200000, 5.000000 - --metrics.prometheus.addEntryPointsLabels=true - --metrics.prometheus.addServicesLabels=true - --metrics.prometheus.entryPoint=metrics - --metrics.prometheus.manualrouting=true envFrom: - secretRef: name: traefik-alidns-secret #4

    2.6.2 也可以使用自签名的证书——一般只在测试时用

    #创建证书 openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout traefik-tls.key -out traefik-tls.crt -subj "/CN=traefik.qikqiak.com" #通过 Secret 对象来引用证书文件 kubectl create secret tls traefik-tls --cert=traefik-tls.crt --key=traefik-tls.key #修改 ingressroute apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard-tls spec: entryPoints: - websecure routes: - match: Host(`traefik.qikqiak.com`) kind: Rule services: - name: api@internal kind: TraefikService tls: secretName: traefik-tls

    由于用的是自签名证书,所以不受信任

    3 ingressroute代理设置

    3.1 http

    apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: ingressroute # 修改名称 namespace: default # 修改namespace spec: entryPoints: - web routes: - match: Host(`name.domain.com`) # 域名 kind: Rule services: - name: nginx # ServiceName port: 80 # ServicePort

    3.2 https

    阿里dns apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: ingressroute-tls # 修改名称 namespace: default # 修改namespace spec: entryPoints: - websecure routes: - match: Host(`name.domain.com`) # 域名 kind: Rule services: - name: nginx # ServiceName port: 80 # ServicePort tls: certResolver: ali domains: - main: "*.domain.com" 自签名证书 apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: ingressroute-tls # 修改名称 namespace: default # 修改namespace spec: entryPoints: - websecure routes: - match: Host(`name.domain.com`) # 域名 kind: Rule services: - name: nginx # ServiceName port: 80 # ServicePort tls: secretName: traefik-tls #创建方式见 2.6.2

    4 中间件的使用

    4.1 如果只希望用户通过 https 来访问应用

    创建中间件 apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: redirect-https spec: redirectScheme: scheme: https 在ingressroute中使用即可 --- apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: ingressroutetls-http spec: entryPoints: - web #这里指的是http,websecure指的是https routes: - match: Host(`myapp.domain.com`) && PathPrefix(`/tls`) kind: Rule services: - name: myapp port: 80 middlewares: - name: redirect-https
    Processed: 0.036, SQL: 9