1.1 ansible安装与配置认证
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。 主要包括: (1)、连接插件connection plugins:负责和被监控端实现通信; (2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机; (3)、各种模块核心模块、command模块、自定义模块; (4)、借助于插件完成记录日志邮件等功能; (5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
特点:
- 不需要安装客户端
- 基于模块工作,模块可以以任何语言开发
- 不仅支持命令行使用模块,也可以支持yaml(python)格式的playbook
- 支持sudo
- 有提供UI(浏览器图形化)
安装
只需在服务端安装(IP:192.168.0.106)。
[root@adailinux ~]# yum install -y epel-release[root@adailinux ~]# yum install -y ansible
配置密钥
创建密钥:[root@adailinux ~]# ssh-keygen Generating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:9f:e7:73:61:9e:af:ea:14:f8:af:82:de:c9:50:06:b0 root@adailinuxThe key's randomart image is:+--[ RSA 2048]----+| . || o || E . || . . || S + . || + o .o || ..o +o o || .+.=..+ || .. +o==oo.|+-----------------+
将公钥拷贝到客户机:
[root@adailinux ~]# cat /root/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuoWwgauteoSamitR+tMXz90nKQJMHJmknTVctIzkJ5YNTdAdHrKBeNiKP3HoODJVkO0Fj3MnWOFHRZtFfzaJ690y846JzKllGmnDcVeaZC6/1Mg3jNVZ7wmtNhMplj+ObJicAOSIoi5bauYPfTQ3F3caCWa/wLBu46pQLu8hCdlKb4TR6t3t+DJqTA5aZz0zrx08YqCZFlv92B+THWhIp0bOd+uJW+ivd38u/FdNaY54z7Qr+S6cQ9Dir5HrG5oWcrd1HbNcHiBrIXXH8t5aQCWJAy0zrG8hfh5d3PJQjo4q7COtj090CAdWIEtT8euz25asnmNmeDdU8CoZkyoiIw== root@adailinux客户机:[root@client ~]# vim .ssh/authorized_keys#ansiblessh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuoWwgauteoSamitR+tMXz90nKQJMHJmknTVctIzkJ5YNTdAdHrKBeNiKP3HoODJVkO0Fj3MnWOFHRZtFfzaJ690y846JzKllGmnDcVeaZC6/1Mg3jNVZ7wmtNhMplj+ObJicAOSIoi5bauYPfTQ3F3caCWa/wLBu46pQLu8hCdlKb4TR6t3t+DJqTA5aZz0zrx08YqCZFlv92B+THWhIp0bOd+uJW+ivd38u/FdNaY54z7Qr+S6cQ9Dir5HrG5oWcrd1HbNcHiBrIXXH8t5aQCWJAy0zrG8hfh5d3PJQjo4q7COtj090CAdWIEtT8euz25asnmNmeDdU8CoZkyoiIw== root@adailinux服务端:[root@adailinux ~]# ssh 192.168.0.109Address 192.168.0.109 maps to bogon, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!Last login: Thu Sep 28 00:49:07 2017 from 192.168.0.106[root@client ~]# 即,106可以登录109机器
ansible远程执行命令
定义主机群组
更改配置文件:[root@adailinux ~]# vim /etc/ansible/hosts# Ex 2: A collection of hosts belonging to the 'webservers' group[testhosts]127.0.0.1192.168.0.109##创建主机组注意,如果要使用127.0.0.1连接本地主机(106)需要将密钥写入本机密钥配置文件:[root@adailinux ~]# vim .ssh/authorized_keys#本地公钥ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuoWwgauteoSamitR+tMXz90nKQJMHJmknTVctIzkJ5YNTdAdHrKBeNiKP3HoODJVkO0Fj3MnWOFHRZtFfzaJ690y846JzKllGmnDcVeaZC6/1Mg3jNVZ7wmtNhMplj+ObJicAOSIoi5bauYPfTQ3F3caCWa/wLBu46pQLu8hCdlKb4TR6t3t+DJqTA5aZz0zrx08YqCZFlv92B+THWhIp0bOd+uJW+ivd38u/FdNaY54z7Qr+S6cQ9Dir5HrG5oWcrd1HbNcHiBrIXXH8t5aQCWJAy0zrG8hfh5d3PJQjo4q7COtj090CAdWIEtT8euz25asnmNmeDdU8CoZkyoiIw== root@adailinux
执行远程命令(ansible模块——command)
执行结果如下:
单个机器:[root@adailinux ~]# ansible 192.168.0.109 -m command -a 'hostname'192.168.0.109 | SUCCESS | rc=0 >>client机器组:[root@adailinux ~]# ansible testhosts -m command -a 'hostname'192.168.0.109 | SUCCESS | rc=0 >>client127.0.0.1 | SUCCESS | rc=0 >>adailinux
说明: -m:指定ansible要调用的模块;-a:指定具体命令。
报错:
"msg" Aborting target uses selinux but python bindings (libselinux-python) aren't installed.
解决办法:
[root@adailinux ~]# yum install -y libselinux-python
ansible模块——shell
[root@adailinux ~]# ansible 192.168.0.109 -m shell -a 'hostname'192.168.0.109 | SUCCESS | rc=0 >>client[root@adailinux ~]# ansible 192.168.0.109 -m shell -a 'cat /etc/passwd|grep root'192.168.0.109 | SUCCESS | rc=0 >>root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin
注: command模块和shell模块的区别是:shell模块支持“管道符”及脚本。
ansible拷贝文件或目录
使用copy模块。
[root@adailinux ~]# ansible 192.168.0.109 -m copy -a "src=/tmp/test.txt dest=/tmp/testdir/ owner=root group=root mode=0644"192.168.0.109 | SUCCESS => { "changed": true, "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "dest": "/tmp/testdir/test.txt", "gid": 0, "group": "root", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "mode": "0644", "owner": "root", "size": 0, "src": "/root/.ansible/tmp/ansible-tmp-1506533297.89-81185506773616/source", "state": "file", "uid": 0}#此处IP可以换成机器组:testhosts“客户机:[root@client ~]# ls /tmp/testdir
注意: 源文件或目录会放到目标目录下面。src表示源地址,dest表示目标地址
远程执行脚本
服务端:192.168.8.141
客户端:192.168.8.142[root@adailinux ~]# vim /etc/ansible/hosts[testhosts]127.0.0.1192.168.8.142
创建脚本:[root@adailinux ~]# vim /tmp/test.sh#!/bin/bashd=`date`echo $d > /tmp/an_test.txt分发脚本;[root@adailinux ~]# ansible testhosts -m copy -a "src=/tmp/test.sh dest=/tmp/test.sh mode=0755"远程执行脚本:[root@adailinux ~]# ansible testhosts -m shell -a "/bin/sh /tmp/test.sh"192.168.8.142 | SUCCESS | rc=0 >>127.0.0.1 | SUCCESS | rc=0 >>在客户机查看:[root@client ~]# ls /tmp/an_test.txt test.sh[root@client ~]# cat /tmp/an_test.txt2017年 09月 28日 星期四 05:30:25 CST
ansible实现任务计划
创建计划任务:
[root@adailinux ~]# ansible 192.168.8.142 -m cron -a "name='test cron' job='/bin/touch /tmp/110.txt' weekday=6"192.168.8.142 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "test cron" ]}查看客户机:[root@client ~]# crontab -l#Ansible: test cron* * * * 6 /bin/touch /tmp/110.txt时间:分钟minute 小时hour 日day 月份month
删除计划任务:
只需加上参数——“state=absent”[root@adailinux ~]# ansible 192.168.8.142 -m cron -a "name='test cron' job='/bin/touch /tmp/110.txt' weekday=6 state=absent"192.168.8.142 | SUCCESS => { "changed": true, "envs": [], "jobs": []}客户机:[root@client ~]# crontab -l
ansible安装rpm包&&管理服务
安装rpm包
[root@adailinux ~]# ansible 192.168.8.142 -m yum -a "name=zabbix-agent.i686"
注意: name后面需要跟一个准确的包名。
管理服务
[root@adailinux ~]# ansible 192.168.8.142 -m service -a "name=httpd state=started enable=no"
列出所有模块:[root@adailinux ~]# ansible-doc -l查看指定模块的参数:[root@adailinux ~]# ansible-doc cron
ansible playbook
相当于把模块写入到配置文件里面,然后单独执行配置文件实现自动化操作。
创建文件
[root@jumpserver ~]# vim /etc/ansible/test.yml---- hosts: 192.168.8.130 remote_user: root tasks: - name: test_playbook shell: touch /tmp/test.txt
说明: hosts参数指定了对哪些主机进行操作;user参数指定了使用什么用户登录远程主机操作;tasks指定了一个任务,其下面的name参数同样是对任务的描述,在执行过程中会打印出来。
定义完成后只需要执行命令:
[root@jumpserver ~]# ansible-playbook test.ymlPLAY [192.168.8.130] ************************************************************************TASK [Gathering Facts] **********************************************************************ok: [192.168.8.130]TASK [test_playbook] ************************************************************************ [WARNING]: Consider using file module with state=touch rather than running touchchanged: [192.168.8.130]PLAY RECAP **********************************************************************************192.168.8.130 : ok=2 changed=1 unreachable=0 failed=0 查看客户机:[root@localhost ~]# ls /tmp/test.txt
即可完成所有配置。
创建用户
[root@jumpserver ansible]# vim create_user.yml---- name: create_user hosts: 192.168.8.130 user: root gather_facts: false vars: - user: "test" tasks: - name: create user user: name="{ { user }}"
说明: name参数对该playbook实现的功能做一个概述,后面执行过程中,会打印 name变量的值 ,可以省略;gather_facts参数指定了在以下任务部分执行前,是否先执行setup模块获取主机相关信息,这在后面的task会使用到setup获取的信息时用到;vars参数,指定了变量,这里指字一个user变量,其值为test ,需要注意的是,变量值一定要用引号引住;user提定了调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。
循环with_items:
---- hosts: testhost user: root tasks: - name: change mod for file file: path=/tmp/{ { item }} mode=600 owner=root group=root with_items: - 1.txt - 2.txt
说明: with_items 就是循环的关键
条件when:
---- hosts: testhost remote_user: root gather_facts: True tasks: - name: use when shell: touch /tmp/when.txt when: facter_ipaddress == "172.7.15.106"
模块handlers:
执行task之后,服务器发生变化之后要执行的一些操作,比如我们修改了配置文件后,需要重启一下服务,具体示例:
---- hosts: testhost remote_user: root tasks: - name: test copy copy: src=/tmp/1.txt dest=/tmp/2.txt notify: test handlers handlers: - name: test handlers shell: echo "121212" >> /tmp/2.txt
说明,只有copy模块真正执行后,才会去调用下面的handlers相关的操作。也就是说如果1.txt和2.txt内容是一样的,并不会去执行handlers里面的shell相关命令。这种比较适合配置文件发生更改后,重启服务的操作。
实例:安装ansible
因为换了机器,所以重新安装ansible并进行配置。
机器 | IP |
---|---|
server(centos7) | 192.168.8.139 |
client(centos7) | 192.168.8.130 |
server机器上编译安装好nginx。
使用ansible源码安装nginx
思路:
先在一台机器上安装好nginx,然后打包,再利用ansible分发下去;或者直接把/usr/local/nginx目录同步到其他机器。 需要注意的是编译安装的nginx会需要一些库文件,所以再同步之后还要在client机器上yum安装这些包。准备工作
[root@jumpserver conf]# cd /usr/local/打包:[root@jumpserver local]# tar czf nginx.tar.gz nginx[root@jumpserver local]# lsbin etc games include lib lib64 libexec nginx nginx.tar.gz sbin share src创建一系列目录:[root@jumpserver local]# cd /etc/ansible/[root@jumpserver ansible]# lsansible.cfg hosts roles[root@jumpserver ansible]# mkdir nginx_install[root@jumpserver ansible]# cd nginx_install/[root@jumpserver nginx_install]# mkdir roles[root@jumpserver nginx_install]# cd roles/[root@jumpserver roles]# mkdir common install#common:用于做前期准备工作(准备一些依赖的包)
定义common内的目录及文件:
[root@jumpserver roles]# cd common/[root@jumpserver common]# mkdir tasks[root@jumpserver common]# cd tasks/[root@jumpserver tasks]# vim main.yml- name: Install initializtion require software yum: name={ { item }} state=installed with_items: - zlib-devel - pcre-devel - openssl-devel
定义install内的目录及文件:
[root@jumpserver install]# pwd/etc/ansible/nginx_install/roles/install[root@jumpserver install]# mkdir tasks vars files templates[root@jumpserver install]# cp /usr/local/nginx.tar.gz files/说明: 我们需要把源码包放到 files目录里面[root@jumpserver install]# cp /usr/local/nginx/conf/nginx.conf templates/[root@jumpserver install]# cp /etc/init.d/nginx templates/[root@jumpserver install]# vim vars/main.ymlnginx_user: wwwnginx_basedir: /usr/local/nginx#指定解压后文件存放目录
说明: 需要再templates下面准备好 默认页、安装nginx的shell脚本、nginx启动脚本、nginx配置文件以及虚拟主机配置文件
[root@jumpserver install]# cd tasks/[root@jumpserver tasks]# vim copy.yml- name: Copy Nginx Software copy: src=nginx.tar.gz dest=/tmp/nginx.tar.gz owner=root group=root- name: Uncompression Nginx Software shell: tar zxf /tmp/nginx.tar.gz -C /usr/local/- name: Copy Nginx Start Script template: src=nginx dest=/etc/init.d/nginx owner=root group=root mode=0755- name: Copy Nginx Config template: src=nginx.conf dest={ { nginx_basedir }}/conf/ owner=root group=root mode=0644
说明: 首先把压缩包拷贝到/tmp/目录下,然后解压到/usr/local/下,再拷贝启动脚本到/etc/init.d/下,再拷贝nginx.conf以及vhost.conf
[root@jumpserver tasks]# vim install.yml- name: Create Nginx User user: name={ { nginx_user }} state=present createhome=no shell=/sbin/nologin- name: Start Nginx Service service: name=nginx state=stopped- name: Add Boot Start Nginx Service shell: chkconfig --level 345 nginx on- name: Delete Nginx compression files shell: rm -rf /tmp/nginx.tar.gz[root@jumpserver tasks]# vim main.yml- include: copy.yml- include: install.yml
说明: roles目录下有三个角色,common为一些准备操作,install为安装nginx的操作;每个角色下面又有几个目录,handlers下面是当发生改变时要执行的操作,通常用在配置文件发生改变,重启服务。files为安装时用到的一些文件,meta为说明信息,说明角色依赖等信息,tasks里面是核心的配置文件,templates通常存一些配置文件,启动脚本等模板文件,vars下为定义的变量。
至此,两个roles:common和install定义完成,接下来定义一个文件入口。定义入口文件
[root@jumpserver tasks]# cd /etc/ansible/nginx_install/[root@jumpserver nginx_install]# vim install.yml---- hosts: 192.168.8.130 remote_user: root gather_facts: True roles: - common - install
执行
[root@jumpserver nginx_install]# pwd/etc/ansible/nginx_install[root@jumpserver nginx_install]# ansible-playbook install.ymlPLAY [192.168.8.130] ************************************************************************TASK [Gathering Facts] **********************************************************************ok: [192.168.8.130]TASK [common : Install initializtion require software] **************************************ok: [192.168.8.130] => (item=[u'zlib-devel', u'pcre-devel', u'openssl-devel'])TASK [install : Copy Nginx Software] ********************************************************changed: [192.168.8.130]TASK [install : Uncompression Nginx Software] *********************************************** [WARNING]: Consider using unarchive module rather than running tarchanged: [192.168.8.130]TASK [install : Copy Nginx Start Script] ****************************************************ok: [192.168.8.130]TASK [install : Copy Nginx Config] **********************************************************ok: [192.168.8.130]TASK [install : Create Nginx User] **********************************************************ok: [192.168.8.130]TASK [install : Start Nginx Service] ********************************************************ok: [192.168.8.130]TASK [install : Add Boot Start Nginx Service] ***********************************************changed: [192.168.8.130]TASK [install : Delete Nginx compression files] ********************************************* [WARNING]: Consider using file module with state=absent rather than running rmchanged: [192.168.8.130]PLAY RECAP **********************************************************************************192.168.8.130 : ok=10 changed=4 unreachable=0 failed=0 查看客户机:[root@localhost ~]# ps aux |grep nginxroot 10791 0.0 0.1 20488 628 ? Ss 19:41 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.confnobody 10794 0.0 0.6 22932 3212 ? S 19:41 0:00 nginx: worker processnobody 10795 0.0 0.6 22932 3212 ? S 19:41 0:00 nginx: worker processroot 13242 0.0 0.1 112668 968 pts/0 R+ 19:46 0:00 grep --color=auto nginx
配置成功!!!
参考
官方文档
安装配置 常见错误 样例库:ansible常用命令及参数
参数: -a 'Arguments', --args='Arguments' 命令行参数 -m NAME, --module-name=NAME 执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数 -i PATH, --inventory=PATH 指定库存主机文件的路径,默认为/etc/ansible/hosts. -u Username, --user=Username 执行用户,使用这个远程用户名而不是当前用户 -U --sud-user=SUDO_User sudo到哪个用户,默认为 root -k --ask-pass 登录密码,提示输入SSH密码而不是假设基于密钥的验证 -K --ask-sudo-pass 提示密码使用sudo -s --sudo sudo运行 -S --su 用 su 命令 -l --list 显示所支持的所有模块 -s --snippet 指定模块显示剧本片段 -f --forks=NUM 并行任务数。NUM被指定为一个整数,默认是5。 #ansible testhosts -a "/sbin/reboot" -f 10 重启testhosts组的所有机器,每次重启10台 --private-key=PRIVATE_KEY_FILE 私钥路径,使用这个文件来验证连接 -v --verbose 详细信息 all 针对hosts 定义的所有主机执行 -M MODULE_PATH, --module-path=MODULE_PATH 要执行的模块的路径,默认为/usr/share/ansible/ --list-hosts 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook 文件 -o --one-line 压缩输出,摘要输出.尝试一切都在一行上输出。 -t Directory, --tree=Directory 将内容保存在该输出目录,结果保存在一个文件中在每台主机上。 -B 后台运行超时时间 -P 调查后台程序时间 -T Seconds, --timeout=Seconds 时间,单位秒s -P NUM, --poll=NUM 调查背景工作每隔数秒。需要- b -c Connection, --connection=Connection 连接类型使用。可能的选项是paramiko(SSH),SSH和地方。当地主要是用于crontab或启动。 --tags=TAGS 只执行指定标签的任务 例子:ansible-playbook test.yml --tags=copy 只执行标签为copy的那个任务 --list-hosts 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook 文件 --list-tasks 列出所有将被执行的任务 -C, --check 只是测试一下会改变什么内容,不会真正去执行;相反,试图预测一些可能发生的变化 --syntax-check 执行语法检查的剧本,但不执行它 -l SUBSET, --limit=SUBSET 进一步限制所选主机/组模式 --limit=192.168.0.15 只对这个ip执行 --skip-tags=SKIP_TAGS 只运行戏剧和任务不匹配这些值的标签 --skip-tags=copy_start -e EXTRA_VARS, --extra-vars=EXTRA_VARS 额外的变量设置为键=值或YAML / JSON #cat update.yml --- - hosts: { { hosts }} remote_user: { { user }} .............. #ansible-playbook update.yml --extra-vars "hosts=vipers user=admin" 传递{ {hosts}}、{ {user}}变量,hosts可以是 ip或组名 -l,--limit 对指定的 主机/组 执行任务 --limit=192.168.0.10,192.168.0.11 或 -l 192.168.0.10,192.168.0.11 只对这个2个ip执行任务
配置sudo用户
---- hosts: all vars: user: test password: "$6$rounds=100000$O2BHfT2XIF6oDb9w$8Hhv4vOrLN6JF/nRVYDd8zZdnn9TNkQutyYYywIcPF2kRiHgkwAjqHIN7sDUkd1DcjLRABWT9ULHZPBOF2bZS/" remote_user: root tasks: - name: Add user { { user }} user: name={ {user}} comment="ceph user" password={ { password }} - name: Config /etc/sudoers lineinfile: dest=/etc/sudoers state=present line='{ {item}}' validate='visudo -cf %s' with_items: - "{ { user}} ALL=(ALL) NOPASSWD: ALL" - "Defaults: { {user}} !requiretty"
此playbook将添加一个具有sudo权限的 test 用户 密码为password
更改用户只用更改vars:中的user 即可
生成密码:
$ pip install passlibpython -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"
输入密码后确认
会生成一长串字符替换playbook中的即可