@wxy
This commit is contained in:
Xingyu Wang 2020-07-12 10:09:54 +08:00
parent 394ae0d4a0
commit 54877598ce

View File

@ -1,6 +1,6 @@
[#]: collector: (lujun9972) [#]: collector: (lujun9972)
[#]: translator: (wxy) [#]: translator: (wxy)
[#]: reviewer: ( ) [#]: reviewer: (wxy)
[#]: publisher: ( ) [#]: publisher: ( )
[#]: url: ( ) [#]: url: ( )
[#]: subject: (Add nodes to your private cloud using Cloud-init) [#]: subject: (Add nodes to your private cloud using Cloud-init)
@ -12,22 +12,21 @@
> 像主流云提供商的处理方式一样,在家中添加机器到你的私有云。 > 像主流云提供商的处理方式一样,在家中添加机器到你的私有云。
![Digital images of a computer desktop][1] ![](https://img.linux.net.cn/data/attachment/album/202007/12/100823rj096h3ax4hhehey.jpg)
[Cloud-init][2] 是一种广泛使用的行业标准方法,用于初始化云实例。云提供商使用 Cloud-init 来定制实例的网络配置、实例信息,甚至用户提供的配置指令。它也是一个可以在你的“家庭私有云”中使用的很好的工具,可以为你的家庭实验室的虚拟机和物理机的初始设置和配置添加一点自动化 —— 并了解更多关于大型云提供商是如何工作的信息。关于更多的细节和背景,请看我之前的文章《[在你的树莓派家庭实验室中使用 Cloud-init][3]》。 [Cloud-init][2] 是一种广泛使用的行业标准方法,用于初始化云实例。云提供商使用 Cloud-init 来定制实例的网络配置、实例信息,甚至用户提供的配置指令。它也是一个可以在你的“家庭私有云”中使用的很好的工具,可以为你的家庭实验室的虚拟机和物理机的初始设置和配置添加一点自动化 —— 并了解更多关于大型云提供商是如何工作的信息。关于更多的细节和背景,请看我之前的文章《[在你的树莓派家庭实验室中使用 Cloud-init][3]》。
![A screen showing the boot process for a Linux server running Cloud-init ][4] ![A screen showing the boot process for a Linux server running Cloud-init ][4]
*运行 Cloud-init 的 Linux 服务器的启动过程Chris Collins[CC BY-SA 4.0][5]* *运行 Cloud-init 的 Linux 服务器的启动过程Chris Collins[CC BY-SA 4.0][5]*
诚然Cloud-init 对于为许多不同客户配置机器的云提供商来说,比对于由单个系统管理员运行的家庭实验室更有用,而且 Cloud-init 解决的许多问题对于家庭实验室来说可能有点多余。然而,设置它并了解它的工作原理是了解更多关于这种云技术的好方法,更不用说它是首次启动时配置设备的好方法。 诚然Cloud-init 对于为许多不同客户配置机器的云提供商来说,比对于由单个系统管理员运行的家庭实验室更有用,而且 Cloud-init 解决的许多问题对于家庭实验室来说可能有点多余。然而,设置它并了解它的工作原理是了解更多关于这种云技术的好方法,更不用说它是首次启动时配置设备的好方法。
本教程使用 Cloud-init 的 NoCloud 数据源,它允许 Cloud-init 在传统的云提供商环境之外使用。本文将向你展示如何在客户端设备上安装 Cloud-init并设置一个运行 Web 服务的容器来响应客户端的请求。你还将学习查客户端从 Web 服务中请求的内容,并修改 Web 服务的容器,以提供基本的、静态的 Cloud-init 服务。 本教程使用 Cloud-init 的 NoCloud 数据源,它允许 Cloud-init 在传统的云提供商环境之外使用。本文将向你展示如何在客户端设备上安装 Cloud-init并设置一个运行 Web 服务的容器来响应客户端的请求。你还将学习如何审查客户端从 Web 服务中请求的内容,并修改 Web 服务的容器,以提供基本的、静态的 Cloud-init 服务。
### 在现有系统上设置 Cloud-init ### 在现有系统上设置 Cloud-init
Cloud-init 可能在新系统首次启动时最有用,它可以查询配置数据,并根据指令对系统进行定制。它可以[包含在树莓派和单板计算机的磁盘镜像中][6],也可以添加到用于<ruby>配给<rt>provision</rt></ruby>虚拟机的镜像中。对于测试用途来说,在现有系统上安装并运行 Cloud-init或者安装一个新系统,然后设置 Cloud-init都是很容易的。 Cloud-init 可能在新系统首次启动时最有用,它可以查询配置数据,并根据指令对系统进行定制。它可以[包含在树莓派和单板计算机的磁盘镜像中][6],也可以添加到用于<ruby>配给<rt>provision</rt></ruby>虚拟机的镜像中。对于测试用途来说,无论是在现有系统上安装并运行 Cloud-init还是安装一个新系统,然后设置 Cloud-init都是很容易的。
作为大多数云提供商使用的主要服务,大多数 Linux 发行版都支持 Cloud-init。在这个例子中我将使用 Fedora 31 Server 来安装树莓派,但在 Raspbian、Ubuntu、CentOS 和大多数其他发行版上也可以用同样的方式来完成。 作为大多数云提供商使用的主要服务,大多数 Linux 发行版都支持 Cloud-init。在这个例子中我将使用 Fedora 31 Server 来安装树莓派,但在 Raspbian、Ubuntu、CentOS 和大多数其他发行版上也可以用同样的方式来完成。
@ -40,7 +39,7 @@ Cloud-init 可能在新系统首次启动时最有用,它可以查询配置数
dnf install -y cloud-init dnf install -y cloud-init
``` ```
Cloud-init 实际上是四个不同的服务(至少在 systemd 下是这样),每个服务都负责检索配置数据,并在启动过程的不同部分进行配置更改,这使得可以做的事情更加灵活。虽然你不太可能直接与这些服务进行太多交互,但在你需要排除一些故障时,知道它们是什么还是很有用的。它们是: Cloud-init 实际上是四个不同的服务(至少在 systemd 下是这样),这些服务负责检索配置数据,并在启动过程的不同阶段进行配置更改,这使得可以做的事情更加灵活。虽然你不太可能直接与这些服务进行太多交互,但在你需要排除一些故障时,知道它们是什么还是很有用的。它们是:
* cloud-init-local.service * cloud-init-local.service
* cloud-init.service * cloud-init.service
@ -59,13 +58,13 @@ systemctl enable cloud-final.service
#### 配置数据源以查询 #### 配置数据源以查询
启用服务后,请配置数据源,客户端将从该数据源查询配置数据。有[大量的数据源类型][7],而且大多数都是为特定的云提供商配置的。对于你的家庭实验室,请使用 NoCloud 数据源,(如上所述)是为在没有云提供商的情况下使用 Cloud-init 而设计的。 启用服务后,请配置数据源,客户端将从该数据源查询配置数据。有[许多数据源类型][7],而且大多数都是为特定的云提供商配置的。对于你的家庭实验室,请使用 NoCloud 数据源,(如上所述)是为在没有云提供商的情况下使用 Cloud-init 而设计的。
NoCloud 允许以多种方式包含配置信息:以内核参数中的键/值对,用于在启动时安装的 CD或虚拟机中的虚拟 CD包含在文件系统中的文件中或者像本例中一样,通过 HTTP 从指定的 URL“NoCloud Net” 选项)获取配置信息。 NoCloud 允许以多种方式包含配置信息:以内核参数中的键/值对,用于在启动时挂载的 CD或虚拟机中的虚拟 CD包含在文件系统中的文件中或者像本例中一样,通过 HTTP 从指定的 URL“NoCloud Net” 选项)获取配置信息。
数据源配置可以通过内核参数提供,也可以在 Cloud-init 配置文件 `/etc/cloud/cloud.cfg` 中进行设置。该配置文件对于使用自定义磁盘镜像设置 Cloud-init 或在现有主机上进行测试非常有效 数据源配置可以通过内核参数提供,也可以在 Cloud-init 配置文件 `/etc/cloud/cloud.cfg` 中进行设置。该配置文件对于使用自定义磁盘镜像设置 Cloud-init 或在现有主机上进行测试非常方便
Cloud-init 还会合并在 `/etc/cloud/cloud.cfg.d/` 中找到的任何 `*.cfg` 文件中的配置数据,因此为了保持干净,请在 `/etc/cloud/cloud.cfg.d/10_datasource.cfg` 中配置数据源。Cloud-init 可以通过使用以下语法从带有 `seedfrom` 键的 HTTP 数据源中读取数据。 Cloud-init 还会合并在 `/etc/cloud/cloud.cfg.d/` 中找到的任何 `*.cfg` 文件中的配置数据,因此为了保持整洁,请在 `/etc/cloud/cloud.cfg.d/10_datasource.cfg` 中配置数据源。Cloud-init 可以通过使用以下语法从 `seedfrom`指向的 HTTP 数据源中读取数据。
``` ```
seedfrom: http://ip_address:port/ seedfrom: http://ip_address:port/
@ -85,7 +84,7 @@ datasource:
    seedfrom: http://ip_address:port/     seedfrom: http://ip_address:port/
``` ```
客户端设置就是这样。现在,重新启动客户端后,它将尝试从你在 `seedfrom` 中输入的 URL 检索配置数据,并进行必要的任何配置更改。 客户端设置就是这样。现在,重新启动客户端后,它将尝试从你在 `seedfrom` 中输入的 URL 检索配置数据,并进行必要的任何配置更改。
下一步是设置一个 Web 服务器来侦听客户端请求,以便你确定需要提供的服务。 下一步是设置一个 Web 服务器来侦听客户端请求,以便你确定需要提供的服务。
@ -93,9 +92,9 @@ datasource:
你可以使用 [Podman][8] 或其他容器编排工具(如 Docker 或 Kubernetes快速创建和运行 Web 服务器。这个例子使用的是 Podman但同样的命令也适用于 Docker。 你可以使用 [Podman][8] 或其他容器编排工具(如 Docker 或 Kubernetes快速创建和运行 Web 服务器。这个例子使用的是 Podman但同样的命令也适用于 Docker。
要开始,请使用 `fedora:31` 容器镜像并创建一个 Containerfile对于 Docker 来说,这会是一个 Dockerfile来安装和配置 Nginx。从该 Containerfile 中,你可以构建一个自定义镜像,并在你希望提供 Cloud-init 服务的主机上运行它。 要开始,请使用 `fedora:31` 容器镜像并创建一个容器文件(对于 Docker 来说,这会是一个 Dockerfile来安装和配置 Nginx。从该容器文件中,你可以构建一个自定义镜像,并在你希望提供 Cloud-init 服务的主机上运行它。
创建一个包含以下内容的 Containerfile 创建一个包含以下内容的容器文件
``` ```
FROM fedora:31 FROM fedora:31
@ -128,13 +127,13 @@ USER 1001
CMD ["nginx", "-g", "daemon off;"] CMD ["nginx", "-g", "daemon off;"]
``` ```
注:本例中使用的 Containerfile 和其他文件可以在本项目的 [GitHub 仓库][9]中找到。 注:本例中使用的容器文件和其他文件可以在本项目的 [GitHub 仓库][9]中找到。
上面 Containerfile 中最重要的部分是改变日志存储方式的部分(写到 STDOUT 而不是文件),这样你就可以在容器日志中看到进入该服务器的请求。其他的一些改变使你可以在没有 root 权限的情况下使用 Podman 运行容器,也可以在没有 root 权限的情况下运行容器中的进程。 上面容器文件中最重要的部分是改变日志存储方式的部分(写到 STDOUT 而不是文件),这样你就可以在容器日志中看到进入该服务器的请求。其他的一些改变使你可以在没有 root 权限的情况下使用 Podman 运行容器,也可以在没有 root 权限的情况下运行容器中的进程。
在 Web 服务器上的第一个测试并不提供任何 Cloud-init 数据;只是用它来查看 Cloud-init 客户端的请求。 在 Web 服务器上的第一个测试并不提供任何 Cloud-init 数据;只是用它来查看 Cloud-init 客户端的请求。
创建 Containerfile 后,使用 Podman 构建并运行 Web 服务器镜像: 创建容器文件后,使用 Podman 构建并运行 Web 服务器镜像:
``` ```
# Build the container image # Build the container image
@ -145,7 +144,7 @@ $ podman build -f Containerfile -t cloud-init:01 .
$ podman run --rm -p 8080:8080 -it cloud-init:01 $ podman run --rm -p 8080:8080 -it cloud-init:01
``` ```
这会运行容器,让你的终端连接到一个伪 TTY。一开始看起来什么都没有发生但是对主机 8080 端口的请求会被路由到容器内的 Nginx 服务器,并且在终端窗口中会出现一条日志信息。这一点可以用主机上的 `curl` 命令进行测试。 这会运行一个容器,让你的终端连接到一个伪 TTY。一开始看起来什么都没有发生但是对主机 8080 端口的请求会被路由到容器内的 Nginx 服务器,并且在终端窗口中会出现一条日志信息。这一点可以用主机上的 `curl` 命令进行测试。
``` ```
# Use curl to send an HTTP request to the Nginx container # Use curl to send an HTTP request to the Nginx container
@ -169,7 +168,7 @@ $ curl http://localhost:8080
注:使用 `Ctrl+C` 停止正在运行的容器。 注:使用 `Ctrl+C` 停止正在运行的容器。
你可以看到请求是针对 `/meta-data` 路径的,即 `http://ip_address_of_the_webserver:8080/meta-data`。这只是一个 GET 请求 —— Cloud-init 并没有向 webserver 发送任何数据。它只是盲目地从数据源 URL 中请求文件,所以要由数据源来识别主机的要求。这个简单的例子只是向任何客户端发送通用数据,但一个更大的家庭实验室应该需要更复杂的服务。 你可以看到请求是针对 `/meta-data` 路径的,即 `http://ip_address_of_the_webserver:8080/meta-data`。这只是一个 GET 请求 —— Cloud-init 并没有向 Web 服务器发送任何数据。它只是盲目地从数据源 URL 中请求文件,所以要由数据源来识别主机的要求。这个简单的例子只是向任何客户端发送通用数据,但一个更大的家庭实验室应该需要更复杂的服务。
在这里Cloud-init 请求的是[实例元数据][10]信息。这个文件可以包含很多关于实例本身的信息,例如实例 ID、分配实例的主机名、云 ID甚至网络信息。 在这里Cloud-init 请求的是[实例元数据][10]信息。这个文件可以包含很多关于实例本身的信息,例如实例 ID、分配实例的主机名、云 ID甚至网络信息。
@ -187,7 +186,7 @@ hostname: raspberry
`local-hostname``hostname` 键正如其名,它们会在 Cloud-init 运行时为客户端设置主机名信息。 `local-hostname``hostname` 键正如其名,它们会在 Cloud-init 运行时为客户端设置主机名信息。
Containerfile 中添加以下行以将 `meta-data` 文件复制到新镜像中。 容器文件中添加以下行以将 `meta-data` 文件复制到新镜像中。
``` ```
# Copy the meta-data file into the image for Nginx to serve it # Copy the meta-data file into the image for Nginx to serve it
@ -214,9 +213,9 @@ podman run --rm -p 8080:8080 -it cloud-init:02
你看,这次 `/meta-data` 路径被提供给了客户端。成功了! 你看,这次 `/meta-data` 路径被提供给了客户端。成功了!
然而,客户端接着在 `/user-data` 路径上寻找第二个文件。该文件包含实例所有者提供的配置数据,而不是来自云提供商的数据。对于一个家庭实验室来说,这两个都是你自己。 然而,客户端接着在 `/user-data` 路径上寻找第二个文件。该文件包含实例所有者提供的配置数据,而不是来自云提供商的数据。对于一个家庭实验室来说,这两个都是你自己提供的
你可以使用[大量的 user-data 模块][11]来配置你的实例。对于这个例子,只需使用 `write_files` 模块在客户端创建一些测试文件,并验证 Cloud-init 是否工作。 你可以使用[许多 user-data 模块][11]来配置你的实例。对于这个例子,只需使用 `write_files` 模块在客户端创建一些测试文件,并验证 Cloud-init 是否工作。
创建一个包含以下内容的用户数据文件: 创建一个包含以下内容的用户数据文件:
@ -239,7 +238,7 @@ write_files:
除了使用 Cloud-init 提供的 `user-data` 模块制作 YAML 文件外,你还可以将其制作成一个可执行脚本供 Cloud-init 运行。 除了使用 Cloud-init 提供的 `user-data` 模块制作 YAML 文件外,你还可以将其制作成一个可执行脚本供 Cloud-init 运行。
创建 `user-data` 文件后,在 Containerfile 中添加以下行,以便在重建映像时将其复制到镜像中: 创建 `user-data` 文件后,在容器文件中添加以下行,以便在重建映像时将其复制到镜像中:
``` ```
# Copy the user-data file into the container image # Copy the user-data file into the container image
@ -267,12 +266,12 @@ podman run --rm -p 8080:8080 -it cloud-init:03
### 验证 Cloud-init 已运行 ### 验证 Cloud-init 已运行
从上面的日志中,你知道 Cloud-init 在客户端主机上运行并请求元数据和用户数据文件,但它是否对它们做了什么?你可以在 `write_files` 部分验证 Cloud-init 是否写入了你在用户数据文件中添加的文件。 从上面的日志中,你知道 Cloud-init 在客户端主机上运行并请求元数据和用户数据文件,但它它们做了什么?你可以在 `write_files` 部分验证 Cloud-init 是否写入了你在用户数据文件中添加的文件。
在 Cloud-init 客户端上,检查 `/srv/foo``/srv/bar` 文件的内容: 在 Cloud-init 客户端上,检查 `/srv/foo``/srv/bar` 文件的内容:
``` ```
# cd /srv/ &amp;&amp; ls # cd /srv/ && ls
bar foo bar foo
# cat foo # cat foo
"Does cloud-init work?" "Does cloud-init work?"
@ -282,7 +281,7 @@ bar foo
成功了!文件已经写好了,并且有你期望的内容。 成功了!文件已经写好了,并且有你期望的内容。
如上所述,还有很多其他模块可以用来配置主机。例如,用户数据文件可以配置成用 `apt` 添加包、复制 SSH `authorized_keys`、创建用户和组、配置和运行配置管理工具等等。我在家里的私有云中使用它来复制我的 `authorized_keys`、创建一个本地用户和组,并设置 sudo 权限。 如上所述,还有很多其他模块可以用来配置主机。例如,用户数据文件可以配置成用 `apt` 添加包、复制 SSH `authorized_keys`、创建用户和组、配置和运行配置管理工具等等。我在家里的私有云中使用它来复制我的 `authorized_keys`、创建一个本地用户和组,并设置 sudo 权限。
### 你接下来可以做什么 ### 你接下来可以做什么
@ -297,7 +296,7 @@ via: https://opensource.com/article/20/5/create-simple-cloud-init-service-your-h
作者:[Chris Collins][a] 作者:[Chris Collins][a]
选题:[lujun9972][b] 选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy) 译者:[wxy](https://github.com/wxy)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出