企业如何用Consul+Nomad在香港服务器上实现自动服务发现与负载调度?

大约半年前,我们团队接手了一个部署在香港本地数据中心的企业项目。项目初期,我们的服务部署依赖于 shell 脚本和一些老旧的 systemd 服务编排方式。随着业务量上升,服务器开始吃紧,服务频繁 down 掉又无人知晓,每次部署都要 SSH 到好几台机器检查端口、重启服务,靠 Excel 表维护服务 IP。这种“手工时代”的操作完全跟不上节奏。
我们必须要解决两个问题:
- 服务需要“自动注册”,否则每个节点变动就要改配置。
- 要实现“负载调度”,避免某一台服务器 CPU 飙高而别的还很空。
在调研了 Kubernetes、Docker Swarm、Rancher、OpenShift 之后,我们最终选择了 HashiCorp 的 Consul + Nomad 组合:轻量、原生支持多数据中心、易于自托管,尤其适合我们的非容器化服务环境(大多数是 Go 和 Python 服务,直接运行二进制或虚拟环境)。
下面是我在这次架构升级中实际踩过的坑、写下的部署流程和优化策略。
一、部署拓扑设计:香港节点为主,架构应对边缘计算
我们在香港数据中心有 5 台裸金属服务器,规划如下:
- Nomad Server 节点:3 台(部署为集群)
- Nomad Client 节点:全部 5 台(含 Server)
- Consul Server 节点:3 台,与 Nomad Server 共用
- Consul Agent(Client):部署在所有节点
- Nginx:作为入口反向代理,通过 Consul DNS 动态解析服务地址
这套架构可以有效应对服务的动态调度,服务挂掉自动替换,DNS 实时发现新节点,最大化利用机器资源。
二、Consul 安装与配置(服务发现基石)
1. 安装 Consul(二进制安装)
wget https://releases.hashicorp.com/consul/1.16.1/consul_1.16.1_linux_amd64.zip
unzip consul_1.16.1_linux_amd64.zip
mv consul /usr/local/bin/
2. 配置 Server 节点(假设服务器 IP 为 10.0.0.1, 10.0.0.2, 10.0.0.3)
/etc/consul.d/server.hcl
server = true
bootstrap_expect = 3
data_dir = "/opt/consul"
bind_addr = "10.0.0.1"
retry_join = ["10.0.0.2", "10.0.0.3"]
ui = true
client_addr = "0.0.0.0"
启动:
consul agent -config-dir=/etc/consul.d/
3. 配置 Client 节点
/etc/consul.d/client.hcl
server = false
data_dir = "/opt/consul"
bind_addr = "10.0.0.4" # 当前机器的 IP
retry_join = ["10.0.0.1", "10.0.0.2", "10.0.0.3"]
三、Nomad 安装与配置(调度引擎核心)
1. 安装 Nomad
wget https://releases.hashicorp.com/nomad/1.7.3/nomad_1.7.3_linux_amd64.zip
unzip nomad_1.7.3_linux_amd64.zip
mv nomad /usr/local/bin/
2. 配置 Nomad Server 节点
/etc/nomad.d/server.hcl
server {
enabled = true
bootstrap_expect = 3
}
bind_addr = "0.0.0.0"
data_dir = "/opt/nomad"
advertise {
http = "10.0.0.1"
rpc = "10.0.0.1"
serf = "10.0.0.1"
}
consul {
address = "127.0.0.1:8500"
}
3. 配置 Nomad Client 节点
/etc/nomad.d/client.hcl
client {
enabled = true
servers = ["10.0.0.1", "10.0.0.2", "10.0.0.3"]
}
consul {
address = "127.0.0.1:8500"
}
bind_addr = "0.0.0.0"
data_dir = "/opt/nomad"
启动命令:
nomad agent -config=/etc/nomad.d/
四、服务自动注册与调度部署:一步到位
1. 创建一个 Nomad Job 文件(以 Python 服务为例)
hello-python.nomad
job "hello-python" {
datacenters = ["dc1"]
type = "service"
group "web" {
count = 3
task "python-api" {
driver = "exec"
config {
command = "/usr/bin/python3"
args = ["-m", "http.server", "8080"]
}
resources {
cpu = 100
memory = 128
}
service {
name = "python-api"
port = "http"
check {
type = "http"
path = "/"
interval = "10s"
timeout = "2s"
}
}
env {
ENV = "production"
}
# 网络端口映射
resources {
network {
port "http" {
static = 8080
}
}
}
}
}
}
2. 提交任务
nomad job run hello-python.nomad
3. 验证服务发现
在任意节点上使用 DNS 解析:
dig @127.0.0.1 -p 8600 python-api.service.consul
Nginx 中配置:
upstream api_backend {
server python-api.service.consul:8080;
}
server {
listen 80;
location / {
proxy_pass http://api_backend;
}
}
五、负载调度策略优化:智能调度靠的就是这几点
1. 加入资源感知
每个 task 申报资源,Nomad 会自动根据空闲资源分配任务:
resources {
cpu = 500 # MHz
memory = 256 # MB
}
2. Job Constraint 控制调度节点
constraint {
attribute = "${node.class}"
operator = "="
value = "gpu"
}
3. 动态扩缩容
结合外部脚本或 API,通过 Nomad CLI 扩缩 task 数:
nomad job scale hello-python web=5
六、总结与思考
Consul + Nomad 这套组合在香港服务器上的落地,给我们带来的是:
- 服务注册发现自动化:不用再改配置、写 nginx reload 脚本
- 任务调度弹性化:按资源调度,不再靠拍脑袋部署
- 架构复杂度下降:部署脚本减少 80%,维护成本大幅下降
当然,这套方案并非“银弹”。它比不上 Kubernetes 的强大生态,但胜在轻量、易于入门、对裸机/传统服务极友好。
如果你也在用自建物理机部署、服务还未容器化、希望实现基础调度和服务发现功能,那我强烈建议你试试 Nomad + Consul,这是一套可以“踩地走”的企业级方案。