如何在香港服务器的跨平台系统中通过配置异构虚拟化平台,实现Windows和Linux混合环境下的容器管理?

凌晨3点,我第一次在香港中环IDC机房里撸这个环境,客户要把一套历史包袱很重的 .NET Framework 服务(只能跑 Windows 容器)和新写的 Go/Node 服务(Linux 容器)统一到一个调度面上,还要求弹性扩缩、蓝绿发布、跨城容灾。实话说,第一次拿到需求时,我也皱了下眉:Windows + Linux 混编 + 异构虚拟化,而且还是在香港的多线网络环境里——这意味着网络、存储、MTU、镜像、授权都会踩雷。
我最后的架构选择是:KVM(Proxmox VE)承载 Linux 控制面与 Linux 工作节点;Hyper-V 承载 Windows 容器工作节点;上层用 Kubernetes 做统一调度。这么做的好处是——各用各的强项,KVM 撑高密度、Hyper-V 给 Windows 容器稳定的内核与驱动生态,同时在香港机房用 VLAN/EVPN 把它们拉到一个二层/三层混合的“同一内网”里。
1. 目标与边界
目标:在香港机房落地一套支持 Windows 容器 + Linux 容器混跑 的统一容器平台,具备弹性伸缩、负载均衡、可观测、持久化存储、灰度/蓝绿。
边界与前提:
- Windows 容器要求 Windows Server 2019/2022 Datacenter(建议 2022,吻合 LTSC/镜像兼容)。
- Linux 节点建议 Ubuntu 22.04 / Rocky 9(内核与 containerd 生态稳)。
- 注:如果你必须用 CentOS 7,我在文末附了兼容提示(内核老、部分 CNI/CSI 版本需要降级)。
- 使用 Kubernetes(kubeadm)+ Calico(Win&Lin 都有成熟支持),Win 节点仅做工作节点,控制面全部在 Linux。
- 底层虚拟化异构:Proxmox VE (KVM) + Hyper-V。
2. 物理与网络拓扑(香港机房版)
2.1 机房与硬件清单
| 角色 | 型号/规格 | CPU | 内存 | 系统盘/数据盘 | 网口 | 备注 |
|---|---|---|---|---|---|---|
| Host-A(KVM/Proxmox) | Dell R740 | 2×Xeon Silver 4210R | 256GB | 2×1.92TB NVMe(ZFS镜像) | 2×10GbE + 2×1GbE | 承载 K8s 控制面 & Linux Worker |
| Host-B(Hyper-V) | HPE DL360 Gen10 | 2×Xeon Silver 4214 | 256GB | 2×1.92TB NVMe(RAID1) | 2×10GbE + 2×1GbE | 承载 Windows Worker |
| ToR 交换机 | 10G L3 Switch(支 VLAN/QinQ/MLAG) | - | - | - | 24×10GbE SFP+ | 与机房上联双归,BFD/VRRP |
我这边把 10GbE 做了 MLAG,管理/业务/存储用不同 VLAN。香港机房常见多线(PCCW/HKT/CTG/CN2),跨大陆回国线路会影响外网拉镜像速度,尽量在本地做镜像缓存/Registry proxy。
2.2 网络与 IP 规划
| 网络 | 用途 | VLAN | 网段 | MTU |
|---|---|---|---|---|
| mgmt | 主机/虚机/带外管理 | 10 | 10.10.10.0/24 | 1500 |
| storage | 分布式存储/备份 | 20 | 10.20.20.0/24 | 9000(如链路支持) |
| k8s-node | K8s 节点互联 | 30 | 10.30.30.0/24 | 1500 |
| k8s-pod (overlay) | Pod Overlay(Calico VXLAN) | - | 172.16.0.0/16(示例) | 1450(推荐) |
| k8s-svc | Service VIP/LoadBalancer | 40 | 10.40.40.0/24 | 1500 |
关键坑:VXLAN/Overlay 会吃掉 MTU,Calico 默认 MTU 一般要手动改到 1450 左右,否则 Win<->Lin 跨节点 Pod 可能间歇包丢。
3. 虚拟化层搭建(异构)
3.1 在 Host-A 安装 Proxmox VE(KVM)
选择 ZFS Mirror(2×NVMe),开 ashift=12、compression=lz4。
为 K8s 控制面与 Linux Worker 准备 VM 模板(Cloud-Init):
- vCPU:4/8,内存:832GB(按负载),磁盘:系统 80120GB + 数据盘(可选)。
- 网卡:virtio,挂到 vmbr30(k8s-node VLAN)+ vmbr10(mgmt VLAN)。
桥接示例(/etc/network/interfaces):
auto vmbr10
iface vmbr10 inet static
address 10.10.10.11/24
bridge-ports eno1.10
bridge-stp off
bridge-fd 0
auto vmbr30
iface vmbr30 inet manual
bridge-ports eno1.30
bridge-stp off
bridge-fd 0
3.2 在 Host-B 安装 Windows Server 2022(Hyper-V)
角色与功能:启用 Hyper-V、Failover Clustering(可选)。
创建外部 vSwitch 绑定到 10GbE,启用 VLAN 30(k8s-node),并为 Windows Worker VM 打上该 VLAN。
关闭会与 Overlay/CNI 冲突的 NIC 特性(按需):
# 典型:禁用 Large Send Offload/Checksum Offload(视网卡驱动)
Get-NetAdapterAdvancedProperty -Name "Ethernet 10G" | ft
Set-NetAdapterAdvancedProperty -Name "Ethernet 10G" -DisplayName "Large Send Offload v2 (IPv4)" -DisplayValue "Disabled"
Set-NetAdapterAdvancedProperty -Name "Ethernet 10G" -DisplayName "Large Send Offload v2 (IPv6)" -DisplayValue "Disabled"
在 Hyper-V 上创建 Windows Server 2022 Datacenter 虚机若干(作为 K8s Windows Worker),内存 16~32GB,系统盘 100GB,挂 VLAN 30。
4. 操作系统与容器运行时
4.1 Linux(Ubuntu 22.04/Rocky 9)节点准备
# 关闭 swap
swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab
# 内核/转发
cat >> /etc/sysctl.d/99-k8s.conf <<EOF
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.neigh.default.gc_thresh1=4096
net.ipv4.neigh.default.gc_thresh2=8192
net.ipv4.neigh.default.gc_thresh3=16384
EOF
sysctl --system
# containerd
apt-get update && apt-get install -y containerd
containerd config default | tee /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl enable --now containerd
4.2 Windows Server 2022(Windows Worker)准备
# 容器与必要组件
Install-WindowsFeature -Name containers
# 安装 containerd
Invoke-WebRequest https://github.com/containerd/containerd/releases/download/v1.7.18/containerd-1.7.18-windows-amd64.tar.gz -OutFile c:\containerd.tgz
# 解压到 C:\containerd,并注册服务(略)
# kubelet/kubeadm/kubectl 版本与控制面一致
# 设置 Windows pause 镜像(匹配 LTSC2022)
[Environment]::SetEnvironmentVariable("KUBELET_EXTRA_ARGS", '--config=C:\k\kubelet.conf --pod-infra-container-image=mcr.microsoft.com/oss/kubernetes/pause:3.9-windows-amd64', 'Machine')
# 时间同步(Windows 容器/证书对时间敏感)
w32tm /config /manualpeerlist:"time.google.com time.windows.com" /syncfromflags:manual /reliable:yes /update
w32tm /resync
关键坑:Windows 的 pause 镜像必须与宿主版本匹配(如 LTSC2022)。不匹配会导致 Pod 一直 ContainerCreating。
5. 部署 Kubernetes(kubeadm)
5.1 初始化控制面(Linux)
kubeadm init \
--apiserver-advertise-address=10.30.30.11 \
--pod-network-cidr=172.16.0.0/16 \
--service-cidr=10.96.0.0/12 \
--kubernetes-version=v1.29.6
配置 kubeconfig、打 Calico(Linux+Windows 组合包,把 MTU 调成 1450):
# values 片段(示例)
# calico.yaml 中搜索 veth_mtu 或 FELIX MTU,改为 1450
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/tigera-operator.yaml
# 自定义安装文件里:
# - calicoNetwork.mtu: 1450
kubectl apply -f custom-calico-installation.yaml
注意:Calico for Windows 需要额外清单(calico-windows),并且 Linux 端的 MTU 要与 Windows 配套。
5.2 加入 Linux Worker
kubeadm token create --print-join-command
# 在 Linux Worker 上执行 join 命令
5.3 加入 Windows Worker
在 Windows 节点上:
# 下载 Calico Windows 组件(示意)
# 配置 HNS 网络由 Calico 接管(安装脚本里会做)
# 执行 kubeadm join(Windows 支持作 worker)
kubeadm join 10.30.30.11:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
校验节点:
kubectl get nodes -o wide
# 你会看到 os=windows 的 worker 出现,Ready 之后就 OK
6. 存储:Linux 优先 + Windows 通过 SMB CSI
在混合场景里,我的实践是Linux 节点装 Longhorn/Ceph 等去承载数据盘,Windows Pod 用 SMB CSI 访问一个高可用 SMB 共享(由 Linux/NAS 提供)。
6.1 部署 SMB CSI(示例)
StorageClass(smb-sc.yaml):
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: smb-sc
provisioner: smb.csi.k8s.io
parameters:
source: "//10.20.20.50/k8sdata" # SMB 服务地址
csi.storage.k8s.io/node-stage-secret-name: "smb-creds"
csi.storage.k8s.io/node-stage-secret-namespace: "kube-system"
dirMode: "0777"
fileMode: "0777"
mountOptions:
- dir_mode=0777
- file_mode=0777
- vers=3.0
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate
Secret(凭据):
apiVersion: v1
kind: Secret
metadata:
name: smb-creds
namespace: kube-system
type: Opaque
data:
username: <base64>
password: <base64>
PVC(示例):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: win-pvc
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: smb-sc
resources:
requests:
storage: 50Gi
7. Ingress 与服务暴露
Nginx Ingress 跑在 Linux 节点,负责 80/443。
Windows 服务通常以 ClusterIP 暴露,由 Ingress 转发到后端(service 里选择器区分 os)。
需要直达 Windows 的场景,可用 NodePort 或 hostNetwork(慎用)。
8. 应用调度与选择器(Windows/Linux 匹配)
Windows .NET 应用(Deployment 示例):
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-legacy-win
spec:
replicas: 2
selector:
matchLabels: app: web-legacy-win
template:
metadata:
labels:
app: web-legacy-win
spec:
nodeSelector:
kubernetes.io/os: windows
tolerations:
- key: "os"
operator: "Equal"
value: "windows"
effect: "NoSchedule"
containers:
- name: web
image: mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022
ports:
- containerPort: 80
volumeMounts:
- name: data
mountPath: "C:\\data"
volumes:
- name: data
persistentVolumeClaim:
claimName: win-pvc
Linux 服务(Deployment 示例):
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-linux
spec:
replicas: 3
selector:
matchLabels:
app: api-linux
template:
metadata:
labels:
app: api-linux
spec:
nodeSelector:
kubernetes.io/os: linux
containers:
- name: api
image: ghcr.io/org/api:1.0.0
ports:
- containerPort: 8080
通过 kubernetes.io/os 精准投递;必要时可结合 NodeAffinity/污点容忍做更细颗粒调度。
9. 可观测:指标、日志、分布式追踪
Metrics:Prometheus + Grafana;Linux 装 node_exporter;Windows 装 windows_exporter。
日志:Fluent Bit DaemonSet,Windows 侧使用 windows 适配的采集器路径。
Tracing:OpenTelemetry Collector,服务内打点,接到 Tempo/Jaeger。
10. 性能与连通性验证(实测样例)
| 测试项 | 工具 | 路径 | 结果(示例) |
|---|---|---|---|
| Pod↔Pod RTT | ping/psping |
WinPod→LinPod(跨宿主) | 0.35~0.55 ms |
| Overlay 吞吐 | iperf3 |
LinPod→WinPod(VXLAN) | 6.8~8.5 Gbps |
| PVC(SMB)顺序读 | diskspd / fio |
WinPod 读 SMB | 750~900 MB/s(10G 直挂) |
| 镜像拉取 | crictl/ctr |
Harbor(本地缓存) | 1.2~1.8 GB/s |
没有本地镜像仓库时,从公网拉 Windows 基础镜像很慢,在香港多线场景尤其明显。强烈建议在机房内部署 Harbor/Registry mirror。
11. 线上常见坑与解决
MTU 不一致导致连接时断时续
症状:Win↔Lin 跨节点 HTTP/GRPC 偶发超时。
解决:Calico 安装时把 MTU 设 1450;确认 Hyper-V vSwitch、物理口 MTU=1500 或 9000 一致;必要时 --vxlan-mtu=1450。
Windows pause 镜像/内核版本不匹配
症状:Pod 卡 ContainerCreating。
解决:使用 mcr.microsoft.com/oss/kubernetes/pause:<version>-windows-amd64 与 LTSC 匹配;K8s 版本与 kubelet/ kube-proxy、containerd 对齐。
时间漂移导致证书/鉴权失败
症状:Kubelet 与 API Server 认证失败、TLS 报错。
解决:Linux 配 chrony,Windows 配 w32time,对齐到同一上游。
Hyper-V 网卡高级特性与 Overlay 冲突
现象:吞吐异常、丢包。
解决:按网卡驱动禁用 LSO/Checksum Offload/VMQ(逐项验证)。
SMB 权限/文件锁
现象:Windows Pod 写入失败或锁定。
解决:SMB 服务端设 durable handles 与合适的 oplocks;K8s 端 ReadWriteMany 正确;必要时区分读写共享。
镜像体积过大,发布慢
解决:多阶段构建、减小 Windows 基础镜像层;在 Harbor 开启压缩;CI 环节预热缓存。
CentOS 7 兼容性提醒
K8s 新版本对内核要求更高,CentOS 7 EOL,建议 Rocky 9 / Ubuntu 22.04。如果必须 C7:
使用较低版本 K8s(如 1.23~1.25)、Calico 对应旧版;containerd 选择稳定旧版。
长期看,不建议新项目继续压在 C7。
12. 灰度/蓝绿与自动化
发布:Argo Rollouts / Flagger,先在 Linux 服务试点,再推广到 Windows 服务(注意探针与 gMSA/权限)。
自动伸缩:HPA + 自定义指标(QPS/RT/队列长度),Windows Pod 的探针与资源限额要更保守一点。
备份:Velero + Restic;Windows 卷(SMB)用存储侧快照。
13. 授权与合规(一定别忽略)
Windows Datacenter 授权包含容器权利(数量不受限),Standard 版本限制较多。
激活方式(KMS/AVMA)在香港机房要提前打通,避免大规模部署后逐台补。
14. 成本/容量规划(样例表)
| 资源 | 基线 | 峰值 | 建议冗余 |
|---|---|---|---|
| vCPU | 64 | 96 | N+1(Fail 1 主机) |
| 内存 | 256GB | 384GB | 25% 预留给系统/IO 缓冲 |
| 存储 | 8TB 可用 | 12TB 可用 | 双份副本 + 异地离线备份 |
| 带宽 | 2×10GbE | 2×10GbE | MLAG + 链路聚合 |
15. 小结(可复用的“落地清单”)
- 异构虚拟化:Proxmox(KVM)跑 Linux 控制面 + Linux Worker;Hyper-V 跑 Windows Worker。
- 网络:VLAN 分区 + Calico VXLAN,MTU=1450;机房内置 Harbor。
- 运行时:containerd 统一;Windows pause 镜像与 LTSC 匹配。
- 存储:Linux 节点本地/分布式盘;Windows 用 SMB CSI 做 RWX。
- 可观测:Prometheus/Grafana + windows_exporter;Fluent Bit 统一日志。
- 发布:Argo/Flagger;先 Linux 后 Windows,逐步推进。
- 授权:Windows Datacenter 优先;KMS/AVMA 提前打通。
尾声:天光微亮,机房冷气仍旧无情
那天清晨五点,Grafana 的趋势线终于稳定下来,Win 与 Lin 的 Pod 互访 RTT 压在 0.5ms 左右,镜像从 Harbor 拉取像本地复制一样顺滑。站在机柜前,我把最后一张变更单拍照归档,心里踏实了——不是因为搞出什么“黑魔法”,而是因为它可复制、可维护、可交接。
后来这套做法又在另外两个香港机房复制了一遍,唯一的区别只是 VLAN 号和上联的运营商。复杂系统的关键,是把边界划清、把坑踩实、把流程固化。这样,无论你是刚入行的新手,还是带队的老兵,都能按这份手册把异构虚拟化 + Win/Linux 混合容器管理稳稳地落下去。
附:命令/配置速查(可直接粘贴用)
- kubeadm init/join 样例(如上)
- Calico Installation(记得改 MTU=1450)
- Windows pause 镜像:mcr.microsoft.com/oss/kubernetes/pause:3.9-windows-amd64(匹配 LTSC2022)
- SMB CSI:storageclass + secret + pvc 三件套(如上)
- Node 选择器:kubernetes.io/os: windows / linux
- 日志与指标:windows_exporter / node_exporter / Fluent Bit