目录
1、概念介绍
Ansible Playbooks 提供了一个可重复、可重用、简单的配置管理和多机部署系统,非常适合部署复杂的应用程序。当你需要反复执行或要执行多个 task 时,可以将这些 task 编写入 playbook,然后用 playbook 推送给在 inventory 中定义好的一组服务器执行。
playbook 以 YAML 格式表示。一个 playbook 由一个或多个 play 组成,一个 play 中
包含一个或多个 task,一个 task 对应一个 module。 playbook 按从上到下的顺序运行。在每个 play 中,tasks 也按从上到下的顺序运行。
roles 角色
当我们刚开始学习运用 playbook 时,因为操作很多,所以很可能会把 playbook 写成一个很大的文件,慢慢你会发现,playbook 的内容较为混乱,难以管理。Roles 相当于我们剧本当中的角色,把不同的任务分配给不同的角色,可以使大型项目易管理,当需要做不同的事情时,只需要调用不同角色即可。
把不同功能的 playbook 分开,一个标准的角色含有下列子目录:
角色子目录 | 说明 |
defaults | 其中的 main.yml 包含角色变量的默认值,在所有变量中优先级最低 |
files | 包含角色任务引用的静态文件 |
handlers | 主要定义处理程序 |
meta | 角色相关信息,如作者、许可证等 |
tasks | 定义任务 |
templates | 任务引用的 jinja2 模板 |
tests | 可以包含清单和 test.yml 的 playbook,用于测试 |
vars | 定义角色的变量 |
playbook 核心元素
① target:定义 PlayBook 的远程主机组
target 常用参数 | 说明 |
hosts | 运行指定任务的目标主机,可以是一个主机组、主机、多个主机,中间以冒号分隔,也可以用 all 参数表示所有主机。 |
remote_user | 指定远程主机上的执行任务的用户。 |
gather_facks | 获取远程主机 facts 基础信息。注:gather_facts: True 表示在远程主机运行 setup 模块,获取远程主机的 facts,facts 就是变量,内建变量 。每个主机的各种信息,cpu 颗数、内存大小等,会存在 facts 中的某个变量中,调用后返回很多对应主机的信息。 |
② variables:定义 PlayBook 使用的变量
variables 常用参数 | 说明 |
vars | 在 yaml 文件中定义变量赋值。定义格式,变量名:变量值 |
vars_files | 指定变量文件,在文件中定义变量 |
③ tasks:定义远程主机上执行的任务列表
tasks 常用参数 | 说明 |
name | 任务显示名称也是屏幕显示信息 |
module_name | module_args: 需要使用的模块名字: 模块参数 |
关于 task 说明:
- Play 的主体部分是 task 列表,task 列表中的各任务按次序逐个在 hosts 中指定的主机上执行
- 在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,整个 tasks都会回滚,请修正 playbook 中的错误,然后重新执行即可。
- 每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的。
- 定义一个 task,常见的格式:” module_name: module_args” 例如:yum: name=httpd state=absent update_cache=yes
- ansible 的自带模块中,command 模块和 shell 模块无需使用 key=value 格式
④ handlers:处理器,当某条件满足时,触发执行的操作。例如修改配置文件之后,启动跟 handlers 任务重启相关联的服务 。
handler 常用参数 | 说明 |
notify | notify”这个 action 可用于在每个 play 的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。 在 notify 中列出的操作称为 handler,也即 notify 中调用 handler 中定义的操作。 |
handler | 也是 task 的列表。在 notify 中列出的操作称为 handler,也即 notify 中 调用 handler 中定义的操作。 Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行。 不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次。 |
⑤ roles :角色,用于层次性、结构化地组织 playbook。roles 能够根据层次型结构自动装载变量文件、tasks 以及 handlers 等。
ansible-playbook 命令
语法:ansible [选项] yaml文件
- -C, --check 只检测可能会发生的改变,但不真执行操作
- -D, --diff 更改(小)文件和模板时,显示这些文件中的差异
- --list-hosts 输出匹配主机的列表;不执行任何其他操作
- --list-tasks 列出将要执行的所有任务
- --syntax-check 对 playbook 执行语法检查,但不要执行
- -t TAGS_NAME 表示跳过标签前的步骤,直接从标签位置开始
ansible-playbook --syntax-check install.yaml
playbook 简单案例
github 上提供了大量的实例供大家参考: https://github.com/ansible/ansible-examples
vim install.yaml
---
- name: yum install package
hosts: web_servers
remote_user: root
vars:
name1: tree
tasks:
- name: install lrzsz
command: yum install -y lrzsz
- name: install tree
command: yum install -y {{name1}}
第一行:使用三个横杠作为开始,在 YAML 语法中,---表示文档开始。
第二行:使用- 开头(横杠后面有空格),YAML 使用"-"表示一个块序列的节点,name play 的名称
第三行:hosts 关键字对应的值为 web-servers,表示我们要在 web-servers 主机组上进行操作
第四行:使用 remote_user 关键字可以指定在进行远程操作时使用哪个用户进行操作,'remote_user: root'表示以远程主机的 root 用户进行操作, 与 hosts 关键字对齐,表示它们是平级的
第五行:vars 设置变量,格式为 key:values
第七行:tasks 任务列表,整个任务列表一共有两个任务组成,每个任务都以"- "开头,每个任务都有自己的名字,任务名使用 name 关键字进行指定,name 下是 我们执行任务的模块。变量调用使{{var}}
# 执行 playbook
ansible-playbook install.yaml
注意:Gathering Facts 任务会收集当前 play 对应的目标主机的相关信息,收集完这些基础信息后,才会执行我们指定的任务。
2、Ansible 变量
自定义变量
① 在剧本中定义变量
---
- hosts: web
vars:
file: /etc/hostname
dir: /root
tasks:
- name: print var
debug:
msg: "{{ dir }}变量file的内容是{{ file }}"
注意:如果msg起始位置有变量需要使用引号。
② 在文件中定义变量
# vars-file.yml
file: /etc/hostname
dir: /root
---
- hosts: web
vars_files: ./vars-file.yml
tasks:
- name: print var
debug:
msg: "{{ dir }}变量file的内容是{{ file }}"
③ 根据主机清单分组自动识别变量
通过主机清单里面的分组进行变量的共享,eg:web服务器 port 80,data服务器 port 873
group_vars/
lb/vars.yml # 存放lb组的变量
web/vars.yml # 存放web组的变量
data/vars.yml # 存xxx组的变量
all/vars.yml # 存放所有主机共用的变量
mkdir -p /etc/ansible/lamp/group_vars
cd /etc/ansible/lamp/group_vars
mkdir {lb, web, data, all}
vim data_vars.yml
port: 873
vim web_vars.yml
port: 80
---
- hosts: web
tasks:
- name: print var
debug:
msg: "当前服务的端口号:{{ port }}"
- hosts: data
tasks:
- name: print var
debug:
msg: "当前服务的端口号:{{ port }}"
facts 变量
fact变量是在运行剧本的时候ansible收集的每台机器的信息
# 查看ansible facts 变量
ansible web_servers -m setup
# 编写剧本
---
- hosts:
tasks: print facts vars
- name: print facts vars
debug:
msg: "facts变量{{ ansible_default_ipv4.addresses }}"
常用 facts 变量
- ansible_hostname 主机名
- ansible_memtotal_mb 内存大小(总计),单位mb
- ansible_processor_vcpus cpu数量
在 /etc/motd 写入主机名,ip地址,内存大小,cpu个数
#批量分发 motd 文件,文件内容根据不容机器变化
①②③④⑤
Palybook 部署 LAMP
ansible 端安装 LAMP
首先,我们可以在 ansible 服务器上安装 LAMP 环境,然后,再将配置文件通过 ansible 拷贝到远程主机上,如果有配置文件不用在管理机安装 LAMP。
① 安装软件
# ---------------------------------安装 httpd---------------------------------
yum install -y httpd
systemctl start httpd
#------------------------------------ 安装 MySQL ----------------------------
yum install -y mariadb-server mariadb
# 创建数据库保存目录
mkdir -p /data/mysql/data
# 修改权限
chown -R mysql:mysql /data/mysql/
# 修改数据保存目录
vim /etc/my.cnf
datadir=/data/mysql/data
# 启动服务
systemctl start mariadb
# --------------------------安装 PHP 和 php-mysql 模块 --------------------------------
yum install -y php php-mysql
# 提供 php 的测试页
vim /var/www/html/index.php
<?php
phpinfo();
?>
# 重启httpd 服务
systemctl restart httpd
确保已经出现上面的测试页,而且,要看到 MySQL 已经被整合进来了,才能进行下一步操作
② 配置主机 和 ssh登录
# 定义主机名
vim /etc/ansible/hosts
[web-servers]
192.168.137.105
192.168.137.106
# 设置 ssh 免密连接
ssh-keygen
ssh-copy-id root@192.168.137.105
ssh-copy-id root@192.168.137.106
playbook 系统环境脚本
# 创建相关文件
mkdir -pv /etc/ansible/lamp/roles/{prepare,httpd,mysql,php}/{tasks,files,templates,vars,meta,default,handlers}
# 拷贝文件:将搭建成功的 LAMP 环境的 httpd 和 MySQL 的配置文件拷贝到对应目录下
cp /etc/httpd/conf/httpd.conf lamp/roles/httpd/files/
cp /etc/my.cnf lamp/roles/mysql/files/
#初始化系统环境的脚本:写 prepare(上面创建好的)角色的 playbooks
vim lamp/roles/prepare/tasks/main.yml
- name: delete yum config
shell: rm -rf /etc/yum.repos.d/* #删除原有的 yum 配置文件
- name: provide yumrepo file
get_url:
url: http://mirrors.aliyun.com/repo/Centos-6.repo
dest: /etc/yum.repos.d/CentOS-Base.repo
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6")
- name: provide yumrepo file
get_url:
url: http://mirrors.aliyun.com/repo/Centos-7.repo
dest: /etc/yum.repos.d/CentOS-Base.repo
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")
- name: clean the yum repo
shell: yum clean all #清除原有的 yum 缓存信息
- name: clean the iptables
shell: iptables -F #清除原有防火墙规则,不然后可能上不了网
- name: close firewalld
service: name=firewalld state=stopped enabled=no
- name: close selinux
template:
src: config.j2
dest: /etc/selinux/config
- name: current close selinux
command: setenforce 0
ignore_errors: true
[root@node_04 ansible] cp /etc/selinux/config lamp/roles/prepare/templates/config.j2
template 模块跟 copy 模块类似,指定模版文件,该文件必须存在于 prepare 角色目录下的 templates 目录中,起名需要加上.j2 结尾,将 templates 下的文件复制到对应主机的对应目录下,src 指定源文件,dest 指定目标目录及复制到目录后改成什么名字。
该模块和 copy 模块作用基本一样,都是把某个文件复制到远端主机上,但是区别在于 template 模块可以获取变量的值,而 copy 则是原封不动的把文件内容复制过去。
构建 httpd 任务
① 配置 httpd 的 tasks
cd /etc/ansible/lamp/roles
cp /var/www/html/index.php httpd/files/
vim httpd/tasks/main.yml
---
- name: web server install
yum: name=httpd state=present
- name: provide test page
# 提供测试页
copy: src=index.php dest=/var/www/html
- name: delete apache config
# 删除原有的 apache 配置文件,如果不删除,下面的 copy 任务是不会执行的,
# 因为当源文件 httpd.conf 和目标文件一样时,copy 命令是不执行的。
# 如果 copy 命令不执行,那么 notify 将不调用 handler。
shell: rm -rf /etc/httpd/conf/httpd.conf
- name: provide configuration file
# 提供 httpd 的配置文件
copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
# 当前面的 copy 复制成功后,通过 notify 通知名字为 restart httpd 的 handlers 运行。
notify: restart httpd
② 构建 httpd 的 handlers
vim httpd/handlers/main.yml
- name: restart httpd
service: name=httpd enabled=yes state=restarted
构建 mariadb 任务
创建 MySQL 服务的任务,需要安装 MySQL 服务,改变属主信息,启动 MySQL
vim /etc/ansible/lamp/roles/mysql/tasks/main.yml
---
# 安装 mysql 服务
- name: install the mysql
yum:
name: ['mariadb-server', 'mariadb','MySQL-python']
state: present
# 创建数据挂载点目录
- name: mkdir data directory
shell: mkdir -p /data/mysql/data
# 提供 mysql 的配置文件
- name: provide configration file
copy: src=my.cnf dest=/etc/my.cnf
# 更改属主和属组
- name: chage the owner
shell: chown -R mysql:mysql /data/mysql
# 启动 mysql 服务
- name: start mariadb
service: name=mariadb enabled=yes state=started
- name: set root passwd
shell: /usr/bin/mysqladmin -uroot password '123456' | /bin/true
- name: create a database
mysql_db:
login_host: localhost
login_user: root
login_password: "123456"
login_port: 3306
name: test
encoding: utf8
state: present
- name: create user
mysql_user:
login_host: localhost
login_user: root
login_password: "123456"
login_port: 3306
name: test
host: "192.168.137.%"
password: "123456"
priv: "test.*:ALL"
state: present
构建 php 任务
vim php/tasks/main.yml
---
- name: install php
yum: name=php state=present #安装 php
- name: install php-mysql
yum: name=php-mysql state=present #安装 php 与 mysql 交互的插件
------------------------------------------------------------------------
# 一次安装多个软件格式:
- name: install php
yum:
name: ['php','php-mysql' , 'php-gd']
state: installed
编写整个任务入口文件
vim /etc/ansible/lamp/roles/site.yml
---
- name: prepare build
remote_user: root
hosts: web_servers
# 要执行的 roles,确保 roles 目录下有同名的文件夹
roles:
- prepare
# 给任务打标签,方便单独测试
tags: prepare
- name: LAMP build
remote_user: root
hosts: web_servers
roles:
- mysql
tags: mysql
- name: LAMP build
remote_user: root
hosts: web_servers
roles:
- php
tags: php
- name: LAMP build
remote_user: root
hosts: web_servers
roles:
- httpd
tags: httpd
# 根据 tags 标签测试服务
ansible-playbook -C /etc/ansible/lamp/roles/site.yml -t httpd
# 开始部署
ansible-playbook -i /etc/ansible/hosts /etc/ansible/lamp/roles/site.yml