记一次客户从0部署禅道

这次是客户给了几台空 VPS,直接在他们环境上搭。

一开始想得比较简单,禅道不就是 PHP + Web + 数据库。真开始弄以后发现,空机器最麻烦的反而不是安装包,是每台机器的基础环境要先统一。不然后面 SQL Server、Redis、F5 一起接进来,问题会混在一起,很难判断是哪一层。

机器信息这里都脱敏,大概是这样:

1
2
3
4
5
6
7
app01    10.10.10.11    禅道应用节点1
app02 10.10.10.12 禅道应用节点2
db01 10.10.20.11 SQL Server主库
db02 10.10.20.12 SQL Server备库
redis01 10.10.30.11 Redis master / Sentinel
redis02 10.10.30.12 Redis replica / Sentinel
redis03 10.10.30.13 Redis replica / Sentinel

系统统一按 CentOS 7.x 来。

1
2
cat /etc/centos-release
uname -a

主机名先改掉

1
hostnamectl set-hostname app01

其他机器分别改成 app02db01db02redis01 这种。

/etc/hosts 也先补上,不然后面一会儿写 IP,一会儿写主机名,自己都容易乱。

1
2
3
4
5
6
7
8
9
cat >> /etc/hosts <<'EOF'
10.10.10.11 app01
10.10.10.12 app02
10.10.20.11 db01
10.10.20.12 db02
10.10.30.11 redis01
10.10.30.12 redis02
10.10.30.13 redis03
EOF

测一下:

1
2
ping -c 2 db01
ping -c 2 redis01

时间要先对齐

多节点环境时间不一致很烦。日志时间对不上是一方面,后面 Redis Sentinel、SQL Server 主备切换排查起来也难受。

1
2
3
4
yum install -y chrony
systemctl enable chronyd
systemctl start chronyd
chronyc tracking

如果客户内网有自己的 NTP,就改 /etc/chrony.conf

1
server 10.10.1.10 iburst

重启:

1
2
systemctl restart chronyd
chronyc sources -v

基础包

1
2
yum install -y epel-release
yum install -y vim wget curl unzip net-tools lsof telnet bind-utils tar gcc gcc-c++ make openssl openssl-devel

有些机器默认连 telnetnc 都没有,测端口时很烦,所以前面先补掉。

目录规划

当时先这样定:

1
2
3
4
5
mkdir -p /data/www
mkdir -p /data/logs/nginx
mkdir -p /data/backup
mkdir -p /data/upload/zentao
mkdir -p /data/www/zentao

后面附件共享也按 /data/upload/zentao 这个路径规划。不要等 F5 接上以后再发现两台应用节点附件目录不一样。

PHP 和 Nginx

CentOS 7 默认源里的 PHP 太旧,这里用 remi 源装 PHP 7.4。

1
2
3
4
5
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install -y yum-utils
yum-config-manager --enable remi-php74

yum install -y nginx php php-fpm php-cli php-common php-mbstring php-gd php-xml php-ldap php-json php-curl php-zip php-bcmath php-opcache

检查:

1
2
php -v
php -m | sort

PHP-FPM 配置看一下:

1
vim /etc/php-fpm.d/www.conf

主要是这几个:

1
2
3
4
5
6
user = nginx
group = nginx
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

启动:

1
2
3
systemctl enable nginx php-fpm
systemctl start nginx php-fpm
systemctl status nginx php-fpm

Nginx 先跑起来

先配一个最小站点,不急着上完整配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
server_name _;
root /data/www/zentao/www;
index index.php index.html;

access_log /data/logs/nginx/zentao_access.log;
error_log /data/logs/nginx/zentao_error.log;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

检查:

1
2
nginx -t
systemctl reload nginx

防火墙

应用机器先只放 Web 端口。

1
2
3
4
5
6
7
systemctl enable firewalld
systemctl start firewalld

firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-all

SQL Server 和 Redis 的端口不要在应用机上乱开,后面按机器分别放。

放一个 phpinfo

1
2
3
cat > /data/www/zentao/www/info.php <<'EOF'
<?php phpinfo();
EOF

测:

1
2
curl -I http://127.0.0.1/info.php
curl http://127.0.0.1/info.php | head

如果 502,先看:

1
2
3
4
systemctl status php-fpm
ls -l /run/php-fpm/www.sock
ps -ef | grep php-fpm
cat /data/logs/nginx/zentao_error.log

权限

禅道解压之后,目录属主统一给 nginx。不要一会儿 root 解压,一会儿 nginx 写缓存,然后页面各种权限报错。

1
2
chown -R nginx:nginx /data/www/zentao
chown -R nginx:nginx /data/upload/zentao

先用最简单的方式看 nginx 用户能不能写:

1
2
sudo -u nginx touch /data/www/zentao/test_write
sudo -u nginx touch /data/upload/zentao/test_write

端口先记下来

1
2
3
4
5
6
80/443       F5 -> app01/app02
9000/sock nginx -> php-fpm
1433 app -> db listener / SQL Server
6379 app -> Redis master
26379 app -> Redis Sentinel
5022 SQL Server AG endpoint

这一步没什么高深的东西,但很重要。

空 VPS 上来不要急着装业务,先把系统版本、主机名、时间、目录、基础包、PHP-FPM、Nginx、端口规划弄一致。后面真出问题时,至少能少怀疑几层。

参考