云原生环境下的容器编排实践
容器编排基础概念
在云原生环境中,容器编排是至关重要的一环。容器编排是指对多个容器进行自动化管理、调度和协同工作的过程,其目的是确保容器化应用程序能够高效、可靠地运行。常见的容器编排工具包括 Kubernetes、Docker Swarm 和 Apache Mesos 等,其中 Kubernetes 是目前最流行且广泛应用的容器编排平台。
容器编排的核心任务之一是资源管理。容器虽然隔离性强,但仍然需要在宿主机上分配 CPU、内存等资源。以 Kubernetes 为例,它通过资源配额(Resource Quota)机制来限制命名空间(Namespace)内可使用的资源总量,例如可以限制一个命名空间最多只能使用 2 个 CPU 核心和 4GB 内存。同时,通过请求(Requests)和限制(Limits)来定义容器对资源的需求和上限。比如,一个 Web 应用容器可能请求 0.5 个 CPU 核心和 1GB 内存,限制为 1 个 CPU 核心和 2GB 内存。这样,Kubernetes 就能根据节点的资源情况,合理地将容器调度到合适的节点上运行。
容器间通信也是容器编排要解决的重要问题。在微服务架构下,一个应用可能由多个容器化的微服务组成,这些微服务之间需要相互通信。Kubernetes 提供了多种方式来实现容器间通信,比如服务(Service)。服务是一种抽象,它定义了一组 Pod(Kubernetes 中最小的可部署和可管理的计算单元,一个 Pod 可以包含一个或多个紧密相关的容器)的逻辑集合以及访问它们的策略。例如,一个电商应用中,订单服务可能需要与库存服务进行通信,通过在 Kubernetes 中定义相应的服务,订单服务就可以通过服务名称来访问库存服务,而无需关心库存服务具体运行在哪些 Pod 上以及它们的 IP 地址。
Kubernetes 架构剖析
-
控制平面组件 Kubernetes 的控制平面由多个关键组件构成,这些组件共同负责集群的管理和决策。
- kube - apiserver:作为 Kubernetes 的前端门面,它是整个集群的控制入口。所有对集群资源的操作,如创建、更新、删除 Pod、Service 等,都要通过 kube - apiserver 来进行。它提供了 RESTful API 接口,供管理员、Kubernetes 客户端以及其他组件进行交互。例如,当使用 kubectl 命令行工具创建一个新的 Pod 时,实际上是向 kube - apiserver 发送了一个 POST 请求,请求体中包含了 Pod 的定义信息。kube - apiserver 接收到请求后,会对请求进行认证、授权和准入控制等一系列处理,然后将资源对象的定义存储到 etcd 中。
- etcd:是 Kubernetes 的分布式键值存储,用于保存集群的所有状态信息。所有的资源对象定义,如 Pod、Service、Namespace 等,都以键值对的形式存储在 etcd 中。etcd 采用了 Raft 一致性算法,确保数据在多个节点之间的一致性和高可用性。例如,当 kube - apiserver 接收到创建 Pod 的请求并处理后,会将 Pod 的相关信息存储到 etcd 中。如果 etcd 集群中的某个节点出现故障,其他节点可以通过 Raft 协议自动选举出新的 leader,保证数据的正常读写,从而确保 Kubernetes 集群的状态信息不丢失。
- kube - scheduler:负责将 Pod 调度到合适的节点上运行。它会根据一系列的调度算法和策略,综合考虑节点的资源情况(如 CPU、内存、磁盘空间等)、节点的标签(Label)、Pod 的资源需求以及其他约束条件,来选择最佳的节点。例如,一个具有 GPU 需求的深度学习任务 Pod,kube - scheduler 会优先选择带有 GPU 且资源满足需求的节点。kube - scheduler 从 etcd 中获取集群中的节点信息和待调度的 Pod 信息,经过计算后,将 Pod 绑定到合适的节点上,然后通过 kube - apiserver 更新 Pod 的状态信息到 etcd 中。
- kube - controller - manager:包含多个控制器,这些控制器负责维护集群的状态。例如,副本控制器(Replication Controller)确保指定数量的 Pod 副本始终处于运行状态。如果某个 Pod 由于节点故障或其他原因意外终止,副本控制器会根据定义的副本数量,在其他可用节点上重新创建新的 Pod。再如,节点控制器(Node Controller)负责监控节点的健康状态,当发现某个节点出现故障时,会将该节点上运行的 Pod 重新调度到其他健康节点上,保证应用的可用性。
-
节点组件 在 Kubernetes 集群的每个节点上,都运行着一些关键组件,用于支持容器的运行和与控制平面的交互。
- kubelet:是节点上最重要的组件,负责与控制平面进行通信,管理节点上的 Pod。kubelet 定期从 kube - apiserver 获取分配到本节点的 Pod 清单,根据清单信息创建、启动和停止容器。例如,当 kube - scheduler 将一个 Pod 调度到某个节点后,kube - apiserver 会将该 Pod 的信息更新到 etcd 中,kubelet 通过监听 etcd 中的变化,获取到该 Pod 的定义信息,然后根据定义创建容器。同时,kubelet 还会向 kube - apiserver 汇报节点的资源使用情况和 Pod 的运行状态等信息。
- kube - proxy:负责实现 Kubernetes 服务的网络代理功能。它在每个节点上运行,通过 iptables 或 IPVS 等技术,将发往 Service 的流量转发到对应的 Pod 上。例如,当一个客户端向某个 Service 发起请求时,kube - proxy 会根据 Service 的定义和负载均衡策略,将请求转发到其中一个后端 Pod 上。kube - proxy 会从 etcd 中获取 Service 和 Endpoints(代表 Service 后端的 Pod 集合)的信息,动态更新 iptables 或 IPVS 规则,以确保流量的正确转发。
- Container Runtime:容器运行时,负责运行容器。常见的容器运行时包括 Docker、containerd 等。以 Docker 为例,kubelet 通过调用 Docker 的 API 来创建、启动、停止容器。例如,当 kubelet 接收到创建 Pod 的指令后,会根据 Pod 中容器的镜像信息,调用 Docker 从镜像仓库中拉取镜像,然后创建并启动容器。
容器编排中的资源管理
- 资源请求与限制 在 Kubernetes 中,为了实现对容器资源的有效管理,每个容器都可以定义资源请求(Requests)和资源限制(Limits)。资源请求表示容器期望使用的资源量,而资源限制则是容器能够使用的资源上限。 例如,对于一个简单的 Node.js Web 应用容器,可以在 Pod 的定义文件中这样设置资源请求和限制:
apiVersion: v1
kind: Pod
metadata:
name: nodejs - app - pod
spec:
containers:
- name: nodejs - app - container
image: my - nodejs - app - image:latest
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "1Gi"
在这个例子中,cpu: "250m"
表示请求 0.25 个 CPU 核心,memory: "512Mi"
表示请求 512MB 内存;cpu: "500m"
表示 CPU 限制为 0.5 个核心,memory: "1Gi"
表示内存限制为 1GB。这样,Kubernetes 在调度 Pod 时,会根据节点的可用资源情况,确保有足够的资源满足 Pod 中容器的请求。同时,如果容器试图使用超过限制的资源,系统会对其进行限制,例如当容器的内存使用超过 1GB 时,可能会被 OOM(Out - Of - Memory)杀手终止。
- 资源配额与限制范围 资源配额(Resource Quota)用于在命名空间(Namespace)级别对资源进行限制。通过设置资源配额,可以控制一个命名空间内可使用的资源总量,防止某个命名空间过度消耗集群资源。 例如,可以创建一个资源配额对象来限制命名空间内 Pod 的数量、CPU 和内存的使用总量:
apiVersion: v1
kind: ResourceQuota
metadata:
name: my - quota
namespace: my - namespace
spec:
hard:
pods: "10"
requests.cpu: "2"
requests.memory: "4Gi"
limits.cpu: "4"
limits.memory: "8Gi"
上述配置表示在 my - namespace
命名空间内,最多只能创建 10 个 Pod,所有 Pod 的 CPU 请求总量不能超过 2 个核心,内存请求总量不能超过 4GB,CPU 限制总量不能超过 4 个核心,内存限制总量不能超过 8GB。这样,在该命名空间内创建 Pod 时,如果资源请求超过配额,创建操作将被拒绝,从而保证了集群资源的合理分配和使用。
容器间通信与网络策略
- Kubernetes 服务类型
Kubernetes 提供了多种服务类型来满足不同场景下的容器间通信需求。
- ClusterIP:这是默认的服务类型,它为 Service 在集群内部提供一个虚拟 IP 地址,只能在集群内部访问。例如,在一个微服务架构的应用中,订单服务和库存服务都运行在集群内部,它们之间的通信可以通过 ClusterIP 类型的服务来实现。当创建一个 ClusterIP 类型的服务时,Kubernetes 会为其分配一个虚拟 IP 地址,集群内的其他 Pod 可以通过该虚拟 IP 地址和服务端口来访问对应的后端 Pod。例如:
apiVersion: v1
kind: Service
metadata:
name: inventory - service
spec:
selector:
app: inventory
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
在这个例子中,selector
字段指定了该服务对应的后端 Pod 标签为 app: inventory
,port
字段表示服务对外暴露的端口为 8080,targetPort
字段表示后端 Pod 实际监听的端口也是 8080。这样,集群内其他 Pod 就可以通过 inventory - service:8080
来访问库存服务。
- NodePort:这种服务类型在每个节点上开放一个指定的端口,通过节点的 IP 地址加上该端口号,就可以从集群外部访问服务。例如,当需要将一个内部的 Web 应用暴露给外部用户访问时,可以使用 NodePort 类型的服务。假设节点的 IP 地址为 192.168.1.100
,服务的 NodePort 为 30000
,那么外部用户就可以通过 http://192.168.1.100:30000
来访问该 Web 应用。在定义 NodePort 服务时,可以如下配置:
apiVersion: v1
kind: Service
metadata:
name: web - service
spec:
selector:
app: web - app
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30000
type: NodePort
这里 nodePort
字段指定了在节点上开放的端口号为 30000。
- LoadBalancer:主要用于云环境中,它会为服务分配一个外部的负载均衡器,将外部流量均匀地转发到后端的 Pod 上。例如在 Amazon EKS(Elastic Kubernetes Service)中,创建一个 LoadBalancer 类型的服务时,AWS 会自动为其分配一个 Elastic Load Balancer(ELB)。这种服务类型适用于需要大规模对外提供服务的场景,能够提供高可用性和可扩展性。其配置示例如下:
apiVersion: v1
kind: Service
metadata:
name: my - external - service
spec:
selector:
app: my - app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
创建该服务后,Kubernetes 会向云提供商请求一个负载均衡器,并将其与服务关联起来,外部用户可以通过负载均衡器的地址来访问服务。
- 网络策略
网络策略(Network Policy)用于定义 Pod 之间的网络访问规则,增强集群的网络安全性。它基于标签选择器来定义哪些 Pod 之间可以通信。
例如,假设有两个命名空间
production
和development
,在production
命名空间中有一个后端服务 Pod,标签为app: backend - prod
,在development
命名空间中有一个前端服务 Pod,标签为app: frontend - dev
。如果只想允许frontend - dev
Pod 访问backend - prod
Pod,可以创建如下网络策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow - frontend - to - backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend - prod
ingress:
- from:
- namespaceSelector:
matchLabels:
name: development
podSelector:
matchLabels:
app: frontend - dev
ports:
- protocol: TCP
port: 8080
在这个网络策略中,podSelector
选择了 production
命名空间中标签为 app: backend - prod
的 Pod,ingress
部分定义了允许来自 development
命名空间中标签为 app: frontend - dev
的 Pod 通过 TCP 端口 8080 进行访问。这样就精确地控制了 Pod 之间的网络流量,提高了集群的安全性。
容器编排中的存储管理
- Volume 概述 在容器化应用中,容器的文件系统是临时的,当容器重启或删除时,容器内的数据会丢失。为了持久化存储数据,Kubernetes 引入了 Volume(卷)的概念。Volume 是一个可以被挂载到 Pod 中一个或多个容器的目录,它独立于容器的生命周期,即使容器重启或删除,Volume 中的数据仍然可以保留。 例如,对于一个数据库容器,需要将数据库的数据文件存储在一个持久化的位置,就可以通过 Volume 来实现。在 Pod 的定义文件中,可以如下定义 Volume:
apiVersion: v1
kind: Pod
metadata:
name: mysql - pod
spec:
containers:
- name: mysql - container
image: mysql:latest
env:
- name: MYSQL_ROOT_PASSWORD
value: password
volumeMounts:
- name: mysql - data - volume
mountPath: /var/lib/mysql
volumes:
- name: mysql - data - volume
emptyDir: {}
在这个例子中,volumes
部分定义了一个名为 mysql - data - volume
的 Volume,类型为 emptyDir
,表示这是一个临时的空目录,在 Pod 创建时创建,在 Pod 删除时删除。volumeMounts
部分将这个 Volume 挂载到 mysql - container
容器的 /var/lib/mysql
目录下,这样 MySQL 数据库的数据文件就会存储在这个 Volume 中,即使 mysql - container
容器重启,数据也不会丢失。
- 持久化卷(PersistentVolume)与持久化卷声明(PersistentVolumeClaim)
虽然
emptyDir
类型的 Volume 可以在 Pod 生命周期内保存数据,但它依赖于 Pod,当 Pod 被删除时数据也会丢失。为了实现更持久化的存储,Kubernetes 引入了持久化卷(PersistentVolume,简称 PV)和持久化卷声明(PersistentVolumeClaim,简称 PVC)。- 持久化卷(PV):是集群中由管理员预先创建的一段存储,它独立于任何单个 Pod,可以被多个 Pod 共享。PV 可以是各种存储类型,如 NFS、Ceph、AWS EBS 等。例如,创建一个 NFS 类型的 PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: my - nfs - pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
server: 192.168.1.10
path: /nfs - share
在这个例子中,定义了一个容量为 10GB 的 PV,访问模式为 ReadWriteMany
,表示可以被多个 Pod 以读写方式挂载。persistentVolumeReclaimPolicy
设置为 Recycle
,表示当 PV 被释放时,会尝试清理其中的数据。nfs
部分指定了 NFS 服务器的地址和共享路径。
- 持久化卷声明(PVC):是用户对存储的请求,它从 PV 中申请资源。例如,一个应用需要使用上面创建的 NFS PV,可以创建如下 PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my - nfs - pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
在这个 PVC 中,指定了访问模式为 ReadWriteMany
,请求的存储容量为 5GB。Kubernetes 会根据 PVC 的要求,从可用的 PV 中选择一个满足条件的 PV 进行绑定。然后在 Pod 中就可以使用这个 PVC:
apiVersion: v1
kind: Pod
metadata:
name: my - app - pod
spec:
containers:
- name: my - app - container
image: my - app - image:latest
volumeMounts:
- name: my - nfs - volume
mountPath: /app/data
volumes:
- name: my - nfs - volume
persistentVolumeClaim:
claimName: my - nfs - pvc
这样,my - app - pod
中的 my - app - container
容器就可以通过 /app/data
目录访问到 NFS 存储中的数据,实现了数据的持久化存储。
容器编排实践案例
- 电商微服务架构容器化部署
假设要构建一个简单的电商微服务架构,包含用户服务、商品服务、订单服务和支付服务。每个服务都以容器的形式进行部署,并使用 Kubernetes 进行容器编排。
- 创建 Docker 镜像:首先,为每个微服务创建 Docker 镜像。以用户服务为例,假设用户服务是一个基于 Spring Boot 的 Java 应用,其 Dockerfile 内容如下:
FROM openjdk:11 - jre - slim
COPY target/user - service - 1.0.0.jar /app/user - service.jar
WORKDIR /app
ENTRYPOINT ["java", "-jar", "user - service.jar"]
通过 docker build -t user - service:1.0.0.
命令构建 Docker 镜像,并将其推送到镜像仓库,如 Docker Hub 或私有镜像仓库。
- 定义 Kubernetes 资源对象:
- Pod 定义:以用户服务 Pod 为例,其定义文件如下:
apiVersion: v1
kind: Pod
metadata:
name: user - service - pod
labels:
app: user - service
spec:
containers:
- name: user - service - container
image: user - service:1.0.0
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "200m"
memory: "512Mi"
这里定义了一个名为 user - service - pod
的 Pod,包含一个 user - service - container
容器,使用 user - service:1.0.0
镜像,并设置了资源请求和限制。
- Service 定义:为用户服务创建一个 ClusterIP 类型的 Service,使其可以被其他服务访问:
apiVersion: v1
kind: Service
metadata:
name: user - service
spec:
selector:
app: user - service
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
这样,其他服务就可以通过 user - service:8080
来访问用户服务。
- 部署与扩展:使用 kubectl apply -f user - service - pod.yaml
和 kubectl apply -f user - service - service.yaml
命令分别创建用户服务的 Pod 和 Service。如果业务量增加,需要扩展用户服务的实例数量,可以通过修改 Pod 的副本数量来实现。例如,将用户服务的 Pod 副本数量扩展到 3 个:
apiVersion: apps/v1
kind: Deployment
metadata:
name: user - service - deployment
spec:
replicas: 3
selector:
matchLabels:
app: user - service
template:
metadata:
labels:
app: user - service
spec:
containers:
- name: user - service - container
image: user - service:1.0.0
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "200m"
memory: "512Mi"
然后使用 kubectl apply -f user - service - deployment.yaml
命令进行部署,Kubernetes 会自动创建 3 个用户服务的 Pod 实例,并通过 Service 进行负载均衡。
- 高可用 Web 应用部署
为了构建一个高可用的 Web 应用,使用 Kubernetes 进行容器编排,并结合负载均衡器。
- 前端与后端服务容器化:假设前端是一个基于 React 的 Web 应用,后端是一个基于 Node.js 的 API 服务。分别为前端和后端创建 Docker 镜像,并推送到镜像仓库。
- Kubernetes 资源定义:
- 后端服务:定义后端服务的 Deployment 和 Service。Deployment 如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend - deployment
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend - container
image: backend - image:latest
resources:
requests:
cpu: "200m"
memory: "512Mi"
limits:
cpu: "400m"
memory: "1Gi"
Service 定义为:
apiVersion: v1
kind: Service
metadata:
name: backend - service
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
- **前端服务**:前端服务的 Deployment 和 Service 定义类似,不过 Service 类型设置为 NodePort,以便外部访问:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend - deployment
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend - container
image: frontend - image:latest
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "200m"
memory: "512Mi"
Service 定义为:
apiVersion: v1
kind: Service
metadata:
name: frontend - service
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 3000
nodePort: 30000
type: NodePort
- **负载均衡配置**:在云环境中,可以创建一个 LoadBalancer 类型的 Service 来对外提供服务。例如,在 AWS EKS 中,可以如下定义:
apiVersion: v1
kind: Service
metadata:
name: web - app - loadbalancer
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
创建该 Service 后,AWS 会自动分配一个 Elastic Load Balancer,将外部流量均匀地转发到前端服务的多个 Pod 上,实现高可用性和可扩展性。同时,前端服务可以通过 backend - service:8080
访问后端服务,完成整个 Web 应用的功能。
容器编排中的监控与故障处理
- 监控指标与工具
在容器编排环境中,监控是确保应用程序健康运行的关键。常见的监控指标包括 CPU 使用率、内存使用率、网络流量、磁盘 I/O 等。
- Prometheus:是一款流行的开源监控系统,它通过拉取(Pull)的方式从目标采集监控数据。在 Kubernetes 环境中,可以部署 Prometheus 来监控集群中的各种资源和应用。例如,可以通过 Prometheus Operator 来简化 Prometheus 的部署和管理。首先,定义一个 Prometheus 实例的自定义资源(Custom Resource,简称 CR):
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: my - prometheus
spec:
replicas: 2
serviceAccountName: prometheus - k8s
resources:
requests:
memory: 400Mi
cpu: 100m
limits:
memory: 800Mi
cpu: 200m
serviceMonitorSelector:
matchLabels:
team: frontend
这里定义了一个具有 2 个副本的 Prometheus 实例,并通过 serviceMonitorSelector
选择要监控的目标。然后,可以创建 ServiceMonitor 资源来指定具体的监控目标,例如监控前端服务的 Pod:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: frontend - service - monitor
labels:
team: frontend
spec:
selector:
matchLabels:
app: frontend
endpoints:
- port: http - metrics
interval: 30s
这样,Prometheus 就会定期从标签为 app: frontend
的 Pod 的 http - metrics
端口采集监控数据。
- Grafana:通常与 Prometheus 结合使用,用于数据可视化。可以在 Grafana 中创建各种仪表盘(Dashboard)来展示 Prometheus 采集到的监控数据。例如,创建一个展示 CPU 和内存使用率的仪表盘,通过配置数据源为 Prometheus,然后在仪表盘上添加相应的图表,设置查询语句来获取 Prometheus 中的数据。如查询前端服务 Pod 的 CPU 使用率:sum(rate(container_cpu_usage_seconds_total{app="frontend"}[5m])) by (pod)
,就可以在 Grafana 仪表盘上直观地看到前端服务 Pod 的 CPU 使用率随时间的变化情况。
- 故障处理与自愈机制
在容器编排环境中,故障处理和自愈机制是保障应用高可用性的重要手段。
- Pod 故障处理:Kubernetes 的控制器(如 Deployment、StatefulSet 等)会自动监控 Pod 的状态。当 Pod 出现故障(如容器崩溃、节点故障等)时,控制器会根据定义的策略进行处理。例如,对于 Deployment,默认会重新创建故障的 Pod,确保副本数量始终满足定义的要求。假设一个名为
my - app - deployment
的 Deployment 定义了 3 个副本,如果其中一个 Pod 由于容器内的应用程序崩溃而终止,Kubernetes 会自动在其他可用节点上创建一个新的 Pod,以维持 3 个副本的数量。 - 节点故障处理:当节点出现故障时,Kubernetes 的节点控制器会检测到节点的状态变化。如果节点不可用,节点控制器会将该节点上运行的 Pod 重新调度到其他健康节点上。例如,在一个包含 5 个节点的 Kubernetes 集群中,如果其中一个节点因为硬件故障而离线,节点控制器会识别到该节点的状态为
NotReady
,然后将该节点上运行的所有 Pod 标记为待调度状态,kube - scheduler 会根据节点的资源情况和其他调度策略,将这些 Pod 重新调度到其他 4 个健康节点上,确保应用的正常运行。 - 健康检查:为了确保容器内的应用程序正常运行,可以在 Pod 中定义健康检查。Kubernetes 支持两种类型的健康检查:存活检查(livenessProbe)和就绪检查(readinessProbe)。存活检查用于判断容器是否正在运行,如果容器未通过存活检查,Kubernetes 会自动重启容器。例如,对于一个基于 Node.js 的 Web 应用容器,可以在 Pod 定义中添加如下存活检查:
- Pod 故障处理:Kubernetes 的控制器(如 Deployment、StatefulSet 等)会自动监控 Pod 的状态。当 Pod 出现故障(如容器崩溃、节点故障等)时,控制器会根据定义的策略进行处理。例如,对于 Deployment,默认会重新创建故障的 Pod,确保副本数量始终满足定义的要求。假设一个名为
apiVersion: v1
kind: Pod
metadata:
name: my - nodejs - app - pod
spec:
containers:
- name: my - nodejs - app - container
image: my - nodejs - app - image:latest
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
这里通过 httpGet
方式,每隔 20 秒向容器的 /healthz
路径发送请求,从容器启动 15 秒后开始检查。如果连续多次请求失败,Kubernetes 会认为容器不健康,从而重启容器。就绪检查用于判断容器是否准备好接收流量,如果容器未通过就绪检查,Kubernetes 不会将流量发送到该容器。例如,可以类似地定义就绪检查:
apiVersion: v1
kind: Pod
metadata:
name: my - nodejs - app - pod
spec:
containers:
- name: my - nodejs - app - container
image: my - nodejs - app - image:latest
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
这样,只有当容器通过就绪检查后,才会被添加到 Service 的后端 Endpoints 中,接收外部流量,从而保证了应用的稳定性和可靠性。
通过以上对容器编排的深入探讨,包括基础概念、Kubernetes 架构、资源管理、容器间通信、存储管理、实践案例以及监控与故障处理等方面,希望能帮助读者全面理解和掌握云原生环境下的容器编排实践,构建高效、可靠的容器化应用。