1. 项目概述在免费云上构建高可用K8s集群最近在社区里看到不少朋友在讨论云原生和Kubernetes但一提到搭建环境很多人就被云厂商的计费模型劝退了。确实一个像样的生产级K8s集群光是控制节点和ETCD的稳定运行就需要不小的开销。不过如果你只是想学习、测试或者搭建一个轻量级的个人项目环境有没有可能“零成本”玩转K8s呢答案是肯定的。今天要聊的这个项目就是围绕“nce/oci-free-cloud-k8s”展开的。简单来说它是一套完整的方案指导你如何利用主流云服务商提供的“永久免费套餐”资源搭建一个功能完备的Kubernetes集群。这里的“免费”不是指试用期而是指那些云厂商明确承诺长期免费提供的计算、存储和网络资源。通过巧妙的资源编排和配置我们可以在不花一分钱的情况下获得一个接近生产环境的K8s playground用于CI/CD流水线测试、微服务架构验证、技术学习甚至是运行一些对资源要求不高的个人应用。这个项目的核心价值在于“降本”与“学习”并重。对于初学者它消除了资金门槛让你可以毫无压力地反复搭建、摧毁、再搭建深刻理解K8s的每一个组件。对于有经验的开发者它提供了一个绝佳的沙箱环境可以安全地尝试Helm Chart、Operator、服务网格如Istio/Linkerd等进阶功能而不用担心操作失误导致账单爆炸。接下来我将从架构设计、实操步骤到避坑指南完整拆解如何实现这一目标。2. 核心架构设计与资源选型2.1 免费云资源池分析要实现“零成本”第一步是摸清我们手上有哪些牌。目前Oracle Cloud Infrastructure (OCI) 的“永久免费套餐”是资源最慷慨的之一常被用作此类项目的基石。其免费资源通常包括计算实例 (VM.Standard.E2.1.Micro 或 Ampere A1)提供1个OCPU或4个Arm核心和1GB/6GB内存的虚拟机。虽然性能有限但运行K8s的控制平面组件如kube-apiserver, kube-controller-manager, kube-scheduler以及1-2个轻量级工作节点是足够的。块存储 (Block Volume)提供总计200GB的免费块存储可用于持久化卷PV保障有状态应用的数据安全。负载均衡器 (Load Balancer)提供1个免费的LB实例带宽10Mbps。这对于暴露K8s集群的Ingress Controller服务如Nginx Ingress至关重要是外部访问集群内服务的门户。VCN与公网IP虚拟云网络和有限的公网IP资源满足网络隔离和外部访问需求。除了OCI其他如Google Cloud Platform (GCP) 的Always Free Tier、AWS的Free Tier部分资源永久免费也可以作为补充或备选。但OCI因其提供的Ampere A1实例4核ARM24GB内存性价比突出常被选为主力。注意免费套餐通常有严格的区域Region限制并非所有数据中心都提供。在创建资源前务必在云控制台确认所选区域是否支持免费套餐并仔细阅读其条款避免因误操作如创建了付费实例规格、超出免费额度而产生意外费用。2.2 Kubernetes发行版与部署工具抉择有了资源下一步是选择如何部署K8s。在资源受限的免费实例上我们需要一个轻量级、高集成度的方案。K3s vs KubeadmK3s由Rancher现为SUSE推出的轻量级Kubernetes发行版将核心组件打包为单个二进制文件默认使用containerd而非Docker内存占用极低控制平面约512MB内存即可运行。它内置了SQLite作为默认存储替代etcd进一步简化了部署。对于免费实例1GB内存的苛刻环境K3s几乎是唯一可行的选择。KubeadmK8s官方的集群引导工具更标准但部署的组件更多资源消耗更大在1GB内存的实例上运行会非常吃力不推荐在此场景使用。因此本项目通常选用K3s作为Kubernetes发行版。它牺牲了一些高级特性如默认的Alpha API但换来了极致的轻量和易用性完美契合免费资源的约束。部署工具虽然可以手动通过SSH在每台机器上安装K3s但为了可重复性和自动化推荐使用Terraform进行云资源虚拟机、网络、安全组的编排再配合Ansible进行集群内K3s的安装与配置。这套组合能实现“基础设施即代码”一键创建和销毁整个环境。2.3 高可用与网络拓扑设计免费实例通常性能不强单点故障风险高。我们的设计目标是在“免费”的前提下尽可能提升可用性。控制平面高可用HA标准的K3s HA需要2个或3个Server节点控制节点和一个外置数据库如MySQL/PostgreSQL。但在免费套餐中运行多个1GB内存的Server节点外加一个数据库实例资源可能捉襟见肘。一个折中的实践是部署两个K3s Server节点形成主备。使用K3s内置的嵌入式etcd而非单机SQLite。K3s支持以etcd模式运行多个Server节点间会自动组成etcd集群实现控制平面和数据存储的双重高可用。这比外置数据库方案更节省资源。虽然两个节点在etcd集群中无法容忍一个节点同时故障需要至少3节点才能满足etcd的多数派选举但这已经比单点大幅提升且能在主节点维护时进行手动切换。工作节点与负载均衡可以创建1-2个额外的免费实例作为Agent节点工作节点专门运行业务Pod。利用OCI的免费负载均衡器将流量引导至运行着Nginx Ingress Controller的Agent节点上。Ingress Controller本身以DaemonSet或Deployment形式运行在K8s集群内。网络规划在OCI VCN中创建一个公有子网用于放置所有实例和负载均衡器简化配置。安全列表Security List必须精细配置开放6443端口K3s API Server、80/443端口Ingress、22端口SSH管理以及K3s节点间通信所需的端口如2379-2380 for etcd, 8472 for Flannel VXLAN等。3. 实战部署从零搭建免费K3s集群3.1 基础设施自动化部署Terraform我们首先使用Terraform定义所有云资源。以下是一个简化的main.tf示例用于在OCI创建必要的资源。# 配置OCI Provider provider oci { tenancy_ocid var.tenancy_ocid user_ocid var.user_ocid fingerprint var.fingerprint private_key_path var.private_key_path region var.region } # 创建VCN和子网 resource oci_core_vcn free_k8s_vcn { compartment_id var.compartment_id cidr_block 10.0.0.0/16 display_name free-k8s-vcn } resource oci_core_subnet public_subnet { compartment_id var.compartment_id vcn_id oci_core_vcn.free_k8s_vcn.id cidr_block 10.0.1.0/24 display_name public-subnet prohibit_public_ip_on_vnic false route_table_id oci_core_route_table.public_route_table.id security_list_ids [oci_core_security_list.public_security_list.id] } # 创建互联网网关和路由表 resource oci_core_internet_gateway igw { compartment_id var.compartment_id vcn_id oci_core_vcn.free_k8s_vcn.id display_name free-k8s-igw } resource oci_core_route_table public_route_table { compartment_id var.compartment_id vcn_id oci_core_vcn.free_k8s_vcn.id route_rules { destination 0.0.0.0/0 destination_type CIDR_BLOCK network_entity_id oci_core_internet_gateway.igw.id } } # 配置安全列表开放必要端口 resource oci_core_security_list public_security_list { compartment_id var.compartment_id vcn_id oci_core_vcn.free_k8s_vcn.id display_name public-security-list # 允许SSH ingress_security_rules { protocol 6 # TCP source 0.0.0.0/0 tcp_options { min 22 max 22 } } # 允许K3s API Server ingress_security_rules { protocol 6 source 0.0.0.0/0 tcp_options { min 6443 max 6443 } } # 允许Flannel VXLAN (Overlay网络) ingress_security_rules { protocol 17 # UDP source 10.0.0.0/16 udp_options { min 8472 max 8472 } } # 允许所有出站 egress_security_rules { protocol all destination 0.0.0.0/0 } } # 创建免费实例两个Server节点 resource oci_core_instance k3s_server { count 2 compartment_id var.compartment_id availability_domain data.oci_identity_availability_domains.ads.availability_domains[0].name shape VM.Standard.E2.1.Micro # 免费规格 create_vnic_details { subnet_id oci_core_subnet.public_subnet.id assign_public_ip true } source_details { source_type image source_id data.oci_core_images.linux_images.images[0].id # 选择一个Linux镜像如Ubuntu } metadata { ssh_authorized_keys file(var.ssh_public_key_path) } display_name k3s-server-${count.index} } # 创建一个负载均衡器 resource oci_load_balancer public_lb { compartment_id var.compartment_id display_name k3s-ingress-lb shape flexible shape_details { minimum_bandwidth_in_mbps 10 maximum_bandwidth_in_mbps 10 # 免费额度内 } subnet_ids [oci_core_subnet.public_subnet.id] }执行terraform apply后基础设施就准备就绪了。你需要将生成的实例公网IP记录到Ansible的inventory文件中。3.2 K3s集群自动化安装与配置Ansible接下来使用Ansible在所有节点上安装和配置K3s。我们编写一个playbooksetup-k3s-ha.yml。准备Ansible Inventory[k3s_servers] server0 ansible_hostserver0_public_ip server1 ansible_hostserver1_public_ip [k3s_agents] # 如果有免费Agent节点可以加在这里 # agent0 ansible_hostagent0_public_ip [k3s_cluster:children] k3s_servers k3s_agents编写主Playbook--- - name: 部署高可用K3s集群 hosts: k3s_cluster become: yes vars: k3s_version: v1.28.8k3s1 # 指定一个稳定版本 k3s_token: my-super-secret-token # 用于节点加入的token tasks: - name: 安装基础依赖 apt: name: - curl - gnupg - software-properties-common state: present when: ansible_os_family Debian - name: 下载并安装K3s block: - name: 在第一个Server节点上安装并启用etcd和TLS SAN shell: | curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION{{ k3s_version }} \ sh -s - server \ --cluster-init \ --token {{ k3s_token }} \ --tls-san LOAD_BALANCER_IP \ --node-taint CriticalAddonsOnlytrue:NoExecute \ --disable traefik # 我们将使用Nginx Ingress args: creates: /usr/local/bin/k3s when: inventory_hostname server0 - name: 从第一个Server节点获取join命令 shell: cat /var/lib/rancher/k3s/server/node-token register: k3s_node_token delegate_to: server0 run_once: yes - name: 在第二个Server节点上加入集群 shell: | curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION{{ k3s_version }} \ sh -s - server \ --server https://server0_private_ip:6443 \ --token {{ k3s_node_token.stdout }} \ --node-taint CriticalAddonsOnlytrue:NoExecute when: inventory_hostname server1 - name: 在Agent节点上加入集群 (如果有) shell: | curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION{{ k3s_version }} \ sh -s - agent \ --server https://server0_private_ip:6443 \ --token {{ k3s_node_token.stdout }} when: k3s_agents in group_names rescue: - name: 安装失败清理 debug: msg: K3s安装失败请检查日志。关键参数解释--cluster-init在第一个Server节点上初始化一个使用嵌入式etcd的集群。--tls-san LOAD_BALANCER_IP将负载均衡器的IP地址添加到API Server的TLS证书中这是后续通过LB访问集群的关键。--node-taint给Server节点打上污点防止普通Pod调度到控制平面提升稳定性。--disable traefikK3s默认安装Traefik作为Ingress Controller我们选择更通用的Nginx Ingress。配置kubectl 在本地机器上从server0节点获取kubeconfig文件。scp ubuntuserver0_ip:/etc/rancher/k3s/k3s.yaml ~/.kube/config sed -i s/127.0.0.1/LOAD_BALANCER_IP/g ~/.kube/config现在运行kubectl get nodes应该能看到两个Ready的Server节点。3.3 部署Ingress Controller与示例应用安装Nginx Ingress Controller 我们使用Helm来安装首先添加仓库并安装。# 在本地或某个集群节点上操作 kubectl create namespace ingress-nginx helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx \ --set controller.service.typeLoadBalancer \ --set controller.service.externalTrafficPolicyLocal安装后查看Service会分配一个CLUSTER-IP。我们需要将OCI的负载均衡器后端指向这个Service所在的节点端口NodePort。配置OCI负载均衡器后端集 在OCI控制台为你之前创建的LB添加后端集Backend Set和监听器Listener。后端集协议选择TCP健康检查路径为/healthzNginx Ingress的默认健康检查端点。后端Backend添加你的两个K3s Server节点的私有IP和端口NodePort通过kubectl get svc -n ingress-nginx查看通常是30000的随机端口。监听器协议TCP端口80和443关联到上面的后端集。这样访问LB的公网IP的80/443端口流量就会被转发到集群内的Nginx Ingress Controller。部署一个测试应用# test-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello-world spec: replicas: 2 selector: matchLabels: app: hello-world template: metadata: labels: app: hello-world spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: hello-world-svc spec: selector: app: hello-world ports: - port: 80 targetPort: 80 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hello-world-ingress spec: ingressClassName: nginx rules: - host: test.your-free-k8s.com # 需要将域名解析到LB的IP或本地hosts绑定 http: paths: - path: / pathType: Prefix backend: service: name: hello-world-svc port: number: 80应用这个配置后通过配置的域名访问就能看到Nginx的欢迎页面。至此一个基于免费云资源的、具备基本高可用能力和外部访问能力的Kubernetes集群就搭建完成了。4. 运维精要、常见问题与成本控制4.1 稳定性优化与监控免费实例资源紧张稳定性需要额外关注。资源限制与调度务必为所有Pod设置合理的resources.requests和resources.limits防止单个Pod耗尽节点资源导致系统崩溃。使用kube-system命名空间下的resourcequota和limitrange来实施命名空间级别的默认限制。# limitrange.yaml apiVersion: v1 kind: LimitRange metadata: name: default-limits namespace: default spec: limits: - default: cpu: 100m memory: 128Mi defaultRequest: cpu: 50m memory: 64Mi type: Container轻量级监控 部署完整的PrometheusGrafana栈可能太重。可以考虑K3s内置指标K3s默认集成了metrics-server运行kubectl top nodes/pods可以查看基础资源使用情况。轻量级替代使用kube-state-metrics结合一个轻量的时序数据库如VictoriaMetrics的单节点版和Grafana。日志使用Fluent Bit替代Fluentd将日志输出到免费或低成本的云日志服务如OCI Logging避免在本地存储。4.2 典型问题排查实录在免费环境搭建过程中我踩过不少坑这里总结几个高频问题节点状态为NotReady现象kubectl get nodes显示NotReady。排查SSH到节点检查systemctl status k3s-agent或k3s服务是否运行。查看日志journalctl -u k3s-agent -f。常见原因防火墙未开放Flannel的VXLAN端口UDP 8472。确保OCI安全列表和实例内部的防火墙如ufw都放行了该端口。检查节点间网络是否互通特别是私有IP之间。Pod一直处于Pending状态现象Pod无法调度。排查kubectl describe pod pod-name查看事件。常见原因Insufficient cpu/memory。免费实例资源太小很容易被系统Pod如kube-system下的占满。需要清理不必要的Pod或调整requests。检查节点污点Taint和Pod容忍Toleration。我们的Server节点有污点普通Pod需要容忍才能调度上去。通过LB无法访问服务现象LB公网IP可以ping通但访问HTTP/HTTPS超时。排查确认LB的后端集健康检查状态是OK。登录到后端实例用curl从节点内部访问Service的ClusterIP和Port确认应用本身正常。检查Nginx Ingress Controller的Pod日志kubectl logs -n ingress-nginx ingress-controller-pod。关键检查点确保Ingress资源中指定的ingressClassName是nginx并且kubectl get ingressclass中确实存在名为nginx的IngressClass。这是K8s 1.18版本后的常见配置点。4.3 成本控制与资源清理“永久免费”不等于“无限免费”严格遵守额度是关键。成本控制清单资源类型OCI 免费额度超限风险点控制措施计算实例2个VM.Standard.E2.1.Micro 或 4个Ampere A1核心创建了付费规格或超出数量Terraform中明确定义shape定期检查实例列表块存储200GB创建额外卷或扩容超限仅使用系统盘如需持久化使用免费对象存储或精简配置负载均衡器1个10Mbps带宽创建多个或带宽升级Terraform中锁定LB配置出站数据每月10TB大量镜像拉取、数据下载使用容器镜像缓存如registry-mirrors避免从集群外频繁拉取大镜像一键清理 这是Terraform的最大优势。当你完成测试运行terraform destroy可以自动、干净地释放所有创建的资源确保不会留下任何“僵尸资源”导致意外计费。务必在非工作时段定期执行销毁和重建这既是成本控制也是练习基础设施即代码的好习惯。资源监控告警 在OCI控制台为你的租户Tenancy或区间Compartment设置预算和用量告警。当任何服务的用量接近免费额度阈值时你会收到邮件通知从而及时干预。5. 场景扩展与进阶玩法搭建好基础集群只是开始这个免费环境是绝佳的实验场。GitOps实践在集群中部署FluxCD或ArgoCD将你的应用声明YAML文件存放在Git仓库如GitHub。任何对Git仓库的提交都会自动同步到集群中。你可以在这个免费集群上完整地体验现代化的GitOps工作流。服务网格初探由于资源限制部署完整的Istio可能困难但可以尝试更轻量的Linkerd或服务网格接口SMI的参考实现如osm-edge。这能让你理解服务间通信、可观测性和安全策略等概念。Serverless体验安装Knative或OpenFaaS在K8s之上体验Serverless函数计算。你可以部署一个简单的HTTP函数感受事件驱动和自动缩放的魅力。混合云模拟如果你有多个云账号如OCI和GCP Always Free可以尝试用K3s的k3sup工具或集群连接工具如Submariner将不同云上的小型集群连接起来模拟混合云场景了解多集群应用分发。这个项目最吸引我的地方在于它用极致的成本控制打开了一扇通往云原生世界的大门。它迫使你去深入理解K8s的每一个组件、每一行配置因为资源有限任何浪费和低效都会立刻暴露出来。这种“带着镣铐跳舞”的经历往往比在资源充沛的生产环境中能带来更深刻的学习和成长。当你能够在这个免费的微型集群上流畅地部署和管理应用时面对任何规模的生产环境你都会更有底气。