Ansible 使用

Admin 2019-11-12 12:01:44 其他

简介

ansible是一个自动化IT工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

ansible其关注点并非配置管理、应用部署或IT流程工作流,而是提供一个统一的界面来协调所有的IT自动化功能,因此Ansible的系统更加易用,部署更快。

ansible可以让用户避免编写脚本或代码来管理应用,同时还能搭建工作流实现IT任务的自动化执行。IT自动化可以降低技术门槛及对传统IT的依赖,从而加快项目的交付速度。

优势

  • 无需按照客户端(Agent), 基于SSH执行

  • 基于模块工作,可以使用任何语言开放自定义模块

  • 使用yaml语言定制playbook

  • 幂等性,多次运行,结果不变

  • 批量任务执行可以写成脚本,而且不用分发到远程就可以执行

  • 支持sudo

架构

1573010196181369.png

ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。

Ansible: ansible 自身核心模块

Host Inventory: 主机库,定义可管控的主机列表

Connection Plugins: 连接插件,被控端实现通信,一般默认基于 SSH 协议连接

Modules:Core Modules ( 自带模块 ) 、 Custom Modules ( 自定义模块 )

Playbooks :任务配置文件,将多个任务定义在剧本中,按照所设定编排的顺序执行完成安排任务 

工作原理

1573011020508151.png

1、管控端支持local 、ssh、zeromq 三种方式连接被管理端,默认使用基于ssh的连接(对应的连接模块)

2、可以按应用类型或角色等方式进行Host Inventory(主机群)分类,管控节点通过各类模块实现相应的操作(单个模块,单条命令的批量执行,可称之为ad-hoc)

3、管控节点可以通过 Playbooks 实现多个task的集合实现一类功能,如: web服务的部署、数据库服务的批量备份等。可以理解为通过组合多条ad-hoc操作的配置文件。

Ansible默认是通过SSH通道来管理的,它底层是通过 paramiko 来实现的。  

执行过程

1573011667604194.png

用法及常用命令介绍

用法可以分为ad-hoc和playbooks两种方式

ad-hoc:点对点,是相对 Playbook 来说的。类似于shell但个命令和shell脚本的区别。

playbooks:可以编排有序的执行过程,甚至于做到在多组机器间,来回有序的执行指定的步骤,并且可以同步或异步的发起任务。

1、ansible 核心命令,主要执行ad-hoc命令,需要跟主机和选项部分,默认不指定模块时,使用的是command模块。

# 部分参数介绍
  -a MODULE_ARGS, --args=MODULE_ARGS  # 模块参数
  --ask-vault-pass                    # 询问密码
  -B SECONDS, --background=SECONDS    # 异步运行,多少秒后失败 (default=N/A)
  -C, --check             # 只是测试下会改变什么不做任何更改;相反,尝试预测可能发生的某些更改
  -D, --diff              # 当更改(小)文件和模板时,显示这些文件中的差异;非常适合于 --check
  -e EXTRA_VARS, --extra-vars=EXTRA_VARS
                          # 将其他变量设置为key=value或yaml/json
  -f FORKS, --forks=FORKS # 指定要使用的并行进程数 (default=5)
  -h, --help              # 显示此帮助消息
  -i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY
                          # 指定主机文件路径或逗号分隔的主机列表,默认在 /etc/ansible/hosts
  -l SUBSET, --limit=SUBSET 
                          # 进一步限制主机或组,如: --limit=192.168.1.2 只执行这一个主机
  --list-hosts            # 列出匹配到的主机列表;不执行任何其他操作              
  -m MODULE_NAME, --module-name=MODULE_NAME
                          # 要执行的模块名 (default=command)
  -M MODULE_PATH, --module-path=MODULE_PATH
                          # 将冒号分隔的路径前置到模块库 (default=~/.ansible/plugins/modules:
                          /usr/share/ansible/plugins/modules)
  -o, --one-line          # 压缩输出
  --playbook-dir=BASEDIR  # 因此命令不在使用 playbooks, 用做playbook的目录设置,
                          包括 roles/ group_vars/等
  -P POLL_INTERVAL, --poll=POLL_INTERVAL 
                          # 如果使用 -B,则设置轮询间隔 (default=15)
  --syntax-check          # 对 playbook 进行语法检查,不执行
  -t TREE, --tree=TREE    # 日志输出到此目录
  --vault-id=VAULT_IDS    # 要使用的标识
  --vault-password-file=VAULT_PASSWORD_FILES
                          # 密码文件
  -v, --verbose           # (-vvv for more, -vvvv to enable connection debugging)
  --version               # 显示版本号、配置文件位置、配置的模块搜索路径、模块位置,可执行的位置

2、ansible-doc 用于查看模块信息,常用参数有两个 -l (列出已安装的所有模块)和 -s (查看模块的用法)

ansible-doc -l
ansible-doc -s command

3、ansible-galaxy 用于方便从 https://galaxy.ansible.com/ 下载第三方扩展模块

ansible-galaxy install docker

4、ansible-inventory 用于操作管控的主机

 ansible-inventory --list 
 ansible-inventory --host=192.168.8.152

5、ansible-playbook 用于通过读取 playbook 文件后,执行相应的动作

6、ansible-pull 使用此命令需要说下 ansible的另一种模式 pull 模式,这和我们平常用的push模式刚好相反,其适用于有数量巨大的机器需要配置,即使使用非常高的线程还是要花费很多时间,你要在一个没有网络连接的机器上运行Anisble,比如在启动之后安装。

7、ansible-vault 用于配置文件中含有敏感信息,又不希望他能被人看到,vault可以帮你加密/解密这个配置文件。主要对于playbooks 里如:涉及到配置密码或其他变量时,可以通过该指令加密,这样我们通过cat看到的会是一个密码串类的文件,编辑的时候需要输入事先设定的密码才能打开。这种 playbook文件 在执行时,需要加上 --ask-vault-pass参数,同样需要输入密码后才能正常执行。

8、ansible-console 是为用户提供的一款交互式工具,可以在ansible-console虚拟出来的终端上像Shell一样使用Ansible内置的各种命令,这为习惯于使用Shell交互方式的用户提供了良好的使用体验。

9、ansible-config 用于查看 ansible 配置

重点使用的是 ansible 和 ansible-playbook, 其他的命令用的相对较少

安装部署

# 依赖模块 paramiko、PyYAML、Jinja2、httplib2、simplejson、pycrypto
pip install ansible
# or
yum install ansible  # ansible在epel源

# 安装完成后查看版本
ansible --version

# 默认主配置文件:/etc/ansible/ansible.cfg, pip 安装需要手动创建这个文件
# 详情请查看 https://github.com/ansible/ansible/blob/devel/examples/ansible.cfg
# 如;关闭检查主机密钥,修改配置 host_key_checking = False

# 默认 Host Inventory 定义管控主机文件:/etc/ansible/hosts
# 也可指定 Host Inventory
# ansible all -i /etc/ansible/hosts -m ping --limit=192.168.8.152

Host Inventory 文件配置

vim /etc/ansible/hosts
192.168.8.152                 # 直接指定主机

[node]                        # 组名
192.168.8.15[1:2]             # 简写数字范围

[node:vars]                   # 组和变量
ansible_ssh_user="opsteam" 
ansible_ssh_port=10220

[group1]
192.168.8.152

[group2]
192.168.8.152

[db]
db-[a:f]-node.ywfuns.com     # 简写字母范围

[targets]                    # 单独指定连接方式
localhost           ansible_connection=local
other1.ywfuns.com   ansible_connection=ssh   ansible_ssh_user=work

# 参考地址:https://ansible-tran.readthedocs.io/en/latest/docs/intro_inventory.html

常用模块

ansible all -m ping   # ping

# setup 获取主机信息,在 playbooks 里经常会用到的一个参数gather_facts就与该模块相关。
ansible node -m setup --limit=192.168.8.152 -a 'filter=ansible_*_mb'

# 将信息输入到/tmp/tt目录下
ansible node -m setup --tree /tmp/tt

# file 模块,用于远程主机上的文件操作
# src  要被链接的源文件路径,只应用于state=link的情况
# dest 被连接的路径,只应用于state=link的情况
# path 文件路径
# recurse 递归, 只对目录有效。
# state 操作, 如下:
#     link:创建软连接,
#     hard:创建硬链接,
#     touch:文件不存在,则会创建,
#     absent:删除目录、文件或取消链接,
#     file:文件不存在则不创建
ansible node -m file --limit=192.168.8.152 -a "src=/etc/hosts dest=/tmp/hosts state=link"
ansible node -m file --limit=192.168.8.152 -a "path=/etc/hosts state=touch"

# copy模块,文件传输操作
# src 源文件路径(或目录)注意:路径”/“结尾,则只复制目录里的内容不复制目录本身
# dest 远程(目标)文件路径
# owner 用户, group 属组,mode 权限
# force 是否覆盖,默认yes
ansible node -m copy --limit=192.168.8.152 -a "src=/etc/hosts dest=/tmp/hosts owner=work 
group=work mode=0644"

# command模块(不是调用shell,没有bash环境),命令执行
# creates 文件存在则命令不执行
# chdir 执行前切换到指定目录
# removes 文件不存在则命令不执行
# executable 切换shell来执行
ansible node -m command --limit=192.168.8.152 -a "cat /tmp/hosts"
ansible node --limit=192.168.8.152 -a "ls /tmp/hosts"

# shell模块,用法和command一样,是用过/bin/sh来执行命令的
ansible node -m shell --limit=192.168.8.152 -a "ls -lh /tmp/"

# raw模块,用法和shell一样,和shell及command的不同的是没有creates、chdir、removes及那些参数
# script模块,将管控端的shell在被管理主机上执行,原理是先将shell复制到远程主机在执行,类似于raw模块
# service模块,对远程主机上的服务操作
# enabled 开机自启动yes|no
# name 服务名称
# runlevel 运行级别
# sleep 执行restarted,之间sleep几秒
# state 执行操作(started, stopped, restarted, reloaded)
ansible node -m service --limit=192.168.8.152 -a "name=httpd state=started enabled=yes"

# cron模块, 定时任务
# name 描述
# hour 时(0-23,*,*/1)
# day 日 (1-31,*,*/1)
# month 月 (1-12,*,*/1)
# weekday 周(0-7,*,*/1)
# minute 分(0-59,*,*/1)
# job 要执行的语句
# state 是否确保任务在或不存在
# user 以哪个用户执行
ansible node -m cron --limit=192.168.8.152 -a 'name="mysql backup" hour="16,4" job="/bin/sh 
 /tmp/back.sh >/dev/null 2>&1"'
 
# yum模块
# name 包名
# state 操作 (present,absent,latest)
ansible node -m yum --limit=192.168.8.152 -a 'name=httpd state=latest'

# user模块
# 新建用户
ansible node -m user --limit=192.168.8.152 -a 'createhome=yes home=/home/work password=111
 name=work shell=/bin/bash state=present'
# 删除用户
ansible node -m user --limit=192.168.8.152 -a 'remove=yes name=work state=absent'

# group模块和user模块使用相同
# mount模块
# fstype 文件类型
# name 挂载点
# src 要挂载的文件
# state 操作
# opts mount命令参数
ansible node -m mount --limit=192.168.8.152 -a 'name=/data src=/dev/sdb1 fstype=ext4
 state=mounted opts=rw'
 
# synchronize模块,使用rsync命令传输文件
# src 源文件路径
# dest 目录路径
# mode 模式pull或push
# rsync_opts rsync命令参数
# dest_port 目标主机端口,默认是ssh的22
# compress 是否要压缩
ansible node -m synchronize --limit=192.168.8.152 -a 'src=/etc/hosts dest=/tmp/h'

# fetch模块,从远程主机上下载文件
ansible node  -m fetch --limit=192.168.8.152 -a 'src=/etc/hosts dest=./'

Playbooks(剧本)

playbooks定义一个或者多个任务,如创建文件、安装程序、启动服务、定时任务、命令执行等。当运行这个脚本时,就可以一次性执行多个任务。且在 playbooks 中可以编排有序的执行过程,甚至于做到在多组机器间,来回有序的执行指定的步骤,并可以同步或异步的发起任务。

我们使用 ad-hoc 时,主要是使用 ansible 命令执行任务,而使用 playbooks 时是用代码控制。

playbooks 用的是YAML格式,核心元素如下:

  • Hosts:主机

  • Tasks:任务列表

  • Variables:变量

  • Templates:包含了模板语法的文本文件

  • Handlers:由特定条件触发的任务

  • Roles:角色

一般所需要的目录(根据特定情况而定):

  • vars 变量层

  • tasks 任务层

  • handlers 触发条件

  • files 文件

  • template 模板

  • roles 角色

  • common 常用

---
- hosts: webservers                                       # 运行主机组
  vars:                                                   # 定义参数
    http_port: 80
    max_clients: 200
  remote_user: root                                       # 执行用户 
  tasks:                                                  # 任务列表
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/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

主机与用户

hosts 用于指定要执行指定任务的主机可以是一个或多个由冒号分隔主机组

remote_user 远程执行任务的用户, 也支持sudo

---
- hosts: webservers
  remote_user: yourname
  sudo: yes

- hosts: webservers
  remote_user: yourname 
  tasks:                                    # tasks 中也可以使用sudo
    - service: name=nginx state=started
      sudo: yes
      
- hosts: webservers
  remote_user: yourname
  sudo: yes
  sudo_user: postgres                       # 也可以sudo到其他用户

Tasks 列表

每一个 playbook 包含了一个 任务列表,一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行,有一点需要明白的是(很重要),在一个 playbook 之中所有 hosts 会获取相同的任务指令。

在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,这个 host 将会从整个 playbook 的运转中移除,如果发生执行失败的情况,需要修改 playbook 中的错误,然后重新执行即可。

每个 task 的目标在于执行一个 moudle(模块,如:service、command、shell、copy、cron、file、yum),通常是带有特定的参数来执行,在参数中也可以使用变量(variables)。modules 具有”幂等”性,如果重复执行 moudle 只会执行需要改变的地方。

tasks:                                                          
  - name: ensure apache is at the latest version            # 名称
    yum: pkg=httpd state=latest                             # 执行的模块
  - name: write the apache config file                      
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running                      
    service: name=httpd state=started

使用 command module 和 shell module 时,返回码如果不是0需要忽略错误。

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

    # 或者

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true

Handlers(由特定条件触发的任务)

上面我们提到过 module 具有”幂等”性,所以远程主机上文件被改动时,可以重新执行 playbooks 来恢复配置,playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动。

当发生改动时,'notify actions' 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动发生,'notify actions' 只会被触发一次。

如:多个资源因一个配置文件被改动,所以 apache 需要重新启动,但是重新启动的操作只会被执行一次。

- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache

notify 就是下列出的 handlers

Handlers 也是一个 task 的列表,通过名字来引用

Handlers 是由 notify 通知执行,如果没有被 notify 通知,Handlers 是不会执行的,如果有多次通知只会执行一次(一般是用来重启服务操作的)

handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

角色(Roles) 和 Include 

使用 include 可以引用 task 文件,可以将一个配置策略分解到更小的文件中。使用 include 语句引用 tasks 是将 tasks 从其他文件拉取过来。因为 handlers 也是 tasks 所以你也可以使用 include 语句去引用 handlers 文件。

- name: this is a play at the top level of a file
  hosts: all
  remote_user: root

  tasks:

  - name: say hi
    tags: foo
    shell: echo "hi..."

- include: load_balancers.yml
- include: webservers.yml
- include: dbservers.yml

Roles 将 tasks,handlers,variables 等等应用到 hosts 中,可以理解Roles是对这些应用的"封装",如:知道 hosts 是dbserver,而不需要知道其中有哪些 task,handlers 等。

使用 Roles 可以很好的组织 playbook,可基于 roles 对内容进行分组,使得我们可以容易地与其他用户分享 roles 。

一个项目的结构如下:

site.yml
webservers.yml
fooservers.yml
roles/
   common/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/
   webservers/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/

一个 playbook 如下:

- hosts: webservers
  roles:
     - common
     - webservers

Variables (定义变量)

facts 可直接调用,通过setup模块直接获取目标主机的facters

ansible hostname -m setup

关闭Facts

 hosts: whatever
  gather_facts: no

playbook中定义变量

- hosts: webservers
  vars:
    http_port: 80

命令行中传递变量

ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"
- hosts: '{{ hosts }}'
  remote_user: '{{ user }}'

  tasks:
     - ...

引用外部的变量文件

- hosts: all
  remote_user: root
  vars:
    favcolor: blue
  vars_files:
    - /vars/external_vars.yml

  tasks:
    - ...

变量访问

{{ ansible_eth0["ipv4"]["address"] }}
{{ ansible_eth0.ipv4.address }}
{{ foo[0] }}

注册变量

- hosts: all
  tasks:
      - name: register variable
        shell: hostname
        register: info
      - name: display variable
        debug: msg="The msg is {{ info }}"
        debug: msg="The msg is {{ info['stdout'] }}"

YAML语法要以{{ foo }}开头的话我们需要将整行用双引号包起来, 如:

- hosts: app_servers
  vars:
       app_path: "{{ base_path }}/22"

Template

Template模块和 copy 类似,不同在于template会做变量替换。

常用参数:

  • backup:如果原目标文件存在,则先备份目标文件

  • dest:目标文件路径

  • force:是否强制覆盖,默认为yes

  • group:目标文件属组

  • mode:目标文件的权限

  • owner:目标文件属主

  • src:源模板文件路径

  • validate:在复制之前通过命令验证目标文件,如果验证通过则复制

- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      template: src=/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode=0644

执行一个playbook

ansible-playbook playbook.yml -f 10 # -f 并发进程

# 其他参数
# 检查语法
ansible-playbook -i /etc/ansible/hosts test.yaml --syntax-check

# 检查tasks任务
ansible-playbook -i /etc/ansible/hosts test.yaml --list-task

# 检查主机
ansible-playbook -i /etc/ansible/hosts test.yaml --list-hosts

# 运行特定的tasks
ansible-playbook -i /etc/ansible/hosts test.yaml --start-at-task='started'


附:

https://github.com/ansible/ansible

https://ansible-tran.readthedocs.io/en/latest/index.html

http://www.ansible.com.cn/index.html

https://github.com/ansible/ansible-examples

相关文章
最新推荐