您的位置:首页 > 运维架构

自动化运维工具之ansible的简单应用

2016-05-25 19:18 761 查看
ansible:
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,例如shell,copy,ping等,ansible只是提供一种框架。ansible的主要特性: 模块化:调用特定的模块,完成特定任务
基于Python语言实现,由Paramiko,PyYAML和jinja2三个关键模块
部署简单:agentless,无需在管控主机安装任何客户端
支持自定义模块;
支持playbook(剧本);
运维工具的工作模式:
1、agent :需要在管控主机上安装客户端,和客户端通信,比如:zabbix,puppt 2、agentless:无需安装客户端,基于SSH协议通信,比如:ansible
ansible是工作在agentless模式下具有幂等性,意思就是无论任务执行一遍或者多遍,对结果都不会产生影响。ansible在控制端只需要告诉监控端的期望状态就可以实现批量部署,只需告诉管控主机需要干什么就行。
ansible的架构图:


ansible通过连接插件Connaction Plugins来负责基于SSH和管控主机进行通信,Host Inventoy则记录了需操作主机的信息。ansible除了直接使用命令行控制外,还可以基于PlayBooks(剧本)来实现管理主机,通过各种模块和自定义模块来操作主机,并借助插件来记录日志和邮件等。

一、ansible的安装
]# yum -y install ansible
]# ls /etc/ansible/
ansible.cfg                    //配置文件
hosts                         //主机清单
roles/                       //定义角色
1、定义hosts:

]# vim /etc/ansible/hosts
[webserver] //定义主机组
172.18.250.77 ansible_ssh_user=root ansible_ssh_pass=123456 //连接主机的账号密码
172.18.250.78 ansible_ssh_user=root ansible_ssh_pass=123456

2、直接给出主机的账号密码不太安全,这时可以基于密钥方式认证:

]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P''
]# ansible webserver -m copy -a "src=/root/.ssh/id_rsa.pub dest=/root/"
]# ansible webserver -m shell -a "cat /root/id_rsa.pub >>/root/.ssh/authorized_keys"
3、可以把账号密码去掉,试试能不能执行
]# vim /etc/ansible/hosts
[webserver]
172.18.250.77
172.18.250.78
]# ansible webserver -m ping
172.18.250.78 | success >> {
"changed": false,
"ping": "pong"
}

172.18.250.77 | success >> {
"changed": false,
"ping": "pong"
}
4、ansible的简单语法格式:
ansible HOST-PATTERN [-f forks] [-m MODULE_name] [-a args]
HOST-PATTERN:主机清单,可以是单个主机,也可以是主机组
-m module: 指明模块,默认为command
-f forks: 指明一次发送几个连接请求
-a args: 在远程主机上执行的参数
查看ansible的常用模块命令: ansible-doc -l

5、常用模块
command模块:在远程主机上执行命令,不支持管道
]# ansible webserver -m command -a "cat /etc/issue"
172.18.250.77 | success | rc=0 >>
\S
Kernel \r on an \m

172.18.250.78 | success | rc=0 >>
\S
Kernel \r on an \m
shell模块:在远程主机shell上执行命令,支持管道
]# ansible webserver -m shell -a "ss -tan |grep :8080"
172.18.250.78 | success | rc=0 >>
LISTEN     0      128                      :::8080                    :::*

172.18.250.77 | success | rc=0 >>
LISTEN     0      128                      :::8080                    :::*
copy模块:复制本地文件到远程主机,或者直接在远程主机上写内容
1、src=/path/to/somefile dest=/path/to/somefile
2、content=someting dest=/path/to/somefile
]# ansible webserver -m copy -a "src=/etc/issue dest=/tmp"
172.18.250.78 | success >> {
"changed": true,
"checksum": "5f63a8ace67bf6a8b62aa7da2cf5eccc05a89308",

172.18.250.77 | success >> {
"changed": true,
"checksum": "5f63a8ace67bf6a8b62aa7da2cf5eccc05a89308",

]# ls /tmp/
issue
cron模块:管理定时计划任务
]# ansible webserver -m cron -a "minute=*/5 state=present job='ntpdate 172.18.0.1 >/dev/null' name=Rsynctime"
172.18.250.78 | success >> {
"changed": true,
"jobs": [
"Rsynctime"
]
}

172.18.250.77 | success >> {
"changed": true,
"jobs": [
"Rsynctime"
]
}
]# crontab -l
#Ansible: Rsynctime
*/5 * * * * ntpdate 172.18.0.1 >/dev/null

mintue=    //分钟
hour=      //小时
day=       //哪天
weekday=   //星期几
month=     //哪月
job=       //内容
name=      //名称
state=     //对内容做什么操作,present:创建  absent:删除
ping模块,对远程主机实行ping操作
]# ansible webserver -m ping
172.18.250.78 | success >> {
"changed": false,
"ping": "pong"
}

172.18.250.77 | success >> {
"changed": false,
"ping": "pong"
}
yum模块,程序包管理
]# ansible webserver -m yum -a "name=httpd state=present"
172.18.250.78 | success >> {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"httpd-2.4.6-31.el7.centos.x86_64 providing httpd is already installed"
]
}

172.18.250.77 | success >> {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"httpd-2.4.6-40.el7.centos.x86_64 providing httpd is already installed"
]
}
service模块,管理远程主机上的服务
]# ansible webserver -m service -a "name=httpd state=started enabled=1"
172.18.250.78 | success >> {
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started"
}

172.18.250.77 | success >> {
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started"
}
name=         //程序名称
state=        //执行的操作,started、stoped、restarted、reloaded
enabled=      //是否开机自启
runlevel=     //运行的级别
script模块,在远程主机上执行本地脚本,无需传递脚本过去
]# ansible webserver -m script -a "/tmp/mkdir.sh"(本地路径)
172.18.250.78 | success >> {
"changed": true,
172.18.250.77 | success >> {
"changed": true,

默认是运行在用户的家目录下
user模块和group模块,在远程主机上创建用户和组
]# ansible webserver -m group -a "name=testgroup system=no gid=2000 state=present"
]# ansible webserver -m user -a "name=usertest system=no uid=2000 group=testgroup state=present"


二、playbooks的应用
运行playbook的方式:
1、只检测可能会发生的改变,但不真正执行操作
ansible-playbook --check file.yaml
2、运行
ansible-playbook file.yaml
先要了解YAML的语法,YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。
YAML文件扩展名通常为.yaml,如example.yaml。
列表(list)的所有元素均使用“-”打头,例如:
# A list of tasty fruits
- Apple
- Orange

字典(dictionary)通过key与value进行标识,例如:
---
# An employee record
name: Example Developer
job: Developer
skill: Elite

也可以将key:value放置于{}中进行表示,例如:
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏。
playbook的核心元素:
Tasks: 任务
Variables: 变量
Templates: 包含了模板语法的文本文件;
Handlers: 由特定条件触发的任务;
Roles: 角色
Hosts: 主机

1、hosts主机和用户
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。
- hosts: webserver
remote_user: root
tasks:
- name: ping
ping:
remote_user: usertest
sudo: yes

remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。
2、tasks任务和action

play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。
tasks:
- name: yum install httpd packages
yum:  name=httpd state=present
- name: start httpd
service: name=httpd state=started
3、 Variables: 变量
3.1、由ansible自己提供的变量:facts,可以直接调用
]# ansible webserver -m setup
172.18.250.78 | success >> {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.18.250.78"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:fefa:c47b"
],
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/31/2013",
"ansible_bios_version": "6.00",
3.2、ansible-playbook命令的命令行中的自定义变量
]# vim /tmp/test.yaml
- hosts: webserver
remote_user: root
tasks:
- name: useradd
user: name={{ pkiname }} state=present
]# ansible-playbook  -e pkiname=user111 --check test.yaml
3.3 向不同的主机中传递变量,在服务的配置文件中直接调用就行
]# vim /etc/ansible/hosts
[webserver]
172.18.250.77  http_port=80
172.18.250.78  http_port=8080
3.4、向组中的主机传递相同的变量,以便在playbook中使用

]# vim /etc/ansible/hosts
[webserver]
172.18.250.77
172.18.250.78
[webserver:vars]
httpd_port=8080
4、 Templates: 包含了模板语法的文本文件,嵌套有脚本(使用模板编程语言编写)
有时候需要根据服务器的配置来修改服务配置文件,这时可以根据模板来解决

]# vim /tmp/nginx.conf.j2
user nginx;
worker_processes {{ ansible_processor_vcpus-1 }};    //根据服务器cpu核数减1
]# vim /tmp/test.yaml
- hosts: webserver
remote_user: root
tasks:
- name: nginx conf
template: src=/tmp/template/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: restart
service: name=nginx state=restarted
5、Handlers: 由特定条件触发的任务;
“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
]# vim /tmp/test.yaml
- hosts: webserver
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
- name: nginx conf
template: src=/tmp/template/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart            //只有当配置文件发生改变时才会触发notify
- name: start nginx
service: name=nginx state=started
handlers:
- name: restart           //触发notify时就执行重启操作
service: name=nginx state=restarted
6、playbook还支持条件测试和循环:

条件测试:
when语句:在task中使用,jinja2语法格式
tasks:
- name: install conf file to centos7
template:src=files/nginx.conf.c7.j2
when: ansible_distribution_major_version == "7"
- name:  install conf file to centos7
template:src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == "6"

循环语句:对迭代项的引用,固定变量名为"item",而后,要在task中使用with_items给定要迭代的元素列表;
with_items两个方法表示:
列表方法:字符串、字典

1、字符串表示
- hosts: all
remote_user: root
tasks:
- name: install some package
yum: name={{ item }} state=present
with_items:
- nginx
- httpd
2、字典表示:
- hosts: all
remote_user: root
tasks:
- name: add group
group: name={{ item }} state=present
with_items:
- group11
- group22
- group33
- name: add user
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11',group: 'group11' }
- { name: 'user22',group: 'group22' }
- { name: 'user33',group: 'group33' }
7、tags:标签
tags用于让用户选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断。
]# vim /tmp/test.yaml
- hosts: webserver
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
- name: nginx conf
template: src=/tmp/template/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart
tags: res                //在配置文件修改这打标签,执行时不会测试instll和start两部分   - name: start nginx          代码
service: name=nginx state=started
handlers:
- name: restart
service: name=nginx state=restarted
]# ansible-playbook  --tags=res --check test.yaml


三、roles
ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
创建role的步骤
(1) 创建以roles命名的目录;
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等;
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建;
(4) 在playbook文件中,调用各角色;

role内各目录中可用的文件
tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;此文件可以使用include包含其它的位于此目录中的task文件;
files目录:存放由copy或script等模块调用的文件;
templates目录:template模块会自动在此目录中寻找Jinja2模板文件;
handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;在handler中使用include包含的其它的handler文件也应该位于此目录中;
vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量;
meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持;
default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件;

示例:创建个nginx角色,实现nginx的安装

]# mkdir /etc/ansible/roles/nginx
]# cd /etc/ansible/roles/nginx/
]# mkdir tasks files templates handlers vars meta default
]# cd tasks/
]# vim main.yml              //编辑task
- name: install nginx
yum: name=nginx state=present
- name: nginx conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
tags: res
- name:  start nginx
service: name=nginx state=started

]# cd handlers/
]# vim main.yml             //编辑handlers
- name: restart nginx
service: name=nginx state=restarted

]# cd templates/
]# cp /tmp/nginx.conf.j2 ./    //准备模板
]# vim /etc/ansible/roles/nginx/templates/nginx.conf.j2
user {{ username }};

]# cd vars/
]# vim main.yml            //定义变量
username: deamon          //变量定义时较特殊,不要加“-”,定义运行nginx的用户

]# vim /tmp/nginx.yml
- hosts:websrvs
remote_user:root
roles:
- nginx                 //直接调用nginx
# 调用变量:
- host:
remote_user:
roles:
- { role: nginx,username: nginx }
# 还可以基于条件测试实现角色调用;
- host:
remote_user:
roles:
- { role: nginx,when: ansible_distribution_majro_version == ’7‘ }

]# ansible-playbook --check /tmp/nginx.yml

PLAY [webserver] **************************************************************

GATHERING FACTS ***************************************************************
ok: [172.18.250.78]
ok: [172.18.250.77]

TASK: [nginx | install nginx] *************************************************
changed: [172.18.250.78]
changed: [172.18.250.77]

TASK: [nginx | nginx conf] ****************************************************
changed: [172.18.250.78]
changed: [172.18.250.77]

TASK: [nginx | start nginx] ***************************************************
changed: [172.18.250.78]
changed: [172.18.250.77]

NOTIFIED: [nginx | restart nginx] *********************************************
changed: [172.18.250.78]
changed: [172.18.250.77]

PLAY RECAP ********************************************************************
172.18.250.77              : ok=5    changed=4    unreachable=0    failed=0
172.18.250.78              : ok=5    changed=4    unreachable=0    failed=0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  运维 自动化 ansible