一文读懂 K8s:Kubernetes 快速入门
引言:从集装箱到管弦乐团的蜕变
在云计算和微服务盛行的今天,容器技术,尤其是Docker,已经成为应用程序打包和部署的标准。它解决了“在我的机器上能运行”的问题,让开发和运维的界限变得模糊。然而,当容器的数量从几个增长到几十个、几百个甚至上千个时,管理这些容器的复杂性指数级上升:它们如何协同工作?如何自动扩缩容?一个容器挂掉后如何自动恢复?如何在不停机的情况下更新应用程序?
这些问题,单靠Docker本身是无法解决的。这就好比你有了无数个标准化生产的集装箱(容器),但你还需要一个强大的港口管理系统、一个调度中心、一个物流网络,来确保这些集装箱能够高效、可靠地运行和运输。
Kubernetes(简称K8s,因为K和s之间有8个字母)正是这个“港口管理系统”和“物流网络”——一个开源的容器编排平台。它源自Google内部的Borg系统,于2014年开源,如今已成为云原生时代的基石。它不仅仅是一个工具,更是一种管理现代复杂分布式系统的哲学。
本文将带领你深入浅出地理解K8s的核心概念、架构原理、常见组件及其工作方式,助你快速入门,从容应对容器时代的挑战。
第一部分:K8s的诞生背景与核心价值
1.1 容器化带来的挑战
Docker的出现极大地简化了应用程序的打包、分发和运行。每个容器都是一个独立的、轻量级的运行环境,包含了应用及其所有依赖。然而,在生产环境中,我们面临以下问题:
- 部署与调度: 如何将容器部署到合适的服务器上?如何确保每个服务器的资源得到充分利用?
- 服务发现与负载均衡: 容器的IP地址是动态变化的,应用程序之间如何找到对方?如何将请求均匀地分发到多个容器实例上?
- 健康检查与自愈: 容器出现故障怎么办?如何自动重启或替换故障容器?
- 扩缩容: 面对流量高峰和低谷,如何动态增加或减少容器实例?
- 配置管理: 如何统一管理容器的配置信息和敏感数据?
- 滚动更新与回滚: 如何在不中断服务的情况下更新应用程序?更新失败后如何快速回滚到旧版本?
手动处理这些问题,不仅效率低下,而且极易出错,成为运维团队的巨大负担。
1.2 Kubernetes的解决方案
K8s应运而生,旨在自动化和简化容器化应用程序的部署、扩展和管理。它的核心价值体现在:
- 自动化操作: K8s能够自动化容器的部署、扩缩容、更新和维护。
- 自愈能力: 当容器、节点甚至集群的一部分出现故障时,K8s能自动检测并尝试恢复服务,保证高可用性。
- 声明式配置: 你只需告诉K8s你想要达到的状态(例如,我需要运行3个Nginx容器),K8s就会尽力去实现并维持这个状态,而不是告诉它一步一步如何操作。
- 服务发现与负载均衡: K8s提供了内置的服务发现机制和负载均衡功能,让应用程序之间能够轻松通信。
- 资源管理: K8s能根据资源需求(CPU、内存)智能地调度容器到合适的节点。
- 可移植性: K8s可以在各种环境中运行,无论是本地开发机、私有数据中心还是公有云。
简单来说,K8s就像一个高明的管弦乐团指挥,你只需给出乐谱(应用程序的声明式配置),它就能协调所有乐手(容器和节点),自动演奏出美妙的乐章(高可用、可扩展的应用服务)。
第二部分:K8s的核心架构与组件
K8s集群由一组主节点(Master Node / Control Plane) 和工作节点(Worker Node) 组成。主节点负责管理和控制整个集群,工作节点则负责运行实际的应用程序容器。
2.1 主节点(Master Node / Control Plane)—— K8s的大脑
主节点是K8s集群的“大脑”,负责维护集群的期望状态。它包含以下核心组件:
-
kube-apiserver (API Server):
- 作用: 它是K8s集群的“前门”,所有外部请求(如
kubectl命令行工具、其他管理工具)和内部组件(如kubelet、scheduler)与K8s集群通信的唯一入口。 - 特点: 提供RESTful API接口,负责身份认证、授权、数据校验和审计。它是整个集群的数据中心枢纽,确保所有操作都经过它的校验。
- 作用: 它是K8s集群的“前门”,所有外部请求(如
-
etcd:
- 作用: K8s集群的“大脑记忆库”,是一个高可用、分布式、一致性的键值存储系统。
- 特点: 存储集群的所有配置数据、状态信息、元数据(如Pod、Service、Deployment等对象的定义和状态),以及集群的期望状态。它是集群的唯一真实来源。
-
kube-scheduler (Scheduler):
- 作用: K8s集群的“任务调度器”,负责监测新创建的、未指定运行节点(Node)的Pod。
- 特点: 根据预设的调度策略(如资源需求、亲和性/反亲和性、节点选择器、Taints和Tolerations等),为Pod选择一个最适合运行的工作节点,并将调度结果更新到API Server。
-
kube-controller-manager (Controller Manager):
- 作用: K8s集群的“自愈引擎”和“状态控制器”,包含多个控制器(如Deployment Controller、ReplicaSet Controller、Node Controller、Service Account Controller等)。
- 特点: 每个控制器都负责维护一种特定的资源类型,确保集群的当前状态与etcd中存储的期望状态一致。例如,ReplicaSet Controller会确保运行的Pod数量始终与期望的副本数一致;Node Controller会检测并处理节点故障。
2.2 工作节点(Worker Node)—— K8s的肌肉
工作节点是K8s集群的“肌肉”,是应用程序真正运行的地方。每个工作节点都包含以下核心组件:
-
kubelet:
- 作用: 运行在每个工作节点上的“节点代理”,它是K8s与容器运行时(如Docker)的桥梁。
- 特点: 接收API Server发送的指令,负责管理节点上的Pod生命周期(创建、启动、停止、删除容器),并向API Server报告节点和Pod的状态。
-
kube-proxy:
- 作用: K8s集群的“网络代理”,运行在每个工作节点上。
- 特点: 负责为Service提供网络代理和负载均衡功能。它会根据Service和Pod的变化,动态更新节点的网络规则(如iptables或ipvs),将对Service的请求转发到正确的Pod。
-
Container Runtime (容器运行时):
- 作用: 负责运行容器的软件,例如Docker、Containerd或CRI-O。
- 特点: kubelet通过CRI(Container Runtime Interface)与容器运行时交互,拉取镜像、运行容器、停止容器等。
第三部分:K8s的核心概念与资源对象
理解K8s的关键在于理解其核心概念和资源对象。K8s中的所有操作都围绕着这些对象进行,它们是K8s世界的“积木”。
-
Pod (豆荚/基本调度单元):
- 定义: K8s中最小的、可部署的计算单元。一个Pod可以包含一个或多个紧密耦合的容器,以及这些容器共享的存储、网络和运行时的配置。
- 特点:
- 原子性: Pod内的容器总是共同调度、共同停止,共享网络命名空间(即它们共享同一个IP地址和端口范围)。
- 共享资源: Pod内的容器可以共享存储卷(Volumes)和网络(IP地址)。
- 一次性: Pod是短暂的,被创建后,如果Pod内的容器挂掉,K8s不会在原地重启它们,而是创建一个全新的Pod来替代。
- 类比: 就像一个独立的小公寓,里面住着一户人家(紧密相关的容器),共享厨房、卫生间(共享网络和存储)。
-
Deployment (部署):
- 定义: K8s中最常用的一种工作负载控制器,用于管理Pod和ReplicaSet。它描述了你希望运行的应用程序的期望状态。
- 特点:
- 声明式更新: 允许你声明应用程序的期望状态(例如,运行多少个Nginx Pod),Deployment会负责创建和更新ReplicaSet,进而管理Pod。
- 滚动更新和回滚: 支持平滑地更新应用程序(逐个替换Pod),并在更新失败时能够快速回滚到旧版本。
- 自动伸缩: 可以与Horizontal Pod Autoscaler (HPA) 配合,根据CPU利用率或自定义指标自动扩缩容Pod数量。
- 类比: 应用程序的“发布经理”,负责版本管理、平滑升级和回滚。
-
Service (服务):
- 定义: 一种抽象,定义了一组Pod的逻辑集合以及访问它们的策略。它为Pod提供了一个稳定的、不变的入口IP地址和DNS名称。
- 特点:
- 服务发现: 即使Pod的IP地址因为重启或扩缩容而变化,Service的IP地址和DNS名称保持不变,方便其他应用程序发现和访问。
- 负载均衡: Service会根据请求自动将流量分发到其关联的Pod上。
- 服务类型:
- ClusterIP (默认): 只能在集群内部访问,为Service提供一个稳定的内部IP。
- NodePort: 在每个工作节点上暴露一个静态端口,可以通过
节点IP:NodePort从集群外部访问Service。 - LoadBalancer: 在支持的云提供商上,会自动创建一个外部负载均衡器,将流量转发到Service。
- ExternalName: 将Service映射到外部的DNS名称。
- 类比: 应用程序的“总机号码”或“公司前台”,无论内部员工(Pod)如何变动,外界(其他应用或用户)只需拨打这个固定号码就能找到服务。
-
Namespace (命名空间):
- 定义: K8s集群内部的逻辑隔离机制,用于将集群资源划分为不同的“虚拟集群”。
- 特点:
- 资源隔离: 不同的Namespace可以拥有相同的资源名称(例如,每个Namespace都可以有一个名为
nginx-deployment的Deployment)。 - 权限管理: 可以为不同的Namespace设置不同的访问权限,实现多租户环境。
- 默认Namespace: K8s集群启动时会有一个
default、kube-system、kube-public等命名空间。
- 资源隔离: 不同的Namespace可以拥有相同的资源名称(例如,每个Namespace都可以有一个名为
- 类比: 一个大型公司的不同“部门”,每个部门有自己的预算和人员,但都在同一个公司框架下。
-
ReplicaSet (副本集):
- 定义: 确保在任何给定时间运行指定数量的Pod副本。
- 特点: 通常由Deployment管理,用户很少直接操作ReplicaSet。当Deployment更新应用程序时,它会创建一个新的ReplicaSet来管理新版本的Pod,并逐渐淘汰旧的ReplicaSet。
- 类比: 负责“保镖数量”的管理员,确保始终有指定数量的保镖(Pod)在岗。
-
ConfigMap (配置映射) & Secret (秘密):
- 定义:
- ConfigMap: 用于存储非敏感的配置信息,如环境变量、命令行参数或配置文件。
- Secret: 专门用于存储敏感数据,如密码、API密钥、令牌等。
- 特点:
- 解耦配置: 将应用程序的配置与代码解耦,方便管理和更新。
- 挂载方式: 可以作为环境变量注入到Pod中,或作为文件挂载到容器的卷中。
- 安全性: Secret的数据经过Base64编码(但并非加密),在K8s集群内部进行管理和分发时会受到更好的保护。
- 类比: ConfigMap是应用的“操作手册”,Secret是应用的“保险箱密码”。
- 定义:
-
Volume (卷):
- 定义: Pod中容器可以访问的目录,提供数据持久化或共享能力。
- 特点: 解决容器重启后数据丢失的问题,也方便Pod内多个容器共享数据。K8s支持多种类型的卷,如emptyDir、hostPath、NFS、云提供商存储(AWS EBS、GCE Persistent Disk等)。
- 类比: 容器的“硬盘”或“共享文件夹”。
-
PersistentVolume (PV) & PersistentVolumeClaim (PVC):
- 定义:
- PV: 集群中由管理员预先配置或动态提供的持久化存储资源。
- PVC: 用户对存储资源的请求,声明了存储的大小、访问模式等。
- 特点:
- 存储抽象: PV/PVC将存储的物理实现与用户需求解耦,用户无需关心底层存储的具体细节。
- 动态供给: K8s可以根据PVC的请求,动态地从存储后端创建PV。
- 类比: PV是“公司的存储仓库”,PVC是“员工提交的存储申请单”。
- 定义:
-
Ingress (入口):
- 定义: K8s集群的“七层负载均衡器”,提供HTTP和HTTPS路由,将外部流量路由到集群内部的Service。
- 特点:
- 统一入口: 允许你使用一个IP地址和多个域名来提供多个Service。
- 高级路由规则: 可以根据请求的URL路径或主机名将流量路由到不同的Service。
- TLS/SSL终止: 可以配置Ingress来处理HTTPS流量。
- 类比: 城市入口的“交通枢纽”,根据车辆(请求)的目的地(URL/域名)将其引导到不同的区域(Service)。
第四部分:K8s的实际操作与快速入门
掌握了理论知识后,最好的学习方式就是动手实践。
4.1 kubectl命令行工具
kubectl是K8s的官方命令行工具,用于与K8s API Server进行交互。它是你管理K8s集群的主要方式。
常用命令示例:
- 查看集群状态:
bash
kubectl cluster-info
kubectl get nodes - 查看资源:
bash
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get all -n default # 查看default命名空间下的所有资源 - 创建/更新/删除资源:
bash
kubectl apply -f my-app.yaml # 创建或更新资源
kubectl delete -f my-app.yaml # 删除资源
kubectl create deployment nginx --image=nginx # 命令行创建Deployment - 日志与进入容器:
bash
kubectl logs <pod-name> -f # 查看Pod日志
kubectl exec -it <pod-name> -- bash # 进入Pod内的容器 - 扩缩容:
bash
kubectl scale deployment <deployment-name> --replicas=5 # 将副本数扩容到5
4.2 K8s的声明式配置 (YAML)
K8s资源通常通过YAML文件进行定义。这种声明式的方式使得配置版本化、可审计、易于共享。
示例:一个简单的Nginx Deployment
创建一个名为nginx-deployment.yaml的文件:
yaml
apiVersion: apps/v1 # API版本,指定Deployment资源属于apps/v1组
kind: Deployment # 资源类型,这里是Deployment
metadata:
name: nginx-deployment # Deployment的名称
labels:
app: nginx # 为Deployment打上标签
spec:
replicas: 3 # 期望的Pod副本数量
selector: # 选择器,用于关联Pod
matchLabels:
app: nginx # 选择所有带有app=nginx标签的Pod
template: # Pod模板,用于创建Pod
metadata:
labels:
app: nginx # Pod的标签,与Deployment的selector匹配
spec:
containers: # 容器列表
- name: nginx # 容器名称
image: nginx:latest # 使用的Docker镜像
ports:
- containerPort: 80 # 容器暴露的端口
resources: # 资源限制和请求
limits:
cpu: "500m" # 最大CPU使用量0.5核
memory: "256Mi" # 最大内存使用量256MB
requests:
cpu: "200m" # 启动时请求0.2核CPU
memory: "128Mi" # 启动时请求128MB内存
示例:为Nginx Deployment创建Service
创建一个名为nginx-service.yaml的文件:
yaml
apiVersion: v1 # API版本,指定Service资源属于v1组
kind: Service # 资源类型,这里是Service
metadata:
name: nginx-service # Service的名称
spec:
selector:
app: nginx # 选择所有带有app=nginx标签的Pod作为后端
ports:
- protocol: TCP
port: 80 # Service监听的端口
targetPort: 80 # 流量转发到Pod的哪个端口
nodePort: 30080 # 当使用NodePort类型时,节点上暴露的端口(范围30000-32767)
type: NodePort # Service的类型,这里选择NodePort,以便从集群外部访问
4.3 部署并访问你的第一个应用
前提: 你需要一个K8s集群。
* 本地学习: 推荐使用Minikube或Docker Desktop(内置Kubernetes)。
* 云端: 各大云厂商(AWS EKS, GCP GKE, Azure AKS)都提供托管K8s服务。
步骤:
- 保存YAML文件: 将上述
nginx-deployment.yaml和nginx-service.yaml文件保存到本地。 - 部署Deployment:
bash
kubectl apply -f nginx-deployment.yaml
K8s会根据YAML文件创建Deployment,Deployment会进一步创建ReplicaSet,ReplicaSet再创建3个Nginx Pod。 - 检查Pod状态:
bash
kubectl get pods -l app=nginx
# 应该看到3个Status为Running的Pod - 部署Service:
bash
kubectl apply -f nginx-service.yaml - 检查Service状态:
bash
kubectl get services nginx-service
# 应该看到Service的ClusterIP、外部IP(如果类型是LoadBalancer),以及NodePort(如果类型是NodePort) - 访问Nginx:
- 如果使用
Minikube,可以通过minikube service nginx-service命令直接在浏览器中打开。 - 如果使用
NodePort,找到集群中任意一个工作节点的IP地址,然后通过http://<节点IP>:<NodePort>访问(例如http://192.168.49.2:30080)。 - 如果使用
LoadBalancer,找到其分配的外部IP地址访问。
- 如果使用
4.4 体验K8s的自愈和扩缩容
-
模拟Pod故障:
bash
kubectl delete pod <其中一个nginx-deployment的pod名称>
你会发现K8s很快会自动创建一个新的Pod来替换被删除的Pod,维持3个副本的期望状态。 -
扩缩容:
bash
kubectl scale deployment nginx-deployment --replicas=5
# 再次查看Pod,会发现变成了5个
kubectl get pods -l app=nginx
将副本数改回3:
bash
kubectl scale deployment nginx-deployment --replicas=3
# 再次查看Pod,会发现自动缩减到了3个
kubectl get pods -l app=nginx
第五部分:K8s的优势、挑战与未来展望
5.1 K8s的显著优势
- 提高开发效率: 开发者可以专注于业务逻辑,无需关心底层基础设施。
- 提升运维效率: 自动化部署、扩缩容、自愈等功能,大大减轻运维负担。
- 高可用性: 自动故障转移和自我修复能力,确保服务持续在线。
- 可伸缩性: 应对流量波动,动态调整资源。
- 环境一致性: 容器化和K8s确保了开发、测试、生产环境的一致性。
- 云厂商锁定解除: K8s作为开源标准,可以在任何支持的云平台或本地数据中心运行,避免特定云厂商的绑定。
5.2 学习K8s面临的挑战
- 学习曲线陡峭: 概念众多,组件复杂,初学者往往感到不知所措。
- 资源消耗: K8s本身也需要一定的计算资源才能运行。
- 网络和存储的复杂性: K8s的网络模型和存储选项相对复杂。
- 安全性: K8s集群的安全性配置需要专业知识和严格实践。
5.3 未来展望
K8s已经成为云原生生态的核心,未来将继续深化发展:
- Operator模式: 允许扩展K8s的能力,管理复杂有状态应用。
- Serverless与K8s集成: 将K8s作为Serverless函数运行的底层平台。
- 边缘计算: K8s正在向边缘设备和物联网领域拓展,管理分布式微型集群。
- 更智能的调度和资源管理: 利用AI/ML技术优化资源调度和成本。
结语
“一文读懂 K8s” 并非意味着你可以读完这3000字就成为K8s专家。相反,这只是一个起点,为你描绘了K8s的宏伟蓝图和核心脉络。K8s是一个庞大且仍在快速发展的生态系统,深入学习需要持续的实践和探索。
从集装箱(容器)到港口(Docker)再到整个智能物流网络(Kubernetes),我们见证了软件交付方式的巨大变革。K8s以其强大的自动化、自愈和调度能力,正在重新定义现代应用程序的部署和管理方式。
勇敢地迈出第一步,在Minikube或Docker Desktop上搭建你的第一个K8s集群,部署一个简单的应用,感受K8s的魔力。你将发现,掌握K8s不仅仅是掌握一项技术,更是获得了驾驭未来云原生世界的强大能力。祝你在K8s的学习旅程中一帆风顺!