ansible配置基础使用

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

前提准备

学习ansible至少需要两台及以上服务器做基础,一台主机,多台从机。多于缺乏硬件资源的同学我们可以使用Docker,关于Docker可以参考之前的文章Docker基础使用,使用docker开启以下三个镜像。

服务器环境centos7centos7centos7
ip地址172.17.0.2172.17.0.3172.17.0.4
身份masterslaveslave
容器ID0784b3ebd803462f8117e08fa341fb8cc4f8
容器名centos-mastercentos-slave1centos-slave2

服务器配置

配置epel

修改3个容器的epel源,我们这里使用了阿里的

1
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

主机安装ansible

1
yum install -y ansible

安装ssh

如果你生成秘钥时出现以下提示bash: ssh: command not found,则要安装ssh客户端,已安装的请忽略

1
2
3
# 安装ssh服务端客户端
yum -y install openssh-server
yum -y install openssh-clients

主机生成密钥对

1
ssh-keygen # 用来生成ssh的密钥对

复制公钥到从机

ssh-copy-id将公钥复制到远程机器中 ,此步干净的容器会出现问题,参考底部常见问题

1
2
ssh-copy-id 172.17.0.3 # 复制公钥到远程主机
ssh-copy-id 172.17.0.4 # 复制公钥到远程主机

配置ansible hosts文件

配置文件位置:/etc/ansible/hosts

未分组主机

直接书写主机名或ip

1
2
172.17.0.3
172.17.0.4

分组主机

按组操控其下的主机

1
2
3
4
5
[db]
172.17.0.3
[web]
172.17.0.4
172.17.0.5

甚至其中可以用到类似正则

如:

1
2
3
4
5
6
7
8
[db]
172.17.0.[100:103]
# 等同于
[db]
172.17.0.100
172.17.0.101
172.17.0.102
172.17.0.103

我们这里就按未分组主机形式,其中控制多个分组可以有以下几种:

交集
1
2
# 查看分组web和db之间的交集所包含的主机是否在线
ansible web:&db -m ping
并集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查看分组web和db之间的并集所包含的主机是否在线
ansible web,db -m ping
#
ansible 'web:db' -m ping

# 返回结果
172.17.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
172.17.0.4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
差集
1
2
3
4
5
6
7
8
9
10
# 查看分组web和db之间的交集(web包含且db不包含的)所包含的主机是否在线

[root@0784b3ebd803 /]# ansible 'web:!db' -m ping
172.17.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}

常用命令

command

1
2
3
4
5
6
7
8
ansible web -a 'ls /'#第一个命令
ansible web -a 'pwd'
ansible web -a 'chdir=/tmp pwd'# 切换目录执行命令,使用场景是编译安装时使用
ansible web -a 'creates=/tmp pwd' # 用来判断/tmp目录是否存在,存在就不执行操作
ansible web -a 'creates=/data pwd' # 因为data不存在,所有才会执行pwd命令
ansible web -a 'removes=/tmp pwd' #用来判断tmp目录是否存在,存在就执行操作
ansible web -a 'removes=/data pwd' #因为data不存在,所有才不会执行

查看用户是否创建成功

1
2
3
4
tail -1 /etc/passwd
tail -1 /etc/shadow
id tom
echo '123' | passwd --stdin tom #设置密码

shell

1
2
3
4
5
ansible web -m shell -a 'echo "123" | passwd --stdin tom' # 批量创建密码
ansible 192.168.107.131 -m shell -a 'bash a.sh' # 执行远程文件方式一
ansible 192.168.107.131 -m shell -a '/root/a.sh' #执行远程文件方式二,文件必须有执行权限
ansible 192.168.107.131 -m shell -a '/root/a.py' # 执行远端的Python脚本

script

1
2
3
4
ansible web -m script -a '/root/m.sh' # 执行本地的文件,执行管控机上的文件
ansible web -m script -a 'removes=/root/m.sh /root/m.sh' # 用来判断被管控机上是不是存在文件,如果存在,存在就执行,不存在就不执行
ansible web -m script -a 'creates=/root/a.sh /root/m.sh' #用来判断被管控机上是不是存在文件,如果存在,就不执行

copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
backup 备份,以时间戳结尾
dest 目的地址
group 文件的属组
mode 文件的权限 r 4 w 2 x 1
owner 文件的属主
src 源文件
# 通过md5码来判断是否需要复制
ansible db -m copy -a 'src=/root/m.sh dest=/tmp/a.sh' #复制本地文件的到远程主机
ansible db -m copy -a 'src=/root/m.sh dest=/tmp/a.sh mode=755' #修改文件的权限
ansible web -m copy -a 'src=/root/m.sh dest=/tmp/a.sh mode=755 owner=tom' 修改文件的属主
ansible web -m copy -a 'src=/etc/init.d dest=/tmp/ mode=755 owner=tom' # 复制本地目录到远程主机,如果改变文件的属性,则文件夹内的文件也会被改变
ansible web -m copy -a 'src=/etc/init.d/ dest=/tmp/ mode=755 owner=tom' # 复制本地目录内的所有文件到远程主机
ansible web -m copy -a "content='大弦嘈嘈如急雨,小弦切切如私语\n' dest=/tmp/b.txt" # 直接将文本内容注入到远程主机的文件中

file

补充

1
2
3
4
5
inode 硬盘的地址
id 获取到的是内存的地址
ln -s a.py b.py 创建软连接
ln a.py c.py 创建硬链接
当 源文件变化时,软连接和硬链接文件都会跟着变化
1
2
3
4
ansible db -m file -a 'path=/lzmly2  state=directory' #在远程机器上创建文件夹
ansible db -m file -a 'path=/root/q.txt state=touch' #用来在远程机器上创建文件
ansible db -m file -a 'path=/tmp/f src=/etc/fstab state=link' #创建软连接src是源地址,path是目标地址
ansible db -m file -a 'path=/tmp/f state=absent' #用来删除文件或者文件夹

fetch

1
2
3
dest 目的地址
src 源地址
ansible web -m fetch -a 'src=/var/log/cron dest=/tmp' # 下载被控节点的文件,每台机器创建一个文件夹,并保留原来的目录结构

yum

  • rpmyum 的区别

    rpm:redhat package manager yum可以解决依赖关系

  • yum 源配置

  • [epel]
    name=Extra Packages for Enterprise Linux 7 - $basearch #名字
    baseurl=http://mirrors.aliyun.com/epel/7/$basearch  #rpm源的地址,可以写http,https,ftp,Samba,file:
    failovermethod=priority
    enabled=1 # 是否开启,1代表开启,0表示关闭
    gpgcheck=0  #是否校验签名,1代表校验,0表示校验
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
    
    1
    2
    3
    4
    5
    6

    - `yum` 安装包组

    ```shell
    yum grouplist # 查看包组信息
    yum groupinstall # 安装包组
    1
    2
    3
    4
    disablerepo #禁用源
    enablerepo #启用源
    name #包名
    state install (`present' or `installed', `latest'), or remove (`absent' or `removed')
    1
    2
    3
    4
    ansible web -m yum -a 'name=wget' # 安装wget
    ansible web -m yum -a 'name=python2-pip' # 安装python2-pip
    ansible web -m yum -a 'name=wget state=absent' # 卸载软件包
    ansible web -m yum -a 'name="@Development Tools"' # 安装包组

查看是否已安装

1
rpm -q nginx

pip

1
2
3
4
pip install 安装包
pip freeze > a.txt 将python的环境打包到文件中
pip install -r a.txt 安装文件中的包
pip list 查看所有的以安装成功的包
1
ansible web -m pip -a 'name=flask' # 安装flask模块

service

1
2
3
4
5
6
ps -ef|grep nginx #查看进程
ss -tnlp # 查看端口信息
systemctl start nginx # centos7
service nginx start # centos6
systemctl enabled nginx # centos7 开机自启动
chkconfig nginx on # centos6开机自启动
1
2
ansible web -m service -a 'name=nginx state=started' # 启动nginx
ansible web -m service -a 'name=nginx state=stopped' # 关闭nginx

cron

本人用的容器,测试没有crontab命令,见常见问题

1
2
3
4
5
6
7
8
9
* * * * * job 
分 时 日 月 周 任务
0 */2 * * * job 每隔两个小时
0 12,13 * * * job 12点和13点
0 12-17 * * * job 12点到17点
0 12-17/2 * * 1,3,6,0 周1,周3,周6,周7 12点到17点每隔两个小时
crontab -e # 编辑计划任务
crontab -l # 查看计划任务
crontab -r # 删除计划任务
1
2
3
4
5
6
7
8
day  天
disabled 禁用
hour 小时
job 任务
minute 分钟
month 月
name 任务名字
weekday 周
1
2
3
ansible db -m cron -a 'minute=26 job="touch /tmp/xzmly.txt" name=touchfile' # 新建一个计划任务
ansible db -m cron -a 'name=touchfile state=absent' # 删除一个计划任务
ansible db -m cron -a 'minute=26 job="touch /tmp/xzmly.txt" name=touchfile disabled=yes' # 禁用计划任务,以#表示禁用

user

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
用户:
管理员 root 0
普通用户
系统用户 不能登录 1-999 centos7 1-499 centos6
登录用户 可以登录 1000-65535 centos7 500-65535 centos6
用户组:
管理员组 root 0
系统用户组 1-999 centos7 1-499 centos6
登录用户组 1000-65535 centos7 500-65535 centos6

-d 指定用户的家目录
-g 指定用户的组
-G 执行用户的附加组
-s 指定登录后使用的shell
-r 创建一个系统组
useradd -r kitty 创建系统用户, 从999倒序
useradd -s /sbin/nologin tomsb 创建的是普通用户,从1000开始升序
useradd -d /opt/tomsb2 tomsb2 创建用户时指定用户的家目录
useradd -u 3000 tomsb6 # 创建用户并指定用户的uid
userdel tom 删除用户
userdel -r tomsb2 删除用户并删除用户的家目录

groupadd machao 创建用户组
groupdel machao 删除用户组
1
2
3
4
5
6
7
8
9
10
11
12
13
group 组
groups 附加组
home 家目录
name 用户名
password 密码
remove ?
shell 用户登录后使用的shell
system 创建一个系统用户
uid 用来指定用户的id
state 状态
ansible db -m user -a 'name=canglaoshi uid=4000 home=/opt/canglaoshi groups=root shell=/sbin/nologin' #创建一个用户,并指定用户的id,用户的家目录,用户的附加组,用户的shell
ansible db -m user -a 'name=canglaoshi state=absent' #删除用户但是不删除用户的家目录
ansible db -m user -a 'name=canglaoshi3 state=absent remove=yes' # 删除用户并删除用户的家目录

group

1
2
3
4
5
6
gid 组的id
name 组名
system 系统组
state
ansible db -m group -a 'name=canglaoshi system=yes' #创建系统组
ansible db -m group -a 'name=canglaoshi state=absent' # 删除组

web

创建一个用户组tom10

1
ansible web -m group -a 'name=tom10'

创建一个用户kitty10

1
ansible web -m user -a 'name=kitty10'

把/etc/fstab文件复制到远程主机上/tmp/f

1
ansible web -m copy -a 'src=/etc/fstab dest=/tmp/f'

安装nginx,并启动,设置开机自启动

1
2
3
ansible web -m yum -a 'name=nginx'

ansible web -m service -a 'name=nginx enabled=yes'

常见问题

从机拒绝访问

报错如下:

1
/usr/bin/ssh-copy-id: ERROR: ssh: connect to host 172.17.0.2 port 22: Connection refused

此时因为从机没有开启ssh导致的,从机可以执行以下操作

1
2
3
/usr/sbin/sshd-keygen -A # 手动执行

/usr/sbin/sshd # 再执行

从机测试ssh服务

1
ssh localhost

问题解决。如果提示输入密码就先设置一个密码。

1
ssh-keygen # 用来生成ssh的密钥对

从机无法安装软件

报错如下:

1
Failed to get D-Bus connection: Operation not permitted

Docker的设计理念是在容器里面不运行后台服务,容器本身就是宿主机上的一个独立的主进程,也可以间接的理解为就是容器里运行服务的应用进程。一个容器的生命周期是围绕这个主进程存在的,所以正确的使用容器方法是将里面的服务运行在前台。

再说到systemd,这个套件已经成为主流Linux发行版(比如CentOS7Ubuntu14+)默认的服务管理,取代了传统的SystemV风格服务管理。systemd维护系统服务程序,它需要特权去会访问Linux内核。而容器并不是一个完整的操作系统,只有一个文件系统,而且默认启动只是普通用户这样的权限访问Linux内核,也就是没有特权,所以自然就用不了!因此,请遵守容器设计原则,一个容器里运行一个前台服务!

如果想使用systemctl命令,可以使用特权模式启动docker,具体步骤如下:

特权模式运行容器

1
2
root@Tony-PC:/home/tony# docker run -d --privileged centos-master init
7474265a02674d34d7ea94c89f05e60a1a2edf7a95ba4830b8e728b512b8e163

后台模式进入容器

1
docker exec -it 7474 bash

再次使用该命令,没问题了。

无法使用cron

报错如下:

1
bash: crontab: command not found

解决办法就是安装呗

1
[root@7474265a0267 /]# ansible all -m yum -a 'name=crontabs'

测试,已解决

1
2
[root@c5c6db1e6ac4 /]# crontab -l
no crontab for root