基于Helm与Kubernetes的5G核心网云原生部署实践
1. 项目概述与核心价值最近在折腾5G核心网部署发现了一个宝藏项目Orange-OpenSource/towards5gs-helm。这可不是一个简单的Helm Chart仓库它背后是Orange这家全球领先的电信运营商的开源实践目标是把复杂的5G核心网组件通过Kubernetes和Helm这套云原生标准工具链变得像部署一个Web应用一样简单、可重复、可管理。如果你正在研究5G、云原生网络或者头疼于如何将NFV网络功能虚拟化平滑过渡到CNF云原生网络功能这个项目绝对值得你花时间深挖。简单来说towards5gs-helm提供了一套完整的、生产可参考的Helm Charts用于在Kubernetes上部署和运行3GPP标准的5G核心网。它基于著名的free5GC或open5gs等开源5GC项目但解决了从“能跑起来”到“能在生产环境稳定运行”之间的巨大鸿沟。项目名中的“towards”很有深意它代表着一种方向——朝着用云原生方法构建和管理5G核心网迈进。对于开发者、架构师和运维工程师而言它不仅仅是一堆YAML文件更是一套经过验证的最佳实践模板涵盖了网络配置、服务发现、持久化、监控、高可用等你在真实部署中必然会遇到的所有棘手问题。2. 项目整体架构与设计哲学2.1 为什么是Helm Kubernetes5G核心网的传统部署方式要么是基于物理专有设备要么是使用VM手动配置的NFV。这两种方式都存在部署慢、升级复杂、资源利用率低、故障恢复时间长的问题。towards5gs-helm选择Helm和Kubernetes正是为了应对这些挑战。Helm作为Kubernetes的包管理器它把5G核心网中每个网络功能如AMF、SMF、UPF以及其依赖如数据库、消息队列打包成一个独立的“Chart”。每个Chart里包含了部署所需的所有Kubernetes资源定义Deployment, Service, ConfigMap等以及可配置的values.yaml。这意味着参数化配置你可以通过一个中心化的values文件轻松调整所有网元的镜像版本、副本数、资源限制、网络配置等无需手动修改几十个YAML文件。依赖管理Chart可以声明依赖关系。例如部署SMF可能需要先有UDM用户数据管理Helm会帮你管理这些依赖的安装顺序。版本化与回滚每次安装或升级都是一个明确的“Release”出问题可以一键回滚到上一个稳定版本这对于核心网络这种对稳定性要求极高的场景至关重要。Kubernetes则提供了运行时的保障声明式运维你只需要告诉K8s“我想要5个AMF实例在运行”它会自动帮你创建、调度、监控并保持这个状态。高可用与自愈通过Deployment和ReplicaSetPod容器实例故障后会自动重启或迁移结合就绪探针和存活探针确保服务持续可用。资源管理与隔离可以为每个5G网元精确分配CPU、内存资源并利用命名空间进行逻辑隔离避免“吵闹的邻居”问题。服务发现与负载均衡Kubernetes Service为内部复杂的5G网元间通信提供了稳定的网络端点无论是ClusterIP用于内部通信还是LoadBalancer/NodePort用于对外暴露N1/N2/N4等接口都变得标准化。注意将5G核心网容器化并上K8s并非简单地把二进制文件塞进容器。需要仔细处理有状态服务如UDM的数据库、高性能网络UPF的数据面转发、以及时间同步NTP/PTP等特殊需求。towards5gs-helm的Chart设计正是在解决这些难题。2.2 核心组件与Chart结构解析该项目通常为5G核心网的每个标准网元提供一个独立的Helm Chart。我们以一套典型的5G SA独立组网核心网为例拆解其核心组件控制面网元AMF (Access and Mobility Management Function)接入和移动性管理功能是终端UE接入网络的第一个控制点。Chart需要配置N1/N2接口、与NRF的交互、以及AMF Set/Region等用于容灾的标识。SMF (Session Management Function)会话管理功能负责UPF选择、IP地址分配、会话策略控制。它的Chart配置最为复杂涉及与PCF、UDM、UPF的多方交互以及数据网络DNN的配置。UDM/UDR (Unified Data Management/Repository)统一数据管理/存储。这是典型的有状态服务Chart中必须包含数据库如MongoDB的部署并处理好数据持久化PersistentVolume和初始化如创建索引。PCF (Policy Control Function)策略控制功能。Chart需要配置策略规则以及与SMF的接口。NRF (Network Repository Function)网络仓库功能相当于5G核心网的服务发现中心。所有网元都要向NRF注册。它的高可用性设计至关重要。AUSF (Authentication Server Function)认证服务器功能。用户面网元UPF (User Plane Function)用户面功能负责数据包的转发、路由和策略执行。这是性能瓶颈和设计难点。Chart需要处理高性能网络通常需要启用hostNetwork模式或使用SR-IOV、DPDK等加速技术以绕过K8s网络栈获得接近线速的转发性能。多网卡配置区分N3接入侧、N6数据网络侧等不同网络接口。特殊权限可能需要privileged: true权限或特定的Linux Capabilities来操作网络设备。支撑与基础设施MongoDB/Redis作为UDM/UDR、PCF等网元的后端存储。项目可能会提供内嵌的子Chart或推荐使用外部的、经过优化的数据库Operator如MongoDB Community Operator。WebUI一个用于展示网络拓扑、查看注册用户、会话状态的可视化控制台。Grafana Prometheus监控套件。Chart中通常会集成ServiceMonitor自动抓取各网元暴露的指标如注册用户数、会话数、消息处理延迟。项目的目录结构通常如下所示towards5gs-helm/ ├── charts/ │ ├── amf/ │ │ ├── Chart.yaml │ │ ├── values.yaml │ │ ├── templates/ # 存放所有K8s资源模板文件 │ │ └── ... │ ├── smf/ │ ├── upf/ │ └── ... ├── umbrella-chart/ # 可选一个总Chart一键部署整个5GC │ ├── Chart.yaml │ ├── values.yaml │ └── charts/ # 依赖所有子Chart └── examples/ └── values-full.yaml # 一份完整的、包含所有配置的values示例文件2.3 网络架构设计考量在Kubernetes中部署5G核心网网络规划是重中之重。towards5gs-helm的values文件里网络相关的配置项通常占很大比重。服务发现与通信所有控制面网元AMF, SMF, UDM等通过Kubernetes ServiceClusterIP类型相互发现和通信。NRF的Service名称如nrf-svc会成为其他网元配置中的通用端点。对外暴露接口N1/N2 (AMF)需要暴露给基站gNB和终端。通常使用LoadBalancer类型的Service在公有云或支持MetalLB的本地集群或者NodePort并配合外部负载均衡器。安全组和防火墙规则必须相应开放。N4 (SMF-UPF)SMF与UPF之间的控制接口。由于UPF可能采用主机网络SMF可能需要通过UPF Pod所在节点的特定IP和端口来访问它。N6 (UPF)UPF到互联网或企业数据网络的出口。这通常通过UPF Pod的第二个网络接口或主机网络直接连接外部物理网络。CNI插件选择默认的Calico或Flannel可能无法满足UPF的高性能需求。生产环境往往会考虑Cilium得益于eBPF的高性能、Multus支持多网卡或特定的SR-IOV CNI插件。towards5gs-helm的UPF Chart可能需要适配不同的CNI配置。3. 核心细节解析与实操要点3.1 Values.yaml 深度配置指南values.yaml是整个Helm部署的灵魂。以AMF Chart为例我们拆解关键配置段# towards5gs-helm/charts/amf/values.yaml 示例片段 image: repository: towards5gs/amf tag: latest # 生产环境务必指定具体版本号如v3.2.1 pullPolicy: IfNotPresent replicaCount: 2 # 决定AMF的Pod副本数用于高可用 # 资源限制根据实际负载调整 resources: limits: cpu: 1 memory: 512Mi requests: cpu: 500m memory: 256Mi # 这是5G核心网特有的配置通过ConfigMap或环境变量注入容器 configuration: # AMF实例标识同一AMF Set内的实例需配置相同的setId amfName: amf1 ngapIp: 0.0.0.0 # 容器内监听地址 sbiIp: 0.0.0.0 nrfUri: http://nrf-svc:8000 # 指向NRF的Service # 服务区域列表定义该AMF覆盖的TACs servedGuamiList: - plmnId: 20893 amfId: cafe00 # 网络切片选择辅助信息 networkSliceList: - sst: 1 sd: 010203 # Kubernetes Service配置 service: type: ClusterIP # 内部通信 ngapPort: 38412 # N2接口端口 sbiPort: 80 # 服务化接口端口 # 如果需要对外暴露N2接口给gNB serviceExternal: enabled: true type: LoadBalancer ngapPort: 38412 # 可以为LoadBalancer指定特定IP或使用注解配置特定云供应商功能 # loadBalancerIP: 10.0.100.10 # annotations: # metallb.universe.tf/address-pool: public-ips关键配置解析与避坑镜像标签永远不要在生产环境使用latest标签。锁定一个已知稳定的版本。资源请求与限制requests是调度依据limits是硬性上限。5G网元尤其是UPF、SMF在忙时可能突发流量limits设置过紧会导致Pod被OOM Kill或Throttle。建议先监控后调整。nrfUri这是服务发现的关键。必须确保这个域名nrf-svc能在Pod内正确解析到NRF的Service。在复杂的多集群或混合网络环境中可能需要配置CoreDNS或hostAliases。网络切片配置sst切片类型和sd切片区分符必须与终端、基站以及SMF、PCF中的配置匹配否则切片选择会失败。对外暴露服务使用LoadBalancer时要清楚云供应商的负载均衡器创建时间和成本。NodePort则需自行管理外部负载均衡和健康检查。3.2 有状态服务的数据持久化UDM/UDR和PCF等网元依赖数据库。在K8s中处理有状态服务需要格外小心。# 以UDM Chart中MongoDB的配置为例 udm: persistence: enabled: true # 使用StorageClass动态 provisioning storageClass: fast-ssd accessModes: - ReadWriteOnce size: 10Gi # 挂载路径 mountPath: /data/db # 或者使用独立的MongoDB子Chart或外部数据库 externalMongoDB: enabled: false # 如果使用云数据库服务或独立部署的MongoDB集群 # uri: mongodb://user:passmongodb-svc:27017/udm实操心得StorageClass选择根据数据库的IO性能要求选择。本地SSD盘localvolume性能最好但需要管理节点亲和性。网络存储如Ceph RBD AWS gp3更灵活但延迟稍高。访问模式MongoDB单实例通常用ReadWriteOnce。如果部署MongoDB副本集生产环境推荐则需要能被多个Pod挂载的ReadWriteMany存储这对存储后端有要求。备份与恢复K8s的PersistentVolumePV本身不提供备份。必须建立独立的数据库备份策略例如使用mongodump定期备份到对象存储或使用K8s原生备份工具如Velero。初始化Chart的templates/目录下可能会有configmap-init.yaml或job.yaml用于在数据库Pod启动后执行初始化脚本创建数据库、用户、集合索引。要确保这些初始化Job只成功运行一次。3.3 配置管理与敏感信息处理5G核心网配置包含IP地址、端口、PLMN ID、数据库密码等大量信息。Helm提供了多种管理方式默认Values 自定义Values文件最佳实践是保持charts/目录下的原始values.yaml不变创建一个自定义的my-values.yaml文件使用helm install -f my-values.yaml来覆盖默认值。这便于版本控制和管理不同环境开发、测试、生产的配置。ConfigMap vs. 环境变量复杂的配置文件如JSON、YAML格式的网元配置适合放在ConfigMap中挂载到容器内。简单的键值对则可以通过环境变量注入。在Chart的templates/configmap.yaml中可以看到如何将values.yaml中的configuration部分生成为ConfigMap。Secret管理数据库密码、证书私钥等必须使用Kubernetes Secret。Helm支持在values.yaml中通过secretKeyRef引用Secret。绝对不要将明文密码写在values.yaml或提交到代码库。可以使用helm secrets插件集成sops或vals在部署时动态解密或使用云厂商的密钥管理服务如AWS KMS, GCP Secret Manager。4. 完整部署流程与核心环节实现4.1 前置环境准备假设你已有一个运行正常的Kubernetes集群版本1.23。以下是额外的必要准备安装Helm确保Helm 3.x客户端已安装。配置存储根据需要创建合适的StorageClass。例如在本地测试中使用hostPath在生产中使用云存储或配置好的Ceph集群。# 示例创建一个使用本地目录的StorageClass (仅用于测试) cat EOF | kubectl apply -f - apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer EOF加载容器镜像如果是在离线环境或内部仓库需要先将towards5gs相关的Docker镜像推送到你的私有仓库并在values.yaml中更新image.repository字段。网络规划确定用于N2、N3、N6等接口的IP地址段。如果使用MetalLB提供LoadBalancer需要配置地址池。如果UPF要使用主机网络或SR-IOV需要在对应节点上配置好物理网卡和驱动。4.2 分步部署实战我们采用“由内向外”的顺序部署先部署内部依赖和服务发现再部署控制面最后部署用户面。步骤一添加仓库并查看Charthelm repo add towards5gs https://orange-opensource.github.io/towards5gs-helm/ helm repo update helm search repo towards5gs # 查看所有可用的Chart步骤二部署NRF服务发现核心NRF是第一个需要部署的组件因为其他所有网元都要向它注册。# 1. 创建一个独立的namespace便于管理 kubectl create namespace 5g-core # 2. 为NRF准备自定义配置 cat nrf-values.yaml EOF replicaCount: 2 image: tag: v3.2.1 service: type: ClusterIP port: 8000 # 如果NRF需要持久化存储例如缓存注册信息可以在这里配置 # persistence: # enabled: true # storageClass: local-storage # size: 5Gi EOF # 3. 部署NRF helm install nrf towards5gs/nrf -n 5g-core -f nrf-values.yaml # 4. 检查部署状态 kubectl get pods,svc -n 5g-core -l appnrf # 等待Pod状态变为Running并且READY为1/1或2/2。步骤三部署UDM/UDR用户数据管理UDM是有状态服务需要数据库。# 1. 准备UDM配置重点是指向NRF和配置数据库 cat udm-values.yaml EOF configuration: nrfUri: http://nrf-svc.5g-core.svc.cluster.local:8000 # 使用完整的K8s内部域名 mongoUri: mongodb://mongodb-svc:27017 # 假设MongoDB Service名称为mongodb-svc # 如果使用Chart内嵌的MongoDB子Chart mongodb: enabled: true architecture: standalone auth: enabled: true rootPassword: 请替换为强密码 # 生产环境应从Secret读取 persistence: enabled: true storageClass: local-storage size: 10Gi EOF # 2. 部署UDM (它会自动部署MongoDB) helm install udm towards5gs/udm -n 5g-core -f udm-values.yaml # 3. 检查MongoDB和UDM Pod kubectl get pods -n 5g-core -l app in (udm, mongodb)步骤四部署其他控制面网元AMF, SMF, PCF, AUSF流程类似每个都需要一份自定义的values.yaml核心是正确配置nrfUri以及与其他网元的关联信息如SMF需要配置UDM、PCF的地址。以AMF为例cat amf-values.yaml EOF replicaCount: 2 configuration: amfName: amf-01 nrfUri: http://nrf-svc.5g-core.svc.cluster.local:8000 servedGuamiList: - plmnId: 20893 # MCC MNC amfId: cafe00 supportTaiList: - plmnId: 20893 tac: 000001 service: type: ClusterIP serviceExternal: enabled: true type: LoadBalancer # 或NodePort annotations: metallb.universe.tf/address-pool: public-ips ngapPort: 38412 EOF helm install amf towards5gs/amf -n 5g-core -f amf-values.yaml步骤五部署UPF用户面功能这是最具挑战性的一步因为涉及高性能网络。cat upf-values.yaml EOF # 关键选择正确的网络模式 network: mode: host # 可选host, sriov, macvlan。host模式性能好但牺牲了可移植性。 # 如果modehost需要指定节点选择器将UPF调度到具有特定网卡的节点上 nodeSelector: node-role.kubernetes.io/upf-node: # 配置N3和N6接口的网卡信息host模式下直接使用主机网卡 interfaces: n3: dev: eth1 # 连接基站的网卡 ip: 10.100.0.10/24 n6: dev: eth2 # 连接互联网的网卡 ip: 192.168.100.10/24 gw: 192.168.100.1 configuration: nrfUri: http://nrf-svc.5g-core.svc.cluster.local:8000 # UPF特定的配置如DNN列表、QoS规则等 dnnList: - dnn: internet cidr: 60.60.0.0/16 # 为UE分配的IP池 EOF # 首先给目标节点打上标签 kubectl label nodes your-upf-node-name node-role.kubernetes.io/upf-node # 然后部署UPF helm install upf towards5gs/upf -n 5g-core -f upf-values.yaml步骤六使用Umbrella Chart一键部署可选对于测试环境项目可能提供一个“总Chart”可以一键部署所有组件。# 下载或克隆仓库进入umbrella-chart目录 git clone https://github.com/Orange-OpenSource/towards5gs-helm.git cd towards5gs-helm/umbrella-chart # 编辑顶层的values.yaml配置所有组件的参数 cp values.yaml my-global-values.yaml vim my-global-values.yaml # 一键安装 helm install full-5gc . -n 5g-core -f my-global-values.yaml4.3 部署后验证与连通性测试部署完成后不能只看Pod状态是Running就万事大吉。基础状态检查kubectl get pods -n 5g-core # 所有Pod应为Running且Ready kubectl get svc -n 5g-core # 查看Service特别是LoadBalancer类型的外部IP日志检查查看关键组件日志确保没有持续报错。kubectl logs -n 5g-core deployment/amf --tail50 kubectl logs -n 5g-core deployment/nrf --tail50 # 重点关注“registered”、“connected”、“successful”等关键字以及错误堆栈。NRF服务注册验证检查各网元是否成功向NRF注册。# 假设NRF Service端口为8000临时端口转发到本地 kubectl port-forward -n 5g-core svc/nrf-svc 8080:8000 # 然后访问NRF的API curl http://localhost:8080/nnrf-nfm/v1/nf-instances应该返回一个JSON列表包含已注册的AMF、SMF等网元信息。基本信令流程测试使用5G测试终端模拟器如UERANSIM连接你部署的AMF外部IP和端口尝试发起注册请求。观察AMF、AUSF、UDM的日志看注册流程是否顺利走通。5. 常见问题、排查技巧与性能调优实录5.1 部署阶段常见问题问题1Pod一直处于Pending状态。可能原因资源不足、节点选择器不匹配、PVC无法绑定。排查kubectl describe pod pod-name -n 5g-core查看Events部分。常见信息Insufficient cpu/memory调整values.yaml中的resources.requests或为集群增加资源。didn‘t find available persistent volumes检查StorageClass配置和PV是否可用。node(s) didn‘t match Pod‘s node selector检查Pod的nodeSelector配置并确保有节点拥有相应标签。问题2Pod处于CrashLoopBackOff状态。可能原因容器启动后立即退出通常是配置错误、依赖服务不可用或镜像问题。排查kubectl logs pod-name -n 5g-core --previous # 查看上一次运行的日志连接NRF失败日志中常见“Failed to connect to NRF”。检查nrfUri配置是否正确注意命名空间5g-core以及NRF服务是否真的可达在Pod内执行curl测试。数据库连接失败检查MongoDB连接字符串、用户名密码以及MongoDB Pod是否就绪。配置文件语法错误检查通过ConfigMap注入的配置文件格式YAML/JSON确保没有缩进或语法错误。问题3Service无法通过域名访问。可能原因CoreDNS问题、网络策略阻拦。排查# 进入一个已存在的Pod如busybox进行调试 kubectl run -it --rm debug --imagebusybox -n 5g-core -- sh # 在debug容器内 nslookup nrf-svc.5g-core.svc.cluster.local curl -v http://nrf-svc.5g-core.svc.cluster.local:8000如果nslookup失败是DNS问题。如果解析成功但curl失败可能是网络策略或服务端口问题。5.2 运行时问题与性能调优问题4UPF数据面转发性能不达标。根因分析默认的容器网络veth pair iptables/ipvs会引入额外开销。解决方案Host网络模式如部署示例所示性能最好但UPF Pod与主机网络栈绑定失去了部分K8s特性如Service网络。SR-IOV为UPF Pod分配一个物理网卡VF虚拟功能能获得接近原生性能。需要在节点安装SR-IOV驱动和CNI插件并在Chart中配置资源请求intel.com/sriov。eBPF加速使用Cilium CNI并开启eBPF主机路由kube-proxy-replacement模式可以大幅提升网络性能。CPU绑核与巨页在UPF的values.yaml中为DPDK或高性能转发的进程分配独占CPU核和HugePages。resources: limits: cpu: 2 memory: 2Gi hugepages-2Mi: 1Gi # 申请巨页 requests: cpu: 2 memory: 2Gi hugepages-2Mi: 1Gi # 使用CPU管理器策略为Pod分配独占CPU # 需要在kubelet开启--cpu-manager-policystatic并为节点打上标签问题5控制面网元如SMF处理延迟高。排查方向资源瓶颈使用kubectl top pods查看CPU/内存使用率。如果持续接近limits需要调高。依赖服务延迟SMF需要频繁调用UDM、PCF。检查这些下游服务的响应时间。可以给这些服务添加Sidecar代理如Envoy来收集指标或直接查看其日志。垃圾回收GC对于JVM或Go编写的网元不合理的GC配置可能导致周期性停顿。需要调整容器的JVM/Go GC参数。日志级别生产环境应将日志级别从DEBUG调整为INFO或WARN减少I/O开销。问题6如何实现跨可用区的高可用解决方案Pod反亲和性在values.yaml中为关键网元AMF, SMF, NRF配置Pod反亲和性确保同一应用的多个副本被调度到不同的节点或可用区。affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - amf topologyKey: topology.kubernetes.io/zone # 或 kubernetes.io/hostnameNRF与数据库的高可用NRF本身可以多副本但需要共享存储吗通常NRF是无状态的注册信息可重建多副本即可。UDM的MongoDB则需要部署为副本集并配置在values.yaml中。全局负载均衡对于暴露给基站的AMF N2接口可以使用多个LoadBalancer IP或者在更高层使用DNS轮询/全局负载均衡器GSLB将流量分发到不同区域的集群。5.3 监控与告警搭建“无监控不运维”。5G核心网更需要细致的监控。集成项目内置的监控很多towards5gs-helmChart已经集成了Prometheus指标暴露。检查values.yaml中是否有metrics或prometheus相关的配置将其启用。metrics: enabled: true serviceMonitor: enabled: true # 自动创建Prometheus Operator的ServiceMonitor关键指标控制面各网元的HTTP/gRPC请求速率、延迟、错误率5xx响应NRF的注册NF数量AMF的注册用户数、连接基站数SMF的活跃会话数。用户面UPF的吞吐量bps, pps、丢包率、转发延迟。系统资源Pod的CPU、内存、网络I/O使用率。配置Grafana仪表盘可以从社区寻找或自行制作5G核心网专属的Grafana看板将上述指标可视化。告警规则如“AMF注册用户数5分钟内下降90%”、“UPF丢包率0.1%”应在Prometheus Alertmanager中配置。5.4 升级与回滚策略版本管理每次部署或升级都应使用明确的Helm Release版本和Chart版本。在values.yaml中固定所有镜像的标签。升级流程# 1. 先查看当前发布状态 helm list -n 5g-core # 2. 拉取最新的Chart helm repo update # 3. 干运行测试升级 helm upgrade release-name towards5gs/chart-name -n 5g-core -f my-values.yaml --dry-run --debug # 4. 执行升级 helm upgrade release-name towards5gs/chart-name -n 5g-core -f my-values.yaml # 5. 观察Pod滚动更新状态 kubectl get pods -n 5g-core -w回滚如果升级后出现问题迅速回滚。helm history release-name -n 5g-core # 查看历史版本 helm rollback release-name revision-number -n 5g-core # 回滚到指定版本数据库Schema升级这是最危险的部分。如果新版本Chart要求数据库Schema变更务必先备份数据库并仔细阅读Chart的升级说明通常位于README.md或UPGRADE.md看是否需要手动执行迁移脚本。