一、 介绍
1、关于Ansible
简单说ansible是自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
Ansible是一个部署一群远程主机的工具;Ansible通过SSH协议实现远程节点和管理节点之间的通信。理论上说,只要管理员通过ssh登录到一台远程主机上能做的操作,Ansible都可以做到。Ansible是python开发的,故依赖一些python库和组件,如:paramiko,PyYaml和jinja三个关键组件;简单来说Ansible是一个自动化运维软件。
2、Ansible构架
右边绿色部分是被管理的主机(虚拟机,物理机,云主机等)从以上架构图中可以看出
ansible是由主机清单(配置),playbook(配置),以及各模块插件组成;
简单的说就是,用户(管理员)通过ansible的主机清单配置或Playbook配置(一组任务),调用ansible的各种模块及参数来对
清单中的主机进行统一管理;
3、测试环境
本次测试的环境
ansible: CentOS7.6._x64 192.168.209.138 , ansible 2.9.10
node1:192.168.209.133 CentOS7.6._x64
node2:192.168.209.146 CentOS7.6._x64
node3:192.168.209.147CentOS7.6._x64
4、配置单向信任关系的免密通道
1.在ansible主机上生成密钥对
[root@ansible ~]# ssh-keygen -t ecdsa
(直接回车)
生成好的秘钥放在 /root/.ssh 下。*.pub 为公钥
2.将生成的公钥上传到所要控制的节点主机上
#3个节点服务器上开启ssh服务 ,开放22号端口,允许root用户登录,检查黑白名单是否拒绝登录
[root@ansible .ssh]# ssh-copy-id -i id_ecdsa.pub root@192.168.209.133
上传公钥到第一台节点服务器(node1)
注意同步过程需要输入yes和各自的root密码即可;此进可直接ssh root@192.168.209.133 就无密码登录上去啦!!
4、安装Asible
[root@ansible ~]# yum install epel-release -y
[root@ansible ~]# yum install ansible -y
#查看版本
[root@localhost ~]# ansible --version
ansible 2.9.10
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
二、配置及获取帮助说明
1.配置与执行文件说明
ansible的主配置文件
/etc/ansible/ansible.cfg
这个文件主要定义了roles_path路径,主机清单路径,连接清单中的主机方式等配置,这些大部的默认配置已经足够我们平时使用,如需要特别配置可以自行去修改;
/etc/ansible/hosts
这个配置文件就是默认主机清单配置文件,可通过ansible.cfg重新定义的;
如定义一组主机:
[root@ansible ~]# cd /etc/ansible/
[root@ansible ansible]# ls
ansible.cfg hosts roles
[root@ansible ansible]# vim hosts 添加服务器ip到webservers组里
[webservers]
192.168.209.133
192.168.209.146
[dbservers]
192.168.209.147
[root@ansible ~]# egrep -v '(^$|^#)' /etc/ansible/hosts 查看效果
[webservers] 给客户机服务器组起的名字
192.168.209.133
192.168.209.146
[dbservers]
192.168.209.147
除了以上两个重要的配置文件还有三个重要的可执行文件分别是:
ansible 主执行程序,一般用于命令行下执行
ansible-playbook 执行playbook中的任务
ansible-doc 获取各模块的帮助信息
2、ansible 使用格式
ansible
HOST-PATTERN #匹配主机模式,如all表示所有主机
-m MOD_NAME #模块名 如:ping、shell
-a MOD_ARGS #模块执行的参数
-f FORKS #生成几个子进行程执行
-C #(不执行,模拟跑)
-u Username #某主机的用户名
-c CONNection #连接方式(default smart)
完整示例:
[root@ansible ansible]# ansible all -m shell -a "ip add"
[root@ansible ansible]# ansible all -m shell -a "mkdir /root/sanchuang"
[root@ansible ansible]# ansible all -m shell -a "ls /root"
[root@ansible ansible]# ansible webservers -m shell -a "ip add"
====
体验:ansbile
*安装一个软件tree,在web组上
ansible web -m yum -a “name=tree state=installed”
*下发一个文件/etc/passwd到所有的机器的/root目录下
ansible all -m copy -a “src=/etc/passwd dest=/root mode=655”
ansible 不是一个守护进程(一直在内存里运行的,等待其他人的访问),当我们执行ansible命令的时候,才去执行,而且本质上ansible就是一个python开发的程序而已。
3、ansible-doc 获取帮助信息
ansible模块比较多,可以通过ansible-doc --help 显示帮助信息
ansible doc -l 获取所有当前版本下的可用模块及简要信息
ansible-doc -s 模块名 获取指定模块帮助信息说明``
三、ansible常用模块
1、copy模块
从本地copy文件分发到目录主机路径
参数说明:
src= 源文件路径
dest= 目标路径
注意src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去
content= 自行填充的文件内容
owner 属主
group 属组
mode权限
示例:
ansible all -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible mode=600"
ansible all -m copy -a "content='hi there\n' dest=/tmp/hi.txt"
#到node1上查看
2、fetch模块
从远程主机拉取文件到本地
示例
[root@ansible ~]# ansible all -m fetch -a "src=/tmp/hi.txt dest=/tmp"
192.168.209.133| SUCCESS => {
"changed": true,
"checksum": "279d9035886d4c0427549863c4c2101e4a63e041",
"dest": "/tmp/172.16.3.152/tmp/hi.txt",
"md5sum": "12f6bb1941df66b8f138a446d4e8670c",
"remote_checksum": "279d9035886d4c0427549863c4c2101e4a63e041",
"remote_md5sum": null
}
…省略
说明:fetch使用很简单,src和dest,dest只要指定一个接收目录,默认会在后面加上远程主机及src的路径
3、shell模块
由于commnad只能执行裸命令(即系统环境中有支持的命令),至于管道之类的功能不支持,
shell模块可以做到
示例:
[root@ansible ~]# ansible all -m shell -a "ifconfig|grep lo"
192.168.209.133 | SUCCESS | rc=0 >>
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
loop txqueuelen 0 (Local Loopback)
4、file模块
设置文件属性(创建文件)
常用参数:
path目标路径
state directory为目录,link为软件链接
group 目录属组
owner 属主等,其他参数通过ansible-doc -s file 获取
absent 删除文件和文件夹
directory 新建目录
touch 新建空文件
link 软连接文件
hard 硬链接文件
示例1:创建目录
[root@ansible ~]# ansible all -m file -a "path=/var/tmp/hello.dir state=directory"
192.168.209.133| SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/var/tmp/hello.dir",
"size": 6,
"state": "directory",
"uid": 0
}
192.168.209.146| SUCCESS => {
“changed”: true,
…省略…
5、cron模块
通过cron模块对目标主机生成计划任务
常用参数:
除了分(minute)时(hour)日(day)月(month)周(week)外
name: 本次计划任务的名称
state: present 生成(默认) |absent 删除 (基于name)
示例:对各主机添加每隔3分钟从ntp1.aliyun.com同步时间
ntpdate命令,更新时间
[root@ansible ~]# ansible all -m cron -a "minute=*/3 job='/usr/sbin/ntpdate
目标机器上查看
[root@node1 tmp]# crontab -l
*/10 * * * * bash /root/iptables_ssh.sh
#Ansible: None
*/3 * * * * /usr/sbin/ntpdate ntp1.aliyun.com name=update_time
删除计划任务
[root@ansible ~]# ansible all -m cron -a "name=update_time state=absent"
编写一个脚本,实现3个node节点服务器备份/var/log目录到/backup目录下文件名格式2019-7-10-log.tar.gz
每天2:30备份
需求分析:
1.在ansible机器上写好脚本
2.把脚本推倒node服务器上
3.创建计划任务
[root@ansible test]# vim backup_log.sh
[root@ansible test]# cat backup_log.sh
#!/bin/bash
ctime=$(date +%F%H%M%S)
mkdir -p /backup
tar czf /backup/${ctime}-log.tar.gz /var/log
[root@ansible test]#
推过去
[root@ansible test]# ansible all -m copy -a 'src=/test/backup_log.sh dest=/root/'
创建计划任务
[root@ansible test]# ansible all -m cron -a "minute=30 hour=2 job='bash /root/backup_log.sh' name=create_backup_log"
6、yum模块
故名思义就是yum安装软件包的模块;
常用参数说明:
enablerepo,disablerepo表示启用与禁用某repo库
name 安装包名
state (present’ orinstalled’, latest’)表示安装, (absent’ or `removed’) 表示删除
示例:
[root@ansible ~]# ansible all -m yum -a "name=ntpdate state=installed"
使用yum模块同时安装多个软件,注意使用逗号隔开
[root@ansible lianxi]# ansible all -m yum -a "name=tree,lsof state=installed"
安装软件也可以使用shell模块去安装(万能的shell)
7、service模块
服务管理模块
常用参数:
name:服务名
state:服务状态
enabled: 是否开机启动
true|falserunlevel: 启动级别 (systemed方式忽略)
停止nginx服务,但是设置开机启动
[root@ansible ~]# ansible all -m service -a "name=nginx state=stopped enabled=true"
启动和重新启动
[root@ansible ~]# ansible all -m service -a "name=nginx state=started enabled=true"
[root@ansible ~]# ansible all -m service -a "name=nginx state=restarted enabled=true"
四、Playbook实战
playbook是Ansible的配置,部署和编排。他可以描述你所希望的远程系统强制执行的政策,或者在一般的IT流程的一组步骤;形象点的说就是:如果ansible的各模块(能实现各种功能)是车间里的各工具;playbook就是指导手册,目标远程主机就是库存和原料对象.
playbook是基于YAML语言格式配置
1、playbook的核心元素
hosts : playbook配置文件作用的主机
tasks: 任务集
variables: 变内置变量或自定义变量在playbook中调用
templates:包含模板语法的文本文件
Handlers 和notity结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags 标签,指定某条任务执行,用于选择运行playbook中的部分代码。
[root@ansible playbooks]# ansible web -m setup
#查看已收集的原始信息
2、playbook运行方式
ansible-playbook --check 只检测可能会发生的改变,但不真执行操作
ansible-playbook --list-hosts 列出运行任务的主机
ansible-playbook --syntax-check playbook.yaml 语法检测
ansible-playbook -t TAGS_NAME playbook.yaml 只执行TAGS_NAME任务
ansible-playbook playbook.yaml 运行
3、Playbook语法
playbook使用yaml语法格式,后缀可以是yaml,也可以是yml。
- 在单一一个playbook文件中,可以连续三个连子号(—)区分多个play。还有选择性的连续三个点好(…)用来表示play的结尾,也可省略。
- 次行开始正常写playbook的内容,一般都会写上描述该playbook的功能。
- 使用#号注释代码。
- 缩进必须统一,不能空格和tab混用。
- 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行实现的。
- YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
- k/v的值可同行写也可以换行写。同行使用:分隔。
- v可以是个字符串,也可以是一个列表
- 一个完整的代码块功能需要最少元素包括
name: task
4、通过playbook安装管理nginx服务
[root@ansible playbooks]# cat nginx.yaml
- hosts: web
remote_user: root
tasks:
- name: install epel-release
yum: name=epel-release state=installed
- name: install nginx
yum: name=nginx state=installed
- name: start nginx
service: name=nginx state=started
语法检查
[root@ansible playbooks]# ansible-playbook --syntax-check nginx.yaml
playbook: nginx.yaml
说明语法没有问题
执行playbook:
[root@ansible playbooks]# ansible-playbook nginx.yaml
PLAY [web] **************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.209.250]
TASK [install epel-release] *********************************************************************************************************
ok: [192.168.209.250]
TASK [install nginx] ****************************************************************************************************************
changed: [192.168.209.250]
TASK [start nginx] ******************************************************************************************************************
changed: [192.168.209.250]
PLAY RECAP **************************************************************************************************************************
192.168.209.250 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
安装redis:
[root@ansible playbooks]# vim redis.yaml
- hosts: web #所有远程主机
remote_user: root #以远程主机上root用户执行
tasks: #任务
- name: install redis #任务之安装
yum: name=redis state=latest #动作调用yum模块安装
- name: start redis #任务之启动redis
service: name=redis state=started #动作调用sevice模块
使用template修改redis的配置文件:
先将reids的配置文件拉取到本地/root/playbooks 下
[root@ansible playbooks]# ansible web -m fetch -a "src=/etc/redis.conf dest=/root/playbooks/"
在redis.conf将bind 127.0.0.1修改为:bind {{ ansible_facts["ens33"]["ipv4"]["address"] }}
[root@ansible playbooks]# cat redis2.yaml
- hosts: web #所有远程主机
remote_user: root #以远程主机上root用户执行
tasks: #任务
- name: install redis #任务之安装
yum: name=redis state=latest #动作调用yum模块安装
- name: copy config file #任务之复制同步配置文件到远程目标主机
template: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis
notify: restart redis #触发的动作的名字,发通知给handlers
tags: configfile #任务标记名configfile
- name: start redis #任务之启动redis
service: name=redis state=started #动作调用sevice模块
handlers: #特定情况下,接收到其他任务的通知时被触发
- name: restart redis
service: name=redis state=restarted
ansible练习
1.在所有的node节点服务器上新建/backup目录
2.将所有节点服务器的/etc/passwd文件拷贝到ansible主机的/backup目录下
3.编写一个脚本实现备份/etc/passwd和/etc/shadow文件到各个节点服务器的/backup下,文件名里包含当天的日期,例如2020-3-28-passwd_shadow.tar.gz 添加一个计划任务,每天的3:30去执行,在所有的node节点服务器上实施。
[root@ansible ~]# cat backup.sh
#!/bin/bash
cp /etc/passwd /backup/
cp /etc/shadow /backup/
cd /backup
tar -cvf $(date +%Y-%m-%d)-passwd_shadow.tar.gz /etc/passwd /etc/shadow
[root@ansible ansible]# cat practice.yaml
- hosts: web
remote_user: root
tasks:
- name: new directory
file: path=/backup state=directory
- name: copy passwd
fetch: src=/etc/password dest=/backup
fetch: src=/etc/shadow dest=/backup
- name: shell
copy: src=/root/backup.sh dest=/root/backup.sh
notify: run shell
handlers:
- name: run shell
cron: minute=1 job='/bin/bash /root/backup.sh' name=backup_file