利用OCI免费套餐构建生产级Kubernetes集群:架构设计与实战部署

利用OCI免费套餐构建生产级Kubernetes集群:架构设计与实战部署 1. 项目概述在OCI免费层上构建生产就绪的K8s集群“nce/oci-free-cloud-k8s”这个项目标题初看可能有些技术缩写但它的核心价值非常明确利用Oracle Cloud InfrastructureOCI的永久免费套餐搭建一个功能完整、可用于学习和轻度生产环境的KubernetesK8s集群。对于开发者、运维工程师或是任何想深入云原生技术栈的人来说这无疑是一个极具吸引力的“羊毛”。OCI的免费套餐在业界以慷慨著称提供包括2个AMD计算实例、4个Arm Ampere A1计算核心、200GB块存储等在内的丰富资源且没有过期时间。这个项目的精髓就在于教你如何合规、高效地将这些免费资源“组装”成一个真正可用的K8s环境而不是仅仅停留在创建几个虚拟机的层面。我之所以花时间研究并实践这套方案是因为在云原生学习过程中一个稳定、低成本且能完全掌控的K8s环境是刚需。公有云托管的K8s服务如EKS、AKS、GKE虽然方便但免费额度有限或成本不菲本地使用Minikube或Kind又受限于本地硬件和网络环境。OCI的免费层恰好提供了一个绝佳的平衡点它拥有公网IP、稳定的网络和充足的资源足以运行一个包含控制平面和工作节点的标准集群让你能实践完整的K8s操作包括部署有状态应用、配置网络策略、设置存储卷等。这个项目适合所有对Kubernetes和云基础设施感兴趣的实践者。无论你是想从零开始学习K8s概念还是需要一个小型、稳定的环境来测试Helm Chart、CI/CD流水线或是部署个人项目这套基于OCI免费层的方案都能提供一个近乎“零成本”的 playground。接下来我将从架构设计、实操部署到运维调优完整拆解如何将这个想法落地。2. 架构设计与资源规划在OCI免费层上构建K8s首要任务是吃透免费套餐的规则并在此基础上设计出最优的架构。盲目创建资源很容易导致超额收费或者构建出性能低下的集群。2.1 OCI免费套餐资源深度解析OCI的“始终免费”资源是项目的基石我们必须精确理解其限制和潜力计算实例VMAMD实例2个每个配备1/8 OCPU相当于1个vCPU核心的1/8和1GB内存。关键点这1/8 OCPU是基准性能但支持突发Burstable性能。在空闲时积累CPU积分需要时爆发使用。对于K8s控制平面组件如kube-apiserver、etcd其负载通常是间歇性的突发特性非常合适。Arm Ampere A1实例最多4个OCPU和24GB内存可以自由组合。例如你可以创建2个VM每个2 OCPU 12GB内存。这是本项目的性能核心。Arm架构的兼容性如今已不是问题主流Linux发行版和容器镜像都提供Arm64版本。存储块存储200GB支持最高100次/月的备份。我们可以将其分割用于虚拟机的启动卷和数据卷。对象存储10GB不限请求次数。适合存放集群备份、容器镜像如果使用OCI容器仓库、日志归档等。网络带宽每月10TB出站数据入站数据免费。对于学习和测试而言10TB是绝对充裕的。公共IP2个临时公共IP和1个预留公共IP。预留公共IP是关键资源我们需要将其分配给负载均衡器Load Balancer或作为某个节点的固定入口。其他还包含负载均衡器10Mbps带宽、监控数据等都是构建生产式架构的重要拼图。注意务必在创建资源时确认所选资源形状Shape属于“始终免费”范畴。OCI控制台会有明确标识。超出免费层的资源会产生费用。2.2 高可用与成本平衡的集群架构在免费资源约束下追求多控制平面节点的高可用HA是不现实的因为那会耗尽所有计算资源。因此我们的目标是构建一个“单控制平面 多工作节点”的稳健架构在免费范围内实现资源最大化利用。我推荐的架构如下控制平面节点1个使用一个Ampere A1实例配置为2 OCPU 12GB内存。选择Ampere而非AMD是因为控制平面组件特别是etcd对内存和稳定I/O有一定要求12GB内存能确保集群运行流畅。我们将在这个节点上安装kubeadm,kubelet,kubectl并运行kubeadm init来初始化控制平面。工作节点2个使用剩余的免费资源创建两个工作节点。工作节点1另一个Ampere A1实例配置为2 OCPU 12GB内存。工作节点2一个AMD实例配置为1/8 OCPU 1GB内存。这样我们总共使用了4个Arm OCPU和1个AMD OCPU完全在免费额度内。AMD节点虽然性能较弱但可以作为运行轻量级、后台任务Pod的节点通过K8s的节点选择器和污点/容忍度来调度。网络与存储设计网络所有实例创建在同一个虚拟云网络VCN和子网内确保Pod网络如Calico、Flannel能够互通。存储为每个实例分配足够的启动卷建议40-50GB剩余的块存储可以创建为独立卷并手动挂载到某个节点上通过K8s的hostPath或后续部署CSI驱动来提供持久化存储。更推荐的做法是使用OCI提供的CSI驱动但这通常需要配置IAM策略可能涉及付费账户的额外权限在纯免费账户中操作需格外谨慎。负载均衡使用免费的负载均衡器服务为其分配那个宝贵的预留公共IP。这样我们就可以通过一个稳定的IP来暴露K8s的Ingress Controller如Nginx Ingress服务从而访问集群内的应用。这个架构的优势在于它充分利用了免费资源中性能最强的Arm实例同时纳入了所有可用资源形成了一个有主次、可调度的混合集群非常贴近真实环境中异构节点的场景。3. 核心组件选型与前置配置在开始创建实例之前我们需要确定几个核心软件的选择这关系到后续部署的顺利程度。3.1 操作系统与容器运行时选择操作系统Oracle Linux 8或Ubuntu 22.04 LTS是首选。两者都对OCI和Arm架构有良好的支持。我个人更倾向于Oracle Linux因为它与OCI集成度更高且其内核针对云环境有优化。Ubuntu的社区资源更丰富根据个人习惯选择即可。容器运行时Kubernetes 1.24版本默认移除了对Docker Shims的支持因此我们需要选择containerd或cri-o。推荐使用containerd它现在是K8s生态中的事实标准轻量且稳定。安装过程也相对简单。3.2 网络插件选型K8s集群的网络插件负责Pod之间的通信。在云环境中Calico和Cilium是两大主流选择。Calico成熟、稳定、文档丰富支持网络策略NetworkPolicy性能不错。对于免费层集群来说它是非常稳妥的选择。Cilium基于eBPF功能强大能提供更佳的可观测性和安全性但部署和配置稍复杂。考虑到我们的目标是快速搭建一个稳定可用的学习环境我推荐使用Calico。我们将使用kubeadm初始化集群时通过传递--pod-network-cidr参数来指定Pod网段然后一键安装Calico的Manifest文件即可。3.3 OCI实例创建与系统配置实操现在我们进入OCI控制台进行实操。创建VCN和子网导航到“网络” - “虚拟云网络”。创建VCN时选择“创建虚拟云网络”并取消勾选“使用CIDR块创建子网”和“创建NAT网关”等选项。我们只创建最基础的VCN以节省可能涉及的非免费资源。创建成功后进入该VCN手动创建一个公共子网。CIDR块可以设为10.0.0.0/24。确保“子网访问”选择了“公共子网”这样实例会自动获取公共IP。创建计算实例导航到“计算” - “实例”。点击“创建实例”。命名和放置给实例起个好记的名字如k8s-master。保持其他默认设置。镜像选择Oracle Linux 8或Ubuntu 22.04的镜像。形状这是关键。点击“更改形状”。对于控制平面节点在“处理器架构”下选择“Arm”然后选择“VM.Standard.A1.Flex”形状。将“OCPU数量”设置为2“内存量(GB)”设置为12。确认每月估算成本为0。对于AMD工作节点选择“AMD”架构形状选择“VM.Standard.E2.1.Micro”这就是那个1/8 OCPU的免费形状。添加SSH密钥必须上传你的公钥如id_rsa.pub这是后续登录的唯一方式。启动卷将启动卷大小调整为50GB免费层内。网络选择刚才创建的VCN和公共子网。确认创建仔细检查形状和费用估算确认无误后创建实例。重复以上过程创建另外两个工作节点实例。配置系统安全组防火墙在实例详情页的“子网”部分点击关联的安全列表。我们需要添加入站规则开放必要的端口控制平面节点需要允许所有节点能访问6443端口kube-apiserver以及节点间Pod网络插件所需的端口如Calico的179、2379、4789、5473等具体看Calico文档。为简化初期可以暂时为安全组添加入站规则源CIDR为10.0.0.0/16你的VCN网段IP协议为“所有协议”。生产环境务必细化规则。工作节点同样需要开放Pod网络和NodePort范围30000-32767的通信。4. 集群初始化与节点加入所有实例创建并运行后通过SSH连接到你的控制平面节点Master。4.1 基础环境准备在所有节点包括Master和Worker上执行以下操作# 1. 关闭SwapKubernetes要求 sudo swapoff -a # 永久禁用编辑 /etc/fstab注释掉swap的行 sudo sed -i / swap / s/^/#/ /etc/fstab # 2. 配置内核模块和sysctl参数 cat EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system # 3. 安装containerd # 对于Oracle Linux 8: sudo dnf config-manager --add-repohttps://download.docker.com/linux/centos/docker-ce.repo sudo dnf install -y containerd.io # 对于Ubuntu 22.04: # sudo apt-get update sudo apt-get install -y containerd # 4. 配置containerd使用systemd作为cgroup驱动 sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml sudo sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml sudo systemctl restart containerd sudo systemctl enable containerd # 5. 安装kubeadm, kubelet, kubectl # 添加Kubernetes仓库 cat EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [kubernetes] nameKubernetes baseurlhttps://pkgs.k8s.io/core:/stable:/v1.28/rpm/ enabled1 gpgcheck1 gpgkeyhttps://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key EOF # 安装指定版本避免自动升级到不兼容版本 sudo dnf install -y kubelet-1.28.0 kubeadm-1.28.0 kubectl-1.28.0 --disableexcludeskubernetes sudo systemctl enable --now kubelet4.2 使用kubeadm初始化控制平面仅在Master节点上执行# 初始化集群指定Pod网段需与后续Calico的默认网段匹配 sudo kubeadm init --pod-network-cidr192.168.0.0/16 --control-plane-endpoint$(hostname -I | awk {print $1}) --apiserver-advertise-address$(hostname -I | awk {print $1}) # 初始化成功后会输出类似下面的信息请务必保存好 # Your Kubernetes control-plane has initialized successfully! # ... # Then you can join any number of worker nodes by running the following on each as root: # kubeadm join control-plane-host:control-plane-port --token token --discovery-token-ca-cert-hash sha256:hash # 配置kubectl mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config4.3 安装Calico网络插件在Master节点上执行kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/tigera-operator.yaml kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/custom-resources.yaml等待几分钟使用kubectl get pods -n calico-system查看所有Pod是否变为Running状态。4.4 将工作节点加入集群在Master节点初始化输出的命令中找到kubeadm join ...那一行。注意如果命令中包含了--control-plane说明是添加控制平面节点我们不需要。确保你使用的是给工作节点加入的命令。分别登录到两个工作节点执行从Master节点获取的kubeadm join命令需要sudo权限。回到Master节点执行kubectl get nodes你应该能看到三个节点状态都是NotReady稍等片刻等待Calico等组件启动就会全部变为Ready。5. 关键服务部署与集群功能完善一个基础的K8s集群已经运行但要让它变得“好用”还需要部署一些核心的插件和服务。5.1 部署Ingress Controller以Nginx Ingress为例Ingress Controller是外部流量进入集群的入口。我们将使用NodePort方式暴露它然后通过OCI负载均衡器将流量指向它。# 使用Helm安装需先安装Helm # 添加仓库并安装 helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx \ --create-namespace \ --set controller.service.typeNodePort \ --set controller.service.nodePorts.http30080 \ --set controller.service.nodePorts.https30443安装后使用kubectl get svc -n ingress-nginx查看ingress-nginx-controller服务的NodePort例如HTTP端口是30080。5.2 配置OCI负载均衡器指向Ingress在OCI控制台进入“网络” - “负载均衡器”。创建负载均衡器选择“公共”类型形状选择“10Mbps”网络选择之前创建的VCN和公共子网。关键一步在“公共IP地址”处选择“预留公共IP”这样你就拥有了一个固定的公网IP。创建后端集协议和端口选择HTTP和30080对应Ingress的NodePort。健康检查路径设为/healthz。添加后端将你的两个工作节点注意是工作节点不是Master的私有IP地址和端口30080添加进去。创建路由规则路径“/”后端集选择刚创建的那个。现在访问负载均衡器的公共IP如果看到Nginx的404页面说明Ingress Controller已经成功通过负载均衡器对外暴露。5.3 部署Metrics Server与启用Dashboard可选Metrics Server用于收集资源指标是HPA自动扩缩容和kubectl top命令的基础。kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # 可能需要修改部署参数以跳过TLS验证在args中添加 --kubelet-insecure-tlsKubernetes Dashboard提供了一个Web UI方便管理。kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml # 创建访问令牌和登录方式较为复杂建议参考官方文档。出于安全考虑不建议在公网直接暴露Dashboard。6. 存储方案与持久化卷实践免费层的200GB块存储我们可以将其一部分作为持久化卷使用。最直接的方式是使用hostPath但这将Pod绑定到了特定节点。更优雅的方式是使用NFS或OCIFSOCI文件存储但OCIFS不在免费套餐内。这里介绍一种折中且实用的方案使用一个节点上的本地目录并通过hostPath提供存储同时配合节点选择器。在某个工作节点上准备存储目录例如我们在worker-1节点上创建/mnt/k8s-data。创建StorageClass和PersistentVolumePV# local-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: local-pv-1 spec: capacity: storage: 50Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: local-storage local: path: /mnt/k8s-data nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - worker-1 # 替换为你的节点主机名kubectl apply -f local-pv.yaml在Pod中通过PersistentVolumeClaimPVC申请使用# test-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc spec: storageClassName: local-storage accessModes: - ReadWriteOnce resources: requests: storage: 10Gi当Pod使用此PVC时调度器会将其调度到worker-1节点上。实操心得对于免费环境hostPath 节点选择器是最简单有效的持久化方案。如果你需要数据在节点间迁移可以考虑部署一个轻量的NFS服务器Pod并将其hostPath到同一个目录其他Pod通过NFS客户端挂载这个NFS服务。这增加了复杂性但提供了更好的可迁移性。7. 运维、监控与成本控制技巧集群跑起来了稳定运行和成本控制是关键。7.1 基础监控与日志监控除了Metrics Server可以部署Prometheus和Grafana。但请注意它们本身会消耗不少资源。在免费层集群中我建议使用精简版的配置或直接使用OCI自带的监控功能基础指标免费通过kubectl top命令进行日常检查。日志同样EFK/ELK栈比较重。可以考虑使用轻量级的Loki和Promtail来收集日志或者简单地将关键应用的日志直接输出到标准输出然后使用kubectl logs查看。7.2 安全加固要点禁用Master节点调度默认Master节点有污点不会调度普通Pod。确保这一点。使用网络策略Calico已安装可以定义NetworkPolicy来限制Pod间的网络流量实现微服务间的安全隔离。定期更新定期使用kubeadm upgrade计划性地升级K8s版本小版本并更新系统包。免费层实例的安全更新至关重要。密钥管理避免在镜像或代码中硬编码敏感信息。对于免费项目可以将少量密钥作为K8s Secret管理。对于更复杂的需求可以考虑使用外部保管库但这超出了免费层的简易范畴。7.3 至关重要的成本控制与资源优化这是使用免费云服务的生命线。设置预算告警在OCI控制台“成本管理”中设置一个极低的预算如1美元并配置告警。这是防止意外收费的最后防线。彻底理解免费清单定期回顾OCI的“始终免费”资源列表确保你没有使用任何不在列表中的付费服务例如某些特定形状的VM、额外的存储性能、高级负载均衡器带宽等。资源清理习惯不用的实例一定要终止Terminate而不仅仅是停止Stop。终止会删除关联的引导卷除非设置了保留。删除不用的块存储卷、负载均衡器、VCN等所有资源。使用OCI资源管理器或CLI编写脚本定期清理测试资源。集群资源优化为Pod设置合理的资源请求requests和限制limits避免资源浪费。使用kubectl top nodes/pods监控资源使用情况及时调整。考虑使用Horizontal Pod Autoscaler (HPA)自动扩缩容应用但在免费层资源紧张的情况下手动管理可能更可控。7.4 常见问题与故障排查实录在部署和运维过程中你肯定会遇到各种问题。这里记录几个典型场景节点状态一直NotReady检查网络插件kubectl get pods -n calico-system查看Calico Pod是否全部Running。查看日志kubectl logs -n calico-system pod-name。检查防火墙安全列表确认VCN的安全列表和实例的网络安全组NSG规则是否允许Pod网络默认Calico使用IPIP或VXLAN端口8472/UDP或4789/UDP和节点间通信。检查kubelet服务在节点上执行sudo systemctl status kubelet和sudo journalctl -u kubelet -f查看日志。Pod一直处于Pending状态kubectl describe pod pod-name查看事件。最常见原因是资源不足CPU/Memory或没有满足节点选择器/污点容忍的节点。在免费层AMD节点1/8 OCPU很容易资源不足调度器不会将Pod调度上去除非该Pod的资源请求极低。kubectl命令执行超时或无法连接检查Master节点的安全列表是否允许你的客户端IP访问6443端口。检查Master节点的kube-apiserverPod是否正常kubectl get pods -n kube-system | grep apiserver。OCI负载均衡器健康检查失败确认后端工作节点的NodePort如30080是否确实有服务在监听。可以在工作节点上执行curl localhost:30080/healthz测试。确认安全列表规则允许负载均衡器IP段访问后端节点的NodePort端口。OCI负载均衡器的健康检查源IP是特定的需要放行。经过以上步骤你应该已经拥有了一个运行在OCI免费层上、功能相对完整的Kubernetes集群。这个环境足以支撑你进行大量的云原生技术实践。记住免费资源的精髓在于“按规则合理利用”时刻关注OCI的控制台和账单页面养成良好的资源管理习惯这个集群就能成为你长期、稳定的学习和实验基地。