美文网首页KubernetesDocker容器
# 一篇文章让你搞懂如何在K8s 里使用 Traefik 2.0

# 一篇文章让你搞懂如何在K8s 里使用 Traefik 2.0

作者: 一个大番茄 | 来源:发表于2020-01-16 14:12 被阅读0次

    原文链接

    了解K8s的同学应该都知道,如果想要把应用暴露到公网上供外部访问,那么不可避免的会接触到Ingress资源。本文以Traefik为例,让大家对Ingress和Traefik的使用有一定的了解。

    Ingress是什么

    我们来看看官方对于Ingress的解释

    An API object that manages external access to the services in a cluster, typically HTTP.
    Ingress can provide load balancing, SSL termination and name-based virtual hosting.

    1. 它也是一个API对象,就如同其他的API对象Service、Deployment一样。
    2. 负责管理外部流量对于集群内部的访问,比如典型通过HTTP协议。
    3. 能承担负载均衡,SSL等职责

    简单来说,它承担的就是一个边缘路由的职责,负责按照你期望的规则管理外部的访问请求,如下面所示:

        internet
            |
       [ Ingress ]
       --|-----|--
       [ Services ]
    

    Traefik 是什么

    上面我们简单说明了什么是Ingress,它是一个API资源对象。得益于K8s高度抽象的设计,可以让我们很方便地做技术选型去实现Ingress的工作。在这里,完成具体工作的组件就是Ingress Controller,Traefik就是其中之一。

    traefik-architecture.png

    市面上有非常多的Ingress Controller,比如Nginx Ingress、kong、istio等等。我之所以选择Traefik的原因是目前项目不算太复杂traefik足够应付,提供了较为简洁的UI界面,能够满足我目前的需求。不过稍微有点坑的地方就是Traefik 2.0的版本发布不久,文档的支持上稍微有点弱,有时候看文档会比较懵。因此,接下来的文章,我就以Traefik 2.0来说明如何在K8s中使用Ingress Controller。

    在K8s集群中部署Traefik

    在这里我没有使用Helm来部署Traefik(因为此时Helm上的Traefik版本还是低于2.0的),先来看看目录下有哪些yaml文件。

    > #ls
    > #traefik-config.yaml  traefik-crd.yaml  traefik-deploy.yaml  traefik-rbac.yaml
    

    接下来我会展示这些文件中的重点内容,限于篇幅的原因,部分内容省略表示,可以在公众号留言我给出完整示例。

    • 先看看 traefik-config.yaml里面的内容:
    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: traefik-config
      namespace: kube-system
    data:
      traefik.yaml: |-
        serversTransport:
          insecureSkipVerify: true
        api:
          ...
        metrics:
          ...
        entryPoints:
          web:
            address: ":80"
          websecure:
            address: ":443"
        providers:
          kubernetesCRD: ""
        log:
            ...
        accessLog:
            ...
    

    这里面都是关于Traefik的一些配置,基本上看名字也能知道各个字段的含义,这里可能需要稍微注意一点的是entryPoints。在这里定义了两条入口,一条叫做web负责监听80端口的访问,一条叫做websecure负责监听443端口,也就是Https的请求。

    • 再来看看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也就是CustomResourceDefinition,在Kubernetes 1.7 之后增加了对 CRD 资源二次开发能力来扩展 Kubernetes API,通过 CRD 我们可以向 Kubernetes API 中增加新资源类型,而不需要修改 Kubernetes 源码来创建自定义的 API server,该功能大大提高了 Kubernetes 的扩展能力。
    在这里,Traefik从2.0的版本不在直接监听Ingress资源,而是通过自定的一个叫做IngressRoute的资源在进行工作,这点是需要注意的地方。除此之外,我们可以看到Traefik还申明了一些自定义的资源。这些资源的使用范围是namespace级别的,在k8s中还支持集群级别的crd。

    • traefik-rbac.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: ingress
      namespace: kube-system
    ---
    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"]
          ... 
    ---
    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: ingress
        namespace: kube-system
    

    在这个文件里定义的是Traefik会涉及到的角色和权限,因为可能要代理各个命名空间的各个服务的流量,因此可以看到有Cluster级别的权限申明。

    • 最重要的traefik-deploy.yaml
      前面的一系列准备工作准备完成之后,就是真正的部署Traefik了,由于内容比较多,为了方便理解我直接在相关的字段后添加注释来说明
    apiVersion: v1
    kind: Service
    metadata:
      name: traefik
      namespace: kube-system
    spec:
      ports:
        - name: web
          port: 80
        - name: websecure
          port: 443
        - name: admin
          port: 8080
      selector:
        app: traefik
    ---
    apiVersion: apps/v1
    kind: DaemonSet # 以DaemonSet的形式运行Traefik
    metadata:
      name: traefik-ingress-controller
      namespace: kube-system
      labels:
        app: traefik
    spec:
      selector:
        matchLabels:
          app: traefik
      template:
        metadata:
          name: traefik
          labels:
            app: traefik
        spec:
          serviceAccountName: ingress       #使用了前文中定义的service account,以便具备相关的权限
          terminationGracePeriodSeconds: 1
          containers:
            - image: traefik:2.0        #使用的是traefik 2.0的版本
              name: traefik-ingress-lb
              env:  # 由于我的服务器是阿里云的ECS,我需要使用阿里云的Access Key以便能够使用Traefik的自动Https签名功能
              - name: ALICLOUD_ACCESS_KEY              # 添加环境变量ALICLOUD_ACCESS_KEY
                value: <根据你自己的情况调整>                 # 阿里云RAM账号的access_key
              - name: ALICLOUD_SECRET_KEY              # 添加环境变量ALICLOUD_SECRET_KEY
                value: <根据你自己的情况调整>                   # 阿里云RAM账号的access_secret
              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:
                - --entrypoints.web.Address=:80
                - --entrypoints.websecure.Address=:443
                - --api.insecure  # 开启webui需要该参数
                - --providers.kubernetescrd
                - --api
                - --api.dashboard=true
                - --accesslog
                # 使用acme.sh通过dns验证域名的所有权,以便能够自动签发https证书
                - --certificatesresolvers.default.acme.dnsChallenge=true
                - --certificatesresolvers.default.acme.dnsChallenge.provider=alidns
                # 邮箱配置
                - --certificatesResolvers.default.acme.email=你的邮箱@gmail.com
                # 保存ACME 证书的位置
                - --certificatesResolvers.default.acme.storage="acme.json"
                - --metrics.prometheus=true
              volumeMounts:
                - mountPath: "/config"
                  name: "config"
          volumes:
            - name: config
              configMap:
                name: traefik-config
          tolerations:              #设置容忍所有污点,防止节点被设置污点
            - operator: "Exists"
          nodeSelector:             #设置node筛选器,在特定label的节点上启动,我为具有公网IP的节点打上了这个标签
            IngressProxy: "true"
    

    到此为止,所有的准备工作都完成了,接下来在目录执行命令kubectl apply -f *,正常的话你可以看到上面几个文件内申明的所有资源都被正确的创建了,我们也可以通过命令验证下traefik是不是在正常运行。

    屏幕快照 2020-01-14 下午3.33.52.png

    正常情况下的话,你可以看到一个daemonset,一个service,和至少一个pod在运行。如果走到这步的话,那说明已经大功告成 了。

    结语

    在本文中,阐述了如何使用Traefik作为Ingress Controller来监听集群外部的网络请求,在接下来的文章中,我将通过一个具体的例子展示如何暴露一个内部的服务到外网访问,以及如何进行自动Https证书签发等内容。

    默认标题_公众号封面首图_2020-01-13-0.png

    相关文章

      网友评论

        本文标题:# 一篇文章让你搞懂如何在K8s 里使用 Traefik 2.0

        本文链接:https://www.haomeiwen.com/subject/cqpfzctx.html