运维工作:系统安装(物理机、虚拟机)--> 程序包安装、配置、服务启动 --> 批量操作 --> 程序发布 --> 监控
稳定可用 ------- 标准化 --------- 自动化
系统安装:
1、物理机:PXE、Cobbler
2、虚拟机:Image Templates
程序配置Configration:
1、puppet (ruby语言研发)
2、saltstack (python语言研发)
3、chef
4、cfengine
5、ansible
批量操作Command and Control:
1、fabric(python语言研发)
2、func
3、ansible
程序发布:
1、人工智能(手动发布)
2、脚本
3、发布程序(运维程序)
程序发布的标准要求:
1、不能影响用户体验;
2、系统不能停机;
3、不能导致系统故障或造成系统完全不可用;
发布路径:
/webapps/tuangou
/webapps/tuangou-1.1
/webapps/tuangou-1.2
灰度模型:
主机
用户
在调度器上下线一批主机(标记为维护模式) ----- 关闭服务 ------ 部署新版本 ------- 启动服务 ------- 在调度器上启用这一批主机;
运维工具的分类:
1、agent:puppet,func
2、agentless(ssh):ansible、fabric
ansible:可以实现系统安装(研发中)、程序配置、批量操作、发布程序(需自定义)
模块化,调用特定的模块,完成特定的任务;
基于Python语言实现,由Paramiko、PyYAML和Jinja2三个关键模块;
部署简单,agentless;
主从模式;
支持自定义模块;
支持Playbook;
幂等性;执行一次跟多次结果一致;
安装ansible:epel,ansible
配置文件:/etc/ansible/ansible.cfg
主机清单:/etc/ansible/hosts
主程序:
ansible
ansible-playbook
ansible-doc
ansible的简单使用格式:
ansible HOST-PATTERN -f forks -m MOD_NAME -a MOD_ARGS
使用前提:
1、各节点先写入/etc/ansible/hosts里
2、各节点基于ssh密钥认证通信
控制端(即ansible主机)
# ssh-keygen -t rsa -P ''
# ssh-copy-id -i ~/.ssh/id_rsa.pub root@各节点
常用模块:
获取模块列表:ansible-doc -l
获取指定模块的帮助:ansible-doc -s MOD_NAME
1、command模块:在远程主机运行命令;
2、shell模块:在远程主机在shell进程下运行命令,支持shell特性,例如管道、重定向等;
3、copy模块:复制ansible主机的文件到各远程节点;
用法:
(1)src= dest=
(2)content= dest=
owner,group,mode
4、cron模块:管理各远程节点的cron任务;
用法:
name= job= state=present(创建)|absent(删除)
minute,hour,day,month,weekday,user
5、fetch模块:从各远程节点拉取文件到ansible本机;
6、file模块:设定远程各节点的文件属性;
用法:
(1)创建链接文件:path= src= state=link
(2)修改属性:path= owner= group= mode=
(3)创建目录:path= state=directory
7、hostname模块:管理远程各节点主机名
8、pip模块:安装远程各节点的python所需的库
9、yum模块:管理各节点的yum程序;
name=:程序包名,可以带版本号;
state=:安装(present|lastest),卸载(absent);
10、service模块:管理远程各节点的服务
name=:
state=:started启动,stopped停止,restarted重启
enabled=0|1:开机是否启动
runlevel=
11、ping模块:ping远程各节点;
12、user模块:管理远程各节点的用户
name=
system=yes|no
uid=
shell=
state=present|absent
home=:家目录
group=:基本组
groups=:额外组
remove:删除用户,同时删除家目录
13、uri模块:访问远程各节点的http|https服务
14、setup模块:收集远程各节点的facts信息;
15、group模块:添加或删除组
name=
state=present|absent
gid=
system=:是否系统组
16、script模块:把一个本地script传递到远程各节点执行
-a “/path/to/script_file”
17、template模块:基于模板方式生成一个文件复制到远程主机
src=
dest=
YAML语法:YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。下面是一个示例。
name: John Smith
age: 41
gender: 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文件扩展名通常为.yaml,如example.yaml。
playbook的核心元素:
hosts:
tasks: 任务
variables: 变量
templates: 模板(包含了模版语法的文本文件)
handlers: 处理器(由特定条件触发的任务)
roles: 角色
案例:
heartbeat.yaml
- hosts: hbhosts
remote_user: root
tasks:
- name: ensure heartbeat latest version
yum: name=heartbeat state=present
- name: authkeys configure file
copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
- name: authkeys mode 600
file: path=/etc/ha.d/authkeys mode=600
notify:
- restart heartbeat
- name: ha.cf configure file
copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
notify:
- restart heartbeat
handlers:
- name: restart heartbeat
service: name=heartbeat state=restarted
playbook的基础组件:
hosts:运行指定任务的目标主机;
remote_user:在远程主机上执行任务的用户;
sudo_user:在需要用到sudo时指定的用户;
tasks:任务列表,自上而下
(1)action:module arguments
(2)module:arguments
注意:shell和command模块后面直接跟命令,而非key=value类的参数列表
handlers:任务,在特定条件下触发,接收到其他任务的通知时被触发;
(1)某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2)任务可以通过“tags”打标签,而后在ansible-playbook命令上使用-t指定进行调用;
运行playbook的方式:
(1)测试
ansible-playbook --check:只检测可能发生的改变,但不真正执行操作;
ansible-playbook --list-hosts:列出运行任务的主机;
(2)运行
variables: 变量;调用 {{ variable }}
1、facts:setup模块提供的;可直接调用
2、ansible-playbook命令的自定义变量:通过双括号进行调用:{{ 变量名 }};
3、通过roles传递变量;
4、Host Incentory:
(1)向不同的主机传递不同的变量;在/etc/ansible/hosts文件下,IP/HOSTNAME variable=value var2=value2
(b)向组中的主机传递相同的变量;在/etc/ansible/hosts文件下,[groupname:vars] var=value
在playbook中定义变量的方法:
vars:
- var1: value1
- var2: value2
inventory参数:用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
模板:templates;文本文件,嵌套有脚本(使用模板编程语言编写)
jinjar2:
1、字面量:
(1)字符串:使用单引号或双引号;
(2)数值:整数,浮点数;
(3)列表:[item1,item2];
(4)元组:(item1,item2);
(5)字典:{key1:value1,key2:value2,...};
(6)布尔型:true|false
2、算术运行:
+,-,*,/,//,%,**
3、比较操作:
==,!=,>,>=,<,<=
4、逻辑运算:
and,or,not
案例:nginx.yaml:在websrvs组安装nginx,并根据模板nginx.j2,启动nginx服务;
# vim nginx.yaml
其中nginx.j2 传递了2个变量
worker_processes {{ ansible_processor_vcpus-1 }}; #由setup模块提供的变量;
listen {{ http_port }} default_server;
http_port变量是由/etc/ansible/hosts文件传递;如下
条件测试:
when语句:在tasks中使用,jinja2的语法格式;
在tasks后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。例如:
tasks:
- name: "shutdown Debian flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "Debian"
循环:迭代,需要重复执行的任务;
对迭代项的引用,固定变量名为“item”;而后在tasks中,使用with_items给定要迭代的元素列表;a、字符串,2、字典
a、例如:
- name: install some package
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm
b、例如
- name: add some group
group: name={{ item }} state=present
with_items:
- group1
- group2
- group3
- name: add some users
user:name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: "user1" group: "group1" }
- { name: "user2" group: "group2" }
- { name: "user3" group: "group3" }
角色roles:roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
roles模块的路径可以在配置文件/etc/ansible/ansible.cfg里roles_path定义.
1
2
|
vim
/etc/ansible/ansible
.cfg
roles_path =
/etc/ansible/roles
:
/usr/share/ansible/roles
|
role内各目录中可用的文件:
tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;其他的文件需要在此文件中通过include进行包含;
files目录:存放由copy或script等模块调用的文件;
templates目录:template模块查找所需要模板文件的目录;
handlers目录:至少应该包含一个名为main.yml的文件,用于定义此角色用到的各handler;在handler中使用include包含的其它的handler文件也应该位于此目录中;
vars目录:至少应该包含一个名为main.yml的文件,用于定义此角色用到的变量;
meta目录:至少应该包含一个名为main.yml的文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持;
default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件;
创建role的步骤
(1) 创建以roles命名的目录;
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等;
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建;
(4) 在playbook文件中,调用各角色;
示例:创建nginx角色
#设置任务文件,注意,配置模板文件的src使用相对路径即可,目录的相对路径是:/usr/share/ansible/roles/nginx/templates/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
vim
/usr/share/ansible/roles/nginx/tasks/main
.yml
- name:
install
nginx package
yum: name=nginx state=latest
- name: copy nginx conf
file
tempalte: src=web.conf.j2 dest=
/etc/nginx/conf
.d
/web
.conf
notify: reload nginx
tags: cpfile
- name: create docroot
dir
file
: path={{ ngx_doc_root }} state=directory
tags: cpfile
- name: start nginx service
service: name=nginx enabled=
true
state=started
#设置变量,在vars目录下定义变量,变量不需要横杆引导
vim
/usr/share/ansible/roles/nginx/vars/main
.yml
ngx_port: 8888
ngx_server_name: www.sunny.com
ngx_doc_root:
/webdata
#设置触发后执行的操作
vim
/usr/share/ansible/roles/nginx/handlers/main
.yml
- name: reload nginx
service: name=nginx state=reloaded
#设置模板文件
vim
/usr/share/ansible/roles/nginx/templates/web
.conf.j2
server {
listen {{ ngx_port }};
server_name {{ ngx_server_name }};
location / {
root {{ ngx_doc_root }};
}
}
|
#调用模块
1
2
3
4
5
|
vim
/root/ansible/nginxrole
.yml
- hosts: dbsrvs
remote_user: root
roles:
- nginx
|
测试模块
1
|
ansible-playbook -C
/root/ansible/nginxrole
.yml
|
注意,由于测试没有实际安装nginx模块,因此测试时,启动服务会失败
执行模块
1
|
ansible-playbook
/root/ansible/nginxrole
.yml
|
执行tag cpfile对应的代码,如果文件web.conf.j2 发生变化,包括定义变量的文件发送变化,就会重新服务该文件到对应机器,同时,notify生效,重启nginx服务
1
|
ansible-playbook -t cpfile
/root/ansible/nginxrole
.yml
|
在执行命令中执行变量,注意,命令里的变量优先级比配置再模块vars下的优先级高
1
|
ansible-playbook -t cpfile -e
"ngx_port=8899"
/root/ansible/nginxrole
.yml
|
在playbook调用角色方法1:
- hosts: websrvs
remote_user: root
roles:
- nginx
- memcached
在playbook调用角色方法2:传递变量给角色
- hosts: websrvs
remote_user: root
roles:
- { role: nginx, username: nginx } 键role用于指定角色名称,后续的K/V用于传递变量给角色
还可以基于条件测试实现角色调用3;
roles:
- { role: nginx, when: ansible_distribution_major_version == '7' }
参考文档:www.ansible.com.cn