🔜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.
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:
- Check the path file pointed to by the environment variable
ANSIBLE_CONFIG
(export ANSIBLE_CONFIG=xxxx); - Check the ansible.cfg configuration file in the current project directory;
~/.ansible.cfg
, check the ansible.cfg configuration file in the current directory;/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:
Execution Process:
- Load the configuration file, default
/etc/ansible/ansible.cfg
; - Find the corresponding host configuration file, locate the host or group to be executed:
- Load the corresponding module file, such as
command
; - Use
ansible
to generate the corresponding temporarypy
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
; - The remote host executes that file;
- Execute and return the result;
- 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'
Parameter | Options | Meaning |
---|---|---|
chdir | chdir /opt | Switch to the specified directory when executing ansible |
creates | creates /data/file | Skip execution if the file exists |
removes | removes /data/file | Execute 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 Parameters | Function |
---|---|
name | The name of the service to be installed |
state=present (default)/absent | Status, 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 Parameters | Function | Notes |
---|---|---|
src | Specify the path of the source file (supports directories or files) | If the source is a directory, the target must also be a directory |
dest | Specify 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 |
mode | Set the permissions of the target file | |
owner | Set the owner of the target file | |
group | Set the group of the target file | |
content | Directly specify the content of the target file | Cannot 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 Parameters | Function |
---|---|
name | Specify the name of the service to be controlled |
state | Specify the service status, optional values: stopped , started , reloaded , restarted , status |
enabled | Set whether the service starts on boot, yes for start, no for not starting |
daemon_reload | Set 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 Parameters | Function | Notes |
---|---|---|
path | Specify the path on the remote server | Can also be written as dest or name |
state | Define operation type: - directory : create directory - touch : create file - link : create soft link - hard : create hard link - absent : delete directory/file/link | |
mode | Set file/directory permissions | Default values: - File 644 - Directory 755 |
owner | Set the owner | Default root |
group | Set the group | Default root |
recurse | Recursive modification | yes or no |
src | Source 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 ' '
Parameter | Function | Optional Values/Description |
---|---|---|
name | Specify username (required) | |
state | Control account creation or deletion | present : create account absent : delete account |
system | Specify whether it is a system account | yes : system account no : regular account |
gid | Specify 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 ' '
Parameter | Function | Optional Values/Description |
---|---|---|
name | Specify username (required) | |
state | Control account creation or deletion | present : create absent : delete |
system | Specify whether it is a system account | yes : system account (e.g., mysql ) no : regular account |
uid | Specify user UID | Numeric (e.g., 1001 ), must be unique |
group | Specify user primary group | Group name or GID (must exist beforehand) |
groups | Specify additional groups for the user | List of group names (e.g., groups=wheel,admin ) |
shell | Set the user's default shell | Path (e.g., /bin/bash ) |
create_home | Whether to create a home directory | yes : automatically create no : do not create (default behavior may depend on the system) |
password | Set user password | It is recommended to use an encrypted string (e.g., password="$6$encrypted_string" ) |
remove | Whether to delete the home directory when deleting the user (requires state=absent ) | yes : delete home directory no : keep |
- 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'
- 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'
- 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') }}"
Parameter | Function | Notes |
---|---|---|
sha512 | Specify hash algorithm (recommended) | Supports sha256 /md5 , but sha512 is more secure 2 |
salt123 | Custom salt value | Salt value must be alphanumeric; containing - or _ will cause hash failure (returns *0 ) 5 |
password_hash filter | Converts plaintext password to encrypted string | Must 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"
- 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 Parameters | Function |
---|---|
src | Specify the device or partition path to be mounted. |
path | Specify the target path to mount to. |
fstype | Specify the file system type to mount. |
state | Specify the mount status, optional values are mounted , (temporary mount) present (permanent mount), unmounted (temporary unmount), or absent (unmount). |
opts | Specify 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 Parameters | Function |
---|---|
minute/hour/day/month/weekday | Minute/Hour/Day/Month/Week |
job | The command to be executed by the scheduled task |
name | The name of the scheduled task |
user | Specify which user the scheduled task belongs to, default is root |
state | present 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 Parameters | Function |
---|---|
path | Specify the path of the source directory or file to be archived. |
dest | Specify the output path of the archive file. |
format | Specify the format of the archive file, can be zip, tar, gz, or bzip2. Default is tar format. |
remove | Specify 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 Parameters | Function |
---|---|
copy | Specify whether to copy the archive file to the remote node for decompression. |
remote_src | (Deprecated) Use the copy parameter instead. |
src | Specify the path of the archive file to be decompressed, can be local or remote path. |
dest | Specify the target directory to which the files will be decompressed. |
creates | Specify a file path; if that file already exists, do not perform the decompression operation. |
remote_tmp | Used to specify the temporary directory on the remote node. Default is /tmp . |
- 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
Parameter | Options | Meaning |
---|---|---|
path | None | Specify the target file path to operate on |
regexp | None | Use regular expressions to match lines in the file |
line | None | Specify the new text content to modify or insert |
insertafter | None | Insert text after the "regex matched line" |
insertbefore | None | Insert text before the "regex matched line" |
state | absent / present (default) | absent deletes matching lines, present ensures text exists |
backrefs | yes / no | yes enables regex back references, no does not operate on the file if not matched |
backup | None | Whether to create a backup file before modification (boolean) |
create | None | Whether to create a new file if the target file does not exist (boolean) |
- Replace Listen in httpd.conf file with Listen8080;
ansible webservers -m lineinfile -a 'path=/etc/httpd/conf/httpd.conf regexp="^Listen" line="Listen 8080"'
- 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.
Syntax | Description |
---|---|
Indentation | YAML uses a fixed indentation style to represent hierarchical structures, with each indentation consisting of two spaces, and tabs cannot be used |
Colon | All colons except those at the end must have a space after them |
Hyphen | Indicates 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
andhosts
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
andhosts
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#
Hostname | IP | Purpose |
---|---|---|
121 | 192.168.1.121 | Ansible control node, Nginx+PHP |
122 | 192.168.1.122 | Ansible managed node, Nginx+PHP |
123 | 192.168.1.123 | Ansible managed node, Nginx (Haproxy) |
124 | 192.168.1.124 | Ansible managed node, Nginx (Haproxy) |
125 | 192.168.1.125 | Ansible 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
.
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