Ansible
一.概述
由于互联网的快速发展导致产品更新换代速度逐渐加快,运维人员每天都要进行大量的维护操作,任按照旧传统方式进行维护使得工作效率低下。这是,部署自动化运维就可以尽可能安全,高效地完成这些工作。
一般,自动化运维工具划分为两类:一类是需要使用代理工具的,也就是基于专用的Agent程序完成管理工作,如:Puppet,Func,Zabbix等;另外一类是不需要配置代理工具的,可以直接基于SSH原理来完成管理功能,如:Ansible,Fabric等
1.Puppet
Puppet基于Rubby开发,支持Linux,Unix,Windows平台,可以针对用户,系统服务,配置文件,软件包,等进行管理,有较强的扩展性,但远程执行命令相对较弱。
2.SaltStack
SaltStack基于python开发,允许管理员对多个操作系统创建统一的管理系统,比Puppet更轻量级。
3.Ansible
Ansible基于python开发,集合了众多优秀运维工具的优点,实现了批量运行命令,部署程序,配置系统等功。默认通过SSH协议进行远程命令执行或下发配置,无需配置任何客户端代理软件,从而使得自动化环境部署变得更加简单。可同时支持多台主机并行管理,是的管理主机更加便捷。
工具 | 开发语言 | 结构 | 配置文件格式 | 运行任务 |
Ansible | pthon | 无 | YAML | 执行命令行 |
SaltStack | Python | C/S | YAML | 支持命令行 |
Puppet | Ruby | C/S | Ruby语法格式 | 通过模块实现 |
二.Ansible核心组件
ansible可以看作是一种基于模块进行工作的框架结构,批量部署能力就是由Ansible所允许的模块实现的。ansible是基于“模块”完成各种“任务”的。其基本框架架构为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cJ09hcGj-1599490966056)(file:///
)]
Ansible基本框架是由六个部分构成的:
Ansible core核心引擎
Host inventory:用来定义Ansible所管理的主机,默认是在Ansible的hosts配置文件中定义被管理主机,同时也支持自定义动态主机清单和指定其他配置文件的位置
Connection plugins链接插件:负责和被管理主机实现通信。除支持使用ssh链接被管理主机外,Ansible还支持其他的链接方式,所以需要有连接插件将各个主机用连接插件连接到Ansible
Playbooks(yam1,yam2)剧本:用来集中定义Ansible任务的配置文件,即将多个任务定义在一个剧本中由Ansible自动执行,可以由控制主机针对多台被管理主机同时运行多个任务
Core modules核心模块:是Ansible自带的模块,使用这些模块将资源分发到被管理主机,使其执行特定任务或匹配特定的状态。
Custom modules自定义模块:用于完成模块功能的补充,可借助相关插件完成记录日志,发送邮件的功能。
三.安装部署Ansible服务
Ansible自动化运维环境由控制主机与被管理主机组成,由于Ansible是基于SSH协议进行通信的,所以控制主机安装Ansible软件后不需要重启或运行任何程序,被管理主机也不需要安装和运行任何代理程序。
电脑配置不行,就只开了两台centos 7.4主机
角色 | 主机名 | IP地址 | |
控制主机 | pc1 | 192.168.133.138 | |
被管理主机 | pc2 | 192.168.133.141 | |
1.安装Ansible
[root@localhost ~]# yum install epel-release -y #安装epel源
[root@localhost ~]# yum install ansible -y #安装ansible
[root@localhost ~]# ansible --version #查看版本
ansible 2.9.10
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, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
2.配置主机清单
Ansible通过读取默认主机清单/etc/ansible/hosts文件,修改主机与组配置后,可同时链接到多个被管理主机上执行任务。比如定义一个webserver组,包含pc2主机,ip:192.168.131.141
[root@localhost ansible]# cat hosts | grep -v -e "#"
i This is the default ansible 'hosts' file.
[webserver]
192.168.131.141
3.设置SSH无密码登录
.ssh 是记录密码信息的文件夹,如果没有登录过root的话,就没有 .ssh 文件夹,因此登录 localhost ,并输入密码就会生成了
ssh localhost
[root@localhost ~]# ssh-keygen -t rsa -f /root/.ssh/id_rsa -N ''
Generating public/private rsa key pair.
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:
SHA256:VBFxrWSiaFFfDZVx7JGFnNcAyX3/7SVZrsLBrWYrXTA root@localhost.localdomain
The key's randomart image is:
+---[RSA 2048]----+
| .. ===X+B*|
| . o.o= O+=|
| o...+ . +o|
| o.. E +|
| . S . + +o|
| o = =|
| o + +.|
| . B . .|
| +.o |
+----[SHA256]-----+
[root@localhost ~]# ssh-copy-id root@192.168.133.141
四.Ansible命令应用基础
Ansible可以使用命令行方式进行自动化管理,基础语法:
ansible < host-pattern > [-m module_name] [-a args]
< host-pattern > 对那些主机生效
[-m module_name] 要使用的模块
[-a args] 模块特有的参数
Ansible的命令行管理工具都是由一系列模块,参数所支持的,-h或者–help得到帮助。如使用ansible-doc工具可以通过ansible-doc -h或ansible-doc --help查看帮助信息
ansible自带了很多模块,能够处理执行ansible的各种管理任务。
了解核心模块:
1.command模块
Ansible管理工具使用-m选项来指定使用模块,默认使用Command模块,即-m选项省略时会运行此模块,用于在被管理主机上运行命令
如在被管理主机上执行date命令,显示被管理主机的时间。
[root@localhost ~]# ansible webserver -m command -a 'date'
192.168.133.141 | CHANGED | rc=0 >>
Mon Sep 7 19:40:10 CST 2020
[root@localhost ~]# ansible 192.168.133.141 -m command -a 'date'
192.168.133.141 | CHANGED | rc=0 >>
Mon Sep 7 19:40:48 CST 2020
[root@localhost ~]# ansible all -m command -a 'date'
192.168.133.141 | CHANGED | rc=0 >>
Mon Sep 7 19:41:21 CST 2020
注意:如果省略-m选项,默认运行command模块
[root@localhost ~]# ansible all -a 'tail -1 /etc/passwd'
192.168.133.141 | CHANGED | rc=0 >>
cat7: x:1000:1000:cat7:/home/cat7:/bin/bash
2.cron模块
Ansible中的cron模块用于定义任务计划。其中有两种状态(statr):present表示添加(省略状态时默认使用) absent表示移除
[root@localhost ~]# ansible webserver -m cron -a 'minute="*/1" job="/bin/echo/hello" name="test cron job"'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"test cron job"
]
}
[root@localhost ~]# ansible webserver -a 'crontab -l'
192.168.133.141 | CHANGED | rc=0 >>
#Ansible: test cron job
*/1 * * * * /bin/echo/hello
[root@localhost ~]# ansible webserver -m cron -a 'minute="*/1" job="/bin/echo/hello" name="test cron job state="absent""'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"test cron job",
"test cron job state=\"absent\""
]
}
[root@localhost ~]# ansible webserver -a 'crontab -l'
192.168.133.141 | CHANGED | rc=0 >>
#Ansible: test cron job
*/1 * * * * /bin/echo/hello
#Ansible: test cron job state="absent"
*/1 * * * * /bin/echo/hello
3.user模块
user模块用于创建用户和更改,删除已存在的用户。其中name选项用来指定创建的用户名称
[root@localhost ~]# ansible webserver -m user -a 'name="cat77"'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1001,
"home": "/home/cat77",
"name": "cat77",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
[root@localhost ~]#
[root@localhost ~]# ansible webserver -m user -a 'name="cat77" state=absent'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "cat77",
"remove": false,
"state": "absent"
}
[root@localhost ~]# ansible webserver -a 'tail -1 /etc/passwd'
192.168.133.141 | CHANGED | rc=0 >>
cat7: x:1000:1000:cat7:/home/cat7:/bin/bash
4.group模块
group模块用于对用户组进行管理
[root@localhost ~]# ansible webserver -m group -a 'name=wgroup gid=306 system=yes'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 306,
"name": "wgroup",
"state": "present",
"system": true
}
[root@localhost ~]# ansible webserver -a 'tail -1 /etc/group'
192.168.133.141 | CHANGED | rc=0 >>
wgroup:x:306:
[root@localhost ~]# ansible webserver -m user -a 'name=stu2 uid=1001 system=yes group=wgroup'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 306,
"home": "/home/stu2",
"name": "stu2",
"shell": "/bin/bash",
"state": "present",
"system": true,
"uid": 1001
}
[root@localhost ~]# ansible webserver -a 'groups stu2'
192.168.133.141 | CHANGED | rc=0 >>
stu2 : wgroup
[root@localhost ~]# ansible webserver -m group -a 'name=wgroup gid=305 system=no state=absent'
192.168.133.141 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"msg": "groupdel: cannot remove the primary group of user 'stu2'\n",
"name": "wgroup"
}
5.copy模块
copy用于实现文件复制和批量下发文件。其中使用src来定义本地源文件路径,使用dest定义被管理主机文件路径,使用content则是通过指定信息内容来生成目标文件
将服务机上内容复制到pc2上并赋予不同文件不同权限
[root@localhost ~]# ansible webserver -m copy -a 'src=/etc/hosts dest=/etc/hosts owner=root mode=640'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "57ea0c22bb38854900c9e6c3fc6873fd2147d3f7",
"dest": "/etc/hosts",
"gid": 0,
"group": "root",
"md5sum": "e206d015008b3c787b8fb3c00077a5d5",
"mode": "0640",
"owner": "root",
"secontext": "system_u:object_r:net_conf_t:s0",
"size": 169,
"src": "/root/.ansible/tmp/ansible-tmp-1599480168.99-56681-213686162287559/source",
"state": "file",
"uid": 0
}
pc2:
[root@localhost ~]# ls -l /etc/hosts
-rw-r-----. 1 root root 158 Jun 7 2013 /etc/hosts
[root@localhost ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
testtest
6.File模块
使用file模块来这是文件属性,其中path指定文件路径,使用src定义源文件路径,使用name或dest来替换创建文件的符号链接
eg 1:
[root@localhost ~]# ansible webserver -m file -a 'owner=stu2 group=stu2 mode=544 path=/etc/hosts'
192.168.133.141 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"gid": 0,
"group": "root",
"mode": "0640",
"msg": "chgrp failed: failed to look up group stu2",
"owner": "stu2",
"path": "/etc/hosts",
"secontext": "system_u:object_r:net_conf_t:s0",
"size": 169,
"state": "file",
"uid": 1001
}
-rw-r-----. 1 stu2 root 169 Sep 7 20:02 /etc/hosts
[root@localhost ~]#
eg:2
nk src=/etc/fstab state=link'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/mnt/fstab.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:mnt_t:s0",
"size": 10,
"src": "/etc/fstab",
"state": "link",
"uid": 0
}
[root@localhost ~]# ansible webserver -a 'ls -l /mnt'
192.168.133.141 | CHANGED | rc=0 >>
total 0
lrwxrwxrwx. 1 root root 10 Sep 7 20:12 fstab.link -> /etc/fstab
7.ping模块
ping模块用于检测指定主机的连通性
[root@localhost ~]# ansible all -m ping
192.168.133.141 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
8.service模块
Ansible中使用service模块来控制管理服务的运行状态。其中,enabled表示开机自启,取值为true或false;使用name定义服务名称;使用state指定服务状态,取值分别为started,stopped,restarted。
[root@localhost ~]# ansible all -a 'systemctl status sshd'
192.168.133.141 | CHANGED | rc=0 >>
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; ve
ndor preset: enabled)
Active: active (running) since Mon 2020-09-07 11:26:20 CST; 8h ag
o
[root@localhost ~]# ansible all -m service -a'enabled=true name=sshd state=started'
192.168.133.141 | SUCCESS => {
9.shell模块
shell模块可以在被管理主机上运行命令,并支持想管道符等功能的复杂命令
[root@localhost ~]# ansible webserver -m user -a 'name=stu3'
192.168.133.141 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
[root@localhost ~]# ansible webserver -m shell -a 'echo 123456 | passwd --stdin stu3'
192.168.133.141 | CHANGED | rc=0 >>
Changing password for user stu3.
passwd: all authentication tokens updated successfully.
10.script模块
script模块可以将本地脚本复制到被管理追上进行运行,需要注意,使用相对路径来指定脚本。
[root@localhost ~]# cat test.sh
#!/bin/bash
echo "hello ansible from script" > /mnt/script.ansible
[root@localhost ~]# ansible all -m script -a 'test.sh'
192.168.133.141 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.133.141 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.133.141 closed."
],
"stdout": "",
"stdout_lines": []
}
pc2:
[root@localhost ~]# cat /mnt/script.ansible
hello ansible from script
11.yum模块
yum模块复杂在被管理主机上安装与卸载软件包,但是需要在每个节点配置自己的yum仓库。使用name指定要安装的软件包,还需要带上软件包的版本号,否则安装最新的软件包;使用state指定安装软件的状态,present,latest用来表示安装,absent表示卸载
[root@localhost ~]# ansible all -m yum -a 'name=httpd'
192.168.133.141 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"httpd-2.4.6-67.el7.centos.x86_64 providing httpd is already installed"
]
}
[root@localhost ~]# ansible all -a 'rpm -qa httpd'
192.168.133.141 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
[root@localhost ~]# ansible all -m yum -a 'name=httpd state=absent'
12.setup模块
setup模块收集 查看被管理主机的facts(facts是ansible采集被管理主机信息的一个功能)。每个被管理主机在接受并运行管理之前,都会将自己的相关信息,(操作系统版本 ip地址等)发送给控制主机。
[root@localhost ~]# ansible all -m setup
五.Ansible中的Inventory(主机清单)
Ansible为了更加便捷地管理主机,在主机清单中将被管理主机进行分组命名,默认的主机清单为/etc/ansible/hosts文件。主机清单可以设置为多个,也可以通过Dynamic Inventory动态生成。
Inventory文件以括号的字符表示为组名,将主机分组管理,也可以将同一主机同时划分到多个不同的组中。如果被管理主机使用非默认的ssh端口,还可以在主机名之后用冒号加端口的方式进行标明。
[webserver] [webserver] [webserver]
192.168.10.1 web1.example.com web[01:05].example.com
192.168.10.2 web2.example.com
Inventory重要概念
1.主机变量
可以在定义主机时添加主机变量,以便在后续的Playbook中使用,如:
www1.zlt.com http_port=80 maxRequestsChild=808
www1.zlt.com http_port=809 maxRequestsChild=909
2.组变量
组变量是指给指定主机设置可以在Playbook中直接使用的变量,如:[server-vars]
ntp_server=ntp.example.org
nfs_server=nfs.example.org
3.组嵌套
在Inventory中的组还可以嵌套其他的组,也可以向组中的主机指定变量。不过这些变量只能在ansible-playbook工具中使用,直接使用Ansible工具并不支持,
[apache]
httpd1.example.org
httpd2.example.org
[nginx]
nginx1.example.org
nginx2.example.org
[webservers:children]
apache
nginx
4.Inventory参数
Ansible基于ssh连接,Inventory中指定被管理主机时,还可以通过参数指定交互方式,参数如下:
ansible_ssh_host:定义hosts ssh地址
ansible_ssh_port:定义hosts ssh端口
ansible_ssh_user:定义hosts ssh认证用户
ansible_ssh_pass:定义hosts ssh认证密码,明文密码不安全
ansible_sudo:定义hosts sudo用户
ansible_sudo_pass:定义hosts sudo密码
ansible_sudo_exe:定义host sudo路径
ansible_connection:定义hosts连接方式,如ssh,local,paramiko
ansible_ssh_private_key_file:定义ssh连接的公钥文件
ansible_shell_type:定义hosts shell类型,默认是sh
ansible_python_interpreter:定义hosts 任务执行python路径
Ansible\_\*\_interpreter:定义hosts其他语言解析路径
如果被配置ssh密钥认证,可以如此对被管理主机进行认证:
#vim /etc/ansible/hosts
[webserver]
192.168.10.1 ansible_ssh_user=root ansible_ssh_pass=123456
六.YAML与playbook介绍
YAML是一种用来表达资料序列的格式,由于参考了多种其他语言,所以具有很高的可计性,YAML是YAML Ain‘t Markup Language的缩写,即YAML不是XML。YAML的意思是 Yet Another Markup Language(仍是一种标记语言),其特性:
1.具有良好的可读性
2.表达能力强
3.和脚本语言的交互性好
4.有一个一致的信息模型
5.可以基于流来处理
Playbook是由一个或多个play组成的列表,主要功能将tas定义好的角色归并为一组进行统一管理,也就是通过task调用Ansible的模板将多个play组织在一个Play中运行
playbook 剧本
play (找谁)
task (干什么)
playbook是由yml语法书写结构清晰,可读性强,所以必须掌握yml基础语法
语法 描述
缩进 yaml使用固定的缩进风格表示层级结构,每个缩进由两个空格组成,不 能使用tab
冒号 以冒号结尾的除外,其他所有冒号后面必须有空格
短横线 表示列表项,使用一个短横线加一个空格。多个项使用同样缩进级别作 为同一列表
eg1:使用ansible安装并配置http服务
[root@localhost ~]# cat http.yaml
- hosts: webserver
tasks:
- name: yum install httpd server
yum: name=httpd state=present - name: configure httpd website
copy: src=./index.html dest=/var/www/index.html owner=apache group=apache mode=644 - name: service httpd server
service: name=httpd state=started enabled=yes - name: service firewalld server
service: name=firewalld state=started - name: configure firewalld server
firewalld: zone=public service=http permanent=yes immediate=yes state=enabled
[root@localhost ~]# ansible-playbook --syntax http.yaml
playbook: http.yaml
测试安装
安装