认识ansible

ansible简介

  官方的title是“Ansible is Simple IT Automation”——简单的自动化IT工具。
  Ansible跟其他IT自动化技术的区别在于其关注点并非配置管理、应用部署或IT流程工作流,而是提供一个统一的界面来协调所有的IT自动化功能,因此Ansible的系统更加易用,部署更快。
  Ansible可以让用户避免编写脚本或代码来管理应用,同时还能搭建工作流实现IT任务的自动化执行。IT自动化可以降低技术门槛及对传统IT的依赖,从而加快项目的交付速度。

ansible优缺点

优点:

  • 轻量级,不需要去客户端安装agent,更新时,只需要在操作机上进行一次更新即可
  • 批量任务执行可以写成脚本,而且不用分发到远程就可以执行
  • 使用python编写的,维护更简单
  • 支持sudo

缺点:

  • 对于几千台、上万台机器的操作,还不清楚性能、效率情况如何,需要进一步了解。

ansible架构及工作原理

     andible基本架构如下图所示

ansible 如何反馈命令结果 ansible的debug_ansible 如何反馈命令结果

  • ansible core : ansible 自身核心模块
  • host inventory: 主机库,定义可管控的主机列表
  • connection plugins: 连接插件,一般默认基于 ssh 协议连接
  • modules:core modules ( 自带模块 ) 、 custom modules ( 自定义模块 )
  • playbooks :剧本,按照所设定编排的顺序执行完成安排任务 

 Ansible工作原理如下图:

ansible 如何反馈命令结果 ansible的debug_yum安装ansible_02

  1. 管理端支持local 、ssh、zeromq 三种方式连接被管理端,默认使用基于ssh的连接---这部分对应基本架构图中的连接模块;
  2. 可以按应用类型等方式进行Host Inventory(主机群)分类,管理节点通过各类模块实现相应的操作---单个模块,单条命令的批量执行,我们可以称之为 ad-hoc;
  3. 管理节点可以通过playbooks ,实现多个task的集合实现一类功能,如web服务的安装部署、数据库服务器的批量备份等。playbooks,我们可以简单的理解为,系统通过组合多条ad-hoc操作的配置文件 。

Ansible默认是通过SSH通道来管理的,也就是它所说的免客户端方式管理, 它底层是通过 paramiko 来实现的。  

ansible执行过程大体过程如下图,其中暖色调的代表已经模块化。

ansible 如何反馈命令结果 ansible的debug_yum安装ansible_03

安装Ansible

YUM方式安装Ansible

Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。它用Python写成,类似于Chef和Puppet,但是有一个不同和优点是我们不需要在节点中安装任何客户端。它使用SSH来和节点进行通信。

#在采用YUM方式安装Ansible,首先安装EPEL源。
yum install -y wget
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sed -i 's/^.*aliyuncs*/#&/g' /etc/yum.repos.d/CentOS-Base.repo
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
#查看EPEL源中的Ansible版本
yum info ansible

#直接安装此版本,如果有其他要求,请调整源,安装其他ansible版本
yum install -y ansible
#安装完成之后,查看ansible版本信息
ansible --version

在主控端(Ansible服务器),基于KEY认证授权节点服务器

在主控端(Ansible服务器)上生成密钥对。

cd /root
ssh-keygen -t rsa
# 接下来一路回车到底

ansible 如何反馈命令结果 ansible的debug_yum安装ansible_04

ssh-copy-id -i ~/.ssh/id_dsa.pub root@node02
ssh-copy-id -i ~/.ssh/id_dsa.pub root@node03

ansible 如何反馈命令结果 ansible的debug_Ansible工作原理_05

其他机器也是,ssh-copy-id 在每台机器上均需执行.

cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

ansible 如何反馈命令结果 ansible的debug_一键初始化/还原操作系统_06

远程主机上的authorized_keys文件中可以保存多个公钥,多个公钥直接追加在末尾。

Ansible服务器清单简单配置

清单文件/etc/ansible/hosts,在此文件中编写节点主机的对应IP地址和hostname

[all]
172.16.7.12  master
172.16.7.15  node01
172.16.7.16  node02
172.16.7.17  node03

测试Ansible

尝试一把简单验证(PING:PONG)

ansible 192.168.10.31 -m ping -k

ansible 如何反馈命令结果 ansible的debug_ansible 如何反馈命令结果_07

SHELL命令执行情况

在主控端执行SHELL命令,查看节点状态信息

ansible -m command -a 'df -lh' websrve

ansible 如何反馈命令结果 ansible的debug_一键初始化/还原操作系统_08

ansible -m command -a 'uptime' websrve

ansible 如何反馈命令结果 ansible的debug_ansible常用模块_09

ansible -m command -a 'netstat -tnlp' websrve

ansible 如何反馈命令结果 ansible的debug_yum安装ansible_10

ansible常用命令

ansible 常用参数:

  1. -m 模块
  2. -i PATH, --inventory=PATH 指定库存主机文件的路径,默认为/etc/ansible/hosts.
  3. -a  (arguments) 命令行参数

示例:

ansible test1 -m copy -a "src=/tmp/test.txt dest=/tmp/test.txt "

ansible-doc

//列出所有已安装的模块
# ansible-doc  -l
//查看具体某模块的用法,这里如查看command模块
# ansible-doc -s command

absible-galaxy

ansible-galaxy 指令用于方便的从https://galaxy.ansible.com/ 站点下载第三方扩展模块,我们可以形象的理解其类似于centos下的yum、python下的pip或easy_install 。如下示例:

ansible-galaxy install aeriscloud.docker

ansible-link

ansible-lint是对playbook的语法进行检查的一个工具。用法是ansible-lint playbook.yml 。

ansible-playbook

该指令是使用最多的指令,其通过读取playbook 文件后,执行相应的动作。

ansible-pull

适用于以下场景:你有数量巨大的机器需要配置,即使使用非常高的线程还是要花费很多时间;你要在一个没有网络连接的机器上运行Anisble,比如在启动之后安装。

ansible-vault

注意:重点是ansible和ansible-playbook

主机组/etc/ansible/hosts

在hosts文件内配置

[hangzhou]
host1
host2
[jiaxing]
host3
host4

ansible默认配置文件

Ansible默认安装好后有一个配置文件/etc/ansible/ansible.cfg
ansible简单使用

[root@test ansible]# ansible test1 -m ping -k
SSH password:
192.168.147.101 | FAILED => Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host.

报错处理办法:
在ansible.cfg配置文件中,也会找到如下部分:

# uncomment this to disable SSH key host checking
host_key_checking = False

默认host_key_checking部分是注释的,通过找开该行的注释,同样也可以实现跳过 ssh 首次连接提示验证部分。
    可见采用密码方式比较麻烦,实际应用中采用ssh 互信方式。
配置ssh 互信时,只需要管理主机能ssh被管理机器,不需要输入密码,即可。

ansible常用模块

ping

ansible test1 -m ping

setup

setup模块,主要用于获取主机信息,在playbooks里经常会用到的一个参数gather_facts就与该模块相关。setup模块下经常使用的一个参数是filter参数,具体使用示例如下:

#查看主机内存信息
[root@test ~]# ansible test1 -m setup -a 'filter=ansible_*_mb'
#查看网卡信息
[root@test ~]# ansible test1 -m setup -a 'filter=ansible_eth0'
#将所有主机的信息输入到/tmp/facts目录下,每台主机的信息输入到主机名文件中(/etc/ansible/hosts里的主机名)
[root@test ~]# ansible all -m setup --tree /tmp/facts

 file 模块

file模块主要用于远程主机上的文件操作。

  • (group、mode、owner):定义文件/目录
  • path:定义文件路径
  • recurse:递归的设置,只对目录有效。
  • src:要被链接的源文件路径,只应用于state=link的情况
  • dest:被连接的路径,只应用于state=link的情况
  • state:directory:如果目录不存在,创建目录
  • file:即使文件不存在,也不会创建
  • link:创建软连接
  • hard:创建硬链接
  • touch:文件不存在,则会创建。如果存在则会,则更新最后修改的时间。
  • absent:删除目录、文件或取消链接。

示例:

[root@test ~]# ansible test1 -m file -a "src=/etc/fstab dest=/tmp/fstab state=link"
[root@test ~]# ansible test1 -m file -a "path=/tmp/fstab state=absent"
[root@test ~]# ansible test1 -m file -a "path=/tmp/fstab state=touch"

copy模块

  • backup:在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no
  • content:用于替代"src",可以直接设定指定文件的值 
  • directory_mode:递归的设定目录的权限,默认为系统默认权限
  • force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
  • others:所有的file模块里的选项都可以在这里使用
  • src:要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用"/"来结尾,则只复制目录里的内容,如果没有使用"/"来结尾,则包含目录在内的整个内容全部复制,类似于rsync。 

示例:

[root@test ~]# ansible test1 -m copy -a "src=/tmp/test.txt dest=/tmp/test.txt owner=foo group=foo mode=0644"

command 模块

  • creates:一个文件名,当该文件存在,则该命令不执行
  • free_form:要执行的linux指令
  • chdir:在执行指令之前,先切换到该指定的目录
  • removes:一个文件名,当该文件不存在,则该选项不执行
  • executable:切换shell来执行指令,该执行路径必须是一个绝对路径

注意:command模块不是调用的shell的指令,所以没有bash的环境变量,也不能使用shell的一些操作方式,其他和shell没有区别
示例:

[root@test ansible]# ansible test1 -a 'df -h'

shell 模块

用法其本和command一样,不过的是其是通过/bin/sh进行执行,所以shell 模块可以执行任何命令,就像在本机执行一样。
示例:

[root@test ansible]# ansible test1 -m shell -a 'ps -ef | grep sshd'

 raw 模块

用法和shell 模块一样 ,其也可以执行任意命令,就像在本机执行一样
注:raw模块和comand、shell 模块不同的是其没有chdir、creates、removes参数,chdir参数的作用就是先切到chdir指定的目录后,再执行后面的命令,这在后面很多模块里都会有该参数 。

script 模块

将管理端的shell 在被管理主机上执行,其原理是先将shell 复制到远程主机,再在远程主机上执行,原理类似于raw模块。

service 模块

  • arguments:给命令行提供一些选项
  • enabled:是否开机启动 yes|no
  • name:必选项,服务名称
  • pattern:定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
  • runlevel:运行级别
  • sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟
  • state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)

示例:

[root@test ansible]# ansible test1 -m service -a "name=httpd state=started enabled=yes"

cron 模块

  • backup:对远程主机上的原任务计划内容修改之前做备份
  • cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划
  • day:日(1-31,*,*/2,……)
  • hour:小时(0-23,*,*/2,……)  
  • minute:分钟(0-59,*,*/2,……)
  • month:月(1-12,*,*/2,……)
  • weekday:周(0-7,*,……)
  • job:要执行的任务,依赖于state=present
  • name:该任务的描述
  • special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly
  • state:确认该任务计划是创建还是删除
  • user:以哪个用户的身份执行

示例:

[root@test ansible]# ansible test1 -m cron -a 'name="check dirs" hour="5,2" job="ls -alh >/dev/null"'

filesystem 模块

  • dev:目标块设备
  • force:在一个已有文件系统的设备上强制创建
  • fstype:文件系统的类型
  • opts:传递给mkfs命令的选项

yum 模块

  • config_file:yum的配置文件
  • disable_gpg_check:关闭gpg_check
  • disablerepo:不启用某个源
  • enablerepo:启用某个源
  • name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径
  • state:状态(present,absent,latest)

示例:

[root@test ansible]# ansible test1 -m yum -a 'name=httpd state=latest'

user和group 模块

  • user模块是请求的是useradd, userdel, usermod三个指令,goup模块请求的是groupadd, groupdel, groupmod 三个指令。

示例:

#创建用户:
[root@test ~]# ansible test1 -m user -a 'createhome=yes home=/home/user1 password=123456 name=user1 shell=/bin/bash state=present'
#删除用户:
[root@test ~]# ansible test1 -m user -a 'remove=yes name=user1 state=absent'

synchronize 模块

使用rsync同步文件

  • archive: 归档,相当于同时开启recursive(递归)、links、perms、times、owner、group、-D选项都为yes ,默认该项为开启
  • checksum: 跳过检测sum值,默认关闭
  • compress:是否开启压缩
  • copy_links:复制链接文件,默认为no ,注意后面还有一个links参数
  • delete: 删除不存在的文件,默认no
  • dest:目录路径
  • dest_port:默认目录主机上的端口 ,默认是22,走的ssh协议
  • dirs:传速目录不进行递归,默认为no,即进行目录递归
  • rsync_opts:rsync参数部分
  • set_remote_user:主要用于/etc/ansible/hosts中定义或默认使用的用户与rsync使用的用户不同的情况
  • mode: push或pull 模块,push模的话,一般用于从本机向远程主机上传文件,pull 模式用于从远程主机上取文件

示例:

[root@test ansible]# ansible test1 -m synchronize -a 'src=/tmp/helloworld dest=/var/www'

mount 模块

  • dump:为备份工具程序,可将目录或整个文件系统备份至指定的设备,或备份成一个大文件。
  • fstype:必选项,挂载文件的类型
  • name:必选项,挂载点
  • opts:传递给mount命令的参数
  • src:必选项,要挂载的文件
  • state:必选项
  • present:只处理fstab中的配置
  • absent:删除挂载点
  • mounted:自动创建挂载点并挂载之
  • umounted:卸载

示例:

#创建设备
[root@test ansible]# ansible test1 -a 'dd if=/dev/zero of=/disk.img bs=4k count=1024'
#与/dev/loop1关联
[root@test ansible]# ansible test1 -a 'losetup /dev/loop1 /disk.img'
#格式化
[root@test ansible]# ansible test1 -m filesystem -a 'fstype=ext3 force=yes opts=-F 
#挂载
[root@test ansible]# ansible test1 -m mount -a 'name=/mnt src=/dev/loop1 fstype=ext3 state=mounted opts=rw'

备注:

losetup: 设置和控制循环设备,这个命令是util-linux软件包的一部分

  • -o 偏移字节数
  • -d 卸载循环设备

使用循环设备的一个例子:

# dd if=/dev/zero of=~/file.img bs=1024k count=10
# losetup --find --show ~/file.img
/dev/loop0
# mkfs -t ext2 /dev/loop0
# mount /dev/loop0 /mnt
...
# umount /dev/loop0
# losetup --detach /dev/loop0

 

熟悉ansible-playbook

 playbook 构成

  • Target section:   定义将要执行 playbook 的远程主机组
  • Variable section:  定义 playbook 运行时需要使用的变量
  • Task section:     定义将要在远程主机上执行的任务列表
  • Handler section:  定义 task 执行完成以后需要调用的任务

一般所需的目录层有:(视情况可变化) 

  • vars     变量层
  • tasks    任务层
  • handlers 触发条件
  • files    文件
  • template 模板

host和user

  • playbook中的每一个play的目的,都是为了让某个或某些主机,以某个指定的用户身份执行任务。
  • hosts 用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组。
  • user 执行该任务组的用户
  • remote_user 则用于指定远程主机上的执行任务的用户,与user相同。
  • sudo 如果设置为yes,执行该任务组的用户,在执行任务时,获取root权限。

任务列表和action

 play的主体部分是task list
 示例:

tasks:
  - name: make sure apache is running
    service: name=httpd state=running

handlers

在notify中列出的操作称为handler也即notify中调用 handler中定义的操作。 
注意:在 notify 中定义内容一定要和tasks中定义的 - name 内容一样,这样才能达到触发的效果,否则会不生效。

 tags

ansible中可以对play、role、include、task打一个tag(标签),然后:
当命令ansible-playbook有-t参数时,只会执行-t指定的tag
当命令ansible-playbook有--skip-tags参数时,则除了--skip-tags指定的tag外,执行其他所有

var

#变量定义在文件中
[root@test playbooks]# cat variables
port: 80
http: nginx

playbook常用模板

template

template模块和copy类似,不同在于template会做变量替换。
常用参数:

  • backup:如果原目标文件存在,则先备份目标文件
  • dest:目标文件路径
  • force:是否强制覆盖,默认为yes
  • group:目标文件属组
  • mode:目标文件的权限
  • owner:目标文件属主
  • src:源模板文件路径
  • validate:在复制之前通过命令验证目标文件,如果验证通过则复制

示例:

- template: src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode=0644
- template: src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode="u=rw,g=r,o=r"

set_face

set_fact模块可以让你在远程受管机器上,去执行脚本的过程来,计算我们需要的值,这些值可以被用在模板,或者变量中。这些值有点类似setup模块中的参数,只不过setup模块,是以单台主机为单位的。
示例:

tasks:
  -name: Calculate InnoDB buffer pool size
  set facl: innodb_buffer_pool_size_mb=”{{ ansible_mentotal_mb /2 }}”

pause

暂停模块可以让我们在playbooks中暂停一段时间,可以知道一个时间段,或者提示用户继续。在命令行中没生么有,但在playbook中,很有用处。
示例:

# Pause for 5 minutes to build app cache.
- pause: minutes=5
# Pause until you can verify updates to an application were successful.
- pause:
# A helpful reminder of what to look out for post-update.
- pause: prompt="Make sure org.foo.FooOverload exception is not present"

wait_for

wait_for模块,用来检测一个tcp端口,是否准备好接收远程连接?这是由远程主机来完成的。
示例:

# 10秒后在当前主机开始检查8000端口,直到端口启动后返回
- wait_for: port=8000 delay=10
# 检查path=/tmp/foo直到文件存在后继续
- wait_for: path=/tmp/foo
# 直到/var/lock/file.lock移除后继续
- wait_for: path=/var/lock/file.lock state=absent
  -name: Wait for Tomcat to start
    wait_for: port=8080 state=started

assemble

assemble组装模块,把多个受管主机的文件,合并成一个文件,当配置文件不允许包含的时候,非常有用。特别在设置root用户的authorized_keys文件的时候。
示例:

# Example from Ansible Playbooks
- assemble: src=/etc/someapp/fragments dest=/etc/someapp/someapp.conf
# When a delimiter is specified, it will be inserted in between each fragment
- assemble: src=/etc/someapp/fragments dest=/etc/someapp/someapp.conf delimiter='### START FRAGMENT ###'

add_host

add_host添加主机模块,是playbook中一个强大的模块,它可以让你动态的,添加受管主机到一个play中。
示例:

# add host to group 'just_created' with variable foo=42
- add_host: name={{ ip_from_ec2 }} groups=just_created foo=42

group_by

group_by模块,可以让我们根据主机的真实特性,进行分组,真实特性可以通过add_fact来实现。Group_by模块只接受一个参数,key,同样组名的机器被分到一个组里面。
示例:

# Create groups based on the machine architecture
-  group_by: key=machine_{{ ansible_machine }}
# Create groups like 'kvm-host'
-  group_by: key=virt_{{ ansible_virtualization_type }}_{{ ansible_virtualization_role }}

get_url

该模块主要用于从http、ftp、https服务器上下载文件(类似于wget),主要有如下选项:

  •   sha256sum:下载完成后进行sha256 check;
  •   timeout:下载超时时间,默认10s
  •   url:下载的URL
  •   url_password、url_username:主要用于需要用户名密码进行验证的情况
  •   use_proxy:是事使用代理,代理需事先在环境变更中定义

示例:

- name: download foo.conf
  get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf mode=0440
- name: download file with sha256 check
  get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf sha256sum=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c

debug

调试模块,用于在调试中输出信息
常用参数:

  • msg:调试输出的消息
  • var:将某个任务执行的输出作为变量传递给debug模块,debug会直接将其打印输出
  • verbosity:debug的级别(默认是0级,全部显示)

fail

用于终止当前playbook的执行,通常与条件语句组合使用,当满足条件时,终止当前play的运行。可以直接由failed_when取代。
选项只有一个:

  • msg:终止前打印出信息

示例:

- fail: msg="The system may not be provisioned according to the CMDB status."
  when: cmdb_status != "to-be-staged"

playbook的roles和include

include

包含task文件 

---
# possibly saved as tasks/foo.yml
- name: placeholder foo
  command: /bin/foo
- name: placeholder bar
  command: /bin/bar

包含handle文件

---
 # this might be in a file like handlers/handlers.yml
 - name: restart apache
  service: name=apache state=restarted

在play末尾包含上面的handler文件:

handlers:
  - include: handlers/handlers.yml

直接包含playbook文件

roles(角色)

roles用来组织playbook结构,以多层目录和文件,将playbook更好的组织在一起。
角色允许你将变量、文件、任务、模板、handlers放到一个文件夹中,然后包含它们。在建立好一个有效的依赖关系之后,还可以在一个角色中包含另外一个角色。
roles组织的playbook结构:

site.yml
webservers.yml
fooservers.yml
roles/
     common/    #下面的子目录都不是必须提供的,没有的目录会自动忽略,不会出现问题,所以你可以只有tasks/子目录也没问题
     files/
     templates/
     tasks/
     handlers/
     vars/
     meta/
     webservers/

然后在playbook文件中包含common和webservers这两个role:

---
- hosts: user_group1
  roles:
     - common
     - webservers