Linux轻量级自动运维工具-
Ansible 创始人 Michael DeHanan 2012-03-09
同类自动化工具:
Ansible
Saltstack
Puppet
Chef
Fabric
Ansible 特点
agentless (去中心化)
只要保存管理机的认证信息,那么任何一台机器都可以变成管理机
Stupied Simple
SSH by default
YAML no code 定制剧本
基于python 实现
模块化:调用特定模块,完成特定任务,支持自定义模块
冥等性
-m 指定模块
-a 指定参数
web 主机列表
ansible特性
模块化:调用特定的模块,完成特定的任务;
基于Python语言研发,由Paramiko, PyYAML和Jinja2三个核心库实现;
部署简单:agentless;
支持自定义模块,使用任意编程语言;
强大的playbook机制;
幂等性;
安装及程序环境:
程序:
ansible
ansible-playbook
ansible-doc
配置文件:
/etc/ansible/ansible.cfg
主机清单:
/etc/ansible/hosts
插件目录:
/usr/share/ansible_plugins
Master 机
安装ansible
yum -y install ansible
ansible命令的使用:
Usage: ansible <host-pattern> [options]
常用选项:
-m MOD_NAME
-a MOD_ARGS
配置Host Inventory:
/etc/ansible/hosts
[group_id]
HOST_PATTERN1
HOST_PATTERN2
编辑/etc/ansible/hosts文件
然后添加我们下面实验操作用到的主机
[web] 主机列表
172.18.252.126
172.18.254.26
172.18.251.122
生成公钥
# ssh-keygen
#ssh-copi-id [email protected] 把公钥发送到目标主机
#ssh-copi-id [email protected]
#ssh-copi-id [email protected]
如果目标主机已经认证过
可以清掉公钥
cd .ssh/
> authorzed_key
> know_hosts
为了实验再来一次
———————————————————————————————————————————————————————————也可
cd /root/.ssh/
生成私钥和公钥 ssh-keygen -t rsa -P ‘‘
ls
复制公钥文件到authorized_keys
# cat id_rsa.pub >> authorized_keys
# chmod 600 authorized_keys
把公钥传送到其他主机
scp authorized_keys 172.18.252.126:/root/.ssh/
.................
.................
然后重新执行ansible的ping模块命令查看该两台主机的连通性
可以发现此时已经成功
# ansible web -m ping
ansible模块:
获取模块列表:ansible-doc -l
获取指定模块的使用帮助:ansible-doc -s MOD_NAME
常用模块:
ping模块:探测目标主机是否存活;
# ansible web -m ping
(注 : 像Ping 这样的模块有上千个)
ansible的默认模块
command
示例1
让所有主机都执行 uname -r 命令 (显示操作系统的发行版号)
# ansible web -m command -a "uname -r"
示例2
在主机上都创建一个 hello 用户
#ansible web -m command -a "useradd hello"
然后检查三台主机是否创建此用户
# ansible web -m command -a "id hello"
# ansible web -m command -a "tail /etc/passwd"
帮三个主机的hello用户改密码
*shell模块:在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等
*因为ansible的command模块并不支持管道等输出,所以下面介绍另外一个ansible的模块shell
# ansible web -m shell -a "echo chenhao | passwd --stdin hello"
但是实际工作中不允许root 用户来直接登录使用,可以使用以下方法
在目标主机
# visudo
把这行注释掉 #wheel ALL=(ALL) ALL
把这行#取消 %wheel ALL=(ALL) NOPASSWD:ALL
# usermod -G wheel chen (把chen 用户添加到 wheel附加组里 就可以直接执行 免密码sudo )
###
# ansible web -m ping -u chen -b --become-user root
小公司 可能会直接使用root
大公司 会把root 权限回收
copy模块:复制文件到远程主机
ansible-doc -s copy
用法:
(1) 复制文件
-a "src= dest= "
(2) 给定内容生成文件
-a "content= dest= "
其它参数:mode, owner, group, …
示例:
复制文件到其他主机
前提: 该目标主机的指定目录需要存在,不然会报错
src 源
dest 目标
mode 权限
# ansible web -m copy -a "src=/path/to/somefile dest=/path/to/somefile mode=600"
# ansible web -m copy -a "src=/etc/fstab dest=/tmp/ backup=yes mode=0644 owner=chen group=hellogroup"
file模块:设置文件的属性
用法:
(1) 创建目录:
-a "path= state=directory"
(2) 创建链接文件:
-a "path= src= state=link"
(3) 删除文件:
-a "path= state=absent“
查看说明
ansible-doc -s file
修改文件的权限和属主
# ansible web -m file -a "path=/path/to/somefile mode=600 owner=chen"
然后到目标主机上验证
创建文件的软连接
ansible web -m file -a "src=/somefile path=/somefile.link state=link"
目标主机上验证文件、
ll /dir/somefile
设置文件的状态为absent(即删除文件)
# ansible web -m file -a "path=/dir/somefile.link state=absent"
_____________________________________________
fetch模块:从远程主机拿文件
# ansible-doc -s fetch
示例: 从172.18.254.26上拿个文件
# ansible 172.18。254.26 -m fetch -a "src=/dir/somefile dest=/root"
获取文件的时候,也会创建对应的ip地址的目录,以区分文件
————————————————————————————————————————————————
cron模块:管理计划任务条目
用法:
-a ""
minute=
hour=
day=
month=
weekday=
job=
name=
user=
state={present|absent}
#ansible-doc -s cron
示例:创建一个同步时间的计划任务,每10分钟同步一下服务器的时间
# ansible web -m cron -a "minute=‘*/10‘ job=‘/usr/sbin/ntpdate 172.18.252.126 &> /dev/null‘ name=‘sync time‘"
验证:目标主机上
crontab -l
示例
删除计划任务
# ansible web -m cron -a "name=‘sync time ‘ state=absent"
这时到目标主机上验证,任务已经被删除了
# crontab -l
hostname模块:管理主机名
用法:
name=
#ansible-doc -s hostname
示例: 查看所有主机名
#ansible web -a "hostname"
修改:
# ansible 172.182.252.84 -m hostname "name=centos007"
_______________________________________________
yum模块:使用yum命令完成程序包管理
用法:
-a ""
(1) name= state={present|latest}
(2) name= state=absent
# ansible-doc -s yum
示例:安装指定包
此实验,首先,确定主机的yum源是可用的,否则实验会失败
# yum info nginx
安装nginx
# ansible web -m yum -a "name=nginx"
删除nginx
# ansible web -m yum "name=nginx state=absent"
这时查看
#yum info nginx 已经没安装的字眼REPO installed
++++++++++++++++++++++++++++++++++++++++++++++++
service模块:服务管理
用法:
-a ""
name=
state=
started
stopped
restarted
enabled=
runlevel=
#ansible-doc -s service
示例: 开启httpd服务
首先确认服务是关闭的
# service httpd stop
#ss -tnl
开启httpd服务,并设置为开机启动
#ansible web -m service -a "name=httpd state=started enabled=ture"
____________________________________
group模块:增加或删除组
用法:
-a ""
name=
state=
system=
gid=
# ansible-doc -s group
示例 添加一个组
# ansible web -m group -a "name=grouphello system=ture" (是否为系统组)
验证 # gentent group hellogroup
删除组:
# ansible web -m group -a "name=hellogroup state=absent"
——————————————————————————————————————————————
user模块: 用户管理
使用格式:
name= : 创建的用户名
state= : present新增,absent删除
force= : 删除用户的时候删除家目录
system= : 创建系统用户
uid= : 指定UID
shell= : 指定shell
home= : 指定用户家目录
# ansible-doc -s user
示例: 添加一个系统用户
# ansible web -m suer -a "name=hellousers system=ture"
验证 # ansible web -a "id hellousers"
(再说一次这里没指定模块,默认模块是command)
示例: 删除一个用户
# ansible web -m user -a "name=hellousers state=absent"
______________________________________________
setup模块:获取主机里面的各种信息
# ansible-doc -s setup
# ansible 172.18.251.122 -m setup
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
________________________________________________________________________________________________________________________________________________
YAML : 是一种数据序列化工具的语言格式
YAML is a data serialization format designed for human readability and interaction with scripting languages.
# yum info PyYAML
数据结构:
key:value
– item1
– item2
– item3
例如{name:jerry, age:21}
PlayBook
核心元素:
Tasks:任务,由模块定义的操作的列表;
Variables:变量
Templates:模板,即使用了模板语法的文本文件;
Handlers:由特定条件触发的Tasks;
Roles:角色;
playbook的基础组件:
Hosts:运行指定任务的目标主机;
remote_user:在远程主机以哪个用户身份执行;
sudo_user:非管理员需要拥有sudo权限;
tasks:任务列表
模块,模块参数:
格式:
(1) action: module arguments
(2) module: arguments
运行playbook,使用ansible-playbook命令
(1) 检测语法
ansible-playbook –syntax-check /path/to/playbook.yaml
(2) 测试运行
ansible-playbook -C /path/to/playbook.yaml
–list-hosts
-list-tasks
–list-tags
(3) 运行
ansible-playbook /path/to/playbook.yaml
-t TAGS, –tags=TAGS
–skip-tags=SKIP_TAGS
–start-at-task=START_AT
示例1:定义一个playbook任务来新增用户和组
定义一个yaml的模板( 这里使用TAB 键是会被踢出运维队伍的,所以全部用空格代替)
# vim group.yml
---
- hosts: all
remote_user: root
tasks:
- name: add a group
group: name=hellogroup system=ture
- name: add a user
user: name=hellousers group=hellogroup system=ture
先检查语法有没有错误,没有提示就说明语法没问题
# ansible-playbook --syntax-check group.yml
先测试运行看看 -C 表示仅测试一遍, 但是不会实际操作
# ansible-playbook -C group.yml
也可以单独测试某些特定的选项查看仅影响的主机
# ansible-playbook -C group.yml --list-hosts
查看运行哪些任务
# ansible-playbook -C group.yml --list-taskss
查看哪个任务打标了,这里并没有任何任务打标记,后面再演示
# ansible-playbook -C group.yml --list-tags
以上都没有问题,开始正式运行该任务
# ansible-playbook group.yml
示例添加用户
vim user.yml
---
- hosts: web
remote_user: root
tasks:
- name: Added User1
user: name=user1 system=true uid=307
- name: Added User2
user: name=user2 system=true uid=308
示例: 定义一个playbook任务来修改文件端口
vim web.yml
此步骤里面有安装httpd的安装包,其实此处有点多余,因为测试的两台主机均已经安装该服务,此处添加上去是为了演示效果,因为当生产环境中,假如存在一台服务器没有该安装包,那么次处就能帮我们安装上去,不然的话,漏了这一步,到后面查原因也挺麻烦的
---
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install conf file
copy: src=/testdir/httpd.conf dest=/etc/httpd/conf/httd.conf
- name: start httpd service
service: name-hhtpd state=started
检查语法问题
# ansible-playbook --syntax-check web.yml
先从一台主机上面把httpd.conf文件拷来编辑
scp 172.18.251.122:/etc/httpd/conf/httpd.conf /testdir/
修改httpd.conf文件
比如修改端口为8080. 其他都为默认配置
Listen 8080
首先备份好鸽子主机里面的配置文件,以防万一
# ansible web -m shell -a "cp /etc/httpd/conf/httpd.conf{,.bask}"
、
检查备份是否成功
# ansible web -a "ls -l /etc/httpd/conf"
测试运行 web.yml 看看有没有问题,没有问题就正常运行
# ansible-playbook -C web.yml
然后就执行该文件
# ansible-playbook web.yml
验证服务器端口打开没有,可以看见8080端口已经打开,实验成功
# ansible websrvs -a "ss -tnl"
---------------
Handlers的使用:由特定条件触发的Tasks;
格式:
tasks:
– name: TASK_NAME
module: arguments
notify: HANDLER_NAME
handlers:
– name: HANDLER_NAME
module: arguments
示例:参照上面的例子继续修改apache的端口
修改端口号为8090
修改原来的web.yml脚本实现操作
---
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install conf file
copy: src=/testdir/httpd.conf dest=/etc/httpd/conf/httd.conf
notify: restart httpd service *****
- name: start httpd service
service: name-hhtpd state=started
handlers: ****
- name: restart httpd service ****
service: name=httpd state=restarted *****
检测语法
#ansible-playbook --syntax-check web.yml
测试运行,可以看出,当复制文件过去的时候,会触发到restart httpd service的handlers任务,所以任务就重启了,而不是启动
# ansible-playbook -C web.yml
正式执行
# ansible-playbook web.yml
验证结果,8090端口已经打开,实验成功
# ansible web -a "ss -tnl"
______________________________
tags:给指定的任务定义一个调用标识;
使用格式:
– name: NAME
module: arguments
tags: TAG_ID
示例:执行特定的tags
修改文件的端口为8088
在此前的配置文件上面插入一个标签instconf
后面打****************号的
---
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install conf file
copy: src=/testdir/httpd.conf dest=/etc/httpd/conf/httd.conf
tags: inatconf ***************
notify: restart httpd service
- name: start httpd service
service: name-hhtpd state=started
handlers:
- name: restart httpd service
service: name=httpd state=restarted
检查语法
#ansible-playbookp--syntax-check web.yml
此处可以查看到该yml脚本有一个标签,影响着websrvs组
测试运行
# ansible-playbook -C -t instconf web.yml
正式运行一下,指定以instconf的标签运行,所以此处不会显示器其他多余的信息,包括安装httpd包和启动httpd服务
# ansible-playbook -t instconf web.yml
验证该结果
# ansible web -a "ss -tnl"
===============================================
Variables:变量
类型:
内建:
(1) facts
自定义:
(1) 命令行传递;
-e VAR=VALUE
(2) 在hosts Inventory中为每个主机定义专用变量值;
(a) 向不同的主机传递不同的变量 ;
IP/HOSTNAME variable_name=value
(b) 向组内的所有主机传递相同的变量 ;
[groupname:vars]
variable_name=value
(3) 在playbook中定义
vars:
– var_name: value
– var_name: value
(4) Inventory还可以使用参数:
用于定义ansible远程连接目标主机时使用的属性,而非传递给playbook的变量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
…
(5) 在角色调用时传递
roles:
– { role: ROLE_NAME, var: value, …}
变量调用:
{{ var_name }}
写了一下午,未完待续。。。。。。