Cloud-Config脚本简介

来自菜鸟教程
(重定向自Cloud-Config脚本简介
跳转至:导航、​搜索

介绍

在最近的发行版上可用的 cloud-init 程序(在撰写本文时只有 Ubuntu 14.04 和 CentOS 7)能够使用和执行来自 DigitalOcean 的 user-data 字段的数据元数据服务。 这个过程的行为会有所不同,具体取决于它找到的信息格式。 user-data 中最流行的脚本格式之一是 cloud-config 文件格式。

Cloud-config 文件是旨在由 cloud-init 进程运行的特殊脚本。 这些通常用于服务器首次启动时的初始配置。 在本指南中,我们将讨论 cloud-config 文件的格式和用法。

关于 Cloud-Config 的一般信息

cloud-config 格式为许多常见的配置项实现了声明式语法,可以轻松完成许多任务。 它还允许您为超出预定义声明功能的任何内容指定任意命令。

这种“两全其美”的方法让该文件充当常见任务的配置文件,同时保持脚本的灵活性以实现更复杂的功能。

YAML 格式

该文件使用 YAML 数据序列化格式编写。 YAML 格式的创建是为了便于人类理解和易于程序解析。

YAML 文件在阅读时通常很容易理解,但最好了解管理它们的实际规则。

YAML 文件的一些重要规则是:

  • 带有空格的缩进表示项目之间的结构和关系。 更多缩进的项目是第一个项目的子项目,它们上方的缩进级别较低。
  • 列表成员可以通过前导破折号来标识。
  • 通过使用冒号 (:) 后跟空格和值来创建关联数组条目。
  • 文本块是缩进的。 要指示应按原样读取块,并保持格式不变,请在块前使用竖线字符 (|)。

让我们以这些规则来分析一个示例 cloud-config 文件,只注意格式:

#cloud-config
users:
  - name: demo
    groups: sudo
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh-authorized-keys:
      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0q4PyG0doiBQYV7OlOxbRjle026hJPBWD+eKHWuVXIpAiQlSElEBqQn0pOqNJZ3IBCvSLnrdZTUph4czNC4885AArS9NkyM7lK27Oo8RV888jWc8hsx4CD2uNfkuHL+NI5xPB/QT3Um2Zi7GRkIwIgNPN5uqUtXvjgA+i1CS0Ku4ld8vndXvr504jV9BMQoZrXEST3YlriOb8Wf7hYqphVMpF3b+8df96Pxsj0+iZqayS9wFcL8ITPApHi0yVwS8TjxEtI3FDpCbf7Y/DmTGOv49+AWBkFhS2ZwwGTX65L61PDlTSAzL+rPFmHaQBHnsli8U9N6E4XHDEOjbSMRX user@example.com
      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcthLR0qW6y1eWtlmgUE/DveL4XCaqK6PQlWzi445v6vgh7emU4R5DmAsz+plWooJL40dDLCwBt9kEcO/vYzKY9DdHnX8dveMTJNU/OJAaoB1fV6ePvTOdQ6F3SlF2uq77xYTOqBiWjqF+KMDeB+dQ+eGyhuI/z/aROFP6pdkRyEikO9YkVMPyomHKFob+ZKPI4t7TwUi7x1rZB1GsKgRoFkkYu7gvGak3jEWazsZEeRxCgHgAV7TDm05VAWCrnX/+RzsQ/1DecwSzsP06DGFWZYjxzthhGTvH/W5+KFyMvyA+tZV4i1XM+CIv/Ma/xahwqzQkIaKUwsldPPu00jRN user@desktop
runcmd:
  - touch /test.txt

通过查看这个文件,我们可以了解到许多重要的事情。

首先,每个 cloud-config 文件必须在第一行单独以 #cloud-config 开头。 这向 cloud-init 程序发出信号,表明它应该被解释为 cloud-config 文件。 如果这是一个常规脚本文件,第一行将指示应该用于执行该文件的解释器。

上面的文件有两个顶级指令,usersruncmd。 这些都用作键。 这些键的值由键后的所有缩进行组成。

users 键的情况下,该值是单个列表项。 我们知道这一点是因为下一级缩进是一个破折号 (-),它指定了一个列表项,并且因为在这个缩进级别只有一个破折号。 在 users 指令的情况下,这顺便表明我们只定义了一个用户。

列表项本身包含一个具有更多键值对的关联数组。 这些是兄弟元素,因为它们都存在于相同的缩进级别。 每个用户属性都包含在我们上面描述的单个列表项中。

需要注意的是,您看到的字符串不需要引用,并且没有不必要的括号来定义关联。 解释器可以相当容易地确定数据类型,并且缩进指示项目之间的关系,无论是对于人类还是程序。

到目前为止,您应该已经掌握了 YAML 格式的工作知识,并且可以轻松地使用我们上面讨论的规则来处理信息。

我们现在可以开始探索 cloud-config 的一些最常见的指令。

用户和组管理

要在系统上定义新用户,您可以使用我们在上面的示例文件中看到的 users 指令。

用户定义的一般格式是:

#cloud-config
users:
  - first_user_parameter
    first_user_parameter
    
  - second_user_parameter
    second_user_parameter
    second_user_parameter
    second_user_parameter

每个新用户都应该以破折号开头。 每个用户在键值对中定义参数。 以下键可用于定义:

  • name:账号用户名。
  • primary-group:用户的主组。 默认情况下,这将是一个与用户名匹配的组。 此处指定的任何组必须已经存在或必须显式创建(我们将在本节后面讨论)。
  • groups:此处可以列出任何补充组,以逗号分隔。
  • gecos:关于用户的补充信息字段。
  • shell:应该为用户设置的shell。 如果不设置,将使用非常基本的 sh shell。
  • expiredate:账户到期的日期,格式为YYYY-MM-DD。
  • sudo:如果您想定义 sudo 权限,则使用 sudo 字符串,不带用户名字段。
  • lock-passwd:默认设置为“True”。 将此设置为“False”以允许用户使用密码登录。
  • passwd:帐户的哈希密码。
  • ssh-authorized-keys:完整的 SSH 公钥列表,应添加到该用户的 authorized_keys 文件中,位于其 .ssh 目录中。
  • inactive:一个布尔值,将帐户设置为非活动状态。
  • system:如果为“True”,则此帐户将是没有主目录的系统帐户。
  • homedir:用于覆盖默认的/home/<username>,否则会创建和设置。
  • ssh-import-id:要从 LaunchPad 导入的 SSH ID。
  • selinux-user:这可用于设置该帐户登录时应使用的 SELinux 用户。
  • no-create-home:设置为“True”以避免为用户创建/home/<username>目录。
  • no-user-group:设置为“True”以避免创建与用户同名的组。
  • no-log-init:设置为“True”不启动用户登录数据库。

除了一些基本信息,如 name 键,您只需要定义偏离默认值或提供所需数据的区域。

对用户来说重要的一件事是 passwd 字段应该 not 用于生产系统,除非您有立即修改给定值的机制。 与作为用户数据提交的所有信息一样,在服务器的整个生命周期内,系统上的 any 用户都可以访问散列。 在现代硬件上,这些哈希值很容易在很短的时间内被破解。 甚至暴露哈希也是一个巨大的安全风险,不应该在任何非一次性机器上承担。

对于示例用户定义,我们可以使用上面看到的示例 cloud-config 的一部分:

#cloud-config
users:
  - name: demo
    groups: sudo
    shell: /bin/bash
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    ssh-authorized-keys:
      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0q4PyG0doiBQYV7OlOxbRjle026hJPBWD+eKHWuVXIpAiQlSElEBqQn0pOqNJZ3IBCvSLnrdZTUph4czNC4885AArS9NkyM7lK27Oo8RV888jWc8hsx4CD2uNfkuHL+NI5xPB/QT3Um2Zi7GRkIwIgNPN5uqUtXvjgA+i1CS0Ku4ld8vndXvr504jV9BMQoZrXEST3YlriOb8Wf7hYqphVMpF3b+8df96Pxsj0+iZqayS9wFcL8ITPApHi0yVwS8TjxEtI3FDpCbf7Y/DmTGOv49+AWBkFhS2ZwwGTX65L61PDlTSAzL+rPFmHaQBHnsli8U9N6E4XHDEOjbSMRX user@example.com
      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcthLR0qW6y1eWtlmgUE/DveL4XCaqK6PQlWzi445v6vgh7emU4R5DmAsz+plWooJL40dDLCwBt9kEcO/vYzKY9DdHnX8dveMTJNU/OJAaoB1fV6ePvTOdQ6F3SlF2uq77xYTOqBiWjqF+KMDeB+dQ+eGyhuI/z/aROFP6pdkRyEikO9YkVMPyomHKFob+ZKPI4t7TwUi7x1rZB1GsKgRoFkkYu7gvGak3jEWazsZEeRxCgHgAV7TDm05VAWCrnX/+RzsQ/1DecwSzsP06DGFWZYjxzthhGTvH/W5+KFyMvyA+tZV4i1XM+CIv/Ma/xahwqzQkIaKUwsldPPu00jRN user@desktop

要定义组,您应该使用 groups 指令。 该指令相对简单,因为它只需要您要创建的组列表。

对此的可选扩展是为您正在创建的任何组创建一个子列表。 这个新列表将定义应该放在这个组中的用户:

#cloud-config
groups:
  - group1
  - group2: [user1, user2]

更改现有用户的密码

对于已经存在的用户帐户(root 帐户是最相关的),可以使用 chpasswd 指令来提供密码。

注意:在调试情况下应该only使用该指令,因为再一次,在服务器的生命周期内,系统上的每个用户都可以使用该值。 这在本节中更加相关,因为使用此指令提交的密码必须以 纯文本 给出。

基本语法如下所示:

#cloud-config
chpasswd:
  list: |
    user1:password1
    user2:password2
    user3:password3
  expire: False

该指令包含两个关联数组键。 list 键将包含一个块,其中列出了您要分配的帐户名称和相关密码。 expire 键是一个布尔值,用于确定是否必须在首次启动时更改密码。 这默认为“真”。

需要注意的一点是,您可以将密码设置为“RANDOM”或“R”,这将生成一个随机密码并将其写入 /var/log/cloud-init-output.log。 请记住,系统上的任何用户都可以访问此文件,因此它不再安全。

将文件写入磁盘

为了将文件写入磁盘,您应该使用 write_files 指令。

应该写入的每个文件都由指令下的列表项表示。 这些列表项将是定义每个文件属性的关联数组。

此数组中唯一需要的键是 path,它定义了写入文件的位置,以及 content,它包含您希望文件包含的数据。

用于配置 write_files 项目的可用键是:

  • path:文件系统上应写入文件的位置的绝对路径。
  • content:应该放在文件中的内容。 对于多行输入,您应该通过在“内容”行上使用竖线字符 (|) 开始一个块,然后是包含内容的缩进块。 二进制文件应包含“!!binary”和管道字符前的空格。
  • owner:应该被赋予文件所有权的用户帐户和组。 这些应该以“用户名:组”格式给出。
  • permissions:应该为此文件提供的八进制权限集。
  • encoding:文件的可选编码规范。 这可以是 Base64 文件的“b64”、Gzip 压缩文件的“gzip”或组合的“gz+b64”。 忽略这一点将使用默认的常规文件类型。

例如,我们可以将文件写入 /test.txt,其内容为:

Here is a line.
Another line is here.

cloud-config 中完成此操作的部分如下所示:

#cloud-config
write_files:
  - path: /test.txt
    content: |
      Here is a line.
      Another line is here.

在服务器上更新或安装软件包

要管理包,需要记住一些相关的设置和指令。

要在基于 Debian 的发行版上更新 apt 数据库,您应该将 package_update 指令设置为“true”。 这与从命令行调用 apt-get update 同义。

默认值实际上是“true”,所以如果你想禁用它,你只需要担心这个指令:

#cloud-config
package_update: false

如果您希望在服务器首次启动后升级所有软件包,您可以设置 package_upgrade 指令。 这类似于手动执行的 apt-get upgrade

默认情况下设置为“false”,因此如果您需要该功能,请确保将其设置为“true”:

#cloud-config
package_upgrade: true

要安装其他软件包,您可以使用“packages”指令简单地列出软件包名称。 每个列表项应该代表一个包。 与上面的两个命令不同,该指令将与 yum 或 apt 托管发行版一起使用。

这些项目可以采用两种形式之一。 第一个只是一个带有包名的字符串。 第二种形式是包含两个项目的列表。 这个新列表的第一项是包名,第二项是版本号:

#cloud-config
packages:
  - package_1
  - package_2
  - [package_3, version_num]

“packages”指令将 apt_update 设置为 true,覆盖之前的任何设置。

为用户帐户和 SSH 守护程序配置 SSH 密钥

您可以在 users 指令中管理 SSH 密钥,但您也可以在专用的 ssh_authorized_keys 部分中指定它们。 这些将被添加到第一个定义的用户的 authorized_keys 文件中。

这采用与 users 指令中的密钥规范相同的一般格式:

#cloud-config
ssh_authorized_keys:
  - ssh_key_1
  - ssh_key_2

您还可以提前生成 SSH 服务器的私钥并将它们放在文件系统上。 如果您想事先向您的客户提供有关此服务器的信息,这将很有用,允许它在服务器上线后立即信任该服务器。

为此,我们可以使用 ssh_keys 指令。 这可以使用 rsa_privatersa_publicdsa_privatedsa_publicecdsa_private 获取 RSA、DSA 或 ECDSA 密钥的密钥对, 和 ecdsa_public 子项。

由于格式和换行对私钥很重要,因此在指定这些时请确保使用带有管道键的块。 此外,您 必须 包括开始键和结束键行,您的键才有效。

#cloud-config
ssh_keys:
  rsa_private: |
    -----BEGIN RSA PRIVATE KEY-----
    your_rsa_private_key
    -----END RSA PRIVATE KEY-----

  rsa_public: your_rsa_public_key

设置受信任的 CA 证书

如果您的基础架构依赖于由内部证书颁发机构签名的密钥,您可以通过注入证书信息来设置新机器以信任您的 CA 证书。 为此,我们使用 ca-certs 指令。

该指令有两个子项。 第一个是 remove-defaults,当设置为 true 时,将删除默认包含的所有正常证书信任信息。 这通常不是必需的,如果您不知道自己在做什么,可能会导致一些问题,因此请谨慎使用。

第二项是trusted,它是一个列表,每个都包含一个受信任的CA证书:

#cloud-config
ca-certs:
  remove-defaults: true
  trusted:
    - |
      -----BEGIN CERTIFICATE-----
      your_CA_cert
      -----END CERTIFICATE-----

配置 resolv.conf 以使用特定的 DNS 服务器

如果您已经配置了您自己想要使用的 DNS 服务器,您可以使用 resolv_conf 指令来管理您的服务器的 resolv.conf 文件。 这目前仅适用于基于 RHEL 的发行版。

resolv_conf 指令下,您可以使用 nameserverssearchdomainsdomainoptions 项目管理您的设置。

nameservers 指令应该包含您的名称服务器的 IP 地址列表。 当用户指定主机但未指定域时,searchdomains 指令获取要搜索的域和子域列表。

domain 设置应该用于任何无法解析的请求的域,并且 options 包含一组可以在 resolv.conf 文件中定义的选项。

如果您使用 resolv_conf 指令,则必须确保 manage-resolv-conf 指令也设置为 true。 不这样做会导致您的设置被忽略:

#cloud-config
manage-resolv-conf: true
resolv_conf:
  nameservers:
    - 'first_nameserver'
    - 'second_nameserver'
  searchdomains:
    - first.domain.com
    - second.domain.com
  domain: domain.com
  options:
    option1: value1
    option2: value2
    option3: value3

运行任意命令以获得更多控制

如果 cloud-config 提供的托管操作都不能满足您的需求,您还可以运行任意命令。 您可以使用 runcmd 指令执行此操作。

该指令采用要执行的项目列表。 这些项目可以用两种不同的方式指定,这将影响它们的处理方式。

如果列表项是简单的字符串,则将整个项传递给 sh shell 进程运行。

另一个选项是传递一个列表,其中的每一项都将以类似于 execve 处理命令的方式执行。 第一项将被解释为要运行的命令或脚本,以下各项将作为该命令的参数传递。

大多数用户可以使用这两种格式中的任何一种,但如果您有特殊要求,您可以灵活地选择最佳选项。 任何输出都将写入标准输出和 /var/log/cloud-init-output.log 文件:

#cloud-config
runcmd:
  - [ sed, -i, -e, 's/here/there/g', some_file]
  - echo "modified some_file"
  - [cat, some_file]

关闭或重新启动服务器

在某些情况下,您需要在执行其他项目后关闭或重新启动服务器。 您可以通过设置 power_state 指令来做到这一点。

该指令有四个可以设置的子项。 它们是 delaytimeoutmessagemode

delay 指定在未来多长时间内应该重新启动或关闭。 默认情况下,这将是“现在”,这意味着程序将立即开始。 要添加延迟,用户应使用 +<num_of_mins> 格式指定应经过的时间量(以分钟为单位)。

timeout 参数采用无单位值,表示在启动 delay 倒计时之前等待 cloud-init 完成的秒数。

message 字段允许您指定将发送给系统所有用户的消息。 mode 指定要启动的电源事件的类型。 这可以是“poweroff”来关闭服务器,“reboot”来重新启动服务器,或者“halt”来让系统决定哪个是最佳操作(通常是关闭):

#cloud-config
power_state:
  timeout: 120
  delay: "+5"
  message: Rebooting in five minutes. Please save your work.
  mode: reboot

结论

以上示例代表了运行 cloud-config 文件时可用的一些更常见的配置项。 本指南中未涵盖其他功能。 其中包括配置管理设置、配置其他存储库,甚至在服务器初始化时使用外部 URL 进行注册。

您可以通过查看 /usr/share/doc/cloud-init/examples 目录来了解有关其中一些选项的更多信息。 如需实用指南帮助您熟悉 cloud-config 文件,您可以在此处按照我们的 如何使用 cloud-config 完成基本服务器配置 的教程进行操作。