Ansible一键布署LAMP

1、环境规划

1.1、主机规划

[root@ansible-control ansible-env]# cat /etc/ansible/hosts 
[php-server]
192.168.10.17

[mysql-server]
192.168.10.19

[nginx-server]
192.168.10.18

[lnmp:children]
php-server
mysql-server
nginx-server

1.2、使用Roles规划目录

# 创建Roles相关目录
mkdir -p /opt/lnmp/group_vars
mkdir -p /opt/lnmp/base/{tasks,files,templates,handlers}
mkdir -p /opt/lnmp/nginx/{tasks,files,templates,handlers}
mkdir -p /opt/lnmp/php/{tasks,files,templates,handlers}
mkdir -p /opt/lnmp/mysql/{tasks,files,templates,handlers}

# 目录结构
/opt/lnmp/
├── base
│   ├── files
│   ├── handlers
│   ├── tasks
│   └── templates
├── group_vars
├── mysql
│   ├── files
│   ├── handlers
│   ├── tasks
│   └── templates
├── nginx
│   ├── files
│   ├── handlers
│   ├── tasks
│   └── templates
├── php
│   ├── files
│   ├── handlers
│   ├── tasks
│   └── templates

1.4、编写入口yaml

cat > /opt/lnmp/run.yaml << 'EOF'
- hosts: all
  roles:
    - role: base

- hosts: php-server
  roles:
    - role: php

- hosts: nginx-server
  roles:
    - role: nginx

- hosts: mysql-server
  roles:
    - role: mysql
EOF

1.5、初始化所有主机

1.5.1、base目录结构

[root@ansible-control lnmp]# tree base/
base/
├── files
├── handlers
├── tasks
│   └── main.yaml
└── templates

1.5.2、base/task/base.yaml

cat > /opt/lnmp/base/tasks/main.yaml << 'EOF' 
- name: set base yum repo
  yum_repository:
    name: CentOS-Base
    baseurl: http://mirrors.aliyun.com/centos/7.9.2009/os/x86_64/
    description: "Base repo"
    enabled: yes
    gpgkey: http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    gpgcheck: true
    state: present

- name: epel yum repo
  yum_repository:
    name: epel
    baseurl: http://mirrors.aliyun.com/epel/7/x86_64/
    description: "epel repo"
    enabled: no
    gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 
    gpgcheck: false
    state: present

- name: install base software
  yum:
    name:
      - tree
      - vim
      - lrzsz
      - unzip
      - psmisc
      - net-tools
      - ntpdate
    state: present

- name: stop firewalld
  systemd:
    name: firewalld
    state: stopped
    enabled: no

- name: disable selinux
  selinux:
    state: disabled

- name: change time zone
  command: timedatectl set-timezone Asia/Shanghai

- name: config sync time
  cron:
    name: ali sync time
    minute: "*/1"
    job: "/sbin/ntpdate ntp5.aliyun.com &>/dev/null"
EOF

2、安装Nginx

2.1、软件下载地址

http://nginx.org/download/nginx-1.12.2.tar.gz

2.2、目录结构

[root@ansible-control lnmp]# tree nginx/
nginx/
├── files
│   ├── index.php
│   └── nginx-1.12.2.tar.gz
├── handlers
│   └── main.yaml
├── tasks
│   └── main.yaml
└── templates
    ├── nginx.conf.j2
    └── nginx.service

2.3、nginx/task/main.yaml

[root@ansible-control lnmp]# cat nginx/tasks/main.yaml 
- name: groupadd
  tags: nginx_install
  group:
    name: nginx

- name: useradd
  tags: nginx_install
  user:
    name: nginx
    group: nginx
    shell: /sbin/nologin
    create_home: no

- name: install lib devel
  tags: nginx_install
  yum:
    name:
      - pcre
      - pcre-devel
      - openssl
      - openssl-devel
      - gcc
      - gcc-c++
    state: installed

- name: cp nginx_src file
  tags: nginx_install
  copy:
    src: nginx-1.12.2.tar.gz
    dest: /root/nginx-1.12.2.tar.gz
    backup: yes

- name: unarchive nginx src
  tags: nginx_install
  unarchive:
    src: /root/nginx-1.12.2.tar.gz
    dest: /root/
    remote_src: yes

- name: compile nginx and install
  tags: nginx_install
  shell: cd "{{nginx_pkg}}" && ./configure --user="{{user}}" --group="{{user}}" --prefix="{{prefix}}" --with-http_ssl_module --with-http_stub_status_module --with-stream && make && make install

- name: copy nginx.conf
  tags:
    - nginx_install
  template:
    src: nginx.conf.j2
    dest: /usr/local/nginx-1.12.2/conf/nginx.conf
    backup: yes
  notify: restart nginx

- name: configure nginx server
  tags: nginx_install
  template:
    src: nginx.service
    dest: /usr/lib/systemd/system/nginx.service
    mode: 0755

- name: change permission
  tags:
    - nginx_install
  file:
    path: "{{prefix}}"
    state: directory
    owner: nginx
    recurse: yes

- name: start nginx service
  tags:
    - nginx_start
    - nginx_install
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: www dir
  tags:
    - php_install
  file:
    path: /var/www
    state: directory
    owner: nginx
    mode: 0755

- name: test php page
  tags:
    - php_install
  copy:
    src: index.php
    dest: /var/www
    owner: nginx
    mode: 0755

2.4、group_vars/nginx-server 

[root@ansible-control lnmp]# cat group_vars/nginx-server 
user: nginx
prefix: /usr/local/nginx-1.12.2
nginx_pkg: /root/nginx-1.12.2
php_ip: 192.168.10.17

2.5、handlers/main.yaml

[root@ansible-control lnmp]# cat nginx/handlers/main.yaml 
- name: restart nginx
  systemd:
    name: nginx
    state: restarted

2.6、template/nginx.conf.j2

[root@ansible-control lnmp]# cat nginx/templates/nginx.conf.j2 
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /var/www;
            index  index.html index.htm index.php;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
            root           /var/www;
            fastcgi_pass   {{php_ip}}:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi.conf;
        }
    }
}

2.7、templates/nginx.service

[root@ansible-control lnmp]# cat nginx/templates/nginx.service 
[Unit]
Description=nginx - high performance web server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile={{ prefix }}/logs/nginx.pid
ExecStartPre={{ prefix }}/sbin/nginx -t -c {{ prefix }}/conf/nginx.conf
ExecStart={{ prefix }}/sbin/nginx -c {{ prefix }}/conf/nginx.conf
ExecReload={{ prefix }}/sbin/nginx -s reload
ExecStop={{ prefix }}/sbin/nginx -s stop
ExecQuit={{ prefix }}/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

3、安装MySQL

3.1、注意事项

# 被控制主机需要安装此包
yum install MySQL-python
 

# ansible 控制主机
yum install mysql-devel 
pip3 install mysqlclient

# mysql 首次初始化数据库时,需要手动介入,设置好root帐号和密码
mysqld --initialize --user=mysql --datadir=/usr/local/mysql/data/

3.2、软件下载地址

https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.41-el7-x86_64.tar.gz

3.3、目录结构

 [root@ansible-control lnmp]# tree mysql
mysql
├── files
│   └── mysql-5.7.41-el7-x86_64.tar.gz
├── handlers
├── tasks
│   └── main.yaml
└── templates
    ├── my.cnf.j2
    ├── mysql.server
    └── mysql.service

3.4、tasks/main.yaml

 [root@ansible-control lnmp]# cat mysql/tasks/main.yaml 
- name: groupadd
  tags: mysql_install
  group:
    name: mysql

- name: useradd
  tags: mysql_install
  user:
    name: mysql
    group: mysql
    shell: /sbin/nologin
    create_home: no

- name: install mysql lib-devel
  tags: mysql_install
  yum:
    name:
      - cmake
      - ncurses-devel
      - autoconf
      - zlib
      - zlib-devel

- name: unzip mysql tar
  tags:
    - mysql_install
  unarchive:
    src: mysql-5.7.41-el7-x86_64.tar.gz
    dest: /usr/local

- name: create software link
  tags:
    - mysql_install
  file:
    src: /usr/local/mysql-5.7.41-el7-x86_64
    dest: /usr/local/mysql
    state: link

- name: mysql config my.cnf
  tags: mysql_install
  template:
    src: my.cnf.j2
    dest: /etc/my.cnf
    backup: yes

- name: mkdir mysql logs
  tags:
    - mysql_install
  file:
    path: "{{ mysql_logs }}"
    state: directory
    owner: mysql

- name: copy mysql.server
  tags:
    - mysql_install
  template:
    src: mysql.server
    dest: "{{ mysql_base }}/mysql.server"
    mode: 755
    backup: yes

- name: copy mysql.service
  tags:
    - mysql_install
  template:
    src: mysql.service
    dest: /lib/systemd/system/mysql.service
    backup: yes

- name:
  tags:
    - mysql_start
  systemd:
    name: mysql
    state: started

- name:
  tags:
    - mysql_start
  community.mysql.mysql_db:
    login_host: "localhost"
    login_port: "{{port}}"
    login_user: "{{login_user}}"
    login_unix_socket: "{{mysql_sock}}"
    login_password: "{{login_password}}"
    encoding: "utf8"
    name: "{{db_name}}"
    state: present 

- name: Create database user
  tags:
    - mysql_start
  community.mysql.mysql_user:
    login_host: "localhost"
    login_port: "{{port}}"
    login_user: "{{login_user}}"
    login_password: "{{login_password}}"
    login_unix_socket: "{{mysql_sock}}"
    name: "{{db_name}}"
    host: '%'
    password: "{{db_pwd}}"
    priv: 'wpdb.*:ALL'
    state: present

3.5、templates/my.cnf.j2

[root@ansible-control lnmp]# cat mysql/templates/my.cnf.j2 
[mysqld]
port = {{port}}
bind-address = 0.0.0.0
symbolic-links=0

skip-name-resolve
slave-skip-errors = 1032,1062,1050

socket={{mysql_sock}}
pid-file ={{mysql_pid}}

datadir={{mysql_data}}

binlog_cache_size = 1M
max_binlog_cache_size = 2M
max_binlog_size = 10M
expire_logs_days = 7
key_buffer_size = 16M
read_buffer_size = 2M
read_rnd_buffer_size = 2M
bulk_insert_buffer_size = 2M

innodb_buffer_pool_size=512M
innodb_buffer_pool_instances=1
innodb_autoextend_increment=128M
innodb_log_file_size=512M
innodb_flush_log_at_trx_commit=2
innodb_buffer_pool_size=512M
max_allowed_packet=64M
binlog_format="MIXED"
character-set-server=utf8

[mysql]
default-character-set=utf8
socket={{mysql_sock}}

[mysqld_safe]
log-error={{mysql_logs}}/mysql_safe.err
pid-file ={{mysql_pid}}

3.6、templates/mysql.server

[root@ansible-control lnmp]# cat mysql/templates/mysql.server 
#!/bin/sh
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
# This file is public domain and comes with NO WARRANTY of any kind

# MySQL daemon start/stop script.

# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
# When this is done the mysql server will be started when the machine is
# started and shut down when the systems goes down.

# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 64 36
# description: A very fast and reliable SQL database engine.

# Comments to support LSB init script conventions
### BEGIN INIT INFO
# Provides: mysql
# Required-Start: $local_fs $network $remote_fs
# Should-Start: ypbind nscd ldap ntpd xntpd
# Required-Stop: $local_fs $network $remote_fs
# Default-Start:  2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop MySQL
# Description: MySQL is a very fast and reliable SQL database engine.
### END INIT INFO
 
# If you install MySQL on some other places than /usr/local/mysql, then you
# have to do one of the following things for this script to work:
#
# - Run this script from within the MySQL installation directory
# - Create a /etc/my.cnf file with the following information:
#   [mysqld]
#   basedir=<path-to-mysql-installation-directory>
# - Add the above to any other configuration file (for example ~/.my.ini)
#   and copy my_print_defaults to /usr/bin
# - Add the path to the mysql-installation-directory to the basedir variable
#   below.
#
# If you want to affect other MySQL variables, you should make your changes
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.

# If you change base dir, you must also change datadir. These may get
# overwritten by settings in the MySQL configuration files.

basedir={{mysql_base}}
datadir={{mysql_data}}

# Default value, in seconds, afterwhich the script should timeout waiting
# for server start. 
# Value here is overriden by value in my.cnf. 
# 0 means don't wait at all
# Negative numbers mean to wait indefinitely
service_startup_timeout=900

# Lock directory for RedHat / SuSE.
lockdir='/var/lock/subsys'
lock_file_path="$lockdir/mysql"

# The following variables are only set for letting mysql.server find things.

# Set some defaults
mysqld_pid_file_path=
if test -z "$basedir"
then
  basedir=/usr/local/mysql
  bindir=/usr/local/mysql/bin
  if test -z "$datadir"
  then
    datadir=/usr/local/mysql/data
  fi
  sbindir=/usr/local/mysql/bin
  libexecdir=/usr/local/mysql/bin
else
  bindir="$basedir/bin"
  if test -z "$datadir"
  then
    datadir="$basedir/data"
  fi
  sbindir="$basedir/sbin"
  libexecdir="$basedir/libexec"
fi

# datadir_set is used to determine if datadir was set (and so should be
# *not* set inside of the --basedir= handler.)
datadir_set=

#
# Use LSB init script functions for printing messages, if possible
#
lsb_functions="/lib/lsb/init-functions"
if test -f $lsb_functions ; then
  . $lsb_functions
else
  log_success_msg()
  {
    echo " SUCCESS! $@"
  }
  log_failure_msg()
  {
    echo " ERROR! $@"
  }
fi

PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
export PATH

mode=$1    # start or stop

[ $# -ge 1 ] && shift


other_args="$*"   # uncommon, but needed when called from an RPM upgrade action
           # Expected: "--skip-networking --skip-grant-tables"
           # They are not checked here, intentionally, as it is the resposibility
           # of the "spec" file author to give correct arguments only.

case `echo "testing\c"`,`echo -n testing` in
    *c*,-n*) echo_n=   echo_c=     ;;
    *c*,*)   echo_n=-n echo_c=     ;;
    *)       echo_n=   echo_c='\c' ;;
esac

parse_server_arguments() {
  for arg do
    case "$arg" in
      --basedir=*)  basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
                    bindir="$basedir/bin"
                    if test -z "$datadir_set"; then
                      datadir="$basedir/data"
                    fi
                    sbindir="$basedir/sbin"
                    libexecdir="$basedir/libexec"
        ;;
      --datadir=*)  datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
                    datadir_set=1
        ;;
      --pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
      --service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    esac
  done
}

wait_for_pid () {
  verb="$1"           # created | removed
  pid="$2"            # process ID of the program operating on the pid-file
  pid_file_path="$3" # path to the PID file.

  i=0
  avoid_race_condition="by checking again"

  while test $i -ne $service_startup_timeout ; do

    case "$verb" in
      'created')
        # wait for a PID-file to pop into existence.
        test -s "$pid_file_path" && i='' && break
        ;;
      'removed')
        # wait for this PID-file to disappear
        test ! -s "$pid_file_path" && i='' && break
        ;;
      *)
        echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
        exit 1
        ;;
    esac

    # if server isn't running, then pid-file will never be updated
    if test -n "$pid"; then
      if kill -0 "$pid" 2>/dev/null; then
        :  # the server still runs
      else
        # The server may have exited between the last pid-file check and now.  
        if test -n "$avoid_race_condition"; then
          avoid_race_condition=""
          continue  # Check again.
        fi

        # there's nothing that will affect the file.
        log_failure_msg "The server quit without updating PID file ($pid_file_path)."
        return 1  # not waiting any more.
      fi
    fi

    echo $echo_n ".$echo_c"
    i=`expr $i + 1`
    sleep 1

  done

  if test -z "$i" ; then
    log_success_msg
    return 0
  else
    log_failure_msg
    return 1
  fi
}

# Get arguments from the my.cnf file,
# the only group, which is read from now on is [mysqld]
if test -x "$bindir/my_print_defaults";  then
  print_defaults="$bindir/my_print_defaults"
else
  # Try to find basedir in /etc/my.cnf
  conf=/etc/my.cnf
  print_defaults=
  if test -r $conf
  then
    subpat='^[^=]*basedir[^=]*=\(.*\)$'
    dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf`
    for d in $dirs
    do
      d=`echo $d | sed -e 's/[  ]//g'`
      if test -x "$d/bin/my_print_defaults"
      then
        print_defaults="$d/bin/my_print_defaults"
        break
      fi
    done
  fi

  # Hope it's in the PATH ... but I doubt it
  test -z "$print_defaults" && print_defaults="my_print_defaults"
fi

#
# Read defaults file from 'basedir'.   If there is no defaults file there
# check if it's in the old (depricated) place (datadir) and read it from there
#

extra_args=""
if test -r "$basedir/my.cnf"
then
  extra_args="-e $basedir/my.cnf"
fi

parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`

#
# Set pid file if not given
#
if test -z "$mysqld_pid_file_path"
then
  mysqld_pid_file_path=$datadir/`hostname`.pid
else
  case "$mysqld_pid_file_path" in
    /* ) ;;
    * )  mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
  esac
fi

case "$mode" in
  'start')
    # Start daemon

    # Safeguard (relative paths, core dumps..)
    cd $basedir

    echo $echo_n "Starting MySQL"
    if test -x $bindir/mysqld_safe
    then
      # Give extra arguments to mysqld with the my.cnf file. This script
      # may be overwritten at next upgrade.
      $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
      wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?

      # Make lock for RedHat / SuSE
      if test -w "$lockdir"
      then
        touch "$lock_file_path"
      fi

      exit $return_value
    else
      log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"
    fi
    ;;

  'stop')
    # Stop daemon. We use a signal here to avoid having to know the
    # root password.

    if test -s "$mysqld_pid_file_path"
    then
      # signal mysqld_safe that it needs to stop
      touch "$mysqld_pid_file_path.shutdown"

      mysqld_pid=`cat "$mysqld_pid_file_path"`

      if (kill -0 $mysqld_pid 2>/dev/null)
      then
        echo $echo_n "Shutting down MySQL"
        kill $mysqld_pid
        # mysqld should remove the pid file when it exits, so wait for it.
        wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
      else
        log_failure_msg "MySQL server process #$mysqld_pid is not running!"
        rm "$mysqld_pid_file_path"
      fi

      # Delete lock for RedHat / SuSE
      if test -f "$lock_file_path"
      then
        rm -f "$lock_file_path"
      fi
      exit $return_value
    else
      log_failure_msg "MySQL server PID file could not be found!"
    fi
    ;;

  'restart')
    # Stop the service and regardless of whether it was
    # running or not, start it again.
    if $0 stop  $other_args; then
      $0 start $other_args
    else
      log_failure_msg "Failed to stop running server, so refusing to try to start."
      exit 1
    fi
    ;;

  'reload'|'force-reload')
    if test -s "$mysqld_pid_file_path" ; then
      read mysqld_pid <  "$mysqld_pid_file_path"
      kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
      touch "$mysqld_pid_file_path"
    else
      log_failure_msg "MySQL PID file could not be found!"
      exit 1
    fi
    ;;
  'status')
    # First, check to see if pid file exists
    if test -s "$mysqld_pid_file_path" ; then 
      read mysqld_pid < "$mysqld_pid_file_path"
      if kill -0 $mysqld_pid 2>/dev/null ; then 
        log_success_msg "MySQL running ($mysqld_pid)"
        exit 0
      else
        log_failure_msg "MySQL is not running, but PID file exists"
        exit 1
      fi
    else
      # Try to find appropriate mysqld process
      mysqld_pid=`pidof $libexecdir/mysqld`

      # test if multiple pids exist
      pid_count=`echo $mysqld_pid | wc -w`
      if test $pid_count -gt 1 ; then
        log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)"
        exit 5
      elif test -z $mysqld_pid ; then 
        if test -f "$lock_file_path" ; then 
          log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
          exit 2
        fi 
        log_failure_msg "MySQL is not running"
        exit 3
      else
        log_failure_msg "MySQL is running but PID file could not be found"
        exit 4
      fi
    fi
    ;;
    *)
      # usage
      basename=`basename "$0"`
      echo "Usage: $basename  {start|stop|restart|reload|force-reload|status}  [ MySQL server options ]"
      exit 1
    ;;
esac

exit 0
mysql.server

3.7、templates/mysql.service

 [root@ansible-control lnmp]# cat mysql/templates/mysql.service 
[Unit]
Description=MySQL server daemon
Documentation=/home/application/mysql/man
After=network.target

[Service]
Type=forking
ExecStart={{mysql_base}}/mysql.server start
ExecReload={{mysql_base}}/mysql.server reload
ExecStop={{mysql_base}}/mysql.server stop
Restart={{mysql_base}}/mysql.server restart
PrivateTmp=True

[Install]
WantedBy=multi-user.target

3.8、group_vars/mysql-server

 [root@ansible-control lnmp]# cat group_vars/mysql-server 
port: 3306
mysql_base: /usr/local/mysql
mysql_data: /usr/local/mysql/data
user: msyql
mysql_pid: /usr/local/mysql/data/mysqld_safe.pid
mysql_sock: /usr/local/mysql/data/mysql.sock
mysql_logs: /usr/local/mysql/logs
login_user: root
login_password: root1234
mysql_sock: /usr/local/mysql/data/mysql.sock

4、安装php

4.1、软件下载地址

https://www.php.net/distributions/php-7.4.16.tar.gz

4.2、目录结构

[root@ansible-control lnmp]# tree php/
php/
├── files
│   ├── index.php
│   ├── mysql-5.7.41-el7-x86_64.tar.gz
│   └── php-7.4.16.tar.gz
├── handlers
├── tasks
│   └── main.yaml
└── templates
    ├── php-fpm.conf.default
    ├── php-fpm.service
    ├── php.ini-production
    ├── www.conf.default
    └── www.conf.j2

 

4.3、tasks/main.yaml

[root@ansible-control lnmp]# ll php/tasks/main.yaml 
-rw-r--r-- 1 root root 2613 Mar  1 23:25 php/tasks/main.yaml
(ansible-env) [root@ansible-control lnmp]# cat php/tasks/main.yaml 
- name: php install lib-devel
  tags: php_install
  yum:
    name:
      - gcc
      - gcc-c++
      - freetype
      - freetype-devel
      - libpng
      - libpng-devel
      - libxml2-devel
      - libmcrypt
      - libmcrypt-devel
      - mhash
      - libxml2
      - libxml2-devel
      - mcrypt
      - zlib
      - zlib-devel
      - libjpeg
      - libjpeg-devel
      - sqlite-devel
      - oniguruma
      - oniguruma-devel
      - expat-devel
    enablerepo: epel
    state: installed

- name: unzip mysql tar
  tags:
    - php_install
  unarchive:
    src: mysql-5.7.41-el7-x86_64.tar.gz
    dest: /usr/local

- name: create software link
  tags:
    - php_install
  file:
    src: /usr/local/mysql-5.7.41-el7-x86_64
    dest: /usr/local/mysql
    state: link

- name: unzip php tar
  tags:
    - php_install
  unarchive:
    src: php-7.4.16.tar.gz
    dest: /root/

- name: php compile install
  tags: php_install
  shell: "cd {{install_dir}} && ./configure --prefix={{prefix}} --with-config-file-path={{prefix}}/etc/ --with-mysqli={{mysql_base}}/bin/mysql_config --with-pdo-mysql={{mysql_base}} --with-expat --with-jpeg --with-freetype --enable-soap --enable-mbstring=all --enable-sockets --enable-gd 
--enable-fpm --with-fpm-user=php --with-fpm-group=php && make && make install"

- name: groupadd
  tags:
    - php_install
  group:
    name: php

- name: useradd
  tags:
    - php_install
  user:
    name: php
    group: php
    shell: /sbin/nologin
    create_home: no

- name: copy php.ini
  tags:
    - php_install
    - copy_phpini
  template:
    src: php.ini-production
    dest: /usr/local/php-7.4.16/etc/php.ini
    backup: yes 

- name: copy php-fpm
  tags:
    - php_install
    - copy_phpini
  template:
    src: php-fpm.conf.default
    dest: /usr/local/php-7.4.16/etc/php-fpm.conf
    backup: yes

- name: copy www.conf
  tags:
    - php_install
    - copy_phpini
  template:
    src: www.conf.j2
    dest: /usr/local/php-7.4.16/etc/php-fpm.d/www.conf
    backup: yes

- name: configure php-fpm server
  tags:
    - php_install
  template:
    src: php-fpm.service
    dest: /usr/lib/systemd/system/php-fpm.service
    mode: 755

- name: systemctl daemon-reload
  tags:
    - php_install
  shell: systemctl daemon-reload

- name: start php-fpm
  tags:
    - php_install
  systemd:
    name: php-fpm
    state: started
    enabled: yes

- name: www dir
  tags: 
    - php_install
  file:
    path: /var/www
    state: directory
    owner: php
    mode: 0755

- name: test php page
  tags:
    - php_install
  copy:
    src: index.php
    dest: /var/www
    owner: php
    mode: 0755

4.3、templates/php-fpm.conf.default

# 文件的来源
scp root@192.168.10.17:/usr/local/php-7.4.16/etc/php-fpm.conf.default /opt/lnmp/php/templates/

[root@ansible-control php]# cat templates/php-fpm.conf.default 
;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP's install
; prefix (/usr/local/php-7.4.16). This prefix can be dynamically changed by using the
; '-p' argument from the command line.

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
; Pid file
; Note: the default prefix is /usr/local/php-7.4.16/var
; Default Value: none
pid = run/php-fpm.pid

; Error log file
; If it's set to "syslog", log is sent to syslogd instead of being written
; into a local file.
; Note: the default prefix is /usr/local/php-7.4.16/var
; Default Value: log/php-fpm.log
;error_log = log/php-fpm.log

; syslog_facility is used to specify what type of program is logging the
; message. This lets syslogd specify that messages from different facilities
; will be handled differently.
; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON)
; Default Value: daemon
;syslog.facility = daemon

; syslog_ident is prepended to every message. If you have multiple FPM
; instances running on the same server, you can change the default value
; which must suit common needs.
; Default Value: php-fpm
;syslog.ident = php-fpm

; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
;log_level = notice

; Log limit on number of characters in the single line (log entry). If the
; line is over the limit, it is wrapped on multiple lines. The limit is for
; all logged characters including message prefix and suffix if present. However
; the new line character does not count into it as it is present only when
; logging to a file descriptor. It means the new line character is not present
; when logging to syslog.
; Default Value: 1024
;log_limit = 4096

; Log buffering specifies if the log line is buffered which means that the
; line is written in a single write operation. If the value is false, then the
; data is written directly into the file descriptor. It is an experimental
; option that can potentionaly improve logging performance and memory usage
; for some heavy logging scenarios. This option is ignored if logging to syslog
; as it has to be always buffered.
; Default value: yes
;log_buffering = no

; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0

; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated.  This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;emergency_restart_interval = 0

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;process_control_timeout = 0

; The maximum number of processes FPM will fork. This has been designed to control
; the global number of processes when using dynamic PM within a lot of pools.
; Use it with caution.
; Note: A value of 0 indicates no limit
; Default Value: 0
; process.max = 128

; Specify the nice(2) priority to apply to the master process (only if set)
; The value can vary from -19 (highest priority) to 20 (lowest priority)
; Note: - It will only work if the FPM master process is launched as root
;       - The pool process will inherit the master process priority
;         unless specified otherwise
; Default Value: no set
; process.priority = -19

; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
;daemonize = yes

; Set open file descriptor rlimit for the master process.
; Default Value: system defined value
;rlimit_files = 1024

; Set max core size rlimit for the master process.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0

; Specify the event mechanism FPM will use. The following is available:
; - select     (any POSIX os)
; - poll       (any POSIX os)
; - epoll      (linux >= 2.5.44)
; - kqueue     (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0)
; - /dev/poll  (Solaris >= 7)
; - port       (Solaris >= 10)
; Default Value: not set (auto detection)
;events.mechanism = epoll

; When FPM is built with systemd integration, specify the interval,
; in seconds, between health report notification to systemd.
; Set to 0 to disable.
; Available Units: s(econds), m(inutes), h(ours)
; Default Unit: seconds
; Default value: 10
;systemd_interval = 10

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;

; Multiple pools of child processes may be started with different listening
; ports and different management options.  The name of the pool will be
; used in logs and stats. There is no limitation on the number of pools which
; FPM can handle. Your system will tell you anyway :)

; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
; Relative path can also be used. They will be prefixed by:
;  - the global prefix if it's been set (-p argument)
;  - /usr/local/php-7.4.16 otherwise
include={{prefix}}/etc/php-fpm.d/*.conf

4.4、templates/php-fpm.service

[root@ansible-control php]# cat templates/php-fpm.service 
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target

[Service]
Type=forking
PIDFile={{prefix}}/var/run/php-fpm.pid
ExecStart={{prefix}}/sbin/php-fpm
ExecReload=/bin/kill -USR2 $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

4.5、templates/php.ini-production

scp root@192.168.10.17:/root/php-7.4.16/php.ini-production /opt/lnmp/php/templates/

 [root@ansible-control php]# cat templates/php.ini-production | grep -Ev '^;|^$'
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = On
expose_php = On
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
[filter]
[iconv]
[imap]
[intl]
[sqlite3]
[Pcre]
[Pdo]
[Pdo_mysql]
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[COM]
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[dba]
[opcache]
[curl]
[openssl]
[ffi]
php.ini - 直接从源代码包复制即可

4.6、templates/www.conf.j2 

scp root@192.168.10.17:/usr/local/php-7.4.16/etc/php-fpm.d/www.conf.default .

 [root@ansible-control php]# cat templates/www.conf.j2 
[www]
user = {{ user }}
group = {{ user }}
listen = {{ansible_default_ipv4.address}}:9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

4.7、group_vars/php-server 

[root@ansible-control lnmp]# cat group_vars/php-server 
install_dir: /root/php-7.4.16 
prefix: /usr/local/php-7.4.16
mysql_base: /usr/local/mysql
user: php
nginx_ip: 192.168.10.18

5、group_vars/all

 [root@ansible-control lnmp]# cat group_vars/all 
db_name: wpdb
db_user: wp
db_pwd: 123456
mysql_ip: 192.168.10.19

6、wordpress布署

6.1、软件下载

https://cn.wordpress.org/latest-zh_CN.tar.gz

6.2、目录结构

 [root@ansible-control lnmp]# tree wordpress/
wordpress/
├── files
│   └── wordpress-6.1.1-zh_CN.tar.gz
├── handlers
├── tasks
│   └── main.yaml
└── templates
    └── wp-config-sample.php

6.3、wordpress/tasks/main.yaml 

 [root@ansible-control lnmp]# cat wordpress/tasks/main.yaml 
- name: unzip wordpress
  tags: worldpress
  unarchive:
    src: wordpress-6.1.1-zh_CN.tar.gz
    dest: /var/www
    owner: php

- name: copy wp-config.php
  tags: worldpress
  template:
    src: wp-config-sample.php
    dest: /var/www/wordpress/wp-config.php
    owner: php
    mode: 0755

6.4、准备wp-config-sample.php

scp root@192.168.10.17:/var/www/wordpress/wp-config-sample.php .

6.5、安装wordpress

http://192.168.10.18/wordpress/wp-admin/install.php

 

 

6.6、安装成功

7、整个项目完整的目录结构

[root@ansible-control lnmp]# tree /opt/lnmp/
/opt/lnmp/
├── base
│   ├── files
│   ├── handlers
│   ├── tasks
│   │   └── main.yaml
│   └── templates
├── group_vars
│   ├── all
│   ├── mysql-server
│   ├── nginx-server
│   └── php-server
├── mysql
│   ├── files
│   │   └── mysql-5.7.41-el7-x86_64.tar.gz
│   ├── handlers
│   ├── tasks
│   │   └── main.yaml
│   └── templates
│       ├── my.cnf.j2
│       ├── mysql.server
│       └── mysql.service
├── nginx
│   ├── files
│   │   ├── index.php
│   │   └── nginx-1.12.2.tar.gz
│   ├── handlers
│   │   └── main.yaml
│   ├── tasks
│   │   └── main.yaml
│   └── templates
│       ├── nginx.conf.j2
│       └── nginx.service
├── php
│   ├── files
│   │   ├── index.php
│   │   ├── mysql-5.7.41-el7-x86_64.tar.gz
│   │   └── php-7.4.16.tar.gz
│   ├── handlers
│   ├── tasks
│   │   └── main.yaml
│   └── templates
│       ├── php-fpm.conf.default
│       ├── php-fpm.service
│       ├── php.ini-production
│       ├── www.conf.default
│       └── www.conf.j2
├── run.yaml
└── wordpress
    ├── files
    │   └── wordpress-6.1.1-zh_CN.tar.gz
    ├── handlers
    ├── tasks
    │   └── main.yaml
    └── templates
        └── wp-config-sample.php

 

posted @ 2023-03-02 15:42  小粉优化大师  阅读(89)  评论(0编辑  收藏  举报