前言
你好,我是言淦!本文承接之前的文章 《Ansible使用小记》。
在前面的文章提到过,Ansible的Ad-Hoc和Playbooks就好比 shell命令 和 shell脚本,下面我会通过部署一个Python项目来介绍Playbooks的用法。
准备一个Python项目
源码如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
if __name__ == '__main__':
app.run(port=5000, debug=True)
完整内容参见:github.com/yangancode/…
Playbooks 编写
1.如果是简单的项目,一般一份YAML文件就能完成整个项目的部署,而如果是比较复杂的项目,或者是多个项目,建议使用Playbooks Roles 来实现,能够使我们的playbooks文件更具有层次性,更容易管理。
2.roles的机制就是分别将变量、文件、任务、模板及处理器放置于单独的目录中,并通过include关键字衔接起来的一种做法(将大模块拆分成小模块),一般在handlers、tasks、vars等目录都会有一份main.yml文件,ansible会自动装载并执行。
通过roles管理的项目,结构一般如下:
├── deploy.yml # 主文件,入口文件
└── roles # 所有的角色都必须放在roles目录下,每个项目可以理解为一个角色
└── python
├── files # 此目录用来存放由copy模块或script模块调用的文件
├── handlers # 此目录用于存放此角色中触发条件时执行的动作 (触发器)
│ └── main.yml
├── tasks # 此目录用于存放次角色的任务列表文件
│ ├── flask.yml
│ └── main.yml
├── templates # 此目录用来存放jinjia2模板文件,比如supervisor配置文件
└── vars # 此目录用来存放一些用到的变量
└── main.yml
下面以部署一个Flask项目为例,介绍每份playbook文件该如何填写,希望能帮助到大家(有用的话点个👍 哦)。
部署一个Flask项目大致有以下步骤:
- 1.检查项目文件夹是否存在,不存在则创建
- 2.检查supervisor是否安装,不存在则安装(使用supervisor管理进程)
- 3.检查虚拟环境(virtualenv)是否存在,不存在则安装
- 4.拷贝项目代码及安装Python依赖
- 5.拷贝supervisor配置文件
- 6.使用supervisor启动/重启服务
对应的yaml文件如下:
# deploy.yml
- hosts: "{{ host | default('osa-web-test') }}"
serial: "{{ serial | default(10) }}"
vars:
version: "{{ git_version | default('master') }}"
roles:
- osa
# tasks/main.yml
- include: "{{ task }}.yml"
# var/main.yml
remote_srv: /home/yangan/services
local_srv: /home/ansible/flask_lab
virtualenv_path: /home/yangan/virtual_env
# handlers/main.yml
# 触发器,这里是触发supervisor重启服务
- name: update supervisor
shell: supervisorctl update && supervisorctl restart {{ service_name }}
# tasks/flask.yml (本次的核心文件)
- name: check supervisor install
stat:
path: /etc/supervisor
register: supervisor_stat
tags:
- deploy
- name: check remote service folder
stat:
path: "{{ remote_srv }}"
register: remote_service_stat
tags:
- deploy
...
# templates/flask.conf (配置文件)
[program: {{ service_name }}]
; 实际命令视项目需要
command={{ virtualenv_path }}/{{ service_name }}/bin/python {{ remote_srv }}/{{service_name}}/main.py
environment=MILOG='format=json&tag_srv=1'
; /home/yangan/services/flask
directory={{ remote_srv }}/{{ service_name }}
autostart=true
autorestart=true
; 这是我自己创建的用户
user=yangan
umask=022
; /home/yangan/services/flask/flask.super.log
stdout_logfile={{ remote_srv }}/{{ service_name }}/{{ service_name }}.super.log
redirect_stderr=true
# Playbook Roles部署
$ ansible-playbook ansible_roles/deploy.yml --sudo --extra-vars 'task=flask service_name=flask'
部署成功后查看服务是否启动:
root@07f1e6b62e12:/home/yangan# supervisorctl
flask RUNNING pid 3445, uptime 0:01:24
supervisor>
其实整个项目看下来,你会发现原理其实不难,主要是Linux相关知识要比较熟练,唯一比较繁琐的是各种路径要匹配得上。另外,上面的代码其实还涉及到一个ansible标签 (tags),这也是一个比较好用的功能,通过使用不同的标签,你可以对任务进行排列,从而使任务可以得到最大限度的复用。
补充:sudo的配置
由于上面安装supervisor使用了 sudo指令,配置sudo的步骤如下:
1.首先确保远程机器用户(yangan)是sudo用户组的,保证其能执行sudo指令
2.在需要执行sudo的任务下添加sudo指令(也可以全局)
- apt: name=supervisor update_cache=yes
when: supervisor_stat.stat.exists == False
sudo: yes
tags:
- deploy
3.修改操作机 /etc/ansible/ansible.cfg 配置下的执行用户
poll_interval = 15
sudo_user = yangan
4.修改 /etc/ansible/hosts 的机器配置,加上密码
[webservers]
root@172.17.0.4 ansible_ssh_user=yangan ansible_sudo_pass='yangan'
5.部署命令加上 --sudo
注:完整代码参见 github.com/yangancode/… (有帮助的话请点个star哦😯)
Playbooks指令介绍
在上面的例子用到的一些指令,在这里会做进一步说明和补充。
serial
一般情况下,如果是分布式项目,我们可能需要在几台机,甚至十几台机部署上面的项目,为了保证部署的稳定性,我们一般会采取滚动更新的做法,serial关键字就是帮我们干这件事的。
在下面例子中, 如果webservers包含四个主机,则后面两个主机会等前面两个主机执行完指令后再执行。
- name: test play
hosts: webservers
serial: 2
tasks:
- name: task one
comand: hostname
另外,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例
- name: test play
hosts: webservers
serial: "30%"
tasks:
- name: task one
comand: hostname
command VS shell
这是两个比较相似的指令,主要区别在于会不会使用Linux的 shell 程序执行指令。
对于 command 指令,它并不会使用shell程序执行命令. 因此,像$HOME这样的变量是不可用的。还有像<, >, |, ;, &等符号都是不可用的。
对于 shell 指令,顾名思义,它会通过shell程序执行命令, 默认是/bin/sh, 像<, >, |, ;, &这些符号都是可用的,但需要注意 shell注入的风险。
总体而言,command相比shell更安全,因为它不受用户环境的影响,很大程度避免了潜在的shell注入风险,如果你需要安全地使用 shell 模块,可以使用{{ var | quote }} 代替 {{ var }} ,确保输入不包含分号或者流式操作。
unarchive
该指令用于解压压缩包,支持tar.gz,zip等。如果需要将远程主机上的某个压缩包解压到指定路径下,需要设置copy=no;如果是将ansible主机上的压缩包在本地解压后传到远程主机上,需要设置copy=yes。
- name: test play
hosts: webservers
serial: 1
tasks:
- name: extract tar.gz
unarchive: src=xxx.tar.gz dest=/tmp/xxx copy=no mode=0755
template
ansible template文件夹下一般存放一些模板文件,常见的有各种配置文件,如上文中的supervisor配置文件,模板文件采用的语法是jinjia2,jinjia2支持的语法有:字符串、整型、列表、元组、字典、加减乘除、if判断、for循环等。
看网上的文章都需要加 j2 后缀?
参考: www.cnblogs.com/qiuhom-1874…
apt
该指令用于安装一些包,不过只适用于操作系统是Ubuntu/debian的机器,执行的机器需要安装 python-apt 库。
blog.csdn.net/modoo_junko… blog.csdn.net/modoo_junko…
copy
Ansible Copy Module Fails: stackoverflow.com/questions/3…
cron
sudo
只运行一次
stackoverflow.com/questions/2…
额外变量
ansible远程执行的环境变量问题
www.jianshu.com/p/b5c4113b2… www.cnblogs.com/yanjieli/p/…
创作不易,有用的话请点个赞呗!