Ansible

什么是Ansible

Ansible是基于python语言开发的,由paramiko和pyYAML两个关键模块构建。playbook是Ansible的核心,是ansible的配置、部署、编排语言,基于YAML语言来编写。

可以做的事:

配置管理

服务及时开通

应用部署

流程编排

监控告警

日志记录


Ansible优点和特性

无代理(采用openssh进行管理)、去中心化、模块化

Ansible tower是ansible的web管理界面

Ansible架构

ansible使用_第1张图片

Ansible安装

rpm包安装

#安装epel源
yum install epel-release
#安装ansible
yum install -y ansible

编译安装

wget ansible-*
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar zxf ansible-*
cd ansible

pip安装

#安装epel源
yum install epel-release
yum install python-pip python-devel
yum install gcc glibc-devel zlib-level rpm-build openssl-devel
pip install --upgrade pip
pip install ansible --upgrade

Ansible使用

ansible配置文件

/etc/ansible/ansible.cfg        主配置文件
#配置项
host_key_checking = False       不检查指纹key

/etc/ansible/hosts                  主机清单
/etc/ansible/roles/                 存放角色的目录

#脚本
基于ssh-key的免密登陆

ansible实现管理的主要方式

Ad-Hoc:即利用ansible命令,主要用于临时命令的使用场景

Ansible-playbook:主要用于长期规划好的,大型项目的场景,需要有前期的规划过程

ansible主要工具

ansible-doc

ansible-doc用来显示模块帮助

#格式
ansible-doc [option] [module...]
#option
    -l, --list              列出可用模块
    -s, --snippet           显示指定模块的playbook片段
#例
ansible-doc -l
ansible-doc -s ping

ansible

#格式
ansible  [-m module_name] [-a args]
#host-pattern,用于匹配被控制的主机列表
    all                         表示inventory主机清单中的所有主机

#选项
    -m module               指定模块,默认command
    -v                          详细过程
    --list-hosts        显示主机列表,可简写--list
    -k, --ask-pass  提示输入ssh链接密码,默认key验证
    -C, --check         检查,并不执行
    -T, --timeout=num       执行命令的超时时间,默认10s
    -u, --user=username 执行远程执行的用户,被控端的用户
    -b, --become        代替旧版的sudo切换
    --becom-user=username        指定sudo的用户,默认为root
    -k, --ask-become-pass           提示输入sudo时的口令/密码

#通配符*
#例
ansible "*" -m module ping
ansible "10.1.1.*" -m module ping

#或关系
#10.1.1.1主机或者10.1.1.10主机
ansible "10.1.1.1:10.1.1.10" -m module ping

#逻辑与
#在webservers组并在dbservers组的主机
ansible "webservers:$dbservers" -m module ping

#逻辑非
#在webservers组,但不在dbservers组中的主机
#逻辑非中主机用单引号''引起来
ansible 'webservers:!dbservers' -m module ping

#正则表达式

ansible执行过程

  • 加载自己的配置文件,默认/etc/ansible/ansible.cfg
  • 加载自己对应的模块文件,如command
  • 通过ansible将模块或者命令生成对应的py临时文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-NUM/xxx.py文件
  • 给文件+x权限
  • 执行并返回结果
  • 删除临时py文件,退出

ansible-galaxy

此工具会下载相应的角色roles,网站:https://galaxy.ansible.com

#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy-redis

ansible-pull

此工具会推送ansible的命令至远程,效率无限提升,对运维要求较高

ansible-playbook

此工具用于执行以编写好的playbook任务

#例
ansible-playbook hello.yml

ansible-vault

此工具用于加解密yml文件

#格式
ansible-vault [create|decrypt|edit|encrypt|rekey|view] 文件名
#例
ansible-vault encrypt hello.yml         加密文件
ansible-vault decrypt hello.yml         解密文件
ansible-vault view hello.yml                查看文件
ansible-vault edit hello.yml                编辑文件
ansible-vault rekey hello.yml               修改口令
ansible-vault create hello.yml          创建新文件

ansible-console

此工具可交互执行命令,支持tab,ansible2.0+新增

#格式
执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$

#常用子命令
设置并发数:   forks n        例如:forks 10
切换组:            cd 主机组   例如:cd webappservers
列出当前主机组列表:      list
列出所有内置命令:           ?或help

#例
root@all (2)[f:5]$ list
root@all (2)[f:5]$ cd appservers
root@appservers (2)[f:5]$ yum name=httpd state=present
root@appservers (2)[f:5]$ service name=httpd state=started

ansible常用模块

command模块

在远程主机执行命令,此为默认模块,可忽略-m选项

此模块不支持变量 < > | ; &等

#例
ansible webservers -a 'echo hello > /data/hello.txt'
ansible webservers -m command -a 'echo hello world!'
shell模块

shell模块和command相似,用shell执行命令,此模块支持变量 < > | ; & *等各种符号,比command更强大

可以在ansible.cfg中更改默认command为shell模块

#例
ansible webservers -m shell -a 'echo $HOSTNAME'
script模块

在远程主机运行ansible服务器上的脚本,此模块会把脚本复制到远程主机,执行完毕后删除

ansible webservers -m script -a /data/test.sh
copy模块

从ansible服务器复制到远程主机

#如果目标存在,默认覆盖,先指定备份
#例1
ansible webservers -m copy -a "src=/root/test.sh dest=/tmp/test.sh owner=wang mode=600 backup=yes"
#解释
src         ansible服务器文件位置
dest        远程主机文件位置
owner       属主
mode        权限
backup  是否备份

#将文本内容直接复制到远程主机
#例2
ansible webservers -m copy -a "content='test line1\ntest line2' dest=/tmp/test.txt"
#解释
content=        输入文本内容
\n                  为换行
dest                远程主机位置
fetch模块

从远程主机提取文件至ansible主控端,与copy相反,目前不支持目录

#例
ansible webservers -m fetch -a "src=/root/test.sh dest=/data/scripts"
file模块

设置文件属性,创建空文件

#创建空文件
#例
ansible webservers -m file -a "path=/date/test.txt state=touch"

#删除空文件
ansible webservers -m file -a "path=/date/test.txt state=absent"        

#设置属性
ansible webservers -m file -a "path=/date/test.txt owner=wang mode=644"

#创建目录
ansible webservers -m file -a "path=/data/mysql state=directory owner=wang group=mysql"

#创建软连接
ansible webservers -m file -a "src=/data/link1 dest=/tmp/link1 state=link"
unarchive模块

解压缩包

实现的两种用法:

1.将ansible主机的压缩包传到远程主机解压缩至特定目录,设置copy=yes

2.将远程主机上的某个压缩包解压到指定路径下,设置copy=no

​ copy:默认为yes,当copy=yes时,拷贝的文件是从ansible主机复制到远程主机上,如果设置copy=no时,会在远程主机上寻找src原文件

​ remote_src:和copy功能一样互斥,yes表示在远程主机,不再ansible主机,no表示文件在ansible主机上

​ src:源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是让远程主机上的路径,则需要设置copy=no

​ dest:远程主机上的目标路径

​ mode:设置解压缩后的文件权限

#例
 ansible webservers -m unarchive -a "src=/tmp/etc.tar.gz dest=/tmp/test/"
archive模块

打包、压缩

ansible webservers -m archive -a "path=/tmp/test/etc dest=/tmp/file1.tar.bz2 format=bz2 owner=wang mode=600"
hostname模块

管理主机名

ansible 10.1.1.1 -m hostname -a "name=mysql_server"
cron模块

计划任务

支持的时间:分钟minute,小时hour,天day,月month,周weekday

#例
#创建计划任务
ansible 10.1.1.1 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'

#解释
job                         远程主机上的文件路径

disabled=yes        禁用计划任务
disabled=no         启用计划任务

#删除计划任务
ansible webservers -m cron -a "name='backup mysql' state=absent"
yum模块

管理软件包,只支持RHEL系列OS,不支持Ubuntu等OS

yum默认安装最新版本

#安装
ansible webservers -m yum -a "name=httpd state=prsent"
#卸载
ansible webservers -m yum -a "name=httpd state=absent"
service模块

服务的管理

#启动服务
ansible webservers -m service -a "name=httpd state=started"
#停止服务
ansible webservers -m service -a "name=httpd state=stopped"

#参数
enable          开启启动yes或no
state               started、stopped、restarted
user模块

用户管理

#创建用户
ansible webservers -m user -a 'name=user1 comment="test user" uid=608 home=/app/user1 group=class shell=/sbin/nologin'

#删除用户及家目录
ansible webservers -m user -a "name=user1 state=absent remove=yes"
group模块

用户组管理

#创建组
ansible webservers -m group -a "name=group1 gid=999"
#删除组
ansible webservers -m group -a "name=group1 state=absent"
lineinfile模块

相当于sed,可以修改文件内容,在ansible使用sed时会遇到特殊符号替换的问题

ansible webservers -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=enforcing'"

#解释
path            需要修改的文件
regexp      过滤条件
line            修改的内容
replance模块

类似sed命令,主要基于正则表达式进行匹配和替换

#注释UUID开头的行
ansible webserver -m replance -a "path=/etc/fstab regexp=^(UUID.*) replance='#\1'"
setup模块

收集主机的系统信息,这些facts信息可以直接以变量的形式使用,但是如果有多台主机,会影响执行速度,可以使用gather_facts=no来禁止ansible手机facts信息

ansible webservers -m setup -a "filter=..."

filter      过滤字段

playbook

playbook介绍

playbook是由一个或多个play组成的列表

playbook主要功能是将定义的一组主机,装扮成事先通过ansible中的task定义好的角色。tast实际是调用ansible的一个module,将多个play组织在一个playbook中,即让它们联合起来,按事先编排的机制执行预定义的动作

playbook文件是采用YAML语言编写的

YAML语言

一种标记语言,可读性高

语言特性

  • YAML可读性好
  • YAML和脚本语言的交互性好
  • YAML使用实现语言的数据类型
  • YAML有一个一致的信息模型
  • YAML易于实现
  • YAML可以基于流来处理
  • YAML表达能力强,扩展性好

格式

在单一文件第一行,用连续三个”-“开始,还有选择性的连续三个点“...”用来表示文件的结尾

第二行开始写正常的playbook内容,一般建议写该playbook的功能

使用#注释代码

缩进必须是统一的,不能空格和tab混用

缩进的级别也必须是统一的,同样的缩进代表同样的级别,程序判断配置的级别是通过缩进结合换行来实现的,YAML文件内容是区分大小写的,key/value的值均需大小写

多个k/v可同行写也可换行写,同行使用,分隔

v可以是字符串,也可以是另一个列表/数组

一个完整的代码块功能需最少元素包括name和task

一个name只能包括一个task

YAML文件扩展名通常为yml或yaml

YAML常见的数据结构

list列表

列表由多个元素组成,且所有元素前均使用“-”开头

#例

#a list of tasty fruits
- Apple
- Orange
- strawberry

[Apple,Orange,strawberry]

dictionary字典

字典通常由多个key与value构成

#例

#an employee record
name: example developer
job: developer
skill: elite

{name: "example developer",job: "developer",skill: "elite"}

playbook核心元素

hosts

执行的远程主机列表

#例
- hosts: webservers:appservers     或
remote_user

可用于hosts和task中,指定通过sudo切换到某个用户的方式在远程主机执行任务

#例
- hosts: webservers
  remote_user: root

  task:
    - name: test connection
      ping:
      remote_user: jack
      sudo: yes
      sudo_user: wang       #默认sudo为root,修改sudo为wang
task和action

主要为task list,可以有多个task list

task两种格式:

1.action:module arguments

2.module:arguments (建议使用)

shell和command模块后面跟命令,不是key/value

#例
- hosts: webservers
  remote_user: root

  task:
    - name: install httpd
      yum: name=httpd
    - name: start httpd
      service: name=httpd state=started enable=yes
其他组件

playbook命令

#格式
ansible-playbook  ... [option]

#常见选项
-C --check                  只检测可能会发生的改变,但不真正执行操作
--list-hosts                    列出运行任务的主机
--list-tags                     列出tag
--list-tasks                    列出task
--limit 主机列表             只针对主机列表中的主机执行
-v -vv -vvv                     显示过程
#playbook文件范例
#创建mysql用户和组
---
# create mysql user and group
- hosts: dbservers
  remote_user: root

  tasks:
    - name: create mysql group
      group: name=mysql system=yes gid=330
    - name: "create mysql user"
      user: name=mysql system=yes group=mysql shell=/sbin/nologin create_home=no home=/data/mysql uid=330
#group、user都是模块
#name: 动作名称
#name= key/value

#检查是否有错误,执行playbook
ansible-playbook /etc/ansible/playbook/install_mysql.yml -C
ansible-playbook /etc/ansible/playbook/install_mysql.yml
#查看是否成功
ansible dbservers -m shell -a "getent passwd mysql"
ansible dbservers -m shell -a "id mysql"

handlers和notify

类似mysql中的触发器触发的动作行为

handlers触发行为,notify触发器

#例yml文件
---
- hosts: webservers
  remote_user: root

  task:
    - name: install httpd
      yum: name=httpd state=present
    - name: copy configure file
      copy: src=file/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd    #notify与handlers中name内容必须一致,相当于一个函数,在此调用函数
    - name: start httpd service
      service: name=httpd state=started enabled=yes

    handlers:
      - name: restart httpd    #notify与handlers中name内容必须一致,相当于一个函数,在此调用函数
        service: name=httpd stated=restarted

#notify出发多个动作
#例
      notify: 
        - restart httpd
        - check httpd process

      handlers:
        - name: restart httpd
          service: name=httpd state=restarted enabled=yes
        - name: check httpd process
          shell: killall -0 httpd &> /tmp/httpd.log

#killall -0 (数字0,检查进程是否存在)

playbook中的变量

变量名只能以字母开头,字母、数字和下划线组成,

```` yml
#变量定义
variable_name=value

#例
http_prot=80

#调用方式
通过{{ variable_name }}调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才能生效

#变量来源
1.ansible的setup facts远程主机的所有变量都可以直接调用,在playbook中调用,命令行不可调用

2.通过命令行指定变量,优先级最高
#例
ansible-playbook -e "variable_name=value"

3.在playbook文件中定义变量
#例

  • hosts: webservers
    remote_user: root
    vars: #定义多个变量variable: value
    • username: user1
    • groupname: group1
      #调用变量
      task:
      • name: create group
        group: name={{ groupname }} state=present
      • name: create user
        user: name={{ username }} state=present

4.使用变量文件
#建立一个独立的playbook文件用来定义文件
#例
vim vars.yml

#variables file
username: user1
groupname: group1
...
#在另一文件中调用变量

  • hosts: webservers
    remote_user: root
    vars_files: #调用变量文件
    • /etc/ansible/variable/vars.yml #文件名路径
      task:
      • name: create group
        group: name={{ groupname }} state=present
      • name: create user
        user: name={{ username }} state=present

5.主机清单文件中定义变量
#例
#定义主机变量
[webservers]
172.16.99.144 http_port=80
#定义主机组变量
[webservers:vars]
ntp_server=ntp.server1.com
http_port=80


#### template模版

> ansible的一个模块
>
> 模版是一个文本文件,可以作为生成文件的模版,并且模版文件中还可以嵌套jinja语法

**jinja2语言**

> jinja2语言使用字面量,有下面形式:
>
> 字符串:使用单引号或双引号
>
> 数字:整数,浮点数
>
> 列表:[item1,item2,...]
>
> 元组:[item1,item2,...]
>
> 字典:{key1:value,key2:value,...}
>
> 布尔型:true/false
>
> 算术运算:+,-,*,/,//,%,**
>
> 比较操作:==,!=,>,<,>=,<=
>
> 逻辑运算:and,or,not
>
> 流表达式:for, if,when
>
> 字面量:表示字符串和数值

**template**

> 功能:可以根据和参考模块文件,动态生成相类似的配置文件
>
> template文件见必须放在template目录下,命名为*.j2结尾
>
> yaml文件和templates目录平级

````shell
#利用template同步nginx配置文件
#准备templates/nginx.conf.j2
vim temnginx.yml
---
  - hosts: webservers
    remote_user: root

    task:
      - name: template config to remote hosts
        template: src=nginx.conf dest=/etc/nginx/nginx.conf

ansible-playbook temnginx.yml 

##template替换,相当于cp
mkdir templates
cp nginx.conf /etc/ansible/templates/nginx.conf.j2
vim /etc/ansible/templates/nginx.conf.j2
#添加下面一行,工作进程
worker_processes {{ ansible_processor_vcpus }};

#修改temnginx2.yml文件
vim temnginx2.yml
---
  - hosts: webservers
    remote_user: root

    task:
      - name: template config to remote hosts
        template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

ansible-playbook temnginx2.yml

#算数运算
worker_processes {{ ansible_processor_vcpus**2 }};

#template文件中的流程控制if和for,在*.j2文件中编辑好后,在yml文件中调用此文件
定义nginx_vhost列表
{% for vhost(变量名) in nginx_vhosts(列表) %}
server {
    listen {{ vhost.listen }}
}
{% endfor %}

#when语句条件测试,在yml文件使用when,j2文件使用if
    task:
      - name: "shutdown"
        when: ansible_os_family == "RedHat"
        command: /sbin/shutdown -h now

#playbook文件中迭代with_items
#重复性执行任务,固定变量名item
   task:
     - name: add users
       user: name={{ item }} state=present group=wheel
       with_item:
         - testuser1
         - testuser2

roles角色

role是ansible1.2版本引入,用于层次性、结构化的组织playbook。role能够根据层次结构自动装载变量文件、task以及handlers等。要使用roles只需在playbook中使用include指令即可

运维复杂的场景建议使用roles,代码复用度高

roles:多个角色的集合,可以将多个role,分别放至目录roles下的独立自目录中

roles目录结构

playbook.yml

roles/

​ project/ 项目名称

​ tasks/ 任务,至少包含一个名为main.yml的文件,include调用

​ files/ copy或script等文件

​ vars/ 变量

​ templates/ 模版,至少包含一个名为main.yml的文件,include调用

​ handlers/ 变量,至少包含一个名为main.yml的文件,include调用

​ default/ 默认变量,优先级比vars低

​ meta/ 元数据,至少包含一个名为main.yml的文件,include调用

​ ...

main.yml文件中定义了yml的执行顺序

#调用角色方法一
---
  - hosts: webservers
    remote_user: root
    roles:
      - mysql
      - nginx

#调用角色方法二
#传递变量给角色
---
  - hosts: webservers
    remote_user: root
    roles:
      - mysql
      - { role: nginx, username: nginx }

#调用角色方法三
#条件测试
---
  - hosts: webservers
    remote_user: root
    roles:
      - mysql
      - { role: nginx, username: nginx, when: ansible_distribution_major_version == "7" }

#调用角色方法四
#使用tag标签