1 ansible 常用指令总结,并附有相关示例。

  • /usr/bin/ansible 主程序,临时命令执行工具
  • /usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man
  • /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具,相当于脚本
  • /usr/bin/ansible-pull 远程执行命令的工具
  • /usr/bin/ansible-vault 文件加密工具
  • /usr/bin/ansible-console 基于Console界面与用户交互的执行工具
  • /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台

利用ansible实现管理的主要方式:

  • Ansible Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景
  • Ansible playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程

ansible 使用前准备

ansible 相关工具大多数是通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能

建议:使用此工具前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点

1.1 ansible-doc

此工具用来显示模块帮助,相当于man

格式

ansible-doc [options] [module...]-l, --list #列出可用模块-s, --snippet #显示指定模块的playbook片段

范例:

#列出所有模块ansible-doc -l#查看指定模块帮助用法ansible-doc ping#查看指定模块帮助用法ansible-doc -s ping

范例: 查看指定的插件

[13:38:40 root@ansible-rocky ~]$ ansible-doc -t connection -l[13:39:08 root@ansible-rocky ~]$ ansible-doc -t lookup -l

1.2 ansible1.2.1 Ansible Ad-Hoc 介绍

Ansible Ad-Hoc 的执行方式的主要工具就是 ansible
特点: 一次性的执行,不会保存执行命令信息,只适合临时性或测试性的任务

1.2.2 ansible 命令用法

格式:

ansible  [-m module_name] [-a args]

选项说明:

--version                               #显示版本-m module                               #指定模块,默认为command-v                                      #详细过程 -vv -vvv更详细--list-hosts                            #显示主机列表,可简写 --list-C, --check                             #检查,并不执行-T, --timeout=TIMEOUT                   #执行命令的超时时间,默认10s-k, --ask-pass                          #提示输入ssh连接密码,默认Key验证-u, --user=REMOTE_USER                  #执行远程执行的用户,默认root-b, --become                            #代替旧版的sudo实现通过sudo机制实现提升权限--become-user=USERNAME                  #指定sudo的run as用户,默认为root-K, --ask-become-pass                   #提示输入sudo时的口令-f FORKS, --forks FORKS                 #指定并发同时执行ansible任务的主机数-i INVENTORY, --inventory INVENTORY     #指定主机清单文件

范例:

#先打通基于key验证#以yanlinux用户执行ping存活检测[14:28:30 yanlinux@ansible-rocky ~]$ ansible all -m ping -u yanlinux10.0.0.18 | SUCCESS => {    "ansible_facts": {        "discovered_interpreter_python": "/usr/libexec/platform-python"    },    "changed": false,    "ping": "pong"}10.0.0.102 | SUCCESS => {    "ansible_facts": {        "discovered_interpreter_python": "/usr/bin/python3"    },    "changed": false,    "ping": "pong"}10.0.0.7 | SUCCESS => {    "ansible_facts": {        "discovered_interpreter_python": "/usr/bin/python"    },    "changed": false,    "ping": "pong"}#以yanlinux sudo至root执行命令##没有添加sudo授权之前[14:36:46 yanlinux@ansible-rocky ~]$ ansible all -a 'ls /root'10.0.0.18 | FAILED | rc=2 >>ls: cannot open directory '/root': Permission deniednon-zero return code10.0.0.102 | FAILED | rc=2 >>ls: cannot open directory '/root': Permission deniednon-zero return code10.0.0.7 | FAILED | rc=2 >>ls: cannot open directory /root: Permission deniednon-zero return code##在所有被控制主机上都加上suod授权[14:30:46 root@ansible-rocky ~]$ echo "yanlinux    ALL=(ALL)   NOPASSWD: ALL" >> /etc/sudoers[14:37:01 yanlinux@ansible-rocky ~]$ ansible all -a 'ls /root' -b10.0.0.102 | CHANGED | rc=0 >>init_os.shsnap10.0.0.7 | CHANGED | rc=0 >>anaconda-ks.cfginit_os.sh10.0.0.18 | CHANGED | rc=0 >>anaconda-ks.cfginit_os.sh##所有被管理主机上创建用户magedu[14:37:05 yanlinux@ansible-rocky ~]$ ansible all -a 'useradd magedu' -b10.0.0.102 | CHANGED | rc=0 >>10.0.0.18 | CHANGED | rc=0 >>10.0.0.7 | CHANGED | rc=0 >>[14:39:46 yanlinux@ansible-rocky ~]$ ansible all -a 'getent passwd magedu' -b10.0.0.7 | CHANGED | rc=0 >>magedu:x:1002:1002::/home/magedu:/bin/bash10.0.0.102 | CHANGED | rc=0 >>magedu:x:1001:1001::/home/magedu:/bin/sh10.0.0.18 | CHANGED | rc=0 >>magedu:x:1001:1001::/home/magedu:/bin/bash

范例: 并发执行控制

#并发是1一个主机一个主机的执行,一条条返回结果[14:42:47 root@ansible-rocky ~]$ ansible all -a 'sleep 5' -f1#并发是10,同时10个主机执行命令,返回结果[14:42:47 root@ansible-rocky ~]$ ansible all -a 'sleep 5' -f10

范例: 使用普通用户连接远程主机执行代替另一个用户身份执行操作

#在被管理主机上创建用户并sudo授权[14:34:00 root@ubuntu2004 ~]$ useradd magedu[14:34:29 root@ubuntu2004 ~]$ echo magedu:centos1 |chpasswd#以yanlinux的用户连接用户并利用sudo代表magedu执行whoami命令[14:58:37 yanlinux@ansible-rocky ~]$ ansible all -a 'whoami' -b --become-user=magedu10.0.0.18 | CHANGED | rc=0 >>magedu10.0.0.7 | CHANGED | rc=0 >>magedu

1.3 ansible-console

此工具可交互执行命令,支持tab,ansible 2.0+新增
提示符格式:

执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$

常用子命令:

  • 设置并发数: forks n 例如: forks 10
  • 切换组: cd 主机组 例如: cd web
  • 列出当前组主机列表: list
  • 列出所有的内置命令: ?或help

范例

[15:24:28 root@ansible-rocky ~]$ ansible-console Welcome to the ansible console. Type help or ? to list commands.root@all (3)[f:5]$ ping10.0.0.18 | SUCCESS => {    "ansible_facts": {        "discovered_interpreter_python": "/usr/libexec/platform-python"    },    "changed": false,    "ping": "pong"}10.0.0.102 | SUCCESS => {    "ansible_facts": {        "discovered_interpreter_python": "/usr/bin/python3"    },    "changed": false,    "ping": "pong"}10.0.0.7 | SUCCESS => {    "ansible_facts": {        "discovered_interpreter_python": "/usr/bin/python"    },    "changed": false,    "ping": "pong"}root@all (3)[f:5]$ list10.0.0.1810.0.0.710.0.0.102root@all (3)[f:5]$ cd websrvsroot@websrvs (2)[f:5]$ list10.0.0.1810.0.0.7root@websrvs (2)[f:5]$ forks 10root@websrvs (2)[f:10]$ cd appsrvsroot@appsrvs (2)[f:10]$ list10.0.0.10210.0.0.18

1.4 ansible-playbook

此工具用于执行编写好的 playbook 任务
范例:

[15:27:57 root@ansible-rocky ~]$ vi hello.yml---#hello world yml file- hosts: websrvs  remote_user: root  gather_facts: no  tasks:    - name: hello world      command: /usr/bin/wall hello world[15:30:12 root@ansible-rocky ~]$ ansible-playbook hello.yml PLAY [websrvs] ****************************************************************************************TASK [hello world] ************************************************************************************changed: [10.0.0.18]changed: [10.0.0.7]PLAY RECAP ********************************************************************************************10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

1.5 ansible-vault

此工具可以用于加密解密yml文件

格式:

ansible-vault [create|decrypt|edit|encrypt|rekey|view]

范例:

#1 加密[15:31:01 root@ansible-rocky ~]$ ansible-vault encrypt hello.yml New Vault password: Confirm New Vault password: Encryption successful##查看文件内容[15:38:15 root@ansible-rocky ~]$ cat hello.yml $ANSIBLE_VAULT;1.1;AES256653237666238316365636361326233336239326334613965633837643330373965636337663632313335646336346136626231353133623566626166626336380a306630643338353031353739353538623739303066366334306535373635343762313238396431313763356533666566346163656630636236663364343461610a3833656435346465643162613261663162333930393861343634363131386332393966353766646264623361326264663730613062633633623932373762383339373566636436336334316666326265356166326163373039616533353564353964396266376637363037353338376236396562623039663637663566303764666664633633383535356236356331376163353833336533326364376235326432656332636239366331653866653061666464343866643537316261616430313761323030343165666330326537653430333764363834326566333666316133386465663334633530356162663963663666626438393534316537363534656262616234333437356635346638313263663265373032346536653135353163376162393030313864333761316261306233323763356639663562393535343165#2 解密[15:38:18 root@ansible-rocky ~]$ ansible-vault decrypt hello.yml Vault password: Decryption successful[15:39:50 root@ansible-rocky ~]$ cat hello.yml ---#hello world yml file- hosts: websrvs  remote_user: root  gather_facts: no  tasks:    - name: hello world      command: /usr/bin/wall hello world      #3 查看加密后的yml文件内容[15:41:44 root@ansible-rocky ~]$ ansible-vault view hello.yml Vault password: ---#hello world yml file- hosts: websrvs  remote_user: root  gather_facts: no  tasks:    - name: hello world      command: /usr/bin/wall hello world#4 编辑加密文件[15:41:50 root@ansible-rocky ~]$ ansible-vault edit hello.yml Vault password:             #输入密码后进入vim编辑器进行编辑#5 修改口令[15:44:53 root@ansible-rocky ~]$ ansible-vault rekey hello.yml Vault password:    #先前的口令New Vault password:  #修改为的口令Confirm New Vault password:  #再确认一遍Rekey successful#6 创建加密新文件[15:46:31 root@ansible-rocky ~]$ ansible-vault create new.ymlNew Vault password: Confirm New Vault password:#7 交互式输入密码来执行加密文件[15:46:46 root@ansible-rocky ~]$ ansible-playbook --ask-vault-pass hello.yml Vault password: PLAY [websrvs] ****************************************************************************************TASK [hello world] ************************************************************************************changed: [10.0.0.18]changed: [10.0.0.7]PLAY RECAP ********************************************************************************************10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 #8 从文件中读取密码[15:52:56 root@ansible-rocky ~]$ ansible-playbook --vault-password-file pass.txt hello.yml PLAY [websrvs] ****************************************************************************************TASK [hello world] ************************************************************************************changed: [10.0.0.18]changed: [10.0.0.7]PLAY RECAP ********************************************************************************************10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0#9 从配置文件中添加密码文件[15:53:33 root@ansible-rocky ~]$ vi /etc/ansible/ansible.cfg#添加以下一行信息ault-password-file=pass.txt[15:58:58 root@ansible-rocky ~]$ ansible-playbook hello.yml PLAY [websrvs] ****************************************************************************************TASK [hello world] ************************************************************************************changed: [10.0.0.18]changed: [10.0.0.7]PLAY RECAP ********************************************************************************************10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

1.6 ansible-galaxy

Galaxy 是一个免费网站, 类似于github网站, 网站上发布了很多的共享的roles角色。

Ansible 提供了ansible-galaxy命令行工具连接 https://galaxy.ansible.com 网站下载相应的roles, 进行init(初始化、search( 查拘、install(安装、 remove(移除)等操作。

范例

#搜索项目[16:05:04 root@ansible-rocky ~]$ ansible-galaxy search lampFound 100 roles matching your search: Name                                      Description ----                                      ----------- abhiarun_94.apache_lamp                   your role description adelaidearnauld.galaxy-lamp               your description adelaidearnauld.lamp_compose              your description ajish_antony.ansible_lamp                 your role description AlexanderAllen.Liara                      The sexiest toolkit for LAMP hackers. alphinaugustine.ansible_role              your description amtega.horde                              Setup horde ...... #2 列出所有已安装的galaxy[16:06:32 root@ansible-rocky ~]$ ansible-galaxy list# /usr/share/ansible/roles# /etc/ansible/roles#3 安装galaxy,默认下载到~/.ansible/roles[16:14:06 root@ansible-rocky ~]$ ansible-galaxy install 想要安装的galaxy#删除ansible-galaxy remove 

2 总结ansible role目录结构及文件用途。

roles目录结构:

├── playbook1.yml├── playbook2.yml├── roles/│ ├── project1/│ │├── tasks/│ │├── files/│ │├── vars/│ │├── templates/│ │├── handlers/│ │├── default/│ │└── meta/│ ├── project2/│ │├── tasks/│ │├── files/│ │├── vars/│ │├── templates/│ │├── handlers/│ │├── default/│ │└── meta/

Roles各目录作用

roles/project/ :项目名称,有以下子目录

  • files/ :存放由copyscript模块等调用的文件
  • templates/template模块查找所需要模板文件的目录
  • tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
  • handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过include进行包含
  • vars/定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含,也可以通过项目目录中的group_vars/all定义变量,从而实现角色通用代码和项目数据的分离
  • meta/定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
  • default/:设定默认变量时使用此目录中的main.yml文件,比vars优先级低

3 使用ansible playbook实现一个mysql角色。

#mysql角色目录[18:16:16 root@ansible-rocky opt]$ tree.├── ansible.cfg├── hosts├── mysql_role.yml└── roles  └── mysql    ├── files    │ └── mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz    ├── tasks    │ └── main.yml    └── templates        └── my.cnf.j2        #定义主机及变量[18:22:50 root@ansible-rocky opt]$ tail -n9 hosts [dbsrvs:vars]db_group=mysqldb_gid=306db_user=mysqldb_uid=306db_version=8.0.31db_file="mysql-{{db_version}}-linux-glibc2.12-x86_64.tar.xz"db_data_dir="/data/mysql"db_root_passwd="lgq123456**"#下载准备mysql源文件包[18:22:54 root@ansible-rocky opt]$ ls roles/mysql/files/mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz#创建task文件[18:24:40 root@ansible-rocky opt]$ cat roles/mysql/tasks/main.yml - name: install dependent package  yum:    name: "{{ item }}"  loop:    - libaio    - numactl-libs- name: create mysql group  group: name={{db_group}} gid={{db_gid}}- name: create mysql user  user: name={{db_user}} uid={{db_uid}} system=yes shell="/sbin/nologin" create_home=no group={{db_group}}- name: copy tar to remote host and file mode  unarchive:    src: "{{ db_file }}"    dest: "/usr/local/"    owner: root    group: root- name: create lingfile /usr/local/mysql  file:    src: "/usr/local/mysql-{{ db_version }}-linux-glibc2.12-x86_64"    dest: "/usr/local/mysql"    state: link- name: path file  copy:    content: "PATH=/usr/local/mysql/bin:$PATH"    dest: "/etc/profile.d/mysql.sh"- name: config file  template:    src: my.cnf.j2    dest: "/etc/my.cnf"- name: create directory  file:    name: "/data"    state: directory- name: init mysql data  shell:    cmd: "/usr/local/mysql/bin/mysqld --initialize-insecure --user={{ db_user }} --datadir={{ db_data_dir }}"  tags:    - init- name: service script  copy:    src: "/usr/local/mysql/support-files/mysql.server"    dest: "/etc/init.d/mysqld"    remote_src: yes    mode: '+x'- name: start service  shell:    cmd: chkconfig --add mysqld;chkconfig mysqld on;service mysqld start- name: change root password  shell:    cmd: "/usr/local/mysql/bin/mysqladmin -uroot password {{ db_root_passwd }}"        #准备MySQL 配置文件模板[18:25:25 root@ansible-rocky opt]$ cat roles/mysql/templates/my.cnf.j2 [mysqld]server-id=1log-bindatadir={{ db_data_dir }}socket={{ db_data_dir }}/mysql.socklog-error={{ db_data_dir }}/mysql.logpid-file={{ db_data_dir }}/mysql.pid[client]socket={{ db_data_dir }}/mysql.sock#准备MySQL角色playbook文件[18:25:38 root@ansible-rocky opt]$ cat mysql_role.yml - hosts: dbsrvs  remote_user: root  gather_facts: no  roles:    - mysql    #部署MySQL[18:26:34 root@ansible-rocky opt]$ ansible-playbook -i hosts mysql_role.ymlPLAY [dbsrvs] *****************************************************************************************TASK [mysql : install dependent package] **************************************************************ok: [10.0.0.38] => (item=libaio)ok: [10.0.0.38] => (item=numactl-libs)TASK [mysql : create mysql group] *********************************************************************changed: [10.0.0.38]TASK [mysql : create mysql user] **********************************************************************changed: [10.0.0.38]TASK [mysql : copy tar to remote host and file mode] **************************************************changed: [10.0.0.38]TASK [mysql : create lingfile /usr/local/mysql] *******************************************************changed: [10.0.0.38]TASK [mysql : path file] ******************************************************************************changed: [10.0.0.38]TASK [mysql : config file] ****************************************************************************changed: [10.0.0.38]TASK [mysql : create directory] ***********************************************************************ok: [10.0.0.38]TASK [mysql : init mysql data] ************************************************************************changed: [10.0.0.38]TASK [mysql : service script] *************************************************************************changed: [10.0.0.38]TASK [mysql : start service] **************************************************************************changed: [10.0.0.38]TASK [mysql : change root password] *******************************************************************changed: [10.0.0.38]PLAY RECAP ********************************************************************************************10.0.0.38                  : ok=12   changed=10   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4 基于角色完成部署LNMP架构,并支持一键发布,回滚应用。同时基于zabbix角色批量部署zabbix。4.1 部署LNMP架构4.1.1 目录结构

[18:57:47 root@ansible-rocky opt]$ tree /opt//opt/├── ansible.cfg├── hosts├── lnmp_role.yml├── mysql_role.yml├── nginx_role.yml├── php-fpm_role.yml├── roles│ ├── mysql│ │ ├── files│ │ │ └── mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz│ │ ├── tasks│ │ │ └── main.yml│ │ └── templates│ │     └── my.cnf.j2│ ├── nginx│ │ ├── handlers│ │ │ └── main.yml│ │ ├── tasks│ │ │ └── main.yml│ │ └── templates│ │     ├── nginx.conf.j2│ │     └── nginx.service.j2│ ├── php-fpm│ │ ├── files│ │ │ ├── test.php│ │ │ └── www.conf│ │ ├── handlers│ │ │ └── main.yml│ │ ├── tasks│ │ │ └── main.yml│ │ └── templates│ │     ├── php-fpm.conf.j2│ │     └── php.ini.j2│ └── wordpress│     ├── files│     │ └── wordpress-6.1.1-zh_CN.zip│     └── tasks│       └── main.yml└── wordpress_role.yml17 directories, 22 files

4.1.2 LNMP架构所需主机清单以及变量设置

[18:58:15 root@ansible-rocky opt]$ cat hosts [websrvs]10.0.0.1810.0.0.28[websrvs:vars]version="1.20.2"url="http://nginx.org/download/nginx-{{ version }}.tar.gz"install_dir="/apps/nginx"fqdn="www.yanlinux.org"root_path="/data/wordpress"app="wordpress-6.1.1-zh_CN"[dbsrvs]10.0.0.38[dbsrvs:vars]db_group=mysqldb_gid=306db_user=mysqldb_uid=306db_version=8.0.31db_file="mysql-{{db_version}}-linux-glibc2.12-x86_64.tar.xz"db_data_dir="/data/mysql"db_root_passwd="lgq123456**"

4.1.2 实现编译安装nginx角色

#task文件[17:55:17 root@ansible-rocky roles]$ cat nginx/tasks/main.yml - name: add group nginx  group: name=nginx system=yes gid=80- name: add user nginx  user: name=nginx group=nginx uid=80 system=yes shell="/sbin/nologin" create_home=no- name: install dependent package  yum: name={{item}} state=latest  loop:    - gcc    - make    - pcre-devel    - openssl-devel    - zlib-devel    - perl-ExtUtils-Embed- name: get nginx source  unarchive:    src: "{{ url }}"    dest: "/usr/local/src"    remote_src: yes- name: compile and install  shell:    cmd: "./configure --prefix={{install_dir}} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make && make install"    chdir: "/usr/local/src/nginx-{{ version }}"    creates: "{{install_dir}}/sbin/nginx"- name: config file  template:    src: nginx.conf.j2    dest: "{{install_dir}}/conf/nginx.conf"    owner: nginx    group: nginx  notify: restart service  tags:    - config- name: create directory  file:    path: "{{install_dir}}/conf/conf.d"    state: directory    owner: nginx    group: nginx- name: change install directory owner  file:    path: "{{install_dir}}"    owner: nginx    group: nginx    recurse: yes- name: copy service file  template:    src: nginx.service.j2    dest: "/lib/systemd/system/nginx.service"- name: check config  shell:    cmd: "{{install_dir}}/sbin/nginx -t"  register: check_nginx_config  changed_when:    - check_nginx_config.stdout.find('successful')    - false- name: start service  systemd:    daemon_reload: yes    name: nginx.service    state: started    enabled: yes      #创建handler文件[17:59:27 root@ansible-rocky roles]$ cat nginx/handlers/main.yml - name: restart service  service:    name: nginx    state: restarted#准备两个template文件[17:59:51 root@ansible-rocky roles]$ cat nginx/templates/nginx.conf.j2 #user  nobody;user nginx;worker_processes  {{ ansible_processor_vcpus*2 }};events {    worker_connections  1024;}http {    include       mime.types;    default_type  application/octet-stream;    log_format  access_json '{"@timestamp":"$time_iso8601",'        '"host":"$server_addr",'        '"clientip":"$remote_addr",'        '"size":$body_bytes_sent,'        '"responsetime":$request_time,'        '"upstreamtime":"$upstream_response_time",'        '"upstreamhost":"$upstream_addr",'        '"http_host":"$host",'        '"uri":"$uri",'        '"xff":"$http_x_forwarded_for",'        '"referer":"$http_referer",'        '"tcp_xff":"$proxy_protocol_addr",'        '"http_user_agent":"$http_user_agent",'        '"status":"$status"}';    # logging                                                                                              access_log {{install_dir}}/logs/access-json.log access_json;    error_log {{install_dir}}/logs/error.log warn;    keepalive_timeout  65;    include {{install_dir}}/conf/conf.d/*.conf;}[18:00:28 root@ansible-rocky roles]$ cat nginx/templates/nginx.service.j2 [Unit]Description=The nginx HTTP and reverse proxy serverAfter=network.target remote-fs.target nss-lookup.target[Service]Type=forkingPIDFile={{install_dir}}/logs/nginx.pidExecStartPre=/bin/rm -f {{install_dir}}/logs/nginx.pidExecStartPre={{install_dir}}/sbin/nginx -tExecStart={{install_dir}}/sbin/nginxExecReload=/bin/kill -s HUP \$MAINPIDKillSignal=SIGQUITTimeoutStopSec=5KillMode=processPrivateTmp=true                                                                                        LimitNOFILE=100000[Install]WantedBy=multi-user.target#总入口playbook文件[18:09:50 root@ansible-rocky opt]$ cat /opt/nginx_role.yml - hosts: websrvs  remote_user: root  roles:    - nginx

4.1.4 实现php-fpm角色

#首先准备php.ini.j2和www.conf文件#修改php上传限制配置[17:04:11 root@ansible-rocky ~]$ vi /opt/roles/php-fpm/templates/php.ini.j2post_max_size = 100M #将次行从8M修改为100Mupload_max_filesize = 100M #将此行从2M改为100M#修改配置文件[17:14:03 root@proxy ~]$ vi /opt/roles/php-fpm/files/www.confuser = nginx #修改为nginxgroup = nginx #修改为nginx;listen = /run/php-fpm/www.sock #注释此行listen = 127.0.0.1:9000 #添加此行,监控本机的9000端口#准备网页配置文件[19:51:32 root@ansible-rocky opt]$ cat /opt/roles/php-fpm/templates/php-fpm.conf.j2 server {    listen 80;    server_name {{ fqdn }};    location / {        root           {{ root_path  }};        fastcgi_pass   127.0.0.1:9000;        fastcgi_index  index.php;        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;        include        fastcgi_params;    }}#准备tasks文件[19:40:32 root@ansible-rocky opt]$ cat /opt/roles/php-fpm/tasks/main.yml- name: install package  yum:    name: "{{ item }}"  loop:    - php-fpm    - php-mysqlnd    - php-json    - php-xml    - php-gd    - php-pecl-zip- name: php path permissions  file:    path: /var/lib/php/    owner: nginx    group: nginx    recurse: yes- name: config php.ini  template:    src: php.ini.j2    dest: /etc/php.ini- name: config www.conf  copy:    src: www.conf    dest: /etc/php-fpm.d/www.conf- name: website config  template:    src: php-fpm.conf.j2    dest: "{{ install_dir }}/conf/conf.d/php-fpm.conf"    owner: nginx    group: nginx  notify: restart nginx- name: start service  service:    name: php-fpm    state: started    enabled: yes    #准备handler文件[19:53:47 root@ansible-rocky opt]$ cat /opt/roles/php-fpm/handlers/main.yml - name: restart nginx  service:    name: nginx    state: restarted    #准备总入口playbook文件[19:54:48 root@ansible-rocky opt]$ cat /opt/php-fpm_role.yml - hosts: websrvs  remote_user: root  roles:    - php-fpm

4.1.5 实现MySQL角色

注意:ansible playbook调用mysql系列模块需要依赖python3-mysql包和利用pip安装pymysql

#下载准备mysql源文件包[18:22:54 root@ansible-rocky opt]$ ls roles/mysql/files/mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz#创建task文件[18:24:40 root@ansible-rocky opt]$ cat roles/mysql/tasks/main.yml - name: install dependent package  yum:    name: "{{ item }}"  loop:    - libaio    - numactl-libs    - python39    - python3-mysql- name: install pymysql  pip:    name: pymysql    state: present    - name: create mysql group  group: name={{db_group}} gid={{db_gid}}- name: create mysql user  user: name={{db_user}} uid={{db_uid}} system=yes shell="/sbin/nologin" create_home=no group={{db_group}}- name: copy tar to remote host and file mode  unarchive:    src: "{{ db_file }}"    dest: "/usr/local/"    owner: root    group: root- name: create lingfile /usr/local/mysql  file:    src: "/usr/local/mysql-{{ db_version }}-linux-glibc2.12-x86_64"    dest: "/usr/local/mysql"    state: link- name: path file  copy:    content: "PATH=/usr/local/mysql/bin:$PATH"    dest: "/etc/profile.d/mysql.sh"- name: config file  template:    src: my.cnf.j2    dest: "/etc/my.cnf"- name: create directory  file:    name: "/data"    state: directory- name: init mysql data  shell:    cmd: "/usr/local/mysql/bin/mysqld --initialize-insecure --user={{ db_user }} --datadir={{ db_data_dir }}"  tags:    - init- name: service script  copy:    src: "/usr/local/mysql/support-files/mysql.server"    dest: "/etc/init.d/mysqld"    remote_src: yes    mode: '+x'- name: start service  shell:    cmd: chkconfig --add mysqld;chkconfig mysqld on;service mysqld start- name: change root password  shell:    cmd: "/usr/local/mysql/bin/mysqladmin -uroot password {{ db_root_passwd }}"    - name: create {{ wp_db_name }} database  mysql_db:    login_host: "localhost"    login_user: "root"    login_password: "{{ db_root_passwd }}"    login_port: 3306    login_unix_socket: "{{ db_data_dir }}/mysql.sock"    name: "{{ wp_db_name }}"    state: present  when: "{{ wp_db_name }} is defined"- name: create {{ wp_db_user }}  mysql_user:    login_host: "localhost"    login_user: "root"    login_password: "{{ db_root_passwd }}"    login_port: 3306    login_unix_socket: "{{ db_data_dir }}/mysql.sock"    name: "{{ wp_db_user}}"    password: "{{ wp_db_passwd }}"    priv: "{{ wp_db_name }}.*:ALL"    host: "10.0.0.%"    state: present  when: "{{ wp_db_user }} is defined"        #准备MySQL 配置文件模板[18:25:25 root@ansible-rocky opt]$ cat roles/mysql/templates/my.cnf.j2 [mysqld]server-id=1log-bindatadir={{ db_data_dir }}socket={{ db_data_dir }}/mysql.socklog-error={{ db_data_dir }}/mysql.logpid-file={{ db_data_dir }}/mysql.pid[client]socket={{ db_data_dir }}/mysql.sock#准备总入口playbook文件[18:25:38 root@ansible-rocky opt]$ cat mysql_role.yml - hosts: dbsrvs  remote_user: root  gather_facts: no  roles:    - mysql

4.2 基于zabbix角色批量部署zabbix

依赖上面搭建好的LNMP架构实现

4.2.1 部署zabbix-server

#总体目录结构[20:27:58 root@ansible-rocky opt]$ tree.├── ansible.cfg├── hosts├── hosts_zabbix├── roles│ ├── mysql│ │ ├── files│ │ │ ├── create.sql.gz│ │ │ └── mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz│ │ ├── tasks│ │ │ └── main.yml│ │ └── templates│ │     └── my.cnf.j2│ ├── nginx│ │ ├── files│ │ ├── handlers│ │ │ └── main.yml│ │ ├── tasks│ │ │ └── main.yml│ │ └── templates│ │     ├── nginx.conf.j2│ │     └── nginx.service.j2│ ├── php-fpm│ │ ├── files│ │ │ ├── test.php│ │ │ └── www.conf│ │ ├── handlers│ │ │ └── main.yml│ │ ├── tasks│ │ │ └── main.yml│ │ └── templates│ │     ├── php-fpm.conf.j2│ │     └── php.ini.j2│ └── zabbix_server│     ├── handlers│     │ └── main.yml│     ├── tasks│     │ └── main.yml│     └── templates│         ├── zabbix.conf.j2│         ├── zabbix_server.conf.j2│         └── zabbix-server-ngx.conf.j2└── zabbix_server.yml29 directories, 26 files#主入口playbook[20:24:45 root@ansible-rocky opt]$ cat zabbix_server.yml - hosts: websrvs  remote_user: root  roles:    - nginx    - php-fpm- hosts: dbsrvs  remote_user: root  roles:    - mysql- hosts: websrvs  remote_user: root  roles:    - zabbix_server#tasks文件[20:30:01 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/tasks/main.yml - name: config zabbix yum repo  yum_repository:    name: "ansible_zabbix"    description: "zabbix repo"    baseurl: "https://mirrors.aliyun.com/zabbix/zabbix/{{ zabbix_version }}/rhel/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/"    gpgcheck: yes    gpgkey: "https://mirrors.aliyun.com/zabbix/zabbix-official-repo.key"- name: install zabbix-server  yum:    name: "{{ item }}"  loop:    - zabbix-server-mysql    - zabbix-agent2    - zabbix-get    - zabbix-web-mysql- name: copy zabbix_server.conf   template:    src: zabbix_server.conf.j2    dest: /etc/zabbix/zabbix_server.conf    mode: 0600  notify:    - restart zabbix-server  tags: restart zabbix-server- name: chown  zabbix-web  file:    path:  /etc/zabbix/web        state: directory    owner: nginx    group: nginx    recurse: yes- name: copy zabbix-server web conf  template:    src: zabbix-server-ngx.conf.j2    dest: "{{ install_dir }}/conf/conf.d/zabbix_server_ngx.conf"    owner: nginx    group: nginx  notify:    - restart nginx- name: copy zabbix.conf into php-fpm.d  template:    src: zabbix.conf.j2    dest: "/etc/php-fpm.d/zabbix.conf"  notify:    - restart php-fpm- name: start zabbix-server  service:    name: zabbix-server    state: restarted    enabled: yes    #查看handler[20:34:11 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/handlers/main.yml - name: restart zabbix-server  service:    name: zabbix-server    state: restarted- name: restart nginx  service:    name: nginx    state: restarted- name: restart php-fpm  service:    name: php-fpm    state: restarted    #查看template文件[20:34:15 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/templates/zabbix.conf.j2 [zabbix]user = nginxgroup = nginxlisten = /run/php-fpm/zabbix.socklisten.acl_users = apache,nginxlisten.allowed_clients = 127.0.0.1pm = dynamicpm.max_children = 50pm.start_servers = 5pm.min_spare_servers = 5pm.max_spare_servers = 35pm.max_requests = 200php_value[session.save_handler] = filesphp_value[session.save_path]    = /var/lib/php/sessionphp_value[max_execution_time] = 300php_value[memory_limit] = 128Mphp_value[post_max_size] = 80Mphp_value[upload_max_filesize] = 80Mphp_value[max_input_time] = 300php_value[max_input_vars] = 10000php_value[date.timezone] = Asia/Shanghai[20:38:05 root@ansible-rocky zabbix_server]$ grep -Ev '^$|#' /opt/roles/zabbix_server/templates/zabbix_server.conf.j2 LogFile=/var/log/zabbix/zabbix_server.logLogFileSize=0PidFile=/var/run/zabbix/zabbix_server.pidSocketDir=/var/run/zabbixDBHost=10.0.0.58DBName=zabbixDBUser=zabbixDBPassword=lgq123456SNMPTrapperFile=/var/log/snmptrap/snmptrap.logTimeout=4AlertScriptsPath=/usr/lib/zabbix/alertscriptsExternalScripts=/usr/lib/zabbix/externalscriptsLogSlowQueries=3000StatsAllowedIP=127.0.0.1##zabbix网页配置文件[20:39:05 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/templates/zabbix-server-ngx.conf.j2server {    listen 80;    server_name {{ zabbix_fqdn }};    root /usr/share/zabbix;    index index.php;    location = /favicon.ico {        log_not_found   off;    }    location / {        try_files       $uri $uri/ =404;    }    location /assets {         access_log      off;         expires         10d;    }    location ~ /\.ht {         deny            all;    }    location ~ /(api\/|conf[^\.]|include|locale|vendor) {         deny            all;         return          404;    }    location ~ [^/]\.php(/|$) {        fastcgi_pass   127.0.0.1:9000;        #fastcgi_pass    unix:/run/php-fpm/zabbix.sock;        fastcgi_split_path_info ^(.+\.php)(/.+)$;        fastcgi_index   index.php;        fastcgi_param   DOCUMENT_ROOT   /usr/share/zabbix;        fastcgi_param   SCRIPT_FILENAME /usr/share/zabbix$fastcgi_script_name;        fastcgi_param   PATH_TRANSLATED /usr/share/zabbix$fastcgi_script_name;        include fastcgi_params;        fastcgi_param   QUERY_STRING    $query_string;        fastcgi_param   REQUEST_METHOD  $request_method;        fastcgi_param   CONTENT_TYPE    $content_type;        fastcgi_param   CONTENT_LENGTH  $content_length;        fastcgi_intercept_errors        on;        fastcgi_ignore_client_abort     off;        fastcgi_connect_timeout         60;        fastcgi_send_timeout            180;        fastcgi_read_timeout            180;        fastcgi_buffer_size             128k;        fastcgi_buffers                 4 256k;        fastcgi_busy_buffers_size       256k;        fastcgi_temp_file_write_size    256k;    }}

4.2.2 部署zabbix-agent

#目录结构[22:59:31 root@ansible-rocky zabbix_agent2]$ tree.├── files│ └── zabbix_agnet2.d│     ├── login.conf│     ├── mem.conf│     ├── mysql.conf│     ├── mysql_repl_status.sh│     ├── mysql.sh│     ├── nginx_status.conf│     ├── nginx_status.sh│     └── tcp_state.conf├── handlers│ └── main.yml├── tasks│ └── main.yml└── templates    └── zabbix_agent2.conf.j25 directories, 11 files#task文件[23:14:12 root@ansible-rocky opt]$ cat /opt/roles/zabbix_agent2/tasks/main.yml - name: install repo   yum_repository:    name: "ansible_zabbix"    description: "zabbix repo"    baseurl: "https://mirrors.aliyun.com/zabbix/zabbix/{{ zabbix_version }}/rhel/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/"    gpgcheck: yes    gpgkey: "https://mirrors.aliyun.com/zabbix/zabbix-official-repo.key"- name: install agent2 for centos or rocky  yum:    name: zabbix-agent2  when:     - ansible_distribution == "Rocky" or ansible_distribution == "Centos"- name: install agent2 for centos or ubuntu  apt:    name: zabbix-agent2    update_cache: yes  when:    - ansible_distribution == "Ubuntu"- name: config file  template:    src: zabbix_agent2.conf.j2    dest: "/etc/zabbix/zabbix_agent2.conf"    mode: 0644  notify:    - restart zabbix-agent2- name: copy zabbix-agent2.d content  copy:    src: zabbix_agent2.d    dest: "/etc/zabbix"  notify:    - restart zabbix-agent2  tags: zabbix_agent2.d- name: start zabbix-agent2  service:    name: zabbix-agent2    state: started    enabled: yes    #handler文件[23:14:14 root@ansible-rocky opt]$ cat /opt/roles/zabbix_agent2/handlers/main.yml - name: restart zabbix_agent2  service:    name: zabbix-agent2    state: restarted    #template文件[23:14:43 root@ansible-rocky opt]$ cat /opt/roles/zabbix_agent2/templates/zabbix_agent2.conf.j2 PidFile=/var/run/zabbix/zabbix_agent2.pidLogFile=/var/log/zabbix/zabbix_agent2.logLogFileSize=0Server={{ zabbix_server_ip }}ServerActive={{ zabbix_server_ip }}Hostname={{ ansible_default_ipv4.address }}Include=/etc/zabbix/zabbix_agent2.d/*.confControlSocket=/tmp/agent.sock

4.2.3 测试

[23:15:29 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.18 -k mem_use_percent20.1886[23:16:51 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.18 -k tcp_state[ESTABLISHED]32[23:17:30 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.28 -k tcp_state[ESTABLISHED]28[23:17:35 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.58 -k tcp_state[ESTABLISHED]55