如何使用 Ansible 自动完成多个 Ubuntu 22.04 服务器的初始服务器设置

_ 作者选择了 免费和开源基金作为 写给捐款计划的一部分接受捐款。

介绍

[Ansible] (https://www.ansible.com/)是一个开源软件工具,用于服务器和应用程序的提供,配置管理和部署自动化. 您可以使用Ansible在一个或多个服务器上自动化任务,或者在多个服务器上运行分布式应用程序. 对于多服务器设置,完成每个服务器的初始服务器设置可能耗费时间,而使用Ansible则会用自定义游戏本来加速进程.

Ansible 是无代理的,所以您不需要在您想要运行 Ansible 的服务器上安装任何 Ansible 组件 。 这些服务器是Ansible主机,必须运行Python3和OpenSSH,这两台服务器都预先安装在Ubuntu 22.04上并全部Linux发行. Ansible控制节点是将启动自动化的机器,如果安装了[Linux (WSL) (https://andsky.com/tech/tutorials/how-to-install-the-windows-subsystem-for-linux-2-on-microsoft-windows-10)的Windows子系统,它可以运行任何相容的Unix类操作系统或Windows.

在本教程中,您将使用Ansible来自动化多个Ubuntu 22.04服务器的初始服务器设置,您将在所有服务器上完成以下初始设置任务:

  • 更新已安装的包 * 添加具有管理权限的非根用户 * 允许非根用户访问 SSH * 启用防火墙 * 更改 SSH 访问端口并使用防火墙来防止暴力攻击并提高服务器的整体安全性 * 禁用根帐户的远程登录 * 确保关键服务处于活动 * 删除不再需要的包依赖性

由于您将使用 Ansible 运行定义每个任务的综合播放簿,这些任务将使用一个命令完成,而无需单独登录服务器。

前提条件

要完成本教程,您将需要:

  • 如果您的控制节点是远程 Ubuntu 22.04 服务器, 请使用 [初始服务器设置] (https://andsky.com/tech/tutorials/initial-server-setup-with-ubuntu-22-04 ) 和 [创建它的 SSH 密钥对 (https://andsky.com/tech/tutorials/how-to-set-up-ssh-keys-on-ubuntu-22-04 ) 来设置 。
  • Git安装在控制节点上. 遵循流行Linux发行的 [如何安装 Git (https://www.digitalocean.com/community/tutorial_collections/how-to-install-git) 教程 。
  • (可选)在 [步骤5] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-5-using-ansible-vault-to-create-an-encrypted-password-file)中,您会使用Ansible Vault为您的主机用户创建加密密码文件. Ansible Vault使用"vi"作为其默认编辑器. 如果您的控制节点是 Linux 机器, 并且您更喜欢使用 ) 教程上设置 Ansible Vault 编辑器, 以更改链接到 EDITOR 环境 shell 变量的文本编辑器 。 该教程将使用 " nano " 作为Ansible Vault的编辑器。
  • 2个或更多的Ubuntu 22.04服务器和每个服务器的公共IPv4地址. 不需要事先设置,因为您会使用Ansible进行第5步中的自动设置,但是您必须能够从上面提到的Ansible控制节点访问这些服务器. 如果您正在使用 DigitalOcean Droplets, 您可以在您的仪表板中找到每个服务器的 ** 公共网络 部分的 IPv4 地址 。

步骤 1 — 在您的控制节点上修改 SSH 客户端配置文件

在此步骤中,您将更改控制节点的 SSH 客户端配置文件中的指令。在进行此更改后,您将不再被要求接受远程机器的 SSH 密钥指纹,因为它们将自动被接受。

虽然您可以使用Ansible的)。

首先,在控制节点上启动终端应用程序,然后使用nano或您最喜欢的文本编辑器,打开 SSH 客户端配置文件:

1sudo nano /etc/ssh/ssh_config

查找包含StrictHostKeyChecking指令的行,删除它并更改值,以便其读取如下内容:

1[label /etc/ssh/ssh_config]
2...
3   StrictHostKeyChecking accept-new
4...

您不需要重新加载或重新启动 SSH DAEMON,因为您只修改了 SSH 客户端配置文件。

<美元 > [注] 注: 如果您不想将StritHostKeyChecking'的值从ask'永久改为accept-new',可以在运行 [Step 7] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-7-checking-the-server-setup-manually)的游戏本后恢复到默认值. 虽然改变值将意味着你的系统自动接受SSH密钥指纹,但如果指纹改变,它会拒绝同一主机后续的连接. 这一特点意味着接受-新'的改变不如将该指示的价值改为`否'那样具有安全风险。 < $ > (美元)

现在您已经更新了 SSH 指令,您将开始 Ansible 配置,您将在下一个步骤中完成。

步骤 2 — 配置 Ansible 主机文件

Ansible hosts 文件(也称为 库存文件)包含关于 Ansible 主机的信息.此信息可能包括群组名称、代名称、域名和 IP 地址。该文件默认情况下位于 /etc/ansible 目录中。在此步骤中,您将添加您在前提部分中旋转的 Ansible 主机的 IP 地址,以便您可以对其运行您的 Ansible 播放簿。

首先,使用nano或您最喜欢的文本编辑器打开主机文件:

1sudo nano /etc/ansible/hosts

在文件中的入门评论后,添加以下行:

 1[label /etc/ansible/hosts]
 2...
 3
 4host1 ansible_host=host1-public-ip-address
 5host2 ansible_host=host2-public-ip-address
 6host3 ansible_host=host3-public-ip-address
 7
 8[initial]
 9host1
10host2
11host3
12
13[ongoing]
14host1
15host2
16host3

「host1」、「host2」和「host3」是您想要自動化初始伺服器設定的每個伺服器的代名詞。

" 初始 " 和 " 进行中 " 是Ansible主机的样本组名称。 选择组名, 以方便知道主机的用途 。 以这种方式分组主机可以将它们作为一个单元处理. 主机可以属于多个组. 此教程中的主机被分配到两个不同的组,因为它们会被用在两个不同的游戏本中:用于步骤6中初始服务器设置的"初始"和用于后期[步骤8](https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible optional-step-8-using-ansible-for-ongoing-maintenance-of-the-hosts)服务器管理的"正在".

hostN-public-ip-address 是每个 Ansible 主机的 IP 地址,请确保将host1-public-ip-address 和随后的行代替为自动化的一部分服务器的 IP 地址。

当你完成修改文件时,保存并关闭它。

在库存文件中定义主机可帮助您指定使用 Ansible 自动化设置的主机。

第3步:克隆Ubuntu初始服务器设置存储库

在此步骤中,您将克隆来自GitHub的样本存储库,其中包含此自动化所需的文件。

这份检索表载有一个多服务器自动化样本的三个文件:初始.yml'、进行中.yml'和`vars/default.yml'。 )和[第8步](https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible optional-step-8-using-ansible-for-ongoing-maintenance-of-the-hosts)两个游戏本中将被调用的变量.

要克隆 Repo,请输入以下命令:

1git clone https://github.com/do-community/ansible-ubuntu.git

或者,如果您已将 SSH 密钥添加到您的 GitHub 帐户中,您可以使用:

1[email protected]:do-community/ansible-ubuntu.git

你现在将有一个名为ansible-ubuntu的文件夹在你的工作目录中。

1cd ansible-ubuntu

这将是您在本教程的剩余时间的工作目录。

在此步骤中,您获得了用于使用 Ansible 自动化多个 Ubuntu 22.04 服务器的样本文件,以便为您的主机准备具有特定信息的文件,您将下次更新 vars/default.yml 文件以便与您的系统工作。

步骤4 - 更改可理解的变量

将该信息放置在一个变量文件中,并调用播放簿中的变量将比在播放簿中硬编码更有效,所以您将在vars/default.yml文件中修改变量以匹配您的偏好和设置需求。

要开始,请使用nano或您最喜欢的文本编辑器打开文件:

1nano vars/default.yml

您将审查文件的内容,其中包括以下变量:

1[label vars/default.yml]
2create_user: sammy
3
4ssh_port: 5995
5
6copy_local_key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"

create_user变量的值应该是每个主机上创建的sudo用户的名称,在这种情况下,它是sammy,但你可以随心所欲命名用户。

ssh_port变量包含你在设置后将使用的连接到 Ansible 主机的 SSH 端口。 SSH 的默认端口为 22,但改变它将大大减少攻击您的服务器的自动攻击次数。 这种更改是可选的,但会增加您的主机的安全姿势。 你应该选择一个不太熟悉的端口,它在102465535之间,并且在 Ansible 主机上也不是其他应用程序使用的。

<美元 > [注] 注: 如果您控制节点正在运行Linux发行,请在) 。 < $ > (美元)

) 中运行主游戏本,并在创建了拥有"sudo"权限的用户后,Ansible控制器会将公钥文件复制到用户主目录中,这使得您可以在初始服务器设置后通过SSH作为用户登录.

当你完成修改文件时,保存并关闭它。

既然你已经给) 和 [步骤8] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible optional-step-8-using-ansible-for-ongoing-maintenance-of-the-hosts 的游戏本时调用这些变量. 下一步,您将使用Ansible Vault为每个主机创建的用户创建并保护密码.

步骤5 — 使用 Ansible Vault 创建加密密码文件

[Ansible Vault] (https://docs.ansible.com/ansible/latest/user_guide/vault.html)用于创建并加密可以在游戏本中引用的文件和变量. 使用 Ansible Vault 保证在执行游戏本时不会以平白文本传输敏感信息. 在此步骤中, 您将创建并加密一个包含变量的文件, 这些变量的值将用于为每个主机的 sudo 用户创建密码 。 通过这种方式使用Ansible Vault,您可以保证在初始服务器设置期间和之后的游戏本中不会在平话本中引用密码.

仍然在ansible-ubuntu目录中,使用以下命令创建和打开保险箱文件:

1ansible-vault create secret

提示时, 输入并确认用于加密) 和 [步骤8] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible optional-step-8-using-ansible-for-ongoing-maintenance-of-the-hosts] 中运行游戏本时需要保险库密码,所以不要忘记它.

在输入并确认保险箱密码后,在链接到壳的EDITOR环境变量的文本编辑器中将打开秘密文件,将这些行添加到文件中,取代type_a_strong_password_heretype_a_salt_here的值:

1[label ~/ansible-ubuntu/secret]
2password: type_a_strong_password_here
3password_salt: type_a_salt_here

" 密码 " 变量的价值将是您在每个主机上创建的) 是指用于生成散列密码的任何长而随机的值. 您可以使用字母顺序或字母顺序的字符串, 但单用数字字符串可能行不通 。 生成散列密码时会加入盐,使得更难猜出密码或破解散列. 在 [步骤6] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-6-running-the-main-playbook-against-your-ansible-hosts) 和 [步骤8] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible optional-step-8-using-ansible-for-ongoing-maintenance-of-the-hosts ) 中执行游戏本时,这两个变量都会被调用.

<美元 > [注] 注: 在测试中,我们发现由只由数字字符所组成的盐导致在步骤6和[步骤8](https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible optional-step-8-using-ansible-for-ongoing-maintenance-of-the-hosts)中运行游戏本的问题. 然而,只有按字母顺序排列的名词才有效。 以字母表示的盐也应起作用。 在指定盐时记住这一点。 < $ > (美元)

当你完成修改文件时,保存并关闭它。

您现在已经创建了一个加密的密码文件,其变量将用于在主机上为)。

步骤6 - 运行主游戏簿反对你的可信主机

在此步骤中,您将使用 Ansible 来自动化您在库存文件中指定的尽可能多的服务器的初始设置。

一个 Ansible 游戏簿由一个或多个游戏组成,每个游戏都有一个或多个任务,你将与你的 Ansible 主机进行的示例游戏簿包含两个游戏,总共有 14 个任务。

在运行播放簿之前,您将审查与其设置过程相关的每个任务. 首先,使用nano或您最喜欢的文本编辑器打开文件:

1nano initial.yml

玩一:

文件的第一部分包含影响游戏行为的下列关键字:

1[label initial.yml]
2- name: Initial server setup tasks
3  hosts: initial
4  remote_user: root
5  vars_files:
6    - vars/default.yml
7    - secret
8...

名称'是对本剧的简短描述,随着本剧的进行,本剧将在剧终站展出. 主机'关键词表示游戏的目标为哪些主机。 在这种情况下,传入关键词的模式是您在 [Step 2] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-2-configuring-the-ansible-hosts-file) 文件中所指定的 /etc/ansible/hosts' 文件所指定的主机的组名. 您使用) 。 vars_ files` 关键字指向包含游戏在执行任务时将参考的变量的文件.

通过此设置,Ansible控制器将尝试通过SSH端口22登录到主机作为用户。对于每个可以登录的主机,它将报告一个OK响应。否则,它将报告服务器无法到达,并将开始执行播放的任务,无论主机可以登录到哪个主机。

接下来是关键字部分,列出要连续执行的任务列表,与游戏一样,每个任务都以一个名称开始,它提供了任务将实现的简短描述。

任务1:更新缓存

播放簿中的第一个任务更新了包数据库:

1[label initial.yml]
2...
3- name: update cache
4  ansible.builtin.apt:
5    update_cache: yes
6...

此任务将使用 ansible.builtin.apt 模块更新包数据库,这就是为什么它被定义为 update_cache: yes

任务2:更新所有已安装的软件包

播放书更新包中的第二个任务:

1[label initial.yml]
2...
3- name: Update all installed packages
4  ansible.builtin.apt:
5    name: "*"
6    state: latest
7...

与第一个任务一样,这个任务也称为)和状态:最新,这相当于登录您的服务器并运行sudo apt upgrade -y命令。

任务3:确保 NTP 服务正在运行

播放簿中的第三个任务确保了 网络时间协议 (NTP) Daemon是活跃的:

1[label initial.yml]
2...
3- name: Make sure NTP service is running
4  ansible.builtin.systemd:
5    state: started
6    name: systemd-timesyncd
7...

此任务会调用 ansible.builtin.systemd 模块 以确保 systemd-timesyncd,即 NTP 示范,正在运行(state: started)。当您想要确保您的服务器保持相同的时间时,您会运行这样的任务,这可以帮助在这些服务器上运行分布式应用程序。

任务4:确保我们有一个sudo

剧本中的第四个任务验证存在一个sudo组:

1[label initial.yml]
2...
3- name: Make sure we have a 'sudo' group
4  ansible.builtin.group:
5    name: sudo
6    state: present
7...

这个任务会调用 ansible.builtin.group 模块 来检查在主机上是否存在一个名为 sudo 的组(state: present)。 因为你的下一个任务取决于主机上是否存在一个 sudo 组,这个任务会检查 sudo 组是否存在,所以你可以确定下一个任务不会失败。

任务 5:创建具有 sudo 特权的用户

玩本中的第五个任务创建了你的非根用户,具有sudo特权:

 1[label initial.yml]
 2...
 3- name: Create a user with sudo privileges
 4  ansible.builtin.user:
 5    name: "{{ create_user }}"
 6    state: present
 7    groups: sudo
 8    append: true
 9    create_home: true
10    shell: /bin/bash
11    password: "{{ password | password_hash('sha512', password_salt) }}"
12    update_password: on_create
13...

在这里,您在每个主机上创建一个用户,通过调用 ansible.builtin.user 模块并将sudo组添加到用户的组中。用户名来自您在vars/default.yml中指定的create_user变量值。这项任务还确保为用户创建一个主目录并与适当的壳分配。

使用"密码"参数和您在[步骤5](https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible#step-5-using-ansible-vault-to-create-an-encrypted-password-file]中设置的密码和盐的组合,这个函数称为SHA-512密码散列算法为用户生成一个散列密码. 带有 " 秘密 " 保险库文件的Paire,密码从未以简写方式传递给控制器。 使用update_ password 时, 您保证只设置创建用户的先行密码 。 如果您重运行了游戏本, 密码将不会重生成 .

任务 6:为远程用户设置授权密钥

播放簿中的第六个任务为您的用户设置了密钥:

1[label initial.yml]
2...
3- name: Set authorized key for remote user
4  ansible.posix.authorized_key:
5    user: "{{ create_user }}"
6    state: present
7    key: "{{ copy_local_key }}"
8...

使用此任务,您将您的公共 SSH 密钥复制到主机中,通过拨打 ansible.posix.authorized_key )。 user 的值是上一项任务中在主机上创建的用户名,而 key 指向要复制的密钥。 两种变量都定义在 var/default.yml 文件中。 这项任务具有与手动运行 ssh-copy-id 命令相同的效果。

任务7:禁用远程登录为 root

播放簿中的第七个任务为用户禁用远程登录:

1[label initial.yml]
2...
3- name: Disable remote login for root
4  ansible.builtin.lineinfile:
5    path: /etc/ssh/sshd_config
6    state: present
7    regexp: '^PermitRootLogin yes'
8    line: 'PermitRootLogin no'
9...

接下来,请使用[anable.buildingin.lineinfile'模块](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html)。 此任务搜索在) 开头的 PermitRoot Login 线条, 然后取而代之。 此任务确保使用 root` 账户的远程登录在本游戏本中运行后失败 。 只有远程登录任务6中创建的用户账户才能成功. 通过禁用远程根登录,您确保只有普通用户可以登录,并且需要一种特权升级方法,通常是"sudo",才能获得管理员权限.

任务 8:更改 SSH 端口

播放簿中的第八个任务更改了SSH端口:

1[label initial.yml]
2...
3- name: Change the SSH port
4  ansible.builtin.lineinfile:
5    path: /etc/ssh/sshd_config
6    state: present
7    regexp: '^#Port 22'
8    line: 'Port "{{ ssh_port }}"'
9...

由于SSH在著名的 " 22 " 港口上听话,它往往受到针对该港口的自动攻击。 通过改变SSH所收听的端口,会减少自动攻击击中主机的次数. 此任务使用相同的 ) 中分配给 ssh_port 变量的端口号 。 在本剧结束时重新启动主机后,您将无法通过端口"22"登录到主机.

任务9:UFW - 允许SSH连接

播放簿中的第九个任务允许SSH流量:

1[label initial.yml]
2...
3- name: UFW - Allow SSH connections
4  community.general.ufw:
5    rule: allow
6    port: "{{ ssh_port }}"
7...

在这里,请使用[community.general.ufw'模块](https://docs.ansible.com/ansible/latest/collections/community/general/ufw_module.html)允许SSH通过防火墙的流量。 通知 SSH 的端口号码不是 22 , 而是您在 [Step 4] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-4-modifying-the-ansible-variables] 文件中的 vars/default.yml 文件指定的自定义端口号码 。 这项任务相当于人工操作ufw允许5995/tcp'命令.

任务 10: SSH 的暴力试图保护

第十个任务是防范暴力攻击:

1[label initial.yml]
2...
3- name: Brute-force attempt protection for SSH
4  community.general.ufw:
5    rule: limit
6    port: "{{ ssh_port }}"
7    proto: tcp
8...

再次调用community.general.ufw模块,此任务使用率限制的规则来拒绝登录到在 30 秒内未能连接到 SSH 端口的 6 次或以上尝试的 IP 地址。

任务 11: UFW - 拒绝其他流量输入并启用 UFW

第十一项任务允许防火墙:

1[label initial.yml]
2...
3- name: UFW - Deny other incoming traffic and enable UFW
4  community.general.ufw:
5    state: enabled
6    policy: deny
7    direction: incoming
8...

在此任务中仍然依赖)并设置默认的策略,以否定所有流量。

任务12:删除不再需要的依赖性

本场比赛的第十二个任务清除包的依赖性:

1[label initial.yml]
2...
3- name: Remove dependencies that are no longer required
4  ansible.builtin.apt:
5    autoremove: yes
6...

通过再次调用ansible.builtin.apt模块,此任务会删除在服务器上不再需要的包依赖,这相当于手动运行sudo apt autoremove命令。

任务 13:重新启动 SSH DAEMON

本图书中的第十三项任务将重新启动SSH。

1[label initial.yml]
2...
3- name: Restart the SSH daemon
4  ansible.builtin.systemd:
5    state: restarted
6    name: ssh

最后一项任务呼叫ansible.builtin.systemd模块重新启动 SSH 对象. 必须重新启动,以便对对象配置文件所做的更改生效. 该任务具有与使用sudo systemctl 重新启动 ssh重新启动对象相同的效果。

最初的连接到主机是通过端口22作为,但以前的任务已经改变了端口号和禁用远程根登录,这就是为什么你需要重新启动SSH大象在这个阶段的游戏。

Play 2:在初始设置后重新启动主机

此游戏在游戏 1 中的最后一项任务成功完成后开始,受以下关键字的影响:

 1[label initial.yml]
 2...
 3- name: Rebooting hosts after initial setup
 4  hosts: initial
 5  port: "{{ ssh_port }}"
 6  remote_user: "{{ create_user }}"
 7  become: true
 8  vars_files:
 9    - vars/default.yml
10    - ~/secret
11  vars:
12    ansible_become_pass: "{{ password }}"
13...

传入 " 东道主 " 关键词的模式是步骤2中`etc/anable/hosts ' 文件所指定的 " 初始 " 组名。 因为你将无法再使用默认的SSH端口"22"登录到主机,"端口"关键词指向配置在 [步骤4] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible step-4-modifying-the-ansible-variables)中的自定义SSH端口.

在第一个播放中,Ansible控制器登录到主机作为用户. 随着第一个播放的远程根登录被禁用,您现在必须指定Ansible控制器应该登录的用户。

`become'关键词规定,特权升级用于指定主机的任务执行. 此关键字指示 Ansible 控制器在必要时为执行主机上的任务承担根权限 。 在这种情况下,控制器将使用"sudo"来承担根权限. ‘ ansible_ become_ pass' 关键词设置特权升级密码, 即用于承担根权限的密码 。 在这种情况下,它用您在第5步中使用Ansible Vault配置的密码指向了变量.

除了指向),这告诉Ansible控制器在哪里找到密码变量。

在关键字部分之后是将在这个游戏中执行的独一无二的任务。

任务14:重新启动所有主机

注意:虽然这是第二场比赛的第一项任务,但它被编号为任务14,因为 Ansible 控制器将其视为不是 Play 2 的任务 1,而是玩本的任务 14。

播放簿的最后任务将重新启动所有主机:

1[label initial.yml]
2...
3- name: Reboot all hosts
4  ansible.builtin.reboot:

在第一次播放中完成任务后重新启动主机意味着在您开始安装应用程序之前,对内核或库的任何更新都将生效。

完整的 Playbook 檔案看起來像這樣:

 1[label initial.yml]
 2- name: Initial server setup tasks
 3  hosts: initial
 4  remote_user: root
 5  vars_files:
 6    - vars/default.yml
 7    - secret
 8
 9  tasks:
10    - name: update cache
11      ansible.builtin.apt:
12        update_cache: yes
13
14    - name: Update all installed packages
15      ansible.builtin.apt:
16        name: "*"
17        state: latest
18
19    - name: Make sure NTP service is running
20      ansible.builtin.systemd:
21        state: started
22        name: systemd-timesyncd
23
24    - name: Make sure we have a 'sudo' group
25      ansible.builtin.group:
26        name: sudo
27        state: present
28
29    - name: Create a user with sudo privileges
30      ansible.builtin.user:
31        name: "{{ create_user }}"
32        state: present
33        groups: sudo
34        append: true
35        create_home: true
36        shell: /bin/bash
37        password: "{{ password | password_hash('sha512', password_salt) }}"
38        update_password: on_create
39
40    - name: Set authorized key for remote user
41      ansible.builtin.authorized_key:
42        user: "{{ create_user }}"
43        state: present
44        key: "{{ copy_local_key }}"
45
46    - name: Disable remote login for root
47      ansible.builtin.lineinfile:
48        path: /etc/ssh/sshd_config
49        state: present
50        regexp: '^PermitRootLogin yes'
51        line: 'PermitRootLogin no'
52
53    - name: Change the SSH port
54      ansible.builtin.lineinfile:
55        path: /etc/ssh/sshd_config
56        state: present
57        regexp: '^#Port 22'
58        line: 'Port "{{ ssh_port }}"'
59
60    - name: UFW - Allow SSH connections
61      community.general.ufw:
62        rule: allow
63        port: "{{ ssh_port }}"
64
65    - name: Brute-force attempt protection for SSH
66      community.general.ufw:
67        rule: limit
68        port: "{{ ssh_port }}"
69        proto: tcp
70
71    - name: UFW - Deny other incoming traffic and enable UFW
72      community.general.ufw:
73        state: enabled
74        policy: deny
75        direction: incoming
76
77    - name: Remove dependencies that are no longer required
78      ansible.builtin.apt:
79        autoremove: yes
80
81    - name: Restart the SSH daemon
82      ansible.builtin.systemd:
83        state: restarted
84        name: ssh
85
86- name: Rebooting hosts after initial setup
87  hosts: initial
88  port: "{{ ssh_port }}"
89  remote_user: "{{ create_user }}"
90  become: true
91  vars_files:
92    - vars/default.yml
93    - secret
94  vars:
95    ansible_become_pass: "{{ password }}"
96
97  tasks:
98    - name: Reboot all hosts
99      ansible.builtin.reboot:

当你完成检查文件时,保存并关闭它。

<$>[注] 注: 您可以添加新的任务到播放簿或修改现有的任务。然而,改变YAML文件可能会损坏它,因为YAML对间隔敏感,所以如果您选择编辑文件的任何方面,请小心。 有关如何使用Ansible播放簿的更多信息,请遵循我们的系列在 How To Write Ansible Playbooks

现在你可以运行播放簿. 首先,检查语法:

1ansible-playbook --syntax-check --ask-vault-pass initial.yml

您将被提示在 [步骤 5] 中创建的密码(https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-5-using-ansible-vault-to-create-an-encrypted-password-file)。如果成功验证后没有YAML语法错误,输出将是:

1[secondary_label Output]
2playbook: initial.yml

您现在可以使用以下命令运行该文件:

1ansible-playbook --ask-vault-pass initial.yml

成功验证后,Ansible 控制器将作为用户登录每个主机,并执行播放簿中的所有任务。而不是单独在每个服务器上运行ssh root@node-ip-address命令,Ansible 会连接到在/etc/ansible/hosts中指定的所有节点,然后在播放簿中执行任务。

对于本教程中的示例主机,Ansible花了大约三分钟来完成三个主机的任务。

1[secondary_label Output]
2PLAY RECAP *****************************************************************************************************
3host1   : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0   
4host2   : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0   
5host3   : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

每个成功评估的任务和游戏关键字部分都会计算到OK列中的数字。在两场比赛中,有14项任务被评估成功,计数为16项。

「無法達到」數顯示了 Ansible 控制器無法登入的主機數目,沒有任務失敗,因此「失敗」數字為「0」。

在此情况下,没有任务被)。

最后两个列()与游戏或任务中指定的错误处理有关。

您现在已经成功地使用 Ansible 自动化了多个 Ubuntu 22.04 服务器的初始服务器设置,以执行一个命令,完成播放簿所指定的所有任务。

要检查一切按预期工作,您将接下来登录到其中一个主机来验证设置。

(可选)步骤 7 — 手动检查服务器设置

若要在前一步结束时确认播放复制的输出,您可以使用先前配置的身份验证来登录您的主机之一,以验证设置. 这些操作是可选的学习目的,因为 Ansible复制报告准确完成。

开始使用以下命令登录到其中一个主机:

1ssh -p 5995 sammy@host1-public-ip-address

您使用 ) 中配置的自定义端口号, ) 中创建的用户 。 如果你能通过该端口登录到主机,你知道Ansible成功完成了这些任务.

一旦登录,请检查您是否能够更新包数据库:

1sudo apt update

如果您被要求提供密码,并可以使用您在 [步骤 5] 中为用户配置的密码进行身份验证(https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-5-using-ansible-vault-to-create-an-encrypted-password-file),您可以确认 Ansible成功完成了创建用户和设置用户密码的任务。

现在你知道设置播放簿按预期工作了,你可以运行第二个播放簿进行持续维护。

(可选)步骤 8 — 使用 Ansible 进行主机的持续维护

在 [步骤6] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-6-running-the-main-playbook-against-your-ansible-hosts] 中执行的初始服务器设置游戏本会按照您的意愿大小到尽可能多的服务器,但它在初始设置后无法管理主机. 虽然您可以单独登录到每个主机运行命令,但这一过程不会在您同时在更多服务器上工作时进行规模化. 作为[步骤3] (https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible step-3-cloning-the-ansible-ubuntu-initial-server-setup-repository)的一部分,你还拉出一个‘正在发生的'。 可用于持续维护的yml " 游戏本。 在这个步骤,你会运行‘持续'。 yml ' playbook,用于自动对本教程中设置的主机进行持续维护.

在运行播放簿之前,您将对每个任务进行审查. 要开始,请使用nano或您最喜欢的文本编辑器打开文件:

1nano ongoing.yml

与最初的设置播放簿不同,维护播放簿只包含一个播放和更少的任务。

玩一:

文件的第一部分中的下列关键字会影响播放的行为:

 1[label ongoing.yml]
 2- hosts: ongoing
 3  port: "{{ ssh_port }}"
 4  remote_user: "{{ create_user }}"
 5  become: true
 6  vars_files:
 7    - vars/default.yml
 8    - secret
 9  vars:
10    ansible_become_pass: "{{ password }}"
11...

除了转移到主机关键字的组之外,这些关键字在设置播放簿的第二次播放中使用。

關鍵字後,列出要順序執行的任務列表,正如在安裝播放本中一樣,維護播放本中的每個任務都以一個「名稱」開始,它提供了該任務將完成的簡短描述。

任务1:更新缓存

第一项任务更新包数据库:

1[label ongoing.yml]
2...
3- name: update cache
4  ansible.builtin.apt:
5    update_cache: yes
6...

此任务将使用ansible.builtin.apt模块更新包数据库,这就是为什么它被定义为update_cache:是的

任务2:更新所有已安装的软件包

第二个任务更新包:

1[label ongoing.yml]
2...
3- name: Update all installed packages
4  ansible.builtin.apt:
5    name: "*"
6    state: latest
7...

与第一个任务一样,这个任务也称为)和状态:最新,这相当于登录您的服务器并运行sudo apt upgrade -y命令。

任务3:确保 NTP 服务正在运行

玩本中的第三个任务确保了NTP Daemon的设置:

1[label ongoing.yml]
2...
3- name: Make sure NTP service is running
4  ansible.builtin.systemd:
5    state: started
6    name: systemd-timesyncd
7...

服务器上的活跃服务可能由于各种原因而失败,所以您要确保这些服务仍然活跃. 此任务会调用).

任务4:UFW - 它在运行吗?

第四个任务检查UFW防火墙的状态:

1[label ongoing.yml]
2...
3- name: UFW - Is it running?
4  ansible.builtin.command: ufw status
5    register: ufw_status
6...

您可以使用sudo ufw status命令检查Ubuntu上的UFW防火墙的状态。输出的第一行将读取Status: activeStatus: inactive。这项任务使用ansible.builtin.command模块运行相同的命令,然后将输出保存到ufw_status变量。

任务 5: UFW - 启用 UFW 并拒绝进入的流量

第五个任务将重新启用UFW防火墙,如果它已经被阻止:

1[label ongoing.yml]
2...
3- name: UFW - Enable UFW and deny incoming traffic
4  community.general.ufw:
5    state: enabled
6  when: "'inactive' in ufw_status.stdout"
7...

此任务呼叫community.general.ufw模块,仅在ufw_status变量输出中出现不活跃一词时才启用防火墙。

任务 6:删除不再需要的依赖性

本剧本中的第六个任务清除包的依赖性:

1[label ongoing.yml]
2...
3- name: Remove dependencies that are no longer required
4  ansible.builtin.apt:
5    autoremove: yes
6...

此任务通过调用ansible.builtin.apt模块来删除在服务器上不再需要的包依赖,这相当于运行sudo apt autoremove命令。

任务7:检查是否需要重新启动

第七个任务检查是否需要重新启动:

1[label ongoing.yml]
2...
3- name: Check if reboot required
4  ansible.builtin.stat:
5    path: /var/run/reboot-required
6  register: reboot_required
7...

在Ubuntu上,一个新安装或升级的软件包将发出信号,表示在安装或升级后通过创建 " /var/run/rebout-rebut-required " 文件而引入的修改需要重启. 您可以使用)保存到`reboot_required'变量。 下一个任务将询问该变量的价值.

任务8:必要时重新启动

第八项任务将必要时重新启动服务器:

1[label ongoing.yml]
2...
3- name: Reboot if required
4  ansible.builtin.reboot:
5  when: reboot_required.stat.exists == true

通过从任务 7 查询 reboot_required 变量,此任务会调用 ansible.builtin.reboot 模块,以便在 /var/run/reboot-required 存在时才重新启动主机。

持续维护的完整播放簿文件将如下:

 1[label initial.yml]
 2- hosts: ongoing
 3  port: "{{ ssh_port }}"
 4  remote_user: "{{ create_user }}"
 5  become: true
 6  vars_files:
 7    - vars/default.yml
 8    - secret
 9  vars:
10    ansible_become_pass: "{{ password }}"
11
12  tasks:
13    - name: update cache
14      ansible.builtin.apt:
15        update_cache: yes
16
17    - name: Update all installed packages
18      ansible.builtin.apt:
19        name: "*"
20        state: latest
21
22    - name: Make sure NTP service is running
23      ansible.builtin.systemd:
24        state: started
25        name: systemd-timesyncd
26
27    - name: UFW - Is it running?
28      ansible.builtin.command: ufw status
29      register: ufw_status
30
31    - name: UFW - Enable UFW and deny incoming traffic
32      community.general.ufw:
33        state: enabled
34      when: "'inactive' in ufw_status.stdout"
35
36    - name: Remove dependencies that are no longer required
37      ansible.builtin.apt:
38        autoremove: yes
39
40    - name: Check if reboot required
41      ansible.builtin.stat:
42        path: /var/run/reboot-required
43      register: reboot_required
44
45    - name: Reboot if required
46      ansible.builtin.reboot:
47      when: reboot_required.stat.exists == true

当你完成检查文件时,保存并关闭它。

<$>[注] 注: 你可以添加新的任务或修改现有的任务在播放簿. 然而,改变YAML文件可能会损坏它,因为YAML对间隔敏感,所以要小心,如果你选择编辑任何方面的文件。 有关如何使用Ansible播放簿的更多信息,请遵循我们的系列在 How To Write Ansible Playbooks

现在你可以运行文件. 首先,检查语法:

1ansible-playbook --syntax-check --ask-vault-pass ongoing.yml

您将被提示在 [步骤 5] 中创建的密码(https://andsky.com/tech/tutorials/how-to-automate-initial-server-setup-of-multiple-ubuntu-22-04-servers-using-ansible# step-5-using-ansible-vault-to-create-an-encrypted-password-file)。如果成功验证后没有YAML语法错误,输出将是:

1[secondary_label Output]
2playbook: ongoing.yml

您现在可以使用以下命令运行该文件:

1ansible-playbook --ask-vault-pass ongoing.yml

成功验证后,Ansible 控制器将以)登录每个主机,以执行播放簿中的任务。而不是在每个服务器上单独运行ssh -p 5995 sammy@host_ip_address命令,Ansible 会连接到在播放簿中的ongoing组中指定的节点,然后在播放簿中执行任务。

如果命令成功完成,将打印以下输出:

1[secondary_label Output]
2PLAY RECAP *****************************************************************************************************
3host1   : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0   
4host2   : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0   
5host3   : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0

与初始服务器设置的播放重复不同,这个播放重复记载了被跳过的两个任务,因为每个任务的条件设置与何时参数未满足。

您可以使用此播放簿来维护主机,而无需手动登录每个主机. 当您在主机上构建和安装应用程序时,您可以将任务添加到播放簿中,以便您也可以使用 Ansible 管理这些应用程序。

结论

在这个教程中,您使用Ansible实现多个Ubuntu 22.04服务器的初始设置自动化. 你还运行了一个二级游戏本 持续维护这些服务器。 Ansible自动化是一个节省时间的工具,当您需要在一个分布式或集群模式下设置一个像CassandraMNIO这样的应用程序.

更多关于 Ansible 的信息可在 官方 Ansible 文档网站 查看 An Introduction to Configuration ManagementConfiguration Management 101: Writing Ansible Playbooks

Published At
Categories with 技术
comments powered by Disqus