容器编排的工业标准,从入门到生产实践
目录
- 什么是 Kubernetes?
- 核心概念与架构
- 安装与环境搭建
- 基本操作(kubectl)
- Pod
- Deployment
- Service
- ConfigMap 与 Secret
- 数据持久化(PV / PVC)
- Ingress
- Namespace
- 实战示例:部署完整 Web 应用
- 常见命令速查
- 总结
什么是 Kubernetes?
Kubernetes(简称 k8s )是 Google 开源的容器编排平台,用于自动化部署、扩缩容和管理容器化应用。
为什么需要 Kubernetes?
单机 Docker 能运行容器,但面对生产环境的挑战:
| 问题 | Kubernetes 的解决方案 |
|---|---|
| 容器崩溃怎么办? | 自动重启(自愈) |
| 流量激增如何扩容? | 水平自动扩缩(HPA) |
| 多台服务器如何调度? | 智能调度器 |
| 服务间如何通信? | 内置 Service 发现 |
| 如何做滚动更新? | 零停机发布 |
| 配置和密钥如何管理? | ConfigMap / Secret |
核心概念与架构
集群架构
arduino
┌─────────────────────────────────────────┐
│ Kubernetes 集群 │
│ │
│ ┌──────────────┐ ┌────────────────┐ │
│ │ Control │ │ Worker Node │ │
│ │ Plane │ │ │ │
│ │ │ │ ┌──────────┐ │ │
│ │ API Server │ │ │ Pod │ │ │
│ │ Scheduler │ │ │ [容器] │ │ │
│ │ etcd │ │ └──────────┘ │ │
│ │ Controller │ │ │ │
│ └──────────────┘ └────────────────┘ │
└─────────────────────────────────────────┘
核心组件
Control Plane(控制平面)
- API Server:集群的统一入口,所有操作都通过它
- Scheduler:决定 Pod 运行在哪个节点上
- Controller Manager:维护集群期望状态(如保证副本数)
- etcd:分布式键值数据库,存储集群所有状态
Worker Node(工作节点)
- kubelet:节点代理,负责管理 Pod 生命周期
- kube-proxy:维护网络规则,实现 Service 转发
- Container Runtime:容器运行时(如 containerd)
核心资源对象
| 对象 | 作用 |
|---|---|
| Pod | 最小部署单元,包含一个或多个容器 |
| Deployment | 管理 Pod 副本,支持滚动更新 |
| Service | 为 Pod 提供稳定的网络访问入口 |
| Ingress | 管理外部 HTTP/HTTPS 流量路由 |
| ConfigMap | 存储非敏感配置信息 |
| Secret | 存储敏感信息(密码、证书) |
| PersistentVolume | 持久化存储资源 |
| Namespace | 集群内的逻辑隔离空间 |
安装与环境搭建
本地开发:minikube(推荐入门)
bash
# macOS
brew install minikube
# 启动集群(单节点)
minikube start
# 查看集群状态
minikube status
# 打开 Dashboard
minikube dashboard
# 停止集群
minikube stop
本地开发:kind(用 Docker 模拟多节点)
perl
# 安装 kind
brew install kind # macOS
# 或
go install sigs.k8s.io/kind@latest
# 创建集群
kind create cluster --name my-cluster
# 删除集群
kind delete cluster --name my-cluster
安装 kubectl(集群管理命令行工具)
bash
# macOS
brew install kubectl
# Linux
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# 验证
kubectl version --client
配置集群访问
perl
# 查看当前配置
kubectl config view
# 查看所有上下文(集群)
kubectl config get-contexts
# 切换集群
kubectl config use-context my-cluster
基本操作(kubectl)
命令结构
xml
kubectl <动词> <资源类型> <资源名> [选项]
常用动词
perl
kubectl get # 查看资源
kubectl describe # 查看详细信息
kubectl apply # 创建或更新资源(推荐)
kubectl delete # 删除资源
kubectl logs # 查看容器日志
kubectl exec # 进入容器
kubectl port-forward # 端口转发
常用示例
perl
# 查看节点
kubectl get nodes
# 查看所有命名空间的 Pod
kubectl get pods -A
# 查看特定命名空间
kubectl get pods -n kube-system
# 实时监听变化
kubectl get pods -w
# 查看资源详情
kubectl describe pod my-pod
# 应用 YAML 配置
kubectl apply -f deployment.yaml
# 删除资源
kubectl delete -f deployment.yaml
kubectl delete pod my-pod
Pod
Pod 是 Kubernetes 中最小的调度单元,通常包含一个主容器(有时也有 sidecar 辅助容器)。
创建 Pod(pod.yaml)
yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
perl
# 创建
kubectl apply -f pod.yaml
# 查看
kubectl get pod my-pod
# 查看日志
kubectl logs my-pod
# 进入容器
kubectl exec -it my-pod -- bash
# 端口转发(本地访问)
kubectl port-forward pod/my-pod 8080:80
⚠️ 生产中不直接使用裸 Pod,应使用 Deployment 管理。
Deployment
Deployment 是最常用的工作负载对象,负责声明式管理 Pod 副本,支持滚动更新和回滚。
deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # 副本数
selector:
matchLabels:
app: nginx
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新时最多多创建 1 个 Pod
maxUnavailable: 0 # 更新时最多 0 个 Pod 不可用
template: # Pod 模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
readinessProbe: # 就绪探针
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe: # 存活探针
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
Deployment 操作
bash
# 部署
kubectl apply -f deployment.yaml
# 查看状态
kubectl get deployment nginx-deployment
kubectl rollout status deployment/nginx-deployment
# 扩缩容
kubectl scale deployment nginx-deployment --replicas=5
# 更新镜像(触发滚动更新)
kubectl set image deployment/nginx-deployment nginx=nginx:1.26
# 查看更新历史
kubectl rollout history deployment/nginx-deployment
# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment
# 回滚到指定版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2
Service
Service 为一组 Pod 提供稳定的网络访问入口,即使 Pod IP 变化,Service IP 保持不变。
Service 类型
| 类型 | 说明 |
|---|---|
ClusterIP |
默认,仅集群内部访问 |
NodePort |
通过节点 IP + 端口从外部访问 |
LoadBalancer |
云厂商负载均衡器(AWS/GCP/阿里云) |
ExternalName |
映射到外部 DNS 名称 |
service.yaml
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # 选择带此标签的 Pod
type: ClusterIP
ports:
- protocol: TCP
port: 80 # Service 端口
targetPort: 80 # Pod 端口
NodePort 示例
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
selector:
app: nginx
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080 # 范围 30000-32767
csharp
kubectl apply -f service.yaml
kubectl get service nginx-service
# 本地访问(minikube)
minikube service nginx-nodeport --url
ConfigMap 与 Secret
ConfigMap(非敏感配置)
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: production
LOG_LEVEL: info
config.yaml: |
server:
port: 8080
timeout: 30s
Secret(敏感数据)
ini
# 命令行创建(值会自动 base64 编码)
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=S3cr3t!
yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64(admin)
password: UzNjcjN0IQ== # base64(S3cr3t!)
在 Pod 中使用
yaml
spec:
containers:
- name: app
image: my-app:latest
env:
# 从 ConfigMap 注入环境变量
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
# 从 Secret 注入环境变量
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
volumeMounts:
# 将 ConfigMap 挂载为文件
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
数据持久化(PV / PVC)
概念
- PersistentVolume (PV) :集群管理员预先创建的存储资源
- PersistentVolumeClaim (PVC) :用户申请存储的请求
- StorageClass:动态创建 PV 的模板
PVC 示例
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce # 单节点读写
storageClassName: standard
resources:
requests:
storage: 5Gi
在 Pod 中挂载 PVC
yaml
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: data
mountPath: /app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: my-pvc
arduino
kubectl get pv
kubectl get pvc
Ingress
Ingress 管理外部 HTTP/HTTPS 流量如何路由到集群内的 Service,是生产环境暴露服务的标准方式。
安装 Ingress Controller(以 nginx 为例)
ruby
# minikube
minikube addons enable ingress
# 通用
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
ingress.yaml
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
tls:
- hosts:
- app.example.com
secretName: tls-secret # TLS 证书 Secret
Namespace
Namespace 提供集群内的逻辑隔离,适合多团队、多环境(dev/staging/prod)共用一个集群。
arduino
# 创建 namespace
kubectl create namespace dev
kubectl create namespace production
# 在指定 namespace 部署
kubectl apply -f deployment.yaml -n dev
# 查看某 namespace 下的资源
kubectl get all -n dev
# 设置默认 namespace(避免每次 -n)
kubectl config set-context --current --namespace=dev
实战示例:部署完整 Web 应用
部署一个包含前端、后端 API 和数据库的完整应用。
文件结构
arduino
k8s/
├── namespace.yaml
├── configmap.yaml
├── secret.yaml
├── postgres/
│ ├── pvc.yaml
│ ├── deployment.yaml
│ └── service.yaml
├── api/
│ ├── deployment.yaml
│ └── service.yaml
└── ingress.yaml
namespace.yaml
vbnet
apiVersion: v1
kind: Namespace
metadata:
name: myapp
postgres/pvc.yaml
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: myapp
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
postgres/deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: myapp
spec:
selector:
app: postgres
ports:
- port: 5432
api/deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: myapp
spec:
replicas: 2
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: my-api:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: "postgresql://postgres:5432/mydb"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
---
apiVersion: v1
kind: Service
metadata:
name: api
namespace: myapp
spec:
selector:
app: api
ports:
- port: 8080
部署步骤
csharp
# 1. 创建命名空间
kubectl apply -f namespace.yaml
# 2. 创建 Secret
kubectl create secret generic db-secret \
--from-literal=password=MyP@ssw0rd \
-n myapp
# 3. 按顺序部署
kubectl apply -f postgres/
kubectl apply -f api/
kubectl apply -f ingress.yaml
# 4. 查看所有资源状态
kubectl get all -n myapp
# 5. 查看 Ingress
kubectl get ingress -n myapp
常见命令速查
bash
# ── 查看资源 ──────────────────────────────────
kubectl get nodes
kubectl get pods -A
kubectl get deploy,svc,ingress -n myapp
kubectl get all -n myapp
# ── 调试 ──────────────────────────────────────
kubectl describe pod <pod-name> -n myapp
kubectl logs <pod-name> -n myapp
kubectl logs <pod-name> -c <container> --previous # 查看上次崩溃日志
kubectl exec -it <pod-name> -n myapp -- bash
kubectl port-forward svc/api 8080:8080 -n myapp
# ── 更新与回滚 ─────────────────────────────────
kubectl set image deploy/api api=my-api:v2 -n myapp
kubectl rollout status deploy/api -n myapp
kubectl rollout undo deploy/api -n myapp
# ── 扩缩容 ─────────────────────────────────────
kubectl scale deploy/api --replicas=5 -n myapp
# ── 资源使用情况 ───────────────────────────────
kubectl top nodes
kubectl top pods -n myapp
# ── 强制删除卡住的 Pod ─────────────────────────
kubectl delete pod <pod-name> --grace-period=0 --force -n myapp
# ── 导出当前配置 ───────────────────────────────
kubectl get deploy api -n myapp -o yaml > api-backup.yaml
总结
| 场景 | 使用的资源 |
|---|---|
| 运行应用 | Deployment + Pod |
| 内部服务通信 | Service (ClusterIP) |
| 对外暴露服务 | Ingress / Service (LoadBalancer) |
| 非敏感配置 | ConfigMap |
| 密码/证书 | Secret |
| 持久化存储 | PVC + PV |
| 环境隔离 | Namespace |
学习路线
markdown
Docker 基础
↓
kubectl 基本操作
↓
Deployment + Service
↓
ConfigMap / Secret / PVC
↓
Ingress + 多环境管理
↓
Helm(包管理)
↓
监控(Prometheus + Grafana)
↓
服务网格(Istio)
Happy Orchestrating! ☸️