第2章 Ansible入门
2.1 安装Ansible
以CentOS为例:
2.1.1 在管理员的电脑安装
- 安装Ansible软件
yum install epel-release -y
yum install ansible -y
- 配置Ansible管理节点到主机的连接
#生成密钥
ssh-keygen
#复制密钥的远程主机上
ssh-copy-id remoteuser@remoteserver
#SSH的时候不会提示是否保存密钥
ssh-keyscan remote_servers >> ~/.ssh/known_hosts
2.1.2 被管理的远程主机
啥也不用做,只需要保证SSH服务是启动的,并且Python版本大于2.4即可。
2.2 Ansible管理哪些主机
2.2.1 什么是主机目录
主机目录(Host Inventory,又称为主机清单)是配置文件,用来告诉Ansible需要管理哪些主机,并且把这些主机按需分类。
2.2.2 主机目录配置文件
默认的文件是: /etc/ansible/hosts .可以修改为其他文件
2.3 Ansible用命令管理主机
Ansible提供了一个命令行工具,官方叫做 Ad-Hoc Commands。
- Ansible命令的格式
ansible <host-pattern> [options]
- 示例
#检查所有的远程主机,是否以 "pangcm" 用户创建了Ansible管理主机可以访问的环境
ansible all -m ping -u pangcm
#执行命令
ansible all -a "/bin/echo hello"
#复制文件
ansible web -m copy -a "src=/etc/hosts dest=/tmp/hosts"
#安装包
ansible web -m yum -a "name=acme state=present"
#添加用户
ansible all -m user -a "name=foo password=<crypted passowrd here>"
#并行执行
ansible lb -a "/sbin/reboot" -f 10
#查看远程主机的全部系统信息
ansible all -m setup
2.4 Ansible用脚本管理主机
为了避免重复输入命令,Ansible提供了脚本功能。Ansible脚本的名字叫做Playboo,使用的YAML格式,文件以yml活yaml为后缀。
2.4.1 执行脚本Playboook的方法
ansible-playbook deploy.yml
2.4.2 Playbook 的例子
Playbook 包含了几个关键字,每个关键字的含义如下。
- hosts: 某主机的IP,或者主机名,或者关键字 all.
- remote_user: 以某个用户身份执行。
- vars: 变量
- tasks: Playbook的核心,定义顺序执行的动作Action。每个Action调用一个Ansible模块。
- action 语法:
module: module_parameter=module_value
- 常用的模块有 yum、copy、template等,模块在Ansible中的作用,相当与bash脚本中的yum、copy这样命令的作用。
- handers: Playbook的Even处理操作,有且仅有被Action触发时才会执行。但是多次出发只执行一次,并按照声明的顺序执行。下面是一个安装Apache的示例:
---
- hosts: web
vars:
http_port:80
remote_user: root
tasks:
- name: ensure apache is at the lastest version
yum: pkg=httpd state=latest
- name: Write the configuration file
template: src=template/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
2.4.3 Play和Playbook
在一个Playbook文件中,针对每一组主机的所有操作就是一个Play,一般情况下一个Playbook只包含一个Play,但是也而已包含多个。
2.5 Ansible模块
2.5.1 什么是Ansible模块
类别于shell,Ansible中的模块就好比shell中的命令。shell中的命令可以带参数,Ansible中的模块也可以带参数。
2.5.2 在命令行中使用模块
在命令行中:
- -m 后面接调用模块的名字
- -n 后面接调用模块的参数
如:
ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts"
2.5.3 在Playbook中使用模块
在Playbook脚本中,tasks中每一个Action都是对模块的一次调用。在每个Action中:
- 冒号前面的是模块的名字
- 冒号后面是调用模块的参数
2.5.4 Ansible模块的特点
- 像Linux中的命令一样,Ansible的模块既可以在命令行中调用,也可以在Ansible脚本Playbook中调用。
- 每个模块的参数和状态判断,都取决于该模块的具体实现,所以在使用它们之前需要查阅该模块的文档。
- 可以通过文档查看具体的用法
- 通过命令 ansible-doc 也可以查看模块的用法
- Ansible提供一些常用功能的模块,同时Ansible也提供API,让用户可以自己写模块,使用的编程语言是Python。
2.5.5 常用的模块
下面介绍一些常用的模块
-
调试和测试类的模块
- ping: ping远程主机,如果返回pong,则意味着能够通过Ansible连接
- debug: 用于调试的模块,只是打印一些消息,类比Linux的ehco。
-
文件类的模块
- copy: 从本地复制文件到远程节点
- template: 从本地复制文件到远程节点,并进行变量的替换
- file: 设置文件属性
-
Linux 上常用的操作
- user: 管理用户账户
- yum: Red Hat 系Linux上的包管理
- service: 管理服务
- firewall: 管理防火墙中的服务和端口
-
执行shell命令
- shell:在节点上执行shell命令,支持 $HOME、 "|" 和 "&" 等。
- command: 在节点上执行shell命令,不支持 $HOME、 "|" 和 "&" 等。
针对上面提到的常用模块,下面针对几个做下具体的介绍
- debug 模块
- 通过参数 msg 定义打印的字符串,当然也可以打印变量
- debug: msg: "I can echo vars {{ inventory_hostname }}"
- 通过参数 var 定义需要打印的变量,后面直接跟变量的名称
- debug: var: inventory_hostname
msg 和 var 都能输出变量,但是 msg输出变量时需要显式地表示变量才行,也就是使用 "{{}}" 标注,如果shell中的 "$()" 。而var则不需要。
-
copy 模块
需要注意的是,copy模块在复制前会先比较文件的 checksum,如果相同则不复制,返回状态OK;如果不同才复制,返回状态 changed.- 设置文件权限
利用mode 设置权限可以是数字,也可以时符号的形式,如"u=rw,g=r,o=r"
- copy: "src=/etc/hosts dest=/tmp/hosts owner=foo group:foo mode=0644"
- 备份节点上原来的文件
当backup参数为yes的时候,如果发生了复制操作,那么会先复制目标节点上的源文件。当两个文件相同时,不再进行复制操作。
- copy: "src=/etc/hosts dest=/tmp/hosts backup=yes"
- 复制后的验证操作
validate 参数接需要验证的命令。一般需要验证复制后的文件,所以 %s 都可以指代复制后的文件。当copy模块中加入 validate 参数后,不仅需要成功复制文件,还需要 validate命令返回成功的状态,整个模块的执行才算成功。常见的场景如 visudo。
- copy: src: /tmp/sudoers dest: /etc/sudoders validate: 'visudo -cf %s'
- 设置文件权限
-
template 模块
使用的方法和copy几乎一模一样,不同的是template可以携带变量。也就是说能够进行变量的替换,起到模版的用途。这里只需要知道变量的使用需要使用 "{{}}" 即可,后面会介绍jinja2的具体用法。常见的场景如nginx配置文件的复制替换。
- file模块
file模块可以用来设置远程主机的文件、软连接和文件夹的权限,也可以用来创建和删除他们。如下所示
- name: "改变文件的权限"
file: path=/etc/foo.conf mode=0644
- name: "创建文件的软链接"
file: src=/tmp/hosts dest=/tmp/hosts_symlink state=link
- name: "创建一个新文件"
file:
path: /etc/foo.conf
state: touch
mode: 0644
- name: "创建一个目录"
file:
path: /tmp/test
state: directory
mode: 0755
- user 模块
user 模块可以增、删、改Linux远程节点的用户账户,并为其设置账户的属性。如下
---
- hosts: remote_host
tasks:
- names: "增加用户"
user: "name=johnd comment='John Doe' uid=1040 group=admin"
- name: "创建用户james,并将其添加到两个group中"
user: "name=james shell=/bin/bash groups=admin,developers append=yes"
- name: "删除账户"
user: "name=johnd state=absent remove=yes"
- name: "修改账户的属性,创建SSH密钥,并放在 ~/.ssh/id_rsa 中 "
user:
name: jsmith
generate_ssh_key: yes
ssh_key_file: .ssh/id_rsa
- yum 模块
yum模块用来管理RedHat系的安装包的,Red Hat8使用了dnf来管理包,如果远程主机是版本8的话,则需要使用dnf模块。
- name: "从yum源上安装最新的httpd包,已经有的话则会更新"
yum: "name=httpd state=latest"
- name: "安装指定版本的包"
yum: "name=httpd-2.2.29-1.4.amzn1 state=present"
- name: "删除httpd包"
yum: "name=httpd state=absent"
- name: "安装一组包"
yum:
name: "@Development tools"
state: present
- name: "本地安装包"
yum: "name=/tmp/httpd.rpm state=present"
- service 服务管理模块
改模块用来管理远程节点上的服务,比如httpd、sshd等。
- name: "开启服务"
service: "name=httpd state=started"
- name: "重启服务"
service: "name=httpd state=restarted"
- name: "设置开机启动"
service: "name=httpd enabled=yes"
- name: "启动网络服务下的接口 eth0"
service: "name=network state=restarted args=eth0"
- firewalld 模块
firewalld 模块为某服务和端口添加firewalld规则。firewalld中有正在运行的规则和永久规则,firewalld模块都支持。
- name: "为服务添加firewalld规则"
firewalld: "zone=dmz service=https permanent=true state=enabled"
- name: "为端口号添加firewalld规则"
firewalld: "port=8081/tcp permanent=true state=disabled"
- name: "其他复杂的firewalld规则"
firewalld: "source=192.168.2.0/24 zone=internal state=enabled"
- name: "其他复杂的firewalld规则"
firewalld: "zone=trusted interface=eth2 permanent=true state=enabled"
- shell 模块
如果能通过其他的Ansible模块实现的尽量不要使用shell模块来实现,原因是shell模块不会对执行的状态进行判断,也就是不存在该模块不存在幂等性。
shell模块支持 $HOME、"<"、">"、"|"、";" 和 "&" 。
- name: "test $home"
shell: echo "test1" > ~/tmp/test1
- name: "test &&"
shell: service jboss start && chkconfig jboss on
- name: "支持调用脚本"
shell: "somescript.sh >> somelog.txt"
- name: "可以指定工作目录"
shell: "somescript.sh >> somelog.txt"
args:
chdir: somedir/
- name: "指定工作目录,并且仅在文件somelog.txt 不存在时执行命令"
shell: "somescript.sh >> somelog.txt"
args:
chdir: somedir/
creates: somelog.txt
- command 模块
功能和shell类似,但是不支持 $HOME、"<"、">"、"|"、";" 和 "&" 等操作。和shell不同的地方是能够传入参数。
- name: "比shell模块多一个传参的方式"
command: /usr/bin/make_database.sh arg1 arg2 creates=/path/database