一篇文章让你搞懂 K8s Ingress,Traefik 2.0 为例(上)

教你如何在 K8s 中使用 Traefik 2.0 作为 Ingress

原文链接

了解 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 就是其中之一。一篇文章让你搞懂 K8s Ingress,Traefik 2.0 为例(上)_第1张图片市面上有非常多的 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: ConfigMapapiVersion: v1metadata:  name: traefik-config  namespace: kube-systemdata:  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里面的内容
## IngressRouteapiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata:  name: ingressroutes.traefik.containo.usspec:  scope: Namespaced  group: traefik.containo.us  version: v1alpha1  names:    kind: IngressRoute    plural: ingressroutes    singular: ingressroute---## IngressRouteTCPapiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata:  name: ingressroutetcps.traefik.containo.usspec:  scope: Namespaced  group: traefik.containo.us  version: v1alpha1  names:    kind: IngressRouteTCP    plural: ingressroutetcps    singular: ingressroutetcp---## MiddlewareapiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata:  name: middlewares.traefik.containo.usspec:  scope: Namespaced  group: traefik.containo.us  version: v1alpha1  names:    kind: Middleware    plural: middlewares    singular: middleware---apiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata:  name: tlsoptions.traefik.containo.usspec:  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: v1kind: ServiceAccountmetadata:  name: ingress  namespace: kube-system---kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: traefik-ingress-controllerrules:  - 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: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: traefik-ingress-controllerroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: traefik-ingress-controllersubjects:  - kind: ServiceAccount    name: ingress    namespace: kube-system

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

  • 最重要的 traefik-deploy.yaml前面的一系列准备工作准备完成之后,就是真正的部署 Traefik 了,由于内容比较多,为了方便理解我直接在相关的字段后添加注释来说明
apiVersion: v1kind: Servicemetadata:  name: traefik  namespace: kube-systemspec:  ports:    - name: web      port: 80    - name: websecure      port: 443    - name: admin      port: 8080  selector:    app: traefik---apiVersion: apps/v1kind: DaemonSet    # 以 DaemonSet 的形式运行 Traefikmetadata:  name: traefik-ingress-controller  namespace: kube-system  labels:    app: traefikspec:  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 是不是在正常运行。

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

结语

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

阅读全文: http://gitbook.cn/gitchat/activity/5e1ffb6c1575ee059291b01d

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

你可能感兴趣的:(一篇文章让你搞懂 K8s Ingress,Traefik 2.0 为例(上))