第4章:Kubernetes编排
Kubernetes核心概念
1. Kubernetes架构
┌────────────────────────────────────────────────────┐
│ Control Plane │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │API Server│ │Scheduler │ │Controller│ │
│ └──────────┘ └──────────┘ │ Manager │ │
│ └──────────┘ │
│ ┌──────────┐ │
│ │ etcd │ (集群状态存储) │
│ └──────────┘ │
└────────────────────────────────────────────────────┘
↓ ↓ ↓
┌──────────────────────────────────────────────────┐
│ Worker Nodes │
│ ┌────────────────────────────────────────────┐ │
│ │ Node 1 │ │
│ │ ┌────────┐ ┌───────┐ ┌───────────────┐ │ │
│ │ │kubelet │ │kube- │ │ Pods │ │ │
│ │ │ │ │proxy │ │ ┌───┐ ┌───┐ │ │ │
│ │ └────────┘ └───────┘ │ │Pod│ │Pod│ │ │ │
│ │ │ └───┘ └───┘ │ │ │
│ │ └───────────────┘ │ │
│ └────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ Node 2 │ │
│ │ (同上) │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
2. 核心资源
Pod:
最小部署单元,包含一个或多个容器
┌─────────────────────┐
│ Pod │
│ ┌──────────────┐ │
│ │ Container 1 │ │
│ └──────────────┘ │
│ ┌──────────────┐ │
│ │ Container 2 │ │
│ └──────────────┘ │
│ 共享: │
│ - 网络命名空间 │
│ - IPC命名空间 │
│ - Volume │
└─────────────────────┘
Deployment:
管理Pod副本,支持滚动更新
Deployment
↓
ReplicaSet (v1)
↓
Pod Pod Pod
Service:
为Pod提供稳定的网络端点
Service (ClusterIP: 10.0.0.100)
↓
Selector: app=myapp
↓
┌────┐ ┌────┐ ┌────┐
│Pod │ │Pod │ │Pod │
└────┘ └────┘ └────┘
3. 安装Kubernetes
方式1:Minikube(本地开发):
# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 启动集群
minikube start --cpus=4 --memory=8192 --driver=docker
# 验证
kubectl get nodes
方式2:k3s(轻量级生产):
# 安装k3s
curl -sfL https://get.k3s.io | sh -
# 配置kubeconfig
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER ~/.kube/config
# 验证
kubectl get nodes
方式3:kubeadm(标准生产):
# 1. 安装Docker、kubeadm、kubelet、kubectl
# (详见官方文档)
# 2. 初始化Master节点
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
# 3. 配置kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 4. 安装网络插件(Calico)
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
# 5. 加入Worker节点
sudo kubeadm join <master-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
资源编排
1. Pod定义
基础Pod:
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1.0.0
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: postgres://db:5432/myapp
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "0.5"
memory: "256Mi"
多容器Pod(Sidecar):
# multi-container-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-with-sidecar
spec:
containers:
# 主应用容器
- name: app
image: myapp:v1.0.0
ports:
- containerPort: 8080
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
# Sidecar容器(日志收集)
- name: log-collector
image: fluentd:latest
volumeMounts:
- name: shared-logs
mountPath: /var/log/app
readOnly: true
volumes:
- name: shared-logs
emptyDir: {}
2. Deployment
完整的Deployment:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
labels:
app: myapp
spec:
replicas: 3
revisionHistoryLimit: 10 # 保留10个历史版本
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多额外创建1个Pod
maxUnavailable: 0 # 最多0个Pod不可用
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
version: v1.0.0
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
containers:
- name: myapp
image: harbor.example.com/myproject/myapp:v1.0.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secret
key: database-url
- name: REDIS_URL
valueFrom:
configMapKeyRef:
name: myapp-config
key: redis-url
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
volumes:
- name: config
configMap:
name: myapp-config
imagePullSecrets:
- name: harbor-secret
3. ConfigMap和Secret
ConfigMap(配置):
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: production
data:
redis-url: redis://redis:6379/0
log-level: info
config.yaml: |
server:
port: 8080
timeout: 30s
database:
max_connections: 100
Secret(密钥):
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: myapp-secret
namespace: production
type: Opaque
data:
database-url: cG9zdGdyZXM6Ly91c2VyOnBhc3N3b3JkQGRiOjU0MzIvbXlhcHAK # base64编码
api-key: eW91ci1hcGkta2V5Cg==
# 创建Secret
kubectl create secret generic myapp-secret \
--from-literal=database-url='postgres://user:password@db:5432/myapp' \
--from-literal=api-key='your-api-key' \
-n production
4. PersistentVolume和PVC
PersistentVolume(PV):
# pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: /data/mysql
PersistentVolumeClaim(PVC):
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: production
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
使用PVC:
# mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: root-password
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc
服务发现与负载均衡
1. Service类型
ClusterIP(集群内部访问):
# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: production
spec:
type: ClusterIP
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
# 访问:curl http://myapp-service.production.svc.cluster.local
NodePort(节点端口访问):
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
spec:
type: NodePort
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 节点端口(30000-32767)
# 访问:curl http://<node-ip>:30080
LoadBalancer(云负载均衡器):
# service-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-lb
spec:
type: LoadBalancer
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
# 云提供商自动创建负载均衡器
# 访问:curl http://<external-ip>
2. Ingress
安装Nginx Ingress Controller:
# 安装Nginx Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/cloud/deploy.yaml
# 验证
kubectl get pods -n ingress-nginx
Ingress规则:
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
多域名Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
# www.example.com → frontend
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# api.example.com → backend
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8080
自动扩缩容
1. Horizontal Pod Autoscaler (HPA)
基于CPU的HPA:
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # CPU使用率超过70%时扩容
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80 # 内存使用率超过80%时扩容
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50 # 每次扩容50%
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1 # 每次缩容1个Pod
periodSeconds: 120
基于自定义指标的HPA:
# custom-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-custom-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 20
metrics:
# 基于QPS(每秒请求数)
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "1000" # 每个Pod处理1000 QPS
2. Vertical Pod Autoscaler (VPA)
# vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: myapp-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
updatePolicy:
updateMode: "Auto" # 自动调整资源限制
resourcePolicy:
containerPolicies:
- containerName: myapp
minAllowed:
cpu: "100m"
memory: "128Mi"
maxAllowed:
cpu: "2"
memory: "2Gi"
3. Cluster Autoscaler
# cluster-autoscaler.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
spec:
serviceAccountName: cluster-autoscaler
containers:
- name: cluster-autoscaler
image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.27.0
command:
- ./cluster-autoscaler
- --cloud-provider=aws
- --namespace=kube-system
- --nodes=2:10:k8s-worker-asg # 最小2个,最大10个节点
- --skip-nodes-with-local-storage=false
Helm包管理
1. 安装Helm
# 安装Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# 验证
helm version
2. 使用Helm Charts
添加仓库:
# 添加官方仓库
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
# 更新仓库
helm repo update
# 搜索Chart
helm search repo mysql
安装应用:
# 安装MySQL
helm install my-mysql bitnami/mysql \
--set auth.rootPassword=secretpassword \
--set primary.persistence.size=10Gi \
--namespace database \
--create-namespace
# 查看状态
helm status my-mysql -n database
# 查看值
helm get values my-mysql -n database
# 升级
helm upgrade my-mysql bitnami/mysql \
--set auth.rootPassword=newsecret \
-n database
# 回滚
helm rollback my-mysql 1 -n database
# 卸载
helm uninstall my-mysql -n database
3. 创建Helm Chart
Chart结构:
myapp/
├── Chart.yaml # Chart元数据
├── values.yaml # 默认配置值
├── templates/ # 模板文件
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # 辅助模板
│ └── NOTES.txt # 安装后说明
└── charts/ # 依赖Chart
Chart.yaml:
apiVersion: v2
name: myapp
description: A Helm chart for myapp
type: application
version: 1.0.0
appVersion: "1.0.0"
maintainers:
- name: Your Name
email: your@email.com
values.yaml:
replicaCount: 3
image:
repository: myapp
pullPolicy: IfNotPresent
tag: "v1.0.0"
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: nginx
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
templates/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
安装自定义Chart:
# 本地Chart
helm install myapp ./myapp -n production
# 自定义值
helm install myapp ./myapp \
--set replicaCount=5 \
--set image.tag=v2.0.0 \
-n production
# 使用values文件
helm install myapp ./myapp -f values-prod.yaml -n production
监控与日志
1. Prometheus监控
安装Prometheus Operator:
# 使用Helm安装kube-prometheus-stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace
ServiceMonitor(监控应用):
# servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: myapp-metrics
namespace: production
labels:
release: kube-prometheus
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: metrics
interval: 30s
path: /metrics
应用暴露Prometheus指标:
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
labels:
app: myapp
spec:
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 8080
- name: metrics
port: 9090
targetPort: 9090 # Prometheus指标端口
PrometheusRule(告警规则):
# prometheusrule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: myapp-alerts
namespace: monitoring
spec:
groups:
- name: myapp
interval: 30s
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.pod }}"
description: "Error rate is {{ $value }} requests/sec"
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.pod }} is crash looping"
2. Grafana可视化
访问Grafana:
# 获取admin密码
kubectl get secret kube-prometheus-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode
# 端口转发
kubectl port-forward -n monitoring svc/kube-prometheus-grafana 3000:80
# 访问:http://localhost:3000
# 用户名:admin
# 密码:(上面获取的密码)
导入Dashboard:
Grafana → Dashboards → Import
推荐Dashboard ID:
- 315:Kubernetes Cluster Monitoring
- 6417:Kubernetes Cluster
- 7249:Kubernetes Deployment
3. EFK日志栈
安装Elasticsearch:
helm repo add elastic https://helm.elastic.co
helm install elasticsearch elastic/elasticsearch -n logging --create-namespace
安装Fluentd:
# fluentd-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
serviceAccountName: fluentd
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch-master.logging.svc.cluster.local"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
安装Kibana:
helm install kibana elastic/kibana -n logging
# 访问Kibana
kubectl port-forward -n logging svc/kibana-kibana 5601:5601
# http://localhost:5601
面试问答
Pod和容器有什么区别?
答案:
容器(Container):
- 单个应用进程
- Docker镜像的运行实例
Pod:
- Kubernetes最小部署单元
- 包含一个或多个容器
- 共享网络和存储
┌─────────────────────┐
│ Pod │
│ ┌──────────────┐ │
│ │ 容器1 │ │
│ │ (主应用) │ │
│ └──────────────┘ │
│ ┌──────────────┐ │
│ │ 容器2 │ │
│ │ (Sidecar) │ │
│ └──────────────┘ │
│ 共享: │
│ - IP地址 │
│ - localhost通信 │
│ - Volume │
└─────────────────────┘
使用场景:
单容器Pod:
- 独立应用
多容器Pod(Sidecar模式):
- 日志收集:App + Fluentd
- 服务网格:App + Envoy
- 配置热更新:App + ConfigReloader
Kubernetes的Service有哪些类型?
答案:
| 类型 | 使用场景 | 访问方式 |
|---|---|---|
| ClusterIP | 集群内部通信 | ClusterIP |
| NodePort | 测试环境 | <NodeIP>:<NodePort> |
| LoadBalancer | 生产环境 | 云负载均衡器IP |
| Ingress | HTTP/HTTPS流量 | 域名 |
详细说明:
ClusterIP(默认):
service-name.namespace.svc.cluster.local
NodePort:
http://<任意节点IP>:30080
LoadBalancer:
http://<外部IP>
Ingress:
http://myapp.example.com
选择建议:
开发环境:ClusterIP + kubectl port-forward
测试环境:NodePort
生产环境:LoadBalancer或Ingress
如何实现Kubernetes的滚动更新和回滚?
答案:
滚动更新:
# 方式1:kubectl set image
kubectl set image deployment/myapp myapp=myapp:v2.0.0 -n production
kubectl rollout status deployment/myapp -n production
# 方式2:kubectl apply
# 修改deployment.yaml中的image
kubectl apply -f deployment.yaml
# 方式3:kubectl edit
kubectl edit deployment myapp -n production
滚动更新策略:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多额外创建1个Pod
maxUnavailable: 0 # 更新时保持所有Pod可用
更新流程:
初始状态:v1.0.0 (3个Pod)
┌────┐ ┌────┐ ┌────┐
│ v1 │ │ v1 │ │ v1 │
└────┘ └────┘ └────┘
步骤1:创建1个v2 Pod
┌────┐ ┌────┐ ┌────┐ ┌────┐
│ v1 │ │ v1 │ │ v1 │ │ v2 │
└────┘ └────┘ └────┘ └────┘
步骤2:删除1个v1 Pod
┌────┐ ┌────┐ ┌────┐
│ v1 │ │ v1 │ │ v2 │
└────┘ └────┘ └────┘
...重复直到全部v2
┌────┐ ┌────┐ ┌────┐
│ v2 │ │ v2 │ │ v2 │
└────┘ └────┘ └────┘
回滚:
# 查看历史版本
kubectl rollout history deployment/myapp -n production
# 回滚到上一个版本
kubectl rollout undo deployment/myapp -n production
# 回滚到指定版本
kubectl rollout undo deployment/myapp --to-revision=2 -n production
# 暂停和恢复
kubectl rollout pause deployment/myapp -n production
kubectl rollout resume deployment/myapp -n production
如何实现Kubernetes的自动扩缩容?
答案:
1. HPA(水平扩缩容):
# 基于CPU/内存
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
2. VPA(垂直扩缩容):
# 自动调整资源requests/limits
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: myapp-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
updatePolicy:
updateMode: "Auto"
3. Cluster Autoscaler(集群扩缩容):
自动增加/减少节点数量:
- Pod pending → 增加节点
- 节点空闲 → 减少节点
三者关系:
HPA:Pod副本数量(2 → 10)
VPA:Pod资源大小(512Mi → 1Gi)
CA:节点数量(3 → 5)
如何保证Kubernetes应用的高可用?
答案:
1. 多副本部署:
spec:
replicas: 3 # 至少3个副本
2. Pod反亲和性:
# 确保Pod分散在不同节点
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
3. PodDisruptionBudget:
# 确保最少可用Pod数量
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
minAvailable: 2 # 至少2个Pod可用
selector:
matchLabels:
app: myapp
4. 健康检查:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
5. 资源限制:
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
6. 滚动更新策略:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0 # 保持所有Pod可用