本文来自边缘计算k3s社区

作者简介

Cello Spring,瑞士人。从电子起步,拥有电子工程学位。尔后开始关注计算机领域,在软件开发领域拥有多年的工作经验。

Traefik是一个十分可靠的云原生动态反向代理。轻量级Kubernetes发行版K3s早在去年就已经内置Traefik,将其作为集群的默认反向代理和Ingress Controller。然而,在本文成文时K3s中的默认内置Traefik版本为v1.7.14。这一版本固然也能很好地运行,但还是少了一些有用的功能。我最想用的功能是为正在使用的Ingress Route自动生成Let’s Encrypt证书。而使用Traefik 2.x版本可以获得这一功能,甚至还有更多其他功能。那么,我们来看看如何使用K3s设置并使用新版本的Traefik。

本文的目标是设置一个新的K3s集群、安装Traefik 2.x版本并配置一些Ingress,这些Ingress将由自动生成的Let’s Encrypt证书保护。

以下是我们将要进行的步骤:

  • 在Civo上创建一个极小的K3s集群

  • 将我们的域(我会使用我的虚拟域celleri.ch)指向集群IP

  • 安装Klipper LB作为我们的LoadBalancer

  • 在集群上安装Traefik v2

  • 部署一个小型工作负载(whoami)到集群上

  • 创建一个Traefik ingress到服务(分为有TLS termination或没有)

  • 使用Traefik 中间件以通过基本身份验证访问Traefik Dashboard

创建Civo集群

为此,请到Civo(civo.com/)并创建一个只有2个节点的超小型集群。如果你还没有账户,可以注册并申请KUBE100 Beta项目以使用其提供的Kubernetes产品。

需要确保我们不使用基本设置安装Traefik(在“Architecture”选项卡上取消选择Traefik)

大约2分钟之后,我们将获得以下集群:

接下来,我们需要记下master节点的IP地址并下载kubeconfig文件。在本例中,它被命名为civo-k3s-with-traefik2-kubeconfig,因为我们将集群命名为k3s-with-traefik2。为了使用kubectl从命令行中访问该集群,我们需要将环境变量指向kubeconfig文件并将上下文更改至我们的新集群。

# set env variable with new cluster config
export KUBECONFIG=./civo-k3s-with-traefik2-kubeconfig
kubectl config use-context k3s-with-traefik2 #check the available nodes
kubectl get nodes NAME STATUS ROLES AGE VERSION
kube-master-de56 Ready master 9m15s v1.16.3-k3s.2
kube-node-40e7 Ready 7m21s v1.16.3-k3s.2

正如我们所见,带有1个master节点和1个worker节点的集群已经准备完毕!继续进行下一步。

将域名Celleri.ch指向新的集群IP地址

最近一段时间,我一直使用Cloudflare(cloudflare.com/dns/)的DNS服务来处理Kubernetes。它十分可靠,有友好的用户界面并且我使用的基本服务都是免费的。

在Cloudflare中我们应用以下设置:

本示例中,我们不想为可能用到的每个子域都创建一个CNAME条目,因此我们在此处创建一个通配符(*)条目作为CNAME。Traefik将确保稍后将流量路由到正确的位置。

安装Klipper LB作为我们的LoadBalancer

默认情况下,K3s内置的Traefik为v1.7.x版本。默认安装还部署了来自Rancher的内部LoadBalancer,Klipper LB。由于在设置集群时,我们没有安装Traefik,因此我们现在必须自己手动安装Klipper LB。

Klipper会将自己挂接到集群节点的主机端口上,并使用端口80、443和8080。

你可以在我的Github Repo里找到我所提到的所有文件:

https://github.com/cellerich/k3s-with-traefik2

# install KlipperLB
kubectl apply -f 00-klipper-lb/klipper.yaml # see if klipper hooked up to the host ports and is working
kc get pods --all-namespaces | grep svclb
kube-system svclb-traefik-gc8lg 3/3 Running 0 96s
kube-system svclb-traefik-pqbzb 3/3 Running 0 96s

这些Pod似乎可以与在其中运行的3个容器(每个主机端口一个容器)一起工作。接下来,我们开始安装Traefik v2。

在集群中安装Traefik v2

Traefik v2附带了许多CRD,这似乎是扩展Kubernetes对象的一种新方法。我还没有完全把精力放在这些CRD上面,但是无论如何我们都要使用它们。你可以在Traefik文档(https://docs.traefik.io/v2.0/user-guides/crd-acme/)中找到正确的yaml文件,或者你可以使用我在Github repo上提供的01-traefik-crd/traefik-crd.yaml文件。

# apply traefik crd's
kubectl apply -f 01-traefik-crd/traefik-crd.yaml

这个命令应该会创建5个CRD。

为了让Traefik可以做它所需要做的事情,我们需要一个clusterrole和一个clusterrolebinding。我们可以使用以下命令:

# apply clusterrole and clusterrolebinding
kubectl apply -f 01-traefik-crd/traefik-clusterrole.yaml

请注意:我们将在命名空间kube-system中为ServiceAccount进行clusterrolebinding,因为稍后我们会将流量安装到该命名空间中。


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: traefik-ingress-controller
namespace: kube-system

最后,我们把Traefik Service、ServiceAccount以及Deployment部署到集群中:

kubectl apply -f 02-traefik-service/traefik.yaml

这应该为我们提供一个LoadBalancer类型的服务,该服务具有集群的master节点的外部地址:

# get traefik service
kubectl get svc -n kube-system | grep traefik traefik LoadBalancer 192.168.211.177 185.136.232.122 80:32286/TCP,443:30108/TCP,8080:30582/TCP 3m43s

部署一个小型工作负载(whoami)到集群

现在是时候在我们的集群中创建一个服务并尝试通过我们的Traefik代理从外部调用它。本示例中我使用的是whoami服务,它也用于Traefik文档中的所有示例。让我们部署它:


# deploy `whoami` in namespace `default`
kubectl apply -f 03-workload/whoami-service.yaml #check the deployment
kubectl get pods | grep whoami whoami-bd6b677dc-lfxbx 1/1 Running 0 5m37s
whoami-bd6b677dc-92jzj 1/1 Running 0 5m37s

好像已经可以运行了。现在要到激动人心的部分了,Traefik Ingress。

为服务创建两个Traefik Ingress(有/没有TLS Termination)

我们想要从外部访问whoami服务,以让我们最终可以定义IngressRoute对象。没错,那些对象是在我们之前安装的CRD中定义的。现在它们派上用场了。我们按照以下方式部署IngressRoutes:

kubectl apply -f 03-workload/whoami-ingress-route.yaml

正如你在定义中所看到的,我们使用tls.certResolver=default指定了一个路由(附带PathPrefix '/tls')。该certResolver在我们的02-traefik-service / traefik.yaml文件中定义。


apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-notls
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`celleri.ch`) && PathPrefix(`/notls`)
kind: Rule
services:
- name: whoami
port: 80 ---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-tls
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`celleri.ch`) && PathPrefix(`/tls`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certResolver: default

现在启动浏览器并访问地址http://celleri.ch/notls,查看即将发生的事情——pod正在响应:

那么https://celleri.ch/tls发生了什么呢?它也在正常运行,但是告诉我们第一个连接不安全。如果我们查看证书,我们就能找到原因:

为了防止因我们的安装程序无法正常工作而使生产服务器受到许多请求的困扰,我们一开始没有使用Let’s Encrypt,而在Traefik Service中使用staging服务器。因此,我们接下来要更改这一设置并使用生产服务器获得一个真实的证书。

更改certresolver以使用Let’s Encrypt生产服务器

在我们定义的Traefik Deployment中,我们有以下参数:


... cropped for readability ... spec:
serviceAccountName: traefik-ingress-controller
containers:
- name: traefik
image: traefik:v2.0
args:
- --api.insecure
- --accesslog
- --entrypoints.web.Address=:80
- --entrypoints.websecure.Address=:443
- --providers.kubernetescrd
- --certificatesresolvers.default.acme.tlschallenge
- --certificatesresolvers.default.acme.email=me@myself.com
- --certificatesresolvers.default.acme.storage=acme.json
# Please note that this is the staging Let's Encrypt server.
- --certificatesresolvers.default.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory ... cropped for readability ...

我们告诉Traefik使用tlschallenge的方法来使用名为default的certificateresolvers。此外,我们还需要提供我们的邮件和证书的存储。我们在前文中还提到我们要使用staging caserver。

重点:在我们的部署中,我们没有存储提供程序或者volume。这意味着,部署重新加载后我们的证书就会消失。证书仅存在于我们的pod内存中。在生产环境中,我们必须解决这一问题并提供一个volume。

好的,让我们注释掉caserver行,然后重新部署Traefik deployment,看看我们是否获得了真实的证书:


... cropped for readability ... spec:
serviceAccountName: traefik-ingress-controller
containers:
- name: traefik
image: traefik:v2.0
args:
- --api.insecure
- --accesslog
- --entrypoints.web.Address=:80
- --entrypoints.websecure.Address=:443
- --providers.kubernetescrd
- --certificatesresolvers.default.acme.tlschallenge
- --certificatesresolvers.default.acme.email=me@myself.com
- --certificatesresolvers.default.acme.storage=acme.json
# Please note that this is the staging Let's Encrypt server.
# - --certificatesresolvers.default.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory ... cropped for readability ...
# deploy the changed file
kubectl apply -f 02-traefik-service/traefik.yaml

一会儿之后,我们将获得一个有效证书:

在这之后,我们可以稍稍放轻松了。但是我们想更近一步,Traefik v2还有一个不错的dashboard,可以查看正在运行的所有Ingress内容。但是我们并不希望每个人都能访问我们的dashboard。有一些基本的身份验证可以更好地保护我们的dashboard。

使用Traefik 中间件以通过基本身份验证访问Traefik Dashboard

在Traefik 2.x中引入了一个新机制——中间件,该机制在处理传入请求时可以帮助我们完成许多任务。我们将使用basicAuth中间件来保护Traefik dashboard并将其暴露给外部。

首先,我们需要使用我们的用户名和哈希密码创建一个Secret,以便basicAuth 中间件在以后使用:

# create user:password file 'user'
htpasswd -c ./user cellerich # enter password twice... # create secret from password file
kubectl create secret generic traefik-admin --from-file user -n kube-system

确保在命名空间kube-system内创建该Secret,因为Traefik Service及其Dashboard也位于此命名空间中。

然后我们部署该中间件以及IngressRoute到我们的集群:

kubectl apply -f 04-traefik-dashboard/traefik-admin-withauth.yaml

现在,我们访问https://traefik.celleri.ch,出现登陆提示:

使用正确的凭据,我们将访问Traefik v2的dashboard:

并且我们会获得许多关于我们Ingress Route的信息:

结 语

这就是教程的全部。在研究过程中,我没有发现太多关于如何在k3s中设置Traefik v2的示例,特别是Klipper LB的部分从未被提及。这就是为什么我想向大家分享我的经验,希望它能够帮助到你,退一万步来说,至少它对我的将来会有所帮助。

参考链接:

Github :

https://github.com/cellerich/k3s-with-traefik2

关于Rancher的Klipper LB:

https://github.com/rancher/klipper-lb

Traefik中间件文档:

https://docs.traefik.io/v2.0/middlewares/overview/

Step by Step!教你如何在k3s集群上使用Traefik 2.x的更多相关文章

  1. 实操教程丨如何在K8S集群中部署Traefik Ingress Controller

    注:本文使用的Traefik为1.x的版本 在生产环境中,我们常常需要控制来自互联网的外部进入集群中,而这恰巧是Ingress的职责. Ingress的主要目的是将HTTP和HTTPS从集群外部暴露给 ...

  2. 仅需5步,轻松升级K3s集群!

    Rancher 2.4是Rancher目前最新的版本,在这一版本中你可以通过Rancher UI对K3s集群进行升级管理. K3s是一个轻量级Kubernetes发行版,借助它你可以几分钟之内设置你的 ...

  3. 仅需60秒,使用k3sup快速部署高可用K3s集群

    作者简介 Dmitriy Akulov,连续创业者,16岁时搭建了开源CDN公共服务jsDelivr的v1版本.目前是边缘托管平台appfleet创始人. 原文链接: https://ma.ttias ...

  4. 如何安装一个高可用K3s集群?

    作者介绍 Janakiram MSV是Janakiram & Associates的首席分析师,也是国际信息技术学院的兼职教师.他也是Google Qualified Developer.亚马 ...

  5. 1款开源工具,实现自动化升级K3S集群!

    即便你的集群能够平稳运行,Kubernetes升级依旧是一项艰难的任务.由于每3个月Kubernetes会发布一个新版本,所以升级是十分必要的.如果一年内你不升级你的Kubernetes集群,你就会落 ...

  6. 多云搭建 K3S 集群

    作者:SRE运维博客 博客地址: https://www.cnsre.cn/ 文章地址:https://www.cnsre.cn/posts/211119132529/ 相关话题:https://ww ...

  7. 如何在 Kubernetes 集群中玩转 Fluid + JuiceFS

    作者简介: 吕冬冬,云知声超算平台架构师, 负责大规模分布式机器学习平台架构设计与功能研发,负责深度学习算法应用的优化与 AI 模型加速.研究领域包括高性能计算.分布式文件存储.分布式缓存等. 朱唯唯 ...

  8. 不同云服务器下,ubuntu下开k3s集群

    首先先感谢老哥的文章:h构建多云环境下的K3S集群,但是我尝试在centos 8.2上面前面一直执行报错 并且安装glibc 2.17时还会报错make版本太低,所以直接放弃centos,投入ubun ...

  9. 跨云厂商部署 k3s 集群

    原文链接:https://fuckcloudnative.io/posts/deploy-k3s-cross-public-cloud/ 最近一两年各大云服务商都出了各种福利活动,很多小伙伴薅了一波又 ...

随机推荐

  1. Function.prototype.call.apply()方法

    在看uncurrying化函数时候,碰到了Function.prototype.call.apply()的用法: 先说说uncurrying()函数: Function.prototype.uncur ...

  2. Chromium的无锁线程模型C++代码示例

    引言 作者:程序员bingo,主要关注客户端架构设计.性能优化.崩溃处理,有多年的Chromium浏览器开发经验. 多线程一直是软件开发中最容易出问题的环节,很多的崩溃.卡死问题都与多线程有关.在常用 ...

  3. django 知识点小结

    以下内容为用django写blog中的一些知识点,权当复习. 一.定义view 1.get_object_or_404()是用get()查询数据,如果不存在就直接返回404 参数: get_objec ...

  4. 分布式爬虫管理平台Crawlab安装与使用

    Why,为什么需要爬虫管理平台? 以下摘自官方文档: Crawlab主要解决的是大量爬虫管理困难的问题,例如需要监控上百个网站的参杂scrapy和selenium的项目不容易做到同时管理,而且命令行管 ...

  5. django 从零开始 12 快速集合queryset对象

    使用序列化将查询到的quweyset对象进行一个格式转换          还没看文档理解 待写 from django.core.serializers import serializers 导入该 ...

  6. async,await怎么用

    async声明一个函数是异步的,await用于等待异步完成,并且await只能在async中使用. 使用async,await并行处理请求,速度减半: 将多个promise直接发起请求,先执行asyn ...

  7. Python基础篇(一)_基本语法元素

    Python基础篇——基本语法元素 缩进:体现强制可读性,一般缩进4个空格.一个或多个Tab 注释:单行注释----以 # 开头 多行注释----每行以 # 开头,以 # 结束 变量:无须提前声明.可 ...

  8. Flask wtforms 表单验证使用

    目录 wtforms 使用1(简单版): 使用2(复杂版): wtforms 安装:pip3 install wtforms 使用1(简单版): from flask import Flask, re ...

  9. 网络安全从入门到精通 ( 第二章-5) 后端基础PHP—简介及基本函数-下

    本文内容: 循环语句 PHP获取表单信息 PHP操作Mysql语句 语法SQL注入 1,循环语句: for循环: 语法:for($x=0,$x<10;$x++){执行语句;} 注意:$x++,先 ...

  10. 聊一聊 React 中的 CSS 样式方案

    和 Angular,Vue 不同,React 并没有如何在 React 中书写样式的官方方案,依靠的是社区众多的方案.社区中提供的方案有很多,例如 CSS Modules,styled-compone ...