Ansible
1.什么是ansible?
ansible是基于ssh架构的自动化运维工具,由python语言实现,通过ansible可以远程批量部署等。
2.部署前提
控制端需要安装ansible,被控制端要开启ssh服务,并允许远程登录,被管理主机需要安装python.
3.配置文件
3.1主配置文件ansible.cfg及匹配规则
1.首先检测ANSIBLE_CONFIG变量定义的配置文件
2.其次当前路径下ansible.cfg
3.然后家目录下ansible.cfg
4.最后/etc/ansible/ansible.cfg
3.2主机清单
需要被控制主机列表: hosts文件
vim /etc/ansible/hosts
[test] # 主机群名
192.168.88.31 # 远程ip
192.168.88.32
[test1]
192.168.88.55
4.ansible-hoc 和ansible-doc
ansible-hoc : 远程命令行控制
ansible-hoc命令行的格式:
ansible-doc的常用参数:
ansible + 主机 + 模块 + 参数
--version : 显示版本
-m : 指定模块
-k : 使用密码验证,要输入密码。默认是密钥验证,所以需要提前对被控机进行免密验证
ansible-doc: 查看帮助文档
ansible-doc 模块
eg:
ansible-doc shell
5.ansible常用模块
5.1 command模块
在远程主机执行命令,默认模块,可忽略-m选项 。Command模块 不支持特殊符号,| > * ,也不支持变量
[root@localhost etc]# ansible all -m command -a "ls"
client_32 | CHANGED | rc=0 >>
anaconda-ks.cfg
client_31 | CHANGED | rc=0 >>
anaconda-ks.cfg
mysql.password
sh
[root@localhost etc]# ansible all -a "ls"
client_31 | CHANGED | rc=0 >>
anaconda-ks.cfg
mysql.password
sh
client_32 | CHANGED | rc=0 >>
anaconda-ks.cfg
5.2 shell模块
Shell命令是通过/bin/sh进行执行的,command命令没有shell的环境变量,因此不支持特殊符号或变量的操作。
chdir:指定执行shell的目录
[root@localhost ~]# ansible all -m shell -a "getenforce"
client_32 | CHANGED | rc=0 >>
Enforcing
client_31 | CHANGED | rc=0 >>
Enforcing
# chdir:指定执行shell的目录
[root@localhost ~]# ansible all -m shell -a "chdir='/tmp' ls -a "
client_32 | CHANGED | rc=0 >>
.
..
ansible_ansible.legacy.command_payload_u3phm_ux
.font-unix
.ICE-unix
.X11-unix
.XIM-unix
client_31 | CHANGED | rc=0 >>
.
..
ansible_ansible.legacy.command_payload_e7vxhgpd
.font-unix
.ICE-unix
.X11-unix
.XIM-unix
5.3 copy模块
从ansible服务器主控端复制文件到远程主机 。
src: 本地源文件地址。
dest: 指定远程目标地址。
mode: 设置权限。
backup: 备份源文件。
content:代替src,填入目标地址,使用content时,dest只能是文件。
[root@localhost ~]# ansible test_31 -m copy -a "src=/tmp/11.txt dest=/tmp/11.txt owner=root group=root mode=777 "
client_31 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"checksum": "70ec68aa8285ad385fbd67c6a59d4612c0d2b086",
"dest": "/tmp/11.txt",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"path": "/tmp/11.txt",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 7,
"state": "file",
"uid": 0
}
5.4 fetch
将远程文件复制到本地,不支持目录复制到本地,如果需要复制目录,可以先打包再fetch.复制会将src目录复制下来以远程主机命名存进dest下。
[root@localhost ~]# ansible test_31 -m fetch -a "src=/tmp/11.txt dest=/tmp/11.txt owner=root group=dc mode=777 "
client_31 | CHANGED => {
"changed": true,
"checksum": "70ec68aa8285ad385fbd67c6a59d4612c0d2b086",
"dest": "/tmp/11.txt/client_31/tmp/11.txt",
"md5sum": "c6981c3084d896fd207df3fde1cb5cf3",
"remote_checksum": "70ec68aa8285ad385fbd67c6a59d4612c0d2b086",
"remote_md5sum": null
}
[root@localhost ~]# cd /tmp/11.txt/client_31
[root@localhost client_31]# ll
total 0
drwxr-xr-x 2 root root 20 Oct 8 13:45 tmp
[root@localhost client_31]# cd ./tmp/
[root@localhost tmp]# ll
total 4
-rwxr-xr-x 1 root root 7 Oct 8 13:45 11.txt
[root@localhost tmp]# ll
# 当源地址是目录
[root@localhost tmp]# mkdir /fetch_test
[root@localhost tmp]# cd /fetch_test/
[root@localhost fetch_test]# ll
total 0
# 远程打包
[root@localhost fetch_test]# ansible test_31 -m shell -a "tar -czvf /tmp/31.tgz /tmp"
client_31 | CHANGED | rc=0 >>
/tmp/
/tmp/.X11-unix/
/tmp/.ICE-unix/
/tmp/.XIM-unix/
/tmp/.font-unix/
/tmp/11.txt
/tmp/ansible_ansible.legacy.command_payload_8ptat5lq/
/tmp/ansible_ansible.legacy.command_payload_8ptat5lq/ansible_ansible.legacy.command_payload.zip
/tmp/31.tgztar: Removing leading `/' from member names
# fetch到本地
[root@localhost fetch_test]# ansible test_31 -m fetch -a "src=/tmp/31.tgz dest=/fetch_test"
client_31 | CHANGED => {
"changed": true,
"checksum": "7d84c1a745f95464b8676ad510493efe2a1f64b0",
"dest": "/fetch_test/client_31/tmp/31.tgz",
"md5sum": "9794d76ba8056e6ce20bccb33ec7069f",
"remote_checksum": "7d84c1a745f95464b8676ad510493efe2a1f64b0",
"remote_md5sum": null
}
# 查看是否成功
[root@localhost fetch_test]# ll
total 0
drwxr-xr-x 3 root root 17 Oct 8 13:52 client_31
5.5 file
对远程文件/目录操作,创建,删除等操作。
参数:
path: 文件路径/目录
owner: 文件/目录的属主
group: 文件/目录的属组
state:
touch: 创建文件
directory: 创建目录
absent: 删除
link: 软链接
mode: 设置权限
recurse: 递归修改,于state=directory结合使用
# 创建目录
[root@localhost ~]# ansible test_31 -m file -a "path=/ansible state=directory owner=1"
client_31 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "bin",
"path": "/ansible",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 1
}
# 创建文件
[root@localhost ~]# ansible test_31 -m file -a "path=/ansible/1 state=touch owner=1"
client_31 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/ansible/1",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "bin",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 0,
"state": "file",
"uid": 1
}
# 创建软连接
[root@localhost ~]# ansible test_31 -m file -a "src=/ansible/1 dest=/ansible/1-link state=link"
client_31 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/ansible/1-link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 10,
"src": "/ansible/1",
"state": "link",
"uid": 0
}
# 删除文件
[root@localhost ~]# ansible test_31 -m file -a "path=/ansible/1 state=absent owner=1"
client_31 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"path": "/ansible/1",
"state": "absent"
}
5.6 uncharive
unarchive:解包解压缩,有两种用法:
1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes。
2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no 。
# copy=yes,默认为yes,将本地压缩包解压到远程
[root@localhost zip]# ansible test_31 -m unarchive -a "src=/opt/zip/filebeat-6.5.4-linux-x86_64.tar.gz dest=/opt/test copy=yes"
# copy=no,将远程压缩包解压到远程
[root@localhost zip]# ansible test_31 -m unarchive -a "src=/opt/zip/kafka_2.13-2.6.0.tgz dest=/opt/test copy=no"
5.7 archive
将远程目录文件打包
path: "要压缩的文件或目录的路径"
dest: "归档文件存放的路径" format: "压缩格式,如 gz, bz2, xz, zip 等"
remove: yes/no, 压缩并删除源文件
ansible test_31 -m archive -a "path=/opt/test/kafka_2.13-2.6.0 dest=/opt/test/kafka.tgz format=gz"
# 将远程主机文件压缩到远程,而不是本地
5.8 yum
远程安装服务
name: 指定服务名称
state: 执行动作。安装installed,present。卸载remove,absent。latest更新最新版
ansible test_31 -m yum -a "name=httpd state=installed"
ansible test_31 -m yum -a "name=httpd state=latest"
ansible test_31 -m yum -a "name=httpd state=removed"
5.9 service
管理远程服务状态。
name: 指定服务名称
state: 执行状态。started开启服务,stoped停止服务,reload重新加载。
enabled: yes 开机自启 ,no开机不自启。
ansible test_31 -m service -a "name=httpd state=stoped"
ansible test_31 -m service -a "name=httpd state=started enabled=yes"
ansible test_31 -m service -a "name=httpd state=reloaded enabled=yes"
6.PlayBook
ansible命令直接调用yml语言写好的playbook,playbook由多条play组成,每条play 都有一个任务(task)相对应的操作,然后调用模块modules,应用在主机清单上,通过 ssh远程连接,从而控制远程主机或者网络设备。
6.1 认识yaml语言
yaml语言的特性:
1.可读性好
2.脚本易于实现
yaml语法基础:
1.在文件的第一行先要三个连续的-,表示开头,三个点表示结束(可省略)。
2.用#表示注释
3.缩进和python必须一样
4.缩进时,tab和空格混用
5.区分大小写
6.文件扩展名通常为yml或者yaml
yaml的数据类型:
字典:字典由多个key与value构成,key和value之间用 :分隔,所有k/v可以放在一行,或 者每个 k/v 分别放在不同行
# An employee record
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# An employee record
{name: "Example Developer”, job: "Developer”, skill: "Elite”}
列表: 列表由多个元素组成,每个元素放在不同行,且元素前均使用"-”打头,或者将所有 元素用 [ ] 括起来放在同一行
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
[Apple,Orange,Strawberry,Mango]
linux的常见数据格式:
xml: 可拓展标记语言,用于数据交换和配置。
json:标记对象法,不支持注释,用于数据交换和配置。
yaml: 非标记语言,用于配置,大小写敏感,不支持tab。
6.2 PlayBook语法格式
1.采用yaml格式编写
2.playbook由一个或者多个play组成c
3.ansible-playbook命令运行剧本
4.每个play中包括hosts,tasks,variables,roles,handlers等元素
5. : 之后必须有空格
---
- hosts: test_31
tasks:
- name: test ping
ping:
- hosts: test
tasks:
- name: test shell
shell: touch /tmp/`pwd`.txt
- hosts: test, test_31
tasks:
- name: test ping_both
ping:
# 注意缩进和冒号之后必须有空格
6.3 playbook应用案例
-
编写ansible-playbook文件为系统创建用户,配置用户uid,group和密码。
--- - hosts: test_31 tasks: - name: add user user: name: dc uid: 1024 group: 0 - name: change password shell: echo "123456" | passwd dc --stdin
-
安装httpd和vim
--- - hosts: test_31 tasks: - name: install_httpd,vim yum: name: - httpd - vim state: present
6.4 定义变量
1. inventory变量
在主机清单配置文件定义变量,{{ }}引用变量,当{{}}开头是要用引号引起来。在主机清单中的普通变量优先级高于公共变量
vim /etc/ansible/hosts
[test_31]
192.168.88.31 node="node1" # 普通变量
test.168.88.32
[test:vars]
node = "hello" # 公共变量
vim var1.yml
---
- hosts: test
tasks:
- name: add_user
user:
name: "{{node}}"
state: present
2.setup模块收集的变量
ansible 的 setup facts 远程主机的所有变量都可直接调用。 Facts:是由正在通信的远程目标主机发回的信息,这些信息被保存在ansible变量 中。 setup模块可以实现系统中很多系统信息的显示,可以返回每个主机的系统信息包括: 版本、主机名、cpu、内存。
ansible test_31 -m setup # 收集的系统变量,可以直接在{{}}应用
ansible all -m setup -a 'filter="ansible_nodename"'
查询主机名
ansible all -m setup -a 'filter="ansible_memtotal_mb"' 查询主机内存
大小
ansible all -m setup -a
'filter="ansible_distribution_major_version"' 查询系统版本
ansible all -m setup -a 'filter="ansible_processor_vcpus"' 查询主机
cpu个数
#var.yml
---
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: create log file
file: name=/data/{{ ansible_nodename }}.log state=touch
owner=wang mode=600
#在playbook调用,不要用ansible命令调用
3.单独的保存变量的文件
可以在一个独立的playbook文件中定义变量,引用变量文件中的变量,比playbook中定义的变量优化级高
[root@192-168-10-22 ansible]# cat vars.yml
var1: vsftpd #注意空格
var2: httpd #注意空格
[root@192-168-10-22 ansible]# cat test.yml
---
- hosts: web
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package
yum: name={{ var1 }}
- name: create file4
file: name=/data/{{ var2 }}.log state=touch
4.playbook定义的变量vars
vim var1.yml
---
- hosts: test
vars:
- node: charlotte
- node1: dc
tasks:
- name: add_user
user:
name: "{{node}}"
state: present
- name: add_user
user:
name: "{{node1}}"
state:present
5.命令行 -e
ansible-playbook -e "node=charlotte" test.yml
vim var1.yml
---
- hosts: test
tasks:
- name: add_user
user:
name: "{{node}}"
state: present
优先级:
命令行>playbook定义的>主机清单
7.notify和handler使用
---
- hosts: test
vars:
name1: httpd
name2: ansible
tasks:
- name: install_epel
yum:
name: epel-release
state: present
- name: install_httpd
yum:
name:
- "{{name1}}"
- "{{name2}}"
state: installed
- name: start_httpd
service:
name: "{{name1}}"
state: started
enabled: yes
- name: change_config
copy:
src: /ansible/http.conf
dest: /etc/httpd/conf.d/http.conf
notify: restart httpd
handlers:
- name: restart httpd
systemd:
name: "{{name1}}"
state: restarted