ansible 第三篇playbook之条件判断、循环和roles分层管理
1. ansible playbook之判断、循环语法:
在ansible playbook里面可以使用when语法来实现判断,通过with_items来实现循环,具体的示例如下:
---
vim httpd_v4.yaml
- hosts: websrvs
remote_user: '{{uservar}}'
vars: #定义变量,变量的值为列表
software:
- python-setuptools
- httpd
- mariadb
tasks:
- name: run this command ans ignore the result
shell: hostname
ignore_errors: True #忽略错误,可以继续执行
register: result #将上面shell的结果赋值给result变量
- debug: msg='{{result.stdout}}'
- name: install mysql and httpd
yum: name={{ software }} state=installed #通过调用循环的变量内容来实现批量安装软件
become: yes
with_items: #循环调用software里面的变量
- '{{software}}'
tags: init
- name: guarantee httpd2 is running
service: name=httpd state=started
become: yes
- name: transfer httpd configfile to remote
template: src=./httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf #使用模板,传送jinja2文件,也可以用copy模块传送普通文件
notify:
- restart httpd
when: result.stdout == 'rainbondnode01' #通过判断主机名是'rainbondnode01才执行拷贝模板文件
handlers: #触发器
- name: restart httpd
service: name=httpd state=restarted
become: yes
在此示例中用到了几个技术点:
- when是条件判断的语法;
- with_items是循环列表;
- register表示将tasks执行的结果赋予变量;
- become是sudo的意思;
- 执行此playbook可以使用ansible-playbook -e uservar=gytest --check httpd_v4.yaml,-e 表示执行命令的时候传递变量;
2. ansible playbook之role分层结构管理:
1. 什么场景下会用到roles?
假如我们现在有3个被管理主机,第一个要配置成httpd,第二个要配置成php服务器,第三个要配置成MySQL服务器。我们如何来定义playbook?
第一个play用到第一个主机上,用来构建httpd,第二个play用到第二个主机上,用来构建php,第三个play用到第三个主机上,用来构建MySQL。这些个play定义在playbook中比较麻烦,将来也不利于模块化调用,不利于多次调。比如说后来又加进来一个主机,这个第4个主机既是httpd服务器,又是php服务器,我们只能写第4个play,上面写上安装httpd和php。这样playbook中的代码就重复了。
为了避免代码重复,roles能够实现代码重复被调用。定义一个角色叫websrvs,第二个角色叫phpappsrvs,第三个角色叫dbsrvs。那么调用时如下来调用:
hosts: host1
role:
- websrvs
hosts: host2
role:
- phpappsrvs
hosts: host3
role:
- dbsrvs
hosts: host4
role:
- websrvs
- phpappsrvs
这样代码就可以重复利用了,每个角色可以被独立重复调用。下面举例说明使用方式。
2. 使用roles来安装lamp+wordpress论坛:
roles需要有一定的目录结构,我实验的lamp的目录结构如下:
[root@rainbondmanager gytest]# tree
.
├── group_vars
│ └── websrvs
├── hosts
├── roles
│ ├── mysql
│ │ ├── files
│ │ │ └── mysql_init.sh
│ │ ├── handlers
│ │ │ └── main.yaml
│ │ ├── tasks
│ │ │ ├── configure.yml
│ │ │ └── main.yaml
│ │ ├── templates
│ │ │ └── my.cnf
│ │ └── vars
│ │ └── main.yaml
│ ├── php
│ │ ├── files
│ │ ├── handlers
│ │ ├── meta
│ │ ├── tasks
│ │ │ └── main.yaml
│ │ ├── templates
│ │ └── vars
│ │ └── main.yaml
│ └── webserver
│ ├── files
│ │ └── wordpress.tar.gz
│ ├── handlers
│ │ └── main.yaml
│ ├── meta
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ └── templates
│ └── httpd.conf.j2
└── site.yaml
第一级至少要有一个site.yml文件,是执行playbook的入口文件;至少要有一个roles目录。roles目录下面是分类创建的目录,比如我需要安装httpd php mysql三个软件,那么就分了3个目录;每一个目录下面的子目录也是固定的,一般大致可以分为files、handlers、tasks、templates、vars、 meta. files目录放的文件一般是通过copy模块调用的本地路径文件,handlers是配置触发器的yaml文件,tasks就是任务文件了,templates是模板文件,一般存放.j2格式的文件,vars是变量定义文件,meta是依赖定义的文件;
接下来我将所有的配置文件内容列出来,并做简单的解释:
[root@rainbondmanager gytest]# cat site.yaml
---
- hosts: websrvs
remote_user: root
roles:
- webserver
- hosts: 10.83.32.130
remote_user: root
roles:
- php
site是入口文件,表示执行的主机、远程执行用户,调用的roles对象。本配置表示websrvs主机组上面安装httpd应用;10.83.32.130这台主机安装php应用;
[root@rainbondmanager gytest]# cat hosts
[websrvs]
10.83.32.130
10.83.32.131
在主目录我还定义了一个hosts文件,使用ansible-playbook -i hosts的方式指定使用这个单独的hosts清单配置,在hosts文件里面也可以定义变量,比如
[websrvs]
10.83.32.130 http_port=80
10.83.32.131 http_port=8080
如果没有用私钥的方式,也可以在hosts文件里面指定ssh用户,ssh端口,ssh密码等
[websrvs]
10.83.32.130 ansible_ssh_user=gytest ansible_ssh_pass=123456
10.83.32.131 ansible_ssh_user=gytest ansible_ssh_pass=123456
主目录还有一个组变量的目录,里面有一个以组名称命名的文件,里面的变量值针对整个组生效,要应用到那个主机组,文件名就需要是哪个主机组
[root@rainbondmanager gytest]# cat group_vars/websrvs
http_port: 8080
[root@rainbondmanager gytest]#
下面我们来分析httpd服务器安装的roles内容
# 第一个是tasks文件内容,里面的copy文件路径直接写相对路径,就是表明file下面的内容,template模板文件也是同理,使用相对路径
[root@rainbondmanager gytest]# cat roles/webserver/tasks/main.yaml
---
- name: installed httpd
yum: name=httpd state=present
tags: install
- name: keep httpd is running
service: name=httpd state=started enabled=true
tags: install
- name: insert iptables rules
shell: iptables -I INPUT -p tcp --dport {{http_port}} -j ACCEPT
- name: transfer index html
copy: src=wordpress.tar.gz dest=/var/www/html/wordpress.tar.gz
tags: install
- name: unzip wordpress
unarchive: src=/var/www/html/wordpress.tar.gz dest=/var/www/html/ copy=no
ignore_errors: True
tags: install
- name: mv wordpress
shell: mv /var/www/html/wordpress/* /var/www/html/
- name: wait for httpd to start
wait_for: port=8080
tags: install
- name: transfer httpd configure file
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
tags: conf
notify:
- restart httpd
cat roles/webserver/handlers/main.yaml
- name: restart httpd
service: name=httpd state=restarted
# tasks任务里面调用的notify通知,默认就是handlers目录下面的文件内容;
cat roles/webserver/templates/httpd.conf.j2 |grep "{{"
Listen {{http_port}}
ServerAdmin {{ansible_fqdn}}
# 模板文件里面调用了facts变量和自定义变量
cat roles/webserver/meta/main.yaml
dependencies:
- {role: mysql, echo_wars: hello_mysql}
# meta目录下面定义了依赖关系,也就是安装httpd的时候,先要确定mysql运行
ls roles/webserver/files/wordpress.tar.gz
roles/webserver/files/wordpress.tar.gz
# file目录是wordpress的源码包,通过copy模块拷贝到远程主机,并通过解压模块解压
然后我们在看看mysql数据库服务器安装的roles文件内容:
[root@rainbondmanager gytest]# cat roles/mysql/tasks/main.yaml
---
- name: install mariadb databases
yum: name={{software}} state=present
with_items:
- '{{software}}'
tags: install
- name: keep mariadb is running
service: name=mariadb state=started enabled=true
tags: install
- name: insert iptables rules
shell: iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
- name: echo_vars
shell: echo '{{echo_vars}}'
register: result
tags: install
- name: excute mysql init scrpts
script: /data/playbooks/gytest/roles/mysql/files/mysql_init.sh
- include: configure.yml
# tasks定义了安装mariadb服务器,启动服务,设置防火墙,执行数据库初始脚本等;
[root@rainbondmanager gytest]# cat roles/mysql/tasks/configure.yml
---
- name: transfer mysql configure file
template: src=my.cnf dest=/etc/my.cnf
notify:
- restart mysql
tags: configure
[root@rainbondmanager gytest]#
# main.yml包含了这个configure.yml,拷贝mysql配置文件到目标机器
[root@rainbondmanager gytest]# cat roles/mysql/handlers/main.yaml
---
- name: restart mysql
service: name=mysql state=restarted
[root@rainbondmanager gytest]#
# 触发器的配置,配置文件更改之后重启mysql
[root@rainbondmanager gytest]# cat roles/mysql/vars/main.yaml
---
software:
- mariadb
- mariadb-server
echo_vars:
- hello_mysql
mysql_port:
- '3306'
[root@rainbondmanager gytest]#
# 变量文件定义,定义了安装mysql的软件包和其他变量
[root@rainbondmanager gytest]# cat roles/mysql/files/mysql_init.sh
#!/bin/bash
#
mysql -uroot -pwordpress2018 -e "update mysql.user set password=password('wordpress2019') where user='root' and host='localhost';"
mysql -uroot -pwordpress2018 -e "grant all privileges ON *.* TO root@'%';"
mysql -uroot -pwordpress2019 -e "flush privileges;"
mysql -uroot -pwordpress2019-e "create database wordpress"
[root@rainbondmanager gytest]#
# mysql初始化脚本,更改root密码,创建wordpress数据库,并给root账户赋权;
[root@rainbondmanager gytest]# cat roles/mysql/templates/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
# mysql的配置文件内容
最后我们一起再来看看php的安装
cat roles/php/tasks/main.yaml
---
- name: installed php-fpm
yum: name={{ software }} state=present
tags: install
# 定义安装php的任务
[root@rainbondmanager gytest]# cat roles/php/vars/main.yaml
---
software:
- php
- php-mysql
- php-gd
- php-imap
- php-ldap
- php-odbc
- php-pear
- php-xml
- php-xmlrpc
# 定义安装php的软件包
今天的博文就写到这里了,关于ansible系列的专题就写到这里,更多关于ansible playbook的例子可以参考github地址https://github.com/ansible/ansible-examples