从零搭建电商独立站 (零)
技术栈使用nginx作为前置代理, 出差员工通过vpn接入内网后, 登录jumpserver访问公司服务器, web应用使用docker部署, 数据库选取MySQL, 用Redis作为前置缓存, 部署gitlab进行本地代码托管并实现CI/CD流水线发布, 最后部署zabbix监控各个服务器性能指标, 实现告警通知
为什么做这样一个项目?
在零散地学习了一些运维软件之后, 为了发现实践可能存在的潜在问题加深理解, 整合所学的知识点, 完全从零开始, 通过技术栈选取、环境资源分配、网络规划到项目搭建, 模拟企业运维环境, 打通整个运维流程
网络规划
因为要考虑到安全隔离、方便扩容和运维, 规划出vpn网,办公网, 管理网, 服务器网, 分别分配网段
192.168.100.0/24
服务器网
192.168.200.0/24
办公网
192.168.300.0/24
管理网
10.10.10.0/24
vpn网
各个网段掩码是 /24, IPv4 地址共 32 位减去网络位 24 剩下 8 个主机位, 可容纳的终端数量是 2^8-2 即 254 个, 减去的 2 个, 一个是网络位 192.168.x.0, 另一个是广播位 192.168.x.255, 小型企业终端、打印机、无线 AP数量算下来网络地址足够
如果需要更多地址, 考虑使用 10.0.0.0/8, 172.16.0.0/12 私网地址, 按照部门划分范围更广的网段, 每个部门单独一个 vlan
准备工作
1. VMware 虚拟网络规划
| 项目 | 值 |
|---|---|
| 虚拟网络 | VMnet8(NAT) |
| 子网网段 | 192.168.100.0/24 |
| 子网掩码 | 255.255.255.0 |
| 网关 IP | 192.168.100.2 |
| DNS | 192.168.100.2 或 223.5.5.5 |
| DHCP | 已关闭 |
| 可用 IP 范围 | 192.168.100.3 ~ 192.168.100.254 |
2. 资源分配
宿主机:i5-13500H / 32G内存 / 360G硬盘
| 节点名 | CPU | 内存 | 磁盘 | 静态IP | 部署角色 |
|---|---|---|---|---|---|
| master-01 | 3核 | 4G | 50G | 192.168.100.10 | Nginx · WireGuard · JumpServer · Zabbix Server · Grafana · Ansible |
| app-01 | 3核 | 6G | 60G | 192.168.100.20 | Docker · GitLab CE · Runner · Saleor全套 |
| app-02 | 2核 | 4G | 40G | 192.168.100.21 | Docker · Saleor备用节点 |
| db-01 | 2核 | 4G | 60G | 192.168.100.30 | PostgreSQL主 · Redis主 |
| db-02 | 2核 | 4G | 40G | 192.168.100.31 | PostgreSQL从 · Redis从 · 哨兵 |
| 合计 | 12核 | 22G | 250G | — | — |
关于内存:这是唯一需要留意的资源。22G 分出去,宿主机 + Windows 系统还剩约 10G,正常够用。如果同时开着 Chrome 几十个标签页 + IDEA 可能会紧张,建议做实验时关掉重型软件。实在不够可以临时把 app-02 关机(它是备用节点,不是每一步都要开)。
- 为什么 app-01 给到 3核6G(最高配)
它要同时扛 GitLab(约2G)+ Saleor 全套四个服务(约3G),是全场最吃内存的节点,所以给最多。Saleor 官方要求 Docker 至少分配 5GB 内存,加上 GitLab,6G 是底线。
- 为什么 db-01 磁盘给 60G
PostgreSQL 的 WAL 日志(写前日志,流复制依赖它)会持续占用空间,加上 Saleor 数据和备份,磁盘给足避免后期写满。
- 为什么 master-01 只要 4G 却装了一堆服务
Nginx、WireGuard、Ansible 都是轻量级,几乎不吃内存;JumpServer 和 Zabbix 稍重但也就 1~2G。这几个错峰使用,4G 够用。如果后面 Zabbix + JumpServer 同时跑觉得卡,可以临时加到 5G。
- IP 分配规律
.10 段 → master管理节点
.20 段 → app应用节点(.20 .21)
.30 段 → db数据节点(.30 .31)
按角色分段,一看 IP 就知道是什么机器,运维时不容易搞错。
3. 系统安装
第一步:开机安装
1. 启动菜单:选"Install"(纯文本安装,最稳)
或"Graphical Install"(图形界面,鼠标可点,新手友好)
2. 语言/地区/键盘:
- Language: English(建议英文,报错信息好搜;中文也行)
- Location: other → Asia → China
- Locale: en_US.UTF-8
- Keyboard: American English
3. 网络配置:
- 选择 "configuration network manually"
- 配置静态 IP 地址
- Hostname: master-01
- Domain name: 留空,直接回车
4. 用户和密码:
- Root password: 设一个你记得住的
- 再次确认 root 密码
- 创建普通用户:
Full name: ops
Username: ops
给 ops 设密码
5. 时区:选 Asia/Shanghai(如果前面选了China会自动跳这步)
第二步:磁盘分区
分区方法选:"Manual"(手动)
然后按这个方案分(50G磁盘):
1. 选中那块50G空闲磁盘 → 回车 → 创建新空分区表
2. 创建 /boot 分区:
- 选 FREE SPACE → Create a new partition
- Size: 1 GB
- Type: Primary
- 位置: Beginning
- Mount point: /boot
- 文件系统: ext4
3. 创建 swap 分区:
- 选 FREE SPACE → Create a new partition
- Size: 2 GB
- Use as: swap area
4. 创建 / 根分区:
- 选 FREE SPACE → Create a new partition
- Size: 剩余全部(约47GB,直接回车用最大值)
- Mount point: /
- 文件系统: ext4
5. 选 "Finish partitioning and write changes to disk"
6. 确认 "Write the changes to disks?" → Yes
第三步:软件选择(最小化安装)
1. 配置软件包管理器(apt 源):
- 扫描额外安装介质:No
- 镜像国家:China
- 镜像站点:选 mirrors.tuna.tsinghua.edu.cn(清华源,国内快)
或 mirrors.aliyun.com(阿里源)
- HTTP代理:留空,回车
2. 参与软件包调查(popularity-contest):No
3. 软件选择(Software selection)——这步很关键:
用空格键取消勾选所有桌面环境!
✅ 只勾选:
[*] SSH server
[*] standard system utilities
❌ 取消:
[ ] Debian desktop environment
[ ] GNOME 等所有桌面
→继续
第四步:安装 GRUB 引导
1. Install the GRUB boot loader: Yes
2. 选择安装设备:选 /dev/sda(那块50G磁盘)
3. 等待完成 → Continue,虚拟机重启
第五步:立刻打第一个快照
系统刚装完、什么都没配,先存档:
关机:在命令行输入 poweroff
关机后:VMware 选中 master-01 → 右键 → 快照 → 拍摄快照
命名:fresh-install
描述:系统刚装完,最小化,未做任何配置
这样万一后面配置搞坏了,能一键回到干净系统,不用重装。
root登录 改网卡名,重启 关selinux 使dns生效 sudo权限管理 配置ssh
4. 系统初始化
第一步:改网卡名
查看当前网卡名:
ip link
编辑 GRUB:
sudo vi /etc/default/grub
找到 GRUB_CMDLINE_LINUX 这一行,加入两个参数:
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
更新 GRUB 并重启:
sudo update-grub
sudo reboot
重启后 ip link 应显示 eth0。
第二步:配静态 IP
Debian netinst 最小化安装默认用 /etc/network/interfaces。编辑:
sudo nano /etc/network/interfaces
按网络规划
auto eth0
iface eth0 inet static
address 192.168.100.10
netmask 255.255.255.0
gateway 192.168.100.2
dns-nameservers 192.168.100.2 223.5.5.5
重启网络:
sudo systemctl restart networking
验证:
ip addr
第三步:DNS 生效
/etc/network/interfaces 里的 dns-nameservers 不是 ifupdown 原生指令,而是交给 resolvconf 这个钩子去处理的。没装 resolvconf 时,这一行等于写了个没人读的注释,DNS 自然就没配上
直接写 /etc/resolv.conf
sudo nano /etc/resolv.conf
写入:
nameserver 223.5.5.5
nameserver 192.168.100.2
保存后立即测试:
ping -c 3 www.baidu.com
注意:如果系统装了
resolvconf或用了NetworkManager,这个文件可能在重启后被覆盖。
第四步 关闭 SELinux (可选)
Debian 12 默认不安装也不启用 SELinux,默认强制访问控制用的是 AppArmor。先确认状态:
sestatus 2>/dev/null || echo "SELinux 未安装"
通常会输出「未安装」。
如果你的环境确实装了 SELinux 且需要关闭,编辑:
sudo nano /etc/selinux/config
把:
SELINUX=enforcing
改为:
SELINUX=disabled
保存后重启生效。
如果想顺手确认 AppArmor 状态:
sudo aa-status
第五步:添加 sudo 权限
确认 sudo 已安装,用户 ops 已存在:
apt install -y sudo
id ops 2>/dev/null || sudo adduser ops
将 ops 加入 sudo 组(Debian 用 sudo 组,不是 RHEL 的 wheel):
sudo usermod -aG sudo ops
验证:
groups ops
应能看到 sudo。切到 ops 测试:
su - ops
sudo whoami # 应返回 root
exit
第六步:配置 SSH
宿主机生成密钥
ssh-keygen -t ed25519 -C "ops@master-01"
上传公钥到 ops 用户
ssh-copy-id -i ~/.ssh/id_ed25519.pub ops@192.168.100.10
或手动(在服务器上以 ops 身份):
mkdir -p ~/.ssh && chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys # 粘贴公钥内容
chmod 600 ~/.ssh/authorized_keys
验证密钥能登录
ssh ops@192.168.100.10
加固 SSH 配置
sudo nano /etc/ssh/sshd_config
确认/修改以下项:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
重启 SSH 服务
Debian 服务名是 ssh(不是 RHEL 的 sshd):
sudo systemctl restart ssh
最终验证
新开一个终端测试(保留当前会话别关,以防配置出错):
ssh ops@192.168.100.10 # 密钥应能登录
ssh root@192.168.100.10 # 应被拒绝
完成后打一个快照 base-config, 克隆出 app-01、app-02、db-01、db-02
5. 克隆机差异化配置
- app-01 / app-02:直接用克隆机,只改系统层身份标识(hostname / IP / machine-id / SSH host key)。
- db-01 / db-02:这两台删掉克隆的磁盘 → 重新装 Debian 12 并手动做 LVM 分区。其中 db-01 用 ext4,db-02 用 xfs。
app-01 / app-02 两台都开机,分别操作。以 app-01 为例
第一步:改 hostname
sudo hostnamectl set-hostname app-01
第二步:改静态 IP
Debian 12 看你装机时用的是哪种网络管理。最小化安装通常是 /etc/network/interfaces:
sudo nano /etc/network/interfaces
把对应网卡段改成
auto eth0
iface eth0 inet static
address 192.168.100.x
netmask 255.255.255.0
gateway 192.168.100.2
dns-nameservers 192.168.100.2 223.5.5.5
应用:
sudo systemctl restart networking
第三步:重新生成 machine-id
克隆机会共用同一个 machine-id,必须重置,否则 DHCP、journald、某些服务会冲突:
sudo rm -f /etc/machine-id /var/lib/dbus/machine-id
sudo systemd-machine-id-setup
sudo ln -sf /etc/machine-id /var/lib/dbus/machine-id
第四步:重新生成 SSH host key
sudo rm -f /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server
sudo systemctl restart ssh
host key 什么时候用
每次你 ssh ops@db-01 发起连接,在输入密码/验证登录密钥之前,握手第一步是:
- 服务器把自己的 host key 公钥发给你的客户端。
- 客户端检查
~/.ssh/known_hosts里有没有这台机器的记录。 - 第一次连会弹这个:
The authenticity of host 'db-01' can't be established.
ED25519 key fingerprint is SHA256:xxxx...
Are you sure you want to continue connecting (yes/no)?
你打 yes,指纹就被记进 known_hosts。以后每次连,客户端都拿服务器发来的 host key 和 known_hosts 里存的比对,一致才继续,不一致就直接报警拒连。
它防的是中间人攻击:如果有人冒充 db-01 截你的连接,它的 host key 对不上存的指纹,客户端立刻报警,就不会把密码/密钥送进假服务器。
第五步:验证并重启
hostnamectl # 确认 hostname
ip a # 确认 IP
cat /etc/machine-id # 确认与其他机器不同
sudo reboot
app-02 重复以上,换成它自己的 hostname 和 IP。
6. db-01 / db-02 重装 + LVM 分区
VMware 层准备(关机状态)
对 db-01:
- 虚拟机 → 设置,按 0.2 表调好 CPU / 内存。
- 删除克隆带过来的硬盘(选中硬盘 → 移除),重新添加一块新硬盘(SCSI,容量按 LVM 规划总和,至少 55G:1+2+30+20 = 53G,留点余量给阶段八扩容演练就别给太满,给 55G 即可)。
- CD/DVD 挂载 Debian 12 netinst ISO(0.4 下载的那个),设为启动时连接。
db-02 同样操作。
安装时的手动 LVM 分区
启动进入安装程序,前面步骤照常,到磁盘分区时选:
手动 (Manual)
然后按下面建立。LVM 的做法是:先建一个小的 /boot 普通分区,剩余空间建一个"用于 LVM 的物理卷",再在里面切逻辑卷。
第一步:建 /boot(普通分区,不进 LVM)
- 选空闲磁盘 → 新建分区 → 1 GB → 主分区 → 起始 → 挂载点
/boot,文件系统 ext4。
第二步:剩余空间设为 LVM 物理卷
- 选剩余空闲空间 → 新建分区 → 用全部剩余 → "用作(Use as)" 改成 物理卷用于 LVM (physical volume for LVM)。
第三步:配置逻辑卷管理器
- 回到分区主菜单 → 选 配置逻辑卷管理器 (Configure LVM)。
- 创建卷组(VG),名字比如
vg_data,选刚才那个 LVM 物理卷。 - 在 VG 里创建逻辑卷(LV),按规划建:
| 逻辑卷名 | 大小 | 后续挂载点 |
|---|---|---|
| lv_swap | 2G | swap |
| lv_root | 30G | / |
| lv_pgdata | 20G | /var/lib/postgresql |
第四步:给每个 LV 设挂载点和文件系统
- 回到分区主菜单,这时能看到三个 LV。逐个进入设置:
- lv_swap → 用作 swap area
- lv_root → 文件系统 db-01 用 ext4 / db-02 用 xfs,挂载点
/ - lv_pgdata → 文件系统 db-01 用 ext4 / db-02 用 xfs,挂载点
/var/lib/postgresql
第五步:完成分区
- 选"分区设定结束并将修改写入磁盘",确认。
安装后基础配置
装完后,db-01 / db-02 还要做和 app 机一样的身份配置——但因为是全新安装,machine-id 和 SSH host key 是自动新生成的,不用再重置。只需:
sudo hostnamectl set-hostname db-01 # db-02 改成 db-02
sudo nano /etc/network/interfaces # 配静态 IP,按 0.2 表
sudo systemctl restart networking
同时基础配置(apt 国内源、常用工具、ops 用户、SSH 密钥登录、禁用密码登录、禁止 root 远程)在这两台重新做一遍——因为它们是全新系统,没继承 master 的加固配置。
验证分区结果:
lsblk # 看分区结构
sudo vgs # 看卷组,确认有剩余空间(VFree 列 > 0)
sudo lvs # 看逻辑卷
df -hT # 看挂载点和文件系统类型(db-01 应是 ext4,db-02 应是 xfs)
7. 网络互通
第一步:域名解析
让 5 台虚拟机能用 hostname 互相访问,不依赖 DNS。每台机器的 /etc/hosts 都要写入全部 5 个节点的映射。
追加命令一次写入,在每台节点执行同一段:
sudo tee -a /etc/hosts > /dev/null <<'EOF'
# === Saleor 实验内网节点 ===
192.168.100.10 master-01
192.168.100.20 app-01
192.168.100.21 app-02
192.168.100.30 db-01
192.168.100.31 db-02
EOF
<<'EOF' 用单引号可防止变量被展开,-a 是追加不覆盖。
第二步:验证
在每台节点上测试解析与连通:
# 解析是否生效(应返回对应 IP)
getent hosts master-01 app-01 app-02 db-01 db-02
# 逐个 ping hostname(不是 IP)
for h in master-01 app-01 app-02 db-01 db-02; do ping -c1 -W1 "$h" >/dev/null && echo "$h OK" || echo "$h FAIL"; done
全部返回 IP 且 ping 通即成功。