1. Ansible详解 ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。 ansible是基于 paramiko 开发的,并且基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远 程主机通讯的。ansible目前已经已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手容易,学习简单。是每位运维工程师必须掌握的技能之一。
ansible特点
部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
默认使用SSH协议对设备进行管理;
有大量常规运维操作模块,可实现日常绝大部分操作;
配置简单、功能强大、扩展性强;
支持API及自定义模块,可通过Python轻松扩展;
通过Playbooks来定制强大的配置、状态管理;
轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。
1.1. ansible的主要模块
Ansible
:Ansible核心程序。HostInventory
:记录由Ansible管理的主机信息,包括端口、密码、ip等。Playbooks
:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。CoreModules
:核心模块 ,主要操作是通过调用核心模块来完成管理任务。CustomModules
:自定义模块,完成核心模块无法完成的功能,支持多种语言。ConnectionPlugins
:连接插件,Ansible和Host通信使用
1.2. ansible安装 ansible安装常用几种方式,yum安装
,apt
和pip程序安装
。
1.2.1. yum安装 yum 安装是我们很熟悉的安装方式了。我们需要先安装一个epel-release
包,然后再安装我们的 ansible 即可。
1 2 yum install epel-release -y yum install ansible –y
1.2.2. pip安装 首先,我们需要安装一个python-pip
包,安装完成以后,则直接使用pip
命令来安装我们的包,具体操作过程如下:
1 2 yum install python-pip pip install ansible
1.2.3. apt(Ubuntu)安装 配置PPA及安装ansible,执行如下命令:
1 2 3 4 $ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install ansible
注意:在早期Ubuntu发行版中, “software-properties-common” 名为 “python-software-properties”.
1.3. ansible 配置公私钥 上面我们已经提到过 ansible 是基于 ssh 协议实现的,所以其配置公私钥的方式与 ssh 协议的方式相同,具体操作步骤如下:
1 2 3 4 5 6 7 # 1.生成私钥 [root@server ~]# ssh-keygen # 2.向主机分发私钥 [root@mgmt2 ~]# ssh-copy-id root@192.168.101.201 [root@mgmt2 ~]# ssh-copy-id root@192.168.101.202 [root@mgmt2 ~]# ssh-copy-id root@192.168.101.203
这样就实现了无密码登陆
通过for循环批量配置ssh密钥
1 2 3 4 5 6 7 8 [root@mgmt2 ~] [root@mgmt2 ~] do ssh-copy-id $i done
注意:如果出现如下报错
1 -bash: ssh-copy-id: command not found
我们需要安装一个包
1 yum -y install openssh-clientsansible
再次执行即可
1.4. ansible配置文件
1 2 3 4 5 配置文件目录:/etc/ansible/ 执行文件目录:/usr/bin/ Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/ Help文档目录:/usr/share/doc/ansible-X.X.X/ Man文档目录:/usr/share/man/man1/
ansible与我们其他的服务在这一点上有很大不同,这里的配置文件查找是从多个地方找的,顺序如下:
1 2 3 4 1. 首先检测ANSIBLE_CONFIG变量定义的配置文件 2. 其次检查当前目录下的./ansible.cfg文件 3. 再次检查当前用户家目录下 ~/ansible.cfg 文件 4. 最后检查 /etc/ansible/ansible.cfg 文件
ansible 的配置文件为/etc/ansible/ansible.cfg
,ansible 有许多参数,下面我们列出一些常见的参数:
1 2 3 4 5 6 7 8 inventory = /etc/ansible/hosts library = /usr/share/ansible forks = 5 sudo_user = root remote_port = 22 host_key_checking = False timeout = 60 log_path = /var/log /ansible.log
在配置文件中,我们提到了资源清单,这个清单就是我们的主机清单,里面保存的是一些 ansible 需要连接管理的主机列表。我们可以来看看他的定义方式:
vim /etc/ansible/hosts
1 2 3 4 5 6 7 8 9 10 1、 直接指明主机地址或主机名: 2、 定义一个主机组[组名]把地址或主机名加进去 [k8s] 192.168.101.201 192.168.101.202 192.168.101.203
1.5. ansible常用命令
/usr/bin/ansible
Ansibe AD-Hoc 临时命令执行工具,常用于临时命令的执行/usr/bin/ansible-doc
Ansible 模块功能查看工具/usr/bin/ansible-galaxy
下载/上传优秀代码或Roles模块 的官网平台,基于网络的/usr/bin/ansible-playbook
Ansible 定制自动化的任务集编排工具/usr/bin/ansible-pull
Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)/usr/bin/ansible-vault
Ansible 文件加密工具/usr/bin/ansible-console
Ansible基于Linux Consoble界面可与用户交互的命令执行工具
其中,我们比较常用的是/usr/bin/ansible
和/usr/bin/ansible-playbook
。
ansible-doc 命令常用于获取模块信息及其使用帮助,一般用法如下:
1 2 ansible-doc -l ansible-doc -s MOD_NAME
我们也可以查看一下ansible-doc的全部用法:
1 2 3 4 5 6 7 8 9 10 11 12 [root@master ~] Usage: ansible-doc [options] [module...] Options: -h, --help show this help message and exit -l, --list List available modules -M MODULE_PATH, --module-path=MODULE_PATH specify path(s) to module library (default=None) -s, --snippet Show playbook snippet for specified module(s) -v, --verbose verbose mode (-vvv for more, -vvvv to enable connection debugging) --version show program's version number and exit
我们可以来看一下,以mysql相关的为例:
1 2 3 4 5 6 [root@master ~] mysql_db Add or remove MySQL databases from a remote... mysql_replication Manage MySQL replication mysql_user Adds or removes a user from a MySQL databas... mysql_variables Manage MySQL global variables [root@master ~]
命令的具体格式如下:
1 ansible <host-pattern> [-f forks] [-m module_name] [-a args]
也可以通过ansible -h
来查看帮助,下面我们列出一些比较常用的选项,并解释其含义:
-a MODULE_ARGS
#模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等-k
,--ask-pass
#ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证--ask-su-pass
#ask for su password。su切换密码-K
,--ask-sudo-pass
#ask for sudo password。提示密码使用sudo,sudo表示提权操作--ask-vault-pass
#ask for vault password。假设我们设定了加密的密码,则用该选项进行访问-B SECONDS
#后台运行超时时间-C
#模拟运行环境并进行预运行,可以进行查错测试-c CONNECTION
#连接类型使用-f FORKS
#并行任务数,默认为5-i INVENTORY
#指定主机清单的路径,默认为/etc/ansible/hosts
--list-hosts
#查看有哪些主机组-m MODULE_NAME
#执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数-o
#压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用-S
#用 su 命令-R SU_USER
#指定 su 的用户,默认为 root 用户-s
#用 sudo 命令-U SUDO_USER
#指定 sudo 到哪个用户,默认为 root 用户-T TIMEOUT
#指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改-u REMOTE_USER
#远程用户,默认为 root 用户-v
#查看详细信息,同时支持-vvv
,-vvvv
可查看更详细信息
1.5.1. ansible主机清单文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@mgmt1 ~] [test ] node1 [proxy] node2 [web] node[3:4] [database] node5 [cluster:children] web database
测试Ansible环境与配置是否正常
1 2 3 4 5 6 [root@mgmt1 ~] [root@mgmt1 ~] [root@mgmt1 ~] [root@mgmt1 ~] [root@mgmt1 ~]
1.5.2. hosts写入密码 1 2 3 4 5 [root@mgmt1 ~] [vmhost] 192.168.101.249 ansible_ssh_user=root ansible_ssh_pass=123456 192.168.101.248 ansible_ssh_user=root ansible_ssh_pass=123456 192.168.101.247 ansible_ssh_user=root ansible_ssh_pass=123456
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@mgmt1 ~] 192.168.101.248 | SUCCESS => { "ansible_facts" : { "discovered_interpreter_python" : "/usr/bin/python" }, "changed" : false , "ping" : "pong" } 192.168.101.247 | SUCCESS => { "ansible_facts" : { "discovered_interpreter_python" : "/usr/libexec/platform-python" }, "changed" : false , "ping" : "pong" } 192.168.101.249 | SUCCESS => { "ansible_facts" : { "discovered_interpreter_python" : "/usr/libexec/platform-python" }, "changed" : false , "ping" : "pong" }
注意:这里ansible配置文件里需要配置关闭:host_key_checking = False
1.6. ansible常用模块 1.6.1. 主机连通性测试 我们使用ansible k8s -m ping
命令来进行主机连通性测试,效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@mgmt2 ansible]# ansible k8s -m ping 192.168.101.201 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": false, "ping": "pong" } 192.168.101.203 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": false, "ping": "pong" } 192.168.101.202 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": false, "ping": "pong" }
1.6.2. command 模块 这个模块可以直接在远程主机上执行命令,并将结果返回本主机。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@mgmt2 ansible]# ansible k8s -m command -a 'free -h' 192.168.101.202 | CHANGED | rc=0 >> total used free shared buff/cache available Mem: 7.6Gi 2.1Gi 2.2Gi 33Mi 3.4Gi 5.3Gi Swap: 0B 0B 0B 192.168.101.203 | CHANGED | rc=0 >> total used free shared buff/cache available Mem: 7.6Gi 2.4Gi 1.8Gi 25Mi 3.4Gi 5.3Gi Swap: 0B 0B 0B 192.168.101.201 | CHANGED | rc=0 >> total used free shared buff/cache available Mem: 3.7Gi 2.3Gi 121Mi 25Mi 1.3Gi 1.3Gi Swap: 0B 0B 0B
命令模块接受命令名称,后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理,比如$HOME和操作如”<”,”>”,”|”,”;”,”&” 工作(需要使用(shell)模块实现这些功能)。注意,该命令不支持| 管道命令
。 下面来看一看该模块下常用的几个命令:
chdir # 在执行命令之前,先切换到该目录 executable # 切换shell来执行命令,需要使用命令的绝对路径 free_form # 要执行的Linux指令,一般使用Ansible的-a参数代替。 creates # 一个文件名,当这个文件存在,则该命令不执行,可以 用来做判断 removes # 一个文件名,这个文件不存在,则该命令不执行
下面我们来看看这些命令的执行效果:
1 2 3 4 5 6 7 8 9 10 11 12 [root@mgmt2 ansible]# ansible k8s -m command -a 'chdir=/opt/ ls' #先切换到/data/ 目录,再执行“ls”命令 192.168.101.201 | CHANGED | rc=0 >> cni containerd 192.168.101.202 | CHANGED | rc=0 >> cni containerd 192.168.101.203 | CHANGED | rc=0 >> cni containerd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@mgmt2 ansible]# ansible k8s -m command -a 'creates=/data/Dockerfile ls' #如果/data/Dockerfile存在,则不执行“ls”命令 192.168.101.202 | CHANGED | rc=0 >> anaconda-ks.cfg docker docker-19.03.9.tgz yq 192.168.101.201 | SUCCESS | rc=0 >> skipped, since /data/Dockerfile exists 192.168.101.203 | CHANGED | rc=0 >> anaconda-ks.cfg docker docker-19.03.9.tgz yq
1 2 3 4 5 6 7 8 9 10 11 [root@mgmt2 ansible]# ansible k8s -m command -a 'removes=/data/Dockerfile free -h' #如果/data/Dockerfile存在,则执行“free -h”命令 192.168.101.202 | SUCCESS | rc=0 >> skipped, since /data/Dockerfile does not exist 192.168.101.203 | SUCCESS | rc=0 >> skipped, since /data/Dockerfile does not exist 192.168.101.201 | CHANGED | rc=0 >> total used free shared buff/cache available Mem: 3.7Gi 2.3Gi 116Mi 25Mi 1.3Gi 1.3Gi Swap: 0B 0B 0B
1.6.3. shell 模块 shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。
1 2 3 4 5 6 7 8 9 10 11 12 [root@mgmt2 ansible]# ansible k8s -m shell -a 'cat /etc/passwd |grep "root"' 192.168.101.201 | CHANGED | rc=0 >> root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin 192.168.101.202 | CHANGED | rc=0 >> root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin 192.168.101.203 | CHANGED | rc=0 >> root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
只要是我们的shell命令,都可以通过这个模块在远程主机上运行,但不可以使用shell模块执行交互命令,如vim,top等。
使用chdir参数切换工作目录
1 ansible k8s -m shell -a 'chdir=/tmp touch my.txt pwd'
shell模块支持判断(creates、removes)
creates 文件名: 文件存在,不执行shell命令
removes 文件名:文件不存在,不执行shell命令
1 2 3 4 5 ansible test -m shell -a "ssh-keygen -f ~/.ssh/id_rsa -N creates=~/.ssh/id_rsa" # 如果已经有密钥文件id_rsa,则不创建密钥(skip跳过) ansible test -m shell -a "unzip xx.zip removes=/bin/unzip" # 如果没有安装unzip软件包,则不执行解压命令(skip跳过)
1.6.4. copy模块 这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。 其相关选项如下:
src
#被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于”rsync”content
#用于替换”src”,可以直接指定文件的值dest
#必选项,将源文件复制到的远程主机的绝对路径 backup
#当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息directory_mode
#递归设定目录的权限,默认为系统默认权限force
#当目标主机包含该文件,但内容不同时,设为yes,表示强制覆盖;设为no,表示目标主机的目标位置不存在该文件才复制。默认为yesothers
#所有的 file 模块中的选项可以在这里使用
用法举例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 [root@mgmt2 ansible]# ansible web -m copy -a 'src=./ansible.cfg dest=/data/' 192.168.101.202 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": false, "checksum": "a2a782df5d7bd49afb0971fc6be21cd825daaaa3", "dest": "/data/ansible.cfg", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/data/ansible.cfg", "size": 20012, "state": "file", "uid": 0 } 192.168.101.201 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": false, "checksum": "a2a782df5d7bd49afb0971fc6be21cd825daaaa3", "dest": "/data/ansible.cfg", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/data/ansible.cfg", "size": 20012, "state": "file", "uid": 0 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 [root@mgmt2 ansible]# ansible web -m copy -a 'content="I love you" dest=/data/love mode=666' 192.168.101.202 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "checksum": "ce48c9870c7ae19796438aed65458c8bdc335157", "dest": "/data/love", "gid": 0, "group": "root", "md5sum": "e4f58a805a6e1fd0f6bef58c86f9ceb3", "mode": "0666", "owner": "root", "size": 10, "src": "/root/.ansible/tmp/ansible-tmp-1631174440.548185-142417634763846/source", "state": "file", "uid": 0 } 192.168.101.201 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "checksum": "ce48c9870c7ae19796438aed65458c8bdc335157", "dest": "/data/love", "gid": 0, "group": "root", "md5sum": "e4f58a805a6e1fd0f6bef58c86f9ceb3", "mode": "0666", "owner": "root", "size": 10, "src": "/root/.ansible/tmp/ansible-tmp-1631174440.5443904-137441252807840/source", "state": "file", "uid": 0 }
我们现在去查看一下我们生成的文件及其权限:
1 2 3 4 5 6 7 8 9 10 [root@mgmt2 ansible]# ansible web -m shell -a 'ls -la /data/' 192.168.101.202 | CHANGED | rc=0 >> total 24 -rw-r--r-- 1 root root 20012 Sep 9 15:54 ansible.cfg -rw-rw-rw- 1 root root 10 Sep 9 16:00 love 192.168.101.201 | CHANGED | rc=0 >> total 230280 -rw-r--r-- 1 root root 20012 Sep 9 15:54 ansible.cfg -rw-rw-rw- 1 root root 10 Sep 9 16:00 love
可以看出我们的love文件已经生成,并且权限为666
我们把文件的内容修改一下,然后选择覆盖备份:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 [root@mgmt2 ansible]# ansible web -m copy -a 'content="I love you today" backup=yes dest=/data/love mode=666' 192.168.101.201 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "backup_file": "/data/love.1710731.2021-09-09@16:08:11~", "changed": true, "checksum": "aae6d5443c11825389059f97953a5596f52472d0", "dest": "/data/love", "gid": 0, "group": "root", "md5sum": "ca125268f92d23fbb2ba11b5033d97a6", "mode": "0666", "owner": "root", "size": 16, "src": "/root/.ansible/tmp/ansible-tmp-1631174889.8834162-86186609378458/source", "state": "file", "uid": 0 } 192.168.101.202 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "backup_file": "/data/love.2458311.2021-09-09@16:08:11~", "changed": true, "checksum": "aae6d5443c11825389059f97953a5596f52472d0", "dest": "/data/love", "gid": 0, "group": "root", "md5sum": "ca125268f92d23fbb2ba11b5033d97a6", "mode": "0666", "owner": "root", "size": 16, "src": "/root/.ansible/tmp/ansible-tmp-1631174889.8911483-24337496953154/source", "state": "file", "uid": 0 }
现在我们可以去查看一下:
1 2 3 4 5 6 7 8 9 10 11 12 [root@mgmt2 ansible]# ansible web -m shell -a 'ls -la /data' 192.168.101.201 | CHANGED | rc=0 >> total 230288 -rw-r--r-- 1 root root 20012 Sep 9 15:54 ansible.cfg -rw-rw-rw- 1 root root 16 Sep 9 16:08 love -rw-rw-rw- 1 root root 10 Sep 9 16:00 love.1710731.2021-09-09@16:08:11~ 192.168.101.202 | CHANGED | rc=0 >> total 32 -rw-r--r-- 1 root root 20012 Sep 9 15:54 ansible.cfg -rw-rw-rw- 1 root root 16 Sep 9 16:08 love -rw-rw-rw- 1 root root 10 Sep 9 16:00 love.2458311.2021-09-09@16:08:11~
可以看出,我们的源文件已经被备份,我们还可以查看一下love
文件的内容:
1 2 3 4 5 6 [root@mgmt2 ansible]# ansible web -m shell -a 'cat /data/love' 192.168.101.201 | CHANGED | rc=0 >> I love you today 192.168.101.202 | CHANGED | rc=0 >> I love you today
证明,这正是我们新导入的文件的内容。
1.6.5. file模块
该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。 下面是一些常见的命令:
force
#需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|nogroup
#定义文件/目录的属组。后面可以加上mode
:定义文件/目录的权限owner
#定义文件/目录的属主。后面必须跟上path
:定义文件/目录的路径recurse
#递归设置文件的属性,只对目录有效,后面跟上src
:被链接的源文件路径,只应用于state=link
的情况dest
#被链接到的路径,只应用于state=link
的情况state
#状态,有以下选项:
directory
:如果目录不存在,就创建目录file
:即使文件不存在,也不会被创建link
:创建软链接hard
:创建硬链接touch
:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间absent
:删除目录、文件或者取消链接文件
用法举例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [root@mgmt2 ansible]# ansible web -m file -a 'path=/data/app state=directory' 192.168.101.202 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/data/app", "size": 6, "state": "directory", "uid": 0 } 192.168.101.201 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/data/app", "size": 6, "state": "directory", "uid": 0 }
我们可以查看一下
1 2 3 4 5 6 7 8 [root@mgmt2 ansible]# ansible web -m shell -a 'ls -l /data' 192.168.101.202 | CHANGED | rc=0 >> total 32 drwxr-xr-x 2 root root 6 Sep 9 16:13 app 192.168.101.201 | CHANGED | rc=0 >> total 230288 drwxr-xr-x 2 root root 6 Sep 9 16:13 app
可以看出,我们的目录已经创建完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [root@mgmt2 ansible]# ansible web -m file -a 'path=/data/hhh.cfg src=ansible.cfg state=link' 192.168.101.202 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "dest": "/data/hhh.cfg", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 11, "src": "ansible.cfg", "state": "link", "uid": 0 } 192.168.101.201 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "dest": "/data/hhh.cfg", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 11, "src": "ansible.cfg", "state": "link", "uid": 0 }
我们可以去查看一下:
1 2 3 4 5 6 7 8 9 10 [root@mgmt2 ansible]# ansible web -m shell -a 'ls -l /data' 192.168.101.202 | CHANGED | rc=0 >> total 32 -rw-r--r-- 1 root root 20012 Sep 9 15:54 ansible.cfg lrwxrwxrwx 1 root root 11 Sep 9 16:19 hhh.cfg -> ansible.cfg 192.168.101.201 | CHANGED | rc=0 >> total 230288 -rw-r--r-- 1 root root 20012 Sep 9 15:54 ansible.cfg lrwxrwxrwx 1 root root 11 Sep 9 16:19 hhh.cfg -> ansible.cfg
我们的链接文件已经创建成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@mgmt2 ansible]# ansible web -m file -a 'path=/data/ansible.cfg state=absent' 192.168.101.201 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "path": "/data/ansible.cfg", "state": "absent" } 192.168.101.202 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "path": "/data/ansible.cfg", "state": "absent" }
我们可以查看一下
1 2 3 4 5 6 [root@mgmt2 ansible]# ansible web -m shell -a 'ls /data/ansible.cfg' 192.168.101.201 | FAILED | rc=2 >> ls: cannot access '/data/ansible.cfg': No such file or directorynon-zero return code 192.168.101.202 | FAILED | rc=2 >> ls: cannot access '/data/ansible.cfg': No such file or directorynon-zero return code
已经没有这个文件
1.6.6. fetch 该模块用于从远程某主机获取(复制)文件到本地。 有两个选项:
dest
:用来存放文件的目录src
:在远程拉取的文件,并且必须是一个file ,不能是目录
具体举例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 root@mgmt2 ansible]# ansible web -m fetch -a 'src=/data/love dest=/data' 192.168.101.202 | CHANGED => { "changed": true, "checksum": "aae6d5443c11825389059f97953a5596f52472d0", "dest": "/data/192.168.101.202/data/love", "md5sum": "ca125268f92d23fbb2ba11b5033d97a6", "remote_checksum": "aae6d5443c11825389059f97953a5596f52472d0", "remote_md5sum": null } 192.168.101.201 | CHANGED => { "changed": true, "checksum": "aae6d5443c11825389059f97953a5596f52472d0", "dest": "/data/192.168.101.201/data/love", "md5sum": "ca125268f92d23fbb2ba11b5033d97a6", "remote_checksum": "aae6d5443c11825389059f97953a5596f52472d0", "remote_md5sum": null }
我们可以在本机上查看一下文件是否复制成功。要注意,文件保存的路径是我们设置的接收目录下的被管制主机ip
目录下:
1 2 3 4 5 6 7 8 9 10 11 [root@mgmt2 ansible]# cd /data/ [root@mgmt2 data]# ls 192.168.101.201 192.168.101.202 [root@mgmt2 data]# cd 192.168.101.201 [root@mgmt2 192.168.101.201]# ls data [root@mgmt2 192.168.101.201]# cd data/ [root@mgmt2 data]# ls love [root@mgmt2 data]# pwd /data/192.168.101.201/data
1.6.7. cron模块 该模块适用于管理cron
计划任务的。 其使用的语法跟我们的crontab
文件中的语法一致,同时,可以指定以下选项:
day=
#日应该运行的工作( 1-31, *, */2, )hour=
# 小时 ( 0-23, *, */2, )minute=
#分钟( 0-59, *, */2, )month=
# 月( 1-12, *, /2, )weekday=
# 周 ( 0-6 for Sunday-Saturday,, )job=
#指明运行的命令是什么name=
#定时任务描述reboot
# 任务在重启时运行,不建议使用,建议使用special_timespecial_time
#特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)state
#指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务user
# 以哪个用户的身份执行
举例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@mgmt2 ~]# ansible web -m cron -a 'name="ntp update every 5 min" minute=*/5 job="/sbin/ntpdate 172.17.0.1 &> /dev/null"' 192.168.101.202 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "ntp update every 5 min" ] } 192.168.101.201 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "ntp update every 5 min" ] }
我们可以去查看一下:
1 2 3 4 5 6 7 8 [root@mgmt2 ~]# ansible web -m shell -a 'crontab -l' 192.168.37.122 | SUCCESS | rc=0 >> # Ansible: ntp update every 5 min */5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null 192.168.37.133 | SUCCESS | rc=0 >> # Ansible: ntp update every 5 min */5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
可以看出,我们的计划任务已经设置成功了。
1.6.8. script模块 如果复杂的命令怎么办?
script允许在本地写脚本,拷贝到被管理端并执行脚本
脚本不是shell脚本(如python、perl脚本等),可以没有-x
1 2 3 4 5 6 7 [root@mgmt2 ~]# cat test.sh # !/bin/bash yum -y install httpd systemctl start httpd [root@mgmt2 ~]# ansible test -m script -a "./test.sh" # test 是主机组的名称
1.6.9. lineinfile 和 replace模块 在修改单个文件的单行内容时可以使用lineinfile模块
1 2 3 4 [root@mgmt2 ~]# ansible test -m lineinfile -a "path=/etc/issue regexp="hello" line='ni hao'" # 在/etc/issue文件中正则匹配包含hello的行,把整行内容替换为ni hao # 如果无法匹配到hello,则在文件最后添加一行nihao # 如果有多行内容包含hello,则仅替换最后一行
lineinfile会替换一整行,replace可以替换关键词
1 2 [root@mgmt2 ~]# ansible test -m replace -a "path=/etc/issue.net regexp=Kernel replace=Ocena" # 将/etc/issue文件全文所有的Kernel替换为Ocean
1.6.10. user模块 user模块可以实现Linux系统账户管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
1.6.11. yum_repository模块 使用yum_repository模块可以创建或修改yum源配置文件
1 2 3 4 5 6 7 [root@mgmt2 ~] [myyum] baseurl = ftp://192.168.4.254/centos gpgcheck = 0 name = hello
使用yum模块可以安装、卸载、升级软件包
state:present(安装)|absent(卸载)|latest(升级)
1 2 3 4 5 6 7 8 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
1.6.12. service模块 service为服务管理模块(启动、关闭、重启服务等)
state:started | stopped | restarted
enable:yes 设置开机启动
1 2 3 4 5 6 7 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
1.6.13. 逻辑卷相关模块 lvg模块:创建、删除卷组(VG),修改卷组大小
state:present(创建) | absent(删除)
1 2 3 4 5 6 7 8 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
lvol模块:创建、删除逻辑卷(LV),修改逻辑卷大小
state:present(创建)| absent(删除)
1 2 3 4 5 6 7 8 9 10 11 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
1.7. sudo提权 1.7.1. 基本概念 sudo
superuser or another do
以超级管理员或其他人的身份执行命令
基本流程
管理员需要先授权(修改/etc/sudoers文件)
普通用户以sudo的形式执行命令
可以通过sudo -l查看授权情况
1.7.2. sudoers语法 修改/etc/sudoers的方法
visudo(带语法检查,默认没有颜色提示)
vim /etc/sudoers (不带语法检查,默认有颜色提示)
授权格式如下:
用户或组 主机列表=(提权身份) [NOPASSWD]:命令列表
命令需要写绝对路径
1 2 3 4 [root@mgmt2 ~] ... ... root ALL=(ALL) ALL %wheel ALL=(ALL) ALL
1.7.3. 配置sudo提权 为所有被管理主机创建系统账户
用户名为alice,密码为123456
在所有被管理主机配置sudo,让alice可以管理系统服务
默认普通用户无权执行systemctl命令
1 2 3 4 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
在所有被管理主机配置sudo,让alice可以执行任何命令
使用NOPASSWD开启无密码验证
1 2 3 4 [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~] [root@mgmt2 ~]
1.8. Ansible配置进阶 1.8.1. 修改ansible配置文件 修改~/ansible/ansible.cfg
修改sudo相关配置(参考/etc/ansible/ansible.cfg)
1 2 3 4 5 6 7 8 9 10 11 [root@mgmt2 ~] [defaults] inventory = /etc/ansible/hosts remote_user = alice [privilege_escalation] become = true become_method = sudo become_user = root become_ask_pass = no
1.8.2. 配置ssh密钥 使用alice远程被管理主机,需要提前配置SSH密钥
1 2 3 4 5 6 7 [root@mgmt2 ~] do ssh-copy-id alice@$i done [root@mgmt2 ~]
1.8.3. inventory配置 修改主机清单文件,添加变量(多个变量空格分隔)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@mgmt2 ~]# cat /etc/ansible/hosts [test] node1 [proxy] node2 [web] node[3:4] [database] node5 [cluster:children] web database
ansible_ssh_prot=220 #自定义远程ssh端口
ansible_ssh_user=alice #自定义远程连接的账户名
ansible_ssh_pass=密码 #自定义远程连接的密码
ansible_ssh_private_key_file=密钥文件 #自定义远程连接的密钥
这里的配置项可以单独配置到对应的主机。