Kubernetes 基础与实战
概述
Kubernetes(简称 K8s)是一个开源的容器编排平台,用于自动部署、扩展和管理容器化应用。本文档涵盖 K8s 核心架构、Pod、Deployment、Service、Ingress、配置管理及常用命令,帮助快速掌握 K8s 基础操作。
一、K8s 架构
Kubernetes 集群由控制平面(Control Plane) 和工作节点(Worker Node) 组成。
1.1 控制平面组件
控制平面负责集群的全局决策和状态管理,通常部署在独立的 Master 节点上。
kube-apiserver
API 服务器是整个集群的入口,所有组件和用户的交互请求都通过 apiserver 处理。它负责认证、授权、准入控制和 RESTful API 的暴露。
# 查看 apiserver 状态
kubectl get componentstatuses
# 或
kubectl get csetcd
etcd 是一个高可用的分布式键值存储,Kubernetes 使用它来持久化所有集群数据(配置、状态、元数据)。它是集群的"唯一数据源"。
- 默认使用 2379 端口
- 建议定期备份 etcd 快照
- 生产环境推荐 3/5/7 节点奇数部署
kube-scheduler
调度器负责将新创建的 Pod 分配到合适的 Node 上。调度过程分为两个阶段:
- 过滤(Predicates):筛选出满足 Pod 资源需求的节点
- 打分(Priorities):对满足条件的节点进行优先级排序,选择最优节点
调度考量因素包括:资源请求、节点亲和性、污点容忍、数据局部性等。
kube-controller-manager
控制器管理器运行多个核心控制器,确保集群实际状态与期望状态一致。重要的控制器包括:
- Node Controller:监控节点健康状态
- Deployment Controller:管理 Deployment 的扩缩容和滚动更新
- ReplicaSet Controller:确保指定数量的 Pod 副本运行
- Endpoint Controller:维护 Service 与 Pod 的映射关系
- Namespace Controller:管理命名空间的生命周期
1.2 工作节点组件
工作节点是运行容器化应用的实际机器。
kubelet
kubelet 是运行在每个节点上的代理进程,负责:
- 接收控制平面下发的 Pod 定义
- 确保 Pod 中的容器正常运行
- 定期向 apiserver 上报节点和 Pod 状态
- 执行存活性探针(livenessProbe)和就绪性探针(readinessProbe)
kube-proxy
kube-proxy 维护节点上的网络规则,实现 Service 的负载均衡和流量转发。支持三种模式:
- iptables 模式(默认):通过 iptables 规则实现 NAT 转发
- IPVS 模式:使用内核 IPVS 模块,性能更高,支持更多负载均衡算法
- userspace 模式:用户态代理,性能较低,已基本弃用
容器运行时
容器运行时负责真正运行和管理容器。Kubernetes 通过 CRI(Container Runtime Interface)与运行时交互。
- containerd:Docker 剥离出的核心容器运行时,生产推荐
- CRI-O:专为 Kubernetes 开发的轻量运行时
- Docker Engine:Kubernetes 1.24+ 已弃用 Docker 作为默认运行时
# 查看节点信息
kubectl get nodes -o wide
# 查看节点详情
kubectl describe node <node-name>二、Pod 核心
Pod 是 Kubernetes 中最小的调度和部署单元,一个 Pod 可以包含一个或多个共享网络和存储资源的容器。
2.1 Pod 定义文件
以下是一个最基本的 Pod YAML 定义:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
env: dev
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"# 创建 Pod
kubectl apply -f pod.yaml
# 查看 Pod
kubectl get pods
# 查看 Pod 详细信息
kubectl get pod nginx-pod -o yaml
# 查看 Pod 描述
kubectl describe pod nginx-pod
# 删除 Pod
kubectl delete pod nginx-pod2.2 多容器 Pod
一个 Pod 中可以运行多个容器,它们共享同一个网络命名空间和存储卷。典型的场景是 Sidecar 模式——主容器负责业务逻辑,Sidecar 容器负责日志收集、代理转发等辅助功能。
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
labels:
app: web
spec:
containers:
- name: app
image: nginx:1.25-alpine
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
- name: sidecar
image: busybox:1.36
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}2.3 Init 容器
Init 容器在主容器启动之前运行,用于执行初始化任务。它们按顺序执行,只有所有 Init 容器成功完成后才会启动主容器。
apiVersion: v1
kind: Pod
metadata:
name: init-container-pod
spec:
initContainers:
- name: init-myservice
image: busybox:1.36
command: ["sh", "-c", "until nslookup myservice; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.36
command: ["sh", "-c", "until nslookup mydb; do echo waiting for mydb; sleep 2; done"]
containers:
- name: app
image: nginx:1.25-alpineInit 容器的关键特性:
- 每个 Init 容器必须成功退出后下一个才能启动
- 如果 Init 容器失败,Kubernetes 会根据 Pod 的
restartPolicy决定是否重启 - Init 容器支持资源限制,但与主容器的资源配额分开计算
- 修改 Init 容器的镜像会导致 Pod 重启
2.4 静态 Pod
静态 Pod 是由 kubelet 直接管理而非通过 apiserver 创建的 Pod。kubelet 会监视指定目录下的 Pod 清单文件。
# 放在 /etc/kubernetes/manifests/ 目录下的 YAML 文件会被 kubelet 自动创建为静态 Pod
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: web
spec:
containers:
- name: web
image: nginx:1.25-alpine
ports:
- containerPort: 80静态 Pod 的特点:
- 由 kubelet 直接管理,不依赖 apiserver
- kubelet 会在 apiserver 上创建对应的镜像 Pod(只读)
- 常用于部署控制平面组件(如 kube-apiserver、etcd)
- 删除静态 Pod 需要删除对应目录下的清单文件
# 查看静态 Pod(名称通常会带有节点名的后缀)
kubectl get pods --all-namespaces | grep static2.5 Pod 生命周期与状态
Pod 从创建到终止经历以下阶段:
| 状态 | 说明 |
|---|---|
| Pending | Pod 已被集群接受,但容器尚未全部创建完成。可能原因:镜像拉取中、调度等待资源 |
| Running | Pod 中的所有容器都已创建,且至少有一个容器正在运行 |
| Succeeded | Pod 中的所有容器都已成功终止且不会再重启(适用于 Job 类任务) |
| Failed | Pod 中的所有容器都已终止,且至少有一个容器以非零状态退出 |
| CrashLoopBackOff | 容器反复启动后崩溃,kubelet 正在以递增的间隔等待重试 |
| Unknown | 无法获取 Pod 状态,通常意味着节点与 apiserver 通信异常 |
# 查看 Pod 状态
kubectl get pods -w
# 查看 Pod 事件
kubectl describe pod <pod-name>
# 查看容器日志(排查 CrashLoopBackOff)
kubectl logs <pod-name> --previous2.6 重启策略
Pod 的 restartPolicy 决定容器退出后的行为:
| 策略 | 行为 |
|---|---|
| Always | 容器退出后总是重启,适用于长期运行的服务(默认值) |
| OnFailure | 仅在容器以非零退出码退出时重启 |
| Never | 从不自动重启容器 |
apiVersion: v1
kind: Pod
metadata:
name: restart-demo
spec:
restartPolicy: OnFailure
containers:
- name: busybox
image: busybox:1.36
command: ["sh", "-c", "exit 1"]三、Deployment
Deployment 是管理无状态应用的更高级抽象,它通过 ReplicaSet 管理 Pod 的副本数量,提供声明式更新、滚动升级、回滚和水平扩缩容能力。
3.1 声明式更新
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"# 创建 Deployment
kubectl apply -f deployment.yaml
# 更新镜像版本(触发滚动更新)
kubectl set image deployment/nginx-deployment nginx=nginx:1.26-alpine
# 查看更新状态
kubectl rollout status deployment/nginx-deployment
# 查看 Deployment 详情
kubectl describe deployment nginx-deployment3.2 滚动更新策略
滚动更新通过逐步替换旧 Pod 来实现零停机部署。关键参数在 spec.strategy.rollingUpdate 中配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine- maxSurge:更新过程中允许超出期望副本数的最大 Pod 数量。可以是绝对数字或百分比(默认 25%)。例如
replicas=5, maxSurge=1表示最多同时运行 6 个 Pod。 - maxUnavailable:更新过程中允许不可用 Pod 的最大数量。可以是绝对数字或百分比(默认 25%)。例如
replicas=5, maxUnavailable=1表示最少保证 4 个 Pod 可用。
配置建议:
- 对可用性要求高的服务:
maxSurge=1, maxUnavailable=0(逐个创建新 Pod,确保旧 Pod 全部可用) - 对资源敏感的场景:
maxSurge=0, maxUnavailable=1(先销毁一个旧 Pod,再创建新 Pod)
3.3 回滚
当更新出现问题时,可以快速回滚到之前的版本。
# 查看 Deployment 历史版本
kubectl rollout history deployment/nginx-deployment
# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment
# 回滚到指定版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2
# 暂停和恢复滚动更新
kubectl rollout pause deployment/nginx-deployment
kubectl rollout resume deployment/nginx-deployment注意:回滚操作会创建新的 ReplicaSet 版本,--to-revision 指向的是历史版本号。
3.4 水平扩缩
# 手动扩缩容
kubectl scale deployment nginx-deployment --replicas=5
# 通过 YAML 更新副本数
kubectl apply -f deployment.yaml # 修改 replicas 后执行
# 自动扩缩容(需安装 metrics-server)
kubectl autoscale deployment nginx-deployment --min=3 --max=10 --cpu-percent=80
# 查看 HPA 状态
kubectl get hpa四、Service
Service 提供了一种稳定的网络访问入口,将一组 Pod 暴露为网络服务。无论 Pod 如何创建和销毁,Service 提供一个固定的虚拟 IP(ClusterIP)和 DNS 名称。
4.1 类型对比
Kubernetes 支持四种 Service 类型:
| 类型 | 访问范围 | 说明 |
|---|---|---|
| ClusterIP | 集群内部 | 默认类型,提供一个集群内可访问的虚拟 IP,外部无法访问 |
| NodePort | 集群外部 | 在每个节点上开放一个端口(30000-32767),通过 NodeIP:NodePort 访问 |
| LoadBalancer | 外部 | 在 NodePort 基础上,自动配置云厂商的负载均衡器 |
| ExternalName | 外部 | 通过 DNS CNAME 将 Service 映射到外部域名 |
4.2 ClusterIP
ClusterIP 是默认的 Service 类型,仅在集群内部可访问。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 804.3 NodePort
NodePort 在每个节点上开放一个固定端口,外部可以通过任意节点的 IP 加端口访问。
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080# 访问方式(任意节点 IP + 端口)
curl http://192.168.1.10:300804.4 LoadBalancer
LoadBalancer 在 NodePort 的基础上自动为云环境创建外部负载均衡器。
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80# 查看外部 IP
kubectl get svc nginx-lb
# 本地开发环境(如 minikube)可通过隧道访问
minikube service nginx-lb4.5 ExternalName
ExternalName 将 Service 映射到外部的 DNS 名称,不创建路由规则。
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: database.example.com集群内的 Pod 可以通过 external-db.default.svc.cluster.local 访问外部的 database.example.com。
4.6 Selector 标签选择
Service 通过 spec.selector 匹配 Pod 的标签,决定将流量转发到哪些 Pod。
# Service 选择器
selector:
app: nginx
env: prod匹配规则:
- 等值匹配:
app=nginx匹配所有包含该标签的 Pod - 多标签匹配:
app=nginx, env=prod必须同时匹配所有标签(AND 逻辑) - 无选择器:不指定 selector 的 Service 可以手动管理 Endpoints
# 无选择器的 Service,用于关联外部服务
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
ports:
- port: 80
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-service
subsets:
- addresses:
- ip: 10.0.0.1
- ip: 10.0.0.2
ports:
- port: 80五、Ingress
Ingress 提供 HTTP/HTTPS 路由功能,将外部请求转发到集群内的 Service。Ingress 需要配合 Ingress Controller 才能工作。
5.1 nginx-ingress 控制器安装
使用 Helm 安装 nginx-ingress-controller:
# 添加 Helm 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# 安装 ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.service.type=NodePort
# 验证安装
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx5.2 路径路由
Ingress 可以将不同路径的请求转发到不同的 Service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: default-service
port:
number: 805.3 虚拟主机
Ingress 支持基于域名(虚拟主机)的路由,将不同域名的请求转发到不同的 Service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: virtual-host-ingress
spec:
ingressClassName: nginx
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 805.4 HTTPS 配置
通过 TLS Secret 为 Ingress 配置 HTTPS:
# 创建 TLS Secret(使用自签名证书或已有证书)
kubectl create secret tls example-tls \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
--namespace defaultapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: https-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: example-tls
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80TLS 配置要点:
tls字段中hosts列表需要与rules中的host对应secretName指向一个包含tls.crt和tls.key的 Secret- 如果使用 Let's Encrypt,可以安装 cert-manager 自动管理证书
六、ConfigMap & Secret
ConfigMap 和 Secret 用于将配置信息与 Pod 解耦,实现配置的集中管理和动态注入。
6.1 ConfigMap
创建方式
字面量创建:
kubectl create configmap app-config \
--from-literal=APP_ENV=production \
--from-literal=APP_LOG_LEVEL=info从文件创建:
# 从单个文件创建(文件名作为 key)
kubectl create configmap nginx-config --from-file=nginx.conf
# 从目录创建
kubectl create configmap app-config --from-file=config/
# 从 .env 文件创建
kubectl create configmap env-config --from-env-file=.envYAML 声明式创建:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: production
APP_LOG_LEVEL: info
nginx.conf: |
server {
listen 80;
server_name example.com;
}6.2 Secret
Secret 与 ConfigMap 类似,但数据以 Base64 编码存储,适合保存敏感信息。
# 字面量创建
kubectl create secret generic db-secret \
--from-literal=DB_USER=admin \
--from-literal=DB_PASSWORD=S3cretP@ss
# 从文件创建
kubectl create secret generic tls-secret \
--from-file=tls.crt \
--from-file=tls.key
# 从 .env 文件创建
kubectl create secret generic app-secret --from-env-file=secret.envYAML 声明式创建:
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
DB_USER: YWRtaW4= # echo -n "admin" | base64
DB_PASSWORD: UzNDcmV0UEBzcw== # echo -n "S3cretP@ss" | base64
---
# 使用 stringData 可写入明文,Kubernetes 会自动编码
apiVersion: v1
kind: Secret
metadata:
name: db-secret-plain
type: Opaque
stringData:
DB_USER: admin
DB_PASSWORD: S3cretP@ss6.3 Pod 挂载方式
环境变量方式
apiVersion: v1
kind: Pod
metadata:
name: config-pod
spec:
containers:
- name: app
image: nginx:1.25-alpine
env:
# 从 ConfigMap 取值
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
# 从 Secret 取值
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-secret
key: DB_USER
envFrom:
# 批量注入 ConfigMap 所有键值对
- configMapRef:
name: app-config
# 批量注入 Secret 所有键值对
- secretRef:
name: db-secret卷挂载方式
apiVersion: v1
kind: Pod
metadata:
name: volume-pod
spec:
containers:
- name: app
image: nginx:1.25-alpine
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
- name: secret-volume
mountPath: /etc/secret
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
- name: secret-volume
secret:
secretName: db-secret挂载为卷时,ConfigMap 和 Secret 的每个 key 会以文件形式呈现,文件内容是对应的 value。Secret 的文件内容仍为明文而非 Base64。
6.4 不可变配置
Kubernetes 1.21+ 支持将 ConfigMap 和 Secret 标记为不可变,以提高性能并防止意外修改:
apiVersion: v1
kind: ConfigMap
metadata:
name: immutable-config
data:
APP_ENV: production
immutable: true
---
apiVersion: v1
kind: Secret
metadata:
name: immutable-secret
type: Opaque
data:
API_KEY: YWJjZGVmMTIzNDU2
immutable: true不可变配置的优势:
- 减轻 apiserver 压力,无需监视变更
- 防止配置被意外修改导致服务异常
- 更改不可变配置需要删除并重新创建资源
七、常用命令速查表
基础操作
# 查看资源
kubectl get pods # 查看 Pod
kubectl get pods -o wide # 查看 Pod 详细信息(含节点 IP)
kubectl get pods --all-namespaces # 查看所有命名空间的 Pod
kubectl get deployments # 查看 Deployment
kubectl get services # 查看 Service
kubectl get nodes # 查看节点
kubectl get namespaces # 查看命名空间
# 查看详情
kubectl describe pod <pod-name> # Pod 详细信息
kubectl describe node <node-name> # 节点详细信息
kubectl describe svc <service-name> # Service 详细信息
# 查看日志
kubectl logs <pod-name> # 查看 Pod 日志
kubectl logs <pod-name> -c <container> # 查看指定容器日志
kubectl logs <pod-name> --previous # 查看上次崩溃的容器日志
kubectl logs -f <pod-name> # 实时跟踪日志
# 进入容器
kubectl exec -it <pod-name> -- /bin/sh # 进入 Pod 的默认容器
kubectl exec -it <pod-name> -c <container> -- /bin/sh # 进入指定容器
# 资源操作
kubectl apply -f <file.yaml> # 创建/更新资源
kubectl delete -f <file.yaml> # 删除资源
kubectl delete pod <pod-name> # 删除 Pod
kubectl delete pod --all # 删除当前命名空间所有 Pod
# 集群管理
kubectl top nodes # 查看节点资源使用
kubectl top pods # 查看 Pod 资源使用
kubectl cluster-info # 查看集群信息
kubectl api-resources # 查看所有 API 资源标签与选择器
# 标签操作
kubectl label pods <pod-name> env=prod # 添加标签
kubectl label pods <pod-name> env- # 删除标签
# 选择器过滤
kubectl get pods -l app=nginx # 等值选择
kubectl get pods -l 'app=nginx,env=prod' # 多条件选择(AND)
kubectl get pods -l 'app in (nginx,redis)' # 集合选择
# 注解(标签不限制字符长度,适合存储非标识性信息)
kubectl annotate pods <pod-name> description="my app annotation"命名空间
# 命名空间操作
kubectl get namespaces # 查看所有命名空间
kubectl get pods -n <namespace> # 指定命名空间查看
kubectl create namespace <name> # 创建命名空间
kubectl delete namespace <name> # 删除命名空间
# 设置默认命名空间
kubectl config set-context --current --namespace=<name>调试与排查
# 事件排查
kubectl get events # 查看集群事件
kubectl get events --sort-by='.lastTimestamp' # 按时间排序
kubectl get events -w # 实时监控事件
# 临时调试 Pod
# 在集群中启动一个临时 Pod 用于调试
kubectl run debug-pod --image=busybox:1.36 -it --rm -- /bin/sh
# 端口转发(将本地端口转发到 Pod)
kubectl port-forward pod/<pod-name> 8080:80
# 复制文件
kubectl cp <pod-name>:/path/to/file ./local-file # 从 Pod 复制到本地
kubectl cp ./local-file <pod-name>:/path/to/file # 从本地复制到 PodYAML 生成技巧
# 使用 dry-run 生成 YAML 模板
kubectl create deployment nginx --image=nginx:1.25-alpine --dry-run=client -o yaml
kubectl create service clusterip my-svc --tcp=80:80 --dry-run=client -o yaml
# 查看已有资源的 YAML
kubectl get pod <pod-name> -o yaml
# 导出资源定义(不含状态等运行时信息)
kubectl get pod <pod-name> -o yaml --export总结
本文覆盖了 Kubernetes 的核心基础概念和操作实践。掌握这些内容后,可以进一步深入学习存储卷(PV/PVC)、网络策略(NetworkPolicy)、RBAC 权限控制、HPA 自动伸缩、Helm Chart 包管理等进阶主题。