龙空技术网

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

财华横溢的程序员 159

前言:

此时大家对“dns challenge”大概比较看重,咱们都想要分析一些“dns challenge”的相关文章。那么小编同时在网摘上搜集了一些关于“dns challenge””的相关文章,希望小伙伴们能喜欢,你们快快来学习一下吧!

了解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.

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

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

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


Traefik 是什么

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


市面上有非常多的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证书签发等内容。

更多内容关注 【程序员财财】查看

标签: #dns challenge