ansible 自动化运维工具
一 安装:yum 安装或者 编译安装
#CentOS 的EPEL源的rpm包安装 [root@centos ~]#yum install ansible #ubuntu 安装 [root@ubuntu ~]#apt -y install ansible 编译安装 yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto wget https://releases.ansible.com/ansible/ansible-1.5.4.tar.gz tar xf ansible-1.5.4.tar.gz cd ansible-1.5.4 python setup.py build python setup.py install mkdir /etc/ansible cp -r examples/* /etc/ansible 二、配置文件 主配置文件: /etc/ansible/ansible.cfg 基本不需要动host_key_checking=False 放开注释,那么在使用ansible 的时候就不需要输入yes no 了
主机清单 : /etc/ansible/hosts 里面添加需要管理的机器 三、基于key 验证 主机清单 : /etc/ansible/hosts 配置说明 ansible_ssh_host #将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置. ansible_ssh_port #ssh端口号.如果不是默认的端口号,通过此变量设置.这种可以使用 ip:端口 192.168.1.100:2222 ansible_ssh_user #默认的 ssh 用户名 ansible_ssh_pass #ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥) ansible_sudo_pass #sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass) ansible_sudo_exe (new in version 1.8) #sudo 命令路径(适用于1.8及以上版本) ansible_connection #与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默 认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来 判断'ssh' 方式是否可行. ansible_ssh_private_key_file #ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的 情况. ansible_shell_type #目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'. ansible_python_interpreter #目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python 不是 2.X 版本的 Python.之所以不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径.... 范例 ntp.magedu.com [webservers] www1.magedu.com:2222 www2.magedu.com [dbservers] db1.magedu.com db2.magedu.com db3.magedu.com #或者 db[1:3].magedu.com 范例2 [webservers] www[1:100].example.com [dbservers] db-[a:f].example.com [appservers] 10.0.0.[1:100] #定义testsrvs组中包括两个其它分组,实现组嵌套 [testsrvs:children] webservers dbservers 范例3 [test] 10.0.0.8 ansible_connection=local #指定本地连接,无需ssh配置 #ansible_connection=ssh 需要StrictHostKeyChecking no 10.0.0.7 ansible_connection=ssh ansible_ssh_port=2222 ansible_ssh_user=wang ansible_ssh_password=magedu 10.0.0.6 ansible_connection=ssh ansible_ssh_user=root ansible_ssh_password=123456 #执行ansible命令时显示别名,如web01 [websrvs] web01 ansible_ssh_host=10.0.0.101 web02 ansible_ssh_host=10.0.0.102 [websrvs:vars] ansible_ssh_password=magedu some_host ansible_ssh_port=2222 ansible_ssh_user=manager aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem freebsd_host ansible_python_interpreter=/usr/local/bin/python ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3 三、基于key 验证直接用,是报红的
如果不配置基于key 验证,那么需要用到参数 -k ,需要输入密码
常用ansible 功能模块:
command
功能:在远程主机执行命令,此为默认模块,可忽略 -m 选项 可以在 /etc/ansible/ansible.cfg 中修改。 注意:此命令不支持 $VARNAME < > | ; & 等,可能用shell模块实现 注意:此模块不具有幂等性常用参数
chdir参数:此参数的作用就是指定一个目录,在执行对应的命令之前,会先进入到chdir参数指定的目录中。
creates参数:看到creates,你可能会从字面上理解这个参数,但是使用这个参数并不会帮助我们创建文件,它的作用是当指定的文件存在时,就不执行对应命令,比如:如果/testdir/test文件存在,就不执行我们指定的命令。
removes参数:与creates参数的作用正好相反,,此参数并不会帮助我们删除文件它的作用是==当指定的文件不存在时,就不执行对应命令,==比如:如果/testdir/tests文件不存在,就不执行我们指定的命令
范例:打开 151 152 机器上 etc 目录下 的centos-release 文件 [root@node01 ~]# ansible webservers -m command -a 'chdir=/etc cat centos-release' 10.0.0.152 | CHANGED | rc=0 >> CentOS Linux release 7.9.2009 (Core) 10.0.0.151 | CHANGED | rc=0 >> CentOS Linux release 7.9.2009 (Core)
[root@node01 ~]# ansible webservers -m command -a 'chdir=/etc creates=/data/f1.txt cat centos-release'
10.0.0.151 | SUCCESS | rc=0 >>
skipped, since /data/f1.txt exists
10.0.0.152 | CHANGED | rc=0 >>
CentOS Linux release 7.9.2009 (Core)
[root@node01 ~]# ansible webservers -m command -a 'chdir=/etc removes=/data/f1.txt cat centos-release'
10.0.0.152 | SUCCESS | rc=0 >>
skipped, since /data/f1.txt does not exist
10.0.0.151 | CHANGED | rc=0 >>
CentOS Linux release 7.9.2009 (Core)
[root@node01 ~]#
虽然shell模块看起来非常万能,但存在着许多风险。例如:shell注入风险,非幂等性(即统一命令多次执行的结果可能是不一样的)
说明:
chdir:在哪个目录下执行shell命令,相当于执行shell命令前先cd到对应目录
creates:如果存在某文件,就不执行shell
removes:如果不存在某文件,就不执行shell;与creates左右相反(有点绕)
executable:修改并指定shell解释器来执行命
free_form:指的就是具体的shell命令,实际上是一个不存在的选项
范例1:查看当前主目录 #-m shell表示使用shell模块 #-a 表示传递shell模块的相关参数 #-i 指定了inventory文件 #local是inventory文件里面定义好的节点 [root@node01 ~]# ansible -i /etc/ansible/hosts local -m shell -a 'pwd' 10.0.0.150 | CHANGED | rc=0 >> /root 范例2:查看远程主机的主机名 注意双引号和单引号的区别,双引号查出来的是自己的,单引号查出来的是远程主机的 [root@node01 ~]# ansible webservers -m shell -a "echo $HOSTNAME" 10.0.0.151 | CHANGED | rc=0 >> node01 10.0.0.152 | CHANGED | rc=0 >> node01 [root@node01 ~]# ansible webservers -m shell -a 'echo $HOSTNAME' 10.0.0.152 | CHANGED | rc=0 >> node03 10.0.0.151 | CHANGED | rc=0 >> node02 [root@node01 ~]#
Script 模块
功能:在远程主机上运行ansible服务器上的脚本(无需执行权限) 注意:此模块不具有幂等性范例 ansible websrvs -m script -a /data/test.sh
copy 模块用于将本地或远程机器上的文件拷贝到远程主机
名称 | 必选 | 默认值 | 可选值 | 备注 |
backup | no | no | yes/no | 在覆盖之前将原文件备份,备份文件包含时间信息 |
src | no | 将本地路径复制到远程服务器; 可以是绝对路径或相对的。如果是一个目录,它将被递归地复制。如果路径以/ 结尾,则只有该目录下内容被复制到目的地,如果没有使用/ 来结尾,则包含目录在内的整个内容全部复制 |
||
dest | yes | 目标绝对路径。如果src 是一个目录,dest 也必须是一个目录。如果dest 是不存在的路径,并且如果dest以/ 结尾或者src是目录,则dest被创建。如果src 和dest 是文件,如果dest 的父目录不存在,任务将失败 |
||
owner | no | 设置文件/目录的所属用户,将被馈送到chown | ||
group | no | 设置文件/目录的所属组,将被馈送到chown | ||
content | no | 当用content代替src参数的时候,可以把文档的内容设置到特定的值 | ||
follow | no | no | yes/no | 是否遵循目的机器中的文件系统链接 |
froce | no | no | yes/no | 当内容不同于源时,将替换远程文件。设置为no ,则只有在目标不存在的情况下才会传输文件 |
local_follow | no | yes | yes/no | 是否遵循本地机器中的文件系统链接 |
mode | no | 设置文件权限,模式实际上是八进制数字(如0644),少了前面的零可能会有意想不到的结果。从版本1.8开始,可以将模式指定为符号模式(例如u+rwx或u=rw,g=r,o=r) |
范例: #如目标存在,默认覆盖,此处指定先备份 ansible websrvs -m copy -a "src=/root/test1.sh dest=/tmp/test2.sh owner=wang mode=600 backup=yes" #指定内容,直接生成目标文件 ansible websrvs -m copy -a "content='test line1\ntest line2\n' dest=/tmp/test.txt" #复制/etc目录自身,注意/etc/后面没有/ ansible websrvs -m copy -a "src=/etc dest=/backup" #复制/etc/下的文件,不包括/etc/目录自身,注意/etc/后面有/ ansible websrvs -m copy -a "src=/etc/ dest=/backupFetch 模块 功能:从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录
范例; ansible websrvs -m fetch -a 'src=/root/test.sh dest=/data/scripts'Get_url 模块 功能: 用于将文件从http、https或ftp下载到被管理机节点上 常用参数如下
注意 这里的src 就是远程主机的目录 dest 代表是 ansible 主控端的主机
常用参数如下: url: 下载文件的URL,支持HTTP,HTTPS或FTP协议 dest: 下载到目标路径(绝对路径),如果目标是一个目录,就用服务器上面文件的名称,如果目标设置了名 称就用目标设置的名称 owner:指定属主 group:指定属组 mode:指定权限 force: 如果yes,dest不是目录,将每次下载文件,如果内容改变,替换文件。如果否,则只有在目标不存 在时才会下载该文件 checksum: 对目标文件在下载后计算摘要,以确保其完整性 示例: checksum="sha256:D98291AC[...]B6DC7B97", checksum="sha256:http://example.com/path/sha256sum.txt" url_username: 用于HTTP基本认证的用户名。 对于允许空密码的站点,此参数可以不使用 `url_password' url_password: 用于HTTP基本认证的密码。 如果未指定`url_username'参数,则不会使用 `url_password'参数 validate_certs:如果“no”,SSL证书将不会被验证。 适用于自签名证书在私有网站上使用 timeout: URL请求的超时时间,秒为单位 范例:下载nginx [root@ansible ~]#ansible websrvs -m get_url -a 'url=http://nginx.org/download/nginx-1.18.0.tar.gz dest=/usr/local/src/nginx.tar.gz checksum="md5:b2d33d24d89b8b1f87ff5d251aa27eb8"'File 模块 功能:设置文件属性,创建软链接等
#创建空文件 ansible all -m file -a 'path=/data/test.txt state=touch' #创建 all 是只hosts 里面的所有IP ansible all -m file -a 'path=/data/test.txt state=absent' #删除 ansible all -m file -a "path=/root/test.sh owner=wang mode=755" #指定所有者并给权限 #创建目录 ansible all -m file -a 'path=/data/testdir state=directory' #递归修改目录属性,但不递归至子目录 ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql" #递归修改目录及子目录的属性 ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes" #创建软链接 ansible all -m file -a 'src=/data/testfile path|dest|name=/data/testfile-link state=link'stat 模块 功能:检查文件或文件系统的状态 注意:对于Windows目标,请改用win_stat模块
选项 path:文件/对象的完整路径(必须)exists: 判断是否存在 isuid: 调用用户的ID与所有者ID是否匹配
常用返回值的判断
范例: [root@node01 ~]# ansible webservers -m stat -a 'path=/data/f1.txt' 10.0.0.151 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "stat": { "atime": 1647163799.815982, "attr_flags": "", "attributes": [], "block_size": 4096, "blocks": 0, "charset": "binary", "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "ctime": 1647163799.8239825, "dev": 64770, "device_type": 0, "executable": false, "exists": true, "gid": 0, "gr_name": "root", "inode": 68, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mimetype": "inode/x-empty", "mode": "0644", "mtime": 1647163799.075982, "nlink": 1, "path": "/data/f1.txt", "pw_name": "root", "readable": true, "rgrp": true, "roth": true, "rusr": true, "size": 0, "uid": 0, "version": "18446744072962527632", "wgrp": false, "woth": false, "writeable": true, "wusr": true, "xgrp": false, "xoth": false, "xusr": false } } 10.0.0.152 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "stat": { "atime": 1647163799.80998, "attr_flags": "", "attributes": [], "block_size": 4096, "blocks": 0, "charset": "binary", "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "ctime": 1647163799.8189805, "dev": 64770, "device_type": 0, "executable": false, "exists": true, "gid": 0, "gr_name": "root", "inode": 68, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mimetype": "inode/x-empty", "mode": "0644", "mtime": 1647163799.06798, "nlink": 1, "path": "/data/f1.txt", "pw_name": "root", "readable": true, "rgrp": true, "roth": true, "rusr": true, "size": 0, "uid": 0, "version": "723331210", "wgrp": false, "woth": false, "writeable": true, "wusr": true, "xgrp": false, "xoth": false, "xusr": false } } [root@node01 ~]#unarchive 模块 功能:解包解压缩 实现有两种用法: 1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes,此为默认值,可省略 2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
帮助语法 - name: Unarchive a file that is already on the remote machine unarchive: src: /tmp/foo.zip #要解压的包 dest: /usr/local/bin #解压到目标位置 remote_src: yes #要解压的包在受控端 no #要解压的包在控制端
常见参数 copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no, 会在远程主机上寻找src源文件 remote_src:和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible 主机上 src:源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果 是远程主机上的路径,则需要设置copy=no dest:远程主机上的目标路径 mode:设置解压缩后的文件权限
范例:解压foo.tgz 到受控端,文件在ansible 主机上,解压后的目标文件在受控端的 car/lib/foo 文件夹下 ansible all -m unarchive -a 'src=/data/foo.tgz dest=/var/lib/foo owner=wang group=bin'
#解压foo.tgz 到受控端,文件在受控机的 tmp目录下,解压后的目标文件在受控端的 car/lib/foo 文件夹下
ansible all -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
#解压foo.tgz 到受控端,文件在受控机的 tmp目录下,解压后的目标文件在受控端的 car/lib/foo 文件夹下
ansible all -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
#解压foo.tgz 到受控端,文件在ansible 主机上,解压后的目标文件在受控端的 car/lib/foo 文件夹下
ansible websrvs -m unarchive -a 'src=https://releases.ansible.com/ansible/ansible-2.1.6.0-0.1.rc1.tar.gz dest=/data/ owner=root remote_src=yes'
#解压foo.tgz 到受控端,文件在受控机的 tmp目录下,解压后的目标文件在受控端的 car/lib/foo 文件夹下
ansible websrvs -m unarchive -a 'src=http://nginx.org/download/nginx- 1.18.0.tar.gz dest=/usr/local/src/ copy=no'Archive 模块 功能:打包压缩保存在被管理节点
帮助语法 EXAMPLES: - name: Compress directory /path/to/foo/ into /path/to/foo.tgz archive: path: /path/to/foo #要压缩的文件或目录 dest: /path/to/foo.tgz #压缩后的文件 format:bz2, gz, tar, xz, zip #指定打包的类型
范例 ansible websrvs -m archive -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=wang mode=0600'Hostname 模块 功能:管理主机名
范例: ansible node1 -m hostname -a "name=websrv" ansible 10.0.0.18 -m hostname -a 'name=node18.magedu.com'Cron 模块 功能:计划任务 支持时间:minute,hour,day,month,weekday
范例 #先创建备份数据库脚本 [root@centos8 ~]#cat /root/mysql_backup.sh #!/bin/bash mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_`date +%F_%T`.sql.gz #创建任务 ansible 10.0.0.8 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh' ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate ntp.aliyun.com &>/dev/null' name=Synctime" #禁用计划任务 ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes" #启用计划任务 ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no #删除任务 ansible websrvs -m cron -a "name='backup mysql' state=absent" ansible websrvs -m cron -a 'state=absent name=Synctime'Yum 和 Apt 模块 功能: yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本 apt 模块管理 Ubuntu
范例 ansible websrvs -m yum -a 'name=httpd state=present' #安装 ansible websrvs -m yum -a 'name=nginx state=present enablerepo=epel' #启用epel源 进行安装 ansible websrvs -m yum -a 'name=* state=lastest exclude=kernel*,foo*' #升级除 kernel和foo开头以外的所有包 ansible websrvs -m yum -a 'name=httpd state=absent' #删除Service 模块 管理服务
范例 示例一、启动httpd服务 # ansible 192.168.85.251 -m service -a "name=httpd state=started" -i hosts 示例二、重载httpd服务 # ansible 192.168.85.251 -m service -a "name=httpd state=reloaded" -i hosts 示例三、重启Httpd服务 ansible 192.168.85.251 -m service -a "name=httpd state=restarted" -i hosts 示例四、停止httpd服务 ansible 192.168.85.251 -m service -a "name=httpd state=stopped" -i hosts 示例五、 启动httpd服务,并加入开机自启 ansible 192.168.85.251 -m service -a "name=httpd state=started enabled=yes" -i hostsUser 模块 管理用户
范例 #创建用户 comment 是描述 ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root' ansible all -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes' #remove=yes表示删除用户及家目录等数据,默认remove=no ansible all -m user -a 'name=nginx state=absent remove=yes' #生成123456加密的密码 ansible localhost -m debug -a "msg={{ '123456'| password_hash('sha512','salt')}}" localhost | SUCCESS => { "msg": "$6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w." }#用上面创建的密码创建用户 ansible websrvs -m user -a 'name=test password="$6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w."' #创建用户test,并生成4096bit的私钥 ansible websrvs -m user -a 'name=test generate_ssh_key=yes ssh_key_bits=4096 ssh_key_file=.ssh/id_rsa'Group 模块 管理组
范例 #创建组 ansible websrvs -m group -a 'name=nginx gid=88 system=yes' #删除组 ansible websrvs -m group -a 'name=nginx state=absent'Setup 模块 功能: setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机 较多,会影响执行速度 可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息
范例 ansible all -m setup ansible all -m setup -a "filter=ansible_nodename" ansible all -m setup -a "filter=ansible_hostname" ansible all -m setup -a "filter=ansible_domain" ansible all -m setup -a "filter=ansible_memtotal_mb" ansible all -m setup -a "filter=ansible_memory_mb" ansible all -m setup -a "filter=ansible_memfree_mb" ansible all -m setup -a "filter=ansible_os_family" ansible all -m setup -a "filter=ansible_distribution_major_version" ansible all -m setup -a "filter=ansible_distribution_version" ansible all -m setup -a "filter=ansible_processor_vcpus" ansible all -m setup -a "filter=ansible_all_ipv4_addresses" ansible all -m setup -a "filter=ansible_architecture" ansible all -m setup -a "filter=ansible_uptime_seconds" ansible all -m setup -a "filter=ansible_processor*" ansible all -m setup -a 'filter=ansible_env'