Ansible 安装、配置
Ansible 简介Ansible 基于 Python paramiko 开发无客户端、无服务端默认 SSH 连接被控主机YAML 语法编写剧本核心靠模块实现批量操作。 核心特性no agents被控机器不用装客户端仅管理节点安装 Ansibleno server无中心服务直接命令运行默认 SSH 通信支持多级编排区分两种使用模式Ad-hoc临时单行快速命令适合简单一次性操作PlaybookYAML 剧本复杂批量部署、持久复用Ansible 安装[rootserver1 ~]# yum install -y ansible-core.x86_64[rootserver1 ~]# yum install -y ansible-collection-redhat-rhel_mgmt.noarch[rootserver1 ~]# netstat -antlp | grep :22[rootserver1 ~]# cd /etc/ansible/[rootserver1 ansible]# cat ansible.cfg[rootserver1 ansible]# vim hosts显示主机清单文件的主机信息[rootserver1 ansible]# ansible-inventory --graphAnsible Ad-hoc临时的在ansible中是指需要快速执行并且不需要保存的命令。免密配置[rootserver1 ansible]# ssh-keygen[rootserver1 ansible]# cat hosts[rootserver1 ansible]# ssh-copy-id 192.168.164.161[rootserver1 ansible]# ssh-copy-id 192.168.164.162[rootserver1 ansible]# ssh-copy-id 192.168.164.171ansible后一定跟解析过的[rootserver1 ansible]# ansible centos7 -m command -a hostnamenode1 | CHANGED | rc0 node1[rootserver1 ansible]# ansible rocky9 -a hostname[rootserver1 ansible]# ansible rocky9 -a touch /tmp/test.txt[rootserver1 ansible]# ansible rocky9 -a ls -l /tmp/test.txt[rootserver1 ansible]# ansible rocky9 -a rm -f /tmp/test.txt语法[rootansible ~]# ansible pattern -m module_name -a arguments参数详解pattern: inventory文件里定义的主机组名,主机名,IP,别名等,all表示所有的主机,支持通配符,正则: - 冒号,多个组,组名之间用冒号隔开web-组名或主机名中含web的webservers[0] - webservers组中的第一台主机, -1表示最后一台主机,[1:2]表示组中的第二台和第三台all 所有-m module_name:模块名称,默认为command-a arguments:传递给模块的参数-i file_name:指定inventory文件,默认为/etc/ansible/hosts-k : 询问密码Ansible模块模块主机连通性保持连通状态[rootserver1 ansible]# ansible web -m ping192.168.164.162 | SUCCESS {ansible_facts: {discovered_interpreter_python: /usr/bin/python3},changed: false,ping: pong}Ansible Playbook剧本playbook严格缩进Playbook 组成Target section定义将要执行 playbook的远程主机组 - hostsVariable section(可选)定义 playbook运行时需要使用的变量- varsTask section定义将要在远程主机上执行的任务列表 - tasksHandler section可选定义 task执行完成以后需要调用的任务 - handlers语法规则文件的第一行应该以---(三个连字符)开始表明YAML文件的开始。YAML中的 列表元素 以”-”开头然后紧跟着一个空格后面为元素内容。同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。play中hostsvariablesrolestasks等对象的表示方法都是键值中间以:分隔表示:后面还要增加一个空格。检测语法检测[rootserver1 ansible]# ansible-playbook --syntax-check /etc/ansible/test.ymlplaybook: /etc/ansible/test.yml测试运行[rootserver1 ansible]# ansible-playbook -C /etc/ansible/test.yml基本使用案例创建普通用户[rootserver1 ~]# ansible-config dump[rootserver1 ~]# useradd testuser[rootserver1 ~]# su - testuser[testuserserver1 ~]$ pwd[testuserserver1 ~]$ ansible-config dump[rootserver2 ~]# useradd testuser[rootserver2 ~]# passwd testuser[testuserserver1 ~]$ ssh-keygen[testuserserver1 ~]$ ssh-copy-id testuserserver2[testuserserver1 ~]$ ssh testuserserver2 记得退出ssh连接[testuserserver1 ~]$ ansible web -m ping设置visudo[rootserver2 ~]# visudo创建目录[testuserserver1 ~]$ mkdir ansible[testuserserver1 ~]$ cd ansible/[testuserserver1 ansible]$ ls[testuserserver1 ansible]$ vim apache.yml[rootserver1 ~]# ansible-doc yum 查看examplesq退出注意权限[testuserserver1 ansible]$ ansible-playbook --syntax-check apache.yml[testuserserver1 ansible]$ ansible-playbook -C apache.yml[testuserserver1 ansible]$ ansible-playbook apache.yml[testuserserver1 ansible]$ ansible-playbook apache.yml 重复命令无影响[testuserserver1 ansible]$ vim apache.yml[rootserver1 ~]# ansible-doc service[rootserver1 ~]# ansible-doc copy[testuserserver1 ansible]$ ansible-playbook apache.yml[testuserserver1 ansible]$ curl server2远程下载[testuserserver1 ansible]$ ansible-config init --disable ansible.cfg[testuserserver1 ansible]$ ls[testuserserver1 ansible]$ ansible-config dump[testuserserver1 ansible]$ vim hosts[web]192.168.164.162[db]192.168.164.171[lamp:children]]webdb[testuserserver1 ansible]$ vim ansible.cfginventory./hosts[testuserserver1 ansible]$ ansible-config dump | grep hostsDEFAULT_HOST_LIST(/home/testuser/ansible/ansible.cfg) [/home/testuser/ansible/hosts][testuserserver1 ansible]$ ansible-inventory --graph[testuserserver1 ansible]$ ansible-inventory --list[rootnode1 ~]# useradd testuser[rootnode1 ~]# passwd testuser[rootnode1 ~]# visudo[testuserserver1 ansible]$ ssh-copy-id testusernode1[testuserserver1 ansible]$ ansible lamp -m ping[testuserserver1 ansible]$ vim ansible.cfg全局定义后playbook不需要再定义become控制机身份不一样时指定remote_user[testuserserver1 ansible]$ vim ansible.cfgremote_usertestuser端口[testuserserver1 ansible]$ vim apache.yml- name: Ensure the default Apache port is 8080ansible.builtin.lineinfile:path: /etc/httpd/conf/httpd.confregexp: ^Listen insertafter: ^#Listen line: Listen 8080[testuserserver1 ansible]$ ansible-playbook apache.yml服务重启生效[rootserver2 ~]# systemctl restart httpd[rootserver2 ~]# netstat -antlp | grep :8080playbook一键实现重启使用触发器[testuserserver1 ansible]$ vim apache.yml加入变量[testuserserver1 ansible]$ vim apache.yml[testuserserver1 ansible]$ ansible web -m setup -a filteransible_hostname192.168.164.162 | SUCCESS {ansible_facts: {ansible_hostname: server2,discovered_interpreter_python: /usr/bin/python3},changed: false}[testuserserver1 ansible]$ ansible-playbook apache.yml[testuserserver1 ansible]$ curl server2server2[testuserserver1 ansible]$ vim apache.yml[testuserserver1 ansible]$ ansible-playbook apache.yml[testuserserver1 ansible]$ vim apache.yml[testuserserver1 ansible]$ ansible-playbook apache.yml变量[testuserserver1 ansible]$ vim apache.ymlvars:- http_port: 80[testuserserver1 ansible]$ ansible-playbook apache.yml如果多主机可先注释掉vars修改hosts[testuserserver1 ansible]$ vim hosts[web]192.168.164.162 http_port80[db]192.168.164.171 http_port8080[lamp:children]webdb[testuserserver1 ansible]$ ansible-playbook apache.ymltemplate[testuserserver1 ansible]$ vim apache.yml[testuserserver1 ansible]$ scp server2:/etc/httpd/conf/httpd.conf .[testuserserver1 ansible]$ mv httpd.conf httpd.conf.j2[testuserserver1 ansible]$ vim httpd.conf.j2Listen {{ http_port }}[testuserserver1 ansible]$ vim hosts[web]192.168.164.162[db]192.168.164.171[lamp:children]webdb[lamp:vars]http_port80[testuserserver1 ansible]$ ansible-playbook apache.yml高可用keepalived配置[testuserserver1 ansible]$ cd[rootserver1 ~]# cd /etc/ansible[rootserver1 ansible]# passwd testuser[rootserver1 ansible]# su - testuser[testuserserver1 ~]$ ssh-copy-id 192.168.164.161[testuserserver1 ~]$ logout[rootserver1 ansible]# visudotestuser ALL(ALL) NOPASSWD: ALL[testuserserver1 ~]$ cd ansible/[testuserserver1 ansible]$ vim hosts[testuserserver1 ansible]$ cp apache.yml keepalived.yml[rootserver1 ~]# yum install -y keepalived[rootserver1 ~]# ll /etc/keepalived/keepalived.conf-rw-r--r-- 1 root root 3550 Nov 2 2025 /etc/keepalived/keepalived.conf[testuserserver1 ansible]$ vim keepalived.yml[testuserserver1 ansible]$ cp /etc/keepalived/keepalived.conf .[testuserserver1 ansible]$ mv keepalived.conf keepalived.conf.j2[testuserserver1 ansible]$ vim keepalived.conf.j2[testuserserver1 ansible]$ ansible-playbook keepalived.yml[testuserserver1 ansible]$ sudo systemctl status keepalived[rootserver2 ~]# systemctl status keepalived批量化创建loop传递数组[testuserserver1 ansible]$ vim user.yml[testuserserver1 ansible]$ vim ansible.cfgdeprecation_warningsfalse[testuserserver1 ansible]$ ansible-playbook user.yml[rootnode1 ~]# cat /etc/shadowtags标签[testuserserver1 ansible]$ ansible-playbook apache.yml --list-tasks[testuserserver1 ansible]$ vim apache.yml[testuserserver1 ansible]$ ansible-playbook apache.yml --list-tags执行标签[testuserserver1 ansible]$ ansible-playbook apache.yml --tagst1跳过标签[testuserserver1 ansible]$ ansible-playbook apache.yml --skip-tagst1变量factslineinfile追加解析[testuserserver1 ansible]$ ansible db -m setup setup模块[testuserserver1 ansible]$ vim lineinfile.yml[testuserserver1 ansible]$ ansible-playbook lineinfile.yml[rootnode1 ~]# cat /etc/hosts魔术变量循环[testuserserver1 ansible]$ vim hosts[webservers]192.168.164.161192.168.164.162192.168.164.171[testuserserver1 ansible]$ vim groups.yml删除解析[testuserserver1 ansible]$ vim test.j2[rootserver2 ~]# vim /etc/hosts[rootserver3 ~]# vim /etc/hosts魔术变量for循环[testuserserver1 ansible]$ vim test.j2[testuserserver1 ansible]$ cat /etc/hosts模板haproxyserver1作为调度器server2、node1作为web-server[rootserver1 ansible]# yum install -y haproxy[testuserserver1 ansible]$ vim hosts[webservers]192.168.164.162192.168.164.171[webservers:vars]http_port80[haproxy]server1[haproxy:vars]http_port80关闭keepalived[testuserserver1 ansible]$ vim keepalived.yml[testuserserver1 ansible]$ ansible-playbook keepalived.yml --tagst1[testuserserver1 ansible]$ vim haproxy.yml---- hosts: haproxy,webserverstasks:- name: deplo haproxyblock:- name: install haproxyansible.builtin.yum:name: haproxystate: present- name: configure the haproxyansible.builtin.template:src: haproxy.cfg.j2dest: /etc/haproxy/haproxy.cfgnotify: restart service haproxy- name: enable service haproxyansible.builtin.service:name: haproxystate: startedenabled: yeswhen: ansible_hostname server1- name: deploy apacheblock:- name: Install the Apacheansible.builtin.yum:name: httpdstate: present- name: Ensure the default Apache port is {{ http_port }}ansible.builtin.template:src: httpd.conf.j2dest: /etc/httpd/conf/httpd.confnotify: restart service httpd- name: Start service httpdansible.builtin.service:name: httpdstate: startedenabled: yes- name: creat index.htmlansible.builtin.copy:content: {{ ansible_hostname }}\ndest: /var/www/html/index.htmlwhen: webservers in group_nameshandlers:- name: restart service haproxyansible.builtin.service:name: haproxystate: restarted- name: restart service httpdansible.builtin.service:name: httpdstate: restarted[testuserserver1 ansible]$ vim httpd.conf.j2Listen {{ http_port }}[testuserserver1 ansible]$ cp /etc/haproxy/haproxy.cfg .[testuserserver1 ansible]$ mv haproxy.cfg haproxy.cfg.j2[testuserserver1 ansible]$ vim haproxy.cfg.j2[testuserserver1 ansible]$ ansible-playbook --syntax-check haproxy.ymlplaybook: haproxy.yml[testuserserver1 ansible]$ ansible-playbook haproxy.yml验证浏览器访问http://192.168.164.16180再创建一台虚拟机node2[rootnode2 ~]# useradd testuser[rootnode2 ~]# passwd testuser[rootnode2 ~]# visudoroot ALL(ALL) ALLtestuser ALL(ALL) NOPASSWD: ALL解析[rootnode2 ~]# vim /etc/hosts[rootserver1 ansible]# vim /etc/hosts[testuserserver1 ansible]$ vim hosts[webservers]server2node1node2[testuserserver1 ansible]$ ansible-playbook haproxy.yml验证浏览器访问http://192.168.164.16180功能集合[testuserserver1 ansible]$ ansible-galaxy collection install ansible.mysql[testuserserver1 ansible]$ ansible-galaxy collection listansible_playbook层级结构ansible-vault --help 查看帮助加密[testuserserver1 ansible]$ vim user.yml[testuserserver1 ansible]$ vim userlist.yml[testuserserver1 ansible]$ ansible-playbook --syntax-check user.yml[testuserserver1 ansible]$ ansible-playbook user.yml加密[testuserserver1 ansible]$ ansible-vault encrypt userlist.yml[testuserserver1 ansible]$ cat userlist.yml 无法查看解密[testuserserver1 ansible]$ ansible-vault decrypt userlist.yml查看[testuserserver1 ansible]$ ansible-vault view userlist.yml修改密码[testuserserver1 ansible]$ ansible-vault rekey userlist.yml编辑[testuserserver1 ansible]$ ansible-vault edit userlist.yml执行加密后的剧本加参数--ask-vault-pass[testuserserver1 ansible]$ ansible-playbook user.yml --ask-vault-pass变量文件层级结构[testuserserver1 ansible]$ vim hosts[web]server2[db]node1[testuserserver1 ansible]$ mkdir host_vars[testuserserver1 ansible]$ cd host_vars/[testuserserver1 host_vars]$ mkdir node1[testuserserver1 host_vars]$ cd node1/[testuserserver1 node1]$ cp ../../userlist.yml vault[testuserserver1 node1]$ ansible-vault encrypt vault[testuserserver1 node1]$ cd ..[testuserserver1 host_vars]$ cd ..[testuserserver1 ansible]$ vim user.yml#vars_files:# - userlist.yml[testuserserver1 ansible]$ ansible-playbook user.yml --ask-vault-passapache[testuserserver1 ansible]$ vim apache.yml- hosts: webservers[testuserserver1 ansible]$ vim hosts[testuserserver1 ansible]$ mkdir group_vars[testuserserver1 ansible]$ cd group_vars/[testuserserver1 group_vars]$ mkdir webservers/[testuserserver1 group_vars]$ cd webservers/[testuserserver1 webservers]$ vim vars---http_port 80[testuserserver1 webservers]$ cd ..[testuserserver1 group_vars]$ cd ..[testuserserver1 ansible]$ ansible-playbook --syntax-check apache.ymlplaybook: apache.yml[testuserserver1 ansible]$ ansible-playbook apache.yml --ask-vault-pass剧本参数滚动部署serial: 1全局并行进程数ansible.cfg[defaults] forks 10或者ansible-playbook apache.yml -f 10限制最大并发throttle: 3剧本安装zabbix参考网站galaxy.ansible.comansible-galaxy collection install ansible.posixvim zabbix.ymlansible-playbook --syntax-check zabbix.yml执行完 playbook访问http://192.168.164.162/zabbix进入 zabbix 初始化向导默认账号Admin密码zabbixansible roles角色apache_role.yml配置role读取路径[testuserserver1 ansible]$ vim ansible.cfgroles_path./ansible[testuserserver1 ansible]$ cd roles/[testuserserver1 ansible]$ cd roles/[testuserserver1 roles]$ ansible-galaxy role --help添加role[testuserserver1 roles]$ ansible-galaxy role init apache- Role apache was created successfully查看结构[testuserserver1 roles]$ sudo yum install -y tree[testuserserver1 roles]$ cd apache/[testuserserver1 apache]$ tree .拆分apache.yml[testuserserver1 apache]$ cd tests/[testuserserver1 tests]$ cat test.yml[testuserserver1 apache]$ rm -rf tests/[testuserserver1 apache]$ ls另开终端[rootserver1 ~]# su - testuser[testuserserver1 ~]$ cd ansible/[testuserserver1 ansible]$ vim apache.yml配置角色apache[testuserserver1 apache]$ cd tasks/[testuserserver1 tasks]$ vim main.yml[testuserserver1 tasks]$ cd ..[testuserserver1 apache]$ cd handlers/[testuserserver1 handlers]$ vim main.yml[testuserserver1 handlers]$ cd ..[testuserserver1 apache]$ cd defaults/[testuserserver1 defaults]$ vim main.yml---http_port: 80[testuserserver1 defaults]$ cd /ansible/[testuserserver1 ansible]$ ansible-inventory --graph[testuserserver1 ansible]$ mv host_vars/ group_vars /tmp/[testuserserver1 ansible]$ ansible-inventory --graph[testuserserver1 ansible]$ ansible-playbook apache_role.yml改变端口读取优先级[testuserserver1 ansible]$ vim apache_role.ymlhttp_port: 8080[testuserserver1 ansible]$ ansible-playbook apache_role.yml[rootserver2 ~]# netstat -anplt | grep :8080配置防火墙[testuserserver1 ansible]$ vim apache_role.yml[testuserserver1 ansible]$ ansible-playbook apache_role.yml另开终端[rootserver1 ~]# cd /home/testuser/ansible/[rootserver1 ansible]# cat apache.yml[testuserserver1 ansible]$ vim apache_role.yml[testuserserver1 ansible]$ ansible-playbook apache_role.yml普通用户安装避免环境混乱[testuserserver1 ansible]$ ansible-galaxy collection install ansible.posix[testuserserver1 ansible]$ ansible-galaxy collection list[testuserserver1 ansible]$ ansible-doc -l套用模板[testuserserver1 ansible]$ ansible-doc ansible.posix.firewalld[testuserserver1 ansible]$ vim apache_role.yml[testuserserver1 ansible]$ ansible-playbook apache_role.ymlselinux需要重启生效[testuserserver1 ansible]$ ansible-doc ansible.posix.selinux安装系统角色[testuserserver1 ansible]$ yum search role[testuserserver1 ansible]$ sudo yum install -y rhel-system-roles.noarch[testuserserver1 ansible]$ rpm -ql rhel-system-rolesroles_path./ansible:/usr/share/ansible/roles[testuserserver1 ansible]$ ansible-galaxy role list系统角色路径[testuserserver1 ~]$ cd /usr/share/doc/[testuserserver1 doc]$ cd rhel-system-roles/时间同步[testuserserver1 rhel-system-roles]$ cd timesync/[testuserserver1 timesync]$ cp example-single-pool-playbook.yml ~/ansible/[testuserserver1 timesync]$ cd ~/ansible/[testuserserver1 ansible]$ mv example-single-pool-playbook.yml timesync.yml[testuserserver1 ansible]$ vim timesync.yml---- name: system timesynchosts: webserversvars:timesync_ntp_servers:- hostname: ntp1.aliyun.compool: trueiburst: trueroles:- rhel-system-roles.timesync[testuserserver1 ansible]$ ansible-playbook timesync.yml剧本导入用于linux版本不同场景导入import_playbook[testuserserver1 ansible]$ vim apache_role.yml- name: timesync palaybookimport_playbook: timesync.yml[testuserserver1 ansible]$ ansible-playbook apache_role.ymlselinuxnode1上[rootnode1 ~]# vim /etc/httpd/conf/httpd.confListen 8000server1上[testuserserver1 ~]$ cd /usr/share/doc/[testuserserver1 doc]$ cd rhel-system-roles/[testuserserver1 rhel-system-roles]$ cd selinux/[testuserserver1 selinux]$ cp example-selinux-playbook.yml ~/ansible/[testuserserver1 ~]$ cd ~/ansible/[testuserserver1 ansible]$ mv example-selinux-playbook.yml selinux.yml[testuserserver1 ansible]$ vim selinux.yml[testuserserver1 ansible]$ vim apache_role.yml[testuserserver1 ansible]$ ansible-playbook apache_role.yml[rootnode1 ~]# firewall-cmd --list-all角色rolenginxserver2[rootserver2 ~]# systemctl disable --now zabbix-server[rootserver2 ~]# systemctl disable --now zabbix-agent[rootserver2 ~]# systemctl disable --now php-fpm[rootserver2 ~]# systemctl disable --now httpd[rootserver2 ~]# systemctl disable --now mysqld网站Ansible Galaxy[testuserserver1 ~]$ ansible-galaxy role install nginxinc.nginx[testuserserver1 ~]$ ansible-galaxy role install geerlingguy.nginxrole位置[testuserserver1 ~]$ ansible-galaxy role list[testuserserver1 ~]$ cd .ansible/roles[testuserserver1 roles]$ cd geerlingguy.nginx[testuserserver1 geerlingguy.nginx]$ ls[testuserserver1 geerlingguy.nginx]$ cd meta[testuserserver1 meta]$ cat main.yml[testuserserver1 meta]$ cd ..[testuserserver1 geerlingguy.nginx]$ cd vars[testuserserver1 vars]$ ls另开终端ansible.cfg配置[testuserserver1 ansible]$ vim ansible.cfgroles_path./ansible:/usr/share/ansible/roles:/home/testuser/.ansible/roles[testuserserver1 ansible]$ vim nginx.yml---- hosts: server2roles:- role: geerlingguy.nginx[testuserserver1 ansible]$ ansible-playbook nginx.yml --list-tasks[testuserserver1 ansible]$ ansible-playbook nginx.yml[testuserserver1 ansible]$ curl server2server2[rootserver2 ~]# rpm -qa|grep nginx注意生产不推荐直接使用删除角色removegitee创建gitee账号[testuserserver1 ~]$ cd .ssh/[testuserserver1 .ssh]$ cat id_rsa.pub上传公钥新建仓库server1上初始化[testuserserver1 ~]$ cd ansible/roles/apache/[testuserserver1 apache]$ git init[testuserserver1 apache]$ git config --global user.name uugit config --global user.email 17456376uu_2026user.noreply.gitee.com[testuserserver1 apache]$ git add .[testuserserver1 apache]$ git commit -m ansible-roleapache提交到本地[testuserserver1 apache]$ ls .git/[testuserserver1 apache]$ git remote add origin gitgitee.com:uu_2026/ansible.git ssh方式免密[testuserserver1 apache]$ git push -u origin master下载role[testuserserver1 apache]$ cd ..[testuserserver1 roles]$ vim requirements.yml---- src: gitgitee.com:uu_2026/ansible.gitscm: gitversion: mastername: apache[testuserserver1 roles]$ ansible-galaxy role install -r roles/requirements.yml -p roles/另一种方式直接克隆修改名字即可