首先要知道ansible是一种轻量级的自动化部署开源软件,被许多中小型的网站所采用。可以完成配置系统、软件发布、高级任务的编排、编排更高级的任务,比如连续部署或零停机时间滚动更新。
ansible的命令格式
ansible
使用命令探测主机
ansible all -m ping -C
192.168.31.201 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.31.203 | SUCCESS => {
"changed": false,
"ping": "pong"
}
查看ansible支持的所有模块
ansible-doc -l
查看模块的所有参数
ansible-doc -s MODULE_NAME
在两台主机上创建两个组
ansible all -m group -a "gid=3000 name=mygrp state=present"
192.168.31.201 | CHANGED => {
"changed": true,
"gid": 3000,
"name": "mygrp",
"state": "present",
"system": false
}
192.168.31.203 | CHANGED => {
"changed": true,
"gid": 3000,
"name": "mygrp",
"state": "present",
"system": false
}
常用的模块
常用模块:
command
-a 'COMMAND'
user
-a 'name= state={present|absent} system= uid='
group
-a 'name= gid= state= system='
cron
-a 'name= minute= hour= day= month= weekday= job= user= state='
copy
-a 'dest= src= mode= owner= group='
注意:src是目录时最后带/复制目录内容,不带/递归复制文件本身
file
-a 'path= mode= owner= group= state={directory|link|present|absent} src='
ping
没有参数
yum
-a 'name= state={present|latest|absent}'
service
-a 'name= state={started|stopped|restarted} enabled='
shell
-a 'COMMAND'
script
-a '/path/to/script'
setup
playbook的核心元素:
- Hosts:主机
- tasks: 任务
- variables: 变量
- templates: 模板包含了模板语法的文本文件
- handlers: 处理器
- roles: 角色
Hosts:运行指定任务的目标主机;
remoute——user:在远程主机上执行任务的用户
sudo_user;
tasks:任务列表
模块,模块参数;
格式:
(1) action: module arguments
(2) module:arguments
注意: shell和command模块后面直接跟命令,而非key=value类的参数;
(1) 某任务的状态在运行后为change时,可通过"notify"
通知给相应的handlers
(2) 任务可以通过"tags"打标签,而后可在ansible-playbook
命令上使用-t指定进行调用;
handlers:
任务,在特定条件下触发;
接收到其他任务的通知时被触发;
notify:HANDLER TASK NAME
variable:
(1) facts:可直接调用;
注意:ansible命令行下可使用setup模块直接获取目标主机的facters;
(2)用户自定义变量;
ansible-playbook命令的命令行中
-e VARS,--extra-vars=VARS
ansible-playbook -e pkgname=memcached name.yaml
(3) 通过roles传递变量
(4) Host Inventory
(a)向不同的主机传递不同的变量;
IP/HOSTANME variable=value var2=value2
(b)向组中的主机传递相同的变量;
[groupname:vars]
variable=value
注意:invertory参数:
用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量;
- ansible_ssh_host
- ansible_ssh_port
- ansible_ssh_user
- ansible_ssh_pass
- ansible_sudo_pass
templates:模板
文本文件,嵌套有脚本(使用模板编程语言编写)
Jinja2:
字面量:
字符串:使用单引号或双引号;
数字:整数,浮点数;
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:
+, -, *, /, //, %, **
比较操作:
==, !=, >, >=, <, <=
逻辑运算:
and, or, not
条件测试
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 centos6
template: src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == "6"
循环
对迭代项的引用,固定变量名为”item“
而后,要在task中使用with_items给定要迭代的元素列表;
列表方法:
字符串
字典
- name: install some packages
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11', group: 'group11' }
- { name: 'user12', group: 'group12' }
- { name: 'user13', group: 'group13' }
roles:角色
每个角色,以特定的层级目录结构进行组织:
mysql/
files/ :存放由copy或script模块等调用的文件;
templates/:template模块查找所需要模板文件的目录;
tasks/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
vars/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
meta/:至少应该包含一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要在此文件中通过include进行包含;
default/:设定默认变量时使用此目录中的main.yml文件;
在playbook调用角色方法1:
- hosts: websrvs
remote_user: root
roles:
- mysql
- memcached
- nginx
在playbook调用角色方法2:传递变量给角色
- hosts:
remote_user:
roles:
- { role: nginx, username: nginx }
#键role用于指定角色名称;后续的k/v用于传递变量给角色;
#还可以基于条件测试实现角色调用;
roles:
- { role: nginx, when: "ansible_distribution_major_version == '7' " }
现在我们计划使用role部署一台nginx两台tomcat主机,这就需要两个角色
首先编辑/etc/ansible/hosts文件,添加需要被控制的主机
[lb]
node2.lvqing.com
[tcservs]
node[3:4].lvqing.com
生成ssh密钥公钥对,发送给待管理主机,然后不需要密码也能ssh登陆了
ssh-keygen -t rsa -P ""
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
然后创建角色对应的目录
mkdir -pv /etc/ansible/roles/{nginx,tomcat,jdk}/{files,templates,tasks,handlers,vars,meta,default}
首先编辑tasks目录下的main.yaml文件
- name: install nginx
yum: name=nginx state =present
when: ansible_os_family == "RedHat"
- name: install conf
copy: src=lb.conf dest=/etc/nginx/conf.d/
tags: conf
notify: restart nginx
- name: start nginx
service: name=nginx state=started enabled=yes
因为定义了notify所以还需要编辑handler文件
- name: restart nginx
service: name=nginx state=restarted
在files下创建需要传过去的配置文件lb.conf
upstream tcservs {
server node3.lvqing.com;
server node4.lvqing.com;
}
server {
listen 80;
server_name node2.lvqing.com;
location / {
proxy_pass http://tcservs;
}
}
至此nginx角色就简单的创建完成了,然后定义tomcat的角色
- name: install package
yum: name={{ item }} state=present
with_items:
- tomcat
- tomcat-admin-webapps
- tomcat-webapps
- tomcat-docs-webapp
when: ansible_os_family == "RedHat"
- name: start tomcat
service: name=tomcat state=started enabled=yes
然后因为tomcat依赖于jdk,我们需要去定义jdk角色
- name: install openjdk
yum: name=java-{{ version }}-openjdk-devel state=present
- name: install env file
copy: name=java.sh dest=/etc/profile.d/
files目录下java.sh文件
export JAVA_HOME=/usr
然后我们再创建一个playbook来使用这几个角色
- hosts: lb
remote_user: root
roles:
- nginx
- hosts: tcservs
remote_user: root
roles:
- { role: jdk, version: 1.8.0 }
- tomcat
然后我们运行剧本ansible-playbooks os.yml
PLAY [lb] **************************************************************************************
TASK [Gathering Facts] *************************************************************************
ok: [node2.lvqing.com]
TASK [nginx : install nginx] *******************************************************************
ok: [node2.lvqing.com]
TASK [nginx : install conf] ********************************************************************
changed: [node2.lvqing.com]
TASK [nginx : start nginx] *********************************************************************
changed: [node2.lvqing.com]
RUNNING HANDLER [nginx : restart nginx] ********************************************************
changed: [node2.lvqing.com]
PLAY [tcservs] *********************************************************************************
TASK [Gathering Facts] *************************************************************************
ok: [node2.lvqing.com]
ok: [node3.lvqing.com]
TASK [jdk : install openjdk] *******************************************************************
ok: [node2.lvqing.com]
ok: [node3.lvqing.com]
TASK [jdk : install env file] ******************************************************************
changed: [node2.lvqing.com]
changed: [node3.lvqing.com]
TASK [tomcat : install package] ****************************************************************
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is
deprecated. Instead of using a loop to supply multiple items and specifying `name: {{ item }}`,
please use `name: [u'tomcat', u'tomcat-admin-webapps', u'tomcat-webapps', u'tomcat-docs-
webapp']` and remove the loop. This feature will be removed in version 2.11. Deprecation
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is
deprecated. Instead of using a loop to supply multiple items and specifying `name: {{ item }}`,
please use `name: [u'tomcat', u'tomcat-admin-webapps', u'tomcat-webapps', u'tomcat-docs-
webapp']` and remove the loop. This feature will be removed in version 2.11. Deprecation
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
changed: [node3.lvqing.com] => (item=[u'tomcat', u'tomcat-admin-webapps', u'tomcat-webapps', u'tomcat-docs-webapp'])
changed: [node2.lvqing.com] => (item=[u'tomcat', u'tomcat-admin-webapps', u'tomcat-webapps', u'tomcat-docs-webapp'])
TASK [tomcat : start tomcat] *******************************************************************
changed: [node3.lvqing.com]
changed: [node2.lvqing.com]
PLAY RECAP *************************************************************************************
node2.lvqing.com : ok=10 changed=6 unreachable=0 failed=0
node3.lvqing.com : ok=5 changed=3 unreachable=0 failed=0
可以看到已经成功完成了