Ansible介绍以及基于角色搭建LNMP和zabbix

  • Ansible介绍以及基于角色搭建LNMP和zabbix已关闭评论
  • 105 次浏览
  • A+
所属分类:linux技术
摘要

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


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 ansible

1.2.1 Ansible Ad-Hoc 介绍

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

1.2.2 ansible 命令用法

格式:

ansible <host-pattern> [-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 yanlinux 10.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 code 10.0.0.102 | FAILED | rc=2 >> ls: cannot open directory '/root': Permission deniednon-zero return code 10.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' -b 10.0.0.102 | CHANGED | rc=0 >> init_os.sh snap 10.0.0.7 | CHANGED | rc=0 >> anaconda-ks.cfg init_os.sh 10.0.0.18 | CHANGED | rc=0 >> anaconda-ks.cfg init_os.sh ##所有被管理主机上创建用户magedu [14:37:05 yanlinux@ansible-rocky ~]$ ansible all -a 'useradd magedu' -b 10.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' -b 10.0.0.7 | CHANGED | rc=0 >> magedu:x:1002:1002::/home/magedu:/bin/bash 10.0.0.102 | CHANGED | rc=0 >> magedu:x:1001:1001::/home/magedu:/bin/sh 10.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=magedu 10.0.0.18 | CHANGED | rc=0 >> magedu 10.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]$ ping 10.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]$ list 10.0.0.18 10.0.0.7 10.0.0.102 root@all (3)[f:5]$ cd websrvs root@websrvs (2)[f:5]$ list 10.0.0.18 10.0.0.7 root@websrvs (2)[f:5]$ forks 10 root@websrvs (2)[f:10]$ cd appsrvs root@appsrvs (2)[f:10]$ list 10.0.0.102 10.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 

Ansible介绍以及基于角色搭建LNMP和zabbix

Ansible介绍以及基于角色搭建LNMP和zabbix

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;AES256 65323766623831636563636132623333623932633461396563383764333037396563633766363231 3335646336346136626231353133623566626166626336380a306630643338353031353739353538 62373930306636633430653537363534376231323839643131376335653366656634616365663063 6236663364343461610a383365643534646564316261326166316233393039386134363436313138 63323939663537666462646233613262646637306130626336336239323737623833393735666364 36336334316666326265356166326163373039616533353564353964396266376637363037353338 37623639656262303966363766356630376466666463363338353535623635633137616335383333 65333263643762353264326563326362393663316538666530616664643438666435373162616164 30313761323030343165666330326537653430333764363834326566333666316133386465663334 63353035616266396366366662643839353431653736353465626261623433343735663534663831 32636632653730323465366531353531633761623930303138643337613162613062333237633566 39663562393535343165  #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.yml New 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 lamp  Found 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=mysql db_gid=306 db_user=mysql db_uid=306 db_version=8.0.31 db_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=1 log-bin datadir={{ db_data_dir }} socket={{ db_data_dir }}/mysql.sock log-error={{ db_data_dir }}/mysql.log pid-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.yml PLAY [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.yml  17 directories, 22 files 

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

[18:58:15 root@ansible-rocky opt]$ cat hosts  [websrvs] 10.0.0.18 10.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=mysql db_gid=306 db_user=mysql db_uid=306 db_version=8.0.31 db_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 server After=network.target remote-fs.target nss-lookup.target  [Service] Type=forking PIDFile={{install_dir}}/logs/nginx.pid ExecStartPre=/bin/rm -f {{install_dir}}/logs/nginx.pid ExecStartPre={{install_dir}}/sbin/nginx -t ExecStart={{install_dir}}/sbin/nginx ExecReload=/bin/kill -s HUP $MAINPID KillSignal=SIGQUIT TimeoutStopSec=5 KillMode=process PrivateTmp=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.j2 post_max_size = 100M #将次行从8M修改为100M upload_max_filesize = 100M #将此行从2M改为100M  #修改配置文件 [17:14:03 root@proxy ~]$ vi /opt/roles/php-fpm/files/www.conf user = nginx #修改为nginx group = 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=1 log-bin datadir={{ db_data_dir }} socket={{ db_data_dir }}/mysql.sock log-error={{ db_data_dir }}/mysql.log pid-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.yml  29 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 = nginx group = nginx  listen = /run/php-fpm/zabbix.sock listen.acl_users = apache,nginx listen.allowed_clients = 127.0.0.1  pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 200  php_value[session.save_handler] = files php_value[session.save_path]    = /var/lib/php/session  php_value[max_execution_time] = 300 php_value[memory_limit] = 128M php_value[post_max_size] = 80M php_value[upload_max_filesize] = 80M php_value[max_input_time] = 300 php_value[max_input_vars] = 10000 php_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.log LogFileSize=0 PidFile=/var/run/zabbix/zabbix_server.pid SocketDir=/var/run/zabbix DBHost=10.0.0.58 DBName=zabbix DBUser=zabbix DBPassword=lgq123456 SNMPTrapperFile=/var/log/snmptrap/snmptrap.log Timeout=4 AlertScriptsPath=/usr/lib/zabbix/alertscripts ExternalScripts=/usr/lib/zabbix/externalscripts LogSlowQueries=3000 StatsAllowedIP=127.0.0.1 ##zabbix网页配置文件 [20:39:05 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/templates/zabbix-server-ngx.conf.j2 server {     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;     }  } 

Ansible介绍以及基于角色搭建LNMP和zabbix

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.j2  5 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.pid LogFile=/var/log/zabbix/zabbix_agent2.log LogFileSize=0 Server={{ zabbix_server_ip }} ServerActive={{ zabbix_server_ip }} Hostname={{ ansible_default_ipv4.address }} Include=/etc/zabbix/zabbix_agent2.d/*.conf ControlSocket=/tmp/agent.sock 

4.2.3 测试

[23:15:29 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.18 -k mem_use_percent 20.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