DevOps 系列工具之 Ansible
Ansible 优缺点自动化引擎,可以实现配置管理、应用部署、服务编排 及其他各种IT需求
依赖 Jinja2、paramiko、PyYAML python库
安装部署简单:只需在主控端部署Ansible环境
基于SSH进行配置管理,充分利用现成的机制
Ansible不需要守护进程,维护简单、系统更加安全可靠
Ansible简单易用
Ansible功能强大:通过模块实现各种功能
Ansible设计优秀,便于分享。
Ansible对云计算和大数据平台都有很好的支持。包含了大量与云服务、AWS、OpenStack、Docker等相关的模块
ansible 的基本使用
ansible使用python语言开发,可以直接使用pip安装
pip install ansible
也可以使用yum和apt-get包管理工具进行安装
ansible
ansible-doc
ansible-playbook
ansible-vault
ansible-console
ansible-galaxy
ansible-pull
在 Ansible 中,用户通过 Ansible 编排引擎操作主机。其中,主机可以通过配置文件配置、调用云计算接口获取、或者访问CMDB中的数据库获取
Ansible 的编排引擎由 Inventory、API、Modules(模块)、Plugins 组成。
Ansible 的典型用法:工程师将需要在远程主机上执行的操作写在 Ansible Playbook 中,然后使用 Ansible 执行 Playbook 中的操作。
vim /etc/ansible/hosts
192.168.1.1 ansible_user=wt ansible_port = 20002
web2-3
vim /etc/ansible/ansible.cfg
remote_user = wt
remote_port = 20002
ansible web -m command -a “hostname”
-m指定模块名称,默认模块是 command
-a 指定模块的参数
-i 指定inventory文件
ansible 的模块包含多个参数,参数使用 “key=value” 的形式表示,各个参数之间用空格分隔。
ansible web -m ping 验证web组中的主机用户SSH是否已经正确配置
ansible web -m copy -a “src=/tmp/index.html dest=/html/index.html” 将本地文件拷贝到服务器中
ansible web -m file -a “dest=/html/index.html mode=500 owner=nginx group=nginx” -become 修改服务器中文件到权限,-become等于sudo
ansible web -m yum -a “name=git state=present” -become 为远程服务器安装git软件
Inventory 管理
在 Ansible 中,将可管理的服务器集合称为 Inventory。因此,Inventory 管理便是服务器管理。
hosts文件位置
1.默认读取 /etc/ansible/hosts 文件;
2.通过命令行参数 -i 指定hosts文件;
3.通过ansible.cfg 文件中的inventory选项指定hosts文件
web.tongwen.com
db1.tongwen.com
db2.tongwen.com
web
db
通过common这个组名可以匹配到 web 和 db 两个组的主机列表
Ansible 通过在组名称后面加上 “:children” 的方式声明这个组下面包含的是其他组的名称,而不是普通的服务器地址。
除了通过组名称来引用hosts文件中定义的主机以外,Ansible还支持通配符、正则表达式等更加灵活的方式来匹配服务器。
ansible <pattern_goes_here> -m <module_name> -a <arguments>
Ansible 匹配服务器时,可以是组名匹配,也可以是模式匹配
ansible web -m service -a “name=httpd state=restarted”
ansible web*.tongwen.com -m service -a “name=httpd state=restarted”
匹配规则: 可以结合 —list-hosts 选项验证Ansible的主机匹配
规则含义web匹配目标组为 web ,多个组以 “:” 分隔192.168.1.1或web1.tongwen.com 匹配目标IP地址或服务器名,如果有多个IP或服务器,以 : 分隔all 或 *匹配所有服务器web:!db匹配web组中且不在db组中的服务器*.tongwen.com 或 192.168.*使用通配符匹配web,web,web[-1]使用索引或切片的方式匹配组中的服务器~(web|db).*.tongwen.com 以~开头的匹配,表示使用正则表达式匹配 动态Inventory获取
动态获取服务器列表,可以减少服务器列表的维护操作
可以通过OpenStack的API或者CMDB数据库中的纪录获取Inventory列表
Inventory 行为参数
名称默认值描述ansible_host主机名称SSH的目的主机名或IPansible_user当前用户SSH连接的用户名ansible_port22SSH连接的端口号ansible_ssh_private_key_filenoneSSH连接使用的私钥ansible_connectionsmartAnsible使用的连接模式,smart、ssh 或 paramikoansible_becomenone类似Linux下的sudoansible_become_usernone切换到哪个用户执行命令ansible_shell_typesh执行命令所使用的shellansible_python_interpreter/usr/bin/python使用哪个Python解释器ansible_*_interpreternone指定其他语言的解释器 定义服务器变量:
hosts文件中,除了行为参数,还可以定义普通的变量。
参数名必须为字母、数字和下划线的组合,并且 首字符必须为字母。
127.0.0.1 mysql_port=3306
192.168.1.1 mysql_port=3307
ansible all -a “echo {{mysql_port}}”
127.0.0.1 mysql_port=3306
192.168.1.1
192.168.1.2
mysql_port=3307
需要定义多个变量时:
为每个服务器和群组创建独立的变量文件
将组的变量文件存放在名为 group_vars 目录下,目录下的文件名与组的名称相同,文件的扩展名.yml/.yaml或没有扩展名
服务器的变量文件存放在名为 host_vars 目录下,文件名与服务器名称相同。
Ansible 将依次在Playbook所在的目录、hosts文件所在的目录和 /etc/ansible/ 目录下寻找 group_vars / host_vars 目录。
vim /etc/ansible/group_vars/db.yml
mysql_port: 3307
此文件遵循YAML语法格式。
YAML 语法
YAML的语法规则如下:
YAML的第一行为”---",表示这是一个YAML文件;
YAML中的字段大小写敏感;
YAML与Python一样,用缩进表示层级关系;
YAML的缩进不允许用Tab键,只运行使用空格,且空格的数目不重要,只要相同层级的元素左侧对齐即可;
# 表示注释,从这个字符一直到行尾都会被解析器忽略;
YAML 支持三种格式的数据,分别是:
对象: 键值对的集合,又称为映射,类似于Python中的字典
数组: 一组按次序排列的值,又称为序列(sequence),类似Python中的列表
纯量: scalars,单个的、不可再分的值,如字符串、布尔值与数字
Ansible 的常用模块
工作原理:
将模块拷贝到远程服务器
执行模块定义的操作,完成对服务器的修改
在远程服务器中删除模块
ansible-doc -l
ansible-doc -l file
ansible-doc file
常用的模块:
1.ping 测试现有的SSH参数是否能够顺利连通远程服务器。
ansible group -m ping
2.远程命令模块
command、raw、script、shell 模块都可以实现在远程主机上执行Linux命令。command 是默认模块。
raw模块相当于使用SSH直接执行Linux命令,不会进入到Ansible的模块子系统中
shell模块还可以执行远程服务器上的shell脚本文件
ansible group -m shell -a “/root/sc/a.sh”
script模块可以在远程服务器上执行主控节点中的脚本文件,其功能相当于scp+shell的组合,执行完后会删除远程服务器上的脚本文件
ansible group -m script -a ’test.sh’
3.file 主要用于对远程服务器上的文件进行操作(包括链接和目录),修改文件的权限、属主、创建删除文件
path 执行文件、目录的路径
recurse 递归设置文件属性,只对目录有效
group 定义文件、目录的组
mode 定义文件/目录的权限
owner 定义文件/目录的所有者
src 要被链接的源文件路径,只应用与state为link 的情况
dest 被链接到的路径,只应用于state为link的情况
force 在两种情况下会强制创建软链接,一种是源文件不存在但之后会建立的情况;一种是目标软链接已经存在,需要先取消之前的软链接,然后创建新的软链接,默认值 no。
ansible group -m file -a “path=/data/release state=directory mode=0755” 创建目录
ansible group -m file -a “path=/data/release state=touch mode=‘u=rw,g=r,o=r'" 修改权限
ansible group -m file -a “src=/etc/passwd dest=/tmp/passwd state=link owner=wt group=wt" 创建一个软链接
ansible group -m file -a ’path=/tmp/passwd owner=root group=root mode=0644’ -become 修改文件的所有者
4.copy 用于将主控节点上的文件或目录拷贝到远程服务器上,类似scp
src 指定要复制到远程主机的文件或目录。如果路径以 / 结尾,则只复制目录里的内容,如果没有以 / 结尾,则复制包含目录在内的整个内容
dest 文件复制的目的地,必须是一个绝对路径,如果源文件是一个目录,那么dest指向的也必须是一个目录
force 默认取值为yes,表示目标主机包含此文件,但内容不同时,覆盖。
backup 默认取值为no,如果为yes,在覆盖前将原文件进行备份
directory_mode 递归设定目录权限,默认为系统默认权限
others 所有file模块里的选项都可以在这里使用
ansible web -m copy -a “src=index.html dest=/data/release/html/index.html" 拷贝文件到服务器
ansible web -m copy -a “src=index.html dest=/data/release/html/index.html backup=yes force=yes” 拷贝文件到服务器,如果已存在,备份后覆盖
ansible web -m copy -a ’src=index.html dest=/data/release/html/index.html owner=root group=root mode=644 force=yes’ -become
5.user/group useradd/userdel/usermod groupadd/groupdel/groupmod
name 需要操作的用户名或组名
comment 用户的详细描述
createhome 创建用户时,是否创建用户的家目录,默认为yes
home 指定用户的家目录,需要和createhome 配合使用
groups 指定用户的属组
uid 设置用户的uid
gid 设置群组的gid
password 设置用户的密码
state 创建用户or删除用户 present 和 absent
expires 用户的过期时间
shell 指定用户的shell环境
ansible web -m user -a ’name=wt comment=“wt user” uid=1001 group=root’ -become 创建一个用户
ansible web -m user -a ’name=wt state=absent’ -become 删除一个用户
ansible web -m user -a ’name=wt comment=“wt user” generate_ssh_key=yes ssh_key_bits=2048’ -become 创建一个用户并生成一对密钥
ansible web -m group -a ’name=wt state=present gid=1001’ -become
ansible web -m group -a ’name=wt state=absent’ -become
6.apt debian ubuntu系统中安装软件/删除软件
name 包名
state 软件包的状态,latest、absent、present、build-sep, 默认为present
autoremove 默认取值为no,如果取值为yes,将会移除不需要的软件包
force 强制安装或删除软件包
update_cache 作用与 apt-get update相同
deb deb文件的路径
ansible web -m apt -a ’name=git state=present’ -become
ansible web -m apt -a ’name=git state=absent’ -become
ansible web -m apt -a ’update_cache=yes’ -become
7.get_url 从互联网下载数据到本地,作用类似于Linux下的curl。
url 必传选项,文件的下载地址
dest 必传选项,文件保存的绝对路径
mode 文件的权限
others 所有file模块里的选项都可以在这里使用
checksum 文件的校验码
headers 传递给下载服务器的HTTP Headers
backup 如果本地已经存在同名文件,备份文件
timeout 下载的超时时间
ansible web -m get_url -a ‘url=http://xxx.com.xxx dest=/opt/xxx mode=0777 checksum=324988594fsj239432u'
8.unarchive
remote_src 默认为no,用来表示解压的文件在远程服务器中还是存在控制节点上。yes 先将控制节点上的文件复制到远程主机中,然后再进行解压。
src 指定压缩文件到路径,该选项到取值取决与remote_src的取值,如果remote_src取值为yes,则src指定的路径是远程服务器中压缩包的地址,如果remote_src取值为no,则src指向的是控制节点中的路径
dest 该选项指定的是远程服务器上的绝对路径,表示压缩文件解压的路径;
list_files 默认情况下该选项取值为no,如果该选项取值为yes,也会解压文件,并且在ansible的返回值中列出压缩包里的文件
exclude 解压文件时排除exclude选项指定的文件或目录列表
keep_newer 默认取值为False,如果该选项取值为True,那么当目标地址中存在同名的文件,并且文件必压缩包中的文件更新时,不进行覆盖
owner
group
mode
ansible web -m unarchive -a ’src=data.tar.gz dest=/tmp/data list_files=yes’
ansible web -m unarchive -a ’src=data.tar.bz2 dest=/tmp/data.tar.bz2’
ansible web -m unarchive -a ’src=/tmp/data.tar.bz2 dest=/tmp remote_src=yes’
9.git 在远程服务器执行 git 相关操作
repo 远程git 库的地址,可以是git协议、ssh、http协议的git库地址
dest 必选选项,git库 clone 到本地服务器以后保存到绝对路径
version 克隆远程git库的版本,取值可为HEAD、分支多名称、tag名称,也可以是一个commit 的hash值
force 默认取值为no,当该选项取值为yes时,如果本地的git库有修改,将会抛弃本地的修改
accept_hostkey 当该选项取值为yes时,如果git库的服务器不在know_hosts中,则添加到know_hosts中,key_file指定科隆远程git库地址时使用的私钥
ansible web -m git -a ‘repo=https://github.com/kennethreitz/requests.git dest=/tmp/requests version=HEAD’ 将requests克隆到/tmp/requests目录下
ansible web -a ‘python setup.py install chdir=/tmp/requests’ -become 从源码安装requests
ansible web -a ‘python -c “import requests”'
10.stat 获取远程服务器上的文件信息,类似Linux 下的stat命令,stat命令可以获取time、ctime、mtime、checksum 、> path 指定文件或目录的路径
ansible web -m stat -a “path=/etc/passwd”
11.cron cron是管理Linux下计划任务的模块
backup 默认 no,当为yes时,表示修改之前先做备份
state 取值为present或absent,用来确认该任务是创建还是删除
name 任务的描述/名字
job 添加或删除任务,主要取决于state 的取值
user 操作哪一个用户的crontab
cron_file 如果指定该选项,则用该文件替换远程主机上的cron.d 目录下的用户任务计划
monthweekdaydayminutehour 取值与crontab类似
minute 取值范围0~59,*表示每分钟运行,*/5 表示每5分钟运行
ansible web -m cron -a ‘backup=yes name=“nginx_log split” minute=*/2 hour=* job=“ls /tmp > /dev/null” '
12.service 类似Linux 下的service命令,用来启动、停止、重启服务
name 服务的名称,该选项为必选项
state 取值为 started、stopped、restarted、reloaded。 started和stopped为幂等的,也就是已经启动的服务,执行started不会有任何操作
sleep 重启的过程中,先停职服务然后sleep几秒再启动
pattern 定义一个模式,Ansible首先通过status命令查看服务的状态,以此判断服务是否在运行,如果通过status查看服务状态时没有响应,Ansible会尝试匹配ps命令的输出,当匹配到相应模式时,认为服务已经启动,否则认为服务没有启动
enabled 取值为yes 或 no,用来设置服务是否开机启动
ansible web -m apt -a “name=apache2 state=present” -become
ansible web -m service -a ’name=apache2 state=stopped’
ansible web -m service -a ’name=apache2 state=restarted’
13.sysctl与linux 下 sysctl命令相似,控制Linux 内核参数
name 需要设置的参数
value 需要设置的值
sysctl_file sysctl.conf 文件的绝对路径,默认路径为/etc/sysctl.conf
> ansible web -m sysctl -a ’name=vm.overcommit_memory value=1’ -become
14.mount 在远程服务器上挂载磁盘,在挂盘操作时,如果指定的挂载点不存在,则创建该路径
name 挂载点的路径
state present、absent、mounted、unmounted。其中mounted与unmounted用来处理磁盘的挂载和卸载,并且会正确配置stab文件,present和absent只会设置stab文件,不会去操作磁盘
fstype 指定文件系统类型,当state取值为present或mounted时,该选项为必填选项
src 挂载点设备
ansible web -m mount -a ’name=/mnt/data src=/dev/vda fstype=ext4 state=mounted’
15.synchronize 对rsync命令的封装
src 需要同步到远程服务器的文件或目录
dest 远程服务器保存数据的路径
archive 默认取值为yes,相当于同时开启recursive、links、perms、times、owner、group、-D选项
compress 默认为yes,表示在文件同步过程中启用压缩
delete 默认为no,当取为yes时,表示删除dest中存在而src中不存在的文件
ansible web -m synchronize -a ’src=/data/test dest=/tmp’
模块的返回值
返回值的名称返回值的含义changed几乎所有的Ansible模块都会返回该变量,表示模块是否对远程主机执行了修改操作failed模块未能执行完成,返回failed 为 truemsg模块执行失败的原因,常见的错误如ssh连接失败,没有权限执行模块等rc与命令行工具相关的模块会返回rc,表示执行Linux命令的返回码stdout与rc类似,返回的是标准输出的结果stderr与rc类似,返回的是错误输出的结果backup_file所有存在backup选项的模块,用来返回备份文件的路径results应用在Playbook中存在循环的情况,返回多个结果 Role
Playbook
vim test_playbook.yml
---
- host: web
become: yes
become_method: sudo
tasks:
- name: copy file
copy: src=/tmp/index.html dest=/html/index.html
- name: change mode
file: dest=/html/index.html mode=500 owner=nginx group=nginx
- name: ensure packages installed
yum: pkg={{ item }} state=present
with_items:
- telnet
- git
Playbook 中首先包含了一些声明信息,如hosts关键字声明该Playbook应用的服务器列表,-表示定义列表
become和become_method表示在远程服务器通过sudo执行操作
Playbook最后包含了若干task,每一个task对应于前面的一条ad-hoc命令。具体执行时,多个task按顺序执行
ansible-playbook test_palybook.yml
Ansible中,每个play必须包含以下两项:
hosts 需要对哪些远程服务器执行操作
tasks 需要在这些服务器上执行的任务列表
task的定义形势:
module: options
action: module options (老版,已弃用)
- name: install apache
apt: name=apache2 update_cache=yes state=present
YAML 中使用>进行折叠,参数较多时,Playbook 可以这么写:
- name: install apache
apt: >
name=apache2
update_cache=yes
state=present
也可以使用缩进子块的形式:
- name: install apache2
apt:
name: apache2
update_cache: yes
state: present
前者代表一个比较长的字符串,后者是一个字典。在task中,name是可选的。
在Playbook 中导入其他 Playbook
vim all.yml
---
- include: db.yml
- include: web.yml
Playbook > Play > task
ansible-playbook all.yml
ansible-playbook & ansible 命令相同的子命令
-T —timeout: 建立SSH连接的超时时间
—key-file —private-key: 建立SSH连接时的私钥
-i —inventory-file: 指定Inventory 文件,默认为 /etc/ansible/hosts
-f —forks: 并发执行的进程数,默认5
—list-hosts: playbook 匹配的服务器列表
ansible-playbook 特有的命令选项
—list-tasks: 列出任务列表
—step: 每执行一个任务后停止,等待用户确认, N,y,c。 no yes continue
—syntax-check: 检查Playbook 的语法
-C —check: 检查当前Playbook是否会修改远程服务器,相当于测试Playbook的执行结果
权限:默认使用当前用户进行连接远程服务器执行操作
使用的用户
---
- hosts: web
remote_user: root
tasks:
- name: test connection
ping:
remote_user: wt
使用sudo
---
- hosts: web
remote_user: wt
tasks:
- service: name=nginx state=started
become: yes
become_method: sudo
通知:notify、handler
handler 是 Ansible 提供的条件机制,与tasks比较类似,都是去执行某些操作。但handler只有在被notify触发后才会执行
在Playbook 中,如果 tasks 后面存在 notify 选项,那么, 当 Ansible 识别到task 改变了系统的状态,就会通过notify触发handler
task 使用 handler 的名字作为参数,以此来触发特定的 handler。
---
- hosts: web
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: write the apache config file
template: src=/data/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
handler 只会在所有task执行完后执行。一个handler被触发多次,它也只会执行一次。
变量:
将变量定义在playbook的vars选项中
- hosts: web
vars:
mysql_port: 3307
将变量保存在独立的文件,并通过 vars_files 选项引用
- hosts: web
vars:
favcolor: blue
vars_files:
- /vars/ex_vars.yml
tasks:
- name: this is just a placeholder
command: /bin/echo foo
保存变量的文件是一个简单的YAML格式的字典:
somevar: some value
password: wt
将任务的执行结果存储为变量, 注册变量,使用 register 获取
---
- hosts: web
tasks:
- shell: /usr/bin/foo
register: foo_result
ignore_errors: True
- shell: /usr/bin/bar
when: foo_result.rc == 5
Facts 变量:Ansible 执行远程部署之前从远程服务器中获取的系统信息,包括服务器名称、IP、操作系统、分区信息、硬件信息等
ansible web -m setup 通过setup 模块查看 Facts 变量的列表
可以在 playbook 中直接通过变量名字进行引用,也可以在jinja2模版中通过变量的名字引用变量。
---
- hosts: web
tasks:
- shell: echo {{ansible_os_family}}
register: myecho
- debug: var=myecho.stdout_lines
- name: install git on Debian Linux
apt: name=git state=installed
when: ansible_os_family == ‘Debian’
setup 模块为了输出结果的可读性,对模块的输出进行了归类和整理。因此,当我们访问复杂的子属性时,需要使用嵌套结构
后去ipv4地址
ansible_eth0[“ipv4”][“address”]
ansible_eth0.ipv4.address
---
- hosts: web
gather_facts: yes
tasks:
- shell: echo {{ansible_eth0[“ipv4”][“address"]}}
register: myecho
- debug: var=myecho.stdout_lines
- shell: echo {{ansible_eth0.ipv4.address}}
register: myecho
- debug: var=myecho.stdout_lines
gather_facts 选项控制是否收集远程服务器的信息,默认取值为yes,不需要可以设为no,提高ansible的部署效率
循环:
- name: install mysql
yum: name={{ item }} state=installed
with_items:
- mysql-server
- MySQL-python
- libselinux-python
条件:在 Playbook 中可以通过when选项执行条件语句
tasks:
- name: “shut down Debian flavored systems”
command: /sbin/shutdown -t now
when: ansible_os_family == “Debian”
when 选项支持多个条件语句,下面时一个YAML格式的多条件:
tasks:
- name: “shut down Ceontos6 systems”
command: /sbin/shutdonw -t now
when:
- ansible_distribution == “Centos”
- ansible_distribution_major_version == “6”
and / or
tasks:
- name: “shut down Centos 6 and Debian 7 systems”
command: /sbin/shutdown -t now
when: (ansible_distribution == “Centos” and ansible_distribution_major_version == “6”) or (ansible_distribution == “Debian” and ansible_distribution_major_version == “7”)
when 选项中可以使用Jinja2的过滤器
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/someting
when: result|failed
- command: /bin/someting_else
when: result|succeeded
when读取变量的值
vars:
epic: True
tasks:
- shell: echo “This certainly is epic”
when: epic
when选项和循环一起使用
tasks:
- command: echo {{ item }}
with_item:
when: item > 5
任务执行策略:
Ansible中,Playbook 的执行是以task为单位进行的。Ansible 默认使用5个进程对远程服务器执行任务。在默认情况的任务执行策略(linear)中,Ansible首先执行task1,并且等所有服务器都执行完了task1再开始执行task2,以此类推。 Ansible2.0开始,支持名为free的任务执行策略,允许执行快的服务器提前完成Play的部署,不用等待其他服务器
---
- hosts: web
strategy: free
tasks:
Playbook 部署 Nginx
---
- hosts: web
become: yes
become_method: sudo
vars:
worker_processes: 4
worker_connections: 768
max_open_files: 65506
tasks:
- name: install nginx
apt: name=nginx update_cache=yes state=present
- name: copy nginx config file
template: src=/home/wt/ansible/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: copy index.html
template:
src: /home/wt/ansible/index.html.j2
dest: /usr/share/nginx/www/index.html
mode: 0644
notify: restart nginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
页:
[1]