Kubernetes 入门:概念与安装
Part 1:什么是 Kubernetes
概念引入
想象你经营一个巨大的集装箱港口:
- 每天有上百艘货船要停靠(你的应用程序)
- 每艘船需要泊位、电力、工人(CPU、内存、存储)
- 有的船坏了要换一艘顶上(自动修复)
- 旺季来了要多安排船,淡季要减少(自动扩缩)
- 你不可能每艘船都手动管
Kubernetes(简称 K8s)就是那个港口调度系统。 你告诉它"我要 3 艘这样的船",它会自动帮你安排泊位、调度工人、坏了就替换、多了就缩减。
名字由来
Kubernetes 来自希腊语,意思是"舵手"或"飞行员"。Google 内部叫它 Borg,2014 年开源后改名 Kubernetes。因为 K 和 s 之间有 8 个字母,所以简称 K8s。
原理讲解
K8s 解决什么问题?
在 K8s 之前,你可能这样部署应用:
#mermaid-svg-k51FIKYY7gB7Yao0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-k51FIKYY7gB7Yao0 .error-icon{fill:#552222;}#mermaid-svg-k51FIKYY7gB7Yao0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-k51FIKYY7gB7Yao0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-k51FIKYY7gB7Yao0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-k51FIKYY7gB7Yao0 .marker.cross{stroke:#333333;}#mermaid-svg-k51FIKYY7gB7Yao0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-k51FIKYY7gB7Yao0 p{margin:0;}#mermaid-svg-k51FIKYY7gB7Yao0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 .cluster-label text{fill:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 .cluster-label span{color:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 .cluster-label span p{background-color:transparent;}#mermaid-svg-k51FIKYY7gB7Yao0 .label text,#mermaid-svg-k51FIKYY7gB7Yao0 span{fill:#333;color:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 .node rect,#mermaid-svg-k51FIKYY7gB7Yao0 .node circle,#mermaid-svg-k51FIKYY7gB7Yao0 .node ellipse,#mermaid-svg-k51FIKYY7gB7Yao0 .node polygon,#mermaid-svg-k51FIKYY7gB7Yao0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-k51FIKYY7gB7Yao0 .rough-node .label text,#mermaid-svg-k51FIKYY7gB7Yao0 .node .label text,#mermaid-svg-k51FIKYY7gB7Yao0 .image-shape .label,#mermaid-svg-k51FIKYY7gB7Yao0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-k51FIKYY7gB7Yao0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-k51FIKYY7gB7Yao0 .rough-node .label,#mermaid-svg-k51FIKYY7gB7Yao0 .node .label,#mermaid-svg-k51FIKYY7gB7Yao0 .image-shape .label,#mermaid-svg-k51FIKYY7gB7Yao0 .icon-shape .label{text-align:center;}#mermaid-svg-k51FIKYY7gB7Yao0 .node.clickable{cursor:pointer;}#mermaid-svg-k51FIKYY7gB7Yao0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-k51FIKYY7gB7Yao0 .arrowheadPath{fill:#333333;}#mermaid-svg-k51FIKYY7gB7Yao0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-k51FIKYY7gB7Yao0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-k51FIKYY7gB7Yao0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k51FIKYY7gB7Yao0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-k51FIKYY7gB7Yao0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k51FIKYY7gB7Yao0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-k51FIKYY7gB7Yao0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-k51FIKYY7gB7Yao0 .cluster text{fill:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 .cluster span{color:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-k51FIKYY7gB7Yao0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-k51FIKYY7gB7Yao0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-k51FIKYY7gB7Yao0 .icon-shape,#mermaid-svg-k51FIKYY7gB7Yao0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k51FIKYY7gB7Yao0 .icon-shape p,#mermaid-svg-k51FIKYY7gB7Yao0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-k51FIKYY7gB7Yao0 .icon-shape .label rect,#mermaid-svg-k51FIKYY7gB7Yao0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k51FIKYY7gB7Yao0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-k51FIKYY7gB7Yao0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-k51FIKYY7gB7Yao0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 手动时代
手动 SSH
手动 SSH
手动 SSH
开发者
服务器1
服务器2
服务器3
问题:每台服务器手动操作,不可扩展、容易出错、无法自动修复。
有了 K8s 之后:
#mermaid-svg-T5Dxcl4nq7o11chF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T5Dxcl4nq7o11chF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T5Dxcl4nq7o11chF .error-icon{fill:#552222;}#mermaid-svg-T5Dxcl4nq7o11chF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T5Dxcl4nq7o11chF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T5Dxcl4nq7o11chF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T5Dxcl4nq7o11chF .marker.cross{stroke:#333333;}#mermaid-svg-T5Dxcl4nq7o11chF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T5Dxcl4nq7o11chF p{margin:0;}#mermaid-svg-T5Dxcl4nq7o11chF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-T5Dxcl4nq7o11chF .cluster-label text{fill:#333;}#mermaid-svg-T5Dxcl4nq7o11chF .cluster-label span{color:#333;}#mermaid-svg-T5Dxcl4nq7o11chF .cluster-label span p{background-color:transparent;}#mermaid-svg-T5Dxcl4nq7o11chF .label text,#mermaid-svg-T5Dxcl4nq7o11chF span{fill:#333;color:#333;}#mermaid-svg-T5Dxcl4nq7o11chF .node rect,#mermaid-svg-T5Dxcl4nq7o11chF .node circle,#mermaid-svg-T5Dxcl4nq7o11chF .node ellipse,#mermaid-svg-T5Dxcl4nq7o11chF .node polygon,#mermaid-svg-T5Dxcl4nq7o11chF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-T5Dxcl4nq7o11chF .rough-node .label text,#mermaid-svg-T5Dxcl4nq7o11chF .node .label text,#mermaid-svg-T5Dxcl4nq7o11chF .image-shape .label,#mermaid-svg-T5Dxcl4nq7o11chF .icon-shape .label{text-anchor:middle;}#mermaid-svg-T5Dxcl4nq7o11chF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-T5Dxcl4nq7o11chF .rough-node .label,#mermaid-svg-T5Dxcl4nq7o11chF .node .label,#mermaid-svg-T5Dxcl4nq7o11chF .image-shape .label,#mermaid-svg-T5Dxcl4nq7o11chF .icon-shape .label{text-align:center;}#mermaid-svg-T5Dxcl4nq7o11chF .node.clickable{cursor:pointer;}#mermaid-svg-T5Dxcl4nq7o11chF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-T5Dxcl4nq7o11chF .arrowheadPath{fill:#333333;}#mermaid-svg-T5Dxcl4nq7o11chF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-T5Dxcl4nq7o11chF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-T5Dxcl4nq7o11chF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T5Dxcl4nq7o11chF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-T5Dxcl4nq7o11chF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T5Dxcl4nq7o11chF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-T5Dxcl4nq7o11chF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-T5Dxcl4nq7o11chF .cluster text{fill:#333;}#mermaid-svg-T5Dxcl4nq7o11chF .cluster span{color:#333;}#mermaid-svg-T5Dxcl4nq7o11chF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-T5Dxcl4nq7o11chF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-T5Dxcl4nq7o11chF rect.text{fill:none;stroke-width:0;}#mermaid-svg-T5Dxcl4nq7o11chF .icon-shape,#mermaid-svg-T5Dxcl4nq7o11chF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T5Dxcl4nq7o11chF .icon-shape p,#mermaid-svg-T5Dxcl4nq7o11chF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-T5Dxcl4nq7o11chF .icon-shape .label rect,#mermaid-svg-T5Dxcl4nq7o11chF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T5Dxcl4nq7o11chF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-T5Dxcl4nq7o11chF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-T5Dxcl4nq7o11chF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 声明式 YAML
调度到
调度到
调度到
开发者
K8s 集群
控制平面
节点1
节点2
节点3
你只需要声明"我要什么",K8s 自动帮你实现。
核心概念速览
| 概念 | 比喻 | 说明 |
|---|---|---|
| Cluster | 整个港口 | 一组服务器组成的集群 |
| Node | 港口里的码头 | 集群中的一台服务器 |
| Pod | 一艘货船 | K8s 的最小调度单元,包含一个或多个容器 |
| Deployment | 航运公司的调度计划 | 声明"我要几艘这样的船" |
| Service | 港口接待处 | 稳定的访问入口,不管后面的船怎么换 |
K8s 架构一览
#mermaid-svg-7B9kKjG59pCn0HWy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7B9kKjG59pCn0HWy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7B9kKjG59pCn0HWy .error-icon{fill:#552222;}#mermaid-svg-7B9kKjG59pCn0HWy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7B9kKjG59pCn0HWy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7B9kKjG59pCn0HWy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7B9kKjG59pCn0HWy .marker.cross{stroke:#333333;}#mermaid-svg-7B9kKjG59pCn0HWy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7B9kKjG59pCn0HWy p{margin:0;}#mermaid-svg-7B9kKjG59pCn0HWy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7B9kKjG59pCn0HWy .cluster-label text{fill:#333;}#mermaid-svg-7B9kKjG59pCn0HWy .cluster-label span{color:#333;}#mermaid-svg-7B9kKjG59pCn0HWy .cluster-label span p{background-color:transparent;}#mermaid-svg-7B9kKjG59pCn0HWy .label text,#mermaid-svg-7B9kKjG59pCn0HWy span{fill:#333;color:#333;}#mermaid-svg-7B9kKjG59pCn0HWy .node rect,#mermaid-svg-7B9kKjG59pCn0HWy .node circle,#mermaid-svg-7B9kKjG59pCn0HWy .node ellipse,#mermaid-svg-7B9kKjG59pCn0HWy .node polygon,#mermaid-svg-7B9kKjG59pCn0HWy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7B9kKjG59pCn0HWy .rough-node .label text,#mermaid-svg-7B9kKjG59pCn0HWy .node .label text,#mermaid-svg-7B9kKjG59pCn0HWy .image-shape .label,#mermaid-svg-7B9kKjG59pCn0HWy .icon-shape .label{text-anchor:middle;}#mermaid-svg-7B9kKjG59pCn0HWy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7B9kKjG59pCn0HWy .rough-node .label,#mermaid-svg-7B9kKjG59pCn0HWy .node .label,#mermaid-svg-7B9kKjG59pCn0HWy .image-shape .label,#mermaid-svg-7B9kKjG59pCn0HWy .icon-shape .label{text-align:center;}#mermaid-svg-7B9kKjG59pCn0HWy .node.clickable{cursor:pointer;}#mermaid-svg-7B9kKjG59pCn0HWy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7B9kKjG59pCn0HWy .arrowheadPath{fill:#333333;}#mermaid-svg-7B9kKjG59pCn0HWy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7B9kKjG59pCn0HWy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7B9kKjG59pCn0HWy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7B9kKjG59pCn0HWy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7B9kKjG59pCn0HWy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7B9kKjG59pCn0HWy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7B9kKjG59pCn0HWy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7B9kKjG59pCn0HWy .cluster text{fill:#333;}#mermaid-svg-7B9kKjG59pCn0HWy .cluster span{color:#333;}#mermaid-svg-7B9kKjG59pCn0HWy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7B9kKjG59pCn0HWy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7B9kKjG59pCn0HWy rect.text{fill:none;stroke-width:0;}#mermaid-svg-7B9kKjG59pCn0HWy .icon-shape,#mermaid-svg-7B9kKjG59pCn0HWy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7B9kKjG59pCn0HWy .icon-shape p,#mermaid-svg-7B9kKjG59pCn0HWy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7B9kKjG59pCn0HWy .icon-shape .label rect,#mermaid-svg-7B9kKjG59pCn0HWy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7B9kKjG59pCn0HWy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7B9kKjG59pCn0HWy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7B9kKjG59pCn0HWy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 工作节点 (Worker Node)
工作节点 (Worker Node)
控制平面 (Control Plane)
kube-apiserver
所有操作的入口
etcd
集群状态存储
kube-scheduler
决定 Pod 放哪个节点
kube-controller-manager
维持期望状态
kubelet
管理 Pod
kube-proxy
网络转发
containerd
运行容器
Pod
Pod
kubelet
kube-proxy
containerd
Pod
Pod
💡 现在不用记住每个组件。 后面每篇文章会逐步介绍它们。这里只需要知道:控制平面负责"决策",工作节点负责"干活"。
声明式 vs 命令式
K8s 最大的特点是声明式操作:
| 命令式(传统) | 声明式(K8s) | |
|---|---|---|
| 方式 | "在服务器 A 上启动这个容器" | "我要 3 个这样的 Pod" |
| 谁做决策 | 你 | K8s |
| 自动修复 | ❌ 需要手动 | ✅ K8s 自动补上 |
| 示例 | docker run nginx |
kubectl apply -f deploy.yaml |
声明式的好处:你写一份 YAML 描述想要的状态,K8s 会持续把现实状态调整到与你声明的一致------即使 Pod 崩溃了、节点宕机了,K8s 都会自动修复。
自检问题
- K8s 的 K 和 s 之间有几个字母?为什么叫 K8s?
查看答案 8 个字母(ubernete),所以 K + 8 + s = K8s。
- Pod 和容器是什么关系?
查看答案 Pod 是 K8s 的最小调度单元,一个 Pod 可以包含一个或多个容器。Pod 里的容器共享网络和存储。
- 声明式和命令式的核心区别是什么?
查看答案 命令式是你告诉系统"怎么做"(具体步骤),声明式是你告诉系统"要什么"(期望状态),由系统自己决定怎么做。K8s 是声明式的。
Part 2:安装 Kind
概念引入
现在你知道了 K8s 是什么,但你不可能在港口调度系统上直接练习------你需要一个迷你港口。
Kind(Kubernetes in Docker) 就是这样一个迷你港口。它在你电脑的 Docker 里运行一个完整的 K8s 集群,启动只要不到 1 分钟,用完随时删掉。就像在你书桌上放了一个港口模型,可以随便摆弄。
#mermaid-svg-GXkDSGSfEqUwXhna{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GXkDSGSfEqUwXhna .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GXkDSGSfEqUwXhna .error-icon{fill:#552222;}#mermaid-svg-GXkDSGSfEqUwXhna .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GXkDSGSfEqUwXhna .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GXkDSGSfEqUwXhna .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GXkDSGSfEqUwXhna .marker.cross{stroke:#333333;}#mermaid-svg-GXkDSGSfEqUwXhna svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GXkDSGSfEqUwXhna p{margin:0;}#mermaid-svg-GXkDSGSfEqUwXhna .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GXkDSGSfEqUwXhna .cluster-label text{fill:#333;}#mermaid-svg-GXkDSGSfEqUwXhna .cluster-label span{color:#333;}#mermaid-svg-GXkDSGSfEqUwXhna .cluster-label span p{background-color:transparent;}#mermaid-svg-GXkDSGSfEqUwXhna .label text,#mermaid-svg-GXkDSGSfEqUwXhna span{fill:#333;color:#333;}#mermaid-svg-GXkDSGSfEqUwXhna .node rect,#mermaid-svg-GXkDSGSfEqUwXhna .node circle,#mermaid-svg-GXkDSGSfEqUwXhna .node ellipse,#mermaid-svg-GXkDSGSfEqUwXhna .node polygon,#mermaid-svg-GXkDSGSfEqUwXhna .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GXkDSGSfEqUwXhna .rough-node .label text,#mermaid-svg-GXkDSGSfEqUwXhna .node .label text,#mermaid-svg-GXkDSGSfEqUwXhna .image-shape .label,#mermaid-svg-GXkDSGSfEqUwXhna .icon-shape .label{text-anchor:middle;}#mermaid-svg-GXkDSGSfEqUwXhna .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GXkDSGSfEqUwXhna .rough-node .label,#mermaid-svg-GXkDSGSfEqUwXhna .node .label,#mermaid-svg-GXkDSGSfEqUwXhna .image-shape .label,#mermaid-svg-GXkDSGSfEqUwXhna .icon-shape .label{text-align:center;}#mermaid-svg-GXkDSGSfEqUwXhna .node.clickable{cursor:pointer;}#mermaid-svg-GXkDSGSfEqUwXhna .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GXkDSGSfEqUwXhna .arrowheadPath{fill:#333333;}#mermaid-svg-GXkDSGSfEqUwXhna .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GXkDSGSfEqUwXhna .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GXkDSGSfEqUwXhna .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GXkDSGSfEqUwXhna .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GXkDSGSfEqUwXhna .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GXkDSGSfEqUwXhna .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GXkDSGSfEqUwXhna .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GXkDSGSfEqUwXhna .cluster text{fill:#333;}#mermaid-svg-GXkDSGSfEqUwXhna .cluster span{color:#333;}#mermaid-svg-GXkDSGSfEqUwXhna div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GXkDSGSfEqUwXhna .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GXkDSGSfEqUwXhna rect.text{fill:none;stroke-width:0;}#mermaid-svg-GXkDSGSfEqUwXhna .icon-shape,#mermaid-svg-GXkDSGSfEqUwXhna .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GXkDSGSfEqUwXhna .icon-shape p,#mermaid-svg-GXkDSGSfEqUwXhna .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GXkDSGSfEqUwXhna .icon-shape .label rect,#mermaid-svg-GXkDSGSfEqUwXhna .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GXkDSGSfEqUwXhna .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GXkDSGSfEqUwXhna .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GXkDSGSfEqUwXhna :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 你的电脑
Kind 集群
kubectl
Docker 引擎
Kind Node
(Docker 容器)
K8s 控制平面 + 工作节点
你
为什么选 Kind?
| 工具 | 启动速度 | 资源占用 | 多节点 | 适合场景 |
|---|---|---|---|---|
| Kind | ⚡ <1分钟 | 小 | ✅ | 本地学习、CI 测试 |
| Minikube | 🐢 2-5分钟 | 大 | ✅ | 需要完整 VM 隔离 |
| Docker Desktop | ⚡ 即开 | 小 | ❌ 单节点 | 只需要简单单节点 |
原理讲解
Kind 的工作原理
Kind 的每个"节点"实际上是一个 Docker 容器。容器里运行着完整的 K8s 组件:
#mermaid-svg-1BGT8N0UeYD5lwcP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1BGT8N0UeYD5lwcP .error-icon{fill:#552222;}#mermaid-svg-1BGT8N0UeYD5lwcP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1BGT8N0UeYD5lwcP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1BGT8N0UeYD5lwcP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1BGT8N0UeYD5lwcP .marker.cross{stroke:#333333;}#mermaid-svg-1BGT8N0UeYD5lwcP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1BGT8N0UeYD5lwcP p{margin:0;}#mermaid-svg-1BGT8N0UeYD5lwcP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP .cluster-label text{fill:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP .cluster-label span{color:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP .cluster-label span p{background-color:transparent;}#mermaid-svg-1BGT8N0UeYD5lwcP .label text,#mermaid-svg-1BGT8N0UeYD5lwcP span{fill:#333;color:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP .node rect,#mermaid-svg-1BGT8N0UeYD5lwcP .node circle,#mermaid-svg-1BGT8N0UeYD5lwcP .node ellipse,#mermaid-svg-1BGT8N0UeYD5lwcP .node polygon,#mermaid-svg-1BGT8N0UeYD5lwcP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1BGT8N0UeYD5lwcP .rough-node .label text,#mermaid-svg-1BGT8N0UeYD5lwcP .node .label text,#mermaid-svg-1BGT8N0UeYD5lwcP .image-shape .label,#mermaid-svg-1BGT8N0UeYD5lwcP .icon-shape .label{text-anchor:middle;}#mermaid-svg-1BGT8N0UeYD5lwcP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1BGT8N0UeYD5lwcP .rough-node .label,#mermaid-svg-1BGT8N0UeYD5lwcP .node .label,#mermaid-svg-1BGT8N0UeYD5lwcP .image-shape .label,#mermaid-svg-1BGT8N0UeYD5lwcP .icon-shape .label{text-align:center;}#mermaid-svg-1BGT8N0UeYD5lwcP .node.clickable{cursor:pointer;}#mermaid-svg-1BGT8N0UeYD5lwcP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1BGT8N0UeYD5lwcP .arrowheadPath{fill:#333333;}#mermaid-svg-1BGT8N0UeYD5lwcP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1BGT8N0UeYD5lwcP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1BGT8N0UeYD5lwcP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1BGT8N0UeYD5lwcP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1BGT8N0UeYD5lwcP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1BGT8N0UeYD5lwcP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1BGT8N0UeYD5lwcP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1BGT8N0UeYD5lwcP .cluster text{fill:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP .cluster span{color:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1BGT8N0UeYD5lwcP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1BGT8N0UeYD5lwcP rect.text{fill:none;stroke-width:0;}#mermaid-svg-1BGT8N0UeYD5lwcP .icon-shape,#mermaid-svg-1BGT8N0UeYD5lwcP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1BGT8N0UeYD5lwcP .icon-shape p,#mermaid-svg-1BGT8N0UeYD5lwcP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1BGT8N0UeYD5lwcP .icon-shape .label rect,#mermaid-svg-1BGT8N0UeYD5lwcP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1BGT8N0UeYD5lwcP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1BGT8N0UeYD5lwcP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1BGT8N0UeYD5lwcP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Kind Node (Docker 容器)
kube-apiserver
etcd
kube-scheduler
controller-manager
kubelet
kube-proxy
containerd
你的 Pod
这意味着你可以在一台电脑上创建多节点集群------每个节点就是一个容器。
前提条件
Kind 依赖 Docker。你需要先安装:
- Docker Desktop (macOS/Windows)或 Docker Engine(Linux)
- kubectl(K8s 命令行工具)
- Kind 本身
🪟 Windows 用户 :本文所有实验命令均为 Linux/macOS shell 语法。建议通过 WSL2 学习:
- 在 PowerShell(管理员)中执行
wsl --install,重启后进入 Ubuntu 终端- 安装 Docker Desktop,在 Settings → Resources → WSL Integration 中启用你的 Ubuntu 发行版
- 后续所有命令直接在 WSL2 Ubuntu 终端中执行(走下面的 Linux 路线即可)
动手实验
步骤 1:安装 Docker
macOS :从 docker.com 下载 Docker Desktop
Linux (Ubuntu):
bash
# 安装 Docker
sudo apt-get update
sudo apt-get install -y docker.io
sudo usermod -aG docker $USER
# 重新登录使 docker 组生效
验证:
bash
docker version
预期输出:
Client:
Version: 29.x.x
Server:
Version: 29.x.x
步骤 2:安装 kubectl
bash
# macOS
brew install kubectl
# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# 如果上面网络下载不了,试下换谷歌源
#curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -L -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
验证:
bash
kubectl version --client
预期输出:
Client Version: v1.31.0
Kustomize Version: v5.4.2
步骤 3:安装 Kind
bash
# macOS
brew install kind
# Linux
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64
[ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-arm64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
验证:
bash
kind version
预期输出:
kind v0.24.0 go1.22.6 linux/amd64
步骤 4:创建你的第一个集群
先创建配置文件(后续 Ingress 和 NodePort 实验需要端口映射):
bash
cat > kind-config.yaml << 'EOF'
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:v1.31.0
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- containerPort: 30080
hostPort: 30080
protocol: TCP
- role: worker
image: kindest/node:v1.31.0
- role: worker
image: kindest/node:v1.31.0
EOF
然后创建集群:
bash
kind create cluster --name k8s-guide --config kind-config.yaml
预期输出:
Creating cluster "k8s-guide" ...
✓ Ensuring node image (kindest/node:v1.31.0) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-k8s-guide"
You can now use your cluster with:
kubectl cluster-info --context kind-k8s-guide
Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/
步骤 5:验证集群
bash
kubectl get nodes
预期输出:
NAME STATUS ROLES AGE VERSION
k8s-guide-control-plane Ready control-plane 2m29s v1.31.0
k8s-guide-worker Ready <none> 85s v1.31.0
k8s-guide-worker2 Ready <none> 85s v1.31.0
bash
kubectl cluster-info
预期输出:
Kubernetes control plane is running at https://127.0.0.1:45819
CoreDNS is running at https://127.0.0.1:45819/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
🎉 恭喜!你有了一个运行中的 K8s 集群!
步骤 6:清理
实验完成后,删除集群:
bash
kind delete cluster --name k8s-guide
💡 如果你还想继续学习,先不要删!后面的文章会继续用这个集群。
自检问题
- Kind 集群的"节点"实际上是什么?
查看答案 是一个 Docker 容器。Kind 在 Docker 容器里运行完整的 K8s 组件(kubelet、kube-apiserver 等)。
- 为什么 Kind 比 Minikube 启动快?
查看答案 Kind 直接利用已有的 Docker 引擎创建容器,不需要启动完整的虚拟机。Minikube 默认需要启动一个 VM,所以更慢。
- kubectl 和 Kind 是什么关系?
查看答案 Kind 负责创建和管理集群,kubectl 负责与集群交互(部署应用、查看状态等)。Kind 创建集群后会自动配置 kubectl 的 context。
下一步
集群准备好了,让我们部署第一个应用:
→ 02. 工作负载:Pod、ReplicaSet 与 Deployment
📚 本文来自 K8s Guide ------ 开源免费的 Kubernetes 中文学习指南
- 🗺️ 初学者轨道 + 面试轨道,从零基础到拿 Offer 一站式覆盖
- 🧪 每篇文章配套 Kind 实验脚本,本地一键运行
- 🔗 本文源码:docs/beginner/01-what-is-k8s.md / docs/beginner/02-install-kind.md
⭐ 如果对你有帮助,欢迎 Star! github.com/callmebg/k8s-guide