Ubuntu 20.04安装CFEngine社区版:详细指南与最佳实践
引言
CFEngine 是一款可扩展的IT基础设施配置管理工具。它允许您使用相同的工具和策略语言来管理基础设施中的所有内容,包括:Linux、Mac、Windows、BSD、Solaris、IBM AIX、HP-UX以及其他系统。您只需在每台需要管理的机器上安装一个用 C 语言编写的代理程序。CFEngine 支持多种平台,并且适用于资源受限的环境,例如大型基础设施或小型物联网 (IoT) 设备。
在本教程中,您将在 Ubuntu 20.04 上安装 CFEngine Community Edition 3.21,编写示例策略文件,并自动化您的策略运行。
先决条件
完成本教程,您需要准备以下材料:
- 一台安装了 Ubuntu 20.04 服务器,并配置了非 root 用户的 sudo 权限。您可以参考我们的指南《Ubuntu 20.04 初始服务器设置》来完成此步骤。
- 一种运行 shell 命令(包括 sudo)的方式,例如 SSH。
- 一个文本编辑器。本教程使用 nano。
第一步 — 安装 CFEngine
在这个步骤中,您将使用 apt 和软件包仓库安装 CFEngine。使用 apt 进行安装的主要优势是以后可以使用 apt 来更新 CFEngine。
CFEngine 还有其他安装方式,适用于不同的使用场景:
- cf-remote 是一个灵活的选择,支持在多台机器上安装、不同版本的 CFEngine 以及每夜构建版本。
- 快速安装 shell 脚本 是单机安装的良好选择。您只需将一个命令复制到终端即可完成安装。
- 您也可以直接从官方网站下载软件包。
如果您使用这些替代方法之一来安装 CFEngine 社区版或企业版,请跳到“第二步 — 启动 CFEngine”,或者在引导之后转到“第三步 — 创建您的第一个策略”。
添加 CFEngine 的公钥
要使用 apt 安装 CFEngine,需要使 apt 能够访问存储库。第一步是将 CFEngine 公共 GPG 密钥添加到 apt 密钥集合中,以便 apt 可以信任存储库中的软件包。
使用以下命令下载密钥:
- wget https://cfengine.com/pub/gpg.key -O ~/cfengine-gpg.key
然后使用 apt-key 添加它:
- sudo apt-key add ~/cfengine-gpg.key
添加 CFEngine 软件包仓库
接下来,您需要使用以下命令将 CFEngine 存储库添加为 apt 源:
- sudo sh -c “echo ‘deb https://cfengine-package-repos.s3.amazonaws.com/pub/apt/packages stable main’ > /etc/apt/sources.list.d/cfengine-community.list”
这个命令将 CFEngine 仓库添加到 apt 源列表目录中的一个文件中。
如果没有指定 sh
参数和 -c
选项,该命令将会出现“权限被拒绝”的错误,因为 sudo
并没有执行输出重定向操作。为了解决这个问题,你可以使用 sh
命令通过 sudo
运行一个 shell,并通过 -c
选项将命令传递给它。
现在,运行更新命令,使 apt 能够看到来自 CFEngine 仓库的新包:
- sudo apt update
使用 apt 安装软件包
现在 CFEngine 软件包已经在 apt 中注册,您可以使用 apt 安装 CFEngine:
- sudo apt install cfengine-community
如果您收到关于该软件包在不同(较旧)操作系统上构建的警告,您可以忽略它。该软件包仍然可以正常使用。
验证安装
当安装完成后,您将在 /var/cfengine/bin
中看到组成 CFEngine 的各个组件。其中,代理(cf-agent
)是您将最常与之互动的组件。该二进制文件评估您编写的策略,对系统进行更改,并记录所执行的操作。默认情况下,代理将每五分钟唤醒一次,如果需要,获取新的策略并强制执行。
请使用以下命令来检查代理程序是否成功安装:
- sudo cf-agent –version
版本号将被打印到屏幕上。
CFEngine Core 3.21.0
注意:目前版本为 3.21.0,您的版本号可能有所不同。如果 cf-agent
命令无效,请检查您的 PATH 变量中是否包含 /var/cfengine/bin/
,以及该目录中是否存在 cf-agent
。
您还可以在 /var/log/CFEngine-Install.log
中查看安装日志文件,获取一些关于出错原因的提示。
第二步 — 启动 CFEngine
要启动 CFEngine,您需要引导代理。使用以下命令来执行此操作:
- sudo cf-agent –bootstrap 127.0.0.1
这个命令告诉代理启动 CFEngine 组件,并从本机(127.0.0.1)获取策略。
将来,您将希望多台机器从同一台服务器中获取策略。在这种情况下,127.0.0.1 将被该服务器的 IP 地址所代替。然而,在本教程中为了入门和学习 CFEngine,您将只使用一台机器和 127.0.0.1。
您现在已经在服务器上安装并运行了 CFEngine。下一步是开始编写策略。
第三步 — 创建您的第一个策略
这是文章《Ubuntu 20.04安装CFEngine社区版指南》的第2部分(共4部分)。
使用CFEngine自动化系统管理任务时,您将创建一个策略文件,该文件使用CFEngine自己的领域专用语言(DSL)编写。要了解有关策略语言的更多信息,例如其功能和结构,可以查阅CFEngine参考文档。
策略文件与脚本不同,它们是声明性的:您描述系统的期望状态,CFEngine将检查是否已达到该状态,并仅在必要时进行更改。一些可能需要在策略中表达的示例有:
- 确保用户sammy存在。
- 保持curl软件包更新(并已安装)。
- 确保telnet未安装。
- 根据模板和数据渲染脚本文件。
- 如果httpd等进程正在运行,则停止它。
- 对/usr/bin文件夹强制执行严格权限。
在所有这些情况下,您都需要编写策略并将其放置在服务器的正确位置(/var/cfengine/masterfiles)。然后,CFEngine会:
- 通过将策略文件传输到其他已引导的主机来自动化策略分发。
- 定期执行您的要求(默认情况下每五分钟运行一次策略)。例如,如果有人删除了用户sammy,或更改了/usr/bin的权限,这些更改将在五分钟内自动恢复。
- 仅在必要时进行更改,例如写入文件(即,如果状态尚未达到期望)。
- 为您处理许多平台差异(例如,用于安装软件包、创建用户和其他操作的命令因操作系统而异)。
在这一步骤中,您将创建一个“Hello World”策略,将文本“Hello!”输出到终端上。
使用nano或您最喜欢的文本编辑器创建一个新文件,~/hello_world.cf
。
- nano ~/hello_world.cf
在文件中添加以下内容。
bundle agent main
{
reports:
"Hello!";
}
CFEngine的策略是声明性的,不是从上到下进行评估。
在CFEngine策略语言中,您对所管理内容的每个声明都被称为“承诺”(promise)。承诺被组织成“捆绑”(bundle)。捆绑非常有用,因为它们允许您选择运行策略的哪些部分(以及哪些部分不运行)以及它们的运行顺序。
在这个策略中,reports
是一种承诺类型,负责将消息打印到终端。在bundle
之后使用了agent
关键字,表示这个捆绑是供cf-agent
组件使用的。这个捆绑的名称是main
。捆绑序列指定了要评估的捆绑。默认情况下,它包含了main
捆绑,所以您不需要改动它。
保存并关闭文件。在使用nano时,按下CTRL+X
退出,按Y
保存,按ENTER
确认文件名并关闭文件。
由于CFEngine通常以root用户身份运行,所以它试图通过对策略文件要求严格权限来防止未经授权的系统更改。(允许其他用户编辑CFEngine运行的策略文件将使他们能够以特权用户的身份对系统进行更改)您可以使用chmod
来编辑文件权限,从而防止其他用户编辑此文件。
- chmod 600 hello_world.cf
运行该策略时,请使用以下命令:
- sudo cf-agent ~/hello_world.cf
CFEngine代理程序根据主名称找到您的捆绑,检查其中的承诺并评估它们。在评估承诺时,代理程序会检查是否需要对系统进行修改。在这种情况下,只有一个承诺,代理程序确定需要在终端打印一条消息来满足它。
您将收到以下输出:
R: Hello!
默认情况下,CFEngine会跟踪已完成的操作,并跳过最近评估的承诺(在最后一分钟内)。如果您尝试重新运行策略,它不会打印任何内容。您可以使用 --no-lock
命令行选项来禁用此锁定。
- sudo cf-agent –no-lock hello_world.cf
您已经创建并运行了您的第一个策略。虽然能够在控制台上输出很有用,但这个策略实际上并没有改变系统。在下一步中,您将会进行改变。
第四步 — 编写管理文本文件内容的策略
在之前的步骤中,您创建了一个策略,用于在终端打印一条消息。然而,更实际的用例是确保在基础设施的所有主机上存在一个带有特定内容的文件。在这一步中,您将编写一个策略,创建一个名为/tmp/my_file.txt
的文本文件,其内容为“Hello, CFEngine!”。
打开一个新的策略文件,~/file_management.cf
。
- nano ~/file_management.cf
请添加以下内容:
bundle agent manage_my_file
{
files:
"/tmp/my_file.txt"
content => "Hello, CFEngine!$(const.n)";
}
这个捆绑包的名称是 manage_my_file
,而不是 main
。当你编写更多策略时,应该为每个捆绑包取一个独特且描述性的名称。请注意,只能有一个主要的捆绑包。
由于该策略管理文件,因此承诺类型是 files
。content
属性用于文件承诺,它指定了文件的内容。字符串的最后部分 $(const.n)
会展开一个特殊变量 const.n
,其结果是在文件末尾添加一个新行。
保存并关闭文件。
与之前一样,在策略文件上设置严格的权限:
- chmod 600 file_management.cf
现在,使用一些附加的命令行选项运行该文件:
- sudo cf-agent –no-lock –info ~/file_management.cf –bundle manage_my_file
由于不再有主要的捆绑包,因此必须使用 --bundle manage_my_file
来指定要运行的捆绑包。
--info
选项会使 CFEngine 打印关于其对系统所做更改的信息性消息。
该命令的输出将包含关于这些变化的信息:
info: Using command line specified bundlesequence info: Created file ‘/tmp/my_file.txt’, mode 0600 info: Updated file ‘/tmp/my_file.txt’ with content ‘Hello, CFEngine!’
这个输出表明 CFEngine 在 /tmp
目录下创建了一个名为 my_file.txt
的文本文件,其内容为“Hello, CFEngine!”。
如果您再次运行相同的命令,关于创建和更新文件的消息将不会再显示。CFEngine 会识别到文件的内容已经是正确的,并且不会进行任何更改。
注意:在编写和测试策略文件时,通常会同时使用 --no-lock
和 --info
参数。为了减少输入,有一些快捷方式可用;-KI
等同于 --no-lock --info
。现在您已经有了一个可工作的系统策略,您可能希望在没有您监督的情况下运行它。您将在下一步中完成这个任务。
步骤5 — 自动化策略执行
您可能不希望一直在命令行中手动运行策略。CFEngine 包含了自动化功能来处理这个问题。
在这一步中,您将通过将策略文件放置在预期位置并更新 JSON 文件来自动运行策略。该 JSON 文件会定期告诉 CFEngine 组件在后台执行何种操作,而无需您明确地手动从命令行运行命令。
使用以下命令将您在上一步骤中创建的策略文件复制到推荐位置:
- sudo cp file_management.cf /var/cfengine/masterfiles/services/
所有的 CFEngine 策略都位于 /var/cfengine/masterfiles/
目录下。这包括了 CFEngine 自带但您并未编写的策略文件。为了将您的自定义策略与默认策略分开,建议将您的策略文件放在 services/
子目录中。
当 CFEngine 代理获取新的策略文件时,它们会将其从主控机上的这个目录复制过来。即使您只使用一台机器,代理的工作方式仍然相同:它会在 /var/cfengine/masterfiles
中查找文件,并将其复制到 /var/cfengine/inputs
中。对于新用户来说,最好使用这些路径。自定义路径或将策略文件放在其他位置需要更多工作,因为您必须确保权限、复制和查找文件的正确性。
接下来,创建一个增量 JSON 文件来指定策略文件的位置以及应该运行的捆绑包。
- sudo nano /var/cfengine/masterfiles/def.json
将以下内容添加到该文件中:
/var/cfengine/masterfiles/def.json
文件。
{
"inputs": [ "services/file_management.cf" ],
"vars": {
"control_common_bundlesequence_end": [ "manage_my_file" ]
}
}
要使您的策略定期运行(每五分钟一次),需要两个步骤:确保代理找到并读取文件,并确保代理运行您的捆绑程序。
在 def.json
中的 inputs
键会告诉智能体要读取哪些策略文件。在这种情况下,智能体将读取您在上一步中创建的策略文件,即 file_management.cf
。
vars
关键字可以用于定义变量。control_common_bundlesequence_end
变量在默认策略中使用,因此您在那里放置的任何束名称都将添加到 bundlesequence
的末尾,并在所有默认束之后进行评估。这两个信息一起意味着 cf-agent
在不必从命令行指定这些内容的情况下,知道要读取哪些策略文件以及其中的哪些束进行评估。
在这一点上,您正在 /var/cfengine/masterfiles/
中编辑策略,自动化会处理其余的事情。更具体地说,cf-agent
会定期唤醒并获取您编写的新策略文件。代理将读取和评估策略,并根据需要执行所有承诺,并对机器进行必要的更改(例如编辑文件和创建用户)。
根据您在本教程中编写的策略,每次代理程序运行时,它都会确保 /tmp/my_file.txt
文件存在且其内容符合策略文件中的规定。
保存并关闭文件。
为确认自动化正在运行,请删除您首次运行文件管理策略时创建的文本文件。
- sudo rm /tmp/my_file.txt
五分钟后,您可以确认 CFEngine 是否在后台重新创建了 my_file.txt
。
- cat /tmp/my_file.txt
Hello, CFEngine.
或者,您还可以强制更早地创建文件。
- sudo rm /tmp/my_file.txt ; sudo cf-agent -Kf update.cf ; sudo cf-agent -KI
rm
命令会删除文件,因此 CFEngine 会认为需要进行更改。
第一个 cf-agent
命令会更新策略文件,将其从 /var/cfengine/masterfiles
复制到 /var/cfengine/inputs
。
最后的 cf-agent
命令强制执行您的策略,使其寻找 /tmp/my_file.txt
文件,必要时创建并编辑它。
在这种情况下,您在删除文件后立即运行代理程序,所以 cf-agent
应该打印出它创建了该文件。(这两个命令之间后台运行代理程序的机会几乎没有。)
注意:命令 sudo cf-agent -Kf update.cf; sudo cf-agent -KI
与 CFEngine 默认每隔五分钟运行的命令相似。因此,如果 CFEngine 正常工作,则运行此命令应具有等待五分钟的相同结果。第一次代理运行更新策略,第二次运行评估策略并对系统进行更改。在这一步中,您已经使用 CFEngine 自动化了您的第一个系统管理任务。虽然本例重点是创建和编辑文件,但对于其他任务的过程是相同的:编写策略,放置在正确的目录中,然后相应地更新 def.json
文件。
结论
您现在已经在一台服务器上安装并启动了 CFEngine。您编写了您的第一个策略,并设置它自动运行。
下一步,您可以查看 CFEngine 官方文档,比如关于文件管理的教程:创建、修改和删除文件。
如果您有任何问题或需要帮助,请随时在 CFEngine 的 GitHub 讨论区中发布。