第二篇文章 开始实操: 1. 安装 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 yum install ansible yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto 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 git clone git://github.com/ansible/ansible.git --recursive cd ./ansible source ./hacking/env-setup yum install python-pip python-devel yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel pip install --upgrade pip pip install ansible --upgrade ansible --version
2. 配置文件(相关工具)
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性(一般无需修改)
/etc/ansible/hosts 主机清单(将被管理的主机放到此文件)
/etc/ansible/roles/ 存放角色的目录
/usr/bin/ansible 主程序,临时命令执行工具
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
/usr/bin/ansible-pull 远程执行命令的工具
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
3. ansible 主配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Ansible 配置文件/etc/ansible/ansible.cfg (一般保持默认) vim /etc/ansible/ansible.cfg [defaults] #inventory = /etc/ansible/hosts # 主机列表配置文件 #library = /usr/share/my_modules/ # 库文件存放目录 #remote_tmp = $HOME/.ansible/tmp # 临时py命令文件存放在远程主机目录 #local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录 #forks = 5 # 默认并发数,同时可以执行5 次 #sudo_user = root # 默认sudo 用户 #ask_sudo_pass = True # 每次执行ansible命令是否询问ssh密码 #ask_pass = True # 每次执行ansible命令是否询问ssh口令 #remote_port = 22 # 远程主机的端口号(默认22 ) 建议优化项: host_key_checking = False # 检查对应服务器的host_key,建议取消注释 log_path=/var/log/ansible.log # 日志文件,建议取消注释 module_name = command # 默认模块
4. inventory 主机清单 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 Inventory 主机清单 1> ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名 2> 默认的inventory file为/etc/ansible/hosts 3> inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成 /etc/ansible/hosts文件格式 inventory文件遵循INI文件风格,中括号中的字符为组名。 可以将同一个主机同时归并到多个不同的组中; 此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明 ntp.magedu.com 不分组,直接加 [webservers] webservers组 www1.magedu.com:2222 可以指定端口 www2.magedu.com [dbservers] db1.magedu.com db2.magedu.com db3.magedu.com 如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机 示例: [websrvs] www[1:100].example.com ip: 1-100 [dbsrvs] db-[a:f].example.com dba-dbff
5. ansible系列命令 利用ansible实现管理的主要方式:
Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景
Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
5.1 ansible-doc (显示模块帮助) ansible-doc: 显示模块帮助
1 2 3 4 5 6 7 8 9 ansible-doc [options] [module...] -a 显示所有模块的文档 -l, --list 列出可用模块 -s, --snippet 显示指定模块的playbook片段(简化版,便于查找语法) 示例: ansible-doc -l 列出所有模块 ansible-doc ping 查看指定模块帮助用法 ansible-doc -s ping 查看指定模块帮助用法
1 2 3 Ansible系列命令 ansible ansible-doc ansible-playbook ansible-vault ansible-console ansible-galaxy ansible-pull
5.2 ansible ansible通过ssh实现配置管理、应用部署、任务执行等功能, 建议:使用之前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点
范例:利用sshpass批量实现基于key验证
1 2 3 4 5 6 ssh-keygen -f /root/.ssh/id_rsa -P '' NET=192.168.135export SSHPASS=magedufor IP in {1..200};do sshpass -e ssh-copy-id $NET .$IP done
5.3 ansible的ping 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 格式: ansible <host-pattern> [-m module_name] [-a args] 例子:ansible target_hosts -m command -a "echo 1" ansible + 被管理的主机(分组名 例:webserver/all-->所有主机) + 模块名 + 参数 --version 显示版本 -m module 指定模块,默认为command -v 详细过程 –vv -vvv更详细 --list-hosts 显示主机列表,可简写 --list -k, --ask-pass 提示输入ssh连接密码,默认Key验证 -C, --check 检查,并不执行 -T, --timeout =TIMEOUT 执行命令的超时时间,默认10s -u, --user=REMOTE_USER 执行远程执行的用户 -b, --become 代替旧版的sudo 切换 --become-user=USERNAME 指定sudo 的runas用户,默认为root -K, --ask-become-pass 提示输入sudo 时的口令
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ping模块: 探测网络中被管理主机是否能够正常使用 走ssh协议 如果对方主机网络正常,返回pong 1> 默认情况下连接被管理的主机是ssh基于key验证,如果没有配置key,权限将会被拒绝 因此需要指定以谁的身份连接,输入用户密码,必须保证被管理主机用户密码一致 ansible all -m ping -k 2> 或者实现基于key验证 将公钥ssh-copy-id到被管理的主机上 , 实现免密登录 ansible all -m ping 3> 指定使用用户连接,注意不同用户之间的认证不通的,所以使用root登陆过但用其他用户登录依旧需要再次输入密码 ansible all -u bote798 -m ping ansible all -m ping 192.168.135.143 | UNREACHABLE! => { "changed" : false , "msg" : "Failed to connect to the host via ssh: ssh: Host verification failed" , "unreachable" : true } 192.168.135.143 | UNREACHABLE! => { "changed" : false , "msg" : "Failed to connect to the host via ssh:root@192.168.135.143: Permission denied (publickey,password)." , "unreachable" : true } ansible all -k -m ping 192.168.135.142 | SUCCESS => { "ansible_facts" : { "discovered_interpreter_python" : "/usr/bin/python3" }, "changed" : false , "ping" : "pong" } 192.168.135.143 | UNREACHABLE! => { "changed" : false , "msg" : "Invalid/incorrect password: \nAuthorized users only. All activities may be monitored and reported.\nPermission denied, please try again." , "unreachable" : true }"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " ssh-keygen -f /root/.ssh/id_rsa -P '' NET=192.168.135 export SSHPASS=magedu for IP in {1..200};do sshpass -e ssh-copy-id $NET .$IP done " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
5.3 ansible的Host-pattern 匹配主机的列表
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 ansible all –m ping ansible "*" -m ping (*表示所有主机) ansible 192.168.135.* -m ping ansible "*srvs" -m ping ansible "webserver:appserver" -m ping ansible “192.168.135.142:192.168.135.143” -m ping 哪个成功就先返回哪个,并且随后在一段时间后返回连接错误的 ansible "webserver:&dbserver" –m ping 在websrvs组并且在dbsrvs组中的主机 ansible 'webserver:!dbserver' –m ping 在websrvs组,但不在dbsrvs组中的主机 注意:此处为单引号,双引号不生效 ansible 'webserver:dbserver:&appserver:!ftpserver' –m ping ansible "webserver:&dbserver" –m ping ansible "~(web|db).*\.magedu\.com" –m ping ansible "~(web|db|app).*" -m ping
5.4 ansible命令执行过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1. 加载自己的配置文件 默认/etc/ansible/ansible.cfg 2. 加载自己对应的模块文件,如command 3. 通过ansible将模块或命令生成对应的临时py文件, 并将该文件传输至远程服务器的对应执行用户$HOME /.ansible/tmp/ansible-tmp-数字/XXX.PY文件 4. 给文件+x执行 5. 执行并返回结果 6. 删除临时py文件,sleep 0退出 ansible "~(web|db|app).*" -m ping > /home/ansible.log grep chmod /home/ansible.log 执行状态: 绿色:执行成功并且不需要做改变的操作 黄色:执行成功并且对目标主机做变更 红色:执行失败
5.5 ansible使用示例 1 2 3 4 5 6 7 8 9 10 11 12 示例 以wang用户执行ping存活检测 ansible all -m ping -u wang -k 以wang sudo至root执行ping存活检测 ansible all -m ping -u wang -k -b 以wang sudo至mage用户执行ping存活检测 ansible all -m ping -u wang -k -b --become-user =mage 以wang sudo至root用户执行ls ansible all -m command -u wang -a 'ls /root' -b --become-user =root -k -K ansible ping模块测试连接 ansible 192.168.38.126,192.168.38.127 -m ping -k
5.6 ansible相关工具 模块文档:https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
5.6.1 ansible-galaxy 此工具会链接https://galaxy.ansible.com下载对应的roles
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ansible-galaxy install xxxx ansible-galaxy install geerlingguy.nginx ansible-galaxy list ansible-galaxy remove geerlingguy.mysqlrm -rf geerlingguy.mysql [root@control-141 roles]# tree geerlingguy.mysql/ geerlingguy.mysql/ ├── defaults │ └── main.yml ├── handlers │ └── main.yml ├── LICENSE ├── meta │ └── main.yml ├── molecule │ └── default │ ├── converge.yml │ └── molecule.yml ├── README.md ├── tasks │ ├── configure.yml │ ├── databases.yml │ ├── main.yml │ ├── replication.yml │ ├── secure-installation.yml │ ├── setup-Archlinux.yml │ ├── setup-Debian.yml │ ├── setup-RedHat.yml │ ├── users.yml │ └── variables.yml ├── templates │ ├── my.cnf.j2 │ ├── root-my.cnf.j2 │ └── user-my.cnf.j2 └── vars ├── Archlinux.yml ├── Debian-10.yml ├── Debian-11.yml ├── Debian-12.yml ├── Debian.yml ├── RedHat-7.yml ├── RedHat-8.yml ├── RedHat-9.yml └── Ubuntu.yml
5.6.2 ansible-pull 此工具会推送ansible的命令至远程,效率无限提升,对运维要求较高
5.6.3 ansbile-playbook 此工具用于执行编写好的playbook任务
范例:
1 2 3 4 5 6 7 8 9 ansible-playbook hello.ymlcat hello.yml --- - hosts: webserver remote_user: root tasks: - name: hello world command : /usr/bin/wall hello world
5.6.4 ansible-vault 此工具可以用于加密解密yml文件
5.6.5 ansible-console 此工具可交互执行命令,支持tab,ansible 2.0+新增
提示符格式:
1 执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]$
常用子命令:
设置并发数:forks n 例如:forks 10
切换组:cd 主机组 例如:cd web
列出当前组主机列表:list
列出所有的内置命令:?或help
范例:
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 [root@control-141 home]# ansible-console Welcome to the ansible console. Type help or ? to list commands. root@all (3)[f:5]$ forks 3 root@all (3)[f:3]$ forks 5 root@all (3)[f:5]$ cd webserver root@webserver (2)[f:5]$ list 192.168.135.143 192.168.135.144 root@webserver (2)[f:5]$ cd all root@all (3)[f:5]$ ls 192.168.135.144 | CHANGED | rc=0 >> anaconda-ks.cfg 192.168.135.142 | CHANGED | rc=0 >> anaconda-ks.cfg 192.168.135.143 | CHANGED | rc=0 >> anaconda-ks.cfg root@all (3)[f:5]$ ? Documented commands (type help <topic>): ======================================== EOF a10 a10_server a10_server_axapi3 a10_service_group a10_virtual_server accelerate ...... root@appsrvs (2)[f:5]$ yum name=httpd state=present root@appsrvs (2)[f:5]$ service name=httpd state=started
5.7 ansible常用模块 功能:在远程主机执行命令,此为默认模块,可忽略 -m选项
注意:此命令不支持 $VARNAME < > | ; & 等,用shell模块实现
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@control-141 ansible]# ansible appserver -m command -a 'cat /etc/system-release' 192.168.135.144 | CHANGED | rc=0 >> openEuler release 24.03 (LTS-SP1) 192.168.135.142 | CHANGED | rc=0 >> openEuler release 24.03 (LTS-SP1) 192.168.135.143 | CHANGED | rc=0 >> openEuler release 24.03 (LTS-SP1) [root@control-141 ~]# ansible webserver -m command -a 'chdir=/etc cat system-release' 192.168.135.143 | CHANGED | rc=0 >> openEuler release 24.03 (LTS-SP1) 192.168.135.144 | CHANGED | rc=0 >> openEuler release 24.03 (LTS-SP1) [root@control-141 etc]# ansible webserver -m command -a 'chdir=/etc creates=/home/1.txt cat system-release' 192.168.135.144 | CHANGED | rc=0 >> openEuler release 24.03 (LTS-SP1) 192.168.135.143 | SUCCESS | rc=0 >> skipped, since /home/1.txt exists
command的局限性:有很多符号(例: $VARNAME < > | ; &等)都不支持,导致很多命令无法使用。
5.7.2 Shell 模块 功能:和command相似,但比command功能更多,用shell执行命令
范例:
1 2 3 4 5 ansible webserver -m shell -a 'echo $HOSTNAME' vim /etc/ansible/ansible.cfg module_name = shell
注意:调用bash执行命令,类似 cat /tmp/test.md | awk -F ‘|’’{print 1,2}’&> /tmp/example.txt这些复杂命令,即使使用shell也可能会失败。
解决办法:写到脚本中,copy到远程,执行,再把需要的结果拉回执行命令的机器
5.7.3 Script 模块 功能:在远程主机上运行ansible服务器上的脚本
范例:
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 38 39 40 41 42 192.168.135.144 | CHANGED => { "changed" : true , "rc" : 0, "stderr" : "Shared connection to 192.168.135.144 closed.\r\n" , "stderr_lines" : [ "Shared connection to 192.168.135.144 closed." ], "stdout" : "开始在远端执行\r\n等待 20秒...\r\n等待 10秒...\r\n等待 5秒...\r\n程序结束\r\n" , "stdout_lines" : [ "开始在远端执行" , "等待 20秒..." , "等待 10秒..." , "等待 5秒..." , "程序结束" ] } 192.168.135.143 | CHANGED => { "changed" : true , "rc" : 0, "stderr" : "Shared connection to 192.168.135.143 closed.\r\n" , "stderr_lines" : [ "Shared connection to 192.168.135.143 closed." ], "stdout" : "开始在远端执行\r\n等待 20秒...\r\n等待 10秒...\r\n等待 5秒...\r\n程序结束\r\n" , "stdout_lines" : [ "开始在远端执行" , "等待 20秒..." , "等待 10秒..." , "等待 5秒..." , "程序结束" ] } [root@node2-143 ansible-tmp-1746103356.844954-4270-93855660393665]# ls demo.sh
1 2 3 4 5 6 7 8 9 10 11 #!/bin/bash echo "开始在远端执行" for wait_time in 30 20 10do echo "等待 ${wait_time} 秒..." sleep $wait_time done echo "程序结束"
5.7.4 Copy模块 功能:从ansible服务器主控端复制文件到远程主机
1 2 3 4 5 6 7 8 9 10 src : 源文件 指定拷贝文件的本地路径 (如果有/ 则拷贝目录内容,比拷贝目录本身) dest: 指定目标路径 mode: 设置权限 backup: 备份源文件 content: 代替src 指定本机文件内容,生成目标主机文件 > ansible websrvs -m copy -a "src=/root/test1.sh dest=/tmp/test2.showner=wang mode=600 backup=yes" 如果目标存在,默认覆盖,此处指定先备份 > ansible websrvs -m copy -a "content='test content\nxxx' dest=/tmp/test.txt" 指定内容,直接生成目标文件
5.7.5 Fetch模块 功能:从远程主机提取文件至主控端,与copy相反,目前不支持目录,可以先打包,再提取文件
范例:
1 2 3 4 5 > ansible websrvs -m fetch -a 'src=/root/test.sh dest=/data/scripts' 会生成每个被管理主机不同编号的目录,不会发生文件名冲突 > ansible all -m shell -a 'tar jxvf test.tar.gz /root/test.sh' > ansible all -m fetch -a 'src=/root/test.tar.gz dest=/data/'
5.7.6 File模块 功能:设置文件属性
1 2 3 4 5 6 7 8 9 10 path: 要管理的文件路径 (强制添加) recurse: 递归,文件夹要用递归 src: 创建硬链接,软链接时,指定源目标,配合'state=link' 'state=hard' 设置软链接,硬链接 state: 状态 absent 缺席,删除 > ansible websrvs -m file -a 'path=/app/test.txt state=touch' 创建文件 > ansible websrvs -m file -a "path=/data/testdir state=directory" 创建目录 > ansible websrvs -m file -a "path=/root/test.sh owner=wang mode=755" 设置权限755 > ansible websrvs -m file -a 'src=/data/testfile dest=/data/testfile-link state=link' 创建软链接
5.7.7 unarchive模块 功能:解包解压缩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 unarchive:解包解压缩,有两种用法: 1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes . 2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no 常见参数: copy:默认为yes ,当copy=yes ,拷贝的文件是从ansible主机复制到远程主机上, 如果设置为copy=no,会在远程主机上寻找src源文件 src: 源路径,可以是ansible主机上的路径,也可以是远程主机上的路径, 如果是远程主机上的路径,则需要设置copy=no dest:远程主机上的目标路径 mode:设置解压缩后的文件权限 示例: ansible websrvs -m unarchive -a 'src=foo.tgz dest=/var/lib/foo' ansible websrvs -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777' ansible websrvs -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
5.7.8 archive模块 功能:
1 2 3 4 5 6 7 8 archive:打包压缩 > ansible all -m archive -a 'path=/etc/sysconfig dest=/data/sysconfig.tar.bz2 format=bz2 owner=wang mode=0777' 将远程主机目录打包 path: 指定路径 dest: 指定目标文件 format: 指定打包格式 owner: 指定所属者 mode: 设置权限
5.7.9 Hostname模块 功能:
1 2 3 Hostname:管理主机名 ansible appsrvs -m hostname -a "name=app.adong.com" 更改一组的主机名 ansible 192.168.38.103 -m hostname -a "name=app2.adong.com" 更改单个主机名
5.7.10 Cron模块 功能:
1 2 3 4 5 6 7 8 Cron:计划任务 支持时间:minute,hour,day,month,weekday > ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.16.0.1 &>/dev/null' name=Synctime" 创建任务 > ansible websrvs -m cron -a 'state=absent name=Synctime' 删除任务 > ansible websrvs -m cron -a 'minute=*/10 job=' /usr/sbin/ntpdate 172.30.0.100" name=synctime disabled=yes' 注释任务,不在生效
5.7.11 Yum模块 功能:
1 2 3 4 5 6 Yum:管理包 ansible websrvs -m yum -a 'list=httpd' 查看程序列表 ansible websrvs -m yum -a 'name=httpd state=present' 安装 ansible websrvs -m yum -a 'name=httpd state=absent' 删除 可以同时安装多个程序包
5.7.12 Service模块 功能:
1 2 3 4 5 Service:管理服务 ansible srv -m service -a 'name=httpd state=stopped' 停止服务 ansible srv -m service -a 'name=httpd state=started enabled=yes' 启动服务,并设为开机自启 ansible srv -m service -a 'name=httpd state=reloaded' 重新加载 ansible srv -m service -a 'name=httpd state=restarted' 重启服务
5.7.13 User模块 功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 User:管理用户 home 指定家目录路径 system 指定系统账号 group 指定组 remove 清除账户 shell 指定shell类型 ansible websrvs -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root' ansible websrvs -m user -a 'name=sysuser1 system=yes home=/app/sysuser1' ansible websrvs -m user -a 'name=user1 state=absent remove=yes' 清空用户所有数据 ansible websrvs -m user -a 'name=app uid=88 system=yes home=/app groups=root shell=/sbin/nologin password="$1$zfVojmPy$ZILcvxnXljvTI2PhP2Iqv1"' 创建用户 ansible websrvs -m user -a 'name=app state=absent' 不会删除家目录 安装mkpasswd yum insatll expect mkpasswd 生成口令 openssl passwd -1 生成加密口令
5.7.14 Group模块 功能:
1 2 3 4 删除用户及家目录等数据 Group:管理组 ansible srv -m group -a "name=testgroup system=yes" 创建组 ansible srv -m group -a "name=testgroup state=absent" 删除组
5.8 日志查看 1 2 3 cat /var/log/ansible.log
5.8 问题汇总 (1) [warning]警告
解决办法: 1 2 3 interpreter_python = auto_legacy_silent
(2)无法下载别人role 这种情况一般是网络不行
1 2 3 4 5 6 [root@control-141 home]# ansible-galaxy install geerlingguy.nginx - downloading role 'nginx' , owned by geerlingguy - downloading role from https://github.com/geerlingguy/ansible-role-nginx/archive/3.2.0.tar.gz [ERROR]: failed to download the file: <urlopen error timed out> [WARNING]: - geerlingguy.nginx was NOT installed successfully. ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.
解决办法: 更改国内源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 mkdir -p ~/.ansible vi ~/.ansible/galaxy.cfg [galaxy] server_list = tsinghua_galaxy, release_galaxy, automation_hub [galaxy_server.tsinghua_galaxy] url = https://mirrors.tuna.tsinghua.edu.cn/ansible-galaxy/ auth_url = https://mirrors.tuna.tsinghua.edu.cn/ansible-galaxy/api/v1/authentications/ [galaxy_server.release_galaxy] url = https://galaxy.ansible.com/ ansible-galaxy install geerlingguy.nginx