ansible配置管理基础应用
2019.10.31 TsengYia
---- http://tsengyia.blog.chinaunix.net/
系统环境:
RHEL 8.0 (Ootpa) [4.18.0-80.el8.x86_64]
软件环境:
ansible 2.8.0
###########################################
一、安装ansible
# yum -y install ansible
配置调整及提权:
# vim /etc/ansible/ansible.cfg
[defaults]
inventory = /etc/ansible/hosts //主机清单的文件路径
remote_user = matthew //用户playbook的用户身份(缺省为当前使用人)
roles_path = /etc/ansible/roles //角色文件的默认存放目录
[privilege_escalation] //提权配置段(配合托管主机的visudo授权)
become=True
become_method=sudo
become_user=root
become_ask_pass=False
二、设置托管主机清单(推荐通过SSH密钥管理所有主机)
# vim /etc/ansible/hosts
192.168.0.1 //可以指定单个IP
192.168.0.2
192.168.0.[11:20] //可以指定范围内的地址
[webservers] //可以设分组
web1.example.com
web2.example.com //可以指定单个域名
web3 ansible_ssh_host=192.168.1.3 ansible_ssh_port=2222 //可以设主机别名web3
web4 ansible_ssh_host=192.168.1.4 ansible_ssh_user="zhsan" ansible_ssh_pass="1234567"
.. ..
[idc007]
172.25.0.11
172.25.0.12
[idc007:children]
webservers //组内还可以嵌套其他组
三、远程执行少量命令(ad-hoc)
基本用法:
# ansible <主机模式> -m 模块名 -a '参数 .. ..'
# ansible <主机模式> -m 模块名 -a '参数 .. ..' -f 10 //并行处理10个主机(默认5)
!!!! 主机模式可以是 /etc/ansible/hosts 文件中指定的 IP地址、主机名、组名,用来限定去操作哪些主机
!!!! 可以使用通配符 * ,允许 : 或 , 分隔多个托管主机或组
!!!! 使用 'group1:group2' 表示在组1中或者在组2中
!!!! 使用 'group1:!group2' 表示在组1中但不在组2中的托管主机
!!!! 使用'group1:&group2' 表示既在组1中也在组2中的托管主机
!!!! 使用'group1[0]' 表示组1中的第1个主机(类似于属组下标的表示方式)
!!!! 使用'group1[0:4]' 表示组1中的第1~5个主机(类似于属组下标的表示方式)
1. 检查所有托管主机是否可以正常响应python指令
# ansible all -m ping
2. 在 192.168开头的托管主机上执行命令
!!!! 缺省使用command模块执行远程命令,若要支持重定向、管道等功能,可以改用shell模块
# ansible 192.168* -a 'useradd zhsan' //在远程主机上添加用户zhsan
# ansible 192.168* -m shell -a 'echo 1234567 | passwd --stdin zhsan' //为该用户设置密码
3. 在远程主机 192.168.0.2 创建目录、文件、设置权限、删除、……
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/ mode=755 state=directory' //建目录
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/a.txt state=touch' //建普通文件
# ansible 192.168.0.2 -m file -a 'src=/etc/resolv.conf name=/etc/rs.conf state=link' //建软链接文件
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/a.txt owner=root mode=775 state=file' //设置权限
# ansible 192.168.0.2 -m file -a 'name=/repo/rh8dvd/ state=absent' //删除文档
4. 在所有托管主机上建立新文件,
# ansible all -m copy -a 'src=/etc/fstab dest=/tmp/fstab.txt mode=644' //上传指定的文件
# ansible all -m copy -a 'content="AAAA\nBBBB\nCCCC\n" dest=/tmp/content.txt' //建立指定内容的新文件
5. 用户账号管理
# ansible all -m user -a 'name=zhsan uid=1234' //添加新用户
# ansible all -m user -a "name=xiaoqi groups=users password={{' 1234567'|password_hash('sha512') }} state=present"
//添加新用户并设置密码、附属组
# ansible all -m user -a 'name=zhsan state=absent remove=yes' //删除用户
6. 通过yum模块管理软件包
# ansible all -m yum -a 'pkg=httpd state=present' //安装httpd软件包
# ansible all -m yum -a 'pkg=vsftpd state=absent' //卸载vsftpd软件包
7. 通过service模块管理系统服务
# ansible webservers -m service -a "name=httpd state=restarted" //确保重启httpd服务
# ansible webservers -m service -a "name=httpd enabled=yes" //确保httpd服务开机后自动运行
8. 通过parted、lvg、lvol、filesystem模块管理磁盘及文件系统
# ansible pc180 -m parted -a "device=/dev/sdc label=gpt number=1 part_type=primary part_start=0% part_end=10GiB"
//创建分区/dev/sdc1
# ansible pc180 -m lvg -a "vg=rhel pesize=16M pvs=/dev/sdc1" //创建卷组rhel
# ansible pc180 -m lvol -a "lv=data size=1500M vg=rhel" //创建逻辑卷data
# ansible pc180 -m filesystem -a "dev=/dev/rhel/data fstype=ext4" //将逻辑卷格式化为ext4文件系统
9. 通过mysql_user模块添加数据库用户
!!!! 前提条件:托管机已安装并运行MySQL或MariaDB服务,且安装了python3-PyMySQL模块包
# ansible host1 -m mysql_user -a 'priv="*.*:ALL" name=jerry host=localhost password="123456" state=present'
10. 模块相关操作
# ansible-doc -l //列出支持的模块
# ansible-doc copy //查看copy模块的使用帮助
四、远程执行复杂任务(playbook)
1. 编写剧本 /root/zhsan.yml ,用来为远程主机添加用户 zhsan 并设置密码 1234567
# vim /root/zhsan.yml
--- //建议的起始标记
- name: Users Administration //场景1开始
hosts: 192.168.0.1 //演员表(作用于哪些主机)
tasks: //任务
- name: add user zhsan //任务1的描述文本
user: //使用user模块
name: zhsan //用户名zhsan
state: present //要求的状态为存在
password: "{{' 1234567'|password_hash('sha512') }}" //设置加密的密码字串
... //建议的结束标记
# ansible-playbook -C /root/zhsan.yml //检查剧本语法
# ansible-playbook /root/zhsan.yml //执行剧本
2. 编写剧本 /root/svr80.yml ,用来管理远程主机svr80的软件包
# vim /root/svr80.yml
---
- name: Deploy LAMP platform
hosts: pc180
tasks:
- name: Install package group
yum: name="@RPM Development tools" state=installed //安装一组软件
- name: Update all packages
yum: name="*" state=latest //升级所有软件包
...
3. 编写剧本 /root/nginx.yml ,用来为远程主机pc180安装并部署Nginx网站服务
# vim /root/nginx.yml
---
- name: Deploy Nginx Web Server
hosts: pc180
tasks:
- name: 1. Remove httpd package //操作1,确保httpd被移除
yum: pkg=httpd state=removed
- name: 2. Install nginx package //操作2,确保nginx被安装
yum: pkg=nginx state=installed
- name: 3. Enable and start nginx service //操作3,确保nginx服务被启用
service: name=nginx state=started enabled=yes
...
4. 编写剧本 /root/selinux.yml ,用来修改远程主机pc180上的SELinux配置
# vim /root/selinux.yml
---
- name: Modify SELinux configuration
hosts: pc180
tasks:
- lineinfile: path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=permissive'
...
5. 编写剧本 /root/webdev.yml, 用来向web服务器部署网页目录,并调整文档的SELinux安全属性
# vim /root/webdev.yml
---
- name: Prepare Web Directory
hosts: pc180
tasks:
- file:
name: /webdev //新文档的名称
group: apache //所属组
mode: 02775 //权限(SetGID)
setype: httpd_sys_content_t //指定SELinux上下文的type类型
state: directory //文档类别为目录
- file:
name: /var/www/html/webdev //链接文件的路径
src: /webdev //链接源
state: link //类型为符号链接
force: yes //强制创建(即使链接源还不存在)
- copy:
content: It's works! //定义首页文件内容
dest: /webdev/index.html //上传为指定文件
mode: 0644 //设置权限
setype: httpd_sys_content_t //指定SELinux上下文的type类型
- service:
name: httpd
state: restarted //重启httpd服务
enabled: yes
...
五、使用变量优化配置
1. 在定义清单时,为主机 192.168.0.1 提供变量
# vim /etc/ansible/hosts
192.168.0.1 datadir="/var/lib/mysql" //定义名为datadir的变量
# ansible 192.168.0.1 -a 'echo {{datadir}}' //测试变量调用
192.168.0.1 | CHANGED | rc=0 >>
/var/lib/mysql //确认结果
2. 在定义清单时,为webservers组提供变量
# vim /etc/ansible/hosts
[webservers]
web1.example.com
web2.example.com
[webservers:vars]
webroot="/var/www/html" //定义名为webroot的变量
index_file="index.html" //定义名为index_file的变量
# ansible websvrs -m file -a 'dest={{webroot}}/{{index_file}} state=touch' //测试变量调用
3. 通过独立的文件为主机 192.168.0.2 、组 dbservers 提供变量
1)准备目录结构
# mkdir -p /etc/ansible/host_vars //默认的主机变量目录位置
# mkdir -p /etc/ansible/group_vars //默认的组变量目录位置
2)为主机 192.168.0.2 提供变量文件
# vim /etc/ansible/host_vars/192.168.0.2 //文件名与清单中的主机地址要相对应
datadir: /var/lib/mysql //注意冒号:后的空格不要省略
# ansible 192.168.0.2 -a 'echo {{ha}}' //测试变量调用
192.168.0.2 | CHANGED | rc=0 >>
/var/lib/mysql //确认结果
3)为组 webservers 提供变量文件
# vim /etc/ansible/group_vars/webservers //文件名与清单中的组名要相对应
http_user: apache //注意冒号:后的空格不要省略
# ansible webservers -a 'echo {{http_user}}' //测试变量调用
192.168.1.3 | CHANGED | rc=0 >>
apache //确认结果
4. 编写剧本 /root/httpd81.yml ,用来修改远程主机pc180上的SELinux配置
# vim /etc/ansible/host_vars/pc180 //为主机定义变量
httpd_config: /etc/httpd/conf/httpd.conf //定义变量httpd_config,存放配置文件路径
listen_port: 81 //定义变量listen_port,存放监听端口
# vim /root/selinux.yml
---
- name: Configuraton Web Service
hosts: pc180
tasks:
- name: Add Listen Port 81 //监听81端口(insertafter默认在最后一个匹配行后插入新行)
lineinfile: path={{httpd_config}} insertafter='^Listen ' line='Listen {{listen_port}}'
- name: Remove Listen Port 8000 //删除指定内容的行
lineinfile: path={{httpd_config}} regexp='^Listen *8000' state=absent
...
六、 搜集托管主机信息/系统变量
!!!! 托管主机的各种环境指标信息,可以通过 setup 模块获得
# ansible host1 -m setup //列出所有信息
# ansible host1 -m setup -a 'filter=*_os_*' //过滤出包含 _os_ 的指标
# ansible host1 -m setup -a 'filter=ansible_memtotal_mb' //过滤出总内存大小的指标
$ ansible pc180 -m setup -a 'filter=ansible_bios_version' //过滤出BIOS版本
# ansible host1 -m debug -a 'var=hostvars["pc180"]' //通过魔法变量hostvars列出托管主机pc180上的变量
# ansible pc180 -m debug -a 'var=group_names' //通过魔法变量group_names列出托管主机所在组名
1. 在剧本中阻止搜集信息
---
- name: xxxx
- hosts: pc180
gather_facts: no //如果用不到,可以不搜集信息(缺省会自动搜集)
tasks:
.. ..
...
2. 编写剧本获取远程主机的主机名、IP地址、网络接口列表、分区大小等信息
# vim /root/getinfo.yml
---
- hosts: pc180
tasks:
- name: Show IP infomation
debug:
msg: >
Hostname is {{ansible_facts.hostname}}
IP address of ens3 is {{ansible_ens3.ipv4.address}}
Size of partition sdb2 is {{ansible_facts.devices.sdb.partitions.sdb2.size}}
Network interfaces is {{ansible_facts.interfaces}}
...
3. 编写剧本向远程主机部署指定文件 /tmp/newfile.txt,包含的内容来自于content提供
# vim /root/putfile.yml
---
- hosts: pc180
tasks:
- copy:
content: |
Hello everyone,
Ansible is such a good tool,
You can try it.
dest: /tmp/newfile.txt
...
4. 编写剧本向远程主机部署指定文件 /etc/myhosts,包含的内容来自于控制机上的模板文件hosts.j2
# vim /etc/ansible/hosts.j2
{% for id in groups.all %}
{{hostvars[id].ansible_facts.ens3.ipv4.address}} {{hostvars[id].ansible_facts.fqdn}} {{hostvars[id].ansible_facts.hostname}}
{% endfor %}
# vim /root/myhosts.yml
---
- name: gather facts
hosts: all
- hosts: pc180
tasks:
- template:
src: hosts.j2
dest: /etc/myhosts
...
5. 编写剧本为托管主机生成硬件报告文件 /root/hwinfo.txt
# vim /root/hw.temp //硬件信息报告模板文件
InverntoryHostname=AAAA
MemTotal=BBBB
BiosVersion=CCCC
Sizeof_sda=DDDD
Sizeof_sdb=EEEE
# vim /root/hwinfo.yml //生成硬件报告剧本
- name: hardware report
hosts: all
ignore_errors: yes //忽略个别错误
vars: //提取硬件检测结果
- sfile: /root/hwinfo.txt //硬件报告文件路径
- host: "{{inventory_hostname}}" //提取清单主机名
- mem: "{{ansible_facts.memtotal_mb}}" //提取总内存大小(MB)
- bios: "{{ansible_facts.bios_version}}" //提取BIOS版本
- vdasize: "{{ansible_facts.devices.sda.size}}" //提取磁盘vda大小
- vdbsize: "{{ansible_facts.devices.sdb.size if ansible_facts.devices.sdb.size is defined else 'NONE' }}" //提取磁盘vdb大小,或NONE
tasks: //修改报告(根据模板内容查找替换)
- get_url: url= dest={{sfile}} force=yes
- replace: name={{sfile}} regexp=AAAA replace={{host}}
- replace: name={{sfile}} regexp=BBBB replace={{mem}}
- replace: name={{sfile}} regexp=CCCC replace={{bios}}
- replace: name={{sfile}} regexp=DDDD replace={{vdasize}}
- replace: name={{sfile}} regexp=EEEE replace={{vdbsize}}
...
6. 编写剧本为受管主机创建逻辑卷
!!!! 当卷组rhel不存在时,提示信息“VG not found”
!!!! 当创建逻辑卷空间不足时,“insufficient free space”
# vim /root/lv.yml
- name: manager volume
hosts: all
tasks:
- name: 1. failed when VG not found
debug: msg="VG not found"
when: "'vgxxx' not in ansible_facts.lvm.vgs" //目标VG不存在时报错
failed_when: "'vgxxx' not in ansible_facts.lvm.vgs" //停止后续任务
- name: 2. lvcreate
block: //配置指令块
- lvol: lv=data size=1500M vg=vgxxx
notify: mkfs //lv建成功后通知mkfs
rescue: //若块操作失败,则执行补救
- debug: msg="insufficient free space"
- lvol: lv=data size=800M vg=vgxxx
notify: mkfs //lv建成功后通知mkfs
handlers: //收到通知后执行
- name: mkfs //定义通知接口名mkfs
filesystem: dev=/dev/vgxxx/data fstype=ext4 force=yes
...
七、在playbook中使用循环、条件
1. 编写剧本 lamp.yml,用来确保在托管主机上安装并启用LAMP平台
# vim lamp.yml
---
- name: Deploy LAMP Platform
hosts: host1
# import_tasks: /etc/ansible/startup.yml
tasks:
- name: install LAMP packages
yum: name:={{item}} state=present //调用循环变量(固定名称item)
loop: //配置列表循环项
- httpd
- mariadb
- mariadb-server
- php
- php-mysqlnd
- name: enable LAMP services
service: name={{item}} state=started enabled=yes
loop:
- httpd
- mariadb
...
2. 编写剧本 when.yml,当托管主机的硬件平台为x86_64时,创建标记文件 /tmp/x86_64.mark
# vim /root/when.yml
---
- name: test match
hosts: 192.168.0.1
gather_facts: yes //搜集客户端环境信息(缺省)
tasks:
- name: if x86_64 then create a file
file:
name: /tmp/x86_64.mark
state: touch
when: ansible_machine == "x86_64" //通过 when 设置执行条件
...
3. 编写剧本 users.yml ,根据托管主机所属的清单组不同分别添加不同的用户
!!!! 如果属于dev或test组,添加用户harry,隶属于附加组 adm,密码为1234
!!!! 如果属于prod组,则添加用户natasha,密码来自于文件 locker.yml 中的变量 pw_of_product
# vim /root/users.yml
---
- name: Add different users according to different conditions
hosts: pc180
vars_files: locker.yml //为用户提供密码的变量列表文件,比如pw_of_product变量
vars:
- grp1: dev
- grp2: test
- grp3: prod
tasks:
- user: name=harry groups=adm state=present password='{{'1234'|password_hash('sha512')}}'
when: (grp1 in group_names) or (grp2 in group_names)
- user: name=natasha state=present password='{{ {{pw_of_product}} |password_hash('sha512')}}'
when: grp3 in group_names
...
!!!! 注意:若密码文件 locker.yml 已经加密,则通过ansible-playbook执行剧本时需指定密码
# vim secret.txt
your_password
# ansible-playbook --vault-password-file=secret.txt users.yml
4. 编写剧本 issue.yml ,为受管主机设置 /etc/myissue 文件内容
!!!! 如果属于dev组,则内容为Development
!!!! 如果属于test组,则内容为Test
!!!! 如果属于prod组,则内容为Production
[matthew@svr8 ansible]$ cat issue.yml
---
- name: modify issue file
hosts: all
tasks:
- name: aaa
copy:
content: |
{% if "dev" in group_names %}
Development
{% elif "test" in group_names %}
Test
{% elif "prod" in group_names %}
Production
{% endif %}
dest: /etc/myissue
...
5. Jinja2模板文件语法
1)if选择,生成端口配置
{% if PORT %}
bind-address=0.0.0.0:{{port}}
{% else %}
bind-address=0.0.0.0:3306
{% endif %}
2)for循环,生成主机映射列表
{% for id in range(6,10) %}
172.24.0.{{id}} node{{id}}.example.com node{{id}}
{% endfor %}
3)for循环生成虚拟web主机配置文件
# vim /etc/ansible/vhosts.conf.j2
{% for id in vhosts %}
ServerName {{ id.servername }}
DocumentRoot {{ id.documentroot }}
{% endfor %}
# vim /root/httpd_vhosts.yml
---
- name: Configure web vhosts
hosts: pc180
vars:
vhosts:
- { servername: 'node1.example.com', documentroot: '/var/www/node1' }
- { servername: 'node2.example.com', documentroot: '/var/www/node2' }
- { servername: 'node3.example.com', documentroot: '/var/www/node3' }
tasks:
- template: src=/etc/ansible/vhosts.conf.j2 dest=/etc/httpd/conf.d/vhosts.conf
...
八、ansible-vault加密管理
!!!! 针对包含敏感数据的清单、剧本、变量等文件,都可以进行加密,以提高安全性
1. 加密文件的基本管理操作
# ansible-vault create secret.yml //新建加密文件,根据提示设置口令
# ansible-vault encrypt secret.yml //加密已有文件,根据提示设置口令
# ansible-vault view secret.yml //查看加密文件,根据提示验证口令
# ansible-vault rekey secret2.yml //修改加密口令,需验证旧口令
# ansible-vault decrypt secret.yml //解除加密保护,需验证旧口令
2. 加密文件的应用
1)使用ansible、ansible-playbook时,添加 --ask-vault-pass 以提示从键盘输入口令(缺省不提示)
# ansible-playbook secret.yml --vault-password-file=/root/ansible.pass
2)使用ansible、ansible-playbook时,通过 --vault-password-file 免除交互
# echo redhat > /root/ansible.pass //创建口令文件
# chmod 600 /root/ansible.pass //控制访问权限
# ansible-playbook secret.yml --vault-password-file=/root/ansible.pass //调用口令文件自动验证
3)加密、解密、查看加密的文件时,通过 --vault-password-file 免除交互
# ansible-vault view secret.yml --vault-password-file=/root/ansible.pass
4)修改加密口令时,新口令可以通过 --new-vault-password-file 免除交互
# echo 1234567 > /root/ansible.newpass //创建新口令文件
# chmod 600 /root/ansible.newpass //控制访问权限
# ansible-vault rekey secret.yml --vault-password-file=/root/ansible.pass --new-vault-password-file=/root/ansible.newpass
九、创建及使用角色
# cd /etc/ansible/roles/
# ansible-galaxy init httpd //初始化指定名称为httpd的角色目录
# vim http/tasks/main.yml //编写此角色的主任务剧本
---
# tasks file for http
- name: 1. install httpd
yum: pkg=httpd state=installed
- name: 2. restart httpd and firewalld
service: name={{item}} state=restarted enabled=yes
loop:
- httpd
- firewalld
- name: 3. deploy index.html //参照模板为受管web主机建立首页文件
template: src=index.html.j2 dest=/var/www/html/index.html
- name: 4. configure firewall rule
firewalld: service=http permanent=yes state=enabled
...
# vim roles/http/templates/index.html.j2 //编写模板文件(需要的话)
Welcome to {{ ansible_facts.fqdn }} on {{ ansible_facts.ens3.ipv4.address }}
# vim /root/httprole.yml //编写调用http角色的应用剧本
---
- name: use role http
hosts: pc180
roles:
- http
...
# ansible-playbook /root/httprole.yml //使用剧本
#############################################################################
阅读(8999) | 评论(0) | 转发(0) |