Ansible基于Python开发,集合了众多优秀运维工具的优点,实现了批量运行命令部署程序、配置系统等功能。默认通过SSH协议进行远程命令执行或下发配置,无需部署任何客户端代理软件,从而使得自动化环境部署变得更加简单。可同时支持多台主机并行管理,使得管理主机更加便捷。
Ansible基本架构由六个部分组成:
Ansible core 核心引擎。
Host inventory 主机清单:用来定义Ansible 所管理的主机,默认是在Ansible的host配置文件中定义被管理主机,同时也支持自定义动态主机清单和指定其他配置文件的位置。
Connection plugins连接插件:负责和被管理主机实现通信。除支持使用ssh连接被管理主机外, Ansible还支持其他的连接方式,所以需要有连接插件将各个主机用连接插件连接到 Ansible。
Playbooks(yaml, injaz2)剧本:用来集中定义
Ansible任务的配置文件,即将多个任务定义在一个剧本中由 Ansible自动执行,可以由控制主机针对多台被管理主机同时运行多个任务。
Core modules核心模块:是 Ansible自带的模块,使用这些模块将资源分发到被管理主机,使其执行特定任务或匹配特定的状态。
Custom modules自定义模块:用于完成模块功能的补充,可借助相关插件完成记录日志、发送邮件等功能。
ansible功能特性:
- 应用代码自动化部署
- 系统管理配置自动化
- 支持持续交付自动化
- 支持云计算,大数据平台环境
- 轻量级,无序在客户端安装agent,更新时只需在控制机上进行更行即可
- 批量任务执行可以写成脚本,不用分发到远程就可以执行
- 支持非root用户管理操作,支持sudo
- 使用python编写,维护更简单
Ansible安装
Ansible 自动化运维环境由控制主机与被管理主机组成,由于Ansible是基于SSH协议进行通信的,所以控制主机安装Ansible软件后不需要重启或运行任何程序,被管理主机也不需要安装和运行任何代理程序。
实验安装环境:
角色 |
主机名 |
IP地址 |
组名 |
控制主机 |
01 |
10.0.0.160 |
|
被管理主机 |
02 |
110.0.0.161 |
webserver |
被管理主机 |
03 |
110.0.0.162 |
mysql |
机器基础优化
#更换yum源 cd /etc/yum.repos.d/ wget –O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo yum clean all yum makecache #安装基础软件 yum install -y lrzsz nmap tree dos2unix nc iproute net-tools ntpdate wget vim bash-completion.noarch bash-completion-extras.noarch telnet #更改主机名 hostname huanglf echo "huanglf" >/etc/hostname #修改字符集 echo "LANG="zh_CN.UTF-8"" >/etc/locale.conf source /etc/locale.conf #关闭防火墙 systemctl stop firewalld.service systemctl disable firewalld.service firewall-cmd --state #关闭邮件服务 systemctl stop dovecot systemctl stop postfix systemctl disable dovecot #添加时间同步 echo '#time sync by oldboy at 2017.10.28' >>/var/spool/cron/root echo '*/5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1' >>/var/spool/cron/root
控制主机安装ansible并生成密钥对批量发送给被管理主机
1、yum安装环境包与ansible
yum install -y epel-release yum install -y ansible
2、查看版本:ansible --version
3、配置被管理端主机IP清单
[root@01 ~]# egrep -v "^#|^$" /etc/ansible/hosts [webserver] 10.0.0.161 [mysql] 10.0.0.162 [root@01 ~]#
4、虽然ansible的配置文件已经设置完成被管理端的IP地址,但是因为ansible是基于ssh协议,所以还需要配置密钥对验证
5、ssh协议免交互代理 创建用户生成秘钥对,也可以使用root
[root@01 ~]# ssh-agent bash [root@01 ~]# ssh-add Enter passphrase for /root/.ssh/id_rsa: abc23 Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa) [root@01 ~]#
6、shell脚本批量发送公钥
yum install -y expect
编写分发秘钥的脚本
[root@01 ~]# cat auto-sshkey.sh #!/bin/sh . /etc/init.d/functions #1.product key pair /usr/bin/rm -f .ssh/* 2&>/dev/null [ -f id_rsa.pub = 0 ] >/dev/null 2>&1 ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa >/dev/null 2>&1 if [ $? -eq 0 ];then action "create dsa $ip" /bin/true else action "create dsa $ip" /bin/false exit 1 fi #2.dis pub key for ip in 161 162 do #expect fenfa_sshkey.exp ~/.ssh/id_dsa.pub 10.0.0.$ip >/dev/null 2>&1 sshpass -p123456 ssh-copy-id -o StrictHostKeyChecking=no 10.0.0.$ip >/dev/null 2>&1 if [ $? -eq 0 ];then action "$ip" /bin/true else action "$ip" /bin/false fi done [root@01 ~]# sh auto-sshkey.sh
验证是否可以免秘钥远程
解决警告问题
sed -i "s%#host_key_checking = False%host_key_checking = False%g" /etc/ansible/ansible.cfg sed -i "s% #deprecation_warnings = True %deprecation_warnings = False%g" /etc/ansible/ansible.cfg
解决警告问题,这个是由于ansible资产文件中带有特殊字符造成的
7、ping通所有可互通的主机
ansible 模块使用
1、ansible 命令使用格式
HOST-PATTERN #匹配主机模式,如all表示所有主机 -m MOD_NAME #模块名 如:ping -a MOD_ARGS #模块执行的参数 -f FORKS #生成几个子进行程执行 -C #(不执行,模拟跑) -u Username #某主机的用户名 -c CONNection #连接方式(default smart)
例如
ansible all -m shell -a "ifconfig|grep ens33"
2、ansible-doc 获取帮助信息
ansible 模块比较多,可以通过ansible-doc
--help 显示帮助信息
ansible doc -l 获取所有当前版本下的可用模块及简要信息
ansible-doc -s 模块名
获取指定模块帮助信息说明``
3、ansible常用模块
3.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 ' dest=/tmp/hi.txt"
3.2、fetch模块
从远程主机拉取文件到本地
ansible all -m fetch -a "src=/tmp/hi.txt dest=/tmp"
3.3、command模块
在远程主机上执行命令,属于裸执行,非键值对显示;不进行shell解析
ansible all -m command -a "ifconfig"
这就是因为command模块不是shell解析属于裸执行导致的
为了能达成以上类似shell中的解析,ansible有一个shell模块
3.4、shell模块
由于commnad只能执行裸命令(即系统环境中有支持的命令)至于管道之类的功能不支
shell模块可以做到
例如:
ansible all -m shell -a "ifconfig|grep ens33"
3.5、file模块
设置文件属性(创建文件)
常用参数:
path 目标路径 state directory 为目录,link为软件链接 group 目录属组 owner 属主 等,其他参数通过ansible-doc -s file 获取
示例1:创建目录
示例2:创建软件链接
ansible all -m file -a "src=/tmp/hi.txt path=/var/tmp/hi.link state=link"
3. 6、cron模块
通过cron模块对目标主机生成计划任务
常用参数:
除了:分(minute) 时(hour) 日(day) 月(month) 周(week)外 name: 本次计划任务的名称 state: present 生成(默认) |absent 删除 (基于name)
示例:对各主机添加每隔3分钟从time.windows.com同步时间
ansible all -m cron -a "minute=*/3 job='/usr/sbin/update time.windows.com &>/dev/null' name=update_time"
示例2:删除计划任务
ansible all -m cron -a "name=update_time state=absent"
3.7、yum模块
故名思义就是yum安装软件包的模块;
常用参数说明:
enablerepo,disablerepo表示启用与禁用某repo库 name 安装包名 state (present' orinstalled', latest')表示安装, (absent' or `removed') 表示删除
示例:通过安装epel扩展源并安装nginx
ansible all -m yum -a "name=epel-release state=installed" ansible all -m yum -a "name=nginx state=installed"
3.8、service模块
服务管理模块
常用参数:
name:服务名 state:服务状态 enabled: 是否开机启动 true|false runlevel: 启动级别 (systemed方式忽略)
例如启动nginx
ansible all -m service -a "name=nginx state=started enabled=true"
在节点上查看
3.9、script模块
把本地的脚本传到远端执行;前提是到远端可以执行,不要把Linux下的脚本同步到windows下执行
[root@01 ~]# cat test.sh #!/bin/bash echo "ansible script test!" > /tmp/ansible.txt ansible all -m script -a "/root/test.sh" [root@01 ~]# ssh 10.0.0.161 [root@02 ~]# cat /tmp/ansible.txt ansible script test! [root@02 ~]#
Playbook实战
playbook是Ansible的配置,部署和编排的语言。他们可以描述你所希望的远程系统强制执行的政策,或者在一般的IT流程的一组步骤;形象点的说就是:如果ansible的各模块(能实现各种功能)是车间里的各工具;playbook就是指导手册,目标远程主机就是库存和原料对象.
playbook是基于YAML语言格式配置,关于YAML
更多playbook官方说明参考
1、playbook的核心元素
hosts : playbook配置文件作用的主机 tasks: 任务列表 variables: 变量 templates:包含模板语法的文本文件 handlers :由特定条件触发的任务 roles :用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等
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安装管理redis服务
[root@01 ~]# mkdir playbooks [root@01 ~]# cd playbooks [root@01 playbooks]# cat redis_first.yaml - hosts: all remote_user: root tasks: - name: install redis yum: name=redis state=latest - name: start redis service: name=redis state=started [root@01 playbooks]#
语法检查
[root@01 playbooks]# ansible-playbook --syntax-check redis_first.yaml playbook: redis_first.yaml #说明语法没有 问题 [root@01 playbooks]#
将要执行的主机
[root@01 playbooks]# ansible-playbook --list-hosts redis_first.yaml playbook: redis_first.yaml play #1 (all): all TAGS: [] pattern: [u'all'] hosts (2): 10.0.0.161 10.0.0.162 [root@01 playbooks]#
执行命令:ansible-playbook redis_first.yaml 结果如下
ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
说明:
自上而下列出了三个任务,分别是[Gathering Facts] , [install redis], [start redis],其中各主机上成功为ok=3,有两项任务执行结果是changed
不可达 和失败的任务均为0;
由于上面的操作是直接安装redis服务并启动,并没有配置文件,这还不能往生产环境中使用,生产环境中的redis肯定有不同的配置项,因此需要在安装时提供配置文件
4、带配置文件的安装管理redis
首先复制一个redis.conf到本地并进行修改
方法一:scp 10.0.0.162:/etc/redis.conf .
方法二:ansible 10.0.0.161 -m fetch -a "src=/etc/redis.conf dest=./"
[root@01 ~]# grep -n -o "bind 0.0.0.0" redis.conf
61:bind 0.0.0.0 #把127.0.0.1 改成0.0.0.0
[root@01 ~]#
将修改好的文件移动到执行安装脚本的目录去
[root@01 ~]# mv /root/10.0.0.161/etc/redis.conf /root/playbooks/redis.conf [root@01 ~]# ls playbooks/ redis.conf redis_first.yaml [root@01 ~]#
编写脚本,指定文件进行安装
[root@01 ~]# cd playbooks [root@01 playbooks]# cat redis_second.yaml - hosts: all remote_user: root tasks: - name: install redis yum: name=redis state=latest - name: copy config file copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis notify: restart redis tags: configfile - name: start redis service: name=redis state=started handlers: - name: restart redis service: name=redis state=restarted [root@01 playbooks]#
再次执行检查脚本语法
- ansible-playbook --syntax-check redis_second.yaml
再次执行安装
- ansible-playbook redis_second.yaml
可以发现只是加了一个配置文件,所有的任务都执行了,可否只应用新添加的任务?当然可以
这里就要通过ansible-playbook -t
TAGS_NAME 来执行了
可以把redis.conf中添加一个登录密码再执行测试下:
利用ansible批量安装zabbix-agent
下载zabbix-agent客户端
wget -q http://mirrors.aliyun.com/zabbix/zabbix/3.4/rhel/7/x86_64/zabbix-agent-3.4.0-1.el7.x86_64.rpm
批量拷贝到客户端上
ansible all -mcopy -a "src=/root/zabbix-agent-3.4.0-1.el7.x86_64.rpm dest=/tmp/zabbix-agent-3.4.0-1.el7.x86_64.rpm owner=root group=root mode=644 backup=yes"
批量安装zabbix-agent
ansible all -m yum -a "name=/tmp/zabbix-agent-3.4.0-1.el7.x86_64.rpm state=present"
拉取一台机器上的配置文件到当前进行编辑,修改好都重新执行安装
修改成如下生效配置
[root@01 ~]# grep "^[a-Z]" 10.0.0.161/etc/zabbix/zabbix_agentd.conf PidFile=/var/run/zabbix/zabbix_agentd.pid LogFile=/var/log/zabbix/zabbix_agentd.log LogFileSize=0 EnableRemoteCommands= 1 Server=10.0.0.160 ListenPort=10050 ServerActive=10.0.0.161 Hostname=Zabbix server Include=/etc/zabbix/zabbix_agentd.d/*.conf [root@01 ~]#
批量分发修改好的zabbix-agent.conf文件
ansible all -m copy -a "src=/root/10.0.0.161/etc/zabbix/zabbix_agentd.conf dest=/etc/zabbix/zabbix_agentd.conf backup=yes"
批量启动,重启,关闭zabbix-agent
ansible all -a "systemctl start zabbix-agent"
ansible批量修改主机名
基于使用root用户或有使用修改主机名的用户名及密码实现
没有修改前
修改配置文件,如果做过面秘钥登录的可以后不需要指定端口跟密码
例如:
10.0.0.161 hostname=web1 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=123456
[root@01 ~]# egrep -v "^#|^$" /etc/ansible/hosts [test] 10.0.0.161 hostname=web1 10.0.0.162 hostname=web2 [root@01 ~]#
[root@01 ~]# cat name.yml --- - hosts: test remote_user: root tasks: - name: change name raw: "echo {{hostname|quote}} > /etc/hostname" - name: shell: hostname {{hostname|quote}} [root@01 ~]#
官方帮助文档地址:http://www.ansible.com.cn/docs/playbooks_intro.html