Kubernetes(K8s)到底是什么?一篇文章带你入门
如果平时接触过 Docker,继续往后学习时,大概率会碰到 Kubernetes。
很多人第一次看到 Kubernetes 时,会觉得它非常复杂:Pod、Deployment、Service、Ingress、Node、Namespace……各种概念扑面而来。但如果先不纠结这些名词,Kubernetes 本身其实解决的是一个很实际的问题:
当服务器和容器越来越多以后,应该怎么统一管理它们?
Kubernetes 就是为了解决这件事而出现的。
从 Docker 说起
假设现在有一个后端服务,我们把它打包成 Docker 镜像,然后运行:
docker run -d -p 8080:8080 my-app
只有一台服务器、几个容器的时候,这种方式非常简单。
但业务规模扩大之后,情况就不一样了。
例如同一个服务可能需要运行 10 个实例,用来分担请求压力。这些实例可能分布在不同服务器上。如果其中一台服务器宕机了,还需要把服务迁移到其他机器。
版本更新的时候,我们可能又希望逐步替换旧容器,而不是直接把所有服务停掉。
这时候单独使用 Docker 就会变得有些麻烦。
我们需要考虑:
哪个容器运行在哪台服务器?
容器挂掉以后谁负责重新启动?
流量应该怎么分配到不同实例?
服务升级的时候如何避免停机?
服务器资源应该怎么合理分配?
如果所有事情都依靠人工完成,服务器数量一多,维护成本很快就会上升。
Kubernetes 的作用,就是帮助我们自动完成这些工作。
Kubernetes 是什么
Kubernetes,简称 K8s,是一个开源的容器编排系统。
这里的“编排”,可以简单理解为:
统一管理大量容器,并自动决定这些容器应该如何运行。
例如我们告诉 Kubernetes:
我的 Web 服务需要一直保持三个实例运行。
Kubernetes 就会尽量维持这个状态。
假设现在有三个容器:
Web
├── 容器 1
├── 容器 2
└── 容器 3
如果容器 2 突然崩溃,Kubernetes 会发现当前只剩两个实例,然后自动创建一个新的实例。
整个过程通常不需要管理员手动执行 docker run。
这种机制也是 Kubernetes 一个非常重要的思想:
我们描述自己想要的状态,Kubernetes 负责让实际状态尽可能接近它。
这种方式被称为声明式管理。
Kubernetes 集群
Kubernetes 一般不会只运行在一台服务器上,而是由多台机器共同组成一个集群。
一个简单的 Kubernetes 集群可以理解成:
Kubernetes Cluster
│
├── Control Plane
│
├── Worker Node 1
│ ├── Pod
│ └── Pod
│
└── Worker Node 2
├── Pod
└── Pod
其中服务器通常被称为 Node,也就是节点。
节点大致分为两类。
一类是 Control Plane,也就是控制平面,负责管理整个集群,比如决定某个应用应该运行在哪台机器上、当前运行状态是否符合要求等。
另一类是 Worker Node,真正负责运行应用。
可以把 Control Plane 理解成 Kubernetes 的“大脑”,Worker Node 则是真正干活的机器。
Pod:Kubernetes 中最基本的运行单位
刚开始学习 Kubernetes 时,一个比较容易产生误解的地方是:
Kubernetes 并不是直接以 Docker 容器作为最小管理单位。
它管理的是 Pod。
Pod 可以理解成一个用来运行容器的“小环境”。
例如:
Pod
└── Container
└── nginx
大多数情况下,一个 Pod 中只运行一个主要容器。
比如运行 nginx:
Pod
└── nginx
运行一个 Java 后端:
Pod
└── Java Application
当然,一个 Pod 也可以包含多个容器。
Pod
├── Application
└── Sidecar
同一个 Pod 中的容器可以共享网络以及部分存储资源,因此一些关系非常紧密的容器可以放在同一个 Pod 中运行。
不过对于刚开始接触 Kubernetes 的人来说,可以先简单记住:
Pod 是 Kubernetes 中运行应用的基本单位。
Deployment:管理多个 Pod
虽然 Pod 是基本单位,但实际使用 Kubernetes 时,很少直接手动创建 Pod。
原因也很简单。
如果 Pod 挂掉了,我们通常希望 Kubernetes 自动创建一个新的 Pod,而不是人工重新启动。
因此一般会使用 Deployment。
假设有一个 nginx 服务,我们希望同时运行三个实例:
Deployment
│
├── Pod nginx-1
├── Pod nginx-2
└── Pod nginx-3
我们只需要在配置中告诉 Kubernetes:
replicas: 3
Kubernetes 就会尽量保证始终有三个 Pod 存在。
如果某个 Pod 崩溃:
原来:
Pod 1
Pod 2
Pod 3
Pod 2 崩溃
Kubernetes 会自动创建新的 Pod:
Pod 1
Pod 3
Pod 4
这就是 Kubernetes 经常提到的自愈能力。
Deployment 还负责应用更新。
比如从:
my-app:v1
升级到:
my-app:v2
Kubernetes 可以逐步创建新版本 Pod,再逐步删除旧版本 Pod,而不是一次性停止所有服务。
这种方式通常叫做:
滚动更新(Rolling Update)。
Service:给 Pod 一个稳定的访问入口
Pod 还有一个特点:
它并不是永久存在的。
Pod 被重新创建以后,IP 地址可能会发生变化。
例如原来的 Pod:
10.244.1.10
重新创建以后可能变成:
10.244.2.15
如果其他服务直接访问 Pod IP,就会产生问题。
因此 Kubernetes 提供了 Service。
可以理解成:
客户端
│
▼
Service
│
├── Pod 1
├── Pod 2
└── Pod 3
客户端不需要关心后面具体有多少个 Pod,也不需要关心 Pod 的 IP 地址。
只需要访问 Service。
Service 会把请求转发到对应的 Pod。
所以 Service 解决的核心问题,就是:
给一组不断变化的 Pod 提供一个相对稳定的访问入口。
Ingress:管理外部 HTTP 访问
如果 Kubernetes 集群中有很多 Web 服务:
user-service
order-service
admin-service
我们可能希望通过不同域名访问:
user.example.com
order.example.com
admin.example.com
这时候通常会使用 Ingress。
大致结构可以理解为:
Internet
│
▼
Ingress
│
├── user.example.com → user-service
├── order.example.com → order-service
└── admin.example.com → admin-service
Ingress 主要负责 HTTP 和 HTTPS 请求的路由。
它和传统的 nginx 反向代理有点类似。
事实上很多 Kubernetes 集群里的 Ingress Controller,本身就是基于 nginx、Traefik 或其他代理软件实现的。
Kubernetes 为什么使用 YAML
使用 Kubernetes 时,会经常看到 YAML 文件。
例如一个简单的 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
这个文件实际上就是在告诉 Kubernetes:
我要创建一个叫做 nginx 的 Deployment。
使用 nginx 镜像。
同时运行三个实例。
容器监听 80 端口。
写完配置之后执行:
kubectl apply -f nginx.yaml
Kubernetes 就会根据这个 YAML 文件创建对应的资源。
这也是 Kubernetes 和直接使用 Docker 一个比较明显的区别。
Docker 中经常是在告诉系统:
帮我启动这个容器。
而 Kubernetes 中更常见的是:
我希望系统最终处于这个状态。
至于中间具体怎么创建、调度和恢复,交给 Kubernetes 自己处理。
kubectl
管理 Kubernetes 集群时,最常见的命令行工具叫:
kubectl
例如查看 Pod:
kubectl get pods
查看 Deployment:
kubectl get deployments
查看 Service:
kubectl get services
如果想查看更多信息,可以使用:
kubectl describe pod <pod-name>
查看容器日志:
kubectl logs <pod-name>
进入容器:
kubectl exec -it <pod-name> -- /bin/sh
可以把 kubectl 理解成我们和 Kubernetes 集群交互的主要工具。
Kubernetes 的核心优势
Kubernetes 真正有价值的地方,并不是因为它可以“运行 Docker”。
Docker 自己就能运行容器。
Kubernetes 更重要的能力,是管理大量容器。
比如服务出现故障以后自动恢复,多台服务器之间自动进行资源调度,根据需求增加或减少实例,在应用升级时执行滚动更新,以及为大量服务提供统一的网络和服务发现机制。
当系统只有两三个服务时,这些能力可能感觉不到有多重要。
但当系统变成:
几十台服务器
几百个服务
上千个容器
以后,人工维护就会变得非常困难。
这个时候 Kubernetes 的价值才真正体现出来。
Docker 和 Kubernetes 是什么关系
很多刚接触 K8s 的人都会问:
用了 Kubernetes,是不是就不用 Docker 了?
严格来说,并不是这种简单的替代关系。
Docker 主要解决的是:
如何把应用打包成容器镜像并运行容器。
Kubernetes 主要解决的是:
如何在多台服务器上统一管理这些容器。
可以简单理解成:
Docker
负责把应用装进容器
Kubernetes
负责管理大量容器
目前 Kubernetes 底层通常使用 containerd、CRI-O 等容器运行时,并不一定直接使用 Docker Engine。
但是我们依然可以使用 Docker 构建镜像:
docker build -t my-app:v1 .
然后把镜像交给 Kubernetes 部署。
所以学习路径一般仍然是:
Linux
↓
Docker
↓
Kubernetes
先理解容器,再学习 Kubernetes,会轻松很多。
Kubernetes 适合所有项目吗?
并不是。
如果只是一个个人博客、一两个后端服务,甚至只有一台服务器,那么直接使用 Docker Compose 往往已经足够。
比如:
nginx
mysql
redis
backend
这种规模使用:
docker compose up -d
就能管理得很好。
如果为了几个容器专门搭建 Kubernetes,反而会增加部署和维护成本。
Kubernetes 更适合服务数量比较多、需要横向扩容、要求高可用、需要持续发布,并且拥有多台服务器的环境。
因此 Kubernetes 并不是 Docker Compose 的“高级替代品”。
它们解决的是不同规模的问题。
总结
如果只用一句话解释 Kubernetes,可以把它理解为:
Kubernetes 是一个帮助我们在多台服务器上自动部署、管理、扩容和恢复容器化应用的平台。
刚开始学习 K8s 时,各种概念确实会比较多,但真正需要先搞清楚的核心关系其实只有几层:
Cluster
│
├── Node
│ │
│ └── Pod
│ │
│ └── Container
│
├── Deployment
│ └── 管理 Pod
│
├── Service
│ └── 提供稳定访问入口
│
└── Ingress
└── 管理 HTTP/HTTPS 外部访问
把 Node、Pod、Deployment 和 Service 这几个概念理解以后,再继续学习 ConfigMap、Secret、Volume、StatefulSet、DaemonSet、HPA 等内容,就会顺畅很多。
Kubernetes 看起来很庞大,但归根结底,它一直在做同一件事情:
让一大堆容器按照我们期望的方式稳定运行。
- 点赞
- 收藏
- 关注作者
评论(0)