我使用类似的 shell (Bash) 脚本在远程 Debian 机器上建立了一个带有一些额外功能的 LAMP:
#/bin/bash
apt update -y
apt upgrade ufw sshguard unattended-upgrades wget curl git zip unzip tree -y
ufw --force enable
ufw allow 22,25,80,443
apt upgrade lamp-server^ ssmtp
apt upgrade python-certbot-apache
apt upgrade php-{cli,curl,mbstring,mcrypt,gd} phpmyadmin
curl -sS https://getcomposer.org/installer -o composer-setup.php
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
a2enmod http2 deflate expires
一些看到类似脚本的系统管理员告诉我这样的话:“你最好使用 Ansible 来完成它,否则维护它将是一场噩梦”。
好吧,我可以使用我编写的以下 Ansible 剧本实现基本相同的效果(尚未测试,因为我现在没有空闲机器,但部署到所有机器时应该可以工作):
---
- hosts: all
become: yes
become_user: root
tasks:
- name: Update apt package-indexes cache
apt:
update_cache=yes
- name: Install external basics
apt: state=latest
with-items:
- ufw
- sshguard
- unattended-upgrades
- wget
- curl
- git
- zip
- unzip
- tree
- name: Setup firewall with ufw
ufw:
rule: allow
port: 22,25,80,443
- name: Establish a LAPMS server environment (Linux, Apache, PHP, MySQL, SSMTP)
apt: state=latest
with-items:
- apache2 # Web server
- python-certbot-apache
- php
- php-mysql # MySQL server
- php-cli
- php-curl
- php-mbstring
- php-mcrypt
- php-gd
- phpmyadmin
- ssmtp # Email server
- name: Manually install PHP Composer
get_url:
url: https://getcomposer.org/installer
dest: /tmp/composer-setup.php
command: php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
- name: Configure PHP variables
shell: |
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
args:
executable: /bin/bash
- apache2_module:
state: present
name: http2
- apache2_module:
state: present
name: deflate
- apache2_module:
state: present
name: expires
我的沉思
在上面的小例子中,我不认为使用纯粹的 Ansible 相对于纯粹的 shell 脚本有显着的优势因为 Ansible 只做我们告诉它的事情并且不执行release_upgrades(从Apache 2.4到3.4)并且基本上会给我apt upgrade -y
与调度相同的自动化(例如cron
),所以我不明白它将如何成为一个帮助器(结果也基本上相同,但是行数要多得多(72 行而不是 20/21),除非使用 Ansible-Galaxy 角色,这些角色是组织良好的程序,包含一个或多个 Ansible 剧本的核心。
我的问题
在诸如上述的琐碎任务中,仅 Ansible 本身(不使用 Ansible-Galaxy 角色)如何比一般的 shell 脚本(特别是 Bash)更有效?
答案1
我不认为 20 行作为一个或两台机器的 shell 脚本有什么大问题。这是一件好事。
也就是说,您的脚本不是幂等的。例如,它使用apt-get upgrade foo
,即使脚本已经在此系统上运行,它也可以执行更改。我认为不值得使用apt-get upgrade foo
。该命令不保证将安全或错误修复更新应用于您的依赖项。
精心编写的 Ansible 手册可以兼作小型系统检查。这依赖于剧本是幂等的(并且它准确地报告“更改”状态)。运行时ansible-playbook --check
将显示系统是否仍然满足所有定义的任务,或者是否已发生更改。这在以后很有用,也可以在运行剧本后立即查找不一致之处。
您可以设置 Ansible,以便可以同时在多台机器上运行它。
像 Ansible 这样的配置工具在大规模应用中非常有用。部分原因是这些特征。部分原因是由于这些限制,它鼓励您遵循这些限制。
鼓励您编写幂等脚本对于维护也很有用。考虑编写一个向现有文件添加行的脚本(或在现有行中添加标记:-( )的诱惑。如果确保幂等性,那么您可以重新运行修改后的脚本,而无需添加重复行。
另一个限制是您是否想从已安装的系统中删除某些内容。在许多情况下,这不是问题,您可以稍后编写卸载脚本/剧本。但在某些情况下你需要小心这一点。例如,您可能希望确保不要使用 Ansiblelineinfile
替换单个行,而是用您自己的版本覆盖整个文件。当您不想再更改 A 行的默认设置,但仍想更改 B 行时,这会很有用。
对于我的使用,我想解决管理防火墙时的删除问题。如果您在安装脚本中停止允许某个端口,您可能会忘记在各处显式阻止该端口。 Ansibleufw
模块在这里没有帮助,因为它只允许添加或删除单个规则。我目前正在考虑使用ufw
防火墙的替代方案,它对配置文件的工作有适当的支持。 (例如firewalld
,,,shorewall
... ferm
)。
答案2
Bash 和 Ansible 之间的区别在于,如果编写得当,Ansible 是幂等的。当剧本重复运行时,不会发生任何变化。在这方面,Bash 脚本描述了一个过程,而 Ansible playbook 则描述了系统的状态。
解决评论
“不确定我对幂等的理解是否足以理解答案”。
幂等性意味着剧本“可以多次应用,而不会改变初始应用之外的结果”。最佳实践是运行剧本两次。在第一次运行期间,剧本会执行所有更改。在第二次运行期间,不应报告任何变化。
答案3
Ansible 的主要卖点之一是,由于使用了 YAML 语法,剧本往往比密集的 BASH oneliner 更容易阅读。您还可以以比 BASH 脚本功能更丰富的方式使用 linter 和调试器,一些 IDE 甚至内置了 Ansible 文本完成模块来协助编写剧本。