系统运维

自动化运维工具Ansible

一、简介

ansible是基于python开发的最新出现的自动化运维工具,集合了众多的运维工具的优点,可以实现批量的系统配置、程序部署、批量运行命令等等。ansible是基于模块工作的,本身无法批量部署。ansible本身只是提供一种框架。主要包含:

1.连接插件connection plugins: 负责和被监控端实现通信;

2.host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;

3.各种模块核心模块、command模块、自定义模块;

4.借助于插件完成记录日志邮件等功能;

5.playbook:剧本执行多个任务时,非必须可以让节点一次运行多个任务。

二、特性

1.部署简单、快捷、方便;

2.支持Linux/UNIX及windows环境;

3.集中化管理;

4.配置简单、功能强大、可扩展性强;

5.主控制端和被控制端基于证书认证,安全可靠;

6.支持API及自定义模块、可通过python轻松扩展。

 

总体架构

执行过程

三、优点

1.轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可

2.批量任务执行可以写成脚本,而且不用分发到远程就可以执行

3.使用python编写,维护更简单

4.使用push方式,控制节点向其他节点推方式,可先测试变更,方便控制管理

 

四、Ansible安装部署与配置

主机名 IP
 testa  10.10.10.1
 testb  10.10.10.2
 testc  10.10.10.3

4.1 Ansible安装

安装可使用源码编译安装,也可以更新yum源后使用yum安装

yum安装:

rpm -ivh http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install ansible -y

定义Host Inventory

添加组名及允许执行命令的主机

vim  /etc/ansible/hosts
[agent]
10.10.10.2
10.10.10.3

设置/etc/ansible/ansible.cfg参数

inventory =/etc/ansible/hosts             #定义资源清单inventory文件的位置,一般保持默认
library =/usr/share/my_modules/           #library指向ansible模块的目录,一般保持默认
forks =10                                 #设置多少个进程同时工作
sudo_user=root                            #设置默认执行命令的用户,也可在playbook中重新设置此参数
remote_port=22                            #制定连接被管理的管理端口,默认为22
timeout =10                               #设置SSH连接的超时时间间隔,单位为秒

各主机SSH互信

ssh-keygen -t rsa    #创建公钥与密钥
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.10.10.2
[root@testa ~]# ssh-keygen -t rsa
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:
21:d3:39:46:9d:ec:8a:c7:f2:e3:75:7e:62:73:f0:95 root@i-78p1k0qz
The key's randomart image is:
+--[ RSA 2048]----+
|        .o .     |
|       o .+      |
|      o *.       |
|       + o.      |
|       oS.      .|
|      o +   .  E.|
|       +  . .o . |
|        o. o+ +  |
|       ... ..=   |
+-----------------+
[root@testa ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.10.10.2
Warning: Permanently added '10.10.10.2' (RSA) to the list of known hosts.
root@10.10.10.2's password: 
Now try logging into the machine, with "ssh 'root@10.10.10.2'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

[root@testa ~]#

此时testa已经可以免密登录testb服务器

[root@testa ~]# ssh root@10.10.10.2
Warning: Permanently added '10.10.10.2' (RSA) to the list of known hosts.
Last login: Tue Oct 31 10:10:06 2017 from 103.20.249.250
[root@testb ~]# 
[root@testb ~]# 
[root@testb ~]# 
[root@testb ~]# ifconfig 
eth0      Link encap:Ethernet  HWaddr 52:54:ED:67:47:F4  
          inet addr:10.57.119.36  Bcast:10.57.119.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:edff:fe67:47f4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:24383 errors:0 dropped:0 overruns:0 frame:0
          TX packets:14676 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:28910021 (27.5 MiB)  TX bytes:1157373 (1.1 MiB)

eth1      Link encap:Ethernet  HWaddr 52:54:6A:F8:23:BC  
          inet addr:10.10.10.2  Bcast:10.10.10.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:6aff:fef8:23bc/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:128 errors:0 dropped:0 overruns:0 frame:0
          TX packets:82 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:24274 (23.7 KiB)  TX bytes:15686 (15.3 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

[root@testb ~]# 

同样方式,如何控制端为testb需要将testb的公钥发布到testa主机,实现互信

 

4.2命令参数介绍

 [root@testa ~]# ansible -h
Usage: ansible <host-pattern> [options]

Options:
  -a MODULE_ARGS, --args=MODULE_ARGS    模块的参数,如果执行默认COMMAND的模块,即是命令参数,如:“date”,"pwd"等等
                        module arguments    模块参数
  -k, --ask-pass        ask for SSH password  登录密码,提示输入SSH密码而不是假设基于密钥的验证
  --ask-su-pass         ask for su password    su切换密码
  -K, --ask-sudo-pass   ask for sudo password  提示密码使用sudo,sudo表示提权操作
  --ask-vault-pass      ask for vault password
  -B SECONDS, --background=SECONDS     后台运行超时时间
                        run asynchronously, failing after X seconds
                        (default=N/A)
  -C, --check           don't make any changes; instead, try to predict some    只是测试一下会改变什么内容,不会真正去执行;相反,试图预测一些可能发生的变化
                        of the changes that may occur
  -c CONNECTION, --connection=CONNECTION   连接类型使用。可能的选项是paramiko(SSH),SSH和地方。当地主要是用于crontab或启动。
                        connection type to use (default=smart)
  -f FORKS, --forks=FORKS   并行任务数。NUM被指定为一个整数,默认是5
                        specify number of parallel processes to use
                        (default=5)
  -h, --help            show this help message and exit   打开帮助文档API
  -i INVENTORY, --inventory-file=INVENTORY    指定库存主机文件的路径,默认为/etc/ansible/hosts
                        specify inventory host file
                        (default=/etc/ansible/hosts)
  -l SUBSET, --limit=SUBSET    进一步限制所选主机/组模式  --limit=192.168.91.135 只对这个ip执行
                        further limit selected hosts to an additional pattern
  --list-hosts          outputs a list of matching hosts; does not execute
                        anything else
  -m MODULE_NAME, --module-name=MODULE_NAME   执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
                        module name to execute (default=command)
  -M MODULE_PATH, --module-path=MODULE_PATH    要执行的模块的路径,默认为/usr/share/ansible/
                        specify path(s) to module library
                        (default=/usr/share/ansible/)
  -o, --one-line        condense output      压缩输出,摘要输出.尝试一切都在一行上输出。
  -P POLL_INTERVAL, --poll=POLL_INTERVAL    调查背景工作每隔数秒。需要- b
                        set the poll interval if using -B (default=15)
  --private-key=PRIVATE_KEY_FILE    私钥路径,使用这个文件来验证连接
                        use this file to authenticate the connection
  -S, --su              run operations with su    用 su 命令
  -R SU_USER, --su-user=SU_USER      指定SU的用户,默认是root用户
                        run operations with su as this user (default=root)
  -s, --sudo            run operations with sudo (nopasswd)    
  -U SUDO_USER, --sudo-user=SUDO_USER    sudo到哪个用户,默认为 root  
                        desired sudo user (default=root)
  -T TIMEOUT, --timeout=TIMEOUT    指定SSH默认超时时间,  默认是10S
                        override the SSH timeout in seconds (default=10)
  -t TREE, --tree=TREE  log output to this directory     将日志内容保存在该输出目录,结果保存在一个文件中在每台主机上。
  -u REMOTE_USER, --user=REMOTE_USER    远程用户, 默认是root用户
                        connect as this user (default=root)
  --vault-password-file=VAULT_PASSWORD_FILE  
                        vault password file
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable    详细信息
                        connection debugging)
  --version             show program's version number and exit   输出ansible的版本

4.3测试

ansible agent -m shell -a "touch /tmp/666" -vvv
#-m  使用command模块  -a 使用command里面支持的命令参数 -vvv 查看详细过程
[root@testa ~]# ansible agent -m shell -a "uptime" 
10.10.10.2 | SUCCESS | rc=0 >>
 14:48:22 up  4:43,  2 users,  load average: 0.00, 0.00, 0.00

10.10.10.3 | SUCCESS | rc=0 >>
 14:48:22 up  4:43,  2 users,  load average: 0.00, 0.00, 0.00

[root@testa ~]# 
[root@testa ~]# ansible agent -m shell -a "ifconfig"
10.10.10.2 | SUCCESS | rc=0 >>
eth0      Link encap:Ethernet  HWaddr 52:54:ED:67:47:F4  
          inet addr:10.57.119.36  Bcast:10.57.119.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:edff:fe67:47f4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:41876 errors:0 dropped:0 overruns:0 frame:0
          TX packets:21901 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:30210096 (28.8 MiB)  TX bytes:1857669 (1.7 MiB)

eth1      Link encap:Ethernet  HWaddr 52:54:6A:F8:23:BC  
          inet addr:10.10.10.2  Bcast:10.10.10.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:6aff:fef8:23bc/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3331 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2154 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2132493 (2.0 MiB)  TX bytes:315219 (307.8 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

10.10.10.3 | SUCCESS | rc=0 >>
eth0      Link encap:Ethernet  HWaddr 52:54:76:1A:CE:42  
          inet addr:10.57.88.216  Bcast:10.57.88.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:76ff:fe1a:ce42/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:37584 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23832 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:30035920 (28.6 MiB)  TX bytes:1990709 (1.8 MiB)

eth1      Link encap:Ethernet  HWaddr 52:54:92:16:7A:C1  
          inet addr:10.10.10.3  Bcast:10.10.10.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:92ff:fe16:7ac1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3021 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1932 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2102816 (2.0 MiB)  TX bytes:287694 (280.9 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:168 (168.0 b)  TX bytes:168 (168.0 b)

[root@testa ~]# 

五、模块介绍

【copy】模块
ansible agent -m copy -a "src=/root/test.sh dest=/tmp"
【file】
调用-s 参数,需要客户端能够无密码使用sudo命令;
ansible agent -m file -a "dest=/tmp/test.sh mode=755 owner=root group=root" -s
【script】
ansible agent -m script -a "/tmp/test.sh"
【shell】创建用户
ansible agent -m shell -a "/tmp/test.sh" 
【group】创建组
ansible agent -m group -a "name=test1 state=present" -s
【user】
ansible agent -m user -a "name=xuel home=/home/xuel state=present" -s
【yum】
可以提供的status:absent,present,installed,removed,latest
ansible agent -m yum -a "name=httpd state=latest" -s
【server】
可以提供的status:running,started,stopped,restarted,reloaded
【cron】
ansible agent -m cron -a 'name="my job" minute=*/1 hour=* day=* month=* weekday=* job="/usr/sbin/ntpdate time1.aliyun.com"'
【get_url】
ansible agent -m get_url -a "url=http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm dest=/tmp"
【synchronize】需要安装rsync
ansible agent -m synchronize -a "src=/root/test.file dest=/tmp"
模块默认使用的为推送push,如果想使用pull功能需添加mode=pull
ansible agent -m synchronize -a "mode=pull src=/tmp/test.file dest=/root/"
【ini_file】 
ansible agent -m ini_file -a "dest=/tmp/test.ini section=Mongo option=Host value=127.0.0.1"
该模块Python需要安装ConfigParser

六、Ansible-playbook介绍

核心组件

hosts             #执行的远程主机列表
tasks             #任务集
varniables        #内置变量或自定义变量
templates         #可替换模版
handlers          #触发操作
playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。  
从根本上来讲所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中即可以让它们联同起来按事先编排的机制同唱一台大戏。  
   
###########################playbook基础组件  
1、Hosts和Users  
   
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。  
hosts用于指定要执行指定任务的主机其可以是一个或多个由冒号分隔主机组。  
remote_user则用于指定远程主机上的执行任务的用户。  
   
不过remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务其可用于play全局或某任务。  
此外甚至可以在sudo时使用sudo_user指定sudo时切换的用户。  
   
- hosts: webnodes  
remote_user: mageedu  
tasks:  
- name: test connection ping:  
remote_user: mageedu sudo: yes  
   
2、任务列表和action  
play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行即在所有主机上完成第一个任务后再开始第二个。  
在运行自下而下某playbook时如果中途发生错误所有已执行任务都将回滚因此在更正playbook后重新执行一次即可。  
task的目的是使用指定的参数执行模块而在模块参数中可以使用变量。模块执行是幂等的这意味着多次执行是安全的因为其结果均一致。  
每个task都应该有其name用于playbook的执行结果输出建议其内容尽可能清晰地描述任务执行步骤。如果未提供name则action的结果将用于输出。  
   
定义task的可以使用“action: module options”或“module: options”的格式推荐使用后者以实现向后兼容。  
如果action一行的内容过多也中使用在行首使用几个空白字符进行换行。  
   
tasks:  
- name: make sure apache is running  
service: name=httpd state=running 
   
在众多模块中只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式例如  
tasks:  
- name: disable selinux  
command: /sbin/setenforce 0如果命令或脚本的退出码不为零可以使用如下方式替代  
tasks:  
- name: run this command and ignore the result  
shell: /usr/bin/somecommand || /bin/true  
或者使用ignore_errors来忽略错误信息  
tasks:  
- name: run this command and ignore the result  
shell: /usr/bin/somecommand  
ignore_errors: True   
   
3、handlers  
   
用于当关注的资源发生变化时采取一定的操作。  
   
“notify”这个action可用于在每个play的最后被触发这样可以避免多次有改变发生时每次都执行指定的操作取而代之仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler也即notify中调用handler中定义的操作。  
   
- name: template configuration file  
template: src=template.j2 dest=/etc/foo.conf  
notify:  
- restart memcached  
- restart apache   
   
handler是task列表这些task与前述的task并没有本质上的不同。  
   
handlers:  
- name: restart memcached  
service: name=memcached state=restarted 
- name: restart apache  
service: name=apache state=restarted

命令

Usage: ansible-playbook playbook.yml
ansible-playbook test1.yml             #执行剧本
ansible-vault encrypt test1.yml         #加密剧本
ansible-vault decrypt test1.yml         #加密剧本
ansible-vault view test1.yml            #加密剧本

YAML简介

YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言包括XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言另外Ingy dtNet与Oren Ben-Kiki也是这语言的共同设计者。  
YAML Ain't Markup Language即YAML不是XML。不过在开发的这种语言时YAML的意思其实是"Yet Another Markup Language"仍是一种标记语言。其特性  
YAML的可读性好  
YAML和脚本语言的交互性好  
YAML使用实现语言的数据类型  
YAML有一个一致的信息模型  
YAML易于实现  
YAML可以基于流来处理  
YAML表达能力强扩展性好  
  
   
##########################YAML语法  
   
YAML的语法和其他高阶语言类似并且可以简单表达清单、散列表、标量等数据结构。其结构Structure通过空格来展示序列Sequence里的项用"-"来代表  
Map里的键值对用":"分隔。YAML文件扩展名通常为.yaml或者.yml。下面是一个示例。  
   
name: John Smith  
age: 41gender: Male  
spouse:  
name: Jane Smith  
age: 37  
gender: Female  
children:  
- name: Jimmy Smith  
age: 17  
gender: Male  
- name: Jenny Smith  
age 13  
gender: Female  
   
YAML 2 个重要的结构组成部分list和directory  
################################# list  
   
列表的所有元素均使用“-”打头例如  
# A list of tasty fruits  
- Apple  
- Orange  
- Strawberry  
- Mango  
   
##############################dictionary  
   
字典通过key与valuef进行标识例如  
---  
# An employee record  
name: Example Developer  
job: Developer  
skill: Elite  
   
也可以将key:value放置于{}中进行表示例如  
---  
# An employee record  
{name: Example Developer, job: Developer, skill: Elite}  
   
多个映射关系组成一个字典一个列表可以包含多个字典。

ymal中的变量

################################## 变量命名  
变量名仅能由字母、数字和下划线组成且只能以字母开头。  
   
################################## facts  
facts是由正在通信的远程目标主机发回的信息这些信息被保存在ansible变量中。要获取指定的远程主机所支持的所有facts可使用如下命令进行  
# ansible hostname -m setup 这个命令可以获得被监控端主机的各种信息将这些信息得到后保存到变量中。  
   
################################ 自定义变量  
在 yaml 中可以使用vars关键字来定义变量  
vars:  
var_name: value  
   
############################# 变量的引用  
{{ var_name }}  
   
   
########################### 特殊的变量迭代  
当有需要重复性执行的任务时可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用并通过with_items语句来指明迭代的元素列表即可。  
   
#######################################示例  
例如在被控端添加 2 个用户  
   
方式1一般做法  
- name: add user testuser1  
user: name=testuser1 state=present groups=wheel 
- name: add user testuser2  
user: name=testuser2 state=present groups=wheel 
   
方式2使用变量方式  
- name: add several users  
vars:  
user1: testuser1  
user2: testuser2  
user: name={{ user1 }} state=present groups=wheel 
user: name={{ user2 }} state=present groups=wheel 
   
方式3使用迭代方式  
- name: add several users  
user: name={{ item }} state=present groups=wheel 
with_items:   
- testuser1   
- testuser2  
事实上with_items中可以使用元素还可为hashes例如  
- name: add several users  
user: name={{ item.name }} state=present groups={{ item.groups }}  
with_items:  
- { name: 'testuser1', groups: 'wheel' }  
- { name: 'testuser2', groups: 'root' }

安装并启动mysql playbook实例

vim install_mysql.yaml
--- 
- hosts: agent
  remote_user: root
  tasks:
  - name: install mysql-server
    yum: name=mysql-server state=present
  - name: start mysql-server
    service: name=mysqld state=started
  - name: check mysql service
    shell: ps -ef |grep mysqld

执行次playbook将mysql数据库安装到agent服务分组里

 

 

 

 

 

 

 

最后感谢薛大佬指点...

(7)

本文由 樱花博客 作者:樱花 发表,转载请注明来源!

关键词:,

热评文章

发表评论