缘起
在开始自建家庭服务器和用容器技术来部署各种私有服务约5年后,我已经熟悉了一套用docker compose管理所有容器的方案,这套方案很优雅也很有用,但这仅限单台电脑。最近我突然有了管理使用多台电脑的需求,我终于开始觉得有必要从单个服务器转向服务器集群,或者说Homelab了。
具体来说,我之前作为服务器的电脑有着比较大的内存和硬盘,但没安装显卡,这对于我之前部署的许多服务已经够了。现在我有了一台有显卡的电脑,想要跑一些大语言模型。当然我可以单独在这台电脑上部署,但这样与我之前的方案就比较割裂了,我希望能有个方案能同时管理这两台电脑。将来再添加其他电脑时也更容易扩展。
当然,转向Kubernetes之前,你最好已经对容器的概念比较熟悉了。我之前写过一系列的关于容器(主要是Docker)的文章可供参考:
- 容器(2):docker最佳实践指南——docker-compose和Portainer
- 容器(3):docker最佳实践指南——数据卷volume的管理
- 容器(4):docker最佳实践指南——容器更新、升级和迁移
- 容器(5):docker最佳实践指南——容器更新监测工具WUD(What’s Up Docker)
- 容器(6):使用Docker时的一些误区、坏习惯和问题
Homelab
什么是Homelab
Homelab表面上的意思是指在家中搭建一个实验室,用于学习、实验和开发。Homelab通常包括一台或多台服务器、网络设备、存储设备等,可以用来运行各种服务和应用程序。
Homelab的规模可大可小,如果你财力充足,可以购买多台高性能服务器,搭建一个大型的家庭实验室;如果你财力有限,也可以只用一台普通的电脑,甚至一个树莓派(Raspberry Pi)就可以搭建一个小型的家庭实验室。
为什么需要Homelab
服务器集群或者Homelab听起来离个人用户比较遥远,但实际上并非如此,我甚至觉得很多玩私有服务器的人可能都会慢慢走向Homelab。即使你没有多台电脑或服务器,依然可以尝试使用Kubernetes(K8s)或K3s来管理你的容器化应用,之后如果你有了多台电脑或服务器,你可以很容易地将现有的Kubernetes集群扩展到多台机器上。
总之,Homelab具有很高的灵活性和可扩展性,可以满足个人用户的各种需求。即使你只有简单的需求和简单的硬件,也可以通过搭建Homelab来学习很多新技术和新知识。
Kubernetes(K8s)和K3s
Kubernetes(K8s)是一个开源的容器编排平台,用于自动化容器化应用的部署、扩展和管理。它可能是应用最广泛的搭建Homelab的方案。
当然,Kubernetes里的知识相当复杂,涉及到很多概念和组件,例如Pod、Service、Deployment、Ingress等。对于初学者来说,可能会觉得过于复杂而有些难以理解。K3s是Kubernetes的一个轻量级版本,专为资源受限的环境设计。它去掉了一些不必要的组件和功能,使得K3s更容易安装和管理。K3s非常适合在家庭实验室或小型集群中使用。
在这个系列的文章中,我们将从非常简单的应用出发,使用K3s从零开始搭建一个Kubernetes集群,并逐步扩展到更复杂的应用和多节点。
K3s基础知识
Kubernetes(K8s)是一个很复杂的系统,里面包含了很多组件。K3s对其做了简化,只留下了最核心的组件。我们这里也先只介绍最核心、最基本的概念,来简单了解一下K3s是怎样运作的,其他的组件和概念以后用到时再做介绍。
下图是一个单节点的服务器上K3s运行的基本框架示例:
当一个用户对某个服务做出一个请求时,运行过程是这样的:
- 当一个外部用户的请求到达K3s集群时,首先会通过Ingress Controller(通常是Traefik)来处理请求。
- Ingress Controller会根据Ingress资源定义的路由规则,将请求转发到相应的Service。
- Service会将请求转发到对应的Pod,Pod中运行着实际的应用程序容器。
另外,管理员可以通过命令行工具kubectl来管理K3s集群内的组件和资源。
接下来我们来简单介绍一下这几个概念。
Pod
Pod是Kubernetes的最小部署单元,它可以包含一个或多个容器。Pod中的容器共享网络和存储资源。Pod通常用于运行一个应用程序或服务。
Service
Service是Kubernetes中的一个抽象概念,用于定义一组Pod的访问策略。Service可以通过一个固定的IP地址和端口来访问Pod,无论Pod的实际IP地址如何变化。Service可以分为ClusterIP、NodePort、LoadBalancer等类型。
- ClusterIP:默认类型,Service只能在集群内部访问。
- NodePort:Service可以在集群外部通过指定的端口访问。
- LoadBalancer:Service可以通过云提供商的负载均衡器来访问。
Ingress和Ingress Controller
Ingress是Kubernetes中的一个资源,用于管理外部访问集群内部服务的路由规则。Ingress可以通过域名或路径来路由请求到不同的Service。Ingress通常与Ingress Controller一起使用,Ingress Controller负责实现Ingress资源定义的路由规则。
Deployment
Deployment是Kubernetes中的一个控制器,用于管理Pod的部署和更新。Deployment可以定义Pod的副本数、更新策略等。通过Deployment,我们可以轻松地扩展或缩减Pod的数量,并且可以在不影响服务可用性的情况下进行滚动更新。
K3s的安装和配置
接下来我们以一个单节点集群为例,来说明如何使用K3s。之后会介绍如果有更多节点时如何扩展集群。
这里我们选择部署一个最简单的whoami服务。
1. 安装K3s
在Linux服务器上安装K3s非常简单,只需要运行以下命令:
|
|
运行完成后,K3s会自动创建一个默认的单节点集群。当安装结束时,你会在命令行看到如下输出:
|
|
这说明这条命令做了以下工作:
- 下载并安装K3s。
- 创建了
kubectl
、crictl
和ctr
的符号链接,这些工具可以用来管理K3s集群。其中kubectl
是Kubernetes的命令行工具,用于管理Kubernetes集群。crictl
是容器运行时接口(CRI)的命令行工具,用于管理容器。ctr
是容器运行时的命令行工具,用于直接与容器运行时交互。
- 创建了
k3s-killall.sh
和k3s-uninstall.sh
脚本,用于停止和卸载K3s。- 运行命令
sudo /usr/local/bin/k3s-killall.sh
可以停止K3s服务。 - 运行命令
sudo /usr/local/bin/k3s-uninstall.sh
可以卸载K3s。
- 运行命令
- 创建了环境变量文件
/etc/systemd/system/k3s.service.env
,用于配置K3s服务。 - 创建了K3s的systemd服务文件
/etc/systemd/system/k3s.service
,并启用了该服务。之后每次电脑开机时,K3s服务都会自动启动。 - 启动了K3s服务。
2. 验证K3s安装
安装完成后,K3s会在/etc/rancher/k3s
目录下创建一个名为k3s.yaml
的配置文件。这个文件包含了K3s集群的配置信息,包括API服务器的地址、认证信息等。
上面提到,K3s还安装了一个kubectl作为管理K3s的命令行工具,kubectl运行时需要根据API服务器的地址、认证信息知道它要管理的是哪个集群。kubectl运行时默认读取/etc/rancher/k3s/k3s.yaml
文件中的配置信息,如果你不是以root来运行kubectl,会因为权限问题无法读取/etc/rancher/k3s/k3s.yaml
文件。这时我们可以将/etc/rancher/k3s/k3s.yaml
复制到~/.kube
目录下,并更改文件权限,让kubectl可以读取集群信息:
|
|
现在你可以使用kubectl来管理K3s集群了。可以运行以下命令来验证K3s是否安装成功:
|
|
如果安装成功,你应该能看到类似下面的输出:
|
|
然后查看正在运行的pods:
|
|
如果一切正常,你应该能看到类似下面的输出:
|
|
其中coredns
是Kubernetes的DNS服务,helm-install-traefik-crd
和helm-install-traefik-qkl97
是指安装了Traefik,local-path-provisioner
是K3s的默认存储类,metrics-server
是Kubernetes的监控服务。
3. 部署whoami服务
现在我们可以部署一个简单的whoami服务来测试K3s集群。whoami是一个非常简单的HTTP服务,它会返回请求的IP地址、请求头等信息,非常适合用来测试K3s集群。
创建whoami应用的manifest
K3s使用一个被称作manifest的YAML文件来定义应用程序的部署。我们可以创建一个名为whoami.yaml
的文件,内容如下:
|
|
虽然这是一个YAML文件,但实际上有三部分。这里为了简单起见,我们把这三部分放在了同一个文件里,后续的文章会说明,为了更好地组织和管理K3s里的应用,我们应该怎样组织文件结构。
这三部分用---
分隔开来,分别定义了:
- Deployment:定义了一个名为
whoami
的Deployment,表示我们要部署一个名为whoami
的应用。这个应用有1个副本(replica),使用Traefik官方提供的whoami镜像,并监听80端口。 - Service:定义了一个名为
whoami
的Service,表示我们要创建一个名为whoami
的服务。这个服务的类型是ClusterIP,表示只能在集群内部访问。它监听80端口,并将请求转发到Pod中的whoami容器的80端口。 - Ingress:定义了一个名为
whoami-ingress
的Ingress,表示我们要创建一个名为whoami-ingress
的Ingress资源。这个Ingress使用Traefik作为Ingress Controller,并将请求路由到名为whoami
的Service。
应用whoami服务
现在我们可以使用kubectl来应用这个manifest文件了。运行以下命令:
|
|
如果一切正常,你应该能看到类似下面的输出:
|
|
查看whoami服务状态
首先,我们来确认whoami服务是否已经成功部署。运行以下命令:
|
|
如果一切正常,你应该能看到类似下面的输出:
|
|
接下来,我们来确认whoami服务的Pod是否已经成功运行。运行以下命令:
|
|
如果一切正常,你应该能看到类似下面的输出:
|
|
接下来,我们来确认whoami服务的Service是否已经成功创建。运行以下命令:
|
|
如果一切正常,你应该能看到类似下面的输出:
|
|
访问whoami服务
现在我们可以通过Ingress来访问whoami服务了。首先,我们在部署whoami的电脑上,或者在同一局域网的电脑上,使用本机地址或者局域网内的地址来访问whoami服务。 如果你在本机上访问,可以使用以下命令:
|
|
如果你在局域网内的其他电脑上访问,例如你的K3s服务器的IP地址是192.168.1.233
,可以使用以下命令:
|
|
这里添加了Host
头部信息,因为Ingress需要根据这个头部信息来路由请求到对应的Service,否则Ingress怎么知道你要访问的是哪个Service呢?
如果一切正常,你应该能看到类似下面的输出:
|
|
如果你能看到类似上面的输出,说明whoami服务已经成功运行了。但是注意,这里的X-Forwarded-For
和X-Real-Ip
的值10.42.0.1
是K3s集群内部的IP地址,而不是你访问的电脑的IP地址。这是因为Ingress Controller(Traefik)会将请求转发到whoami服务时,使用了K3s集群内部的IP地址。
TODO: 如何解决这一问题?
如果你想在外部访问whoami服务,你需要将域名whoami.example.com
解析到你的K3s服务器的公网IP地址上。然后你就可以通过浏览器或其他HTTP客户端来访问whoami服务了。
如果你在浏览器中访问http://whoami.example.com
,你应该能看到类似下面的页面:
|
|
总结
在本篇文章中,我们介绍了K3s的基础知识,并演示了如何在单节点K3s集群上部署一个简单的whoami服务。
在接下来的文章中,我们将继续扩展K3s集群,介绍如何部署更复杂的应用,如何管理多节点集群,以及如何使用K3s的其他功能来满足不同的需求。
鸣谢
我在学习如何使用K3s时参考了Youtube博主LinuxCloudHacks的视频From Zero to Hero: K3s, Traefik & Cloudflare Your Home Lab Powerhouse。