上一节我们介绍了《Kubernetes Service详解》,Service是我们应用的访问入口,真正的应用是跑在后端的容器里面的,而这些容器都是以容器组(Pod)为单位进行管理和调度的,本节主要给大家介绍容器组(Pod)以及容器组控制器(Controllers).
如何理解Pod? 我们可以把它想象成一个虚拟机(VM), 一个Pod里面通常只跑一个应用容器,有时候我们的应用容器之间耦合度比较紧密,我们也可以让它们跑在一个Pod里面。同一Pod里面的容器共享存储和网络。Pod是Kubernetes管理与调度的最小单位。
那么如何使用Pod呢,下面通过一段最简单的编排代码定义一个Pod:
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
containers:
- image: nginx
name: nginx-name
ports:
- containerPort: 80
上面的编排创建一个名为nginx的Pod,Pod里面只运行一个容器(name=nginx-name),容器里面跑真正的nginx应用服务。
容器探针主要用于诊断容器里面应用是否正常,为修复容器或服务负载提供依据。
容器探针有两种:存活探针(liveness)和就绪探针(readiness)。
主要用于判断容器是否处于运行状态,比如当服务crash或者死锁等情况发生时,kubelet会kill掉容器, 然后根据其设置的restartPolicy进行相应操作(可能会在本机重新启动容器,或者因为设置Kubernetes QoS,本机没有资源情况下会被分发到其他机器上重新创建)。
主要用于判断服务是否已经正常工作,如果服务没有加载完成或工作异常,服务所在的Pod的IP地址会从服务的endpoints中被移除,也就是说,当服务没有ready时,会将其从服务的load balancer中移除,不会再接受或响应任何请求。
以上两种探针都支持以下三种类型的实现:
探针类型 | 说明 | 通过健康检查标准 |
---|---|---|
ExecAction | 容器内部执行shell命令 | shell命令返回0 |
HTTPGetAction | 通过容器的IP、port、path用HTTP Get请求进行检查 | 200<=返回值<400 |
TCPSocketAction | 通过容器的IP、port执行tcp进行检查 | port是否打开 |
下面使用一个简单的例子说明:
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
containers:
- image: nginx
name: nginx-name
ports:
- containerPort: 80
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 8
periodSeconds: 2
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 8
periodSeconds: 2
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
上面的例子中添加了两个探针:存活探针(livenessProbe)和就绪探针(readinessProbe)。
存活探针使用TCPSocketAction实现,就绪探针使用HTTPGetAction实现。
解释下以上几个参数:
容器钩子主要是让容器可以优雅的终止,或者启动后做一些初始化操作。
主要有两个:PostStart 和 PreStop
以上两种钩子都支持以下两种类型的实现:
Action类型 | 说明 | 成功标志 |
---|---|---|
ExecAction | 容器内部执行shell命令 | shell命令返回0 |
HTTPGetAction | 通过容器的IP、port、path用HTTP Get请求进行检查 | 200<=返回值<400 |
下面使用一个简单的例子说明:
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
containers:
- image: nginx
name: nginx-name
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo postStart handler > /tmp/started.txt"]
preStop:
exec:
command: ["/bin/sh", "-c", "echo preStop handler > /tmp/stopping.txt"]
以上例子实现的是:
Kubernetes支持给容器设置资源,可以设置最小请求的资源和最大使用的资源。
通过resources.requests 设置容器最小需要的资源,也用于调度时决策。
通过resources.limits 设置容器运行占用的最大资源。
通过一个简单的例子说明下:
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
containers:
- image: nginx
name: nginx-name
ports:
- containerPort: 80
resources:
requests:
memory: "60Mi"
cpu: "0.1"
limits:
memory: "128Mi"
cpu: "0.2"
以上例子中:
设置容器最小需要的资源:内存:60Mi,cpu:0.1
设置容器最大占用的资源:内存:128Mi,cpu:0.2
针对内存和CPU的单位进行说明:
内存单位:
内存资源是以字节为单位的,可以表示为纯整数或者固定的十进制数字,后缀可以是E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.比如,下面几种写法表示相同的数值:
128974848, 129e6, 129M , 123Mi
CPU单位:
整数或者小数均可,整数比较好理解。
如果是小数,那么一个容器申请0.5个CPU,就相当于申请1个CPU的一半,你也可以加个后缀m 表示千分之一的概念。比如说100m的CPU,100豪的CPU和0.1个CPU都是一样的。
平常使用的过程中,我们很少会直接创建Pod,因为Pod的生命周期是短暂的,且没有自愈能力。因此我们都会通过Controller来管理Pod.
Controller可以创建和管理多个Pod,提供副本管理,滚动升级和集群级别的自愈能力。
下面介绍Kubernetes中几种常用的Controller.
介绍Deployment之前,先简单说下副本控制器,主要是用于确保Pod的实际副本数跟用户定义的副本数保持一致,少增多减。平时我们不需要手动创建副本控制器,而是用更高层次的Deployment,它能管理副本控制器,并提供对Pod的更新等功能。
Deployment的定义:为Pod和副本控制器提供声明式更新。
它主要有以下几个功能:
template
字段来声明Pod的新状态。set image
可以升级或更新应用的镜像。
kubectl set image deploy nginx nginx-name=nginx:v2
scale
可以伸缩应用的副本数。
kubectl scale deploy nginx --replicas=3
--record
,都会保存下来。
kubectl create -f deployment.yaml --record
rollout status
可以查看指定Deployment的状态.
kubectl rollout status deploy nginx
rollout history
可以查看历史版本信息。
kubectl rollout history deploy nginx
rollout undo
可以回滚到上一个版本
kubectl rollout undo deploy nginx
rollout undo --to-revision=‘指定版本’
可以回滚到指定版本。
kubectl rollout undo deploy nginx --to-revision=2
rollout pause
暂停更新
kubectl rollout pause deploy nginx
rollout resume
恢复已暂停资源
kubectl rollout resume deploy nginx
StatefulSet是为了解决有状态服务的问题(Deployment是为无状态服务而设计的)。
在具有以下特点时使用StatefulSet:
StatefulSet的稳定性主要通过以下几点体现:
在创建StatefulSet的时候,通过volumeClaimTemplates
字段设置PVC的模板,这样它的每一个副本就会拥有各自的数据卷。
为StatefulSet部署的应用创建无头服务(Headless Service),这样集群内部每个成员都会有一个唯一的DNS域名来作为其网络标识,成员之间通过这个域名进行通信。
StatefulSet创建出来的每个Pod,会得到以下域名:
$(podname).$(servicename).$(namespace).svc.cluster.local
StatefulSet的有序性主要通过podManagementPolicy
字段来设置:
DaemonSet能够让指定Pod部署到所有Node节点。
当有新的节点加入到Kubernetes集群中时,DaemonSet Controller会自动在该节点上部署指定Pod;
被DaemonSet Controller创建的Pod会默认指定.spec.nodeName,所以pod会被k8s的调度器忽略.
当k8s的调度器没有启动的时候,DaemonSet Controller也能工作.
DaemonSet通常用来部署一些集群的日志、监控或者其他系统管理应用。
本文介绍了Kubernetes 工作负载(Workloads)的使用。我们知道Pod是对容器的封装,Controller是对Pod的封装,通常我们写编排文件都是通过Controller来定义我们的应用,避免直接使用Pod,因为Pod的生命周期比较短,且没有自愈能力。下节分享《Kubernetes 存储管理》。