SaaS创业团队如何在香港服务器的 Ubuntu 环境中搭建 Kubernetes 集群,并快速实现全球化部署(高阶、实操、带坑位复盘)

凌晨 2:40,我和同事阿康在香港将军澳机房对着一排裸露着热插拔托架的 1U 服务器,最后一次确认 BMC 网络、光口链路聚合和 PDU 的冗余。我们这套面向全球的首个生产级 K8s 集群,要在天亮前可用:首批用户在欧洲和东南亚。
我们的目标很清晰:用香港本地高带宽低时延的优势做全球流量的“第一落点”和“智能分发”,配合 Cloudflare 的边缘网络,把 SaaS 的多区域访问体验做对——先快,再稳,再省。下面是我完整的落地过程、参数、脚本、踩坑与复盘。
1. 适用读者与产出物
适用对象:SaaS 初创团队 CTO / 架构师 / SRE / 高阶运维工程师,也照顾新手按步骤操作。
交付结果:一套在香港机房(Ubuntu 22.04/24.04 LTS)落地的高可用 Kubernetes集群,具备:
- 双活 API 高可用(HAProxy + Keepalived VIP)
- Cilium CNI( eBPF、可选加密、NetworkPolicy)
- MetalLB(L2 模式出公网/机房内网负载)
- Longhorn 分布式块存储(NVMe)
- Ingress-NGINX + Cloudflare(WAF/CDN/SSL/TLS)
- cert-manager + ExternalDNS(自动证书与域名)
- Harbor 私有镜像仓库 + GitHub Actions CI/CD
- 监控日志链路:kube-prometheus-stack + Loki
- 备份与容灾:Velero + S3 兼容对象存储(Cloudflare R2/MinIO)
- 可扩展到多区域的 DNS 智能流量调度
2. 目标架构(文字拓扑)
[Internet Users]
|
Cloudflare (Proxy, WAF, CDN, LB, Geo)
|
┌───────────────香港 IDC───────────────┐
| VIP(10.0.10.10):6443 <Keepalived+HAProxy> |
| | \ |
| CP1|CP2|CP3 Workers x N Storage x M(Longhorn)
| | |
| Cilium CNI + MetalLB + Ingress-NGINX + cert-manager + ExternalDNS
| | \
| Apps/NS Harbor/Monitoring/Velero ...
└──────────────────────────────────────────────────────────────┘
|
R2/MinIO/S3(备份/镜像副本)
3. 资源、版本与参数清单(实配示例)
3.1 服务器规格(样例)
| 角色 | 数量 | CPU | 内存 | 系统盘 | 数据盘 | 网卡 | 备注 |
|---|---|---|---|---|---|---|---|
| 控制面 CP | 3 | AMD EPYC 7443P(24C) | 128GB | 2×480GB SSD RAID1 | — | 2×10GbE(LACP) | 机柜双上联 |
| 工作节点 | 6 | AMD EPYC 7313P(16C) | 128GB | 2×480GB SSD RAID1 | 2×3.84TB NVMe(Longhorn复用一块) | 2×10GbE | 根据业务横向扩容 |
| 存储节点 | 3 | AMD EPYC 7302P(16C) | 128GB | 2×480GB SSD RAID1 | 4×3.84TB NVMe | 2×10GbE | Longhorn 3 副本策略 |
- 操作系统:Ubuntu Server 22.04/24.04 LTS(最小化安装)
- 时钟同步:chrony(对接机房 NTP)
- K8s:kubeadm v1.29/1.30(本文以 v1.29.x 为例)
- 运行时:containerd 1.7+
- CNI:Cilium 1.15+(eBPF)
- Ingress:ingress-nginx 1.11+
- 存储:Longhorn 1.6+
- 证书:cert-manager 1.14+
- 监控:kube-prometheus-stack 60.x+
- 备份:Velero 1.13+
3.2 网络与 IP 规划(示例)
| 网络 | 网段 | 用途 |
|---|---|---|
| 管理网 MGMT | 10.0.0.0/24 | BMC、SSH、Ansible |
| 业务网 PROD | 10.0.10.0/24 | 节点互联、Pod/Service 出口 |
| 存储网 STORAGE | 10.0.20.0/24 | Longhorn 数据复制(独立物理口/VLAN) |
| Kubernetes VIP | 10.0.10.10 | kube-apiserver 虚拟地址(HA) |
| MetalLB 池 | 10.0.10.200-10.0.10.250 | 暴露 LoadBalancer 类型服务 |
4. 机房基线与 Ubuntu 初始化
4.1 BIOS/BMC/固件与链路
- 开启 SR-IOV/VT-d/IOMMU,关闭 C-States 过深省电,性能更稳。
- 固件统一到同一大版本,网卡驱动与固件匹配(Mellanox/Intel)。
- 业务网与存储网分物理口/VLAN,ToR 交换机做 LACP(802.3ad)。
4.2 Ubuntu 基线脚本(所有节点执行)
# 01-base.sh
set -eux
sudo apt update
sudo apt -y upgrade
# 基础工具
sudo apt -y install htop iotop iftop nvme-cli jq gnupg2 apt-transport-https \
curl ca-certificates software-properties-common git chrony
# 时钟同步
sudo timedatectl set-timezone Asia/Hong_Kong
sudo sed -i 's/^pool .*/server ntp.hk.example iburst/' /etc/chrony/chrony.conf
sudo systemctl enable --now chrony
# 关闭 swap
sudo swapoff -a
sudo sed -ri 's/^(.*swap.*)$/#\1/g' /etc/fstab
# 内核参数
cat <<'EOF' | sudo tee /etc/sysctl.d/99-k8s.conf
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0
fs.inotify.max_user_watches=524288
fs.inotify.max_user_instances=1024
net.netfilter.nf_conntrack_max=2621440
EOF
sudo modprobe br_netfilter
sudo sysctl --system
# iptables 切回 legacy(避免某些扩展与 nft 冲突)
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy || true
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true
# 禁用 UFW(后续由 Cilium/NetworkPolicy 控制)
sudo systemctl disable --now ufw || true
4.3 containerd 安装与配置
# 02-containerd.sh
set -eux
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release; echo $UBUNTU_CODENAME) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt -y install containerd.io
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl enable --now containerd
4.4 安装 kubeadm/kubelet/kubectl(锁版本)
# 03-k8s.sh
set -eux
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-1-29.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-1-29.gpg] \
https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /" | \
sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null
sudo apt update
sudo apt -y install kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
5. 控制面高可用:Keepalived + HAProxy
5.1 HAProxy(CP1/CP2/CP3 都装)
sudo apt -y install keepalived haproxy
# /etc/haproxy/haproxy.cfg 关键段
cat <<'EOF' | sudo tee /etc/haproxy/haproxy.cfg
global
maxconn 100000
log /dev/log local0
defaults
mode tcp
timeout connect 5s
timeout client 1m
timeout server 1m
frontend k8s_api
bind 10.0.10.10:6443
default_backend k8s_masters
backend k8s_masters
balance roundrobin
option tcp-check
server cp1 10.0.10.11:6443 check fall 3 rise 2
server cp2 10.0.10.12:6443 check fall 3 rise 2
server cp3 10.0.10.13:6443 check fall 3 rise 2
EOF
sudo systemctl enable --now haproxy
5.2 Keepalived(使用单播避免 VRRP 组播与机房网络策略冲突)
# /etc/keepalived/keepalived.conf
cat <<'EOF' | sudo tee /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
state BACKUP
interface bond0
virtual_router_id 51
priority 100
advert_int 1
unicast_src_ip 10.0.10.X # 当前节点IP
unicast_peer {
10.0.10.11
10.0.10.12
10.0.10.13
}
authentication {
auth_type PASS
auth_pass k8sVIPpass
}
virtual_ipaddress {
10.0.10.10/24 dev bond0
}
track_script {
chk_haproxy
}
}
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
weight 20
}
EOF
sudo systemctl enable --now keepalived
现场坑 1:某些机房对 VRRP 组播有限制,直接漂 VIP 会失败。用 unicast 模式规避;同时把 virtual_router_id 固定,所有节点一致。
6. kubeadm 初始化与加入
6.1 kubeadm 配置(CP1 上生成并分发)
cat <<'EOF' > kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 10.0.10.11
bindPort: 6443
nodeRegistration:
criSocket: "unix:///run/containerd/containerd.sock"
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: "v1.29.6"
controlPlaneEndpoint: "10.0.10.10:6443"
networking:
podSubnet: "10.244.0.0/16" # cilium 会接管
serviceSubnet: "10.96.0.0/12"
apiServer:
extraArgs:
audit-log-maxage: "7"
audit-log-maxsize: "100"
audit-log-maxbackup: "10"
controllerManager: {}
scheduler: {}
etcd:
local:
dataDir: /var/lib/etcd
EOF
6.2 初始化控制面(CP1)
sudo kubeadm init --config kubeadm-config.yaml
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
6.3 其余控制面加入(CP2/CP3)
在 CP1 获取 kubeadm join ... --control-plane 命令并在 CP2/CP3 执行(包含 --certificate-key)。
6.4 工作节点加入
在每个 Worker 节点执行 kubeadm join ...(包含 token、discovery-token-ca-cert-hash)。
7. 安装 Cilium(CNI)
# 安装 helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm repo add cilium https://helm.cilium.io/
helm repo update
# 可根据 MTU 与机房网络调整 tunneling/encryption
helm install cilium cilium/cilium \
--version 1.15.5 \
--namespace kube-system \
--set kubeProxyReplacement=strict \
--set k8sServiceHost=10.0.10.10 \
--set k8sServicePort=6443 \
--set ipam.mode=kubernetes
现场坑 2(MTU):机房骨干 + Cloudflare + eBPF overlay 时可能出现 Path MTU 降低导致的断续丢包。务必核对 ToR 与上联 MTU,必要时在 Cilium 设置 --set global.mtu=XXXX 并与网卡/交换机一致。
8. MetalLB(L2 模式)
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
cat <<'EOF' | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 10.0.10.200-10.0.10.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec: {}
EOF
9. Longhorn 分布式存储(NVMe)
helm repo add longhorn https://charts.longhorn.io
helm repo update
kubectl create ns longhorn-system
helm install longhorn longhorn/longhorn -n longhorn-system --version 1.6.1 \
--set persistence.defaultClassReplicaCount=3 \
--set defaultSettings.defaultDataPath="/var/lib/longhorn"
现场坑 3:Longhorn 需要独立磁盘或分区。别把系统盘拿来玩;确保存储网有足够带宽(我们放在 10GbE 独立网)。
10. Ingress-NGINX + Cloudflare 适配(Real IP/Proxy Protocol)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
kubectl create ns ingress-nginx
helm install ingress ingress-nginx/ingress-nginx -n ingress-nginx \
--set controller.service.type=LoadBalancer \
--set controller.service.annotations."metallb\.universe\.tf/allow-shared-ip"="ingress" \
--set controller.config.use-proxy-protocol="true" \
--set controller.config.real-ip-header="proxy_protocol" \
--set controller.config.set-real-ip-from="0.0.0.0/0"
现场坑 4:Cloudflare 代理后端时,如果开启 Proxy Protocol,请同时在 Cloudflare LB/Listener 侧开启;否则 NGINX 解析不到真实源 IP。若不使用 Proxy Protocol,可改走 X-Forwarded-For 并维护 Cloudflare IP 段白名单。
11. cert-manager 与 Cloudflare DNS 自动化
helm repo add jetstack https://charts.jetstack.io
helm repo update
kubectl create ns cert-manager
helm install cert-manager jetstack/cert-manager -n cert-manager \
--set crds.enabled=true
# Cloudflare API Token Secret
kubectl -n cert-manager create secret generic cloudflare-api-token-secret \
--from-literal=api-token='<CF_API_TOKEN>'
# ClusterIssuer(DNS01 验证)
cat <<'EOF' | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns01
spec:
acme:
email: ops@example.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: acme-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
EOF
12. ExternalDNS(自动创建/更新 DNS 记录)
helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
helm repo update
kubectl create ns external-dns
kubectl -n external-dns create secret generic cloudflare-api-token-secret \
--from-literal=api-token='<CF_API_TOKEN>'
helm install external-dns external-dns/external-dns -n external-dns \
--set provider=cloudflare \
--set env[0].name=CLOUDFLARE_API_TOKEN \
--set env[0].valueFrom.secretKeyRef.name=cloudflare-api-token-secret \
--set env[0].valueFrom.secretKeyRef.key=api-token \
--set domainFilters[0]=example.com \
--set policy=sync \
--set txtOwnerId=hk-cluster
13. Harbor 私有镜像仓库(可选)
helm repo add harbor https://helm.goharbor.io
helm repo update
kubectl create ns harbor
helm install harbor harbor/harbor -n harbor \
--set externalURL=https://harbor.example.com \
--set expose.type=ingress \
--set expose.tls.enabled=true \
--set expose.ingress.className=nginx \
--set expose.ingress.hosts.core=harbor.example.com \
--set harborAdminPassword='StrongP@ssw0rd!'
通过 Ingress + cert-manager 自动签发 TLS;镜像推送走 Cloudflare 直连或灰度关闭代理(避免大体积镜像被缓存/限速)。
14. CI/CD:GitHub Actions → Harbor → K8s
.github/workflows/deploy.yml(示例)
name: build-and-deploy
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: harbor.example.com
username: ${{ secrets.HARBOR_USER }}
password: ${{ secrets.HARBOR_PASS }}
- name: Build
run: |
docker buildx build --platform linux/amd64 \
-t harbor.example.com/saas/app:${{ github.sha }} \
-t harbor.example.com/saas/app:latest \
--push .
- name: Kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBECONFIG }}" > $HOME/.kube/config
- name: Deploy
run: |
sed -i "s#IMAGE_TAG#${{ github.sha }}#g" k8s/deploy.yaml
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/deploy.yaml
k8s/deploy.yaml(关键段)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: saas
spec:
replicas: 4
selector:
matchLabels: { app: app }
template:
metadata:
labels: { app: app }
spec:
containers:
- name: app
image: harbor.example.com/saas/app:IMAGE_TAG
ports:
- containerPort: 8080
resources:
requests: { cpu: "200m", memory: "256Mi" }
limits: { cpu: "1", memory: "1Gi" }
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
namespace: saas
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
15. 监控与日志
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# kube-prometheus-stack
kubectl create ns monitoring
helm install monitor prometheus-community/kube-prometheus-stack -n monitoring
# Loki + promtail(可选)
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki -n monitoring --set singleBinary=true
helm install promtail grafana/promtail -n monitoring \
--set "config.clients[0].url=http://loki.monitoring.svc:3100/loki/api/v1/push"
16. 备份与灾备(Velero + R2/MinIO)
# 以 Cloudflare R2 为例(S3 兼容)
export VELERO_ACCESS_KEY_ID=AKIAxxxx
export VELERO_SECRET_ACCESS_KEY=xxxx
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.8.2 \
--bucket saas-backup \
--secret-file ./credentials-velero \
--backup-location-config s3Url=https://<accountid>.r2.cloudflarestorage.com,region=auto \
--use-node-agent
策略:每天全量命名空间级备份,关键数据(数据库 PVC)每 6 小时增量,保留 7-14 天;演练跨集群恢复到备用环境(如新加坡/东京)。
17. 安全与治理(建议基线)
- NetworkPolicy:默认拒绝、按 NS/标签白名单互通(Cilium 原生支持)。
- 镜像来源白名单:限制为 harbor.example.com 与受信任公共仓库。
- Admission:Kyverno/Gatekeeper 校验镜像签名、资源限额、禁止特权容器。
- 密钥管理:Sealed Secrets 或 External Secrets(对接 Vault/ASM)。
- 审计:apiserver 审计日志 → Loki/对象存储长期保存。
18. 对外发布样例(自动证书 + 自动 DNS)
ingress.yaml(示例,自动颁发 TLS 和 A 记录)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
namespace: saas
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-dns01"
external-dns.alpha.kubernetes.io/hostname: "app.example.com"
spec:
ingressClassName: nginx
tls:
- hosts: [ "app.example.com" ]
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port: { number: 8080 }
---
apiVersion: v1
kind: Service
metadata:
name: app-svc
namespace: saas
spec:
type: LoadBalancer
selector: { app: app }
ports:
- port: 8080
targetPort: 8080
ExternalDNS 会写入 app.example.com 到 Cloudflare;cert-manager 通过 DNS01 完成证书签发并维护续期。
19. 全球化部署策略(从香港出发)
第一阶段(香港单区 + 边缘加速)
- 所有入口走 Cloudflare 代理(缓存静态、Argo 智能路由可选)。
- 香港集群提供统一 Ingress 出口,MetalLB 分配公网/IDC 地址。
- 用户就近接入 Cloudflare Anycast,回源到香港。
第二阶段(多区域集群)
- 在 新加坡/东京/法兰克福 复制同构集群(同样的 Helm 基线)。
- 使用 Cloudflare Load Balancer + Geo-Steering/Session Affinity,按地理/健康度分配到最近活跃区域。
- 镜像仓库多区域副本(Harbor + registry 镜像复制;或用公共仓库 + 策略镜像)
数据层根据业务特点选择:
- 读多写少:各区读本地、写异步到主(例如只在 HK 写主库)
- 强一致:引入多主/共识(TiDB/CockroachDB/Etcd-Sharded),网络与延迟成本需评估
- 灾备:Velero 定期把关键命名空间同步备份到所有区域对象存储。
示例延迟(实测参考值,非官方):
| 地区 | 直连香港(ms) | 走 Cloudflare 回源(ms) | 体验 |
|---|---|---|---|
| 新加坡 | 35-45 | 30-40 | 边缘就近 + 智能路由更稳 |
| 东京 | 45-60 | 40-55 | 峰值抖动下降 |
| 法兰克福 | 180-220 | 160-200 | 首屏提升 10-20% |
| 洛杉矶 | 120-150 | 100-130 | 峰值拥塞更可控 |
20. 端口与防火墙白名单(节选)
| 方向 | 协议/端口 | 说明 |
|---|---|---|
| 外网→Ingress | TCP/80,443 | 业务入口 |
| 节点间 | TCP/2379-2380 | etcd |
| 节点间 | TCP/10250 | kubelet |
| Pod 网络 | 多端口 | Cilium eBPF/隧道 |
| 监控 | TCP/9090,3000 | Prometheus/Grafana |
| 存储 | TCP/9500, 10000-32767 | Longhorn 数据/引擎 |
21. 常见坑位与现场处置
VRRP 组播被机房屏蔽
现象:VIP 不漂移或漂移不稳定
处理:Keepalived 改 unicast,ToR 明确允许该流量,优先独占 VLAN。
MTU 不一致导致连接间歇失败
现象:服务偶发 502/超时、只在部分客户端出现
处理:统一主机、交换机、CNI MTU;Cilium 指定 --set global.mtu=9000/1500 与实际一致。
iptables nft 与 legacy 混乱
现象:部分规则失效、NodePort 不通
处理:按上文切回 legacy(或全栈 nft,但组件要匹配);重启 kubelet 与网络栈。
Cloudflare 代理 + Proxy Protocol 配置不一致
现象:后端拿不到真实 IP、日志全是代理节点
处理:两端一致开启/关闭;或使用 X-Forwarded-For 并维护可信名单。
Longhorn 磁盘误用系统盘
现象:I/O 抖动、系统盘被打满
处理:严格用独立 NVMe;设置磁盘调度 none(NVMe),NUMA 亲和优化。
证书签发速率限制
现象:频繁改域名触发 Let’s Encrypt 速率限制
处理:灰度用 Staging CA;外域名统一走子域与 wildcard。
镜像下载瓶颈
现象:首发时很多节点拉镜像慢
处理:Harbor 开启本地缓存、启用分层复用,机房内部署 registry mirror。
22. 性能与容量基线(我们线上达标参考)
| 指标 | 目标线 | 备注 |
|---|---|---|
| P99 首字节延迟(亚洲用户) | ≤ 300ms | Cloudflare 边缘 + 香港回源 |
| 单集群 QPS | 50k+ | 视业务类型不同 |
| 部署耗时(CI→上线) | ≤ 5 分钟 | 镜像构建 + 部署滚更 |
| Pod 启动到就绪 | ≤ 15 秒 | 预拉镜像 + Readiness 探针 |
| 备份恢复 RTO | ≤ 30 分钟 | Velero 命名空间级恢复 |
| 存储 IOPS(随机读 4k) | ≥ 200k/节点 | NVMe + Longhorn 三副本 |
23. 完整“首个业务”上线清单(随手卡)
- 节点基线 + 审计
- kubeadm 初始化 + 加入
- Cilium/MetalLB/Ingress 安装
- cert-manager/ExternalDNS/Cloudflare 接通
- Longhorn 卷就绪 + 读写压力测试
- Harbor/CI/CD 通路打通(灰度环境)
- 监控告警完善,Grafana 看板固定
- Velero 全量备份完成一次并演练恢复
- WAF/速率限制/限流(Nginx 或 Cloudflare)
- HPA 压测与回滚演练
早上 6:10,监控大屏上全是绿勾。第一批欧洲用户打点上报稳定,Cloudflare 边缘命中率爬升到 80% 左右。我们把最后一口冷咖啡倒掉,走出机房时将军澳天边已经泛白。
做全球化,并不一定非要一上来就多区域多活。从香港出发,把一套稳扎稳打、可复制的 Kubernetes 基线打好,配合边缘网络与自动化,把速度、稳定与成本三角平衡出来——这就是我们真实经历过的路线图。
希望这篇“带温度”的教程,能让你在凌晨值守时少踩几个坑,也能更从容地迎接清晨那束“绿灯”。
附录:一键检测脚本(节选)
#!/usr/bin/env bash
# quick-healthcheck.sh
set -e
echo "[*] Node summary"
kubectl get node -o wide
echo "[*] Core addons"
kubectl -n kube-system get ds,deploy | egrep "cilium|coredns|metrics"
echo "[*] Ingress & LB"
kubectl -n ingress-nginx get svc,deploy
kubectl -n metallb-system get ipaddresspools,l2advertisements
echo "[*] Storage"
kubectl -n longhorn-system get po,svc
kubectl get sc,pv,pvc
echo "[*] Certs & DNS"
kubectl -n cert-manager get clusterissuer
kubectl -n external-dns get deploy
echo "[*] Monitoring"
kubectl -n monitoring get po,svc | egrep "prometheus|grafana|alertmanager"
echo "[*] Velero"
kubectl -n velero get po,backup,backupstoragelocations