k3d 入门:在 Docker 中运行 k3s

​https://www.xtplayer.cn/k3d/introduction-k3d-run-k3s-docker-src/#The-“Simple”-Way​

在本文中,我们将讨论 k3d,它是一种支持你在已经安装 Docker 的地方,一次性运行 Kubernetes 集群的工具。我知道你有问题,让我开始把。

什么是 k3d?

k3d 是用来在 Docker 中运行 K3s 集群的一个小程序。K3s 是轻量级,CNCF 认证的 Kubernetes 分发版且是沙盒项目。设计用于低资源环境下,K3s 是作为单个二进制文件发布的适用于低于 512M 内存。要学习关于 K3s 的更多内容,请参考 ​​该文档​​​,或者​​这些博客​​​,或者​​这些视频​​。

k3d 使用通过 ​​K3s 仓库​​​ 构建的 ​​Docker 镜像​​ 在已经安装 Docker 的任何机器上,在 Docker 容器中构建多个 K3s 节点。这样,单个的物理 (或者虚拟) 机 (让我们称为 Docker 宿主) 可以运行多个 K3s 集群,同时每个集群拥有多台 Server 和 agent 节点。

k3d 可以做什么?

随着 k3d 的 4.0.0 版本于 2021 年 1 月的发布,k3d 提供如下的功能:

  • 创建/停止/启动/删除/扩展/收缩 k3s 集群 (以及单独节点)
  • 通过命令行 flag
  • 通过配置文件
  • 管理和交互用于集群的容器
  • 管理集群的 kube config
  • 从本地 Docker 守护进程导入镜像到运行在集群中的容器运行时中

显然,还有更多的方式,你可以用来在细节进行调整


k3d 5.4.2 于 2022 年 7 月 6 日发布(​​https://github.com/k3d-io/k3d/releases​​)


k3d 用来做什么?

最常用的场景是,对于本地的有点复杂和资源限制的 Kubernetes 开发环境。开始的开发 k3d 的意图是为开发者提供一种简单的工具,来支持他们在其开发环境中运行轻量级的 Kubernetes 集群。为他们提供与生产环境类似的快速迭代 ( 对于在本地运行 docker-compose 与生产环境下运行 Kubernetes )。

时光推移,k3d 也演进成为运营在隔离环境下测试某些 Kubernetes 特性的工具 (或者,特指 k3s)。例如,使用 k3d,你可以轻易创建多个节点组成的集群,在其上部署应用,简单地停止某个节点,并查看 Kubernetes 的响应,比如可能将你的应用调度到其它节点上。

另外,你可以使用 k3d 在你的持续集成系统中,来快速构建集群,在其上部署测试栈,并运行集成测试。一旦完成之后,你就可以简单地解除这整个集群。不需要担心正确的清理方式和可能的残留。

我们还提供了 ​​k3d-bind​​ 镜像 (类似于电影《盗梦空间》中的梦中梦,我们可以在容器中套娃容器)。使用它,当你运行 k3d 的时候,你可以创建 docker 套 docker 的环境,它可以在 Docker 中裂变出 k3s 集群。这意味着你只需要单个容器 (k3d-bind) 运行在你的 Docker 宿主上,在其中运行整个的 k3s/Kubernetes 集群。

如何使用 k3d?

  1. 安装​​k3d​​​ (以及​​kubectl​​, 如果你希望使用它。)


注意:要演练本文内容,至少需要 k3d v4.1.1


  1. 尝试如下示例,或者使用​​官方文档​​,或者使用 CLI 的帮助来找到你自己的方式 (k3d [command] --help)

​简单​​方式

k3d cluster create

该一条命令就可以带有两个容器的 K3s 集群:一个 Kubernetes 控制位面节点 (server),以及一个前面的负载均衡器 (serverlb)。它将它们推入到独立的 Docker 网络中,并在 Docker 宿主上随机选择的端口上暴露出 Kubernetes API。它还在后台创建了一个命名的 Docker 卷,作为镜像导出的备用。

默认情况下,如果你没有名称参数,集群将被命名为 ​​k3s-default​​​,容器将被显示为 ​​k3d-<-role>-<#>​​​,因此在这里将会是 ​​k3d-k3d-default-serverlb​​​ 和 ​​k3d-k3s-default-server-0​​。

k3d 等到所有准备好之后,从集群中拉取 Kubeconfig 并将它与你的默认的 Kubeconfig 合并 (通常在 $HOME/.kube/config 或者你的 ​​KUBECONFIG​​ 环境变量执行的路径)。

不用担心,你可以调整这些行为。

使用 ​​kubectl​​​ 来检查你刚刚创建成果来输出你的节点:​​kubectl get nodes​​。

k3d 还提供了一些命令来列出你的创造:​​k3d cluster|node|registry list​

C:\Software\cncf>kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3d-k3s-default-server-0 Ready control-plane,master 84m v1.23.6+k3s1

C:\Software\cncf>k3d cluster list
NAME SERVERS AGENTS LOADBALANCER
k3s-default 1/1 0/0 true

C:\Software\cncf>k3d node list
NAME ROLE CLUSTER STATUS
k3d-k3s-default-server-0 server k3s-default running
k3d-k3s-default-serverlb loadbalancer k3s-default running
k3d-k3s-default-tools k3s-default running

C:\Software\cncf>k3d registry list
NAME ROLE CLUSTER STATUS

​简单但是优美​​ 方式

k3d cluster create mycluster --api-port 127.0.0.1:6445 --servers 3 --agents 2 --volume '/home/me/mycode:/code@agent[*]' --port '8080:80@loadbalancer'

这条命令创建带有 6 个容器的 K3s 集群:

  • 1 个负载均衡器
  • 3 个服务器 (控制位面节点)
  • 2 个 agents (以前的工作节点)

使用 ​​--api-port 127.0.0.1:6445​​​ 参数,你可以告诉 k3d 将 Kubernetes API 端口映射到 ​​127.0.0.1/localhost​​​ 的端口 6445。这意味着你可以在你的 Kubeconfig 中使用这个连接串 ​​server:https://127.0.0.1:6445​​ 来连接到集群。

本端口也会将你的负载均衡器映射到你的宿主机。从这开始,请求将被代理到你的服务器节点。有效模拟生产环境的设置,这样你的服务器节点也可以下线,你会期望它故障转移到其它节点上。

而 ​​--volume /home/me/mycode:code@agent[*]​​​ 将你的本地目录 ​​/home/me/mycode​​​ 绑定到你所有的 agent 节点的路径 ​​/code​​​ 。将 ​​*​​ 替换为索引 (这里是 0 或者 1) 来仅仅绑定到其中之一。

告诉 k3d 哪些节点应该挂载卷的规范被称为 ​​节点过滤​​​,它也被用于其它标志中,例如用于端口映射的 ​​--port​​ 标志。

也就是说,​​--port 8080:80@loadbalancer​​​ 将你的本地端口 ​​8080​​​ 映射到负载均衡器 (serverlb) 的 ​​80​​​ 端口,它可以用来转发 HTTP 入口流量到你的集群中。例如,你现在可以部署一个 web 应用到集群中 (Deployment),它可以通过类似于 ​​myapp.k3d.localhost​​ 向外部暴露出 (Service)。

然后 (提供将域名解析到你的本地宿主 IP 的所有设置),你可以使用浏览器访问 ​​http://myapp.k3d.localhost:8080​​​ 来访问你的应用。访问流量通过你的宿主穿过 Docker 网桥界面到达负载均衡器。从这里 ​​it​​ 代理集群,将流量转发到你的应用所在 Pod 中的 Service。


注意:你需要做一些设置来将你的 ​​myapp.k3d.localhost​​​ 解析到你的本地宿主 IP (127.0.0.1)。最常用的方式是在你的 ​​/etc/hosts​​ 文件 (Windows 中是 C:\Windows\System32\drivers\etc\host) 中使用如下设置:


127.0.0.1 myapp.k3d.localhost

不过,这种方式不支持统配符 (*.localhost),所以随后可能会变得琐碎,所以,你可能希望看一下这个工具 (​​https://en.wikipedia.org/wiki/Dnsmasq​​​" dnsmasq (MacOS/UNIX) or ​​https://stackoverflow.com/a/9695861/6450189​​" Acrylic (Windows)) 来简化一下。


提示: 你可以在有些系统上安装包 ​​libnss-myhostname​​​ (至少 Linux 操作系统,包括 SUSE 和 OpenSUSE) 来自动解析 ​​*.localhost​​​ 域名到 ​​127.0.01​​​,这样你就不需要反复处理 ​​/etc/hosts​​ 文件,如果你倾向于通过 Ingress 测试,你需要设置一个域名。


有趣的一件事需要提示一下:如果你创建了多于 1 个的服务器节点,K3s 将提供 ​​--cluster-init​​ 参数,这意味着它切换内部的数据存储 (默认是 SQLite) 用于 etcd。

配置即代码方式

从 k3d v4.0.0 ( 2021 年 1月) 开始,我们支持使用配置文件来通过代码配置所有你前面使用命令参数方式的配置。

在本文编写的时候,用来验证配置文件有效性的 ​​JSON Schema 可以在这里找到​

这里是一个配置文件示例:

# k3d configuration file, saved as e.g. /home/me/myk3dcluster.yaml
apiVersion: k3d.io/v1alpha2 # this will change in the future as we make everything more stable
kind: Simple # internally, we also have a Cluster config, which is not yet available externally
name: mycluster # name that you want to give to your cluster (will still be prefixed with `k3d-`)
servers: 1 # same as `--servers 1`
agents: 2 # same as `--agents 2`
kubeAPI: # same as `--api-port 127.0.0.1:6445`
hostIP: "127.0.0.1"
hostPort: "6445"
ports:
- port: 8080:80 # same as `--port 8080:80@loadbalancer
nodeFilters:
- loadbalancer
options:
k3d: # k3d runtime settings
wait: true # wait for cluster to be usable before returining; same as `--wait` (default: true)
timeout: "60s" # wait timeout before aborting; same as `--timeout 60s`
k3s: # options passed on to K3s itself
extraServerArgs: # additional arguments passed to the `k3s server` command
- --tls-san=my.host.domain
extraAgentArgs: [] # addditional arguments passed to the `k3s agent` command
kubeconfig:
updateDefaultKubeconfig: true # add new cluster to your default Kubeconfig; same as `--kubeconfig-update-default` (default: true)
switchCurrentContext: true # also set current-context to the new cluster's context; same as `--kubeconfig-switch-context` (default: true)

假设我们将它保存为文件 ​​/home/me/myk3dcluster.yaml​​,你可以如下使用它来配置一个集群。

k3d cluster create --config /home/me/myk3dcluster.yaml

注意,你仍然可以使用额外的参数,它们优先于配置文件中的配置使用。

还可以使用 k3d 做什么?

你可以使用更多方式来使用 k3d ,包括:

  • 与使用 k3d-managed 容器一起创建集群
  • 使用带有热代码重载的快速部署集群
  • 使用 k3d 来合并其它开发工具,例如​​Tile​​​ 或者​​Skaffold​
  • 它们都可以借助于​​k3d image import​​ 导入镜像的能力
  • 它们都可以替换来使用 k3d 托管来加速你的开发循环

你可以尝试预先在演示仓库中准备好的脚本,或者观看我们在研讨会上展示的结果。

另外,记住 K3d 是一个社区驱动的项目,所以我们总是高兴地听取来自你的声音。

参考资料