ansible 环境配置

配置centos7.4的源 及安装

只需要 epel-release
yum install -y epel-release
安装ansible
yum install -y ansible

验证安装结果( 查看ansible版本)

ansible --version

关闭selinux firewall

配置域名并创建组

配置文件:
(1)ansible应用程序的主配置文件:/etc/ansible/ansible.cfg
(2) Host Inventory定义管控主机:/etc/ansible/hosts
ansible.cfg配置文件可以存在于多个地方。读取配置文件的顺序依次是当前命令执行目录,其次是用户家目录下的.ansible.cfg,最后是/etc/ansible/ansible.cfg,先找到哪个就用哪个。

#vim /etc/hosts //配置域名
#vim /etc/ansible/hosts //创建添加组
添加变量
#vim /etc/ansible/ansible.cfg //无需使用密码远程
#ansible 组 --list -hosts //查看
#ansible web -m ping
#ssh web1
不同路径下分组
#cp -r /etc/ansible /opt
#vim /etc/ansible/ansible.cfg //指定路径
inventory = /opt/ansible/hosts
#vim /opt/ansible/hosts //添加创建组
#ansible aa --list-hosts

使用交互式密码分组

#vim /etc/ansible/hosts //删除变量
#ansible all -m command -a 'hostname' -k
#ansible all -m command -a 'id' -k //查看

使用脚本,脚本输出的必须是json格式(ansible方可识别)

创建密钥实现批量无密码配置

#rm -rf ~/.ssh/*
#cd /root/.ssh
#ssh-keygen //创建密钥
#ls
#ansible all -m authorized_key -a "user=root exclusive=true manage_dir=true key='$(< /root/.ssh/id_rsa.pub)'" -k -v //批量传送密钥
#ssh web1 //测试

ansible 系列命令

一 ansible 命令 :用于执行临时性的工作
二 ansible-doc :说明模块的手册 相当于shell的man
ansible-doc -l 列出所有的模块
ansible-doc [模块名] 查看帮助
ansible-doc modulename 查看modulename帮助 文档
三 ansible-console:类似于shell一样的交互式工具,
四 ansible-galaxy
五 ansible-playbook ansible的脚本
六 ansible-vault 配置文件加密
加密:ansible-vault encrypt a.yml
解密:ansible-vault decrypt a.yml
七 ansible-pull 与push工作模式相反 数量巨大的机器需要管理时

ansible 命令格式

ansible [options]

host-pattern 主机定义的分组

]# vim /etc/ansible/hosts
#inventory file例子,添加主机名hostname或者ip地址 
#未分组的主机,添加在最前面 
122.19.45.201 
hostname1 
122.19.45.[1:10]    #[1:10]表示所有1~10之间的数字,表示一组ip地址45.1、45.2、... 

#分组管理的主机 
[test0]     #组名 
122.28.13.100 
122.19.61.68:5030    #如果主机ssh端口不是22,可在地址后加:指定 

[targets1] 
localhost     ansible_connection=local 
122.28.13.10  ansible_connection=ssh  ansible_ssh_user=user  #指定连接类型和连接用户名 

[targets2]    #可配置主机变量 
host1       http_port=80 
host2       http_port=80 var2=xxx var3=xxx 

[targets2:var]  #添加关键字var,配置组变量,对属于该组的所有主机都适用 
var4=xxx 
var5=xxx 

[targets3:children]  #添加关键字children,把组作为其他组的子成员 
targets1 
targets2 

主机列表的正则匹配

ansible支持主机列表的正则匹配

全量: all/*
逻辑或: :
逻辑非: !
逻辑与: &
切片: []
正则匹配: 以~开头

ansible all -m ping  #所有默认inventory文件中的机器
ansible '*' -m ping  #同上
ansible '121.28.13.*' -m  ping #所有122.28.13.X机器

ansible  'web1:web2'  -m  ping  #所有属于组web1或属于web2的机器
ansible  'web1:!web2'  -m  ping #属于组web1,但不属于web2的机器
ansible  'web1&web2'  -m  ping  #属于组web1又属于web2的机器

ansible webserver[0]  -m  ping    #属于组webserver的第1台机器
ansible webserver[0:5]  -m  ping  #属于组webserver的第1到4台机器

ansible '~(beta|web)\.example\.(com|org)'  -m ping 

Ansible选项:

-M 指定模块路径
-m 使用模块,默认 command 模块
-a or --args 模块参数
-i inventory 文件路径,戒可执行脚本
-k 使用交互式登陆密码,而不是使用秘钥
-e 定义变量
-v 详细信息,-vvvv 开启 debug 模式
-K 提示输入sudo密码,与sudo一起使用
-o 一个主机的执行结果在一行显示
-s -u指定用户的时候,使用sudo获得root权限
-t 将输入放到制定的目录下,命名为每一个主机的名称
-T 超时时长
-B 在后台运行命令,在制定NUM秒后kill该任务
-P 每隔NUM秒,poll一个后台任务 和-B一起使用
-u 指定移动端的执行用户
-U sudo到SUDO_USERNAME,代替root用户
-c 指定建立连接的类型,一般有ssh,localhost FILES
-f 并发进程数量 默认是5

常用模块

ping模块

ansible all -m ping
检测机器是否可登录,ping模块不需要传送参数

command模块 #未指定模块 默认为command 未启动shell

comand模块的参数非key=value格式,直接给出要执行的命令
可以执行任意命令,但不接受管道命令和重定向符号,如果想使用这些,则需要使用Shell模块。

shell | raw 模块

shell调用/bin/sh进行执行命令
raw 没有chdir creates removes 参数
shell 模块,用法其本和command一样,不过的是其是通过/bin/sh进行执行,所以shell 模块可以执行任何命令,就像在本机执行一样

script 模块

# cat a.sh 
#!/bin/bash
if ! $(id lisi > /dev/null) ;then  
    useradd -g 100 zhangsan
    echo 123456| passwd --stdin zhangsan 
    chage -d 0 zhangsan
# ansible all -m script  -a 'a.sh'

script模块,其是将管理端的shell 在被管理主机上执行,其原理是先将shell 复制到远程主机,再在远程主机上执行,原理类似于raw模块

分发配置文件

copy模块

src:要复制到进程主机的文件在本地的地址,可以是
绝对路径,也可以是相对路径。如果路径是一个目录,
它将递归复制。在这种情况下,如果路径使用"/"来结
尾,则只复制目录里的内容,如果没有使用"/"来结尾,
则包含目彔在内的整个内容全部复制,类似于rsync

dest:必选项。进程主机的绝对路径,如果源文件是
一个目录,那么该路径也必须是个目录

复制文件
ansible all -m copy -a 'src=/root/alog dest=/root/a.log'
复制目录
ansible all -m copy -a 'src=urdir dest=/root/'

适合短小的目录与文件的分发

lineinfile 模块

类似于sed的一种行编辑替换模块
path=路径/文件 目的文件
regexp=正则 匹配
line=修改后的该行

# ansible all -m lineinfile -a 'path="/etc/sysconfig/network-scripts/ifcfg-eth0" regexp="^BOOTPROTO=" line="BOOTPROTO=static"'

replace 模块

path=路径/文件 目的文件 修改哪个文件
regexp=正则 匹配 修改哪个地方
replace=替换后的字符 修改成什么样子

#ansible all -m replace -a 'path="/etc/sysconfig/network-scripts/ifcfg-eth0" regexp="^(BOOTPROTO=).*" replace="\1none"'
#ansible all -m replace -a 'path="/etc/selinux/config" regexp="^(SELINUX=).*" replace="\1disabled"'

修改配置文件 相同的用copy 不同的 用linefile|replace

yum 模块

使用yum包管理器来管理软件包
config_file:yum的配置文件
disable_gpg_check:关闭gpg_check
disablerepo:不启用某个源
enablerepo:启用某个源
name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径
state:状态(present,absent,latest) #不写状态默认是安装

删除软件包
ansible all -m yum -a 'name="lrzsz" state=absent'
删除多个软件包
ansible all -m yum -a 'name="lrzsz,lftp" state=absent'
安装软件包
ansible all -m yum -a 'name="lrzsz"'
安装多个软件包
ansible all -m yum -a 'name="lrzsz,lftp"'

file模块

用来设置文件、文件夹或快链的属性,或者删除文件、快链、文件夹。
创建一个文件夹,如果目标不存在
ansible webservers -m file -a "path=/tmp/tdir state=directory mode=0755"

get_url模块

从服务器上下载一个文件到远程主机指定的目录
ansible webservers -m get_url -a "url='http://baidu.com dest=/tmp/ba.html"

service模块

name:必选项,服务名称
enabled:是否开机启动 yes|no
sleep:如果执行了restarted,在则stop和start之间
沉睡几秒钟
state:对当前服务执行启动,停止、重启、重新加载
等操作(started,stopped,restarted,reloaded)
ansible all -m service -a 'name="sshd" enabled="yes" state="started"'

在web1 web2 上安装apache
并且设置开机启动 启动服务 并且把端口改称8080
修改默认主页为hello world

#  vim auto_apache.sh
#!/bin/bash
ansible all -m yum -a 'name="httpd"'
ansible all -m lineinfile -a 'path="/etc/httpd/conf/httpd.conf" regexp="^Listen" line="Listen 8080"'
ansible all -m service -a 'name="httpd" enabled="yes" state="started"'
echo hello world > /root/test.html
ansible all -m copy -a 'src=/root/test.html dest=/var/www/html/index.html'

setup模块

用于获取主机信息
filter 可以过滤到我们需要的信息
ansible t1 -m setup -a 'filter=ansible_distribution'

user模块

-a 'name= state={present(创建)|absent(删除)} force=(是否强制操作删除家目录) system= uid= shell= home='
[root@localhost ~]# ansible all -m user -a 'name=ansible state=present'
user:用户管理模块
常用参数:

name=           #指定用户名(必须指定)
state=present/absent    #添加/删除用户
system=yse/no       #是否创建为系统用户
uid=            #指定用户uid
shell=          #指定用户shell环境
home=           #指定用户家目录
group=          #指定用户组
groups=         #指定用户组附加组,以”,“分隔

例:
ansible web -m user -a  'name=HR state=present system=yes uid=100 groups=root,ntp shell=/bin/csh home=/home/HR_home'

ansible web -m user -a  'name=HR state=absent' #删除用户

批量创建用户和密码时可以使用该命令

ansible host -m shell -a ‘useradd username’
ansible host -m shell -a ‘echo password | passwd username --stdin’

cron模块

计划任务管理模块

    name           #任务计划的描述信息(必须指定)
    minute           #分(0-59 ,* ,*/2)
    hour           #时(0-23 ,* ,*/2)
    day           #日(1-31 ,* ,*/2)
    month           #月(1-12 ,* ,*/2)
    weekday        #周(0-6 ,*)
    job=path           #执行的命令的绝对路径
    backup=yes/no      #是否先备份再创建新的任务计划
    user           #以哪个用户新建任务计划,默认 root
    state=present/absent    #创建删除计划任务

例:

ansible web -m cron -a 'name=A user=root job="/bin/date &>/dev/null" weekday="*/1" state=present'
-a 'name= state= minute= hour= day= month= weekday= job='
[root@localhost ~]# ansible all -m cron -a 'name=Time state=present minute="*/5" job="/usr/sbin/ntpdate 172.168.0.1 &> /dev/null'' '

synchronize模块

目的:将主控方/root/a目录推送到指定节点的/tmp目录下
命令:ansible all -m synchronize -a 'src=/root/a dest=/tmp/ compress=yes'

delete=yes 使两边的内容一样(即以推送方为主)
--exclude=.git 忽略同步.git结尾的文件
由于模块,默认都是推送push。因此,如果你在使用拉取pull功能的时候,可以参考如下来实现
mode=pull 更改推送模式为拉取模式

ansible Playbook

json 数据格式 轻量级数据交换格式 JavaScript 对象表示法
yaml 数据格式
jinja2 数据格式

playbook 由YAML语言编写 遵循YAML标准
由---开始 ansible的命令流

检测所有主机是否连通 \

# vim ping.yml  #创建playbook
---
- hosts: all
  remote_user: root
  tasks:
    - ping:

]# ansible-playbook ping.yml -f 5 #运行playbook
-f 并发进程数量 默认是5
tasks 在对应的所有主机上执行的命令 上一个命令执行完毕后 才会执行下一个命令

实验案例
给所有主机添加plj用户
默认密码为123456
要求第一次登陆修改密码

# vim useradd.yml
---
- hosts: all
  remote_user: root
  tasks:
    - name: create user plj
      user: name=plj groups=users
    - shell: echo 123456 | passwd --stdin plj
    - shell: chage -d 0 plj

选项 -name 给命令做一个简短的注释

playbook 语法进阶

定义变量以及过滤器的使用

# vim useradd.yml
---
- hosts: all
  remote_user: root
  vars:
    username: lx
  tasks:
    - user: name={{username}} groups=users password={{'123456'|password_hash('sha512')}}
    - shell: chage -d 0 {{username}}

ansible-playbook对错误的处理 上一个命令的返回值如果不为0 则中止执行

忽略当前产生的错误

第一种方式:
shell: /usr/bin/somecommand || /bin/true
第二种方式:

- name: run some command
  shell: /usr/bin/somecommand
  ignore_errors: true

handlers 用于当关注的资源发生变化时采取一定的操作

# vim setup_apache.yml

---
- hosts: test
  vars:
    http_port: 80
    servername: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: name=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
  handlers:
  - name: restart apache
    service: name=httpd state=restarted

模板文件

]# sed -n '/^\(Listen\|ServerName\)/p' /srv/httpd.j2
Listen {{http_port}}
ServerName {{servername}}

when 当满足特定条件时 触发操作

register 变量注册 保存某个命令的执行结果

写一个playbook 要求查看web服务器的负载情况 当系统负载大于0.7的时后 停止apache服务
uptime | awk '{printf("%.2f\n",$(NF-2))}' 输出系统负载

#  vim load.yml
---
- hosts: all
  remote_user: root
  tasks:
    - shell: uptime | awk '{printf("%.2f\n",$(NF-2))}'
      register: result
    - service: name=httpd state=stopped
      when: result.stdout|float > 0.7

使用
# awk 'BEGIN{while(1){}}'& 提高系统负载
# watch -n 1 'uptime ;netstat -anptu | grep 80' 同时查看uptime以及apache的运行状态

with_items playbook的标准循环

# vim useradd_item.yml
---
- hosts: all
  remote_user: root
  tasks:
    - user:
        name: "{{item.name}}"
        group: "{{item.group}}"
      with_items:
        - {name: 'nb', group: 'users'}
        - {name: 'dd', group: 'root'}

with_nested 嵌套循环

tag 标签

ansible调试方法

检测语法
ansible-playbook --syntax-check playbook.yaml

测试运行
ansible-playbook -C playbook.yaml

显示收到影响到主机 --list-hosts
显示工作的 task --list-tasks
显示将要运行的 tag --list-tags

debug模块 运行时输出更详细的信息 帮助排错

---
- hosts: 192.168.1.16
  remote_user: root
  tasks:
    - shell: uptime |awk '{printf("%f\n",$(NF-2))}'
      register: result
    - shell: touch /tmp/isreboot
      when: result.stdout|float > 0.5
    - name: Show debug info
      debug: var=result