ansible批量推送公钥

1.使用 ssh-keygen -t rsa生成密钥对

ssh-keygen -t rsa

2.推送单个公钥到远程机器

格式: ssh-copy-id -i ~/.ssh/id_rsa.pub username@[ip,hostname]

ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

3.添加ansible hosts

编辑/etc/ansible/hosts,没有则创建些文件。

格式:【主机名】 【主机地址】 【主机密码】 默认是root用户来进行的

[tomcat-servers]
1 ansible_ssh_user="tomcat"  ansible_ssh_host=192.168.100.1 ansible_ssh_pass="test"
2 ansible_ssh_user="tomcat"  ansible_ssh_host=192.168.100.2 ansible_ssh_pass="test"

新版的ansible(2.4) hosts有更新, 用以下方式:

[tomcat-servers]
192.168.100.1   ansible_user=tomcat  ansible_ssh_pass="test"
192.168.100.2   ansible_user=tomcat  ansible_ssh_pass="test"

4.批量推送公钥到远程机器

机器多的情况下,使用ssh-copy-id方法有些费时,使用ansible-playbook推送ymal,这里使用到了authoried_keys模块,可以参考官方文档http://docs.ansible.com/authorized_key_module.html

将以下文件命名为:push.ssh.ymal

 # Using alternate directory locations:
  - hosts: tomcat-servers
    user: tomcat (互信用户)
    tasks:
     - name: ssh-copy
       authorized_key: user=tomcat(互信用户) key="{{ lookup('file', '/home/tomcat/.ssh/id_rsa.pub(master端公钥)') }}"
       tags:
         - sshkey

5.执行推送命令

ansible-playbook push.ssh.ymal -f 10 (并发数)

6.如若报错,解决

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.

修改host_key_checking(默认是check的):

vi /home/xiangdong/ansible/ansible.cfg
# uncomment this to disable SSH key host checking
host_key_checking = False

7.测试

#查看各机器时间
ansible all -a date
#ansible all -m command -a date # 作用同上

#ping
 ansible all -m ping

输出结果:

$ ansible all  -m ping 
192.168.100.1 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

Ansible+Jenkins+Svn实现自动化部署

  • 实验平台:CentOS6.8
  • 主机使用IP: 10.113.128.120
  • Jenkins版本:2.46.3

一、安装ansible

1. yum安装

yum -y install ansible

如果yum安装没有找到ansible包
使用阿里云的源

http://mirrors.aliyun.com/repo/epel-6.repo
cd /etc/yum.repo.d/
wget http://mirrors.aliyun.com/repo/epel-6.repo  #下载源

2. 配置文件

cd /etc/ansible/
ll

total 28
-rw-r--r-- 1 root root 18066 Jun  2 05:49 ansible.cfg       #ansible主配置文件
-rw-r--r-- 1 root root  1016 Jun  2 05:49 hosts             #定义主机组
drwxr-xr-x 2 root root  4096 Jun  2 05:49 roles             #定义规则

二、配置ansible

1. 为远程连接主机生成公/私钥

ssh-keygen -t rsa -P ''       #-t生成密钥类似(rsa/dsa) -P提供旧密码,'' 表示没有

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
5b:9e:3b:b7:04:47:e8:b3:28:cd:5a:ff:5e:a3:ae:b2 root@TLCUM01
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|           .     |
|          . .    |
|         . .     |
|        S = .    |
|       o = *     |
|      . * + . o  |
|       +...o.o . |
|      . Eo+B*.   |
+-----------------+
cd /root/.ssh/
ll

total 8
-rw------- 1 root root 1675 Jul  4 08:34 id_rsa         #私钥
-rw-r--r-- 1 root root  394 Jul  4 08:34 id_rsa.pub     #公钥

2. 写入信任文件

cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys   #将公钥导入authorized_keys并分发到需远程控制的服务器/root/.ssh/目录内(需新建改目录)

完成上步后:

ssh + 远程服务器IP  #即可实现免密钥登入(ansible主机必须与其互通)

3.定义主机

vim /etc/ansible/hosts

[bs]
10.113.128.28
[yy]
10.113.128.196
[bb]
10.113.128.34

4. 测试

ansible 0BS -m command -a pwd
10.113.128.28 | SUCCESS | rc=0 >>
/root

ansible命令详解

ansible
Usage: ansible <host-pattern> [options]

Options:
  -a MODULE_ARGS, --args=MODULE_ARGS        #模块的参数,如果执行默认COMMAND的模块,即是命令参数,如:“date”,"pwd"等等
                        module arguments    #模块参数
  --ask-vault-pass      ask for vault password
  -B SECONDS, --background=SECONDS          #后台运行超时时间
                        run asynchronously, failing after X seconds
                        (default=N/A)
  -C, --check           don't make any changes; instead, try to predict some
                        of the changes that may occur   #只是测试一下会改变什么内容,不会真正去执行;相反,试图预测一些可能发生的变化
  -D, --diff            when changing (small) files and templates, show the
                        differences in those files; works great with --check    
  -e EXTRA_VARS, --extra-vars=EXTRA_VARS
                        set additional variables as key=value or YAML/JSON
  -f FORKS, --forks=FORKS                                   #并行任务数。NUM被指定为一个整数,默认是5
                        specify number of parallel processes to use
                        (default=5)
  -h, --help            show this help message and exit     #打开帮助文档API
  -i INVENTORY, --inventory-file=INVENTORY                  #指定库存主机文件的路径,默认为/etc/ansible/hosts
                        specify inventory host path
                        (default=/etc/ansible/hosts) or comma separated host
                        list.
  -l SUBSET, --limit=SUBSET                                 #进一步限制所选主机/组模式  --limit=192.168.91.135 只对这个ip执行
                        further limit selected hosts to an additional pattern
  --list-hosts          outputs a list of matching hosts; does not execute
                        anything else
  -m MODULE_NAME, --module-name=MODULE_NAME                 #执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
                        module name to execute (default=command)
  -M MODULE_PATH, --module-path=MODULE_PATH                 #要执行的模块的路径,默认为/usr/share/ansible/
                        specify path(s) to module library (default=None)
  --new-vault-password-file=NEW_VAULT_PASSWORD_FILE
                        new vault password file for rekey
  -o, --one-line        condense output                     #压缩输出,摘要输出.尝试一切都在一行上输出。
  --output=OUTPUT_FILE  output file name for encrypt or decrypt; use - for
                        stdout
  -P POLL_INTERVAL, --poll=POLL_INTERVAL                    #调查背景工作每隔数秒。需要-b
                        set the poll interval if using -B (default=15)
  --syntax-check        perform a syntax check on the playbook, but do not
                        execute it
  -t TREE, --tree=TREE  log output to this directory                #将日志内容保存在该输出目录,结果保存在一个文件中在每台主机上。
  --vault-password-file=VAULT_PASSWORD_FILE
                        vault password file
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable
                        connection debugging)                       #详细信息
  --version             show program's version number and exit      #输出ansible的版本

  Connection Options:
    control as whom and how to connect to hosts

    -k, --ask-pass      ask for connection password     #登录密码,提示输入SSH密码而不是假设基于密钥的验证
    --private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
                        use this file to authenticate the connection
    -u REMOTE_USER, --user=REMOTE_USER
                        connect as this user (default=None)
    -c CONNECTION, --con=CONNECTION              #连接类型使用。可能的选项是paramiko(SSH),SSH和地方。当地主要是用于crontab或启动。
                        connection type to use (default=smart)
    -T TIMEOUT, --timeout=TIMEOUT       #指定SSH默认超时时间,  默认是10S
                        override the connection timeout in seconds
                        (default=10)
    --ssh-common-args=SSH_COMMON_ARGS
                        specify common arguments to pass to sftp/scp/ssh (e.g.
                        ProxyCommand)
    --sftp-extra-args=SFTP_EXTRA_ARGS
                        specify extra arguments to pass to sftp only (e.g. -f,
                        -l)
    --scp-extra-args=SCP_EXTRA_ARGS
                        specify extra arguments to pass to scp only (e.g. -l)
    --ssh-extra-args=SSH_EXTRA_ARGS
                        specify extra arguments to pass to ssh only (e.g. -R)

  Privilege Escalation Options:
    control how and which user you become as on target hosts

    -s, --sudo          run operations with sudo (nopasswd) (deprecated, use
                        become)
    -U SUDO_USER, --sudo-user=SUDO_USER
                        desired sudo user (default=root) (deprecated, use
                        become)     #远程用户, 默认是root用户
    -S, --su            run operations with su (deprecated, use become)
    -R SU_USER, --su-user=SU_USER   #指定SU的用户,默认是root用户
                        run operations with su as this user (default=root)
                        (deprecated, use become)
    -b, --become        run operations with become (does not imply password
                        prompting)
    --become-method=BECOME_METHOD
                        privilege escalation method to use (default=sudo),
                        valid choices: [ sudo | su | pbrun | pfexec | doas |
                        dzdo | ksu | runas ]
    --become-user=BECOME_USER
                        run operations as this user (default=root)
    --ask-sudo-pass     ask for sudo password (deprecated, use become)
    --ask-su-pass       ask for su password (deprecated, use become)
    -K, --ask-become-pass           #提示密码使用sudo,sudo表示提权操作
                        ask for privilege escalation password
</host-pattern>

三、Jenkins

1. 官网下载jenkins

https://jenkins.io/download/                     #这里我下载通用war包(在此我下的2.46.3版本2.60.1版本在tomcat下跑不起来,报错是版本有问题~)
http://mirrors.jenkins.io/war-stable/2.46.3/     #2.46.3版本的下载地址
还可以直接跑(建议使用Tomcat的方式):
改变端口再次执行,
java -jar jenkins.war --httpPort=$HTTP_PORT, 例如java -jar jenkins.war --httpPort=1080

2. 访问测试

10.113.128.120:8080/jenkins   #或localhost:8080/jenkins

四.配置Jenkins

1. 配置登录

将/root/.jenkins/secrets/initialAdminPassword里的密码文件拷贝进去

未分类

2. 选择第一个

未分类

3. 开始安装

未分类

4. 配置用户信息

未分类

5. 安装完成

未分类

6. 测试(10.113.128.120:8080/jenkins)

未分类

五、搭建svn

1. 安装

sudo yum -y install subversion  #安装svn
mkdir /ane/svn/tl -p            #创建选择在var路径下创建版本库
svnadmin create /ane/svn/tl/    #在第二步建立的路径基础上,创建版本库
cd /ane/svn/tl/conf             #进入配置目录
ll

authz:                          #负责账号权限的管理,控制账号是否读写权限
passwd:                         #负责账号和密码的用户名单管理
svnserve.conf:                  #svn服务器配置文件
vim authz                       #编辑

[aliases]
# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average

[groups]
# harry_and_sally = harry,sally
# harry_sally_and_joe = harry,sally,&joe

# [/foo/bar]
# harry = rw
# &joe = r
# * =

# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r

[]
ane = rw                            #新增(ane用户读写权限)
vim passwd                          #编辑

[users]
# harry = harryssecret
# sally = sallyssecret
ane = redhat                        #给ane用户密码为redhat

vim svnserve.conf                   #编辑


[general]

anon-access = read
auth-access = write

password-db = /ane/svn/tl/conf/passwd   #使用paswwd文件里的配置;这里要给绝对路径

authz-db = /ane/svn/tl/conf/authz       #使用authz文件里的配置;这里要给绝对路径

realm = My First Repository             #Svn讲解

六、构建

1. 首先配置好ansible里的规则(playbook) 进入roles

pwd
/etc/ansible/roles
mkdir tlsit             #创建palybook目录(tlsit项目名称)
cd /etc/ansible/roles/tlsit/
vim bs.yml

-hosts: bs             #这个是你选择的主机
 roles:
 -bs                   #这个是你下步创建的目录
NullCopy

再在bs.yml同级下创建bs文件为其添加远程构建步骤

mkdir bs
cd bs
mkdir tasks
vim main.yml

- name: del
  shell: rm -rf /ane/update/*
- name: copy
  copy: src=/root/.jenkins/workspace/sit-0BS/ROOT/ROOT.war  dest=/ane/update/
- name: update
  shell: sh /ane/script/startApp.sh

2. 进入Jenkins的主界面

点击系统管理->选择管理插件->安装Ansible plugin插件(右上角搜索),点击直接安装

3. 进入Jenkins的主界面点击新建或创建一个新任务

4. 输入项目的名字选择第一个点击OK

未分类

5. 选择源码管理中的Subversion(SVN) 填写第五步搭建SVN的地址(里面需要有代码)

未分类

6. 选择构建 增加构建步骤 选择 Execute shell

未分类

7. 配置

未分类

8. 选择构建 增加构建步骤 选择 lnvoke Ansible Playbook

未分类

9. 配置

未分类

10. 点击立即构建。

蓝色–>成功
红色–>失败
白色–>为构建或取消构建

Ansible入门与Playbook实战

一、简要

1、关于Ansible

Ansible是一个部署一群远程主机的工具;Ansible通过SSH协议实现远程节点和管理节点之间的通信。理论上说,只要管理员通过ssh登录到一台远程主机上能做的操作,Ansible都可以做到。Ansible是python开发的,故依赖一些python库和组件,如:paramiko,PyYaml和jinja三个关键组件;

2、ansible架构

Ansible入门与playbook实战
右边绿色部分是被管理的主机(虚拟机,物理机,云主机等)从以上架构图中可以看出
ansible是由主机清单(配置),playbook(配置),以及各模块插件组成;
简单的说就是,用户(管理员)通过ansible的主机清单配置或Playbook配置(一组任务),调用ansible的各种模块及参数来对清单中的主机进行统一管理;

3、测试环境

本次测试环境:

  • ansible: CentOS7.4_x64 172.16.3.167 epel yum安装ansible
  • node1: 172.16.3.152 CenOS7.2_x64
  • node2: 172.16.3.216 CentOS7.2_x64

从ansible上生成ssh私钥同步到两台node主机上,实现无密钥登录管理(推荐)

[root@ansible ~]# ssh-keygen -t rsa

直接回车生成私钥;
同步到到两台node上

[root@ansible ~]# ssh-copy-id -i ~/.ssh/id_rsa 172.16.3.216
[root@ansible ~]# ssh-copy-id -i ~/.ssh/id_rsa 172.16.3.152

注意同步过程需要输入yes和各自的root密码即可;此进可直接ssh [email protected] 就无密码登录上去啦!
配置ansible的主机清单,即把node1与node2主机添加到管理清单中

[root@ansible ~]# egrep -v '(^$|^#)' /etc/ansible/hosts
[websrvs]
172.16.3.152
172.16.3.216

到此处配置的环境完成!

4、安装

目前,只要机器上安装了 Python 2.6 或 Python 2.7 (windows系统不可以做控制主机),都可以运行Ansible.
安装ansible很简单,可通过git从githu上直接获取代码,也可以像redhat/CentOS上通过yum进行安装,

[root@ansible ~]# yum install epel-release -y
[root@ansible ~]# yum install ansible -y
#查看版本
[root@ansible ~]# ansible --version
ansible 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Nov 20 2015, 02:00:19) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]

二、配置及获取帮助说明

通过rpm -ql ansible可以看到有很多文件,主要是配置文件和和可执行文件,以及所依赖的python库文件

1、配置与执行文件说明

ansible的主配置文件

/etc/ansible/ansible.cfg

这个文件主要定义了roles_path路径,主机清单路径,连接清单中的主机方式等配置,这些大部的默认配置已经足够我们平时使用,如需要特别配置可以自行去修改;

/etc/ansible/hosts

这个配置文件就是默认主机清单配置文件,可通过ansible.cfg重新定义的;
如定义一组主机:

[root@ansible ~]# egrep -v '(^$|^#)' /etc/ansible/hosts

[websrvs]
172.16.3.152
172.16.3.216

除了以上两个重要的配置文件还有三个重要的可执行文件分别是:
ansible 主执行程序,一般用于命令行下执行
ansible-playbook 执行playbook中的任务
ansible-doc 获取各模块的帮助信息

2、ansible 使用格式

ansible

HOST-PATTERN #匹配主机模式,如all表示所有主机
-m MOD_NAME #模块名 如:ping
-a MOD_ARGS #模块执行的参数
-f FORKS #生成几个子进行程执行
-C #(不执行,模拟跑)
-u Username #某主机的用户名
-c CONNection #连接方式(default smart)

完整示例:
[root@ansible ~]# ansible all -m shell -a "ifconfig|grep enp0s3"
172.16.3.152 | SUCCESS | rc=0 &gt;&gt;
enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt; mtu 1500

172.16.3.216 | SUCCESS | rc=0 &gt;&gt;
enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt; mtu 1500

3、ansible-doc 获取帮助信息

ansible模块比较多,可以通过ansible-doc –help 显示帮助信息
ansible doc -l 获取所有当前版本下的可用模块及简要信息
ansible-doc -s 模块名 获取指定模块帮助信息说明“

三、Ansible常用模块

1、copy模块

从本地copy文件分发到目录主机路径
参数说明:
src= 源文件路径
dest= 目标路径
注意src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去
content= 自行填充的文件内容
owner 属主
group 属组
mode权限
示例:

ansible all -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible mode=600"
ansible all -m copy -a "content='hi theren' dest=/tmp/hi.txt"
到node1上查看
[root@node1 tmp]# ll
-rw------- 1 root root 465 2月 9 14:59 fstab.ansible
-rw-r--r-- 1 root root 9 2月 9 14:58 hi.txt

2、fetch模块

从远程主机拉取文件到本地
示例

[root@ansible ~]# ansible all -m fetch -a "src=/tmp/hi.txt dest=/tmp"
172.16.3.152 | SUCCESS =&gt; {
"changed": true,
"checksum": "279d9035886d4c0427549863c4c2101e4a63e041",
"dest": "/tmp/172.16.3.152/tmp/hi.txt",
"md5sum": "12f6bb1941df66b8f138a446d4e8670c",
"remote_checksum": "279d9035886d4c0427549863c4c2101e4a63e041",
"remote_md5sum": null
}
.......省略

说明:fetch使用很简单,src和dest,dest只要指定一个接收目录,默认会在后面加上远程主机及src的路径

3、command模块

在远程主机上执行命令,属于裸执行,非键值对显示;不进行shell解析;
示例1:

[root@ansible ~]# ansible all -m command -a "ifconfig"
172.16.3.152 | SUCCESS | rc=0 &gt;&gt;
enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt; mtu 1500
inet 172.16.3.152 netmask 255.255.255.0 broadcast 172.16.3.255
.....省略.....
172.16.3.216 | SUCCESS | rc=0 &gt;&gt;
enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt; mtu 1500
inet 172.16.3.216 netmask 255.255.255.0 broadcast 172.16.3.255
.....省略.....

示例2:

[root@ansible ~]# ansible all -m command -a "ifconfig|grep lo"
172.16.3.152 | FAILED | rc=2 &gt;&gt;
[Errno 2] 没有那个文件或目录

172.16.3.216 | FAILED | rc=2 &gt;&gt;
[Errno 2] 没有那个文件或目录

这就是因为command模块不是shell解析属于裸执行导致的
为了能达成以上类似shell中的解析,ansible有一个shell模块;

4、shell模块

由于commnad只能执行裸命令(即系统环境中有支持的命令),至于管道之类的功能不支持,
shell模块可以做到
示例:

[root@ansible ~]# ansible all -m shell -a "ifconfig|grep lo"
172.16.3.152 | SUCCESS | rc=0 &gt;&gt;
lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt; mtu 65536
loop txqueuelen 0 (Local Loopback)

172.16.3.216 | SUCCESS | rc=0 &gt;&gt;
lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt; mtu 65536
loop txqueuelen 0 (Local Loopback)

5、file模块

设置文件属性(创建文件)
常用参数:
path目标路径
state directory为目录,link为软件链接
group 目录属组
owner 属主
等,其他参数通过ansible-doc -s file 获取
示例1:创建目录

[root@ansible ~]# ansible all -m file -a "path=/var/tmp/hello.dir state=directory"
172.16.3.152 | SUCCESS =&gt; {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/var/tmp/hello.dir",
"size": 6,
"state": "directory",
"uid": 0
}
172.16.3.216 | SUCCESS =&gt; {
"changed": true,
.....省略.....

示例2:创建软件链接

[root@ansible ~]# ansible all -m file -a "src=/tmp/hi.txt path=/var/tmp/hi.link state=link"
172.16.3.152 | SUCCESS =&gt; {
"changed": true,
"dest": "/var/tmp/hi.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 11,
"src": "/tmp/hi.txt",
"state": "link",
"uid": 0
}
172.16.3.216 | SUCCESS =&gt; {
"changed": true,
.....省略.....

6、cron模块

通过cron模块对目标主机生成计划任务
常用参数:
除了分(minute)时(hour)日(day)月(month)周(week)外
name: 本次计划任务的名称
state: present 生成(默认) |absent 删除 (基于name)

示例:对各主机添加每隔3分钟从time.windows.com同步时间

[root@ansible ~]# ansible all -m cron -a "minute=*/3 job='/usr/sbin/update time.windows.com &amp;&gt;/dev/null' name=update_time"
172.16.3.152 | SUCCESS =&gt; {
"changed": true,
"envs": [],
"jobs": [
"update_time"
]
}
172.16.3.216 | SUCCESS =&gt; {
"changed": true,
"envs": [],
"jobs": [
"update_time"
]
}

#到node1上查看
[root@node1 tmp]# crontab -l
#Ansible: update_time
*/3 * * * * /usr/sbin/update time.windows.com &amp;&gt;/dev/null

示例2:删除计划任务

[root@ansible ~]# ansible all -m cron -a "name=update_time state=absent"
172.16.3.152 | SUCCESS =&gt; {
"changed": true,
"envs": [],
"jobs": []
}
172.16.3.216 | SUCCESS =&gt; {
"changed": true,
"envs": [],
"jobs": []
}
#node1上查看
[root@node1 tmp]# crontab -l
会发现已经被删除了

7、yum模块

故名思义就是yum安装软件包的模块;
常用参数说明:
enablerepo,disablerepo表示启用与禁用某repo库
name 安装包名
state (present’ orinstalled’, latest’)表示安装, (absent’ or `removed’) 表示删除
示例:通过安装epel扩展源并安装nginx

[root@ansible ~]# ansible all -m yum -a "name=epel-release state=installed"
[root@ansible ~]# ansible all -m yum -a "name=nginx state=installed"

8、service模块

服务管理模块
常用参数:
name:服务名
state:服务状态
enabled: 是否开机启动 true|false
runlevel: 启动级别 (systemed方式忽略)

示例:

[root@ansible ~]# ansible all -m service -a "name=nginx state=started enabled=true"
到node1上查看
[root@node1 tmp]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since 五 2018-02-09 15:54:29 CST; 1min 49s ago
Main PID: 10462 (nginx)
CGroup: /system.slice/nginx.service
├─10462 nginx: master process /usr/sbin/nginx
└─10463 nginx: worker process
......省略......

9、script模块

把本地的脚本传到远端执行;前提是到远端可以执行,不要把Linux下的脚本同步到windows下执行;
直接上示例:
本地ansible上的脚本:

[root@ansible ~]# cat test.sh
#!/bin/bash
echo "ansible script test!" &gt; /tmp/ansible.txt
[root@ansible ~]# ansible all -m script -a "/root/test.sh"
172.16.3.152 | SUCCESS =&gt; {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 172.16.3.152 closed.rn",
"stdout": "",
"stdout_lines": []
}
172.16.3.216 | SUCCESS =&gt; {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 172.16.3.216 closed.rn",
"stdout": "",
"stdout_lines": []
}
到node1上查看
[root@node1 tmp]# ls
ansible.txt fstab.ansible hi.txt
[root@node1 tmp]# cat ansible.txt
ansible script test!

script模块这个功能可以做很多事,就看你怎么用了~
以上是常用模块,至于其他模块的使用可通过官方模块列表获得~

四、Playbook实战

playbook是Ansible的配置,部署和编排的语言。他们可以描述你所希望的远程系统强制执行的政策,或者在一般的IT流程的一组步骤;形象点的说就是:如果ansible的各模块(能实现各种功能)是车间里的各工具;playbook就是指导手册,目标远程主机就是库存和原料对象.
playbook是基于YAML语言格式配置,关于YAML
更多playbook官方说明参考http://docs.ansible.com/ansible/latest/playbooks_intro.html

1、playbook的核心元素

hosts : playbook配置文件作用的主机
tasks: 任务列表
variables: 变量
templates:包含模板语法的文本文件
handlers :由特定条件触发的任务
roles :用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等

2、playbook运行方式

ansible-playbook –check 只检测可能会发生的改变,但不真执行操作
ansible-playbook –list-hosts 列出运行任务的主机
ansible-playbook –syntax-check playbook.yaml 语法检测
ansible-playbook -t TAGS_NAME playbook.yaml 只执行TAGS_NAME任务
ansible-playbook playbook.yaml 运行

3、通过playbook安装管理redis服务

#在家目录下创建playbooks
[root@ansible ~]# mkidr playbooks
[root@ansible ~]# cd playbooks
[root@ansible playbooks]# cat redis_first.yaml
- hosts: all
remote_user: root
tasks:
- name: install redis
yum: name=redis state=latest

- name: start redis
service: name=redis state=started

语法检测:

[root@ansible playbooks]# ansible-playbook --syntax-check redis_first.yaml

playbook: redis_first.yaml

说明语法没有 问题
将要执行的主机:

[root@ansible playbooks]# ansible-playbook --list-hosts redis_first.yaml
playbook: redis_first.yaml
play #1 (all): all TAGS: []
pattern: [u'all']
hosts (2):
172.16.3.216
172.16.3.152

执行

[root@ansible playbooks]# ansible-playbook redis_first.yaml
PLAY [all] *****************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************
ok: [172.16.3.216]
ok: [172.16.3.152]
TASK [install redis] *******************************************************************************************************
changed: [172.16.3.216]
changed: [172.16.3.152]
TASK [start redis] *********************************************************************************************************
changed: [172.16.3.152]
changed: [172.16.3.216]
PLAY RECAP *****************************************************************************************************************
172.16.3.152 : ok=3 changed=2 unreachable=0 failed=0
172.16.3.216 : ok=3 changed=2 unreachable=0 failed=0

说明:
自上而下列出了三个任务,分别是[Gathering Facts] , [install redis], [start redis],其中各主机上成功为ok=3,有两项任务执行结果是changed
不可达 和失败的任务均为0;

由于上面的操作是直接安装redis服务并启动,并没有配置文件,这还不能往生产环境中使用,生产环境中的redis肯定有不同的配置项,因此需要在安装时提供配置文件

4、带配置文件的安装管理redis

首先复制一个redis.conf到本地并进行修改

[root@ansible ~]# ansible 172.16.3.152 -m fetch -a "src=/etc/redis.conf dest=./"
[root@ansible ~]# mv /root/172.16.3.152/etc/redis.conf /root/playbooks/redis.conf
修改bind 0.0.0.0

cat redis_second.yaml
- hosts: all #所有远程主机
remote_user: root #以远程主机上root用户执行
tasks: #任务
- name: install redis #任务之安装
yum: name=redis state=latest #动作调用yum模块安装
- name: copy config file #任务之复制同步配置文件到远程目标主机
copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis #动作copy模块执行
notify: restart redis #触发的动作
tags: configfile #任务标记名configfile
- name: start redis #任务之启动redis
service: name=redis state=started #动作调用sevice模块
handlers: #特定情况下,接收到其他任务的通知时被触发
- name: restart redis
service: name=redis state=restarted

再次测试并执行

[root@ansible playbooks]# ansible-playbook redis_second.yaml

PLAY [all] ****************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************
ok: [172.16.3.152]
ok: [172.16.3.216]
TASK [install redis] ******************************************************************************************************
ok: [172.16.3.216]
ok: [172.16.3.152]
TASK [copy config file] ***************************************************************************************************
changed: [172.16.3.152]
changed: [172.16.3.216]
TASK [start redis] ********************************************************************************************************
ok: [172.16.3.152]
ok: [172.16.3.216]
RUNNING HANDLER [restart redis] *******************************************************************************************
changed: [172.16.3.152]
changed: [172.16.3.216]
PLAY RECAP ****************************************************************************************************************
172.16.3.152 : ok=5 changed=2 unreachable=0 failed=0
172.16.3.216 : ok=5 changed=2 unreachable=0 failed=0

可以发现只是加了一个配置文件,所有的任务都执行了,可否只应用新添加的任务?当然可以
这里就要通过
ansible-playbook -t TAGS_NAME 来执行了
可以把redis.conf中添加一个登录密码再执行测试下:

[root@ansible playbooks]# ansible-playbook -t configfile redis_second.yaml
PLAY [all] ****************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************
ok: [172.16.3.152]
ok: [172.16.3.216]
TASK [copy config file] ***************************************************************************************************
changed: [172.16.3.216]
changed: [172.16.3.152]
RUNNING HANDLER [restart redis] *******************************************************************************************
changed: [172.16.3.152]
changed: [172.16.3.216]
PLAY RECAP ****************************************************************************************************************
172.16.3.152 : ok=3 changed=2 unreachable=0 failed=0
172.16.3.216 : ok=3 changed=2 unreachable=0 failed=0

以上执行结果就没有 了安装与启动的步骤~只有更新和重启!
更多playbook使用示例请添加链接描述https://github.com/ansible/ansible-examples

总结

ansible通过常用模块在命令行就可以针对主机清单来管理配置远程主机,无需要代理客户端程序,但需要目标主机有ssh和python2.4+;基于
ssh协议既可以通过用户名和密码,也可以通过私钥,推荐使用私钥;
windows上需要安装powershell及winrm服务也可以做到,关于这方面 可以参考我之前的博客http://blog.51cto.com/dyc2005/2064746
通过ansib-doc来获取模块信息及指定模块帮助信息;
ansible-playbook 基于YAML语法配置;可以对playbook文件进行测试,解析并执行应用于指定无端主机;非常方便我们统一编排分发管理远程主机;
本文旨在入门;后续会针对playbook的roles角色及其他更多强大功能再进行详细说明;如有不当之处欢迎留言交流!

//下面这个css和插件后台设置的主题有关系,如果需要换样式,则需要修改以下CSS名称

Ansible 的 command 和 shell 模块

ansible 的 command 和 shell 模块都可以执行命令,例如:

➜  www ansible k8s-master -m command  -a 'pwd'
kubernetes-1 | SUCCESS | rc=0 >>
/root

➜  www ansible k8s-master -m shell  -a 'pwd'
kubernetes-1 | SUCCESS | rc=0 >>
/root

但是如果你使用 command 运行一些包含特殊符号的命令,比如“|” “<” “>” 之类的命令就无法执行,原因我们通过

ansible-doc command    

查看

Notes:
  * If you want to run a command through the shell (say you are using `<', `>', `|', etc), you actually want the [shell]
        module instead. The `command' module is much more secure as it's not affected by the user's environment.
  *  `creates', `removes', and `chdir' can be specified after the command. For instance, if you only want to run a
        command if a certain file does not exist, use this.

因此在使用的时候需要注意了。

解决新装 ubuntu 无法运行 ansible 的问题

尽管用 CentOS 的人多,但我是推崇 Ubuntu Server,简洁易用,包管理可靠稳健。

但是,用 ubuntu server xenial 或以上的版本,就会遇到一个新装的系统,无法执行 ansible 的问题。因为 ubuntu xenial 以上版本已经默认使用 python3 了。通常的解决方法就是安装 python-minimal 包。

最近设计一套 ansible 脚本时,预设的环境是离线内网集群,那么如何解决这个问题呢?我编写了一个初始化 playbook 代码。

以下我的 hosts 内容,ubuntu_hosts是空的:

[servers]
centos7 ansible_host=192.168.1.146 ansible_ssh_port=22
ubuntu16 ansible_host=192.168.3.231 ansible_ssh_port=22

[ubuntu_hosts]

以下我的 playbook 内容:

- hosts: all
  become: yes
  gather_facts: no
  tasks:
    - include_role:
        name: init
        tasks_from: check_python.yml

- hosts: all
  become: yes
  roles:
    - init

我们来看看 init 里的 check_python.yml 做了什么动作:

- block:
    - name: testing python2
      raw: test -e /usr/bin/python
      when: ansible_python_interpreter is not defined
  rescue:
    - name: testing python3
      raw: test -e /usr/bin/python3
    - name: set python3 as default python command
      lineinfile:
        path: hosts
        line: '{{ inventory_hostname }} ansible_python_interpreter=/usr/bin/python3'
        insertafter: '[ubuntu_hosts]'
      delegate_to: localhost
      become: no
    - meta: clear_host_errors
    - meta: refresh_inventory
  1. 首先检查是否有 python 命令。

  2. 如果检查失败,那么执行 resuce 部分的 tasks,把这台机器写入到 hosts 文件里,指定使用 python3 作为交互命令。

  3. 清除错误,刷新 inventory 列表。为之后的动作扫清障碍。

这样我们就得到了一个新的 hosts 列表:

[servers]
centos7 ansible_host=192.168.1.146 ansible_ssh_port=22
ubuntu16 ansible_host=192.168.3.231 ansible_ssh_port=22

[ubuntu_hosts]
ubuntu16 ansible_python_interpreter=/usr/bin/python3

以下是输出截图

未分类

原本我是用了个偷懒的方法,直接在 Ubuntu Xenial 上建一个软链 /usr/bin/python 指向 /usr/bin/python3 的,也能解决 ansible 的执行问题。但考虑到这样可能会给以后运行其它 python 应用挖坑,所以还是稍微折腾一下,确保我们不改动系统级别的命令工具。

ansible笔记(4):常用模块之文件操作

在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。

ansible系列博文直达链接:ansible轻松入门系列

“ansible系列”中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。

前文中,我们已经介绍了怎样使用模块,而且我们知道,ansible有很多模块,每个模块都有自己的功能,”模块”涉及到的方向比较多,所以对于个人来说,并没有必要了解所有的模块,我们只需要根据实际的业务场景了解相应的模块即可,而且ansible比较贴心,ansible根据模块的功能对这些模块进行了大致的分类,比如,如果某些模块都是操作文件的,就把它们分类到文件类模块中,如果某些模块都是操作数据库的,就把他们分类到数据库类模块中,那么,ansible把模块分为了哪些类呢?你可以参考官方手册,找到答案,模块的分类目录如下
http://docs.ansible.com/ansible/latest/modules_by_category.html

上述链接不仅对模块进行了分类,还给出了每个模块的使用示例,不过这些示例都是编写”剧本(playbook)”的示例,我们还没有介绍过怎样编写剧本,所以暂时不会参考这些示例,前文的示例中,我们一直以命令的方式运行ansible,通过命令的方式调用模块,这种直接在命令行中运行的ansible命令被称作为”ad-hoc命令”,我们可以通过”ad-hoc命令”的方式,快速的了解一个模块。

在前文的示例中,我们已经了解了ping模块与fetch模块,那么这篇文章中,我们来了解一些新的模块,这些模块都是常用的操作文件的模块,不过这篇文章写得并不全面,后续有空会继续补充总结,对等更新的朋友说声见谅,最近比较忙。

copy模块

见名知义,copy模块的作用就是拷贝文件,它与之前介绍的fetch模块类似,不过,fetch模块是从远程主机中拉取文件到ansible

主机,而copy模块是将ansible主机上的文件拷贝到远程主机中。

此处我们介绍一些copy模块的常用参数,然后再给出对应示例。

  • src参数 :用于指定需要copy的文件或目录

  • dest参数 :用于指定文件将被拷贝到远程主机的哪个目录中,dest为必须参数

  • content参数 :当不使用src指定拷贝的文件时,可以使用content直接指定文件内容,src与content两个参数必有其一,否则会报错。

  • force参数 : 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变。

  • backup参数 : 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机。

  • owner参数 : 指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错。

  • group参数 : 指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错。

  • mode参数 : 指定文件拷贝到远程主机后的权限,如果你想将权限设置为”rw-r–r–“,则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示。

对应上述参数的ad-hoc示例命令如下:

将ansible主机中/testdir/copytest文件复制到远程主机的/opt目录下

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/"

在远程主机的/opt目录下生成文件test,test文件中有两行文本,第一行文本为aaa,第二行为bbb,当使用content指定文件内容时,dest参数对应的值必须是一个文件,而不能是一个路径。

ansible test70 -m copy -a 'content="aaanbbbn" dest=/opt/test'

将ansible主机中/testdir/copytest文件复制到远程主机的/opt目录中时,如果远程主机中已经存在/opt/copytest文件,并且文件内容与ansible主机中的copytest文件的内容不一致,则不执行拷贝操作,远程主机中的/opt/copytest文件内容不会被改变。

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ force=no"

将ansible主机中/testdir/copytest文件复制到远程主机的/opt目录中时,如果远程主机中已经存在/opt/copytest文件,并且文件内容与ansible主机中的copytest文件的内容不一致,会执行拷贝操作,但是在执行拷贝操作之前,会将远程主机中的原文件重命名,以作备份,然后再进行拷贝操作。

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ backup=yes"

拷贝文件时,指定文件的属主,需要注意,远程主机上必须存在对应的用户。

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ owner=zsy"

拷贝文件时,指定文件的属组,需要注意,远程主机上必须存在对应的组。

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ group=zsy"

拷贝文件时,指定文件的权限

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ mode=0640"

file模块

file模块可以帮助我们完成一些对文件的基本操作,比如,创建文件或目录、删除文件或目录、修改文件权限等

此处我们介绍一些file模块的常用参数,然后再给出对应示例。

  • path参数 :必须参数,用于指定要操作的文件或目录,在之前版本的ansible中,使用dest参数或者name参数指定要操作的文件或目录,为了兼容之前的版本,使用dest或name也可以。

  • state参数 :此参数非常灵活,此参数对应的值需要根据情况设定,比如,当我们需要在远程主机中创建一个目录的时候,我们需要使用path参数指定对应的目录路径,假设,我想要在远程主机上创建/testdir/a/b目录,那么我则需要设置path=/testdir/a/b,但是,我们无法从”/testdir/a/b”这个路径看出b是一个文件还是一个目录,ansible也同样无法单单从一个字符串就知道你要创建文件还是目录,所以,我们需要通过state参数进行说明,当我们想要创建的/testdir/a/b是一个目录时,需要将state的值设置为directory,”directory”为目录之意,当它与path结合,ansible就能知道我们要操作的目标是一个目录,同理,当我们想要操作的/testdir/a/b是一个文件时,则需要将state的值设置为touch,当我们想要创建软链接文件时,需将state设置为link,想要创建硬链接文件时,需要将state设置为hard,当我们想要删除一个文件时(删除时不用区分目标是文件、目录、还是链接),则需要将state的值设置为absent,”absent”为缺席之意,当我们想让操作的目标”缺席”时,就表示我们想要删除目标。

  • src参数 :当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源。

  • force参数 : 当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件,不过强制创建链接文件分为两种情况,情况一:当你要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当你要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,回将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当你要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件。

  • owner参数 :用于指定被操作文件的属主,属主对应的用户必须在远程主机中存在,否则会报错。

  • group参数 :用于指定被操作文件的属组,属组对应的组必须在远程主机中存在,否则会报错。

  • mode参数:用于指定被操作文件的权限,比如,如果想要将文件权限设置为”rw-r-x—“,则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的,如果你想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700,很方便吧。

  • recurse参数:当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性。

对应上述参数的ad-hoc示例命令如下:

在test70主机上创建一个名为testfile的文件,如果testfile文件已经存在,则会更新文件的时间戳,与touch命令的作用相同。

ansible test70 -m file -a "path=/testdir/testfile state=touch"

在test70主机上创建一个名为testdir的目录,如果testdir目录已经存在,则不进行任何操作。

ansible test70 -m file -a "path=/testdir/testdir state=directory"

在test70上为testfile文件创建软链接文件,软链接名为linkfile,执行下面命令的时候,testfile已经存在。

ansible test70 -m file -a "path=/testdir/linkfile state=link src=/testdir/testfile"

在test70上为testfile文件创建硬链接文件,硬链接名为hardfile,执行下面命令的时候,testfile已经存在。

ansible test70 -m file -a "path=/testdir/hardfile state=hard src=/testdir/testfile"

在创建链接文件时,如果源文件不存在,或者链接文件与其他文件同名时,强制覆盖同名文件或者创建链接文件,参考上述force参数的解释。

ansible test70 -m file -a "path=/testdir/linkfile state=link src=sourcefile force=yes"

删除远程机器上的指定文件或目录

ansible test70 -m file -a "path=/testdir/testdir state=absent"

在创建文件或目录的时候指定属主,或者修改远程主机上的文件或目录的属主。

ansible test70 -m file -a "path=/testdir/abc state=touch owner=zsy"
ansible test70 -m file -a "path=/testdir/abc owner=zsy"
ansible test70 -m file -a "path=/testdir/abc state=directory owner=zsy"

在创建文件或目录的时候指定属组,或者修改远程主机上的文件或目录的属组。

ansible test70 -m file -a "path=/testdir/abb state=touch group=zsy"
ansible test70 -m file -a "path=/testdir/abb group=zsy"
ansible test70 -m file -a "path=/testdir/abb state=directory group=zsy"

在创建文件或目录的时候指定权限,或者修改远程主机上的文件或目录的权限。

ansible test70 -m file -a "path=/testdir/abb state=touch mode=0644"
ansible test70 -m file -a "path=/testdir/abb mode=0644"
ansible test70 -m file -a "path=/testdir/binfile mode=4700"
ansible test70 -m file -a "path=/testdir/abb state=directory mode=0644"

当操作远程主机中的目录时,同时递归的将目录中的文件的属主属组都设置为zsy。

ansible test70 -m file -a "path=/testdir/abd state=directory owner=zsy group=zsy recurse=yes"

ansible笔记(3):ansible模块的基本使用

在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。

ansible系列博文直达链接:ansible轻松入门系列

“ansible系列”中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。

在前文的基础上,我们已经知道,当我们使用ansible完成实际任务时,需要依靠ansible的各个模块,比如,我们想要去ping某主机,则需要使用ping模块,命令如下

ansible all -m ping

前文说过,除了ping模块,ansible还有很多模块可供我们使用,那么ansible都有哪些模块呢?我们可以使用如下命令,查看ansible都有哪些模块。

ansible-doc  -l

执行上述命令后,可以看到ansible中各个模块的名称,以及模块的大概功能,当然,通过”ansible-doc -l”命令获取到的模块信息比较概括,并不是特别详细,如果想要获取到各个模块更加详细的用法,可以使用“ansible-doc -s”命令,比如,我们想要获取ping模块的详细使用方法,则可以使用如下命令查看

ansible-doc -s ping

即使使用“ansible-doc -s ping”命令查看ping模块的信息,得到的信息也是比较少的,这是因为ping模块本来就比较简单,而且ping模块并没有太多参数可用,但是并非所有模块都像ping模块一样简单,有的模块在使用时必须使用参数,比如 fetch 模块,见名知义,fetch为”拿来”之意,当我们需要将受管主机中的文件拉取到ansible主机时,则可以使用此模块,首先,我们可以使用“ansible-doc -s fetch”命令,查看一下fetch模块的用法,如下图所示

未分类

从帮助信息中可以看出,fetch模块的作用就是”Fetches a file from remote nodes”,即”从受管主机中拉取文件”之意,而且fetch模块提供了一些参数供我们使用,我们可用的参数有 dest、fail_on_missing、flat、src、validate_checksum ,如上图所示,返回信息中注释了每个参数的作用。

比如src参数,src参数的作用就是指定从受管主机中拉取哪个文件。

比如dest参数,dest参数的作用就是指定拉取文件到本地以后文件存放的位置。

细心如你一定发现了,在上图中,dest参数和src参数的注释中都包含”(required)”字样,这表示,在使用fetch模块时,dest参数与src参数是必须提供的,如果在使用fetch模块时,没有提供这两个参数,将会报错,想想也对,如果我们想要从远程主机中拉取文件,那么我们必须告诉ansible,从哪里拉取文件,拉取后将文件存放到哪里吧,所以,在学习怎样使用一个模块时,要注意这些必选参数,那么,我们就从fetch模块入手,看看怎样使用带有参数的模块吧~

在开始之前,先来看一下我们的主机清单配置,配置如下

[testA]
test60 ansible_host=10.1.1.60
test61 ansible_host=10.1.1.61

[testB]
test70 ansible_host=10.1.1.70

[test:children]
testA
testB

假如我们想要将testA组中所有主机的/etc/fstab文件拉取到本地,则可以使用如下命令

ansible testA -m fetch -a "src=/etc/fstab dest=/testdir/ansible/"

如上述命令所示,-m选项用于调用指定的模块,”-m fetch”表示调用fetch模块,

-a选项用于传递模块所需要使用的参数, -a “src=/etc/fstab dest=/testdir/ansible/”表示我们在使用fetch模块时,为fetch模块传入了两个参数,src与dest。

那么,我们一起来看一下上述命令的执行效果吧,如下

未分类

从命令的执行结果可以看出,上述命令执行成功了,因为两个主机对应的返回信息都返回了”SUCCESS”字样。

你可能会有疑问,为什么命令执行成功了,返回的信息却是”黄色”的,在我们的印象中,执行成功,返回的信息不应该是”绿色”的吗?这是为什么呢?此处我们暂且不讨论这个话题,后面我们再行解释。

从返回信息可以看出,执行上述ansible命令后,主机test60和主机test61中的文件已经拉取成功,test61的fstab文件被拷贝到了本机的/testdir/ansible目录中,而且,ansible在/testdir/ansible目录中自动创建了目录结构 test61/etc/,由于我们是同时从多台受管主机中拉取相同名称的文件,所以ansible会自动为我们创建各个主机对应的目录,以区分存放不同主机中的同名文件,有没有觉得很方便,很人性化呢~?

之前说过,ansible具有幂等性,幂等性能够保证我们重复的执行一项操作时,得到的结果是相同的,我们再来回顾一下幂等性的概念。

“幂等性”是什么意思呢?举个例子,你想把一个文件拷贝到目标主机的某个目录上,但是你不确定此目录中是否已经存在此文件,当你使用ansible完成这项任务时,就非常简单了,因为如果目标主机的对应目录中已经存在此文件,那么ansible则不会进行任何操作,如果目标主机的对应目录中并不存在此文件,ansible就会将文件拷贝到对应目录中,说白了,ansible是”以结果为导向的”,我们指定了一个”目标状态”,ansible会自动判断,”当前状态”是否与”目标状态”一致,如果一致,则不进行任何操作,如果不一致,那么就将”当前状态”变成”目标状态”,这就是”幂等性”,”幂等性”可以保证我们重复的执行同一项操作时,得到的结果是一样的。

那么我们就来实验一下,看看重复执行相同的ansible命令时,会得到什么效果,效果如下图所示

未分类

从上图可以看出,返回信息仍然包含”SUCCESS”字样,证明ansible命令执行成功,不过很明显,这次的返回信息为”绿色”,而且细心如你一定发现了,这次绿色的返回信息中,”changed”字段的值为false,而之前黄色的返回信息中,”changed”字段的值为true。

当返回信息为绿色时,”changed”为false,表示ansible没有进行任何操作,没有”改变什么”。

当返回信息为黄色时,”changed”为true,表示ansible执行了操作,”当前状态”已经被ansible改变成了”目标状态”。

没错,这就是幂等性的体现,当第一次执行上述命令时,ansible发现当前主机中并没有我们需要的fstab文件,ansible就会按照我们指定的操作,拉取fstab文件,也就是说,ansible”改变”了”当前状态”,将当前”没有fstab文件的状态”变为了”有fstab文件的状态”,当我们再次执行同样的命令时,ansible发现对应文件已经存在与对应目录中,于是ansible并没有做出任何操作,也没有进行任何改变,因为”当前状态”与我们预期的”目标状态”一致,没有必要再做出重复的无用功。

看到这里,你应该已经明白,为什么执行ansible命令时,会返回黄色的成功信息或者绿色的成功信息了吧?我们可以通过返回信息的颜色,更加精准的判断执行命令之前的状态是否与我们预期的一致。

从返回信息中可以看到,当ansible进行fetch操作时,会对对应文件进行哈希计算,算出文件哈希值,也就是说,如果我们改变了文件中的内容,哈希值也将随之发生改变,这个时候,即使对应目录中存在同名的文件,ansible也会判断出两个文件属于不同的文件,因为它们的哈希值并不相同,我们来实验一下,操作如下

未分类

如上图所示,我们在/testdir/ansible/test61/etc/fstab文件的尾部加入一个”空格”,以改变文件内容,然后又执行了fetch命令,我们发现,test61的返回信息为黄色,test60主机的返回信息为绿色,证明ansible已经做出了正确的判断,将修改过的文件替换了,替换为重新拉取的文件。

小结

我们对上文的一些命令进行总结,方便以后回顾

列出ansible所支持的模块

ansible-doc -l

查看模块的详细帮助信息,比如查看fetch模块的帮助

ansible-doc -s fetch

调用模块,比如调用ping模块

ansible all -m ping

调用模块的同时传入模块所需要的参数,以fetch模块为例

ansible 10.1.1.60 -m fetch -a "src=/etc/fstab dest=/testdir/ansible/"

关于ansible模块的基本使用,我们暂时先介绍到这里,希望能够对你有所帮助~

ansible笔记(2):清单配置详解

在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。

ansible系列博文直达链接:ansible轻松入门系列

“ansible系列”中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。

上一篇文章介绍了ansible的基本概念,以及相关的基础配置,我们已经知道,如果想要管理受管主机,则需要将受管主机添加到ansible的管理清单中,当安装ansible以后,会提供一个默认的管理清单,即/etc/ansible/hosts文件,今天我们就来详细的聊聊它。

仍然以我们之前的演示环境为例,我们有4台主机,IP如下

  • 10.1.1.71

  • 10.1.1.70

  • 10.1.1.61

  • 10.1.1.60

主机71为ansible主机,同时,主机71的公钥已经配置在了其他3台主机中。

在前文中,我们已经介绍了怎样简单的配置清单,比如通过IP地址的方式配置受管主机,或者通过别名的方式配置受管主机,此处不再赘述,假设,我想要通过ansible管理主机60与主机61,那么我可以在/etc/ansible/hosts中写入如下内容

10.1.1.60

10.1.1.61

配置完成后,即可通过命令管理这两台主机,仍然使用之前的示例命令作为演示。

未分类

如上图所示,我们使用了两条命令,分别去ping主机60和主机61,是没有问题的,其实,我们也可以使用”all”关键字,在一条命令中,一次性的去操作”清单”中的所有主机,示例如下

未分类

是不是很简单,有没有很方便?那么,聪明如你一定会想,我们能不能自定义一些类似”all”这样的关键字呢?

答案是肯定的,清单支持”分组”功能,我们可以将某些主机分为一组,然后通过组名去管理组内的所有主机。

比如,主机60和主机61都属于A模块的服务器,主机70属于B模块的服务器,那么,我们则可以在清单中进行如下配置

未分类

上述配置表示我们定义了两个组,A组和B组,A组中包含主机60与61,B组中包含主机70,经过上述配置后,我们可以通过组名去管理组内的所有主机,示例如下。

未分类

当然,在实际的应用中,我们并不会使用”A”或者”B”这样的名字作为组名,此处是为了演示方便,在实际使用时,组名应该尽量的见名知义

在上例的A组中,两台受管主机的IP地址为10.1.1.60和10.1.1.61 ,细心如你一定发现了,这两台主机的IP地址是连续的,所以,我们可以使用更简洁的方法,配置A组中的受管主机,示例如下

未分类

上例A组中的配置与之前A组中的配置的效果是相同的,不过这种方式更加方便,因为如果你需要配置10台IP地址连续的主机时,只需要一条配置就可以搞定了。

除了使用IP地址,我们也可以使用主机名配置受管主机,当然,使用主机名配置受管主机的前提是ansible主机可以正确解析对应的主机名,比如,我们想要通过主机名配置两台主机,示例如下。

未分类

眼尖的你一定又从上述配置中发现了某种规律,没错,上述主机名中,”dbSrv-“之后的字母是按照字母顺序排列的,所以,上述配置也可以简写为如下模样,它们的效果是相同的。

未分类

通常情况下,我们为了更加的灵活的管理受管主机,可能需要在组内嵌套组。

比如,服务器环境从大类上可以分为”生产环境”和”测试环境”,所以,我们很自然的把主机分成了两组,生产组和测试组,但是,仔细想想,生产环境又包含很多业务模块,比如,A模块生产组、B模块生产组,同理,测试环境中也会有同样的问题,比如A模块测试环境组,B模块测试组,这时,我们就需要更加细化的进行分组,示例如下

未分类

上述示例表示我们配置了3个组,proA组、proB组、pro组,而pro组中包含”子组”,没错,”children”关键字表示当前组中存在子组,pro组的子组就是proA组和proB组,也就是说,当我们操作pro组时,就相当于操作proA组和ProB组中的所有主机,这样分组就能为我们带来一些好处,比如,当我们需要针对生产环境中的所有主机进行操作时,调用pro组即可,当我们需要对生产环境中的某一个模块进行操作时,比如生产环境中的A模块,那么我们只调用proA组即可。

当然,你也可以使用更加”原始”的方法,实现与上述分组相同的效果,示例如下。

未分类

没错,同一主机可以被分配到不同的组中,而这种分组的方式与之前子组的分组方式实现的效果是相同的,但是,这样分组并不能体现出组与组之间的逻辑层级关系,而且,当子组内的主机非常多时,这种原始的方法容易让管理变得”混乱”,所以,当组与组之间存在一定的层级关系时,我们还是推荐使用嵌套组的方式配置组,因为这样做逻辑上更加清晰。

到目前为止,我们一直都在使用INI的配置风格去配置”清单”,其实,/etc/ansible/hosts不仅能够识别INI的配置语法,还能够识别”YAML”的配置语法。

YAML是一种语言,YAML是”YAML Ain’t a Markup Language”的缩写,从YAML的全称可以看出来,YAML并不是一种标记语言,但是,如果你使用过类似XML这种标记语言,那么你可能会很快的学会YAML,与XML相同的是,我们可以使用YAML编写配置文件,而ansible的清单也支持YAML的语法,所以我们可以使用YAML语法编写清单,从而管理受管主机,这样说可能不是特别容易理解,不如先来看一个小例子(没有接触过YAML语法没有关系,先向下看)

如下示例仍然是在/etc/ansible/hosts文件中编写

未分类

上述配置就是使用YAML语法配置的主机清单,非常简单

最上方使用all关键字,all后面有”:”,你一定联想到了,我们之前可以使用all关键字,管理清单中的所有主机,这里的”all:”就是这个含义。

第二行开头使用一个空格作为缩进,使用hosts关键字,表示hosts属于all的下一级,我们可以这样理解,all是默认的一个组,这个组是最大的一个组,当我们需要在组中定义受管主机时,就需要使用到hosts关键字,当我们进行自定义分组时,也需要使用hosts关键字,每个分组指明自己组内的受管主机时,都要使用到hosts关键字,注意,在YAML的语法中,只能使用空格作为缩进,不能使用tab,否则语法上会报错,如果你习惯使用vim编辑文件,同时你又习惯使用tab作为缩进,那么你可以将ansible主机上的vim进行设置,默认将tab转化为空格,这样就能兼容你的使用习惯了,我就是这样设置的。

第三行开头使用两个空格作为缩进,然后指明了主机60的IP地址,没错,主机60的IP地址就是hosts元素下一级的元素

第四行开头使用两个空格作为缩进,然后指明了主机61的IP地址,你一定想明白了,主机60和主机61的层级是相同的,它们是平级的,因为它们的左侧缩进是对齐的。

为了让从来没有接触过YAML的朋友能够更好的理解,在下面的示例中,我们会先给出INI风格的配置,然后使用YAML语法写出同样效果的配置,并进行对比,以方便理解,虽然”清单”能够同时识别这两种语法,但是不建议在一个”清单”中同时混用这两种语法。

此处先列出上述YAML配置以及对应的INI配置

#YAML示例
all:
  hosts:
    10.1.1.60:
    10.1.1.61:

#上例相当于如下INI配置
10.1.1.60
10.1.1.61

那么,我们来扩展一下

#先看一个INI风格的配置,示例如下
10.1.1.61

[test1]
10.1.1.60

[test2]
10.1.1.70
#上述配置表示当前清单中有3台受管主机,主机61不属于任何组,主机60属于test1组,主机70属于test2组

#使用YAML语法进行同等效果的配置如下
#注意,为了使缩进显得更加明显,此处每次缩进使用两个空格
all:
  hosts:
    10.1.1.61:
  children:
    test1:
      hosts:
        10.1.1.60:
    test2:
      hosts:
        10.1.1.70:
#从上例可以看出,当直接在清单中创建组时,需要在all关键字内使用children关键字,而定义每个组时,有必须使用hosts关键字,指明组内的主机

有了上面的基础,我们来看一下当组中嵌套组时,使用YAML语法应该怎样描写

#仍然先写出INI风格的示例以作对比,如下
[proA]
10.1.1.60

[proB]
10.1.1.70

[pro:children]
proA
proB

#对应YAML格式的配置如下
all:
  children:
    pro:
      children:
        proA:
          hosts:
            10.1.1.60:
        proB:
          hosts:
            10.1.1.70:
#上述配置表示,pro组有两个子组,分别为proA组和proB组,而这两个组分别有自己组内的主机。

细心如你,一定已经发现,当我们使用YAML语法配置清单时,无非是使用hosts、children等关键字与我们的自定义名称进行排列组合罢了。

#前文中,我们还介绍了使用别名的方式配置受管主机,INI格式的示例如下

未分类

#同等效果的YAML语法配置如下

未分类

注意:上图中标注的”空格”不可省,这是YAML的语法,省略空格后会报错

其实,我们还可以在清单中配置变量,但是,目前我们并没有实际的演示场景,所以此处先行略过。

更多内容可以参考官网手册,直达链接如下

http://docs.ansible.com/ansible/latest/intro_inventory.html

你可能已经习惯使用INI的语法编辑清单,或者你对YAML并不熟悉,于是你准备放弃学习YAML语法,这样并不可行,因为之后我们会介绍怎样编写ansible的剧本,编写ansible剧本时,只能使用YAML语法,所以,不要放弃YAML,当然,我们也不用过于深究YAML的语法,我们只要记住一些套路(固定格式),就可以编写ansible剧本了,所以不要着急,船到桥头自然直,到时候你自然会掌握这些语法的。

好了,关于”清单”的配置暂时总结到这里,希望能够对你有所帮助。

使用ansible批量格式化并挂载磁盘

初始化安装elasticsearch这类集群系统的时候,往往需要批量操作大量的磁盘。可以通过ansible快速完成这类工作。

假设每台设备有10块盘(sdxxx),要挂载到/dataxxx,elasticsearch数据目录为/dataxxx/es,首先将变量写入vars/main.yaml,

---

disks:
  /dev/sdb: /data1
  /dev/sdc: /data2
  /dev/sdd: /data3
  /dev/sde: /data4
  /dev/sdf: /data5
  /dev/sdg: /data6
  /dev/sdh: /data7
  /dev/sdi: /data8
  /dev/sdj: /data9
  /dev/sdk: /data10

然后,创建任务文件,tasks/main.yaml,

---

- file:
    path: "{{ item.value }}/es"
    state: directory
    owner: elasticsearch
    group: elasticsearch
    mode: 0755
  with_dict: "{{ disks }}"

- name: umount datanode disks
  mount:
    path: "{{ item.value }}"
    state: absent
  with_dict: "{{ disks }}"

- name: format datanode disks
  filesystem: fstype=xfs dev="{{ item.key }}" force=true
  with_dict: "{{ disks }}"

- name: mount datanode disks
  mount:
    path: "{{ item.value }}"
    src: "{{ item.key }}"
    fstype: xfs
    opts: "defaults,noatime,nobarrier"
    state: mounted
  with_dict: "{{ disks }}"

创建目录、umount、format、mount、写入/etc/fstab,一气呵成。

ansible 基本概念,ad-hoc操作

概述

本文描述自动化运维工具 Ansible 的安装及基础使用方法,包含:

  • Centos 下的安装
  • 主机配置
  • Ad-Hoc command(命令行执行)
  • Playbook (任务剧本)

Ansible 和 Saltstack 是目前主流的两个自动化运维工具,都可以用于同时对大量主机进行系统配置,应用部署等工作,利用这种集成化的自动运维工具最大的优势在于运维体系结构的持续可维护性。本文先着眼于 Ansible 的基础使用,不会进行太多扩展,通过本文可以快速上手使用 Ansible。

安装

Ansible 的一大特点是 agentless,可以通过 SSH 来对服务器进行管理,意味着只需要将 Ansible 部署到一台服务器。

Ansible 并非一定使用 ssh 来与服务器进行通信,它也支持 ZeroMq 的扩展。事实上,如果不是总要同时对一个庞大主机群进行操作,通过 ssh 进行通信在效率上的损失还是可以接受的。

在 Centos 系统上,Ansible 可以用过 yum 来进行安装,前提是需要 EPEL 的源。

以 Centos7 为例执行下列命令安装 EPEL 源:

rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

安装 Ansible

yum install ansible

通常情况下,Ansible 可以部署到登录服务器上,登录服务器存放 ssh 私钥,这样在对操作主机群时就无需每次输入密码。

主机配置

Ansible 默认主机配置文件在 /etc/ansible/hosts,你也可以创建新的配置文件来管理主机,如果使用其他主机配置,在执行命令行时就需要通过 -i 参数指定主机配置。

下边是一个主机配置的例子,foo.example.com 这些就是主机的定义,webservers 是主机组的定义,在使用 Ansible 时,可以通过主机组对一组服务器进行操作。

[webservers]
foo.example.com
bar.example.com

Ad-Hoc Command

Ad-Hoc Command 指那些希望立即执行对一组服务器进行操作,而这个操作过程不需要进行保存的方式。例如临时需要对webservers 这组主机下的 /opt/testfile 文件进行删除,而这种操作是没有必要保存成 Playbook (剧本模式,稍后会说到)的。

$ ansible webservers -m command -a "rm -f /opt/testfile" 

参数 -m 指定使用的功能模块是 command,-a 设置模块所需参数队列,对于 command 模块来讲,这个参数就是你需要执行的命令。

事实上,command 模块也有几个参数,当需要指定多个参数时,就需要使用 arg1=value1 arg2=value2 这样的键值对方式指定,当没有指定参数时,在这里实际上使用 command 的是 free_form 参数。

Ansible 默认使用的模块是 command,这意味着上述命令行并不需要显式指定功能模块,可以直接使用下列命令行
ansible webservers -a "rm -f /opt/testfile"

再举个简单的例子,批量文件分发:

$ ansible webservers -m copy -a "src=/etc/hosts dest=/tmp/hosts"

上述命令将本地 /etc/hosts 分发到 webservers 的 /tmp/hosts。

使用 ansible-doc -l 可以查看 Ansible 支持哪些模块,也可以直接前往 这里 去查看。

使用 ansible-doc -s module_name 可以获取模块的使用帮助。

Playbook

Playbook 可以称之为任务剧本,它允许你按照剧本的方式编排需要完成的任务,使用 YAML 的语法格式。

早期,我们可能使用脚本来完成一些流程相对繁多的任务,脚本可以很好的执行,但可读性差。YAML 这种配置性的语法格式则可读性很好,并且对于没有编程基础的运维人员来讲,它也更容易上手。

看一个 playbook 的例子:

---
- hosts: webservers
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: name=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 (and enable it at boot)
    service: name=httpd state=started enabled=yes
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

这个简单的例子完成的任务是部署或更新 webservers 这一组主机的 apache。

  • hosts:定义操作的主机组

  • remote_user:使用的用户

  • task:任务步骤,共分为三步:

    • 1 通过 yum 模块确认 apache 是否安装以及是否是最新版本,如果不是则安装或更新;
    • 2 通过 template 模块来设置配置文件,如果配置有更新则通知 handler 重启 apache;
    • 3 通过 service 模块来判断 apache 是否在运行,如果没有则启动 apache。
  • handlers:事件处理,处理任务中的 notify

Playbook 完成后,执行就可以完成对一组服务器的操作

ansible-playbook playbook.yml 

以上就是 Ansible 的基础使用方法,更多的可以去参考 Ansible 的文档http://docs.ansible.com/ansible/latest/index.html