Ansible自动化运维配置与应用(结合实例)

2019-04-03 10:57:40 浏览数 (1)

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)。

代码语言:javascript复制
[root@adailinux ~]# yum install -y epel-release
[root@adailinux ~]# yum install -y ansible

配置密钥

代码语言:javascript复制
创建密钥:
[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@adailinux
The key's randomart image is:
 --[ RSA 2048]---- 
|      .          |
|       o         |
|      E .        |
|         . .     |
|        S   .    |
|           o .o  |
|        ..o  o o |
|        . .=..   |
|       ..  o==oo.|
 ----------------- 

将公钥拷贝到客户机:

代码语言:javascript复制
[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
#ansible
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAuoWwgauteoSamitR tMXz90nKQJMHJmknTVctIzkJ5YNTdAdHrKBeNiKP3HoODJVkO0Fj3MnWOFHRZtFfzaJ690y846JzKllGmnDcVeaZC6/1Mg3jNVZ7wmtNhMplj ObJicAOSIoi5bauYPfTQ3F3caCWa/wLBu46pQLu8hCdlKb4TR6t3t DJqTA5aZz0zrx08YqCZFlv92B THWhIp0bOd uJW ivd38u/FdNaY54z7Qr S6cQ9Dir5HrG5oWcrd1HbNcHiBrIXXH8t5aQCWJAy0zrG8hfh5d3PJQjo4q7COtj090CAdWIEtT8euz25asnmNmeDdU8CoZkyoiIw== root@adailinux

服务端:
[root@adailinux ~]# ssh 192.168.0.109
Address 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远程执行命令

定义主机群组
代码语言:javascript复制
更改配置文件:
[root@adailinux ~]# vim /etc/ansible/hosts
# Ex 2: A collection of hosts belonging to the 'webservers' group
[testhosts]
127.0.0.1
192.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)

执行结果如下:

代码语言:javascript复制
单个机器:
[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 >>
client

127.0.0.1 | SUCCESS | rc=0 >>
adailinux

说明: -m:指定ansible要调用的模块;-a:指定具体命令。

报错:

代码语言:javascript复制
"msg" Aborting target uses selinux but python bindings (libselinux-python) aren't installed.

解决办法:

代码语言:javascript复制
[root@adailinux ~]# yum install -y libselinux-python
ansible模块——shell
代码语言:javascript复制
[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/bash
operator:x:11:0:operator:/root:/sbin/nologin

注: command模块和shell模块的区别是:shell模块支持“管道符”及脚本。

ansible拷贝文件或目录

使用copy模块。

代码语言:javascript复制
[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

代码语言:javascript复制
[root@adailinux ~]# vim /etc/ansible/hosts
[testhosts]
127.0.0.1
192.168.8.142
代码语言:javascript复制
创建脚本:
[root@adailinux ~]# vim /tmp/test.sh
#!/bin/bash
d=`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.txt
2017年 09月 28日 星期四 05:30:25 CST

ansible实现任务计划

创建计划任务:

代码语言:javascript复制
[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”

代码语言:javascript复制
[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包
代码语言:javascript复制
[root@adailinux ~]# ansible 192.168.8.142 -m yum -a "name=zabbix-agent.i686"

注意: name后面需要跟一个准确的包名。

管理服务
代码语言:javascript复制
[root@adailinux ~]# ansible 192.168.8.142 -m service -a "name=httpd state=started enable=no"
代码语言:javascript复制
列出所有模块:
[root@adailinux ~]# ansible-doc -l

查看指定模块的参数:
[root@adailinux ~]# ansible-doc cron

ansible playbook

相当于把模块写入到配置文件里面,然后单独执行配置文件实现自动化操作。

创建文件

代码语言:javascript复制
[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参数同样是对任务的描述,在执行过程中会打印出来。

定义完成后只需要执行命令:

代码语言:javascript复制
[root@jumpserver ~]# ansible-playbook test.yml

PLAY [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 touch

changed: [192.168.8.130]

PLAY RECAP **********************************************************************************
192.168.8.130              : ok=2    changed=1    unreachable=0    failed=0  

查看客户机:
[root@localhost ~]# ls /tmp/
test.txt

即可完成所有配置。

创建用户

代码语言:javascript复制
[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:

代码语言:javascript复制
---
- 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:

代码语言:javascript复制
---
- 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之后,服务器发生变化之后要执行的一些操作,比如我们修改了配置文件后,需要重启一下服务,具体示例:

代码语言:javascript复制
---
- 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安装这些包。

准备工作

代码语言:javascript复制
[root@jumpserver conf]# cd /usr/local/

打包:
[root@jumpserver local]# tar czf nginx.tar.gz nginx
[root@jumpserver local]# ls
bin  etc  games  include  lib  lib64  libexec  nginx  nginx.tar.gz  sbin  share  src

创建一系列目录:
[root@jumpserver local]#  cd /etc/ansible/
[root@jumpserver ansible]# ls
ansible.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内的目录及文件:
代码语言:javascript复制
[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内的目录及文件:
代码语言:javascript复制
[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.yml
nginx_user: www
nginx_basedir: /usr/local/nginx
#指定解压后文件存放目录

说明: 需要再templates下面准备好 默认页、安装nginx的shell脚本、nginx启动脚本、nginx配置文件以及虚拟主机配置文件

代码语言:javascript复制
[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

代码语言:javascript复制
[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定义完成,接下来定义一个文件入口。

定义入口文件
代码语言:javascript复制
[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

执行

代码语言:javascript复制
[root@jumpserver nginx_install]# pwd
/etc/ansible/nginx_install

[root@jumpserver nginx_install]# ansible-playbook install.yml

PLAY [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 tar

changed: [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 rm

changed: [192.168.8.130]

PLAY RECAP **********************************************************************************
192.168.8.130              : ok=10   changed=4    unreachable=0    failed=0 


查看客户机:
[root@localhost ~]# ps aux |grep nginx
root     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.conf
nobody   10794  0.0  0.6  22932  3212 ?        S    19:41   0:00 nginx: worker process
nobody   10795  0.0  0.6  22932  3212 ?        S    19:41   0:00 nginx: worker process
root     13242  0.0  0.1 112668   968 pts/0    R    19:46   0:00 grep --color=auto nginx

配置成功!!!

参考

官方文档 http://docs.ansible.com/ansible/ 安装配置 http://sofar.blog.51cto.com/353572/1579894 常见错误 http://afewbug.com/article/26 样例库:https://github.com/dl528888/ansible-examples

ansible常用命令及参数

代码语言:javascript复制
参数:
  -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用户

代码语言:javascript复制
---
- 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 即可

生成密码:

代码语言:javascript复制
$ pip install passlib
python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"

输入密码后确认

会生成一长串字符替换playbook中的即可

(adsbygoogle = window.adsbygoogle || []).push({});

0 人点赞