Kubernetes: 生产级的分布式集群部署
Kubernetes
快速入门
简介
Kubernetes(简称k8s)是一个开源的容器编排平台。相比于Docker,它能够在集群级别自动化地管理容器的部署、扩缩容和运维,但学习成本也相对更高- 除了基础的容器调度与自愈能力,
k8s原生支持服务发现、负载均衡、滚动更新与配置管理等服务治理,配合Istio等服务网格组件,可以替代传统的RPC框架,将流量治理、可观测性、安全等能力下沉至基础设施层 - 官方文档
工具介绍
- 对本地环境,
minikube提供了一种k8s的单节点集群方案minikube start --driver=docker:用docker驱动启动一个minikube容器(集群),让它接管dockerminikube status:查看集群状态minikube stop:停止集群minikube delete:删除集群minikube dashboard:快速开启一个由minikube管理的dashboard(管理容器的可视化网页)
k3s是一个轻量级的k8s发行版,单个二进制文件即包含全部组件,内存占用约512MB,适合低配机器、边缘设备与CI环境,也可作为本地方案的另一选择curl -sfL https://get.k3s.io | sh -:一条命令安装并启动,自带containerd、Flannel网络、本地存储与Service LoadBalancer,开箱即用k3s kubectl get node:内置了kubectl,无需单独安装- 凭证位于
/etc/rancher/k3s/k3s.yaml,让外部kubectl/helm使用需export KUBECONFIG=/etc/rancher/k3s/k3s.yaml k3s-killall.sh/k3s-uninstall.sh:停止/彻底卸载k3d在docker容器里运行k3s,可以像minikube一样快速创建和销毁多节点集群,兼顾轻量与隔离
kubectl是和k8s集群交互的命令行工具kubectl [command] [kind] [name] [flags]是一般的命令格式,其中kind是k8s API定义的类型kubectl get pod/service/node:获取pod/service/node等的简短状态kubectl logs [podname]:查看日志kubectl exec -it [podname] -- /bin/sh:进入容器(--interactive --tty)kubectl apply [-f x.yaml]...:应用配置
helm是k8s的包管理器,替代了apply并提供更好的管理方式Chart:一个完整应用所需的全部配置,在其目录下Chart.yaml:一个Chart的定义values-*.yaml:所有环境变量的定义,默认查找values.yaml文件templates/:go tmpl文件所在目录,定义应用的配置模板Chart.lock:锁文件,由helm dependency build根据Chart.yaml所依赖的chart的版本生成charts/:本chart依赖的子charts
Release:一个Chart在集群中的运行实例Repo:类似docker hub,每个仓库有一个index.yaml
核心字段
apiVersion与kind
k8s使用声明式管理,所有集群的状态通过yaml来定义apiVersion:api版本定义,格式为GROUP/VERSION,一般来说v1是稳定版本,但存在特例- 核心组(
v1):基础资源,包含Pod、Service、ConfigMap、Secret、Namespace apps/v1:工作负载管理,包含Deployment、StatefulSet、DaemonSet、ReplicaSetbatch/v1:批处理任务,包含Job、CronJobnetworking.k8s.io/v1:网络配置,包含Ingress、NetworkPolicyrbac.authorization.k8s.io/v1:RBAC权限控制,包含Role、RoleBinding、ClusterRole、ClusterRoleBindingstorage.k8s.io/v1:存储管理,包含StorageClass、VolumeAttachmentautoscaling/v2:自动扩缩容,包含HorizontalPodAutoscaler(v1已废弃,生产使用v2)apiextensions.k8s.io/v1:自定义资源,包含CustomResourceDefinition(CRD),不常用networking.istio.io/v1:Istio网络配置,包含VirtualService、DestinationRule、Gateway、ServiceEntrysecurity.istio.io/v1:Istio安全配置,包含AuthorizationPolicy、PeerAuthenticationtelemetry.istio.io/v1:Istio可观测性配置,包含Telemetry- 使用
kubectl explain [kind]查看资源对应的apiVersion和字段说明 - 使用
kubectl api-resources查看所有资源及其所属API组
- 核心组(
kind:资源类型,如Pod、Deployment、ServicePod:最小部署单元,包含一个或多个容器,适用于临时调试、手动运行任务Deployment:管理无状态应用,支持滚动更新和回滚,最常用的控制器StatefulSet:管理有状态应用(如数据库),提供稳定的网络标识和持久存储DaemonSet:在每个节点上运行一个Pod副本,适用于日志收集、监控代理ReplicaSet:维护Pod副本数量,Deployment底层依赖,通常不直接使用Job:一次性任务,执行完成后退出CronJob:定时任务,按Cron表达式周期性执行Service:为Pod提供稳定的访问入口,支持负载均衡Ingress:七层负载均衡,基于域名和路径路由到不同ServiceConfigMap:存储非敏感配置数据,以键值对形式挂载到PodSecret:存储敏感信息(密码、密钥),base64编码存储,本身并不加密也不安全,只是因为敏感信息通常存在特殊字符甚至是二进制数据,而k8s传输数据使用json,因此通常转为base64,而Secret则是在ConfigMap的基础上添加一层base64编码校验的资源类型StorageClass:存储模板,定义动态供给方式和存储参数PVC(PersistentVolumeClaim):命名空间级别的存储声明,由用户创建,引用StorageClass动态供给PV(PersistentVolume):集群级别的存储资源,云环境通常由StorageClass动态创建NetworkPolicy:网络策略,限制Pod间的网络通信LimitRange:资源限制范围,限制Pod的资源使用上下限ResourceQuota:资源配额,限制命名空间的总资源使用量HorizontalPodAutoscaler:自动扩缩容,根据 CPU/内存使用率调整Pod副本数Namespace:资源隔离,不同命名空间的资源相互独立
示例:
1
2
3
4apiVersion: v1
kind: Pod
metadata:
name: pod-1
metadata
metadata.name:适用于所有资源,资源名称在命名空间内唯一,DNS 解析时会用到(如 Service 的name.namespace.svc.cluster.local)metadata.labels:适用于所有资源,键值对标签用于资源筛选和关联,Service 通过 labels 匹配 Pod,Deployment 通过 labels 管理 Podmetadata.namespace:适用于所有资源,指定资源所属命名空间,默认为default,系统组件在kube-system示例:
1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: nginx
namespace: default
spec:
containers:
- name: nginx
image: nginx:1.21
spec
spec.selector:适用于 Deployment、StatefulSet、DaemonSet、Job、Service,选择器匹配 Pod 的 labels,决定控制器管理哪些 Pod,必须与spec.template.metadata.labels匹配spec.template:适用于 Deployment、StatefulSet、DaemonSet、Job、CronJob,Pod 模板定义要创建的 Pod 的完整配置,包含metadata.labels和spec.containersspec.replicas:适用于 Deployment、StatefulSet,期望的 Pod 副本数量,默认为 1示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
containers 与
volumes
spec.containers:适用于Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,容器列表,每个容器包含以下字段:name:容器名称image:镜像名称和标签ports.containerPort:容器暴露的端口resources.requests:最小资源需求(CPU、内存),调度依据resources.limits:最大资源限制(CPU、内存),防止资源争抢volumeMounts:存储卷挂载路径env:环境变量配置livenessProbe:存活探针,检测容器是否存活,失败则重启容器initialDelaySeconds:首次探测延迟periodSeconds:探测间隔failureThreshold:失败阈值,允许的最大连续探测失败次数,超出此阈值将重启podsuccessThreshold:成功阈值,将该pod视为健康的最小连续探测成功次数,存活探针的成功阈值必须是1- 探测方式:
httpGet(指定path和port)、tcpSocket(指定port)、exec(指定command)
readinessProbe:就绪探针,检测容器是否就绪,失败则从Service摘除。参数与livenessProbe相同,但失败后不会重启容器,只是暂时停止流量进入
spec.volumes:适用于Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,存储卷定义,常用类型:emptyDir:临时存储,Pod删除时数据丢失,适用于缓存、临时文件configMap:挂载ConfigMap,需指定name,可选择挂载特定items或全部键值对。支持optional: true(ConfigMap不存在时不阻塞启动)和defaultMode(文件权限,默认0644)secret:挂载Secret,参数与ConfigMap类似,额外支持secretName指定Secret名称。常用于挂载TLS证书(secret.items指定tls.crt和tls.key)或数据库密码persistentVolumeClaim:挂载PVC,需指定claimName,支持readOnly: true设置只读挂载。PVC绑定的PV可以是静态供给(管理员预先创建)或动态供给(通过StorageClass自动创建)
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
- name: cache
mountPath: /var/cache
- name: tls
mountPath: /etc/tls
readOnly: true
- name: data
mountPath: /var/data
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
volumes:
- name: config
configMap:
name: my-config
defaultMode: 0644
- name: cache
emptyDir: {}
- name: tls
secret:
secretName: my-tls-secret
items:
- key: tls.crt
path: cert.pem
- key: tls.key
path: key.pem
- name: data
persistentVolumeClaim:
claimName: my-pvc
readOnly: false
Service 独有字段
spec.type:服务类型,可选值:ClusterIP:默认值,仅在集群内部可访问NodePort:通过节点端口暴露,范围30000-32767,但问题在于限制端口且不支持域名,用户不方便访问且会暴露服务IP,仅适用于开发测试LoadBalancer:配合云厂商负载均衡器使用,适用于生产环境的对外提供服务ExternalName:映射到外部域名,相当于DNS层面的代理,方便内部服务访问外部第三方服务
spec.externalTrafficPolicy:外部流量策略,仅NodePort/LoadBalancer有效Cluster(默认):流量经kube-proxy转发,可跨节点负载均衡,但会做一次SNAT,丢失客户端真实IPLocal:流量只转发到本节点的Pod,保留客户端真实IP,但本节点无Pod时流量会被丢弃,需配合探针摘除不健康节点
spec.ports:端口配置列表,每个端口包含:port:Service暴露的端口,供集群内部访问targetPort:Pod容器端口nodePort:节点端口(仅NodePort类型,范围30000-32767)protocol:协议,默认TCPname:端口名称,多端口时必须指定
spec.clusterIP:虚拟IP地址,设置为None时为Headless Service,无头服务是指,该Service不会做负载均衡,在DNS解析它管理的pod的地址时会直接指向其管理的pod IP,通常用于有状态服务,例如数据库服务等示例:
1
2
3
4
5
6
7
8
9
10
11
12apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
Ingress 独有字段
spec.rules:路由规则列表,基于域名和路径转发到不同Servicehost:域名,如api.example.com(可选,不指定则匹配所有域名)http.paths:路径规则列表path:匹配路径,如/api、/pathType:路径匹配类型Exact:精确匹配Prefix:前缀匹配ImplementationSpecific:由Ingress Controller决定
backend:后端服务配置service.name:Service名称service.port.number:Service端口号
spec.tls:TLS证书配置,支持HTTPSspec.ingressClassName:指定Ingress Controller的名称,对应IngressClass资源的名称,通常不需要自己创建nginx:Nginx Ingress Controller安装时自动创建istio:Istio Gateway安装时自动创建
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
tls:
- hosts:
- api.example.com
secretName: tls-secret
ConfigMap 与
Secret 独有字段
data:键值对配置数据,Secret的值需base64编码stringData:仅Secret支持,明文写入自动转base64type:仅Secret支持,类型标识Opaque:默认kubernetes.io/dockerconfigjson:镜像拉取凭证kubernetes.io/tls:TLS证书
示例:
1
2
3
4
5
6
7apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
key1: value1
key2: value2
PV 与 PVC
独有字段
供给模式:
- 静态供给:管理员手动创建
PV,用户创建PVC绑定已有PV,适用于本地存储、NFS等无动态供给的场景 - 动态供给:用户创建
PVC并引用StorageClass,Provisioner自动创建PV并绑定,云环境推荐方式
- 静态供给:管理员手动创建
spec.capacity.storage:仅PV,存储大小,如10Gispec.accessModes:访问模式ReadWriteOnce:单节点读写ReadWriteMany:多节点读写ReadOnlyMany:多节点只读
spec.storageClassName:存储类名称,用于PV和PVC绑定spec.resources.requests.storage:仅PVC,请求的存储大小spec.volumeMode:卷模式Filesystem:默认值,文件系统模式Block:块设备模式
spec.persistentVolumeReclaimPolicy:仅PV,回收策略Retain:保留数据,需手动清理Recycle:回收数据,已废弃Delete:删除存储资源
示例(动态供给):
1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard # 引用 StorageClass 动态创建 PV
StorageClass 独有字段
provisioner:存储供给器,决定使用哪种存储后端- 云厂商:
kubernetes.io/aws-ebs、kubernetes.io/gce-pd、kubernetes.io/azure-disk - 第三方:
nfs-client、rbd.csi.ceph.com(Ceph) - 本地存储:
kubernetes.io/no-provisioner
- 云厂商:
parameters:存储参数,传递给供给器的配置- AWS
EBS:
type: gp2(存储类型)、zone: us-east-1a(可用区)、fsType: ext4 - GCE
PD:
type: pd-standard、replication-type: regional-pd - Ceph RBD:
pool: rbd、cluster: ceph
- AWS
EBS:
reclaimPolicy:回收策略,PVC删除时PV的处理方式Delete:删除PV和底层存储(默认)Retain:保留PV和数据,需手动清理Recycle:已废弃,执行rm -rf /volume/*后重用
volumeBindingMode:绑定模式,控制PV创建和绑定的时机Immediate:立即创建并绑定(默认)WaitForFirstConsumer:延迟到第一个Pod调度后再创建,确保PV与Pod在同一可用区
allowVolumeExpansion:是否允许动态扩容(true/false)- 需要存储后端支持,AWS EBS、GCE PD 支持,NFS 不支持
mountOptions:挂载选项,传递给mount命令- 例如:
["hard", "nfsvers=4.1", "noatime"](NFS 选项)
- 例如:
allowedTopologies:限制PV创建的拓扑位置(如可用区)- 配合
WaitForFirstConsumer使用,确保存储与Pod在同一区域
- 配合
- 示例:
1 | apiVersion: storage.k8s.io/v1 |
Deployment 独有字段
spec.strategy:更新策略RollingUpdate:滚动更新,逐步替换PodRecreate:重建,先删除旧Pod再创建新Pod
spec.strategy.rollingUpdate.maxSurge:滚动更新时最多超出期望副本数的数量,控制更新过程中可以多创建多少个新Pod,可以是数字或百分比spec.strategy.rollingUpdate.maxUnavailable:滚动更新时最多不可用的副本数,控制更新过程中最多有多少个旧Pod可以不可用,可以是数字或百分比,设置为0同时使maxSurge>0可保证不停机更新maxSurge与maxUnavailable配合使用场景:maxSurge: 25%+maxUnavailable: 0:先创建新Pod,确认就绪后再删除旧Pod,零停机但资源占用高maxSurge: 0+maxUnavailable: 25%:先删除旧Pod再创建新Pod,资源占用低但会有短暂不可用maxSurge: 1+maxUnavailable: 1:平衡更新速度和资源占用,最常用配置
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
StatefulSet 独有字段
spec.serviceName:关联的Headless Service名称,用于Pod网络标识spec.podManagementPolicy:Pod管理策略OrderedReady:默认值,按顺序逐个启动或删除PodParallel:并行启动或删除Pod
spec.updateStrategy:更新策略RollingUpdate:滚动更新OnDelete:手动删除Pod后更新
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-statefulset
spec:
serviceName: my-headless-service
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
Job 与
CronJob 独有字段
spec.completions:仅Job,完成次数,默认为 1spec.parallelism:仅Job,并行Pod数量,默认为 1spec.backoffLimit:仅Job,失败重试次数,默认为 6spec.schedule:仅CronJob,Cron表达式,如0 * * * *(每小时)spec.concurrencyPolicy:仅CronJob,并发策略Allow:允许并发Forbid:禁止并发Replace:替换旧任务
spec.successfulJobsHistoryLimit:仅CronJob,保留成功Job数量,默认为 3spec.failedJobsHistoryLimit:仅CronJob,保留失败Job数量,默认为 1示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18apiVersion: batch/v1
kind: CronJob
metadata:
name: my-cronjob
spec:
schedule: "0 * * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: job
image: busybox
command: ["echo", "hello"]
restartPolicy: OnFailure
健康检查字段
spec.containers[].livenessProbe:适用于Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,存活探针,检测容器是否存活,失败则重启容器spec.containers[].readinessProbe:适用于Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,就绪探针,检测容器是否就绪,失败则从Service摘除spec.containers[].startupProbe:适用于Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,启动探针,检测容器是否启动完成,用于慢启动应用探测方式(三种探针通用):
httpGet:HTTP请求探测,需指定path和porttcpSocket:TCP端口探测,需指定portexec:执行命令探测,需指定command
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:1.21
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 3
startupProbe:
httpGet:
path: /health
port: 80
failureThreshold: 30
periodSeconds: 10
节点调度字段
spec.nodeSelector:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,简单的节点选择器,通过标签匹配节点spec.nodeName:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,直接指定节点名称,跳过调度器spec.tolerations:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,容忍度,允许 Pod 调度到有污点的节点示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeSelector:
disktype: ssd
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
containers:
- name: nginx
image: nginx:1.21
镜像拉取字段
spec.containers[].imagePullPolicy:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,镜像拉取策略,可选值:Always:每次都拉取镜像IfNotPresent(默认):本地不存在时才拉取Never:从不拉取,只使用本地镜像
spec.imagePullSecrets:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,拉取私有镜像的凭证,存储在 Secret 中示例:
1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
imagePullSecrets:
- name: my-registry-secret
containers:
- name: nginx
image: nginx:1.21
imagePullPolicy: IfNotPresent
环境变量字段
spec.containers[].env:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,环境变量列表,支持直接赋值和引用 ConfigMap/Secretspec.containers[].envFrom:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,从 ConfigMap 或 Secret 批量导入环境变量示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:1.21
env:
- name: ENV_VAR_1
value: "value1"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: password
envFrom:
- configMapRef:
name: my-config
重启策略字段
spec.restartPolicy:适用于 Pod,重启策略,可选值:Always(默认):容器退出后总是重启OnFailure:容器异常退出时重启Never:从不重启
示例:
1
2
3
4
5
6
7
8
9apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: nginx:1.21
服务账户字段
spec.serviceAccountName:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,指定 Pod 使用的 ServiceAccount,用于访问 API Serverspec.automountServiceAccountToken:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,是否自动挂载 ServiceAccount Token,默认为true示例:
1
2
3
4
5
6
7
8
9
10apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: my-sa
automountServiceAccountToken: false
containers:
- name: nginx
image: nginx:1.21
初始化容器字段
spec.initContainers:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,初始化容器列表,在主容器启动前按顺序执行,必须全部成功退出后主容器才会启动示例:
1
2
3
4
5
6
7
8
9
10
11
12apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
initContainers:
- name: init-db
image: busybox
command: ["sh", "-c", "echo Initializing..."]
containers:
- name: nginx
image: nginx:1.21
优先级字段
spec.priorityClassName:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,优先级类名,高优先级 Pod 抢占低优先级 Pod 资源spec.priority:适用于 Pod、Deployment、StatefulSet、DaemonSet、Job、CronJob,优先级数值,范围 1000000000 到 -2147483648示例:
1
2
3
4
5
6
7
8
9apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
priorityClassName: high-priority
containers:
- name: nginx
image: nginx:1.21
Istio
简介
Istio是最流行的服务网格(Service Mesh)实现,将流量治理、安全、可观测性等能力从业务代码中下沉到基础设施层,业务容器无感知- 架构分为两层:
- 控制面(
istiod):负责配置分发(Pilot)、证书签发(CA),是集群中的单一大脑 - 数据面(
Envoy):以sidecar形式注入到每个Pod,通过iptables透明劫持出入流量,所有经过Pod的请求都会先经过Envoy代理
- 控制面(
- 核心能力:
- 流量治理:按域名/路径/权重路由、灰度发布、重试、超时、熔断、会话保持
- 安全:服务间自动
mTLS、基于身份的访问控制(AuthorizationPolicy) - 可观测性:自动生成访问日志、指标(
Metrics)与调用链(Tracing)
Sidecar注入方式:- 命名空间标签:
kubectl label namespace [ns] istio-injection=enabled,该命名空间下所有新建Pod都会被注入 Pod级别:在spec.template.metadata.annotations中设置sidecar.istio.io/inject: "true"(或"false"排除)- 注入发生在
Pod创建时,已运行的Pod需要重建才能生效
- 命名空间标签:
安装
推荐使用
helm安装,分为两个chart,依赖顺序不能颠倒:1
2
3
4helm repo add istio https://istio-release.storage.googleapis.com/charts
kubectl create namespace istio-system
helm install istio-base istio/base -n istio-system
helm install istiod istio/istiod -n istio-system --waitbasechart定义了CRD与集群级别的角色等前置资源,istiodchart部署控制面本身常用配置(通过
istiod的values覆盖meshConfig):1
2
3
4
5
6
7
8
9
10
11istiod:
meshConfig:
accessLogFile: /dev/stdout # 开启访问日志,输出到容器标准输出
outboundTrafficPolicy:
mode: ALLOW_ANY # 未注册外部服务的出站流量默认放行(默认 REGISTRY_ONLY 会拒绝)
global:
proxy:
resources: # sidecar(Envoy)的资源限制,避免占用过多业务资源
limits:
cpu: 1000m
memory: 1Giistioctl是Istio的命令行工具,常用命令:istioctl proxy-status:查看所有sidecar与istiod的同步状态istioctl proxy-config route [pod]:查看指定sidecar的实际路由表,排查路由不生效问题istioctl analyze:静态分析集群内Istio配置的潜在冲突
Gateway
入口网关,控制哪些流量可以进入网格,相当于传统架构的负载均衡器 +
Nginx的server块spec.selector:通过标签匹配承载流量的ingress gatewayPod(通常部署在istio-system),一个网关Pod可被多个Gateway资源复用spec.servers:服务器列表,每个包含:port:监听端口(number、name、protocol)hosts:监听的域名列表tls:TLS配置,httpsRedirect: true将HTTP重定向到HTTPS;mode: SIMPLE终止TLS,证书通过credentialName引用Secret
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: my-gateway
spec:
selector:
istio: ingress # 匹配 ingress gateway Pod 上的标签
servers:
- port:
number: 80
name: http
protocol: HTTP
tls:
httpsRedirect: false
hosts:
- api.example.com
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: example-tls # 引用同命名空间的 kubernetes.io/tls 类型 Secret
hosts:
- api.example.com
VirtualService
路由规则,控制流量在网格内如何转发,相当于
Nginx的location块,需同时被Gateway(入口)或Service(内部)引用spec.hosts:匹配的目标域名,网关场景为外部域名,内部场景为Service的FQDNspec.gateways:绑定的Gateway名称,内部流量路由可省略(默认mesh)spec.http:HTTP路由规则列表,按顺序首次匹配生效:match:匹配条件(uri.prefix、headers、port等)route:转发目标,destination.host指向Service,destination.port.number指向端口weight:多目标按权重分流,灰度发布的基础rewrite、timeout、retries、fault(注入延迟/中止做故障演练)
spec.tcp:TCP路由,适用于非HTTP协议(如数据库)的端口转发示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: my-vs
spec:
hosts:
- api.example.com
gateways:
- my-gateway
http:
- match:
- uri:
prefix: /v2
route:
- destination:
host: api-v2.default.svc.cluster.local
port:
number: 80
- route: # 兜底规则,其余流量走稳定版本
- destination:
host: api-v1.default.svc.cluster.local
port:
number: 80
weight: 90
- destination:
host: canary.default.svc.cluster.local
port:
number: 80
weight: 10 # 10% 灰度
DestinationRule
目标策略,定义流量到达目标
Service后的转发策略,与VirtualService配合使用spec.host:作用的Service(需与VirtualService的route.destination.host一致)spec.trafficPolicy:流量策略:loadBalancer:负载均衡算法,consistentHash(基于源IP/指定Header的会话保持)、leastRequest、randomconnectionPool:连接池限制(tcp/http的最大连接数、并发请求数)outlierDetection:熔断策略,连续错误次数(consecutive5xxErrors)达到阈值后摘除实例tls:ISTIO_MUTUAL开启双向mTLS
spec.subsets:将同一Service按Pod标签划分为不同子集(如v1、v2),供VirtualService按subset精确路由示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: my-dr
spec:
host: api.default.svc.cluster.local
trafficPolicy:
loadBalancer:
consistentHash:
useSourceIp: true # 基于来源 IP 的会话保持
subsets:
- name: stable
labels:
version: stable
- name: canary
labels:
version: canary
ServiceEntry
将网格外部的服务注册进网格,让外部服务也能享受
Istio的路由、熔断与mTLS能力,是最能体现“替代自建代理”的资源典型场景:将外部
IP/域名伪装成集群内的Service,内部服务直接通过Service域名访问外部数据库或第三方APIspec.hosts:对外暴露的虚拟域名,通常用[name].[namespace].svc.cluster.local让内部访问无感知spec.addresses:为该条目分配的虚拟IP(可选)spec.ports:端口与协议(HTTP、TCP、MONGO等)spec.resolution:地址解析方式,STATIC(端点IP固定)、DNS(按域名解析)spec.location:MESH_EXTERNAL(外部服务)或MESH_INTERNALspec.endpoints:实际后端端点列表(address+ports)示例(将外部
MongoDB伪装成集群内Service):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: external-mongo
spec:
hosts:
- external-mongo.default.svc.cluster.local # 内部用该域名访问
ports:
- number: 27017
name: mongo
protocol: MONGO
resolution: STATIC
location: MESH_EXTERNAL
endpoints:
- address: 10.0.0.10 # 外部 MongoDB 实际地址
ports:
mongo: 27017
AuthorizationPolicy
访问控制策略,基于工作负载身份(而非
IP)决定谁可以访问谁,默认全部放行,一旦定义则未匹配的请求全部拒绝spec.selector:策略作用的Pod标签spec.action:ALLOW(白名单)、DENY(黑名单)、CUSTOMspec.rules[].from.source:请求来源,ipBlocks/remoteIpBlocks(IP黑白名单)、principals(对端服务身份)、namespacesspec.rules[].to.operation:请求目标,methods、paths、ports示例(网关层
IP黑名单):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: ingress-policy
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingress
action: DENY
rules:
- from:
- source:
remoteIpBlocks:
- 1.2.3.4/32
证书管理
Gateway的HTTPS证书通常配合cert-manager自动签发与续期,形成ClusterIssuer→Certificate→Secret(kubernetes.io/tls) →Gateway.credentialName的链路HTTP-01校验需要真实公网入口,通配符域名(*.example.com)必须使用DNS-01校验,此时需要一个DNS服务商的API凭证Secret(如Cloudflare的Api Token)示例(
DNS-01通配符证书):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-token
key: api-token
Charts 实践
以上能力在生产实践中通常都会沉淀为一个 helm
仓库,并按“基础设施 → 应用模板 →
代理组件”分层组织,这也是大家的普遍做法
总览
- 基础设施层:
base:集群初始化,创建基础命名空间与镜像仓库凭证(registry secret),并托管cert-manager依赖,作为其他所有chart的前置istio:以umbrella chart封装官方base+istiod依赖,统一注入meshConfig(访问日志格式、ALLOW_ANY出站策略、sidecar资源限制),并创建带istio-injection标签的istio-system命名空间ingress:封装官方gateway chart(部署ingress gatewayPod),配套ClusterIssuer、Cloudflare DNS凭证、AuthorizationPolicyIP黑名单等模板monitoring:聚合kube-prometheus-stack+loki+promtail+grafana+grafana-mcp依赖,并模板化大量Grafana告警规则(证书过期、Pod状态、CPU/内存、JVM、WebSocket等)与数据源配置
- 应用模板层:
common:最简无状态应用模板,仅Deployment+Service+ 镜像凭证spring-app:功能最全的Spring应用模板,见下文spring-job:一次性/定时任务模板,仅Job+ 密钥 + 存储,无Service与路由
- 代理组件层(纯
Istio资源,不包含任何业务镜像):simple-proxy:L7反向代理,Gateway+VirtualService+ServiceEntry+DestinationRule四件套,把外部域名流量转发到一组上游,可选consistentHash会话保持,替代自建Nginxmongo-proxy:L4代理,ServiceEntry将外部MongoDBIP注册为集群内Service,VirtualService的tcp规则把网关443端口转发到27017mongodb:bitnami mongodb依赖 +mongo-express管理界面,通过Istio网关暴露
- 环境特定层:
github-actions-cache-server:自托管GitHub Actions缓存服务(PVC+HPA+Ingress)aliyun-pod-ip:阿里云ack-extend-network-controller依赖,管理Pod弹性IP
应用模板的设计要点
以 spring-app 为例,一个生产级应用 chart
通常包含:
- 工作负载:
Deployment(探针、资源限制)+HPA(CPU利用率自动扩缩)+PDB(保证节点维护时的最小可用副本数) - 流量入口:
Service+Istio的Gateway/DestinationRule(可选会话保持),证书由cert-manager自动签发 - 安全:
ServiceAccount+ 最小化RBAC,关闭automountServiceAccountTokenNetworkPolicy默认拒绝出站,仅放行DNS,并显式屏蔽云厂商metadata网段(169.254.0.0/16、100.64.0.0/10),防止应用被SSRF后窃取云凭证- 数据库密钥、
CloudflareToken等以Secret模板管理
- 多云适配:同一
chart通过values切换对象存储挂载方案(oss/gcs/cos)与StorageClass(按云厂商提供不同存储模板) - 环境隔离:默认注入
nodeSelector: example.io/environment={{ .Release.Namespace }}与对应容忍度,让命名空间与节点环境一一对应,用户可整体覆盖 - 生命周期钩子:
post-install/post-upgradeJob执行数据库迁移(schema变更)等前置任务
沉淀的最佳实践
umbrella chart封装上游依赖:不直接部署第三方chart,而是以依赖(dependencies+condition开关)的方式包装,统一版本与定制,升级时只需改一处版本号- 版本统一为
0.0.0:由CI在发布时统一注入版本号,避免手工维护,可回溯到具体commit - 用
Istio资源替代传统代理:外部MySQL/MongoDB/第三方API的访问入口全部用ServiceEntry+VirtualService建模,业务方看到的是稳定的集群内域名,底层地址变更只需改chart的values - 可观测性即代码:
Grafana数据源、告警规则、通知渠道全部模板化在monitoringchart中,随应用一起评审与发布