一、说明
ansible是很好用的服务器管理工具。之前的整理的记录都比较零散,整体结构不够清晰。每次查的时候,都要翻半天。所以这次重新整理了一份大纲,方便后续的使用。
本文的一些示例,拷贝的是官网 ansible6版本的内容。ansible6和当前的 ansible2.x版本有些变化,使用是请注意。
文档中的内容都没有经过测试,使用前记得测试。
二、ansible简介
ansible是一个基于ssh的配置管理工具。它不需要在管理服务器上安装客户端。所以使用起来方便、快捷。
三、ansible安装
centos7 yum安装
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum install ansible
更详细的安装参考官网安装文档
四、ansible列表清单(inventory)与配置文件
1.inventory
列表清单里面保存的是托管主机的列表。支持INI和YAML两种格式。
列表清单支持(以下只列出一些,更详细可以查看官网内容):
- ip
- 主机名
- 支持组
- 支持自定义别名
- 支持自定义端口
- 支持子分组
1.1 INI格式示例
mail.example.com #可以是主机名,也可以是ip
[webservers] #组方式
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
[redis:children] #子分组模式,此分组里面的主机列表时WebRedis+ServerRedis
webredis
serverdis
[WebRedis]
1.1.1.1
2.2.2.2
[ServerRedis]
3.3.3.3
4.4.4.4
1.2 YAML格式示例
all:
hosts:
mail.example.com:
children:
webservers:
hosts:
foo.example.com:
bar.example.com:
dbservers:
hosts:
one.example.com:
two.example.com:
three.example.com:
redis:
children:
WebRedis:
hosts:
1.1.1.1:
2.2.2.2:
ServerRedis:
hosts:
3.3.3.3:
4.4.4.4:
1.3 文件内的常用参数
参数为旧版本参数,若参数不可以使用,则可以在官网查看新的参数
ansible_ssh_host
将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port
ssh端口号.如果不是默认的端口号,通过此变量设置.
ansible_ssh_user
默认的 ssh 用户名
ansible_ssh_pass
ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass
sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)
sudo 命令路径(适用于1.8及以上版本)
ansible_connection
与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.
ansible_ssh_private_key_file
ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type
目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter
目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
1.4 详细内容
更详细的内容参考官网文档
朱双印博客关于inventory的内容参考
2.配置文件
Ansible支持多种配置其行为的来源,包括一个名为Ansible .cfg的ini文件、环境变量、命令行选项、playbook关键字和变量。有关每个源的相对优先级的详细信息,
五、ansible的两种使用方式
ansible可以使用两种方式,命令行和playbook模式。这里简单说下命令行模式,playbook模式可以看后面内容。
1.命令行模式(ad-hoc)
- ansible-doc
ansible-doc -l
# 显示所有的模块列表
ansible-doc -s fetch
# 显示某个模块的详细信息
- 对所有主机执行ping操作
ansible all -m ping
# all 是需要运行的主机列表,这里表示所有。
# -m 表示使用哪个模块
# ping 要执行的命令
- 使用fetch拷贝文件
ansible 10.1.1.60 -m fetch -a "src=/etc/fstab dest=/testdir/ansible/"
# -a 表示参数
更详细的讲解可以看此文章
2.playbook
六、ansible常用模块
1.模块列表(官网)
1.1 模块列表链接
1.2 常用模块链接
常用的模块,在最新的版本中,都归到ansible.builtin下面,并且使用方式也有了差别。
2.文件操作
- copy
文件拷贝模块,可以将文件从ansible服务器拷贝到列表服务器。
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/"
# /testdir/copytest文件拷贝到 test70服务器的/opt/目录下面
- file
实现对列表主机上文件的操作。比如创建文件、目录,删除文件、目录等
ansible test70 -m file -a "path=/testdir/testfile state=touch"
# 在test70的主机上创建/testdir/testfile文件
- find
在远程主机查找文件,类似于linux 的find命令
- blockinfile
在指定的文件插入一段带标记的文本。因为插入时,是标记了的,后续可以基于标记操作这段文本。
ansible test70 -m blockinfile -a 'path=/testdir/rc.local block="systemctl start mariadb\nsystemctl start httpd" marker="#{mark} serivce to start" '
# block 要插入的内容
# femarker插入的标记
详细说明可以看官网
- lineinfile
文本修改模块,类似于sed命令。
ansible test70 -m lineinfile -a 'path=/testdir/test regexp="^line" line="test text" '
# path后面是要操作的路径
# regexp 要匹配的字符串
# line 要替换的字符串
详细说明可以看官网
- replace
3.命令
- command(linux系统)
这个模块是在远程主机执行命令的模块。注意:使用command模块在远程主机中执行命令时,不会经过远程主机的shell处理,在使用command模块时,如果需要执行的命令中含有重定向、管道符等操作时,这些符号也会失效,比如”<“, “>”, “|”, “;” 和 “&” 这些符号,如果你需要这些功能,可以参考后面介绍的shell模块
- shell(linux系统)
这个模块是在远程主机执行命令的模块。shell模块与command不同之处在于,shell模块执行的命令,是通过远程主机的shell处理,而command不是。
- script(linux系统)
在远程主机执行脚本的模块
4.系统
- user
- cron
- service模块
5.包管理
- yum_repository
管理远程主机的yum仓库模块
- yum
管理远程主机yum模块
6.setup模块
获取管理主机(facts)模块
ansible <hostname> -m setup
7.fail异常处理模块
- name: Example using fail and when together
ansible.builtin.fail:
msg: The system may not be provisioned according to the CMDB status.
when: cmdb_status != "to-be-staged"
七、playbook
实际工作中,我们的要执行的任务一般都不会简单的几条命令可以搞定的,需要很多条命令才能完成一个任务。
比如安装nginx,我们需要下载软件、安装、配置等等。
使用ad-hoc的模式,执行的任务必须要写到一条命令中,如果无法写入一条命令中,则必须手动去执行下一条命令。这样并不方便,实现自动化也不容易。
有没有办法可以实现自动批量的执行任务?playbook就是用来实现这个功能。
我们可以将要执行的命令,按照规则playbook中,然后运行playbook,就可以实现我们期望的结果。
1.playbook文件说明
playbook是一个yaml文件。它由Task、module、play构成。
- name: My first play
# playbook的名字
hosts: virtualmachines
# 要执行的hosts
tasks:
# 任务清单
- name: Ping my hosts
# 任务名称
ansible.builtin.ping:
# 执行ping模块
- name: Print message
# 任务名称
ansible.builtin.debug:
# 执行debug模块
msg: Hello world
更多内容可以看官网文档:创建playbook、playbook关键字
2.facts
ansible可以获取远程主机或者ansible本身的信息,这些信息最后会存储到变量中。这些变量和值成为facts。
获取facts信息,可以使用steup模块。
ansible <hostname> -m setup
facts支持自定义变量
详细说明可以看官网文档
3.变量
ansible支持在变量,变量支持列表和字典
不是所有的字符串都是有效的Ansible变量名。变量名只能包含字母、数字和下划线。Python关键字或playbook关键字不是有效的变量名。变量名不能以数字开头。
示例:
- 定义变量
- hosts: app_servers
vars:
base_path: /etc/nginx/conf.d/80.conf
# 使用vars定义变量
app_path: "{{ base_path }}"/22
# 使用{{}} 引用变量
- 定义列表
- hosts: app_servers
vars:
# 使用vars定义变量
region:
- /etc/nginx/conf.d/80.conf
- /etc/nginx/conf.d/81.conf
- /etc/nginx/conf.d/82.conf
app_path: {{ region[0] }}/22
# 使用{{}} 引用变量
- 定义字典
- hosts: app_servers
vars:
# 使用vars定义变量
path:
- path_80:/etc/nginx/conf.d/80.conf
- path_81:/etc/nginx/conf.d/81.conf
- path_82:/etc/nginx/conf.d/82.conf
app_path: {{ path.path_80 }}/22
# 使用{{}} 引用变量
- 引文变量文件
还可以将变量单独存放到一个文件中,然后在palybook中引文这个文件使用变量。
---
- hosts: all
remote_user: root
vars:
favcolor: blue
vars_files:
# 使用vars_files引入变量文件
- /vars/external_vars.yml
tasks:
- name: This is just a placeholder
ansible.builtin.command: /bin/echo foo
- 注册变量
playbook支持将ansible任务输出中的返回值赋值到变量中。
---
- hosts: test70
remote_user: root
tasks:
- name: test shell
ansible.builtin.shell: "echo test > /var/testshellfile"
register: testvar
- name: shell module return values
debug:
var: testvar
上例中共有两个任务,第一个任务使用shell模块在test70主机中创建了一个测试文件 /var/testshellfile,将字符”test”输入到了测试文件中,然后使用”register”关键字将当前shell任务的返回值写入了名为”testvar”的变量中,第二个任务使用debug模块输出了第一个任务中的注册变量的值,没错,注册变量就是这么简单,使用register关键字指定对应的变量名即可。
- 通过命令行传入变量
---
- hosts: test70
remote_user: root
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{pass_var}}"
ansible-playbook cmdvar.yml --extra-vars "pass_var=cmdline pass var"
命令值传入的变量值优先级高于playbook定义的变量
- 清单配置定义变量
清单配置文件也支持定义变量。
4.条件判断
playbook支持判断语句
- 关键字:when
示例:
tasks:
- name: Shut down Debian flavored systems
ansible.builtin.command: /sbin/shutdown -t now
when: ansible_facts['os_family'] == "Debian"
# 如果系统版本是"Debian",则执行shutdown命令。
- 运算符
== :比较两个对象是否相等,相等为真
!= :比较两个对象是否不等,不等为真
> :比较两个值的大小,如果左边的值大于右边的值,则为真
< :比较两个值的大小,如果左边的值小于右边的值,则为真
>= :比较两个值的大小,如果左边的值大于右边的值或左右相等,则为真
<= :比较两个值的大小,如果左边的值小于右边的值或左右相等,则为真
and :逻辑与,当左边与右边同时为真,则返回真
or :逻辑或,当左边与右边有任意一个为真,则返回真
not :取反,对一个操作体取反
( ) :组合,将一组操作体包装在一起,形成一个较大的操作体
5.循环
playbook也支持循环。旧版本的使用的是with_*这些关键字,新版使用的loop以及lookup。h
- name: Add several users
ansible.builtin.user:
name: "{{ item }}"
# item是loop中循环的值。
state: present
groups: "wheel"
loop:
- testuser1
- testuser2
# 以上相当于以下的内容
- name: Add user testuser1
ansible.builtin.user:
name: "testuser1"
state: present
groups: "wheel"
- name: Add user testuser2
ansible.builtin.user:
name: "testuser2"
state: present
groups: "wheel"
6.模板
playbook支持模板文件,使用的是Jinja2模板。
7.tags
在使用playbook时,可以给指定的任务添加标签。在运行playbook时指定标签,就只执行指定了标签的任务。
示例文件:
tasks:
- name: Install the servers
ansible.builtin.yum:
name:
- httpd
- memcached
state: present
tags:
- packages
- webservers
- name: Configure the service
ansible.builtin.template:
src: templates/src.j2
dest: /etc/foo.conf
tags:
- configuration
执行playbook
ansible-playbook --tags=packages tagestest.yaml
上面的playbook,就只执行yum这个命令,其它命令不执行。
五种特殊的标签
always
never
tagged
untagged
all
8.handlers
8.1 handlers
有时,希望只有在机器上发生更改时才运行任务。
例如,如果任务更新了某个服务的配置,则可能需要重新启动该服务,但如果配置没有改变,则不需要重新启动该服务。Ansible使用处理程序来解决这个用例。处理程序是只在收到通知时才运行的任务。
下面的示例,只有当Write the apache config file的任务执行后,才会执行名为Restart apache的handlers。
- name: Verify apache installation
hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: Ensure apache is at the latest version
ansible.builtin.yum:
name: httpd
state: latest
- name: Write the apache config file
ansible.builtin.template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- Restart apache
- name: Ensure apache is running
ansible.builtin.service:
name: httpd
state: started
handlers:
- name: Restart apache
ansible.builtin.service:
name: httpd
state: restarted
8.2 handlers错误处理
当Ansible从命令或模块接收到非零返回码时,默认情况下它会停止在该主机上执行,并在其他主机上继续执行。然而,在某些情况下,您可能需要不同的行为。有时非零返回码表示成功。有时,您希望一台主机上出现故障,从而停止所有主机上的执行。Ansible提供了处理这些情况的工具和设置,并帮助您获得所需的行为、输出和报告。
默认情况下,当主机上的任务失败时,Ansible会停止执行该主机上的任务。如果使用了ignore_errors关键字,则在失败后继续执行。
- name: Do not count this as a failure
ansible.builtin.command: /bin/false
ignore_errors: yes
详细说明可以看官方文档
9.插件
playbook支持很多插件,具体可以看官方的插件列表
10.include
在playbook可以将其他的playbook文件导入,由过个playbook组合成一个playbook文件。
可以在一个非常大的文件中编写一个简单的剧本,大多数用户首先学习的是单文件方法。然而,将自动化工作分解成更小的文件是组织复杂任务集并重用它们的极好方法。更小、更分布式的工件允许您在多个剧本中重用相同的变量、任务和玩法,以解决不同的用例。您可以跨多个父剧本,甚至在一个剧本中多次使用分布式工件。例如,您可能希望将更新客户数据库作为几个不同剧本的一部分。如果将与更新数据库相关的所有任务放在一个任务文件或一个角色中,则可以在多个剧本中重用它们,而只在一个地方维护它们。
# restarts.yml
- name: Restart apache
ansible.builtin.service:
name: apache
state: restarted
- name: Restart mysql
ansible.builtin.service:
name: mysql
state: restarted
- name: Trigger an included (dynamic) handler
hosts: localhost
handlers:
- name: Restart services
include_tasks: restarts.yml
# 将restarts.yml导入。
tasks:
- command: "true"
notify: Restart services
更多内容可以看官方文档
11.block
playbook中可以将多个任何放到一个组中,这个组就是block。
tasks:
- name: Install, configure, and start Apache
block:
- name: Install httpd and memcached
ansible.builtin.yum:
name:
- httpd
- memcached
state: present
- name: Apply the foo config template
ansible.builtin.template:
src: templates/src.j2
dest: /etc/foo.conf
- name: Start service bar and enable it
ansible.builtin.service:
name: bar
state: started
enabled: True
when: ansible_facts['distribution'] == 'CentOS'
become: true
become_user: root
ignore_errors: yes
12.tests
详见官方文档
13.过滤器
过滤器允许您将JSON数据转换为YAML数据,拆分URL以提取主机名,获取字符串的SHA1散列,添加或乘整数,等等。您可以使用这里介绍的特定于ansible的过滤器来操作您的数据,也可以使用Jinja2附带的任何标准过滤器—请参阅官方Jinja2模板文档中的内置过滤器列表。还可以使用Python方法转换数据。你可以创建自定义的Ansible过滤器作为插件,尽管我们通常欢迎新的过滤器进入Ansible -core repo,以便每个人都可以使用它们。
详见官方文档
八、角色
角色允许您根据已知的文件结构自动加载相关的变量、文件、任务、处理程序和其他Ansible构件。在将内容按角色分组之后,您可以轻松地重用它们并与其他用户共享它们。
详见官方文档
九、数据加密
Ansible Vault加密变量和文件,因此您可以保护敏感内容,如密码或密钥,而不是将其作为明文显示在剧本或角色。
详见官方文档
十、特权模式
Ansible使用现有的权限升级系统来执行具有根权限或其他用户权限的任务。因为这个功能允许您“成为”另一个用户,不同于登录到机器上的用户(远程用户),我们称之为“成为”。become使用现有的特权升级工具,如sudo、su、pfexec、doas、pbrun、dzdo、ksu、runas、machinectl等。
详见官网文档