kylin-ansible自动化
ansible自动化
一、ansible主机架构
1、连接插件 connection plugins 用于连接主机 用来连接被管理端
2、核心摸块 core modues 连接主机实现操作,它依赖于具体的模块来做具体的事情
3、自定义模块 custom modules 根据自己的需求编写具体的模块
4、插件 plugins 完成模块功能的补充
5、剧本 playbook ansible的配置文件,将多个任务定义在剧本中,由ansible自动执行
6、主机清单 invenlory 定义ansible需要操作主机的范围
最重要的一点是 ansible是模块化的 它所有的操作都依赖于模块
二、安装配置ansible
第一步:安装
Centos系统直接yum安装或pip安装
kylin系统使用如下步骤安装:
1.yum -y install ansible
2.编译安装Python3.8
1)下载Python3.8安装包
wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
2)解压缩
xz -d Python-3.8.2.tar.xz
tar xvf Python-3.8.2.tar
3)配置
cd /root/Python-3.8.2
./configure --prefix=/usr/local/python38 --enable-shared
4)编译安装
make && make install
5)配置python3.8的lib到ldconfig
vi /etc/ld.so.conf.d/python3.conf,添加如下内容
/usr/local/python38/lib
然后执行:ldconfig
6)创建Python软链接
ln -s /usr/local/python38/bin/pip3 /usr/local/bin/pip3
ln -s /usr/local/python38/bin/python3 /usr/local/bin/python3
7)设置PATH
echo 'export PATH=/usr/local/bin:$PATH' >> /etc/profile
8) 重新加载环境变量
source /etc/profile
到此,Python3.8环境安装完毕~
python3 -V #查看python版本
3.pip3 install ansible
第二步:配置
[root@ansible ~]# cat /etc/ansible/ansible.cfg
#[defaults]
#跳过检查主机指纹
#不显示弃用警告
#指定Python解释器的路径
[defaults]
host_key_checking = False
deprecation_warnings = False
interpreter_python = /usr/bin/python3
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
三、Ansible主机清单---Inventory
- /etc/ansible/hosts 是ansible默认主机资产清单文件,用于定义被管理主机的认证信息, 例如ssh登录用户名、密码以及key相关信息。Inventory文件中填写需要被管理的主机与主机组信息。
- 还可以自定义Inventory主机清单的位置,使用-i指定文件位置即可。
1.基于用户密码方式连接
使用用户名和密码定义主机清单
- 语法格式
IP ansible_ssh_user= ansible_ssh_port= ansible_ssh_pass=''
- 示例
[root@ansible ~]# vim /etc/ansible/hosts
10.0.0.31 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='dezyan123.com'
#测试
[root@ansible ~]# ansible 10.0.0.31 -m ping
10.0.0.31 | SUCCESS => {
"changed": false,
"ping": "pong"
}
使用别名定义主机清单
- 语法格式
别名 ansible_ssh_host= ansible_ssh_user= ansible_ssh_port= ansible_ssh_pass=''
- 示例
nfs ansible_ssh_host=10.0.0.31 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='dezyan123.com'
#测试
[root@ansible ~]# ansible nfs -m ping
10.0.0.31 | SUCCESS => {
"changed": false,
"ping": "pong"
}
2.基于密钥方式连接
生成密钥对
1.生成秘钥对
[root@ansible ~]# ssh-keygen
2.发送到客户端
[root@ansible ~]# ssh-copy-id 10.0.0.31
[root@ansible ~]# ssh-copy-id 10.0.0.41
3.测试ssh免密
[root@ansible ~]# ssh 10.0.0.41
[root@ansible ~]# ssh 10.0.0.31
使用别名定义主机清单
[root@ansible ~]# vim /etc/ansible/hosts
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
#测试
[root@ansible ~]# ansible nfs -m ping
nfs | SUCCESS => {
"changed": false,
"ping": "pong"
}
定义主机清单组
[root@ansible ~]# vim /etc/ansible/hosts
#直接写IP也可以,无需配置别名
[test]
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
#测试
[root@ansible ~]# ansible test -m ping
backup | SUCCESS => {
"changed": false,
"ping": "pong"
}
nfs | SUCCESS => {
"changed": false,
"ping": "pong"
}
定义子组
[root@ansible ~]# vim /etc/ansible/hosts
[test01]
nfs ansible_ssh_host=10.0.0.31
[test02]
backup ansible_ssh_host=10.0.0.41
[test:children]
test01
test02
#测试
[root@ansible ~]# ansible test -m ping
backup | SUCCESS => {
"changed": false,
"ping": "pong"
}
nfs | SUCCESS => {
"changed": false,
"ping": "pong"
}
四、Ansible ad-hoc
- Ansible提供的一种快速执行单个命令或一系列命令的方式
- ansible执行命令都是以模块的方式执行
- 基本语法格式
ansible 主机名称 -m 指定模块的名称 -a 具体执行的命令动作
ansible内置命令帮助文档
ansible-doc 模块名
底行输入:/EXAMPLE查看示例
模块1:yum(安装软件包)
- 动作
- name=软件包名
- state=执行的动作
- present 安装
- absent 卸载
- 示例
1.安装unzip命令
[root@ansible ~]# ansible backup -m yum -a 'name=unzip state=present'
2.卸载unzip命令
[root@ansible ~]# ansible backup -m yum -a 'name=unzip state=absent'
3.安装指定目录下存放的rpm包
[root@ansible ~]# ansible backup -m yum -a 'name=rpm包具体路径 state=present'
4.安装rsync服务
[root@ansible ~]# ansible backup -m yum -a 'name=rsync state=present'
模块2:copy(拷贝文件更改文件内容)
- 动作
- src=源文件(ansible服务器上的位置)
- dest=目标地址(目标主机的位置)
- owner=属主
- group=属组
- mode=权限数字
- backup=yes (给当前的文件做一个以时间命名的备份文件,存放在目标主机上)
- content=字符串(将字符串写入到目标文件中)
- 示例
1.将本地/etc/hosts文件拷贝到41服务器的/opt目录下
[root@ansible ~]# ansible backup -m copy -a 'src=/etc/hosts dest=/opt/'
2.编写rsync匿名用户的密码文件
[root@ansible ~]# ansible backup -m copy -a 'content=backup:123 dest=/etc/passwd.txt mode=600'
模块3:user(创建用户)
- 动作
- name=用户名
- uid=用户uid
- group=组名称
- shell=指定解释器
- create_home=false(默认不写此参数为创建家目录)
- state=状态
- present 创建用户
- absent 删除用户
- remove=yes 删除用户并且删除其家目录(userdel -r)
- 示例
1.创建普通用户dzy,指定uid为1016
[root@ansible ~]# ansible backup -m user -a 'name=dzy uid=1016 state=present'
[root@backup ~]# id dzy
uid=1016(dzy) gid=1016(dzy) groups=1016(dzy)
2.创建虚拟用户ding,指定uid为777,组名为ding
[root@ansible ~]# ansible backup -m group -a 'name=ding gid=777 state=present'
[root@ansible ~]# ansible backup -m user -a 'name=ding uid=777 group=ding shell=/sbin/nologin create_home=false state=present'
3.删除普通用户dzy,并删除其家目录
[root@ansible ~]# ansible backup -m user -a 'name=dzy remove=yes state=absent'
模块4:group(创建组)
- 动作
- name=组名名称
- gid=组id
- state=状态
- present 创建
- absent 删除
- 示例
创建ding用户组,指定gid为777
[root@ansible ~]# ansible backup -m group -a 'name=ding gid=777 state=present'
模块5:file(创建删除文件目录,修改权限)
- 动作
- path=文件路径
- state=状态
- touch(文件)
- directoty(目录)
- absent(删除文件或目录)
- owner=属主
- group=属组
- mode=权限数字(0600)
- recurse=yes(递归修改)
- 示例
1.创建普通文件test.txt,并将其属主属组改为dezyan,权限为0600
[root@ansible ~]# ansible backup -m file -a 'path=/root/test.txt state=touch owner=dezyan group=dezyan mode=0600'
2.创建一个名为dir的目录
[root@ansible ~]# ansible backup -m file -a 'path=/root/dir state=directory'
3.递归修改dir目录下所有文件的属主属组为dezyan
[root@ansible ~]# ansible backup -m file -a 'path=/root/dir owner=dezyan group=dezyan recurse=yes'
4.删除dir目录及目录下的所有文件
[root@ansible ~]# ansible backup -m file -a 'path=/root/dir state=absent'
模块6:systemd(修改服务状态)
- 动作
- name=服务名
- state=状态
- started(启动)
- stopped(停止)
- restarted(重启)
- reloaded(重载)
- enabled=yes(开机自启)
- 示例
1.启动rsync服务并设置开机自启
[root@ansible ~]# ansible backup -m systemd -a 'name=rsyncd state=started enabled=yes'
模块7:yum_repository(添加系统yum源)
-
动作
- name=文件名
- description=描述(备注)
- baseurl=存储库的基本URL
- enabled=yes(启用该yum源)
- gpgcheck=no(不启用GPG签名检查)
- gpgkey=存储库GPG密钥的URL或文件路径
-
示例
1.配置一个nginx的yum源
ansible backup -m yum_repository -a 'name="nginx stable repo" description='nginx YUM repository' baseurl=http://nginx.org/packages/centos/7/$basearch/ gpgcheck=0 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true'
模块8:mount(磁盘操作)
- 动作
- src=挂载目录
- path=挂载点
- fstype=分区类型
- opts=挂载选项
- state=状态
- present(开机挂载,仅将挂载配置写入/etc/fstab)
- mounted(挂载设备,并将配置写入/etc/fstab)
- umounted(卸载设备,不会清除/etc/fstab写入的配置)
- absent(卸载设备,会清理/etc/fstab写入的配置)
- 示例
模块9:cron(定时任务)
- 动作
- minute=* hour=* day=* month=* weekday=*
- job=任务
- 示例
#设置一条定时任务,每分钟执行一次test.sh脚本
[root@ansible ~]# ansible web_group -m cron -a "minute=* hour=* day=* month=* weekday=* job='/bin/sh /server/scripts/test.sh'"
模块10:firewalld(防火墙)
- 动作
- service=指定开放或关闭的服务名称
- port=指定开放或关闭的端口
- permanent=yes(是否添加永久生效)
- state=状态
- enabled
- disabled
- masquerade=yes(开启地址伪装)
- source=192.169.0.0/24(指定来源IP)
- immediate
模块11:selinux
- 动作
- state=状态
- disabled(关闭)
- permissive(开启)
- state=状态
- 示例
#关闭selinux
[root@ansible ~]# ansible nfs -m selinux -a 'state=disabled'
模块12:unarchive(解压)
- 支持tar、zip、bzip2、gzip多种解压模式
- 动作
- src=压缩包(ansible服务器上的位置或指定的URL链接 )
- dest=目标解压地址
- creates=目录(如果目标解压地址不存在,会创建该目录)
- owner= group= mode= (设置解压后的文件权限)
模块13:get_url(主机信息)
- 常用动作
1.查看所有详细信息
[root@ansible ~]# ansible web01 -m setup
2.获取IP地址
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_default_ipv4'
3.获取主机名
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_fqdn'
4.获取内存信息
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_memory_mb'
5.获取磁盘信息
[root@ansible ~]# ansible web01 -m setup -a 'filter=ansible_devices'
- 其他信息参数
ansible_all_ipv4_addresses:仅显示ipv4的信息。
ansible_devices:仅显示磁盘设备信息。
ansible_distribution:显示是什么系统,例:centos,suse等。
ansible_distribution_major_version:显示是系统主版本。
ansible_distribution_version:仅显示系统版本。
ansible_machine:显示系统类型,例:32位,还是64位。
ansible_eth0:仅显示eth0的信息。
ansible_hostname:仅显示主机名。
ansible_kernel:仅显示内核版本。
ansible_lvm:显示lvm相关信息。
ansible_memtotal_mb:显示系统总内存。
ansible_memfree_mb:显示可用系统内存。
ansible_memory_mb:详细显示内存情况。
ansible_swaptotal_mb:显示总的swap内存。
ansible_swapfree_mb:显示swap内存的可用内存。
ansible_mounts:显示系统磁盘挂载情况。
ansible_processor:显示cpu个数(具体显示每个cpu的型号)。
ansible_processor_vcpus:显示cpu个数(只显示总的个数)。
模块14:mysql_db(数据库操作)
-
动作:
- login_user=用户名
- login_host=登录主机
- login_port=数据端口
- name=要操作的数据库名(all代表所有)
- target=指定导出或导入的数据库文件
- state=状态
- present 创建数据库
- absent 删除数据库
- dump 导出数据库
- import 导入数据库
-
示例:
1.将all.sql导入到新数据库中
[root@ansible ~]# ansible db01 -m mysql_db -a 'login_user: root login_host: localhost login_port: 3306 name: all target: /root/db-all.sql state: import '
五、Ansible Playbook
①剧本文件
在 Ansible 中”剧本文件”是以yml结尾的文件,使用的都是 yaml 语法
②语法格式
- 缩进:YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用TAB
- 冒号:以冒号结尾的除外,其他所有冒号后面所有必须有空格
- 短横线:表示列表项,使用一个短横杠加一个空格,多个项使用同样的缩进级别作为同一列表
- 层级关系
- 第一层级:hosts属于最高层级
- 第二层级:tasks、vars、handers同级,次于hosts
- 第三层级:模块层级
- 第四层级:模块动作
- hosts: hostname #yaml语法中最顶层的结构,用于指定执行主机
vars: #次于hosts层级,属于角色层,定义下方要使用的变量
pk: wget #定义变量
tasks: #次于hosts层级,属于执行层,定义要执行的动作
- name: Install wget #定义动作名称
yum: #定义要执行的动作(模块)
name: wget #使用模块内置动作实现自动化
state: present
-
语法检测:
注意:语法检测只能检查缩进、冒号、短横线、空格的语法错误,无法检查单词(模块名)是否正确
[root@ansible ansible]# ansible-playbook --syntax-check yml文件
playbook: wget.yml #执行结果为此,无警告、报错即为语法正确
- 执行yml文件
[root@ansible ansible]# ansible-playbook yml文件
③主机清单
- 所有示例均以此列表清单的别名为准
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
[webs]
web01 ansible_ssh_host=10.0.0.7
wen02 ansible_ssh_host=10.0.0.8
[mariadb]
db01 ansible_ssh_host=10.0.0.51
④第一层级
- hosts: hostname #指定主机名、组名
⑤第二层级
1.Playbook-task执行层级
示例1:Playbook安装wget包
第一步:编写yml文件
[root@ansible playbook]# vim wget.yml
- hosts: backup #定义执行操作的主机(在列表清单中定义)
tasks: #具体执行的任务
- name: Install wget #注释
yum: #模块名
name: wget #模块内置动作、状态
state: present
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check wget.yml
playbook: wget.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook wget.yml
示例2:使用Playbook部署rsync服务
- 需提前准备好rsyncd.conf配置文件
第一步:编写yml文件
[root@ansible playbook]# vim backup.yml
- hosts: backup
tasks:
- name: install rsync server
yum:
name: rsync
state: present
- name: Configure rsync server
copy:
src: /etc/ansible/serverconf/rsyncd.conf
dest: /etc/rsyncd.conf
- name: create group www
group:
name: www
gid: 666
- name: create user www
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
- name: create passwd file
copy:
content: rsync_backup:123456
dest: /etc/rsync.passwd
mode: 0600
- name: create backup directory
file:
path: /backup
state: directory
owner: www
group: www
- name: systemctl start rsync
systemd:
name: rsyncd
state: started
enabled: yes
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check wget.yml
playbook: wget.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook wget.yml
示例3:使用Playbook部署NFS服务
第一步:编写yml文件
[root@ansible playbook]# vim nfs.yml
- hosts: nfs
tasks:
- name: download nfs server
yum:
name: nfs-utils
state: present
- name: configure nfs
copy:
src: /etc/ansible/serverconf/exports
dest: /etc/exports
- name: create group www
group:
name: www
gid: 666
- name: create user www
user:
name: www
uid: 666
group: www
state: present
shell: /sbin/nologin
create_home: false
- name: create nfs file
file:
path: /data/wordpress
owner: www
group: www
state: directory
- name: systemctl start nfs
systemd:
name: nfs
state: started
enabled: yes
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check nfs.yml
playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook nfs.yml
示例4:使用Playbook部署nginx服务
第一步:编写yml文件
[root@ansible playbook]# vim nginx.yml
- hosts: web01
tasks:
- name: create nginx.repo
yum_repository:
name: nignx
description: Nginx Yum repo
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
- name: install nginx server
yum:
name: nginx
state: present
- name: create group www
group:
name: www
gid: 666
- name: create user www
user:
name: www
uid: 666
group: www
state: present
shell: /sbin/nologin
create_home: false
- name: configure nginx
copy:
src: /etc/ansible/serverconf/nginx.conf
dest: /etc/nginx/nginx.conf
- name: systemctl start nginx
systemd:
name: nginx
state: started
enabled: yes
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check nginx.yml
playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook nginx.yml
示例5:使用Playbook部署php服务
第一步:编写yml文件
[root@ansible playbook]# vim php.yml
- hosts: web01
tasks:
- name: Install PHP Server
yum:
name: php,php-bcmath,php-cli,php-common,php-devel,php-embedded,php-fpm,php-gd,php-intl,php-mbstring,php-mysqlnd,php-opcache,php-pdo,php-process,php-xml,php-json
state: present
- name: Configure PHP Server
copy:
src: /etc/ansible/serverconf/www.conf
dest: /etc/php-fpm.d/
- name: Start PHP Server
systemd:
name: php-fpm
state: started
enabled: yes
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check php.yml
playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook php.yml
示例6:使用Playbook部署mariadb
导出原数据库所有库
mysqldump -udzy -pdzy123.com -A > dump_file.sql
第一步:编写yml文件
[root@ansible playbook]# vim mysql.yml
- hosts: db01
tasks:
- name: Install mariadb Server
yum:
name: mariadb-server,python3-mysqlclient
state: present
- name: Start mariadb Server
systemd:
name: mariadb
state: started
enabled: yes
- name: copy all.sql to 51
copy:
src: /etc/ansible/serverconf/db-all.sql
dest: /root/
- name: Configure Mmriadb Server
mysql_db:
login_user: root
login_host: localhost
login_port: 3306
name: all
target: /root/db-all.sql
state: import
- name: Restart mariadb
systemd:
name: mariadb
state: restarted
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check mysql.yml
playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook mysql.yml
示例7:使用Playbook部署wordpress
第一步:编写yml文件
[root@ansible playbook]# vim wp.yml
- hosts: web01
tasks:
- name: Delete Default default.conf
file:
path: /etc/nginx/conf.d/default.conf
state: absent
- name: Copy wp.conf
copy:
src: /etc/ansible/serverconf/wp.conf
dest: /etc/nginx/conf.d/
- name: unarchive code.tar.gz
unarchive:
src: /etc/ansible/serverconf/code.tar.gz
dest: /
creates: /code/wordpress
- name: Restart Nginx Server
systemd:
name: nginx
state: restarted
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check wp.yml
playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook wp.yml
示例8:客户端挂载nfs共享目录
第一步:编写yml文件
[root@ansible playbook]# vim web01-mount.yml
- hosts: web01
tasks:
- name: install nfs server
yum:
name: nfs-utils
state: present
- name: create /code/wordpress/wp-content/uploads/
file:
path: /code/wordpress/wp-content/uploads/
state: directory
- name: mount nfs /data/wordpress
mount:
src: 172.16.1.31:/data/wordpress
path: /code/wordpress/wp-content/uploads/
state: mounted
fstype: nfs
- name: reload photo to server
unarchive:
src: /etc/ansible/serverconf/imag.tar.gz
dest: /code/wordpress/wp-content/uploads/
creates: /code/wordpress/wp-content/uploads/
第二步:检查语法
[root@ansible playbook]# ansible-playbook --syntax-check web01-mount.yml
playbook: nfs.yml
第三步:执行剧本
[root@ansible playbook]# ansible-playbook web01-mount.yml
2.Playbook-vars角色层级
定义方式1:Playbook中直接定义
示例1:定义单一变量(变量内只有一个值)
#动作内不包含路径
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars:
pkg: wget
tasks:
- name: Install Package
yum:
name: "{{ pkg }}" #注意格式:"{{ 变量名 }}"
state: present
#动作内包含路径
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars:
pkg: test
tasks:
- name: create file
file:
path: /root/{{ pkg }} #注意格式:{{ 变量名 }}
state: touch
- 由此可见,在动作不包含路径时使用变量需要加"",包含路径时无需加""
示例2:定义多个变量(变量中包含多个值)
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars:
pkg:
- wget
- lrzsz
- unzip
tasks:
- name: create file
yum:
name: "{{ pkg }}"
state: present
示例3:动作中使用多个变量
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars:
pkg: test
msg: ding
tasks:
- name: create file
file:
path: /root/{{ pkg }}_{{ msg }}
state: touch
#nfs中查看
[root@nfs ~]# ll
total 0
-rw-r--r-- 1 root root 0 Jan 1 19:41 test_ding
定义方式2:vars_files文件中定义
- 创建并编写存放变量的文件
[root@ansible playbook]# vim vars.yml
pkg: test
msg: dingzhiyan
- 在Playbook中调用
示例1:调用单一变量(创建单一文件)
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars_files: vars.yml #使用vars_files指定变量文件
tasks:
- name: create file
file:
path: /root/{{ pkg }}
state: touch
#执行测试查看
[root@nfs ~]#
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan 1 19:47 test
示例2:多用多个变量(批量创建多个文件)
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars_files: vars.yml
tasks:
- name: create file
file:
path: /root/{{ item }}
state: touch
loop:
- "{{ pkg }}"
- "{{ msg }}"
#执行测试查看
[root@nfs ~]# ll
total 0
-rw-r--r-- 1 root root 0 Jan 1 20:01 dingzhiyan
-rw-r--r-- 1 root root 0 Jan 1 20:01 test
示例3:多个变量拼接使用
[root@ansible playbook]# vim test.yml
- hosts: nfs
vars_files: vars.yml #使用vars_files指定变量文件
tasks:
- name: create file
file:
path: /root/{{ pkg }}_{{ msg }}
state: touch
#执行测试查看
[root@nfs ~]#
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan 1 19:47 test_dingzhiyan
定义方式3:直接使用内置变量
- 内置变量通过setup模块来查看。
[root@ansible playbook]# ansible nfs -m setup
- 查询、使用内置变量的方法
1.通过命令查看ansible提供的所有内置变量
#找到关于ipv4的段落
"ansible_default_ipv4": {
"address": "10.0.0.31",
"alias": "ens33",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "ens33",
"macaddress": "00:0c:29:04:17:cf",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"prefix": "24",
"type": "ether"
2.观察层级关系,此处与yaml语法中的层级关系相同
ansible_default_ipv4属于其顶层,其余属于他的附属层
3.调用其中信息的方法为:
顶层名.附属层名
示例:调用IP信息
ansible_default_ipv4.address
示例1:使用内置变量创建以IP+主机名命名的文件
[root@ansible playbook]# vim test.yml
- hosts: nfs
tasks:
- name: create file
file:
path: /root/{{ ansible_default_ipv4.address }}_{{ ansible_hostname }}
state: touch
#测试查看
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan 1 20:07 10.0.0.31_nfs
定义方式4:在主机清单中定义(不建议使用)
[root@ansible playbook]# vim /etc/ansible/hosts
[webs]
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8
[webs:vars] #为上方组定义变量
pk1=wget
pk2=lrzsz
- 调用:直接在Playbook文件中使用即可
定义方式5:ansible官方推荐使用方式
示例1:定义主机变量(针对单一主机的变量)
1.在当前目录中创建host_vars目录
[root@ansible ansible]# mkdir host_vars
2.创建、编写定义变量的文件
#注意!!
#文件名称必须要与列表清单中的主机名相同
#文件要放在host_vars目录中
[root@ansible ansible]# vim host_vars/nfs
name: ding
age: 23
sex: man
3.调用变量测试
[root@ansible ansible]# vim test.yml
- hosts: nfs
tasks:
- name: create file
file:
path: /root/{{ name }}_{{ age }}_{{ sex }}
state: touch
[root@nfs ~]# ll
-rw-r--r-- 1 root root 0 Jan 1 20:32 ding_23_man
示例2:定义组变量(多个主机)
- 文件名称为all时,对所有主机都生效
1.在当前目录中创建group_vars目录
[root@ansible ansible]# mkdir group_vars
2.创建、编写定义变量的文件
#注意!!
#文件名称必须要与列表清单中的组名相同
#文件要放在group_vars目录中
[root@ansible ansible]# vim group_vars/webs
name: ding
age: 23
sex: man
3.调用方法与示例1相同,只不过是对多台主机生效了
定义方式6:变量注册(重要)
- 使用Ansible执行命令,有一些是无法返回结果的
#执行后无法查看ls -l 所列出的信息
- hosts: web01
tasks:
- name: list /root
command: ls -l
- 通过变量注册返回详细信息
#使用register模块及debug模块中的msg动作实现
#以ls -l 为例
- hosts: web01
tasks:
- name: list root file
command: ls -l
register: ng_re #自定义变量名
- name: print ng_re env
debug:
msg: "{{ ng_re }}" #使用register定义的变量名
示例1:检查nginx的语法是否正确并返回结果
[root@ansible playbook]# vim test.yml
- hosts: web01
tasks:
- name: check nginx config
command: nginx -t
register: ng_check
- name: print check result
debug:
msg: "{{ ng_check}}"
[root@ansible playbook]# ansible-playbook test.yml
#TASK [print check result]的结果中会打印信息
ok: [web01] => {
"msg": {
…………
"rc": 0,
…………
"stderr_lines": [
"nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
"nginx: configuration file /etc/nginx/nginx.conf test is successful"
],
}
}
示例2:获取返回结果中子集的值
-
获取方法与系统变量的使用方法原理相同
-
使用方法:
msg: "{{ 变量名.子集名}}"
或 msg: "{{ 变量名['子集名'] }}" #官方推荐写法
- 示例:
- hosts: web01
tasks:
- name: check nginx config
command: nginx -t
register: ng_check
- name: print check result
debug:
msg: "{{ ng_check.stderr_lines}"
#这样,获取的就是如下信息
TASK [print check result] ******************************************************
ok: [web01] => {
"msg": [
"nginx: the configuration file /etc/nginx/nginx.conf syntax is ok",
"nginx: configuration file /etc/nginx/nginx.conf test is successful"
]
}
3.Playbook-handlers任务触发层级
-
监控文件(或其他)是否发生变化 如果一致不触发handlers,如果发生变化则触发handlers进行指定动作
-
语法格式
tasks:
- name: Configure Nginx Server
模块:
动作:
notify: name #此处的name必须与handlers的name一致
handlers:
- name: Restart Nginx Server #必须和notify后的名称一致
模块:
动作:
……
- 示例:
#检测nginx配置文件变化,如果发生变化,切语法正确,启动nginx
- hosts: web02
tasks:
- name: Nginx Repo
yum_repository:
name: nginx
description: Nginx YUM repo
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
- name: Install Nginx Server
yum:
name: nginx
state: present
- name: Configure Nginx Server
copy:
src: nginx.conf
dest: /etc/nginx/
notify: Restart Nginx Server
- name: check nginx conf
shell: nginx -t
ignore_errors: yes
register: ng_re
- name: create group www
group:
name: www
gid: 666
- name: Create www user
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
- name: Start Nginx Server
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Restart Nginx Server # 必须和notify后的名称一致
systemd:
name: nginx
state: restarted
when: ng_re.stderr_lines is search "ok"
⑥第三层级
1.when判断模块
判断机制1:精确判断-单一条件
- 全部满足,才会执行
#以安装wget命令为例
- hosts: all
tasks:
- name: Install wget
yum:
name: wget
state: absent
when: ansible_hostname == "web01" #系统内置变量名 == "字符串"
#该Playbook的含义是:当目标主机名为web01时才执行此模块及其动作
#若替换为:
when: ansible_default_ipv4.address == "10.0.0.8"
#代表只有目标IP为10.0.0.8时才会执行
判断机制2:精确判断-多个条件同时满足
- 全部满足,才会执行
#以安装wget命令为例
- hosts: lnmp
tasks:
- name: Install wget
yum:
name: wget
state: present
when:
- ansible_default_ipv4.address == "10.0.0.7"
- ansible_hostname == "web01"
#此时,目标主机的主机名必须为web01且IP地址为10.0.0.7时才会执行
判断机制3:精确判断-多个条件满足其一
- 满足其一,就会执行
#以安装wget命令为例
- hosts: lnmp
tasks:
- name: Install wget
yum:
name: wget
state: present
when: ( ansible_default_ipv4.address == "10.0.0.7" ) or ( ansible_hostname == "web01" )
#此时,目标主机的主机名必须为web01 或者 IP地址为10.0.0.7时才会执行
判断机制4:模糊判断-search
-
不能使用正则表达式
-
变量中只要含有定义的字符串,就会执行
-
注:
search过滤器在Ansible 2.9中被弃用,并在Ansible 2.10中被移除
#以安装wget命令为例
- hosts: lnmp
tasks:
- name: Install wget
yum:
name: wget
state: present
when: ansible_hostname is search "web"
#此时,目标主机的主机名中包含web就会执行,例如web01 ,02web,01web02都会执行
判断机制5:模糊判断-match
- 可以使用正则表达式
- 变量中定义的字符串需满足正则,才会执行
[root@ansible dezyan]# cat w.yml
- hosts: lnmp
tasks:
- name: Install wget
yum:
name: wget
state: present
when: ansible_hostname is match "^web$"
#此时,只有目标主机为web时,才会执行
注意!!!
1.无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次。
2.Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。
3.Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。
4.如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的–force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。
5.不能使用handlers替代tasks
示例:
- 在部署nginx业务时,我们需要修改配置文件,并检查语法是否正确才可重新启动
- 在ansible的Playbook中,我们可以使用when判断nginx -t结果是否正确决定是否重新启动nginx
[root@ansible ansible]# cat nginx.yml
- hosts: web02
tasks:
- name: Nginx Repo
yum_repository:
name: nginx
description: Nginx YUM repo
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
- name: Install Nginx Server
yum:
name: nginx
state: present
- name: Configure Nginx Server
copy:
src: nginx.conf
dest: /etc/nginx/
- name: check nginx conf
shell: nginx -t
ignore_errors: yes
register: ng_re #变量注册,将nginx -t的结果返回给ng_re
- name: create group www
group:
name: www
gid: 666
- name: Create www user
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
- name: Start Nginx Server
systemd:
name: nginx
state: restarted
enabled: yes
when: ng_re.stderr_lines is search "ok" #结果包含ok时,执行动作
2.ignore_errors忽略错误模块
- 默认playbook会检测task执行的返回状态,如果遇到错误则会立即终止playbook的后续task执行,然而有些时候playbook即使执行错误了也要让其继续执行。
示例:检测nginx语法,如果错误,忽略并继续向下执行
…………
- name: check nginx conf
shell: nginx -t
ignore_errors: yes #添加此模块即可
register: ng_re
……………
3.item-loop-字典循环模块
- 循环通过动作:
{{ item }}以及他的子集{{ item.string }}进行定义 - 使用loop或者with_items模块来调用
示例1:启动多个服务
- hosts: web02
tasks:
- name: Restart Nginx PHP
systemd:
name: "{{ item }}"
state: started
loop:
- nginx
- php-fpm
示例2:创建多个文件(使用子集)
- hosts: web02
tasks:
- name: create file
file:
path: "{{ item.name }}"
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
state: touch
loop:
- { name: a.txt,owner: www,group: www,mode: '0600' }
- { name: b.txt,owner: root,group: root,mode: '0644' }
4.tags标签模块
- 在我们使用ansible执行Playbook时,有时候有需求只执行其中一个动作,这时我们便可以使用tags模块并结合ansible命令来实现
- 注意:可以给多个任务打相同的tag,在执行时就会执行多个动作
- 查看标签
[root@ansible ansible]# ansible-playbook nfs.yml --list-tags
- 执行标签
[root@ansible ansible]# ansible-playbook nfs.yml -t hehe
- 配置示例
- name: Create "{{ dir }}"
file:
path: "{{ dir }}"
state: directory
owner: www
group: www
tags: hehe
5.include使多个tasks组合模块
- 准备两个yml文件
[root@ansible ansible]# cat web.yml
- name: create a.txt
file:
path: /root/a.txt
state: touch
[root@ansible ansible]# cat mysql.yml
- name: create file
file:
path: /root/php.txt
state: touch
- 使用include整合
[root@ansible dezyan]# cat web.yml
- hosts: all
tasks:
- include_tasks: web.yml
when: ansible_hostname == "web02"
- include_tasks: mysql.yml
when: ansible_hostname == "backup"
6.template调用jinja2模版文件
yml调用方式
- name: Configure nfs Server
template:
src: exports.j2 #jinja2文件名,常以.j2结尾
dest: /etc/exports #目标路径及文件名
jinja2文件及其语法
- 逻辑判断(使用较少)
#循环表达式
{% for i in EXPR %}
{% endfor %}
#条件判断
{% if EXPR %}
{% elif EXPR %}
{% else %}
{% endif %}
#注释
{# COMMENT #}
- 变量引用
{{ 变量名 }} #在文件中哪里使用往哪里填
示例1:推送一个欢迎界面
- jinja2文件
{# 展示主机名,内存,IP地址 #}
Welcome to {{ ansible_hostname }}
This system total mem is : {{ ansible_memtotal_mb }} MB
This system ip address: {{ ansible_default_ipv4.address }}
- yml文件调用
- hosts: web01
tasks:
- name: copy motd
template:
src: motd.j2
dest: /etc/motd
示例2:使用for循环生成lb配置文件
- jinja2文件:nginx.conf.j2
upstream {{ server_name }} {
{% for n in range(7,9) %}
server 172.16.1.{{ n }}:{{ up_port }};
{% endfor %}
}
server {
listen 80;
server_name {{ server_name }};
location / {
proxy_pass http://{{ server_name }};
proxy_set_header Host $http_host;
}
}
- yml文件:cp.yml(在此定义jinja2中的变量)
- hosts: lnmp
vars:
- server_name: www.wp.com
- up_port: 80
tasks:
- name: copy motd
template:
src: nginx.conf
dest: /root/
- 执行查看结果
[root@web01 ~]# cat nginx.conf
upstream www.wp.com {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name www.wp.com;
location / {
root /code;
index index.html;
proxy_pass http://www.wp.com;
proxy_set_header Host $http_host;
}
}
示例3:使用if判断生成keepalived配置文件
- jinja2:keep.j2
global_defs {
router_id {{ ansible_fqdn }}
}
vrrp_instance VI_1 {
{% if ansible_fqdn == "web01" %}
state MASTER
priority 150
{% else %}
state BACKUP
priority 100
{% endif %}
interface eth0
virtual_router_id 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3
}
}
- yml文件:cp.yml
- hosts: lnmp
vars:
- server_name: www.wp.com
- up_port: 80
tasks:
- name: copy motd
template:
src: keep.j2
dest: /root/
示例4:rsync配置文件使用jinja2模版
#1.定义jinja2变量配置文件
[root@ansible ansible]# cat rsyncd.conf.j2
uid = {{ user }}
gid = {{ user }}
port = {{ rsync_port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[backup]
path = {{ rs_dir }}
#2.yml调用jinja2文件
[root@ansible ansible]# cat rs.yml
- hosts: backup
vars:
- user: www
- rsync_port: 873
- rs_dir: /backup
tasks:
- name: Install Rsync Server
yum:
name: rsync
state: present
- name: Configure Rsync Server
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
loop:
- { src: rsyncd.conf.j2, dest: /etc/rsyncd.conf,mode: '0644' }
- { src: rsync.passwd, dest: /etc/,mode: '0600' }
notify: Restart Rsync Server
- name: Create "{{ user }}" group
group:
name: "{{ user }}"
gid: 666
- name: Create "{{ user }}" user
user:
name: "{{ user }}"
uid: 666
group: "{{ user }}"
shell: /sbin/nologin
create_home: false
- name: Create "{{ rs_dir }}"
file:
path: "{{ rs_dir }}"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
- name: Start Rsync Server
systemd:
name: rsyncd
state: started
enabled: yes
handlers:
- name: Restart Rsync Server
systemd:
name: rsyncd
state: restarted
六、ansible roles 角色
- 我们编写Playbook时,文件太多,又乱,不美观,所以我们可以使用roles来优化一下
1.创建roles
[root@ansible roles]# ansible-galaxy init rsync
- Role rsync was created successfully
2.roles创建的目录结构及详解
- 目录结构
[root@ansible roles]# tree rsync/
rsync/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
- 目录详解
defaults #用于定义角色的默认变量,一般在vars目录中定义,可删除
files #用于存放文件,这些文件会在执行任务时被复制到远程主机上
handlers #当我们在tasks中定义了handlers,要在这里写要执行的动作
meta #用不到,删
tasks #编写任务,动作,模块
templates #用于存放jinja2文件
tests #测试任务,删
vars #定义全局变量
示例1:重构rsync服务
- 编写tasks中的文件main.yml
- name: Install Rsync Server
yum:
name: rsync
state: present
- name: Configure Rsync
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
loop:
- { src: rsyncd.conf.j2,dest: /etc/rsyncd.conf,mode: '0644' }
- { src: rsync.passwd.j2,dest: /etc/rsync.passwd,mode: '0600' }
notify: Restart Rsync Server
- name: Create "{{ user }}" group
group:
name: "{{ user }}"
gid: 666
- name: Create "{{ user }}" user
user:
name: "{{ user }}"
uid: 666
group: "{{ user }}"
shell: /sbin/nologin
create_home: false
- name: Create "{{ rs_dir }}"
file:
path: "{{ rs_dir }}"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
- name: Start Rsync Server
systemd:
name: rsyncd
state: started
enabled: yes
- 编写vars中的文件main.yml
user: www
rsync_port: 873
rs_dir: /backup
- 编写handlers中的文件main.yml
- name: Restart Rsync Server
systemd:
name: rsyncd
state: restarted
- 编写jinja2配置文件rsyncd.conf.j2及匿名用户密码文件
uid = {{ user }}
gid = {{ user }}
port = {{ rsync_port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[backup]
path = {{ rs_dir }}
rsync_backup:123456
- 在rsync目录的上一级编排调用
- hosts: all
roles:
- role: rsync
when: ansible_hostname == "backup"
本文来自博客园,作者:丁志岩,转载请注明原文链接:https://www.cnblogs.com/dezyan/p/18784463

浙公网安备 33010602011771号