banner
云野阁

云野阁

闲云野鹤,八方逍遥

Ansible Knowledge Organization

🔜What is Ansible?🔚

Ansible is an IT automation tool. Its main application scenarios include configuration management, software deployment, continuous delivery, and advanced task orchestration for smooth rolling updates without downtime.

Ansible provides open-source automation, reducing complexity and running anywhere. With Ansible, you can automate almost any task.

Architecture#

Ansible: The core program of Ansible.
HostInventory: Records information about hosts managed by Ansible, including ports, passwords, IPs, etc.
Playbooks: YAML format files that define multiple tasks in one file, specifying which modules the hosts need to call to complete functionalities.
CoreModules: Core modules, primarily used to complete management tasks by calling core modules.
CustomModules: Custom modules that accomplish functionalities that core modules cannot, supporting multiple languages.
ConnectionPlugins: Connection plugins used for communication between Ansible and hosts.

1

Important Concepts of Ansible#

Control Node#

The control node is the machine that runs the Ansible CLI tool. It is responsible for communicating with managed nodes (controlled nodes), issuing commands, and executing tasks.

Managed Node (Controlled Node)#

Also known as "hosts," these are the target devices managed by Ansible. The Ansible control node executes tasks on these machines. Managed nodes do not need to install any agents.

Inventory#

A list of target hosts or nodes to be managed. It is the configuration file used by Ansible to define target host information, supporting static or dynamic host inventories. It is also used for group assignments, allowing node selection in plays and bulk variable assignments.

Playbook#

A playbook is the core part of Ansible configuration management, consisting of a set of YAML files used to automate task execution. Playbooks can execute multiple steps (e.g., installing software, starting services, etc.) and define execution order, tasks, etc.

Modules#

Modules are the units that perform actual tasks in Ansible. They are highly reusable code blocks responsible for executing specific operations (such as installing packages, configuring files, etc.).

Roles#

Roles are a way to organize playbooks, grouping multiple tasks, files, templates, variables, etc., into a complete functional module. Roles help break down complex configurations into reusable components. Reusable Ansible content that can be used within plays.

Tasks#

Tasks are specific operations defined in a playbook. Each task typically calls an Ansible module to perform a specific operation. It is more suitable for ad-hoc execution scenarios.

Plugins#

Code snippets that extend the core functionality of Ansible. Plugins can control how you connect to managed nodes (connection plugins), manipulate data (filter plugins), and even control what is displayed in the console (callback plugins).

Collections#

The distribution format for Ansible content, which can include playbooks, roles, modules, and plugins.

Ansible Task Execution Modes#

The Ansible system can be divided into two categories based on how the control host operates on managed nodes: ad-hoc and playbook:

  • Ad-hoc mode (point-to-point mode)
      Uses a single module and supports batch execution of a single command. Ad-hoc commands are commands that can be quickly entered and do not need to be saved.
  • Playbook mode (playbook mode)
      This is the main management method of Ansible and is key to Ansible's powerful functionality. Playbooks complete a type of functionality through multiple tasks. You can simply understand a playbook as a configuration file that combines multiple ad-hoc operations.

Ansible Installation (CentOS 7)#

Modify the system mirror source to Aliyun mirror source

cd /etc/yum.repos.d
mv CentOS-Base.repo CentOS-Base.repo.bak
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

Method 1: Install using yum#

Install the epel-release package and Ansible

yum install epel-release -y
yum install ansible -y
# Check version
 ansible --version

Method 2: Install using pip#

yum install python3 python3-devel python3-pip -y
python3 -m pip install ansible
# Check version
 ansible --version

Ansible Configuration File#

The priority order for reading the configuration file is as follows:

  1. Check the path file pointed to by the environment variable ANSIBLE_CONFIG (export ANSIBLE_CONFIG=xxxx);
  2. Check the ansible.cfg configuration file in the current project directory;
  3. ~/.ansible.cfg, check the ansible.cfg configuration file in the current directory;
  4. /etc/ansible/ansible.cfg, check the configuration file in the etc directory.

Ansible Passwordless Login#

Root User#

Set up SSH passwordless login on the control node and transfer the key to the managed node.

ssh-keygen -t dsa -f ~/.ssh/id_dsa -P ""
ssh-copy-id -i ~/.ssh/id_dsa.pub root@managed_host_ip

Regular User#

Both the control node and the managed node need to have a regular user; here we take the test user as an example.

# Add test user and set password
useradd test
passwd test

Set up SSH passwordless login on the control node and transfer the key to the managed node.

ssh-keygen -t dsa -f ~/.ssh/id_dsa -P ""
ssh-copy-id -i ~/.ssh/id_dsa.pub test@managed_host_ip

Modify the test user's sudo permissions on all hosts.

visudo
test    ALL=(ALL)       NOPASSWD: ALL

Modify the configuration file on the control node /etc/ansible/ansible.cfg to set regular user privilege escalation.

vi /etc/ansible/ansible.cfg
# Uncomment the following content
[privilege_escalation]
become=True   # Enable privilege escalation
become_method=sudo  # Escalate to root user privileges via sudo
become_user=root  # Execute tasks as root user
become_ask_pass=False  # Disable password prompt

Ansible Ad-Hoc and Common Modules#

Ad-Hoc#

Ad-hoc refers to the command line mode, which ends after execution.

Command Syntax Structure:

ansible 'groups' -m command -a 'df -h', its meaning is as follows:

2

Execution Process:

  1. Load the configuration file, default /etc/ansible/ansible.cfg;
  2. Find the corresponding host configuration file, locate the host or group to be executed:
  3. Load the corresponding module file, such as command;
  4. Use ansible to generate the corresponding temporary py file from the module or command and transfer that file to the remote server's corresponding execution user $HOME/.ansible/tmp/ansible-tmp-number/XXX.PY;
  5. The remote host executes that file;
  6. Execute and return the result;
  7. Delete the temporary py file, sleep 0 to exit;

Execution Status:

When using ad-hoc to execute a remote command, pay attention to the color of the returned result:

  • Green: Indicates that the managed node has not been modified
  • Yellow: Indicates that changes were detected on the managed node
  • Red: Indicates that an error occurred; pay attention to the prompts

Common Modules#

Command Module#

Basic Format and Common Parameters

ansible 'group/IP' -m command -a '[parameters] command'
ParameterOptionsMeaning
chdirchdir /optSwitch to the specified directory when executing ansible
createscreates /data/fileSkip execution if the file exists
removesremoves /data/fileExecute if the file exists

[root@121 ~]# ansible webservers -m command -a 'ls /root'

192.168.1.122 | CHANGED | rc=0 >>
anaconda-ks.cfg
test.txt
192.168.1.121 | CHANGED | rc=0 >>
anaconda-ks.cfg
test

[root@121 ~]# ansible webservers -m command -a 'creates=/root/test.txt hostname'
192.168.1.122 | SUCCESS | rc=0 >>
skipped, since /root/test.txt exists
192.168.1.121 | CHANGED | rc=0 >>
121
[root@121 ~]# ansible webservers -m command -a 'removes=/root/test.txt hostname'
192.168.1.122 | CHANGED | rc=0 >>
122
192.168.1.121 | SUCCESS | rc=0 >>
skipped, since /root/test.txt does not exist
[root@121 ~]#

The shell module supports pipes, while the command module does not

Shell Module#

Basic Format and Common Parameters

ansible 'group/IP/all' -m shell -a '[parameters] command'

ansible webservers -m shell -a 'ps aux | grep sshd'

Yum/Apt Module#

Common ParametersFunction
nameThe name of the service to be installed
state=present (default)/absentStatus, absent means uninstall the service

Install service#

ansible webservers -m yum -a 'name=httpd'

Uninstall service#

ansible webservers -m yum -a 'name=httpd state=absent'

Copy Module#

Basic Format and Common Parameters

ansible < > -m copy -a 'src=   dest=   [owner= ] [mode=]   '
Common ParametersFunctionNotes
srcSpecify the path of the source file (supports directories or files)If the source is a directory, the target must also be a directory
destSpecify the location of the target file (must be an absolute path)1. If the source is a directory, the target must be a directory 2. The target file will overwrite the original content if it already exists
modeSet the permissions of the target file
ownerSet the owner of the target file
groupSet the group of the target file
contentDirectly specify the content of the target fileCannot be used simultaneously with the src parameter

ansible dbservers -m copy -a 'src=/etc/fstab dest=/opt/fstab.bak owner=root mode=640'
ansible dbservers -a 'ls -l /opt'
ansible dbservers -a 'cat /opt/fstab.bak'

Systemd Module#

Common ParametersFunction
nameSpecify the name of the service to be controlled
stateSpecify the service status, optional values: stopped, started, reloaded, restarted, status
enabledSet whether the service starts on boot, yes for start, no for not starting
daemon_reloadSet to yes to restart the systemd service to make unit files effective

ansible webservers -m systemd -a 'name=firewalld state=started enabled=yes'

File Module#

Basic Format and Common Parameters

ansible < > -m file -a ''
Common ParametersFunctionNotes
pathSpecify the path on the remote serverCan also be written as dest or name
stateDefine operation type: - directory: create directory - touch: create file - link: create soft link - hard: create hard link - absent: delete directory/file/link
modeSet file/directory permissionsDefault values: - File 644 - Directory 755
ownerSet the ownerDefault root
groupSet the groupDefault root
recurseRecursive modificationyes or no
srcSource file on the target host (different from the copy module)

Create /data directory, authorize test group#

ansible webservers -m file -a 'owner=test group=test mode=644 path=/data state=directory recurse=yes '

Group Module#

Basic Format and Common Parameters

ansible <group/IP/all> -m group -a ' '
ParameterFunctionOptional Values/Description
nameSpecify username (required)
stateControl account creation or deletionpresent: create account absent: delete account
systemSpecify whether it is a system accountyes: system account no: regular account
gidSpecify group ID (modify user group)Numeric format (e.g., 1001)

ansible webservers -m group -a 'name=www gid=666 state=present '

User Module#

Basic Format and Common Parameters

ansible <group/IP/all> -m user -a ' '
ParameterFunctionOptional Values/Description
nameSpecify username (required)
stateControl account creation or deletionpresent: create absent: delete
systemSpecify whether it is a system accountyes: system account (e.g., mysql) no: regular account
uidSpecify user UIDNumeric (e.g., 1001), must be unique
groupSpecify user primary groupGroup name or GID (must exist beforehand)
groupsSpecify additional groups for the userList of group names (e.g., groups=wheel,admin)
shellSet the user's default shellPath (e.g., /bin/bash)
create_homeWhether to create a home directoryyes: automatically create no: do not create (default behavior may depend on the system)
passwordSet user passwordIt is recommended to use an encrypted string (e.g., password="$6$encrypted_string")
removeWhether to delete the home directory when deleting the user (requires state=absent)yes: delete home directory no: keep
  1. Create www user, specify uid 666, primary group www
ansible webservers -m user -a 'name=www uid=666 group=www shell=/sbin/nologin create_home=no'
  1. Create db user, primary group is root, additional groups are adm, sys
ansible webservers -m user -a 'name=db group=root groups=adm,sys append=yes shell=/bin/bash create_home=yes'
  1. Create a ddd user with password 123, needs to log in to the system

(1) Password encryption

ansible localhost -m debug -a "msg={{ '123' | password_hash('sha512', 'salt123') }}"
ParameterFunctionNotes
sha512Specify hash algorithm (recommended)Supports sha256/md5, but sha512 is more secure 2
salt123Custom salt valueSalt value must be alphanumeric; containing - or _ will cause hash failure (returns *0) 5
password_hash filterConverts plaintext password to encrypted stringMust be called through {{ }} and used with variables

localhost | SUCCESS => {
"msg": "$6$salt123$c806NQq6Oqk29MjZdmHxTw7sK3BB1K498o7sZC47UiwQmjx5NJyi5ZhWWGngXf3UfyELHQ1wRJ//oW/Y94azv0"
}

(2) Write the creation command to complete the creation

ansible webservers -m user -a "name=ddd password=encrypted_password_from_step_one shell=/bin/bash create_home=yes"
  1. Create a dev user and generate the corresponding key for it
ansible webservers -m user -a 'name=dev generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa'

Mount Module#

Common ParametersFunction
srcSpecify the device or partition path to be mounted.
pathSpecify the target path to mount to.
fstypeSpecify the file system type to mount.
stateSpecify the mount status, optional values are mounted, (temporary mount) present (permanent mount), unmounted (temporary unmount), or absent (unmount).
optsSpecify mount options, such as mount options or parameters.

Mount the /nfs directory on 192.168.1.121 to the /nfs directory on 192.168.1.122#

ansible 192.168.1.122 -m mount -a 'src=192.168.1.121:/nfs path=/nfs fstype=nfs opts=defaults state=present '

Cron Module#

Basic Format and Common Parameters

ansible <group/IP/all> -m cron -a ' '
Common ParametersFunction
minute/hour/day/month/weekdayMinute/Hour/Day/Month/Week
jobThe command to be executed by the scheduled task
nameThe name of the scheduled task
userSpecify which user the scheduled task belongs to, default is root
statepresent means add (can be omitted), absent means remove.

Add a scheduled task to execute /data/test.sh script every day at 19:00, task name is script-test.#

ansible webservers -m cron -a 'name="script-test" hour=19 minute=00 job="/bin/bash /data/test.sh" '

Comment out the scheduled task#

ansible webservers -m cron -a 'name="script-test" hour=19 minute=00 job="/bin/bash /data/test.sh" disabled=yes '

Delete the scheduled task#

ansible webservers -m cron -a 'name="script-test" hour=19 minute=00 job="/bin/bash /data/test.sh" state=absent '

Archive Module#

Common ParametersFunction
pathSpecify the path of the source directory or file to be archived.
destSpecify the output path of the archive file.
formatSpecify the format of the archive file, can be zip, tar, gz, or bzip2. Default is tar format.
removeSpecify whether to delete the source directory or file after archiving. Optional values are yes or no. Default is no, meaning do not delete the source directory or file.

Unarchive Module#

Common ParametersFunction
copySpecify whether to copy the archive file to the remote node for decompression.
remote_src(Deprecated) Use the copy parameter instead.
srcSpecify the path of the archive file to be decompressed, can be local or remote path.
destSpecify the target directory to which the files will be decompressed.
createsSpecify a file path; if that file already exists, do not perform the decompression operation.
remote_tmpUsed to specify the temporary directory on the remote node. Default is /tmp.
  1. Decompress the compressed package from the control end to the managed end:

ansible webservers -m unarchive -a 'src=./test.tar.gz dest=/mnt'
2. Decompress the compressed package from the managed end to the managed end:

ansible webservers -m unarchive -a 'src=/tmp/config_vpn_new.zip dest=/mnt remote_src=yes'

Lineinfile Module#

Meaning: Replace | Append | Delete

ParameterOptionsMeaning
pathNoneSpecify the target file path to operate on
regexpNoneUse regular expressions to match lines in the file
lineNoneSpecify the new text content to modify or insert
insertafterNoneInsert text after the "regex matched line"
insertbeforeNoneInsert text before the "regex matched line"
stateabsent / present (default)absent deletes matching lines, present ensures text exists
backrefsyes / noyes enables regex back references, no does not operate on the file if not matched
backupNoneWhether to create a backup file before modification (boolean)
createNoneWhether to create a new file if the target file does not exist (boolean)
  1. Replace Listen in httpd.conf file with Listen8080;

ansible webservers -m lineinfile -a 'path=/etc/httpd/conf/httpd.conf regexp="^Listen" line="Listen 8080"'

  1. Add a gateway to the host:

ansible webservers -m lineinfile -a 'path=/etc/sysconfig/network-scripts/ifcfg-eth1 line="GATEWAY=172.16.1.200"'
3. Delete the host's gateway:

ansible webservers -m lineinfile -a 'path=/etc/sysconfig/network-scripts/ifcfg-ethl regexp="^GATEWAY" state=absent'

Ansible Playbook#

A playbook is a text file written in YAML syntax, consisting of plays and tasks.
play: Mainly defines the hosts or host groups to be operated on.

task: Mainly defines the specific tasks to be executed on the hosts or host groups, which can be one task or multiple tasks (modules).

A playbook consists of one or more plays, and a play can contain multiple task tasks.

It can be understood as using multiple different modules to accomplish a task together.

Playbook Writing Format#

Playbooks are written in YAML syntax, with a clear structure and strong readability.

SyntaxDescription
IndentationYAML uses a fixed indentation style to represent hierarchical structures, with each indentation consisting of two spaces, and tabs cannot be used
ColonAll colons except those at the end must have a space after them
HyphenIndicates list items, using a short dash followed by a space. Multiple items use the same indentation level as the same list

Playbook Application Example:#

Install Nginx#

(1) Write the playbook file

vi nginx.yml

- hosts: webservers
  tasks:
    - name: Install Nginx
      yum:
        name: nginx
        state: present
    - name: Start Nginx
      systemd:
        name: nginx
        state: started
        enabled: yes

(2) Check if the file has syntax errors

ansible-playbook --syntax nginx.yml
or
ansible-playbook --syntax-check nginx.yml

[root@121 data]# ansible-playbook --syntax nginx.yml

playbook: nginx.yml

(3) Simulate execution

ansible-playbook -C nginx.yml

[root@121 data]# ansible-playbook -C nginx.yml

PLAY [webservers] **************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.1.122]
ok: [192.168.1.121]

TASK [Install Nginx] *********************************************************
changed: [192.168.1.122]
changed: [192.168.1.121]

TASK [Start Nginx] *********************************************************
changed: [192.168.1.121]
changed: [192.168.1.122]

PLAY RECAP *********************************************************************
192.168.1.121 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.122 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

(4) Actual execution

ansible-playbook nginx.yml

[root@121 data]# ansible-playbook nginx.yml

PLAY [webservers] **************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.1.122]
ok: [192.168.1.121]

TASK [Install Nginx] *********************************************************
changed: [192.168.1.121]
changed: [192.168.1.122]

TASK [Start Nginx] *********************************************************
changed: [192.168.1.122]
changed: [192.168.1.121]

PLAY RECAP *********************************************************************
192.168.1.121 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.122 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Install NFS Service#

Task Order:

  • Download NFS program
  • Mount NFS configuration file (set trigger, modify configuration file to make configuration take effect)
  • Initialize NFS settings (set user, group, permissions)
  • Start NFS

The trigger set is handles, and in the second step, add notify information. When the configuration file is modified, handles will obtain the information from notify to restart the NFS service, making the configuration take effect again.

File Preparation:

# Create a directory to store this project
mkdir nfs
# Create NFS configuration file, write the following content
vi exports.j2

/ansible_test 192.168.1.0/24(rw,all_squash,anonuid=7777,anongid=7777)

Place the Ansible configuration file ansible.cfg and hosts in advance in this project directory.

Create NFS Playbook

vi nfs.yml

- hosts: webservers
  tasks:
    - name: Download NFS
      yum:
        name: nfs-utils
        state: present
    - name: Configure NFS
      copy:
        src: ./exports.j2
        dest: /etc/exports
      notify: restart nfs  # Trigger information
    - name: Init group
      group:
        name: bbb
        gid: 7777
    - name: Init user
      user:
        name: bbb
        uid: 7777
        group: bbb
        shell: /sbin/nologin
        create_home: no
    - name: Init directory
      file:
        path: /ansible_test
        state: directory
        owner: bbb
        group: bbb
        mode: "0755"
    - name: Start NFS
      systemd:
        name: nfs
        state: started
        enabled: yes
  handlers:  # Trigger
    - name: Restart NFS
      systemd:
        name: nfs
        state: restarted

Execute and Verify

 ansible-playbook --syntax-check nfs.yml
 ansible-playbook -C nfs.yml
 ansible-playbook nfs.yml
 
 # Check NFS service
 showmount -e 192.168.1.121
 showmount -e 192.168.1.122
 
 # Mount test
 mount -t nfs 192.168.1.121:/ansible_test /data/test
 mount -t nfs 192.168.1.122:/ansible_test /data/test1

[root@121 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 898M 0 898M 0% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.7M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root 17G 1.7G 16G 10% /
/dev/sda1 1014M 153M 862M 16% /boot
tmpfs 182M 0 182M 0% /run/user/0
192.168.1.121:/ansible_test 17G 1.7G 16G 10% /data/test
192.168.1.122:/ansible_test 17G 2.2G 15G 13% /data/test1

Install Rsync Service#

Rsync Server:#

Task Order:

  • Download Rsync program
  • Mount Rsync configuration file (set trigger, modify configuration file to make configuration take effect)
  • Initialize Rsync settings (set user, group, permissions)
  • Create virtual user and password
  • Start Rsync

The trigger set is handles. When the configuration file or virtual user password is modified, handles will obtain the information from notify to restart the Rsync service, making the configuration take effect again.

File Preparation:

# Create a directory to store this project
mkdir rsync
# Copy Rsync configuration file rsyncd.conf and modify it (you can first manually download Rsync, copy the configuration file, and then uninstall, or directly use the following content)

uid = ansible_www
gid = ansible_www
port = 873
fake super = yes
use chroot = yes
max connections = 4
timeout = 900
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
[backup]
path = /backup

Place the Ansible configuration file ansible.cfg and hosts in advance in this project directory.

Create Rsync Playbook

vi rsync.yml

- hosts: webservers
  tasks:
    - name: Download Rsync
      yum:
        name: rsync
        state: present
    - name: Configure Rsync
      copy:
        src: ./rsyncd.conf
        dest: /etc/rsyncd.conf
        owner: root
        group: root
        mode: "0644"
      notify: restart rsync
    - name: Init group
      group:
        name: ansible_www
        gid: 8888
    - name: Init user
      user:
        name: ansible_www
        uid: 8888
        group: ansible_www
        shell: /sbin/nologin
        create_home: no
    - name: Init directory
      file:
        path: /backup
        state: directory
        owner: ansible_www
        group: ansible_www
        mode: "0755"
        recurse: yes
    - name: Init Rsync user password
      copy:
        content: "rsync_backup:123456"
        dest: /etc/rsync.passwd
        owner: root
        group: root
        mode: 0600
      notify: restart rsync
    - name: Start Rsync
      systemd:
        name: rsyncd
        state: started
        enabled: yes
  handlers:
    - name: Restart Rsync
      systemd:
        name: rsyncd
        state: restarted

Execute and Verify

ansible-playbook --syntax-check rsync.yml 
ansible-playbook -C rsync.yml 
ansible-playbook rsync.yml  

# Verify
rsync -avz host_group [email protected]::backup
Rsync Client:#

Task Order:

  • Push the script to the specified path on the managed end
  • Configure the scheduled task

Create Rsync Client Playbook

vi rsync-client.yml

- hosts: localhost
  tasks:
    - name: Create scripts path
      file:
        path: /scripts
        owner: root
        group: root
        state: directory
        mode: 0755
    - name: Push scripts
      copy:
        src: test.sh
        dest: /scripts/test.sh
        owner: root
        group: root
        mode: 0755
    - name: Contable job
      cron:
        name: "Push backup data"
        minute: "*/1"
        job: "/bin/bash /scripts/test.sh &>/dev/null"

Create test.sh for testing

#!/bin/bash
RSYNC_PASSWORD="123456"  rsync -avz /backup/ [email protected]::backup

Check if there are scheduled tasks

crontab -l

#Ansible: Push backup data

*/1 * * * * /bin/bash /scripts/test.sh &>/dev/null

Use Ansible to Deploy Multi-node PhpMyAdmin#

Project Requirements#
  • Use LNMP to deploy PhpMyAdmin
  • Nginx (Haproxy) as load balancer
  • Redis for session persistence
Host Planning#
HostnameIPPurpose
121192.168.1.121Ansible control node, Nginx+PHP
122192.168.1.122Ansible managed node, Nginx+PHP
123192.168.1.123Ansible managed node, Nginx (Haproxy)
124192.168.1.124Ansible managed node, Nginx (Haproxy)
125192.168.1.125Ansible managed node, Redis
Deployment Steps#
Environment Preparation

Ensure that Ansible is prepared on node 121 and set up passwordless login for the above 5 machines, refer to the configuration process above.

# Create a directory to store project files
mkdir /data/phpmyadmin
# Copy the Ansible configuration file `ansible.cfg` and `hosts` to the phpmyadmin directory, and modify the configuration
cp /etc/ansible/ansible.cfg /data/phpmyadmin/ansible.cfg
# Modify the path in the configuration file and uncomment
inventory      = /data/phpmyadmin/host_group

cp /etc/ansible/hosts /data/phpmyadmin/host_group
# Modify the host group
[webservers]
192.168.1.121
192.168.1.122

[dbservers]
192.168.1.125

[lbservers]
192.168.1.123
192.168.1.124

Confirm whether the configuration file reading path is the current project's /data/phpmyadmin/ansible.cfg

[root@121 phpmyadmin]# ansible --version
ansible 2.9.27
config file = /data/phpmyadmin/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Jun 28 2022, 15:30:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

Verify whether all hosts can ping

[root@121 phpmyadmin]# ansible all -m ping
192.168.1.122 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.1.124 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.1.123 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.1.125 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.1.121 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}

Install Redis

Task Order:

  • Download Redis program
  • Mount Redis configuration file (set trigger, modify configuration file to make configuration take effect)
  • Start Redis

Set the trigger handles to restart the Redis service.

(1) Copy the Redis configuration file redis.conf to the /data/phpmyadmin/files directory

mkdir /data/phpmyadmin/files
# If there is no redis.conf file, you can first use the command yum -y install redis to download it and then copy it
cp /etc/redis.conf /data/phpmyadmin/files
# Modify the configuration file, add the IPs of the hosts where Redis will be installed
bind 127.0.0.1 192.168.1.125

(2)

vi redis.yml

- hosts: dbservers
  tasks:
    - name: Download Redis
      yum:
        name: redis
        state: present
    - name: Configure Redis
      copy:
        src: ./files/redis.conf
        dest: /etc/redis.conf
        owner: redis
        group: root
        mode: 0640
      notify: restart redis
    - name: Start Redis
      systemd:
        name: redis
        state: started
        enabled: yes
  handlers:
    - name: Restart Redis
      systemd:
        name: redis
        state: restarted

(3) Install and test

ansible-playbook --syntax-check redis.yml
ansible-playbook -C redis.yml
ansible-playbook redis.yml
# Test, previously installed Redis on control node 121, can directly test on 121
# Note the firewall port
redis-cli -h 192.168.1.125

[root@121 phpmyadmin]# redis-cli -h 192.168.1.125
192.168.1.125:6379>

Install MariaDB

Install MariaDB on 192.168.1.125

 yum -y install mariadb-server
 systemctl start mariadb
 systemctl enable mariadb
 # Set root user password
 mysqladmin -uroot password '123456'
 # Log in to create user
 mysql -uroot -p123456
 # Create database
 create database php_db;
 # Create database user
 grant all on php_db.* to php_user@'%' identified by '123456';
Install Nginx, PHP

Task Order:

  • Download Nginx, PHP programs
  • Mount Nginx, PHP configuration files (set trigger, modify configuration file to make configuration take effect)
  • Initialize Nginx settings (set user, group, permissions)
  • Start Nginx, PHP

Set the trigger handles to restart Nginx, PHP services.

(1) Set up PHP7 download source, execute on 121, 122

rpm -Uvh https://mirror.webtatic.com/yum/el7/epel-release.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

(2) Copy the Nginx and PHP configuration files to the /data/phpmyadmin/files directory and modify the configuration

# Nginx configuration file
cp /etc/nginx/nginx.conf /data/phpmyadmin/files
# PHP configuration file
cp /etc/php.ini /data/phpmyadmin/files
cp /etc/php-fpm.d/www.conf /data/phpmyadmin/files

Modify the Nginx configuration file to change the user to www.

vi nginx.conf
user www;

In the /data/phpmyadmin/files directory, create a new Nginx proxy file for phpmyadmin

vi phpmyadmin.conf

server {
    listen 80;
    server_name ansible.phpmyadmin.local;

    # Ensure this path matches the actual path of phpMyAdmin
    root /code/phpmyadmin;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        # The absolute path must be complete and correct
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;

        # Add key parameters
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_intercept_errors on;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

Modify the PHP configuration file php.ini, set Redis connection.

vi php.ini
[Session]

session.save_handler = redis
session.save_path = "tcp://192.168.1.125:6379?weight=1&timeout=2.5"

Modify the PHP configuration file www.conf, set user and group, and comment out some settings.

vi www.conf

[www]
user = www
group = www

;php_value[session.save_handler] = files
;php_value[session.save_path]    = /var/lib/php/session

(3) Download PhpMyAdmin

# Download PhpMyAdmin program to /data/phpmyadmin/files directory
curl -O https://files.phpmyadmin.net/phpMyAdmin/5.2.2/phpMyAdmin-5.2.2-all-languages.zip

# Unzip the program
unzip phpMyAdmin-5.2.2-all-languages.zip
# Copy and modify the configuration file to connect to the MariaDB database
cp phpMyAdmin-5.2.2-all-languages/config.sample.inc.php config.inc.php
# Change localhost to 192.168.1.125
$cfg['Servers'][$i]['host'] = '192.168.1.125';

(4) Create Nginx-PHP Playbook

vi nginx-php.yml

- hosts: webservers
  tasks:
    - name: Download Nginx
      yum:
        name: nginx
        state: present
    - name: Download PHP
      yum:
        name: "{{ packages }}"
      vars:
        packages:
        - php72w
        - php72w-cli
        - php72w-common
        - php72w-devel
        - php72w-embedded
        - php72w-fpm
        - php72w-gd
        - php72w-mbstring
        - php72w-mysqlnd
        - php72w-opcache
        - php72w-pdo
        - php72w-xml
        - php72w-ldap
        - php72w-pecl-redis

    - name: Configure Nginx
      copy:
        src: ./files/nginx.conf
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: 0644
      notify: restart nginx
    - name: Init group www
      group:
        name: www
        gid: 666
    - name: Init user www
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: no
    - name: Start Nginx
      systemd:
        name: nginx
        state: started        
        enabled: yes

    - name: Configure php.ini
      copy:
        src: ./files/php.ini
        dest: /etc/php.ini
        owner: root
        group: root
        mode: 0644
      notify: restart php    
    - name: Configure www.conf
      copy:
        src: ./files/www.conf
        dest: /etc/php-fpm.d/www.conf
        owner: root
        group: root
        mode: 0644
      notify: restart php        
    - name: Start PHP
      systemd:
        name: php-fpm
        state: started        
        enabled: yes
        
    - name: Copy Nginx conf 
      copy:
        src: ./files/phpmyadmin.conf
        dest: /etc/nginx/conf.d/phpmyadmin.conf
      notify: restart nginx      
    - name: Create code directory
      file:
        path: /code
        state: directory
        owner: www
        group: www
        mode: "0755"
        recurse: yes    
    - name: Unarchive PhpMyAdmin   # Unzip PhpMyAdmin
      unarchive: 
        src: ./files/phpMyAdmin-5.2.2-all-languages.zip
        dest: /code/
        owner: www
        group: www
        creates: /code/phpMyAdmin-5.2.2-all-languages/config.inc.php        
    - name: Create link  # Create soft link
      file: 
        src: /code/phpMyAdmin-5.2.2-all-languages/
        dest: /code/phpmyadmin 
        state: link
    - name: Change PhpMyAdmin configuration 
      copy:
        src: ./files/config.inc.php
        dest: /code/phpMyAdmin-5.2.2-all-languages/config.inc.php  
          
        
  handlers: 
    - name: Restart Nginx
      systemd:
        name: nginx
        state: restarted
    - name: Restart PHP
      systemd:
        name: php-fpm
        state: restarted

(5) Install and test

ansible-playbook --syntax-check nginx-php.yml
ansible-playbook -C nginx-php.yml
ansible-playbook nginx-php.yml

(6) Configure hosts on your local computer C:\Windows\System32\drivers\etc\hosts

# Configure the hosts for 121 and 122 for access testing
192.168.1.121 ansible.phpmyadmin.local
192.168.1.122 ansible.phpmyadmin.local

(7) Access ansible.phpmyadmin.local in the browser, the username and password are the user php_user created when installing the MariaDB database and its password 123456.

3

4

Load Balancing Method 1: Nginx

(1) Copy the Nginx configuration file nginx.conf to the /data/phpmyadmin/files directory and rename it to nginx.conf.lb

cp /etc/nginx.conf /data/phpmyadmin/files/nginx.conf.lb

(2) Create a configuration file proxy.conf in the /data/phpmyadmin/files directory for load balancing

vi proxy.conf

upstream ansible {
    server 192.168.1.121;
    server 192.168.1.122;
}
server {
    listen 80;
    server_name ansible.phpmyadmin.local;
    location / {
        proxy_pass http://ansible;
        proxy_set_header Host $http_host;
    }

}

(3) Create lb-nginx Playbook

vi lb-nginx.yml

- hosts: lbservers
  tasks:
    - name: Download Nginx
      yum:
        name: nginx
        state: present
    - name: Configure Nginx
      copy:
        src: ./files/nginx.conf.lb
        dest: /etc/nginx/nginx.conf
      notify: restart nginx
    - name: Copy Nginx conf
      copy:
        src: ./files/proxy.conf
        dest: /etc/nginx/conf.d/proxy.conf
      notify: restart nginx
    - name: Start Nginx
      systemd:
        name: nginx
        state: started
        enabled: yes
  handlers:
    - name: Restart Nginx
      systemd:
        name: nginx
        state: restarted

(4) Install and test

ansible-playbook --syntax-check lb-nginx.yml
ansible-playbook -C lb-nginx.yml
ansible-playbook lb-nginx.yml

(5) Configure hosts on your local computer C:\Windows\System32\drivers\etc\hosts

192.168.1.123 ansible.phpmyadmin.local
192.168.1.124 ansible.phpmyadmin.local

(6) Access ansible.phpmyadmin.local in the browser, and observe the database server - user, refresh to see if the user switches between 121 and 122.

Load Balancing Method 2: Haproxy

(1) Set up Haproxy download source

rpm -Uvh https://repo.ius.io/ius-release-el7.rpm

(2) Copy /etc/haproxy/haproxy.cfg to the /data/phpmyadmin/files directory

cp /etc/haproxy/haproxy.cfg /data/phpmyadmin/files

You can first install Haproxy on any server to obtain the /etc/haproxy/haproxy.cfg file.

(3) Modify the haproxy.cfg configuration file, adding the following content.

frontend web
                bind *:8080
                mode http
                acl ansible_domain hdr_reg(host) -i ansible.phpmyadmin.local
                use_backend ansible_cluster if ansible_domain
backend ansible_cluster
                balance roundrobin
                option httpchk HEAD / HTTP/1.1\r\nHost:\ ansible.phpmyadmin.local
                server server1 192.168.1.121:80 check port 80 inter 3s rise 2 fall 3
                server server2 192.168.1.122:80 check port 80 inter 3s rise 2 fall 3

(4) Create lb-haproxy Playbook

vi lb-haproxy.yml

- hosts: lbservers
  tasks:
    - name: Download Haproxy
      yum:
        name: haproxy22
        state: present
    - name: Configure Haproxy
      copy:
        src: ./files/haproxy.cfg
        dest: /etc/haproxy/haproxy.cfg
        owner: root
        group: root
        mode: 0644
      notify: restart haproxy  
    - name: Start Haproxy
      systemd:
        name: haproxy
        state: started        
        enabled: yes
  handlers: 
    - name: Restart Haproxy
      systemd:
        name: haproxy
        state: restarted

(5) Install and test

ansible-playbook --syntax-check lb-haproxy.yml
ansible-playbook -C lb-haproxy.yml
ansible-playbook lb-haproxy.yml

(5) Configure hosts on your local computer C:\Windows\System32\drivers\etc\hosts

192.168.1.123 ansible.phpmyadmin.local
192.168.1.124 ansible.phpmyadmin.local

(6) Access ansible.phpmyadmin.local:8080 in the browser, and observe the database server - user, refresh to see if the user switches between 121 and 122.

The knowledge in this article comes from the Bilibili video BV11JZcYwEDd

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.