A-A+

ansible安装与配置使用入门

2017年02月28日 运维工具 暂无评论 阅读 3,120 views 次
摘要:

Ansible作为一个python写的自动化部署工具, 确实较之前所接触的Chef, saltstack, puppet更有自己的一些优势, 首先就是agentless, 无需在Linux client安装任何服务即可无缝连接Linux default ssh端口进行部署(windows需要安装winrm 开启ssh服务), 不推荐Saltstack的原因也是因为其需要在每台agent逐一去安装client service并测试, 这本身就会耗费一些时间成本.
其他呢? 容易上手, 语法简单, 有现成模板学习, 加之是我们非常喜爱的python语法!

=====================================================
一、基础介绍
=====================================================

1、简介

ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

2、总体架构

ansible1

3、特性

(1)、no agents:不需要在被管控主机上安装任何客户端;
(2)、no server:无服务器端,使用时直接运行命令即可;
(3)、modules in any languages:基于模块工作,可使用任意语言开发模块;
(4)、yaml,not code:使用yaml语言定制剧本playbook;
(5)、ssh by default:基于SSH工作;
(6)、strong multi-tier solution:可实现多级指挥。

4、优点

(1)、轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
(2)、批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
(3)、使用python编写,维护更简单,ruby语法过于复杂;
(4)、支持sudo。

5、任务执行流程

说明:
(1)、以上内容大多是基于网络分享的基础上总结而来,学习借鉴之用;
(2)、以下基于 CentOS 6.4 和 CentOS 7.1系统环境。

=====================================================
二、Ansible基础安装与配置
=====================================================

1、Ansible基础安装

#yum install ansible -y

2、Ansible配置

(1)、SSH免密钥登录设置

## 生成公钥/私钥
# ssh-keygen -t rsa -P ''

## 写入信任文件(将/root/.ssh/id_rsa_storm1.pub分发到其他服务器,并在所有服务器上执行如下指令):
# cat /root/.ssh/id_rsa_storm1.pub >> /root/.ssh/authorized_keys
# chmod 600 /root/.ssh/authorized_keys

(2)、ansible配置

# mkdir -p /etc/ansible
# vim /etc/ansible/ansible.cfg
……
remote_port = 36000
private_key_file = /root/.ssh/id_rsa_cloud
……

## 主机组定义

# vim /etc/ansible/hosts
[storm_cloud]
10.0.0.241

(3)、简单测试

# ansible storm_cloud -m command -a 'uptime'

说明:第一次运行时,需要输入一下“yes”【进行公钥验证】,后续无需再次输入。

## 再次运行

# ansible storm_cloud -m command -a 'uptime'

3、常用模块使用

执行Ad-Hoc命令(就是无需保存的快速执行shell命令):
使用-a指定命令, -f指定并发数(默认为5), -m是选择使用的模块:

(1)、setup
## 用来查看远程主机的一些基本信息

# ansible storm_cloud -m setup

(2)、ping
## 用来测试远程主机的运行状态

# ansible storm_cloud -m ping

(3)、file
## 设置文件的属性
相关选项如下:
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效
src:被链接的源文件路径,只应用于state=link的情况
dest:被链接到的路径,只应用于state=link的情况
state:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件

示例:
## 远程文件符号链接创建

# ansible storm_cloud -m file -a "src=/etc/resolv.conf dest=/tmp/resolv.conf state=link"
10.0.0.241 | SUCCESS => {
    "changed": true,
    "dest": "/tmp/resolv.conf",
    "gid": 0,
    "group": "root",
    "mode": "0777",
    "owner": "root",
    "size": 16,
    "src": "/etc/resolv.conf",
    "state": "link",
    "uid": 0
}

## 远程文件信息查看

# ansible storm_cloud -m command -a "ls –al /tmp/resolv.conf"
10.0.0.241 | SUCCESS | rc=0 >>
lrwxrwxrwx 1 root root 16 Feb  3 17:21 /tmp/resolv.conf -> /etc/resolv.conf

## 远程文件符号链接删除

# ansible storm_cloud -m file -a "path=/tmp/resolv.conf state=absent"
10.0.0.241 | SUCCESS => {
    "changed": true,
    "path": "/tmp/resolv.conf",
    "state": "absent"
}

## 远程文件信息查看

# ansible storm_cloud -m command -a "ls -al /tmp/resolv.conf"
10.0.0.241 | FAILED | rc=2 >>
ls: cannot access /tmp/resolv.conf: No such file or directory

说明:如上显示,代表文件或链接已经删除。

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

示例:
## 将本地文件“/etc/ansible/ansible.cfg”复制到远程服务器

# ansible storm_cloud -m copy -a "src=/etc/ansible/ansible.cfg dest=/tmp/ansible.cfg owner=root group=root mode=0644"
10.0.0.241 | SUCCESS => {
    "changed": true,
    "checksum": "08890d78a852b4873a9e3de574504b84d5a5cb62",
    "dest": "/tmp/ansible.cfg",
    "gid": 0,
    "group": "root",
    "md5sum": "a320115fab711db877f7feaa50a471bb",
    "mode": "0644",
    "owner": "root",
    "size": 14398,
    "src": "/root/.ansible/tmp/ansible-tmp-1486567148.29-275230931250353/source",
    "state": "file",
    "uid": 0
}

## 远程文件信息查看

# ansible storm_cloud -m command -a "ls -al /tmp/ansible.cfg"
10.0.0.241 | SUCCESS | rc=0 >>
-rw-r--r-- 1 root root 14398 Feb  3 17:28 /tmp/ansible.cfg

(5)、command
## 在远程主机上执行命令
相关选项如下:
creates:一个文件名,当该文件存在,则该命令不执行
free_form:要执行的linux指令
chdir:在执行指令之前,先切换到该目录
removes:一个文件名,当该文件不存在,则该选项不执行
executable:切换shell来执行指令,该执行路径必须是一个绝对路径

示例:

# ansible storm_cloud -m command -a "uptime"
10.0.0.241 | SUCCESS | rc=0 >>
 17:29:56 up 374 days,  3:03,  2 users,  load average: 0.02, 0.02, 0.00

(6)、shell
## 切换到某个shell执行指定的指令,参数与command相同。
与command不同的是,此模块可以支持命令管道,同时还有另一个模块也具备此功能:raw
示例:
## 先在本地创建一个SHELL脚本

# vim /tmp/cloud_test.sh
#!/bin/sh
date +%F_%H:%M:%S
#chmod +x /tmp/cloud_test.sh

## 将创建的脚本文件分发到远程

# ansible storm_cloud -m copy -a "src=/tmp/cloud_test.sh dest=/tmp/cloud_test.sh owner=root group=root mode=0755"
10.0.0.241 | SUCCESS => {
    "changed": true,
    "checksum": "d59e6a64ddefbee62777648f65cde15a67e4d682",
    "dest": "/tmp/cloud_test.sh",
    "gid": 0,
    "group": "root",
    "md5sum": "6097884da6d269fc48b4f8110d8ed592",
    "mode": "0755",
    "owner": "root",
    "size": 28,
    "src": "/root/.ansible/tmp/ansible-tmp-1486567346.83-3736190193631/source",
    "state": "file",
    "uid": 0
}

## 远程执行

# ansible storm_cloud -m shell -a "/tmp/cloud_test.sh"
10.0.0.241 | SUCCESS | rc=0 >>
2017-02-03_17:32:12

(7)、更多模块
其他常用模块,比如:service、cron、yum、synchronize,可以结合自身的系统环境进行测试。其他还有stat、get_url、mount、sysctl等模块就不一一例举。
service:系统服务管理

# ansible storm_cloud -m service -a "name=nginx state=restarted"
10.0.0.241 | SUCCESS => {
    "changed": true,
    "name": "nginx",
    "state": "started"
}
# ansible storm_cloud -m service -a "name=nginx state=started"
# ansible storm_cloud -m service -a "name=nginx state=stoped"

cron:计划任务管理

# ansible storm_cloud –m cron –a “name=’check dirs’ hour=’5,2’ job=’ls -alh > /dev/null’ ”

效果如下:

#ansible: check dirs
* 5,2 * * *  ls -alh > /dev/null  ‘*’  file.chown  /etc/passwd  root  root

yum:yum软件包安装管理

# ansible storm_cloud -m yum -a "name=zlib state=present"
10.0.0.241 | SUCCESS => {
    "changed": false,
    "msg": "",
    "rc": 0,
    "results": [
        "zlib-1.2.3-29.el6.x86_64 providing zlib is already installed"
    ]
}

synchronize:使用rsync同步文件

# ansible storm_cloud -m synchronize -a "src=/root/ dest=/data/ansible_test/ rsync_opts='--exclude=RTDATA'" -i "123.59.33.132,"

user:系统用户管理
#添加用户

# ansible storm_cloud -m user -a "name=www group=www home=/home/www shell=/sbin/nologin"
10.0.0.241 | SUCCESS => {
    "append": false,
    "changed": false,
    "comment": "",
    "group": 500,
    "home": "/home/www",
    "move_home": false,
    "name": "www",
    "shell": "/sbin/nologin",
    "state": "present",
    "uid": 500
}

#删除用户

# ansible storm_cloud -m user -a "name=www state=absent remove=yes”

group:系统用户组管理

# ansible storm_cloud -m group -a "name=www"
10.0.0.241 | SUCCESS => {
    "changed": false,
    "gid": 500,
    "name": "www",
    "state": "present",
    "system": false
}

更多模块可以参考:

#ansible-doc –l

参考网站:
http://docs.ansible.com/modules_by_category.html

(8)、补充概念

playbook的组成:playbook是由一个或多个“play”组成的列表,可以让它们联同起来按事先编排的机制执行;所谓task无非是调用ansible的一个module,而在模块参数中可以使用变量;模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致;

执行模型:task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在顺序运行某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在修改playbook后重新执行一次即可;

task组成:每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出;

notify指定handler的执行机制:“notify”这个action可用于在每个play的最后被触发,在notify中列出的操作称为handler,仅在所有的变化发生完成后一次性地执行指定操作。

=====================================================
三、ansible的playbook
=====================================================

1、完成后的目录结构如下:

[root@localhost ansible]# tree
.
├── ansible.cfg
├── group_vars
├── hosts
├── roles
│   └── nginx
│       ├── defaults
│       ├── files
│       │   ├── nginx-1.6.2.tar.gz
│       │   └── pcre-8.35.tar.gz
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       ├── tasks
│       │   └── main.yml
│       ├── templates
│       │   ├── nginx
│       │   └── nginx.conf
│       └── vars
│           └── main.yml
└── webserver.yml

具体操作步骤:

# cd /etc/ansible/
# mkdir group_vars
# touch webserver.yml
# cd roles
# mkdir -p nginx/{meta,vars,files,handlers,tasks,templates,default}

相关目录说明:
group_vars:这里面定义的变量,对全局role都生效
webserver.yml:总调文件
vars:这里面定义的变量,只对当前role有作用
role:在ansible可以将任务等模块化,方便重复使用
tasks:任务就是按配置文件的定义的去执行的操作。
handlers:当被操作的主机配置发生改变时要进行的操作,这里需要通知它,然后handlers定义的动作会被执行。
file:主要是存储一些服务器需要的系统配置文件
meta:定义role和role之间的依赖关系
templates:存放模板,对应task里面的模块template
default目录:为当前角色设定默认变量时使用此目录

2 本例以使用playbook编译安装nginx为例

[root@localhost ansible]# tree roles/
roles/
└── nginx
    ├── defaults
    ├── files
    │   ├── nginx-1.6.2.tar.gz (源码包)
    │   └── pcre-8.35.tar.gz (源码包)
    ├── handlers
    │   └── main.yml (定义配置文件修改后触发的动作)
    ├── meta
    ├── tasks
    │   └── main.yml
    ├── templates
    │   ├── nginx (启动脚本)
    │   └── nginx.conf (主配置文件)
    └── vars
        └── main.yml (定义本role里的变量)

A、nginx配置文件的具体内容:

# cat tasks/main.yml
- name: create software directory
  file: dest={{ SOFTWARE }}/ state=directory
- name: Copy nginx_tar_gz to client
  copy: src=nginx-{{ nginx_version }}.tar.gz dest=/usr/local/src/nginx-{{ nginx_version }}.tar.gz
- name: Install nginx package
  yum: name={{ item }} state=present #(循环调用with_items里的软件包,采用yum方式安装)
  with_items:
    - zlib
    - zlib-devel
    - openssl
    - openssl-devel
    - pcre-devel
  ignore_errors: True
#(因为ansible执行时候如果一条命令报错,后面的命令不会再执行,这个参数的作用是忽略报错继续后面的安装)
- name: Add group "www" #(添加nginx用户组)
  group: name=www
- name: Add user "www"
  user: name=www group=www home=/home/www shell=/sbin/nologin
#(添加nginx用户指定所属组,家目录,及shell不允许登录)
- name: Tar pcre.tgz
  unarchive: src=/etc/ansible/roles/nginx/files/pcre-8.35.tar.gz dest={{ SOFTWARE }}/ copy=yes
  #(此参数用于将宿主机上的软件包传递到目标目录直接解压,copy=no 的意思是不复制软件包到目标机器上)
- name: configure pcre
  command: chdir={{ SOFTWARE }}/pcre-8.35 ./configure
- name: make pcre
  command: chdir={{ SOFTWARE }}/pcre-8.35 make
- name: make install pcre
  command: chdir={{ SOFTWARE }}/pcre-8.35 make install
- name: Tar nginx.tgz
  #unarchive: src=/usr/local/src/nginx-{{ nginx_version }}.tar.gz dest={{ SOFTWARE }} copy=no
  command: tar zxf /usr/local/src/nginx-{{ nginx_version }}.tar.gz -C {{ SOFTWARE }}
- name: configure nginx
  command: chdir={{ SOFTWARE }}/nginx-{{ nginx_version }} {{ configure }}
- name: make nginx
  command: chdir={{ SOFTWARE }}/nginx-{{ nginx_version }} make
- name: make install nginx
  command: chdir={{ SOFTWARE }}/nginx-{{ nginx_version }} make install
- name: create vhost directory
  file: dest=/usr/local/nginx-{{ nginx_version }}/conf/vhost/ state=directory
  #(此参数是定义目录或者文件的属性,此处为创建一个目录)
- name: create access directory
  file: dest=/data/logs/www/vhosts/ state=directory
- name: create error directory
  file: dest=/data/logs/www/error/ state=directory
- name: create data directory
  file: dest=/data/www/ state=directory
#- name: Copy host_config to client
#  template: src=test.conf dest=/usr/local/nginx-{{ nginx_version }}/conf/vhost/test.conf mode=755
#  notify: restart vhost_nginx
#  #(将templates目录下面的test.conf主机模板拷贝到目标主机上,并且指定,当配置文件有改动时候重启nginx服务)
- name: Copy nginx_config to client
  template: src=nginx.conf dest=/usr/local/nginx-{{ nginx_version }}/conf/nginx.conf owner=root group=root
  notify: restart conf_nginx
  #(此处也是重启nginx服务,之所以写不同的名称,是因为相同的名称只有第一个配置生效,即同时修改了两个配置文件,只有上面的会重启服务,下面的不会)
- name: copy nginx_script to client
  template: src=nginx dest=/etc/init.d/nginx mode=0755
- name: Start nginx service
  service: name=nginx state=started enabled=yes     #(启动服务,并设置将服务添加到启动服务里面设置开机自起)

B、定义上面文件中引用的变量

# cat vars/main.yml (定义上面文件中引用的变量)
nginx_version: 1.6.2
SOFTWARE: /usr/local/src/software
NGINX_PREFIX: /usr/local/nginx-{{ nginx_version }}
configure: ./configure --user=www --group=www --prefix={{ NGINX_PREFIX }} --sbin-path={{ NGINX_PREFIX }}/sbin/nginx --conf-path={{ NGINX_PREFIX }}/conf/nginx.conf --with-http_stub_status_module --with-http_ssl_module --with-pcre={{ SOFTWARE }}/pcre-8.35/ --lock-path={{ NGINX_PREFIX }}/logs/nginx.lock --pid-path={{ NGINX_PREFIX }}/logs/nginx.pid

C、定义配置文件修改后触发的动作

# cat handlers/main.yml #(定义配置文件修改后触发的动作)
- name: restart vhost_nginx
  service: name=nginx state=restarted
- name: restart conf_nginx
  service: name=nginx state=restarted

3 总调度文件

[root@localhost ansible]# cat webserver.yml
- hosts: test
  remote_user: root
  roles:
    – nginx

4 验证语法是否有误

[root@localhost ansible]# ansible-playbook /etc/ansible/webserver.yml --syntax-check

5 实际结果

[root@localhost ansible]# ansible-playbook /etc/ansible/webserver.yml -v

如果没有报错,则执行完毕,登录目标服务器可以查看安装的服务是否正常。

给我留言

本站理念:

致力于运维技术的分享,运维前源技术的探讨,欢迎广大朋友一起参与,一起分享,共同成长。

交流探讨:

QQ群:26489714