Kubernetes和云原生:从Docker到K8s的知识三明治


Kubernetes和云原生:从Docker到K8s的知识三明治

Kubernetes和云原生从Docker到K8s封面图

我最近在云服务大厂实习,需要补一下 Kubernetes 和云原生的知识。

但问题是,我并不是一开始就懂 K8s。我之前主要用过 Docker,知道可以把一个应用打包成镜像,然后用容器跑起来。比如本地起一个 MySQL、Redis、Nginx,或者把自己的后端服务打成镜像,这些都还比较直观。

可是当容器数量变多之后,问题就来了。

一个容器挂了怎么办?多个容器之间怎么互相访问?服务升级时怎么不停机?数据库这种有数据的服务怎么处理?应用配置变了是不是还要重新打镜像?容器要跑在哪台机器上?机器挂了以后谁来把服务重新拉起来?

如果只有两三个容器,我们还可以用 Shell 脚本、Docker Compose 或者手动命令勉强管理。但如果是一整个项目、多个服务、多台机器、多个环境,这件事就会迅速失控。

Kubernetes 要解决的,就是“容器多了以后怎么管理”的问题。

它不是 Docker 的替代品,而是站在 Docker 这类容器技术之上,帮我们做容器编排、调度、服务发现、扩缩容、配置管理、存储管理和故障恢复。

这篇文章就按“知识三明治”的方式来补:先用 Docker 的直觉理解 K8s,再逐个解释核心组件,最后看一下它在云原生里的位置。

一、从 Docker 到 Kubernetes:为什么需要 K8s

Docker 解决的是“怎么把应用和运行环境打包起来”。

比如一个 Java 应用原来需要 JDK、配置文件、启动脚本、依赖包。不同机器环境不一样,很容易出现“我本地能跑,你服务器跑不了”的问题。Docker 把这些东西打进镜像里,容器启动后环境基本一致,这就方便很多。

但 Docker 更偏向管理单个容器,或者少量容器。

假设现在有一个简单系统:

  • 一个前端服务
  • 一个后端 API 服务
  • 一个 MySQL 数据库
  • 一个 Redis 缓存
  • 一个 Nginx 网关

用 Docker 跑起来不难。但继续往下想:

  • 后端 API 要不要多跑几个副本?
  • 某个副本挂了,谁负责重新启动?
  • Redis 的地址变了,后端配置怎么更新?
  • MySQL 数据不能丢,容器重启后数据放哪里?
  • Nginx 怎么把外部请求转发到正确服务?
  • 服务升级时怎么做到用户无感?
  • 这些容器到底应该跑在哪台机器上?

这些问题单靠手写脚本也能做一部分,但很快会变得复杂。

于是 Kubernetes 出场了。

可以先把它理解成:Kubernetes 是一个容器管理平台,它负责在一组机器上管理一堆容器,让它们按照我们声明的方式运行。

二、Kubernetes 的基本直觉:我想要什么状态

Kubernetes 里很重要的一个思想叫“声明式”。

你不是一步一步告诉它:先创建这个容器,再启动那个容器,再检查一下,再挂了重启。

你更多是在告诉它:

我希望这个应用一直有 3 个副本,使用 nginx:1.25 这个镜像,对外暴露 80 端口。

然后 Kubernetes 会不断检查当前状态和你想要的状态是否一致。如果少了一个副本,它就补一个;如果某个 Pod 挂了,它就重新创建;如果你把副本数从 3 改成 5,它就再扩两个。

这个过程可以理解为:

flowchart LR
    A[你写配置
期望状态] --> B[Kubernetes 接收配置] B --> C[检查当前状态] C --> D{是否一致} D -->|一致| E[保持运行] D -->|不一致| F[创建 / 删除 / 更新资源] F --> C

这就是 K8s 的核心直觉:你描述目标状态,它负责尽量把现实状态调整过去。

三、Node:K8s 里的机器

Node 是 Kubernetes 里的节点,可以是一台物理机,也可以是一台虚拟机。

如果你之前用 Docker,大概率是在自己电脑或者一台服务器上跑容器。而 Kubernetes 通常管理的是多台机器。每台机器就是一个 Node。

这些 Node 合在一起,就是一个 Kubernetes 集群。

可以先这样理解:

  • Node:一台能跑容器的机器。
  • Cluster:很多 Node 组成的集群。
  • Kubernetes:负责管理整个集群。

在云厂环境里,Node 很可能就是云服务器 ECS、CVM、EC2 这类虚拟机。你不一定直接登录每台机器,但你的应用最终还是会被调度到某些 Node 上运行。

四、Pod:K8s 不是直接管理容器

学 Kubernetes 第一个容易卡住的概念就是 Pod。

我们直觉上会以为:Docker 里跑的是容器,那 K8s 应该也是直接管理容器。

但实际上,Kubernetes 最小的调度单位不是容器,而是 Pod

Pod 可以理解为“容器外面的一层壳”,它给容器提供一个运行环境。一个 Pod 里可以有一个容器,也可以有多个容器。它们可以共享网络、存储和一些运行时配置。

大部分情况下,一个 Pod 里只跑一个主业务容器。比如:

  • 一个后端服务 Pod,里面跑一个 Java 容器。
  • 一个 Nginx Pod,里面跑一个 Nginx 容器。
  • 一个 Redis Pod,里面跑一个 Redis 容器。

那什么时候一个 Pod 里会有多个容器?

通常是这些容器关系非常紧密,必须一起工作。比如主业务容器旁边加一个日志采集容器,或者加一个代理容器。这种模式常叫 sidecar。

先不要被这些高级用法绕进去。入门时记住一句话就够了:

Pod 是 Kubernetes 管理应用实例的最小单位,容器通常运行在 Pod 里面。

五、Pod IP:为什么直接访问 Pod 不靠谱

每个 Pod 创建后,Kubernetes 会给它分配一个集群内部 IP。Pod 之间可以通过这个 IP 通信。

比如后端应用要访问数据库,理论上可以直接访问数据库 Pod 的 IP。

但这会有一个问题:Pod 不是稳定的。

Pod 很容易被创建、销毁和重建:

  • 容器崩了,Pod 可能被重建。
  • Node 挂了,Pod 可能被调度到别的 Node。
  • 应用升级了,旧 Pod 会被新 Pod 替换。
  • 手动扩缩容时,Pod 数量会变化。

Pod 一重建,IP 可能就变了。

如果应用程序写死数据库 Pod 的 IP,那数据库 Pod 一换,应用就找不到数据库了。

所以不能让应用直接依赖 Pod IP。

这就引出了 Service。

六、Service:给一组 Pod 一个稳定入口

Service 是 Kubernetes 里非常重要的对象。

它解决的问题是:Pod IP 不稳定,但服务访问需要一个稳定入口。

比如数据库可能有一个 Pod,也可能有多个 Pod。无论背后的 Pod 怎么变,应用都希望用一个固定地址访问数据库。

Service 就像一个中间层:

  • 前面给调用方一个稳定地址。
  • 后面自动转发到健康的 Pod。

可以把它类比成反向代理或者负载均衡器。

flowchart LR
    A[应用 Pod] --> B[数据库 Service
稳定入口] B --> C[数据库 Pod 1] B --> D[数据库 Pod 2] B --> E[数据库 Pod 3]

即使数据库 Pod 1 挂了,被新的 Pod 替换了,Service 的地址也不变。应用继续访问 Service,Service 再把请求转发到可用的 Pod。

这里顺手补一下正向代理和反向代理。

正向代理代理的是客户端。比如科学上网时,客户端先把请求发给代理服务器,代理服务器再帮你去访问目标网站。目标网站看到的是代理服务器,不一定知道真实客户端是谁。

反向代理代理的是服务端。比如 Nginx 后面有多台服务器,用户只访问 Nginx,Nginx 再把请求转发给某一台后端服务器。用户不知道后面真实服务器是谁。

Service 更像反向代理:调用方不需要知道后面具体有哪些 Pod,只需要访问 Service。

七、内部服务和外部服务

不是所有服务都应该暴露给外部用户。

比如:

  • 数据库
  • Redis 缓存
  • 消息队列
  • 内部管理服务

这些通常只需要在集群内部访问,不应该直接暴露到公网。

而下面这些服务可能需要对外暴露:

  • 前端页面
  • 后端 API
  • 网关服务
  • 对外开放的平台接口

所以可以先分成两类:

  • 内部服务:只在集群内部访问。
  • 外部服务:需要让用户或外部系统访问。

Service 有几种常见类型:

  • ClusterIP:默认类型,只能在集群内部访问。
  • NodePort:在 Node 上开放一个端口,通过 NodeIP:端口 访问。
  • LoadBalancer:通常对接云厂的负载均衡器,给服务分配外部入口。
  • ExternalName:把服务映射到一个外部域名。

刚入门时,重点理解 ClusterIP 和 NodePort 就够了。

ClusterIP 就像“内网地址”,只在集群里用。NodePort 就像在机器上开了一个端口,比如你以前访问 localhost:8080,本质上也是通过 IP 和端口访问服务。

但生产环境一般不会让用户记 IP 和端口,而是使用域名。

这就轮到 Ingress 了。

八、Ingress:用域名和路径访问服务

Service 能解决服务入口问题,但如果要对外提供正式访问,通常还需要域名、路径转发、HTTPS 证书等能力。

Ingress 就是用来管理外部访问规则的。

比如:

  • www.example.com 访问前端服务。
  • api.example.com/user 访问用户服务。
  • api.example.com/order 访问订单服务。

Ingress 可以根据域名和路径,把请求转发到不同的 Service。

flowchart TD
    U[用户浏览器] --> I[Ingress
统一入口] I -->|/user| S1[user-service] I -->|/order| S2[order-service] S1 --> P1[用户服务 Pod] S2 --> P2[订单服务 Pod]

需要注意的是,Ingress 本身更像一份规则,真正执行转发的通常是 Ingress Controller,比如 Nginx Ingress Controller,或者云厂自己的网关组件。

入门时可以这样记:

  • Pod:真正跑应用的地方。
  • Service:给 Pod 一个稳定入口。
  • Ingress:把外部域名和路径转到 Service。

九、ConfigMap:配置不要写死在镜像里

以前我们写应用时,数据库地址、Redis 地址、端口号、开关配置,可能会写在配置文件或环境变量里。

如果这些配置直接打进镜像,就会很麻烦。

比如数据库地址变了,难道还要重新改代码、重新构建镜像、重新部署吗?这对线上服务很不友好。

Kubernetes 提供了 ConfigMap,用来管理普通配置。

它的作用是:把配置从镜像里拿出来,交给运行环境管理。

比如同一个后端镜像,可以在开发环境连接开发数据库,在测试环境连接测试数据库,在生产环境连接生产数据库。镜像不变,只是注入的 ConfigMap 不同。

可以这样理解:

  • 镜像负责“程序是什么”。
  • ConfigMap 负责“程序运行时用什么配置”。

这样应用和配置就解耦了。

十、Secret:敏感信息不要放 ConfigMap

ConfigMap 适合放普通配置,但不适合放密码、Token、证书这类敏感信息。

所以 Kubernetes 提供了 Secret。

Secret 用来保存敏感配置,比如:

  • 数据库用户名和密码
  • API Token
  • TLS 证书
  • 私钥片段

不过这里有个坑:Kubernetes Secret 默认只是 Base64 编码,不等于加密。

Base64 很容易解码,网上随便找个工具就能还原。所以 Secret 不是“绝对安全保险箱”,还需要配合权限控制、访问审计、密钥管理系统等手段。

入门时先记住:

  • 普通配置放 ConfigMap。
  • 敏感配置放 Secret。
  • Secret 默认 Base64 不是加密,不要误以为万事大吉。

真是一层套一层。

十一、Volume:Pod 重启后数据怎么办

Pod 是不稳定的。它可能被删除、重建、迁移。

如果 Pod 里跑的是无状态应用,比如普通后端 API,那问题不大。这个 Pod 挂了,重新拉一个就行。

但如果 Pod 里跑的是数据库,事情就复杂了。

数据库最重要的是数据。如果 Pod 一重启,数据就没了,那肯定不行。

Kubernetes 提供 Volume 来解决这个问题。

Volume 可以把一块存储挂载到 Pod 里。这样数据不完全跟着容器生命周期走,而是放在外部存储或节点存储上。

在云环境里,这个存储可能是:

  • 云硬盘
  • NAS
  • 对象存储
  • 分布式存储
  • 本地磁盘目录

入门时可以先把 Volume 理解成:给 Pod 挂一块“不会因为容器重启就马上消失”的存储。

后面还会遇到 PV、PVC、StorageClass,它们是更完整的持久化存储管理方式。初学不用急着一次吃完。

十二、Deployment:管理应用副本和更新

如果一个服务只有一个 Pod,那么这个 Pod 挂了,服务就不可用了。

为了高可用,我们通常会让同一个服务跑多个副本。

比如后端 API 跑 3 个 Pod:

flowchart LR
    S[api-service] --> P1[api Pod 1]
    S --> P2[api Pod 2]
    S --> P3[api Pod 3]

但问题是:谁来保证一直有 3 个 Pod?谁来处理 Pod 挂了以后补一个?谁来做版本升级?

Deployment 就是用来管理这些事情的。

它主要负责:

  • 定义应用有多少个副本。
  • 某个 Pod 挂了以后自动补齐。
  • 应用升级时做滚动更新。
  • 新版本有问题时支持回滚。

比如你声明一个 Deployment:副本数是 3。Kubernetes 就会努力保证集群里一直有 3 个对应的 Pod。

如果其中一个 Pod 挂了,它会再创建一个新的 Pod。

这就叫副本控制。

滚动更新是什么

滚动更新可以理解为:不要一下子把旧版本全部停掉,而是一批一批替换。

比如原来有 3 个旧版本 Pod,现在要升级到新版本。Kubernetes 可以先启动 1 个新版本 Pod,确认它能正常接流量,再逐步替换剩下的旧版本 Pod。

这样用户不容易感知到服务中断。

这就是所谓的平滑升级。

十三、ReplicaSet:Deployment 和 Pod 中间的一层

当你创建 Deployment 后,Kubernetes 通常不会直接由 Deployment 管 Pod,而是中间还有一层 ReplicaSet。

关系大概是:

flowchart TD
    D[Deployment
定义版本和副本策略] --> R[ReplicaSet
维护副本数量] R --> P1[Pod 1] R --> P2[Pod 2] R --> P3[Pod 3]

ReplicaSet 的作用是维护某一批 Pod 的副本数量。

平时我们一般不直接操作 ReplicaSet,而是操作 Deployment。你可以把 ReplicaSet 理解成 Deployment 背后自动创建和管理的“副本控制器”。

在命令里看到类似 nginx-deployment-6d6565499c-xrkv9 这种 Pod 名字时,中间那段通常就和 ReplicaSet 有关。

十四、StatefulSet:有状态应用不能简单复制

Deployment 很适合管理无状态应用,比如普通 API 服务、前端服务、计算服务。

什么叫无状态?

简单说:这个 Pod 挂了,换一个新的也没关系。因为关键数据不在它本地,或者它可以从数据库、缓存、对象存储里重新拿到。

但数据库、消息队列、部分缓存、搜索引擎这类服务就不一样。它们有自己的数据、身份、顺序和存储需求。

这种就叫有状态应用。

有状态应用不能简单地“复制 3 个一模一样的 Pod”就完事。因为每个副本可能有不同数据,或者需要固定身份,比如:

  • mysql-0
  • mysql-1
  • mysql-2

它们之间可能有主从关系、同步关系、选主关系。

StatefulSet 就是 Kubernetes 用来管理有状态应用的对象。

它和 Deployment 有点像,也能管理副本数量,但它额外强调:

  • 每个 Pod 有稳定名字。
  • 每个 Pod 有稳定网络标识。
  • 每个 Pod 可以绑定自己的持久化存储。
  • 创建、删除、更新通常有固定顺序。

不过要注意:不是所有数据库都适合直接放进 Kubernetes 里。

有些有状态服务部署和维护很复杂,生产环境里也常常会使用云数据库、独立数据库集群,或者专门的 Operator 来管理,而不是自己手写一个 StatefulSet 就完事。

所以入门理解到这里就够:

  • 无状态应用通常用 Deployment。
  • 有状态应用可以用 StatefulSet。
  • 数据库这类服务要格外小心,不要以为多起几个 Pod 就高可用了。

十五、Kubernetes 架构:Master-Worker

Kubernetes 是典型的 Master-Worker 架构。

  • Master Node:负责管理整个集群。
  • Worker Node:负责真正运行应用。

现在很多文档会把 Master Node 称为 Control Plane,也就是控制平面。为了入门好理解,先叫 Master 也没问题。

整体结构可以这样看:

flowchart TD
    U[用户 / kubectl] --> A[kube-apiserver]

    subgraph Master[Master Node / Control Plane]
        A --> S[Scheduler]
        A --> C[Controller Manager]
        A --> E[etcd]
        A --> CCM[Cloud Controller Manager]
    end

    subgraph W1[Worker Node 1]
        K1[kubelet]
        P1[kube-proxy]
        R1[container runtime]
        Pod1[Pod]
    end

    subgraph W2[Worker Node 2]
        K2[kubelet]
        P2[kube-proxy]
        R2[container runtime]
        Pod2[Pod]
    end

    A --> K1
    A --> K2
    R1 --> Pod1
    R2 --> Pod2

下面拆开看。

十六、Worker Node 上有什么

Worker Node 是真正跑业务应用的机器。

每个 Worker Node 上通常有三个重要组件:

  • container runtime
  • kubelet
  • kube-proxy

container runtime

container runtime 是容器运行时。

它负责拉取镜像、创建容器、启动容器、停止容器。

以前大家经常听 Docker,现在 Kubernetes 里也可能使用 containerd、CRI-O 等运行时。对入门来说,可以先理解为:container runtime 就是负责真正把容器跑起来的东西。

kubelet

kubelet 是每个 Node 上非常关键的组件。

它负责管理当前节点上的 Pod。

Master 告诉这个 Node:“你这里应该跑某个 Pod。”然后 kubelet 就会调用容器运行时,把对应容器拉起来,并持续汇报状态。

可以理解为:kubelet 是 Node 上的管家。

它会关心:

  • Pod 有没有启动成功。
  • 容器是否还活着。
  • 当前节点资源状态如何。
  • 要不要向 apiserver 汇报最新状态。

kube-proxy

kube-proxy 负责网络代理和负载均衡相关工作。

前面说 Service 会把请求转发到后端 Pod。那这件事在每个节点上就离不开 kube-proxy 这类组件的参与。

你可以先简单理解为:kube-proxy 帮 Service 把流量导到正确的 Pod。

十七、Master Node 上有什么

Master Node 负责管理整个集群。

它上面有几个核心组件。

kube-apiserver

kube-apiserver 是 Kubernetes 的入口。

无论你用 kubectl 创建 Deployment,还是其他组件要读取集群状态,基本都要经过 apiserver。

它负责:

  • 提供 Kubernetes API。
  • 接收用户请求。
  • 做认证、授权和准入控制。
  • 把资源状态写入 etcd。
  • 让其他组件通过它协作。

可以把 apiserver 理解成 Kubernetes 集群的大门和中转站。

Scheduler

Scheduler 是调度器。

当你创建一个新的 Pod 时,它一开始还不知道该跑在哪个 Node 上。Scheduler 会根据节点资源、调度规则、亲和性、污点容忍等条件,决定把 Pod 放到哪台机器上。

入门理解可以简单一点:Scheduler 负责给 Pod 挑机器。

Controller Manager

Controller Manager 是控制器管理器。

它负责各种控制循环。

比如你声明一个 Deployment 要 3 个副本,但现在只有 2 个,控制器就会发现“不一致”,然后创建新的 Pod 让它恢复到 3 个。

Node 挂了、Pod 少了、资源状态不对,这些都需要控制器不断检查和修正。

所以可以理解为:Controller Manager 负责让现实状态接近期望状态。

etcd

etcd 是一个高可用键值存储系统。

Kubernetes 会把集群状态存在 etcd 里,比如有哪些 Node、有哪些 Pod、有哪些 Service、当前配置是什么。

注意:etcd 存的是 Kubernetes 集群状态,不是你的业务数据。

你的 MySQL 数据、用户订单、文件内容,不应该存在 etcd 里。

Cloud Controller Manager

Cloud Controller Manager 是 Kubernetes 和云厂基础设施之间的连接层。

比如在云上创建 LoadBalancer、挂载云盘、识别云服务器节点,这些都需要和云平台 API 交互。

不同云厂有不同实现,但 Kubernetes 尽量提供统一抽象。

对云厂实习来说,这个组件挺有意义,因为它说明:Kubernetes 并不是孤立运行的,它会和云服务器、负载均衡、云硬盘、网络等云产品发生关系。

十八、kubectl:和 Kubernetes 对话的命令行

kubectl 是 Kubernetes 的命令行工具。

你可以通过 kubectl 和 apiserver 交互,比如:

kubectl get nodes
kubectl get pods
kubectl get services
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl exec -it <pod-name> -- /bin/bash

如果你刚开始学,不用一口气背所有命令。先掌握几个最常用的:

  • kubectl get:查看资源列表。
  • kubectl describe:查看资源详细信息和事件。
  • kubectl logs:查看 Pod 日志。
  • kubectl exec:进入 Pod 内部执行命令。
  • kubectl apply -f:根据 YAML 文件创建或更新资源。
  • kubectl delete -f:根据 YAML 文件删除资源。

这些命令就是你排查问题的入口。

十九、YAML:把命令变成配置文件

刚开始可以用命令创建资源,比如:

kubectl create deployment nginx-deployment --image=nginx

但命令不方便长期维护。更推荐把资源写成 YAML 文件。

比如一个简单 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

这里先看几个关键字段:

  • apiVersion:使用哪个 API 版本。
  • kind:资源类型,比如 Deployment、Service。
  • metadata.name:资源名称。
  • spec.replicas:副本数量。
  • selector.matchLabels:Deployment 用什么标签选择 Pod。
  • template:Pod 模板,描述要创建什么样的 Pod。
  • containers.image:容器镜像。

应用配置:

kubectl apply -f nginx-deployment.yaml

查看 Pod:

kubectl get pods -o wide

这里的 -o wide 可以看到更多信息,比如 Pod IP、所在 Node。

如果把 replicas: 3 改成 replicas: 2,再执行 apply,Kubernetes 就会把副本数调整成 2。

这就是声明式配置的好处:配置文件就是你希望集群变成的样子。

二十、用 Service 把 nginx 暴露出去

前面的 Deployment 创建了 3 个 nginx Pod,但它们的 IP 是集群内部 IP,外部访问不了,而且 Pod IP 也不稳定。

这时可以创建 Service。

一个简单 Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

这个 Service 会选择带有 app: nginx 标签的 Pod,把请求转发到它们的 80 端口。

但这个 Service 默认是 ClusterIP 类型,只能集群内部访问。

如果想通过 Node 的 IP 和端口访问,可以改成 NodePort:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080

应用之后:

kubectl apply -f nginx-service.yaml
kubectl get services
kubectl get nodes -o wide

然后就可以尝试访问:

http://NodeIP:30080

这里的 30080 就是暴露在 Node 上的端口。NodePort 默认端口范围通常是 30000-32767

这个例子把前面的概念串起来了:

flowchart LR
    U[浏览器访问
NodeIP:30080] --> S[NodePort Service] S --> P1[nginx Pod 1] S --> P2[nginx Pod 2] S --> P3[nginx Pod 3] D[Deployment] --> P1 D --> P2 D --> P3

这时候你就能看到 K8s 的基本链路:

Deployment 创建和管理 Pod,Service 选择这些 Pod 并提供访问入口。

二十一、Namespace:给资源分空间

Namespace 是命名空间,用来把 Kubernetes 资源分组。

可以理解为在一个集群里划分多个空间,不同项目、团队或环境可以放在不同 Namespace 里。

比如:

  • dev:开发环境
  • test:测试环境
  • prod:生产环境
  • monitoring:监控组件
  • portainer:可视化管理工具

命令里经常会看到 -n 参数:

kubectl get pods -n default
kubectl apply -n portainer -f portainer.yaml

这里的 -n 就是指定 Namespace。

Namespace 的意义是隔离和分组,但它不是虚拟机,也不是强安全边界。入门阶段先理解为“资源分目录”就行。

二十二、minikube、K3s 和云厂集群

如果只是本地学习,可以用 minikube 或 K3s。

minikube 是一个轻量级 Kubernetes 发行版,可以在本地启动一个单节点集群,适合入门学习。

常见命令:

minikube start
kubectl get nodes

如果国内拉镜像慢,可以指定镜像源或版本:

minikube start --image-mirror-country='cn' --kubernetes-version=v1.23.9

K3s 是一个轻量级 Kubernetes,适合资源有限的环境,也常用于边缘计算、开发测试、小集群。

如果你用 Multipass 创建几台 Ubuntu 虚拟机,可以用 K3s 搭一个简单 Master-Worker 集群。

但如果是在云厂实习,你接触的更多可能是托管 Kubernetes:

  • 腾讯云 TKE
  • 阿里云 ACK
  • AWS EKS
  • Google GKE
  • Azure AKS

它们本质上也是 Kubernetes,只是云厂帮你托管了很多集群管理工作,比如控制面、节点池、负载均衡、云盘、网络插件、监控日志集成等。

所以本地学习 minikube / K3s 是为了理解原理;到云厂看托管 K8s,是看这些原理如何产品化。

二十三、把所有概念串成一张图

到这里,核心概念可以串起来了:

flowchart TD
    A[Docker 镜像] --> B[Pod
运行容器] C[Deployment
管理副本和更新] --> B D[Service
稳定访问入口] --> B E[Ingress
域名 / 路径转发] --> D F[ConfigMap
普通配置] --> B G[Secret
敏感配置] --> B H[Volume
持久化存储] --> B I[Node
运行 Pod 的机器] --> B

如果再放进集群架构里,就是:

flowchart LR
    U[用户 / kubectl] --> M[Master Node
管理集群] M --> W1[Worker Node 1] M --> W2[Worker Node 2] W1 --> P1[Pod] W2 --> P2[Pod] S[Service] --> P1 S --> P2 I[Ingress] --> S

这两张图基本覆盖了入门阶段最重要的关系。

二十四、用 Docker 使用经验类比 K8s

如果你只用过 Docker,可以这样类比:

  • Docker 里你关心 docker run,K8s 里你更多关心 kubectl apply -f yaml
  • Docker 里你直接跑容器,K8s 里容器通常跑在 Pod 里。
  • Docker 里容器挂了可能手动重启,K8s 里 Deployment 会帮你补副本。
  • Docker 里端口映射用 -p 8080:80,K8s 里常用 Service / NodePort / Ingress 暴露服务。
  • Docker 里配置可能用环境变量,K8s 里可以用 ConfigMap / Secret 管理配置。
  • Docker 里数据卷用 volume,K8s 里也有 Volume / PVC 这套机制。
  • Docker Compose 管一组容器,K8s 管一组机器上的一组应用。

这个类比不完全严谨,但足够帮入门者建立第一层直觉。

二十五、实习时先掌握哪些就够用

如果刚开始补 K8s,不建议一上来就钻 CNI、CSI、CRI、etcd 高可用、iptables、IPVS、Operator、Service Mesh。

先把下面这些搞清楚:

  1. Node 是机器。
  2. Pod 是最小调度单位,容器跑在 Pod 里。
  3. Pod IP 不稳定,所以需要 Service。
  4. Service 给一组 Pod 提供稳定入口。
  5. Ingress 负责外部域名和路径转发。
  6. ConfigMap 放普通配置,Secret 放敏感配置。
  7. Volume 解决 Pod 重启后的数据问题。
  8. Deployment 管理副本、滚动更新和回滚。
  9. StatefulSet 用来管理有状态应用。
  10. Master 管集群,Worker 跑应用。
  11. kubectl 是和集群交互的命令行。
  12. YAML 是声明资源期望状态的配置文件。

掌握这些之后,再看云厂里的容器服务、节点池、负载均衡、日志服务、监控告警,就不会完全懵了。

结语:K8s 先别学成玄学

Kubernetes 的生态很大,大到很容易让初学者误以为它是一门玄学。

但刚入门时,不要急着背所有名词。先从 Docker 的问题出发:一个容器好管理,很多容器、多台机器、多个服务、多个环境就不好管理了。

Kubernetes 解决的就是这些复杂性:

  • 它用 Pod 包住容器。
  • 用 Deployment 管应用副本。
  • 用 Service 解决访问入口不稳定。
  • 用 Ingress 管外部流量。
  • 用 ConfigMap 和 Secret 管配置。
  • 用 Volume 管数据。
  • 用 Master-Worker 架构管理整个集群。

所以第一阶段不需要装作很懂。只要能把这条线讲清楚:

Docker 让应用容器化,Kubernetes 负责在一组机器上管理这些容器,让它们能被调度、访问、扩缩、更新和恢复。

这就已经是一个很好的开始了。


文章作者: Onefly
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Onefly !
评论
  目录