写在前面
在上一篇文章中,我们深入学习了Pod和Label的概念。Pod虽然是Kubernetes最小的调度单元,但在实际生产环境中,我们很少直接管理Pod,而是使用更高级的控制器来管理。Deployment是Kubernetes中最常用的控制器,用于管理无状态应用;Service则提供了服务发现和负载均衡能力;Namespace实现了资源的逻辑隔离。
这篇文章将详细讲解Deployment、Service和Namespace这三个核心对象,帮助你理解Kubernetes如何管理应用的部署、服务发现和资源隔离。
一、Deployment:无状态应用管理
1.1 Deployment的概念
Deployment是Kubernetes中最常用的控制器,用于管理无状态应用。它提供了声明式的更新能力,可以确保Pod按照期望的状态运行。
┌─────────────────────────────────────────────────────────────────────────┐
│ Deployment管理层次结构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Deployment │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ 期望状态(Desired State) ││ │
│ │ │ - 副本数:3 ││ │
│ │ │ - 镜像:nginx:1.21 ││ │
│ │ │ - 标签选择器:app=nginx ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ ReplicaSet ││ │
│ │ │ ┌───────────────────────────────────────────────────────┐ ││ │
│ │ │ │ 管理Pod副本 │ ││ │
│ │ │ │ - 确保Pod数量符合期望 │ ││ │
│ │ │ │ - 创建/删除Pod以匹配期望状态 │ ││ │
│ │ │ └───────────────────────────────────────────────────────┘ ││ │
│ │ │ │ ││ │
│ │ │ ▼ ││ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │
│ │ │ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │ ││ │
│ │ │ │ nginx │ │ nginx │ │ nginx │ ││ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ Deployment管理ReplicaSet,ReplicaSet管理Pod │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Deployment的核心功能:
- 副本管理:确保指定数量的Pod副本始终运行
- 滚动更新:支持渐进式更新应用版本
- 回滚能力:可以回滚到之前的版本
- 扩缩容:支持手动和自动扩缩容
1.2 Deployment的YAML定义
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
labels:
app: nginx
spec:
# 副本数
replicas: 3
# 标签选择器
selector:
matchLabels:
app: nginx
# Pod模板
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
# 滚动更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多可以超出期望副本数的数量
maxUnavailable: 1 # 最多不可用的副本数
# 历史版本保留数量
revisionHistoryLimit: 10
# 最小就绪时间
minReadySeconds: 5
# 进度截止时间
progressDeadlineSeconds: 600
1.3 创建和管理Deployment
创建Deployment:
# 使用命令行创建
kubectl create deployment nginx --image=nginx:1.21 --replicas=3
# 使用YAML文件创建
kubectl apply -f nginx-deployment.yaml
# 查看Deployment
kubectl get deployments
# 查看Deployment详情
kubectl describe deployment nginx-deployment
# 查看Deployment的Pod
kubectl get pods -l app=nginx
扩缩容:
# 手动扩容到5个副本
kubectl scale deployment nginx --replicas=5
# 基于CPU使用率自动扩缩容
kubectl autoscale deployment nginx --min=2 --max=10 --cpu-percent=80
# 查看HPA状态
kubectl get hpa
更新镜像:
# 更新镜像版本
kubectl set image deployment/nginx nginx=nginx:1.22
# 查看更新状态
kubectl rollout status deployment/nginx
# 查看更新历史
kubectl rollout history deployment/nginx
# 查看特定版本详情
kubectl rollout history deployment/nginx --revision=2
回滚:
# 回滚到上一版本
kubectl rollout undo deployment/nginx
# 回滚到指定版本
kubectl rollout undo deployment/nginx --revision=1
# 查看回滚状态
kubectl rollout status deployment/nginx
1.4 滚动更新策略
Deployment支持两种更新策略:
RollingUpdate(滚动更新):默认策略,渐进式更新Pod。
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 可以超出期望副本数的最大数量(可以是数字或百分比)
maxUnavailable: 1 # 不可用副本的最大数量(可以是数字或百分比)
Recreate(重建):先删除所有旧Pod,再创建新Pod。
spec:
strategy:
type: Recreate
┌─────────────────────────────────────────────────────────────────────────┐
│ 滚动更新过程示意图 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 初始状态(3个v1副本): │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod v1 │ │ Pod v1 │ │ Pod v1 │ │
│ │ :80 │ │ :80 │ │ :80 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 步骤1:创建1个v2副本(maxSurge=1) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod v1 │ │ Pod v1 │ │ Pod v1 │ │ Pod v2 │ │
│ │ :80 │ │ :80 │ │ :80 │ │ :80 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 步骤2:删除1个v1副本(maxUnavailable=1) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod v1 │ │ Pod v1 │ │ Pod v2 │ │
│ │ :80 │ │ :80 │ │ :80 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 步骤3:继续创建v2副本... │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod v1 │ │ Pod v1 │ │ Pod v2 │ │ Pod v2 │ │
│ │ :80 │ │ :80 │ │ :80 │ │ :80 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 最终状态(3个v2副本): │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod v2 │ │ Pod v2 │ │ Pod v2 │ │
│ │ :80 │ │ :80 │ │ :80 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
1.5 Deployment状态
Deployment有以下几种状态:
|-------------|----------------------------|
| 状态类型 | 说明 |
| Progressing | Deployment正在创建新的ReplicaSet |
| Complete | 所有副本都已更新完成 |
| Failed | 更新过程中出现错误 |
| Paused | 暂停更新 |
查看Deployment状态:
# 查看Deployment状态
kubectl get deployment nginx -o wide
# 查看Deployment条件
kubectl describe deployment nginx | grep -A 5 Conditions
# 查看ReplicaSet
kubectl get rs -l app=nginx
二、Service:服务发现与负载均衡
2.1 Service的概念
Service是Kubernetes中定义服务抽象的对象,它定义了一组Pod的逻辑集合和访问策略。Service提供了稳定的服务入口,客户端不需要关心后端Pod的变化。
┌─────────────────────────────────────────────────────────────────────────┐
│ Service工作原理 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 客户端请求 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Service │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ ClusterIP: 10.96.0.1 ││ │
│ │ │ Port: 80 ││ │
│ │ │ Selector: app=nginx ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐│ │
│ │ │ Endpoints ││ │
│ │ │ - 10.244.1.5:80 ││ │
│ │ │ - 10.244.1.6:80 ││ │
│ │ │ - 10.244.2.3:80 ││ │
│ │ └─────────────────────────────────────────────────────────────┘│ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │
│ │ IP: 10.244.1.5 │ │ IP: 10.244.1.6 │ │ IP: 10.244.2.3 │
│ │ Label: app=nginx │ │ Label: app=nginx │ │ Label: app=nginx │
│ └─────────────────────┘ └─────────────────────┘ └─────────────────────┘
│ │
│ Service通过Selector找到匹配的Pod,将流量负载均衡到这些Pod │
│ │
└─────────────────────────────────────────────────────────────────────────┘
2.2 Service类型
Kubernetes支持四种Service类型:
|--------------|-----------------|-----------|
| 类型 | 说明 | 使用场景 |
| ClusterIP | 集群内部IP,只能在集群内访问 | 内部服务、数据库 |
| NodePort | 在每个节点上开放端口 | 开发测试、外部访问 |
| LoadBalancer | 云厂商提供的负载均衡器 | 生产环境、外部访问 |
| ExternalName | 映射到外部DNS名称 | 访问外部服务 |
┌─────────────────────────────────────────────────────────────────────────┐
│ Service类型对比 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ClusterIP(默认类型): │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 集群内部 │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 客户端 │────────▶│ Service │───▶ Pods │ │
│ │ └─────────┘ │ClusterIP│ │ │
│ │ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ NodePort: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 外部 │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 客户端 │────────▶│ Node │────────▶│ Service │───▶ Pods │ │
│ │ └─────────┘ │:30080 │ │ClusterIP│ │ │
│ │ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ LoadBalancer: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 外部 │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 客户端 │────────▶│ 云LB │────────▶│ Service │───▶ Pods │ │
│ │ └─────────┘ │ 公网IP │ │NodePort │ │ │
│ │ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
2.3 Service的YAML定义
ClusterIP类型:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: default
spec:
type: ClusterIP # 服务类型
selector:
app: nginx # Pod选择器
ports:
- name: http
port: 80 # Service端口
targetPort: 80 # Pod端口
protocol: TCP
NodePort类型:
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- name: http
port: 80 # Service端口
targetPort: 80 # Pod端口
nodePort: 30080 # 节点端口(范围:30000-32767)
protocol: TCP
LoadBalancer类型:
apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer
annotations:
# 云厂商特定注解
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
ExternalName类型:
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: ExternalName
externalName: external.example.com
2.4 Service的端口配置
spec:
ports:
# 单端口配置
- port: 80 # Service暴露的端口
targetPort: 8080 # Pod容器端口
protocol: TCP # 协议(TCP/UDP/SCTP)
name: http # 端口名称
# 多端口配置
- port: 80
targetPort: 8080
name: http
- port: 443
targetPort: 8443
name: https
# 使用端口号名称
- port: 80
targetPort: http # 引用容器定义中的端口名称
2.5 Service的流量策略
spec:
# 内部流量策略
internalTrafficPolicy: Local # Local或Cluster
# Local:只转发到本节点的Pod
# Cluster:转发到所有节点的Pod(默认)
# 外部流量策略
externalTrafficPolicy: Local # Local或Cluster
# Local:保留客户端源IP,只转发到本节点Pod
# Cluster:分发到所有节点Pod,源IP被SNAT
2.6 Service管理命令
# 创建Service
kubectl expose deployment nginx --port=80 --target-port=80
# 查看Service
kubectl get services
kubectl get svc
# 查看Service详情
kubectl describe service nginx-service
# 查看Endpoints
kubectl get endpoints nginx-service
# 查看Service的ClusterIP
kubectl get service nginx-service -o jsonpath='{.spec.clusterIP}'
# 端口转发(本地访问)
kubectl port-forward service/nginx-service 8080:80
# 删除Service
kubectl delete service nginx-service
2.7 Headless Service
Headless Service是一种特殊的Service,没有ClusterIP,用于需要直接访问Pod的场景。
apiVersion: v1
kind: Service
metadata:
name: nginx-headless
spec:
type: ClusterIP
clusterIP: None # 设置为None,表示Headless Service
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Headless Service的应用场景:
-
StatefulSet:为每个Pod提供稳定的网络标识
-
服务发现:通过DNS直接解析到Pod IP
-
客户端负载均衡:客户端自己选择Pod
查询Headless Service的DNS记录
kubectl run -it --rm debug --image=busybox -- nslookup nginx-headless
三、Namespace:资源隔离
3.1 Namespace的概念
Namespace是Kubernetes中实现多租户资源隔离的机制。它将集群划分为多个虚拟集群,不同Namespace中的资源相互隔离。
┌─────────────────────────────────────────────────────────────────────────┐
│ Namespace资源隔离 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Kubernetes集群 │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Namespace: default │ │ Namespace: dev │ │ │
│ │ │ ┌───────────────┐ │ │ ┌───────────────┐ │ │ │
│ │ │ │ Deployments │ │ │ │ Deployments │ │ │ │
│ │ │ │ Services │ │ │ │ Services │ │ │ │
│ │ │ │ Pods │ │ │ │ Pods │ │ │ │
│ │ │ └───────────────┘ │ │ └───────────────┘ │ │ │
│ │ └─────────────────────┘ └─────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │
│ │ │ Namespace: staging │ │ Namespace: prod │ │ │
│ │ │ ┌───────────────┐ │ │ ┌───────────────┐ │ │ │
│ │ │ │ Deployments │ │ │ │ Deployments │ │ │ │
│ │ │ │ Services │ │ │ │ Services │ │ │ │
│ │ │ │ Pods │ │ │ │ Pods │ │ │ │
│ │ │ └───────────────┘ │ │ └───────────────┘ │ │ │
│ │ └─────────────────────┘ └─────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 不同Namespace中的资源相互隔离,但可以通过Service跨命名空间访问 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
3.2 默认Namespace
Kubernetes集群创建时会自动创建以下Namespace:
|-----------------|-----------------------|
| Namespace | 说明 |
| default | 默认命名空间,未指定命名空间的资源都在这里 |
| kube-system | Kubernetes系统组件所在的命名空间 |
| kube-public | 公开可读的命名空间,所有用户可读 |
| kube-node-lease | 节点心跳数据,用于节点健康检测 |
# 查看所有Namespace
kubectl get namespaces
kubectl get ns
# 查看kube-system命名空间的Pod
kubectl get pods -n kube-system
3.3 创建和管理Namespace
创建Namespace:
# 使用命令行创建
kubectl create namespace dev
# 使用YAML文件创建
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: dev
labels:
environment: development
team: backend
EOF
Namespace的YAML定义:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
environment: production
team: platform
annotations:
description: "Production environment namespace"
管理Namespace:
# 查看Namespace详情
kubectl describe namespace dev
# 删除Namespace(会删除其中的所有资源)
kubectl delete namespace dev
# 在指定Namespace中创建资源
kubectl apply -f deployment.yaml -n dev
# 查看指定Namespace的资源
kubectl get pods -n dev
# 查看所有Namespace的资源
kubectl get pods -A
3.4 Namespace资源配额
使用ResourceQuota限制Namespace的资源使用:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
# 计算资源限制
requests.cpu: "10" # CPU请求总量
requests.memory: 20Gi # 内存请求总量
limits.cpu: "20" # CPU限制总量
limits.memory: 40Gi # 内存限制总量
# 资源数量限制
pods: "50" # Pod数量
services: "10" # Service数量
replicationcontrollers: "5" # RC数量
resourcequotas: "1" # ResourceQuota数量
secrets: "20" # Secret数量
configmaps: "20" # ConfigMap数量
persistentvolumeclaims: "10"# PVC数量
# 特定资源限制
count/deployments.apps: "10"
count/statefulsets.apps: "5"
查看ResourceQuota:
# 查看ResourceQuota
kubectl get resourcequota -n dev
# 查看ResourceQuota详情
kubectl describe resourcequota dev-quota -n dev
3.5 Namespace资源限制
使用LimitRange限制单个Pod/Container的资源:
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: dev
spec:
limits:
# Container资源限制
- type: Container
default: # 默认限制
cpu: "500m"
memory: "512Mi"
defaultRequest: # 默认请求
cpu: "100m"
memory: "128Mi"
max: # 最大限制
cpu: "2"
memory: "2Gi"
min: # 最小限制
cpu: "50m"
memory: "64Mi"
maxLimitRequestRatio: # 限制与请求的最大比率
cpu: "5"
memory: "4"
# Pod资源限制
- type: Pod
max:
cpu: "4"
memory: "4Gi"
# PVC资源限制
- type: PersistentVolumeClaim
max:
storage: "50Gi"
min:
storage: "1Gi"
3.6 跨Namespace访问
默认情况下,Service只能在同一Namespace内访问。跨Namespace访问需要使用完整的Service名称:
<service-name>.<namespace-name>.svc.cluster.local
# 在dev命名空间访问prod命名空间的Service
curl http://nginx-service.prod.svc.cluster.local
# 简写形式(在集群内)
curl http://nginx-service.prod
四、实战案例:完整的应用部署
让我们通过一个完整的案例,演示Deployment、Service和Namespace的综合应用。
4.1 场景描述
部署一个多环境的Web应用:
- 开发环境(dev命名空间)
- 生产环境(prod命名空间)
- 每个环境有独立的Deployment和Service
- 配置资源配额和限制
4.2 创建命名空间
# namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
labels:
environment: development
---
apiVersion: v1
kind: Namespace
metadata:
name: prod
labels:
environment: production
4.3 配置资源配额
# resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
services: "10"
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: prod-quota
namespace: prod
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "50"
services: "20"
4.4 部署应用
# dev-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: web-app
namespace: dev
spec:
type: ClusterIP
selector:
app: web-app
ports:
- port: 80
targetPort: 80
# prod-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: prod
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "400m"
---
apiVersion: v1
kind: Service
metadata:
name: web-app
namespace: prod
spec:
type: ClusterIP
selector:
app: web-app
ports:
- port: 80
targetPort: 80
4.5 部署和验证
# 创建命名空间
kubectl apply -f namespaces.yaml
# 创建资源配额
kubectl apply -f resourcequota.yaml
# 部署开发环境
kubectl apply -f dev-deployment.yaml
# 部署生产环境
kubectl apply -f prod-deployment.yaml
# 查看各环境资源
kubectl get all -n dev
kubectl get all -n prod
# 查看资源配额使用情况
kubectl describe resourcequota -n dev
kubectl describe resourcequota -n prod
# 测试跨命名空间访问
kubectl run -it --rm debug --image=busybox --namespace=dev -- \
wget -qO- http://web-app.prod.svc.cluster.local
# 端口转发访问
kubectl port-forward service/web-app 8080:80 -n dev
kubectl port-forward service/web-app 8081:80 -n prod
总结
这篇文章详细讲解了Kubernetes的三个核心对象------Deployment、Service和Namespace,主要内容包括:
- Deployment:无状态应用管理器,提供副本管理、滚动更新和回滚能力
- Service:服务发现与负载均衡,支持ClusterIP、NodePort、LoadBalancer、ExternalName四种类型
- Namespace:资源隔离机制,支持资源配额和限制
这三个对象是Kubernetes中最常用的核心对象,理解它们的工作原理和使用方法对于管理容器化应用至关重要。
下一篇文章将深入讲解Kubernetes的服务发现和负载均衡机制,包括Ingress、网络模型和Service Mesh等内容,讲解Kubernetes如何处理复杂的网络通信场景。