乔克
乔克
Published on 2024-11-15 / 44 Visits
0
0

Traefik mesh:更简单的服务网格

Traefik mesh 是一款轻量级的服务网格,它简单易行,易于安装并且易于使用。

Traefik mesh 建立在 Traefik 之上,适合于符合最新网络接口规范 SMIKubernetes 集群。

Traefik mesh 的最大特点就是非侵入性,也就是使用 Traefik mesh 并不会改变你现有的 Kubernetes 对象。

非侵入性服务网格

Traefik mesh 不使用任何 sidecar 模式,其路由处理是通过运行在每个节点的 proxy 完成。网格控制器也是通过单独的 Pod 运行,负责处理代理节点的所有配置分析和部署。

使用 Traefik mesh 之后,其逻辑如下。
图片.png

Traefik mesh 没有通过 sidecar 的形式进行流量拦截或者修改,哪是怎么实现的呢?

它其实是借助于 CoreDNS,它通过修改 CoreDNS 的少量配置,让用于允许使用 Mesh 端点而不是标准的 Kubernetes 端点,Mesh 端点和用于服务并行运行,用户可以选择是否使用它。

安装

前提:
Kubernetes 1.11+
CoreDNS 1.3+
Helm v3

Traefik mesh 的安装很简单,使用 Helm 即可实现快速的安装。

(1)添加 Helm 仓库

helm repo add traefik-mesh https://helm.traefik.io/mesh
helm repo update

(2)下载 Chart 包

helm pull traefik-mesh/traefik-mesh

(3)解压 Chart 包

tar xf traefik-mesh-3.0.6.tgz

Traefik mesh 会部署 4 个服务,它们分别是:

  • controller:Mesh 的控制器,负责代理节点的所有配置分析和配置
  • proxy:Mesh 的代理,负责处理每个节点的流量代理
  • tracing:跟踪配置
  • metrics:监控配置

(4)安装 traefik mesh

helm install traefik-mesh .

traefik mesh 需要 coredns 的配合,主要改动部分如下:

    #### Begin Maesh Block
    maesh:53 {
        errors
        rewrite continue {
            name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.maesh default-{1}-6d61657368-{2}.default.svc.cluster.local
            answer name default-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.default\.svc\.cluster\.local {1}.{2}.maesh
        }
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            upstream
            fallthrough in-addr.arpa ip6.arpa
        }
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }
    #### End Maesh Block

    #### Begin Traefik Mesh Block
    traefik.mesh:53 {
        errors
        rewrite continue {
            name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.traefik.mesh default-{1}-6d61657368-{2}.default.svc.cluster.local
            answer name default-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.default\.svc\.cluster\.local {1}.{2}.traefik.mesh
        }
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            upstream
            fallthrough in-addr.arpa ip6.arpa
        }
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }
    #### End Traefik Mesh Block

如果在部署过程中,coredns 报以下错误:

plugin/forward: this plugin can only be used once per Server Block

请检查 coredns 的 configMap 配置,看 DNS 下是否有两个 forward。

配置

Traefik mesh 的配置分为静态配置和动态配置。

静态配置

  • 可以手动指定 controller 镜像版本和 Traefik 镜像版本
  • 可以配置 controllerproxies 的日志级别和格式
  • 可以配置 mesh 的模式,默认是 HTTP
  • 可以打开 tracing 功能
  • 可以开启 ACL 权限控制功能,这配置了 Traefik 网格以 ACL 模式运行,除非通过 SMI 流量目标明确允许,否则禁止所有流量

动态配置

在 Kubernetes service 上使用 annotations 和 SMI 对象可向 Traefik Mesh 提供动态配置。支持的动态配置参数主要有:

  • Traffic-Type
  • Scheme
  • Retry
  • Circuit-Breaker
  • Rate-Limit
  • Traffic-Split
  • Traffic-Targe

这里简单介绍如何在 Kubernetesservice 中使用 annotations 进行配置。

(1)Traffic-Type 主要用于配置流量类型,可以配置 tcp,udp,http 三种类型,如果没有配置,默认使用 http 类型,配置如下:

mesh.traefik.io/traffic-type: "http"

(2)Scheme 主要配置请求的协议,可以配置 http,https,h2c 三种类型,配置如下:

mesh.traefik.io/scheme: "h2c"

(3)Retry 主要配置重试次数,当网络等异常情况下,会根据用户配置发起几次重试,如果还是失败,则返回失败,配置如下:

mesh.traefik.io/retry-attempts: "2"

(4)Cricuit break 主要用于配置断开流量转发,当系统处于健康的情况下,默认是关闭的,如果系统异常,则会打开,不再转发流量到异常的系统中,配置如下:

mesh.traefik.io/circuit-breaker-expression: "Expression"

(5)Rate limit 主要用于配置限流,单位是请求次数/秒,可以配置平均请求和突发请求,配置如下:

mesh.traefik.io/ratelimit-average: "100"
mesh.traefik.io/ratelimit-burst: "200"

(6)Access control 主要用于配置权限控制,可以配置应用允许哪些客户端访问。
比如定义如下路由:

---
apiVersion: specs.smi-spec.io/v1alpha3
kind: HTTPRouteGroup
metadata:
  name: server-routes
  namespace: server
spec:
  matches:
    - name: api
      pathRegex: /api
      methods: ["*"]
    - name: metrics
      pathRegex: /metrics
      methods: ["GET"]

它表示可以通过任何方法访问 /api 路径,只允许使用 GET 方法访问 /metrics 路径。定义好路由还不够,在默认情况下,所有的流量都会被拒绝访问,如果要授予客户端访问权限,需要配置 TrafficTarget,如下:

---
apiVersion: access.smi-spec.io/v1alpha2
kind: TrafficTarget
metadata:
  name: client-server-target
  namespace: server
spec:
  destination:
    kind: ServiceAccount
    name: server
    namespace: server
  rules:
    - kind: HTTPRouteGroup
      name: server-routes
      matches:
        - api
  sources:
    - kind: ServiceAccount
      name: client
      namespace: client

该配置表示允许运行在 client namespace 下的具有 saclient 的所有 pod 访问 api 路由。

(7)Traffic Split 主要用于流量拆分,特别是在做金丝雀发布的时候特别有用,比如如下配置:

apiVersion: split.smi-spec.io/v1alpha3
kind: TrafficSplit
metadata:
  name: server-split
  namespace: server
spec:
  service: server
  backends:
    - service: server-v1
      weight: 80
    - service: server-v2
      weight: 20

其表示将 80% 的流量转发到 server-v1,20% 的流量转发到 server-v2。

例子

上面已经安装部署好 Traefik mesh,下面已官方的例子来进行简单的测试。
(1)部署应用

apiVersion: v1
kind: Namespace
metadata:
  name: whoami

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: whoami-server
  namespace: whoami

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: whoami-client
  namespace: whoami
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoami
  namespace: whoami
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      serviceAccount: whoami-server
      containers:
        - name: whoami
          image: traefik/whoami:v1.6.0
          imagePullPolicy: IfNotPresent

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoami-tcp
  namespace: whoami
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami-tcp
  template:
    metadata:
      labels:
        app: whoami-tcp
    spec:
      serviceAccount: whoami-server
      containers:
        - name: whoami-tcp
          image: traefik/whoamitcp:v0.1.0
          imagePullPolicy: IfNotPresent

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: whoami
  labels:
    app: whoami
spec:
  type: ClusterIP
  ports:
    - port: 80
      name: whoami
  selector:
    app: whoami

---
apiVersion: v1
kind: Service
metadata:
  name: whoami-tcp
  namespace: whoami
  labels:
    app: whoami-tcp
spec:
  type: ClusterIP
  ports:
    - port: 8080
      name: whoami-tcp
  selector:
    app: whoami-tcp

---
apiVersion: v1
kind: Pod
metadata:
  name: whoami-client
  namespace: whoami
spec:
  serviceAccountName: whoami-client
  containers:
    - name: whoami-client
      image: giantswarm/tiny-tools:3.9
      command:
        - "sleep"
        - "3600"

上面部署了两个应用,一个 http 类型应用,一个是 tcp 类型应用。

可以通过以下命名查看应用启动情况 kubectl get all -n whoami

图片.png

然后可以测试以下应用连通性,如下:

# kubectl -n whoami exec whoami-client -- curl -s whoami.whoami.svc.cluster.local
Hostname: whoami-576cb59fd-qvnl7
IP: 127.0.0.1
IP: 172.16.235.193
RemoteAddr: 172.16.7.181:33150
GET / HTTP/1.1
Host: whoami.whoami.svc.cluster.local
User-Agent: curl/7.64.0
Accept: */*

# kubectl -n whoami exec -ti whoami-client -- nc whoami-tcp.whoami.svc.cluster.local 8080
my data
Received: my data

Received: 
eee
Received: eee
eee
Received: eee

如果现在要为上面的服务配置 Traefik mesh,只需要更改这两个服务的 service,http 类型应用的 service 加 mesh.traefik.io/traffic-type: "http" 的 annotations,tcp 类型应用的 service 加 mesh.traefik.io/traffic-type: "tcp" 的 annotations,如下:

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: whoami
  labels:
    app: whoami
  annotations:
    mesh.traefik.io/traffic-type: "http"
    mesh.traefik.io/retry-attempts: "2"
spec:
  type: ClusterIP
  ports:
    - port: 80
      name: whoami
  selector:
    app: whoami

---
apiVersion: v1
kind: Service
metadata:
  name: whoami-tcp
  namespace: whoami
  labels:
    app: whoami-tcp
  annotations:
    mesh.traefik.io/traffic-type: "tcp"
spec:
  type: ClusterIP
  ports:
    - port: 8080
      name: whoami-tcp
  selector:
    app: whoami-tcp

现在访问服务,只需将 svc.cluster.local 改为 traefik.mesh 即可。
比如之前访问方式如下:

kubectl -n whoami exec whoami-client -- curl -s whoami.whoami.svc.cluster.local

加了 traefik mesh 之后,即为:

kubectl -n whoami exec whoami-client -- curl -s whoami.whoami.traefik.mesh

当然之前的访问方式依然存在,用什么样的方式由用户自己决定。

脚注

【1】https://traefik.io/traefik/
【2】https://smi-spec.io/
【3】https://coredns.io/


Comment