Kubernetes容器编排
简介
Kubernetes(通常简称为K8s)是一个开源的容器编排平台,用于自动化容器化应用的部署、扩展和管理。它最初由Google设计并捐赠给Cloud Native Computing Foundation(CNCF)。Kubernetes提供了一个可以跨主机集群部署和调度容器的平台,解决了容器化应用在生产环境中面临的诸多挑战。
核心概念与架构
Kubernetes架构
Kubernetes采用主从架构,由控制平面(Control Plane)和工作节点(Worker Nodes)组成:
控制平面组件
- API Server:所有组件之间通信的核心,提供RESTful API
- etcd:分布式键值存储,保存集群所有数据
- Scheduler:监控新创建的Pod,并将其分配到节点
- Controller Manager:运行控制器进程,如节点控制器、副本控制器等
- Cloud Controller Manager:与云服务提供商交互的组件
工作节点组件
- kubelet:确保容器在Pod中运行
- kube-proxy:维护节点上的网络规则,实现服务抽象
- Container Runtime:运行容器的软件,如Docker、containerd等
基本对象
Kubernetes中的基本对象包括:
- Pod:最小部署单元,包含一个或多个容器
- Service:定义Pod的访问方式,提供固定IP和负载均衡
- Volume:数据持久化存储
- Namespace:资源隔离机制,将集群分割成多个虚拟集群
控制器
控制器构建在基本对象之上,提供额外功能:
- ReplicaSet:确保指定数量的Pod副本运行
- Deployment:管理ReplicaSet,提供声明式更新
- StatefulSet:管理有状态应用
- DaemonSet:确保所有节点运行特定Pod
- Job/CronJob:运行一次性或定时任务
安装与配置
本地开发环境
使用Minikube
bash
# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 启动Minikube
minikube start
# 检查状态
minikube status
使用kind (Kubernetes in Docker)
bash
# 安装kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.1/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/
# 创建集群
kind create cluster
# 查看集群
kubectl cluster-info --context kind-kind
安装kubectl
kubectl是与Kubernetes集群交互的命令行工具:
bash
# 下载最新版本
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# 安装
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# 验证安装
kubectl version --client
生产环境部署
生产环境可以使用以下工具部署Kubernetes集群:
- kubeadm:官方集群创建工具
- kops:在AWS上创建生产级Kubernetes集群
- kubespray:使用Ansible部署Kubernetes
- 管理服务:GKE (Google)、EKS (AWS)、AKS (Azure)等
Kubernetes基本操作
命名空间管理
bash
# 创建命名空间
kubectl create namespace my-namespace
# 查看命名空间
kubectl get namespaces
# 在特定命名空间中操作
kubectl -n my-namespace get pods
Pod管理
bash
# 创建Pod
kubectl run nginx --image=nginx
# 查看Pod
kubectl get pods
# 查看Pod详情
kubectl describe pod nginx
# 删除Pod
kubectl delete pod nginx
# 从YAML文件创建Pod
kubectl apply -f pod.yaml
# 查看Pod日志
kubectl logs nginx
# 在Pod中执行命令
kubectl exec -it nginx -- bash
Deployment管理
bash
# 创建Deployment
kubectl create deployment nginx --image=nginx --replicas=3
# 查看Deployment
kubectl get deployments
# 扩展Deployment
kubectl scale deployment nginx --replicas=5
# 更新镜像
kubectl set image deployment/nginx nginx=nginx:1.19
# 回滚Deployment
kubectl rollout undo deployment/nginx
# 查看Deployment历史
kubectl rollout history deployment/nginx
Service管理
bash
# 创建Service
kubectl expose deployment nginx --port=80 --type=ClusterIP
# 查看Service
kubectl get services
# 描述Service
kubectl describe service nginx
# 删除Service
kubectl delete service nginx
配置管理
bash
# 创建ConfigMap
kubectl create configmap app-config --from-file=config.properties
# 创建Secret
kubectl create secret generic db-secret --from-literal=username=admin --from-literal=password=secret
# 查看ConfigMap
kubectl get configmaps
# 查看Secret
kubectl get secrets
YAML配置文件
Pod配置示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
resources:
limits:
cpu: "0.5"
memory: "512Mi"
requests:
cpu: "0.2"
memory: "256Mi"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
Deployment配置示例
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
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
env:
- name: NGINX_PORT
value: "80"
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
volumes:
- name: config-volume
configMap:
name: nginx-config
Service配置示例
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
type: ClusterIP
Ingress配置示例
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
存储管理
持久卷(PV)与持久卷声明(PVC)
yaml
# 持久卷
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-storage
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: /data/pv0001
# 持久卷声明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
在Pod中使用PVC
yaml
apiVersion: v1
kind: Pod
metadata:
name: pvc-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- mountPath: "/data"
name: data-volume
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: pvc-storage
存储类(StorageClass)
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
fsType: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
网络
Service类型
Kubernetes提供多种Service类型:
- ClusterIP:默认类型,仅集群内部可访问
- NodePort:在每个节点上开放端口,可从外部访问
- LoadBalancer:使用云提供商的负载均衡器
- ExternalName:将Service映射到外部DNS名称
网络策略
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
安全
RBAC(基于角色的访问控制)
yaml
# 创建Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
# 创建RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
ServiceAccount
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-service-account
---
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
serviceAccountName: app-service-account
containers:
- name: app
image: myapp:1.0
Pod安全策略
yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'persistentVolumeClaim'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
readOnlyRootFilesystem: true
高级功能
HPA(水平Pod自动扩展)
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
亲和性与反亲和性
yaml
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- app
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: app:1.0
污点与容忍度
yaml
# 给节点添加污点
kubectl taint nodes node1 key=value:NoSchedule
# Pod容忍污点
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
部署策略
滚动更新
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
# ...其他配置
蓝绿部署
yaml
# 蓝版本(当前版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
spec:
containers:
- name: app
image: myapp:1.0
# 绿版本(新版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green
template:
metadata:
labels:
app: myapp
version: green
spec:
containers:
- name: app
image: myapp:2.0
# 服务(切换流量)
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # 切换到green进行流量切换
ports:
- port: 80
targetPort: 8080
金丝雀发布
yaml
# 主要部署(90%流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-main
spec:
replicas: 9
selector:
matchLabels:
app: myapp
version: stable
template:
metadata:
labels:
app: myapp
version: stable
spec:
containers:
- name: app
image: myapp:1.0
# 金丝雀部署(10%流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-canary
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: canary
template:
metadata:
labels:
app: myapp
version: canary
spec:
containers:
- name: app
image: myapp:2.0
# 服务(同时选择两个版本)
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp # 同时匹配stable和canary
ports:
- port: 80
targetPort: 8080
监控与日志
Prometheus + Grafana
yaml
# 使用Helm安装Prometheus和Grafana
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack
日志收集
使用EFK/ELK栈收集日志:
- Elasticsearch:存储和索引日志
- Fluentd/Filebeat:收集和转发日志
- Kibana:可视化和分析日志
yaml
# 使用Helm安装EFK栈
helm repo add elastic https://helm.elastic.co
helm repo update
helm install elasticsearch elastic/elasticsearch
helm install kibana elastic/kibana
helm install filebeat elastic/filebeat
故障排查
常见问题排查
bash
# 查看Pod状态
kubectl get pods
# 查看Pod详情
kubectl describe pod <pod-name>
# 查看Pod日志
kubectl logs <pod-name>
# 查看容器日志
kubectl logs <pod-name> -c <container-name>
# 查看前一个容器的日志(如果容器重启)
kubectl logs <pod-name> --previous
# 查看节点状态
kubectl get nodes
kubectl describe node <node-name>
# 查看集群事件
kubectl get events --sort-by='.metadata.creationTimestamp'
常见Pod状态问题
Pending:Pod未被调度到节点
- 资源不足
- PV不可用
- 节点选择器不匹配
ImagePullBackOff:无法拉取镜像
- 镜像名称错误
- 镜像仓库需要认证
- 网络问题
CrashLoopBackOff:容器反复崩溃
- 应用配置错误
- 资源不足
- 健康检查失败
Error:容器启动出错
- 命令参数错误
- 权限问题
最佳实践
资源管理
- 设置资源请求和限制:为每个容器设置CPU和内存请求与限制
- 使用命名空间:按团队或环境划分命名空间
- 实施资源配额:为命名空间设置资源配额
- 使用HPA:根据负载自动扩展应用
安全性
- 最小权限原则:使用RBAC限制权限
- 使用网络策略:限制Pod间通信
- 使用安全上下文:限制容器权限
- 定期更新镜像:修复安全漏洞
- 扫描镜像:使用工具检测镜像漏洞
高可用性
- 多副本部署:每个应用至少运行2-3个副本
- 反亲和性调度:将Pod分散到不同节点
- 使用PDB:设置Pod中断预算
- 健康检查:配置存活和就绪探针
- 多区域部署:跨多个可用区部署
GitOps
- 声明式配置:所有资源使用YAML定义
- 配置版本控制:将配置存储在Git仓库
- 自动化部署:使用ArgoCD或Flux等工具
- 环境一致性:使用相同的配置部署多个环境
常用工具生态
包管理
- Helm:Kubernetes的包管理器
- Kustomize:无模板的Kubernetes配置管理
CI/CD
- ArgoCD:GitOps持续交付工具
- Flux:GitOps操作器
- Jenkins X:云原生CI/CD平台
- Tekton:Kubernetes原生CI/CD系统
服务网格
- Istio:强大的服务网格平台
- Linkerd:轻量级服务网格
- Consul Connect:HashiCorp的服务网格解决方案
开发工具
- Skaffold:本地Kubernetes开发
- Telepresence:本地开发与远程集群连接
- Tilt:本地Kubernetes开发环境
实际应用案例
微服务应用部署
yaml
# 前端服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: frontend:1.0
ports:
- containerPort: 80
resources:
limits:
cpu: "0.5"
memory: "512Mi"
requests:
cpu: "0.2"
memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- port: 80
type: ClusterIP
# API服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: api:1.0
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: "database"
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-secrets
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
---
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
ports:
- port: 80
targetPort: 8080
# 数据库
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
serviceName: "database"
replicas: 1
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
containers:
- name: database
image: postgres:13
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: db-secrets
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
- name: POSTGRES_DB
value: "myapp"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: database
spec:
selector:
app: database
ports:
- port: 5432
入口配置
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- example.com
secretName: example-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
总结
Kubernetes已成为容器编排的事实标准,为现代云原生应用提供了强大的平台。通过自动化部署、扩展和管理容器化应用,Kubernetes解决了传统部署方式的诸多挑战。
掌握Kubernetes不仅需要了解其核心概念和组件,还需要熟悉最佳实践和常见问题的解决方案。随着云原生技术的不断发展,Kubernetes生态系统也在不断壮大,为开发者和运维人员提供了丰富的工具和解决方案。
无论是小型创业公司还是大型企业,Kubernetes都能提供一致的应用部署和管理体验,帮助组织实现DevOps转型,提高开发效率和系统可靠性。