K8s<五>
七、Kubernetes Pod 资源1、Pod 服务状态1、无状态服务是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。多个实例可以共享相同的持久化数据。例如:nginx 实例,tomcat 实例等相关的 k8s 资源有:ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创
七、Kubernetes Pod 资源
1、Pod 服务状态
1、无状态服务
-
是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。
-
多个实例可以共享相同的持久化数据。例如:nginx 实例,tomcat 实例等
-
相关的 k8s 资源有:ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创建的 pod 序号都是随机值。并且在缩容的时候并不会明确缩容某一个pod,而是随机的,因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以。
2、有状态服务
-
宠物和牛的类比,农场主的牛如果病了可以丢掉再重新买一头,如果宠物主的宠物病死了是没法找到一头一模一样的宠物的。有状态服务可以说是需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql数据库、kafka、zookeeper等)
-
每个实例都需要有自己独立的持久化存储,并且在 k8s 中是通过申明模板来进行定义。持久卷申明模板在创建 pod 之前创建,绑定到 pod 中,模板可以定义多个。
volumeClaimTemplates:
- metadata:
name: zookeeper
spec:
selector:
matchLabels:
app: zookeeper
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 3Gi
-
有状态的 pod 是用来运行有状态应用的,所以其在数据卷上存储的数据非常重要,在 Statefulset 缩容时删除这个声明将是灾难性的,特别是对于 Statefulset 来说,缩容就像减少其 replicas 数值一样简单。基于这个原因,当你需要释放特定的持久卷时,需要手动删除对应的持久卷声明。
-
相关的 k8s 资源为:statefulSet,由于是有状态的服务,所以每个 pod 都有特定的名称和网络标识。比如 pod 名是由 statefulSet名+有序的数字组成(0、1、2…)
-
在进行缩容操作的时候,可以明确知道会缩容哪一个 pod,从数字最大的开始。并且 Statefulset 在有实例不健康的情况下是不允许做缩容操作的。
-
StatefulSet 缩容,任何时候只会操作 一个 pod 实例,所以有状态应用的缩容不会很迅速。举例来说, 一个分布式存储应用若同时下线多个节点 ,则可能导致其数据丢失 。 比如说一个数据项副本数设置为 2 的数据存储应用, 若同时有两个节点下线,一份数据记录就会丢失,如果它正好保存在这两个节点上 。 若缩容是线性的 ,则分布式存储应用就有时间把丢失的副本复制到其他节点 ,保证数据不会丢失。
2、Pod 基本介绍
-
kubernetes 中的一切都可以理解为是一种资源对象,pod,rc,service,都可以理解是 一种资源对象。
-
pod 由一个叫 ”pause“ 的根容器,加上一个或多个用户自定义的容器构造。pause 的状态带便了这一组容器的状态,pod里多个业务容器共享pod的Ip和数据卷。
-
kubernetes 环境下,pod 是容器的载体,所有的容器都是在 pod 中被管理,一个或多个容器放在 pod 里作为一个单元方便管理。docker 和 kubernetes 也不是一家公司的,如果做一个编排部署的工具,为了更好的管理别人公司开发的产品,然后就把 docker 容器放在了 pod 里,在 kubernetes 的集群环境下,直接管理 pod,然后对于docker 容器的操作,封装在 pod 里,不直接操作。
1、Pod 的创建过程
-
Pod 是 Kubernetes 的基础单元,了解其创建的过程,更有助于理解系统的运作。
- ①用户通过 kubectl 或其他 API 客户端提交 Pod Spec 给 API Server。
- ②API Server 尝试将 Pod 对象的相关信息存储到 etcd 中,等待写入操作完成,API Server 返回确认信息到客户端。
- ③API Server 开始通告 etcd 中的状态变化。
- ④所有的 Kubernetes 组件通过 “watch” (动态监控) etcd 机制跟踪检查 API Server 上的相关信息变动。
- ⑤kube-scheduler(调度器)通过其 “watch”(动态监控)etcd 检测到 API Server 创建了新的 Pod 对象但是没有绑定到任何工作节点。
- ⑥kube-scheduler 为 Pod 对象挑选一个工作节点并将结果信息更新到 API Server。
- ⑦调度结果新消息由 API Server 更新到 etcd,并且 API Server 也开始反馈该 Pod 对象的调度结果。
- ⑧Pod 被调度到目标工作节点上的 kubelet 尝试在当前节点上调用 docker engine 进行启动容器,并将容器的状态结果返回到 API Server。
- ⑨API Server 将 Pod 信息存储到 etcd 系统中。
- ⑩在 etcd 确认写入操作完成,API Server 将确认信息发送到相关的 kubelet。
2、Pod 类型
-
静态Pod不存放在etcd存储里,而是存放在某个具体的 Node 上的一个具体文件中,并且只在此 Node 上启动运行。静态 Pod 是由 kubelet 进行管理的仅存在于特定 Node 上的 pod.它们不能通过 API Server 进行管理,无法与 ReplicationController,Deployment 或者 DaemonSet 进行关联,也无法进行健康检查。不常用,所以了解就好
-
普通的 Pod 一旦被创建,就会被存储到 etcd 中,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定(Binding),该 Node 上的 kubelet 进程会将其实例化成一组相关的 Docker 容器并启动起来。当 Pod 里的某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod(重启Pod里的所有容器);如果 Pod 所在的 Node 宕机,则会将这个 Node 上的所有 Pod 重新调度到其他节点上运行。
3、Pod、容器与Node的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ow3rpxoG-1610418200971)(assets/8198f5ace2255bd4f515e3db6362cd5d.png)]
- 定义一个简单的Pod资源文件:
apiVersion: v1
kind: Pod
metadata:
name: myweb
labels:
name: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app: v1
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: 'mysql'
- name: MYSQL_SERVICE_PORT
value: '3306'
-
kind 为 pod 表明这是一个Pod的定义,
-
metadata 里的 name 属性为 Pod 的名字,metadata 里还能定义资源对象的标签(Label),这里声明myweb拥有一个name=myweb的标签(Label)。
-
Pod里包含的容器组的定义则在spec一节中声明,这里定义了一个名字为myweb,对应镜像为kubeguide/tomcat-app: v1的容器,该容器注入了名为MYSQL_SERVICE_HOST=‘mysql’ 和 MYSQL_SERVICE_PORT='3306’的环境变量(env关键字),并且在8080端口(containerPort)上启动容器进程。
-
Pod的IP加上这里的容器端口,就组成了一个新的概念——Endpoint(端点),它代表着此Pod里的一个服务进程的对外通信地址。一个Pod也存在着具有多个Endpoint的情况,比如我们把 Tomcat 定义为一个 Pod 时,可以对外暴露管理端口与服务端口这两个 Endpoint。
-
Docker 里的 Volume 在 Kubernetes 里也有对应的概念—— Pod Volume,Pod Volume 有一些扩展,比如可以用分布式文件系统 GlusterFS 等实现后端存储功能;Pod Volume 是定义在 Pod 之上,然后被各个容器挂载到自己的文件系统中的。对于Pod Volume的定义我们后面会讲到。
-
这里顺便提一下Event 概念,Event是一个事件的记录,记录了事件的最早产生时间、最后重现时间、重复次数、发起者、类型,以及导致此事件的原因等众多信息。Event 通常会关联到某个具体的资源对象上,是排查故障的重要参考信息,当我们发现某个Pod迟迟无法创建时,可以用 kubectl describe pod xxx来查看它的描述信息,用来定位问题的原因。
-
每个Pod都可以对其能使用的服务器上的计算资源设置限额,当前可以设置限额的计算资源有CPU和Memory两种,其中CPU的资源单位为CPU(Core)的数量,是一个绝对值。对于容器来说一个CPU的配额已经是相当大的资源配额了,所以在Kubernetes里,通常以千分之一的CPU配额为最小单位,用m来表示。通常一个容器的CPU配额被定义为100-300m,即占用0.1-0.3个CPU。与CPU配额类似,Memory配额也是一个绝对值,它的单位是内存字节数。
对计算资源进行配额限定需要设定以下两个参数:- Requests:该资源的最小申请量,系统必须满足要求。
- Limits:该资源最大允许使用的量,不能超过这个使用限制,当容器试图使用超过这个量的资源时,可能会被Kubernetes Kill并重启。
-
通常应该把Requests设置为一个比较小的数值,满足容器平时的工作负载情况下的资源需求,而把Limits设置为峰值负载情况下资源占用的最大量。下面是一个资源配额的简单定义:
spec:
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- 最小0.25个CPU及64MB内存,最大0.5个CPU及128MB内存。
4、pod 定义相关资源说明及示例
- 下面是一个完整的 yaml 格式定义的文件,注意格式,子集包含关系,不要有tab,要用空格。不是所有的元素都要写,按照实际应用场景配置即可。
apiVersion: v1 # 版本
kind: pod # 类型,pod
metadata: # 元数据
name: String # 元数据,pod的名字
namespace: String # 元数据,pod的命名空间
labels: # 元数据,标签列表
- name: String # 元数据,标签的名字
annotations: # 元数据,自定义注解列表
- name: String # 元数据,自定义注解名字
spec: # pod中容器的详细定义
containers: # pod中的容器列表,可以有多个容器
- name: String
image: String # 容器中的镜像
imagesPullPolicy: [Always|Never|IfNotPresent] # 获取镜像的策略
command: [String] # 容器的启动命令列表(不配置的话使用镜像内部的命令)
args: [String] # 启动参数列表
workingDir: String # 容器的工作目录
volumeMounts: # 挂载到到容器内部的存储卷设置
- name: String
mountPath: String
readOnly: boolean
ports: # 容器需要暴露的端口号列表
- name: String
containerPort: int # 容器要暴露的端口
hostPort: int # 容器所在主机监听的端口(容器暴露端口映射到宿主机的端口)
protocol: String
env: # 容器运行前要设置的环境列表
- name: String
value: String
resources: # 资源限制
limits:
cpu: Srting
memory: String
requeste:
cpu: String
memory: String
livenessProbe: # pod内容器健康检查的设置
exec:
command: [String]
httpGet: # 通过httpget检查健康
path: String
port: number
host: String
scheme: Srtring
httpHeaders:
- name: Stirng
value: String
tcpSocket: # 通过tcpSocket检查健康
port: number
initialDelaySeconds: 0 # 首次检查时间
timeoutSeconds: 0 # 检查超时时间
periodSeconds: 0 # 检查间隔时间
successThreshold: 0
failureThreshold: 0
securityContext: # 安全配置
privileged: falae
restartPolicy: [Always|Never|OnFailure] # 重启策略
nodeSelector: object # 节点选择
imagePullSecrets:
- name: String
hostNetwork: false # 是否使用主机网络模式,默认否
volumes: # 在该pod上定义共享存储卷
- name: String
meptyDir: {}
hostPath:
path: string
secret: # 类型为 secret 的存储卷
secretName: String
item:
- key: String
path: String
configMap: # 类型为configMap的存储卷
name: String
items:
- key: String
path: String
5、Pod 中 command 和 args
command: ['sh'] # 启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT
args: ["$(str)"] # 启动容器的命令参数,对应 Dockerfile 中 CMD 参数
env: # 指定容器中的环境变量
- name: str # 变量的名字
value: "/etc/run.sh" # 变量的值 sh /etc/run.sh
Image Entrypoint | Image Cmd | Container command | Container args | Command run |
---|---|---|---|---|
[/ep-1] | [foo bar] | [ep-1 foo bar] | ||
[/ep-1] | [foo bar] | [/ep-2] | [ep-2] | |
[/ep-1] | [foo bar] | [zoo boo] | [ep-1 zoo boo] | |
[/ep-1] | [foo bar] | [/ep-2] | [zoo boo] | [ep-2 zoo boo] |
6、 Pod 定义 apiVsersion
1、查看当前可用的API版本
[root@k8s-master ~]# kubectl api-versions
-
1.6版本之前 apiVsersion:extensions/v1beta1
-
1.6版本到1.9版本之间:apps/v1beta1
-
1.9版本之后: apps/v1
2、各种 apiVersion 的含义
1、alpha 内测版
- 该软件可能包含错误。启用一个功能可能会导致bug
- 随时可能会丢弃对该功能的支持,恕不另行通知
2、beta 公测版
- 软件经过很好的测试。启用功能被认为是安全的。
- 默认情况下功能是开启的
- 细节可能会改变,但功能在后续版本不会被删除
3、stable 稳定版
-
该版本名称命名方式:vX 这里X是一个整数
-
稳定版本、放心使用
-
将出现在后续发布的软件版本中
4、v1
- Kubernetes API 的稳定版本,包含很多核心对象:pod、service等
5、apps/v1beta2
-
在kubernetes1.8版本中,新增加了 apps/v1beta2 的概念,apps/v1beta1 同理
-
DaemonSet,Deployment,ReplicaSet 和 StatefulSet 的当时版本迁入 apps/v1beta2,兼容原有的 extensions/v1beta1
6、apps/v1
-
在 kubernetes1.9 版本中,引入 apps/v1,deployment 等资源从 extensions/v1beta1, apps/v1beta1 和 apps/v1beta2 迁入 apps/v1,原来的 v1beta1 等被废弃。
-
apps/v1 代表:包含一些通用的应用层的api组合,如:Deployment, RollingUpdate, and ReplicaSet
7、batch/v1
-
代表 job 相关的 api 组合
-
在 kubernetes1.8 版本中,新增了 batch/v1beta1,后 CronJob 已经迁移到了 batch/v1beta1,然后再迁入 batch/v1
8、autoscaling/v1
-
代表自动扩缩容的 api 组合,kubernetes1.8 版本中引入。
-
这个组合中后续的 alpha 和 beta 版本将支持基于memory 使用量、其他监控指标进行扩缩
9、extensions/v1beta1
- deployment 等资源在1.6版本时放在这个版本中,后迁入到 apps/v1beta2,再到 apps/v1 中统一管理
10、certificates.k8s.io/v1beta1
- 安全认证相关的api组合
11、authentication.k8s.io/v1
- 资源鉴权相关的api组合
3、Pod 生命周期
1、pod 的四种状态
状态值 | 描述 |
---|---|
Pending | APIserver已经创建该server,但pod内有一个或多个容器的镜像还未创建,可能在下载中。 |
Running | Pod内所有的容器已创建,所有容器都是运行状态 |
Failed | Pod内所有容器都已退出,其中至少有一个容器退出失败 |
Unknown | 由于某种原因无法获取Pod的状态,比如 网络不通。 |
2、Kubernetes 排错之 Pod 异常
- 一般来说,无论 Pod 处于什么异常状态,都可以执行以下命令来查看 Pod 的状态
1、查看 Pod 的配置是否正确
[root@k8s-master ~]# kubectl get pod <pod-name> -o yaml
2、查看 Pod 的事件
[root@k8s-master ~]# kubectl describe pod <pod-name>
3、查看容器日志
[root@k8s-master ~]# kubectl logs <pod-name> [-c <container-name>]
kubectl logs test-pod -c c1-name/ -- /bin/bash /-c c1-name -- /bin/bash / -c c2-name -- /bin/bash
- 这些事件和日志通常都会有助于排查 Pod 发生的问题。
2、Pod 一直处于 Pending 状态
- Pending 说明 Pod 还没有调度到某个 Node 上面。查看到当前 Pod 的事件,进而判断为什么没有调度。可能的原因包括
- 资源不足,集群内所有的 Node 都不满足该 Pod 请求的 CPU、内存、GPU 等资源
- HostPort 已被占用,通常推荐使用 Service 对外开放服务端口
3、Pod 一直处于 Waiting 或 ContainerCreating 状态
-
查看到当前 Pod 的事件。可能的原因包括
- 镜像拉取失败
- 配置了错误的镜像
- Kubelet 无法访问镜像(国内环境访问 gcr.io 需要特殊处理)
- 私有镜像的密钥配置错误
- 镜像太大,拉取超时(可以适当调整 kubelet 的 --image-pull-progress-deadline 和 --runtime-request-timeout 选项)
-
CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如
-
无法配置 Pod 网络
-
无法分配 IP 地址
-
-
容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数
4、Pod 处于 ImagePullBackOff 状态
-
这通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用 docker pull 来验证镜像是否可以正常拉取。
-
如果是私有镜像,需要首先创建一个 docker-registry 类型的 Secret
[root@k8s-master ~]# kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
- 然后在容器中引用这个 Secret
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: my-secret
5、Pod 一直处于 CrashLoopBackOff 状态
- CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出了。此时可以先查看一下容器的日志
[root@k8s-master ~]# kubectl logs <pod-name>
[root@k8s-master ~]# kubectl logs --previous <pod-name>
-
这里可以发现一些容器退出的原因,比如
- 容器进程退出
- 健康检查失败退出
-
此时如果还未发现线索,还可以到容器内执行命令来进一步查看退出原因
[root@k8s-master ~]# kubectl exec cassandra -- cat /var/log/cassandra/system.log
- 如果还是没有线索,那就需要 SSH 登录该 Pod 所在的 Node 上,查看 Kubelet 或者 Docker 的日志进一步排查了
# 查询 Node
[root@k8s-master ~]# kubectl get pod <pod-name> -o wide
5、Pod 处于 Error 状态
- 依赖的 ConfigMap、Secret 或者 PV 等不存在
- 请求的资源超过了管理员设置的限制,比如超过了 LimitRange 等
- 违反集群的安全策略,比如违反了 PodSecurityPolicy 等
- 容器无权操作集群内的资源,比如开启 RBAC 后,需要为 ServiceAccount 配置角色绑定
6、Pod 处于 Terminating 或 Unknown 状态
- 从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。想要删除这些状态的 Pod 有三种方法:
- 从集群中删除该 Node。使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node。而在物理机部署的集群中,需要管理员手动删除 Node(如 kubectl delete node 。
- Node 恢复正常。Kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod。
- 用户强制删除。用户可以执行 kubectl delete pods --grace-period=0 --force 强制删除 Pod。除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题。
7、Pod 行为异常
- 这里所说的行为异常是指 Pod 没有按预期的行为执行,比如没有运行 podSpec 里面设置的命令行参数。这一般是 podSpec yaml 文件内容有误,可以尝试使用 --validate 参数重建容器,比如
[root@k8s-master ~]# kubectl delete pod mypod
[root@k8s-master ~]# kubectl create --validate -f mypod.yaml
- 也可以查看创建后的 podSpec 是否是对的,比如
[root@k8s-master ~]# kubectl get pod mypod -o yaml
8、修改静态 Pod 的 Manifest 后未自动重建
-
Kubelet 使用 inotify (监控文件系统) 机制检测 /etc/kubernetes/manifests 目录(可通过 Kubelet 的 --pod-manifest-path 选项指定)中静态 Pod 的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发生修改静态 Pod 的 Manifest 后未自动创建新 Pod 的情景,此时一个简单的修复方法是重启 Kubelet。
-
Inotify 可用于检测单个文件,也可以检测整个目录。当检测的对象是一个目录的时候,目录本身和目录里的内容都会成为检测的对象。此种机制的出现的目的是当内核空间发生某种事件之后,可以立即通知到用户空间。方便用户做出具体的操作
4、Pod 重启策略
- Pod的重启策略应用于Pod内的所有容器,由Pod所在Node节点上的Kubelet进行判断和重启操作。重启策略有以下三种:
重启策略 | 描述 |
---|---|
Always | 容器失效时,即重启 (不能正常提供服务) |
OnFailure | 容器终止运行,且退出码不为0 时重启 退出码是0(不重启) |
Never | 不重启 |
5、Pod 健康检查
1、健康检测介绍
- Kubernetes内部通过2种探针,实现了对Pod健康的检查
- LivenessProbe探针:判断容器是否存活(running)
- 表示container是否处于live状态。如果 LivenessProbe失败,LivenessProbe将会通知kubelet对应的container不健康了。随后kubelet将kill掉 container,并根据RestarPolicy进行进一步的操作。默认情况下LivenessProbe在第一次检测之前初始化值为 Success,如果container没有提供LivenessProbe,则也认为是Success;
- ReadinessProbe探针: 用于判断容器是否启动完成(ready)
- 表示container是否以及处于可接受service请求的状态了。如 果ReadinessProbe失败,endpoints controller将会从service所匹配到的endpoint列表中移除关于这个container的IP地址。因此对于Service匹配到的 endpoint的维护其核心是ReadinessProbe。默认Readiness的初始值是Failure,如果一个container没有提供 Readiness则被认为是Success。
- LivenessProbe探针:判断容器是否存活(running)
- Kubernetes 内部2种探针结果也有三个固定的可选值:
- Success:表示通过检测
- Failure:表示没有通过检测
- Unknown:表示检测没有正常进行
- Kubernetes 内部2种探针的三种健康的检查方法
- ExecAction:在container中执行指定的命令。当其执行成功时,将其退出码设置为0;
- TCPSocketAction:执行一个TCP检查使用container的IP地址和指定的端口作为socket。如果端口处于打开状态视为成功
- HTTPGetAcction:执行一个HTTP默认请求使用container的IP地址和指定的端口以及请求的路径作为url,用户可以通过host参数设置请求的地址,通过scheme参数设置协议类型(HTTP、HTTPS)如果其响应代码在200~400之间,设为成功。
- Kubernetes 内部2种探针用法都一样,拥有相同的参数和相同的监测方式。
- initialDelaySeconds:用来表示初始化延迟的时间,也就是告诉监测从多久之后开始运行,单位是秒
- timeoutSeconds: 用来表示监测的超时时间,如果超过这个时长后,则认为监测失败
2、健康检测测试
-
针对LivenessProbe如何使用,请看下面的几种方式,如果要使用ReadinessProbe只需要将livenessProbe修改为readinessProbe即可
-
LivenessProbe探针通过三种方式来检查容器是否健康
1、容器内部执行命令
- ExecAction:在容器内部执行一个命令,如果返回码为0,则表示健康
apiVersion: v1
kind: Pod
metadata:
name: liveness
spec:
containers:
- name: liveness
image: busybox
args:
- "/bin/sh"
- "-c"
- "echo ok > /tmp/healthy; sleep 10; rm - rf /tmp/healthy; sleep 3600"
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 15 # 用来表示初始化延迟的时间,也就是告诉监测从容器启动之后延迟多久进行liveness探测,单位是秒
timeoutSeconds: 1 # 用来表示监测的超时时间,如果超过这个时长后,则认为监测失败
periodSeconds: 20 # 检测间隔时间
# 查看pod重启情况
kubectl get pods -w
2、通过IP 和port
- TcpAction:通过IP 和port ,如果能够和容器建立连接则表示容器健康
apiVersion: v1
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 15
timeoutSeconds: 1
# 查看pod重启情况
kubectl get pods -w
==============================================================================================
apiVersion: v1
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
timeoutSeconds: 1
# 查看pod重启情况
kubectl get pods -w
3、获取状态码
- HttpGetAction:发送一个http Get请求(ip+port+请求路径)如果返回状态吗在200-400之间则表示健康
apiVersion: v1
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /_status/healthz # 请求路径
port: 80
initialDelaySeconds: 15
timeoutSeconds: 1
6、Pod 调度策略
1、默认的scheduler的调度过程是通过自己的预设来影响预选、优选过程,从而实现符合我们期望的调度结果
- 预选策略:从所有节点当中选择基本符合选择条件的节点。
- 优选函数:在众多符合基本条件的节点中使用优选函数,计算节点各自的得分,通过比较进行排序。从最高得分的节点中随机选择出一个作为Pod运行的节点。
2、影响调度方式
-
节点选择器:NodeSelector,甚至可以设置nodename来选择节点本身。
-
亲和性调度:NodeAffinity(节点亲和性)、podAffinity(Pod亲和性)、PodAntiAffinity(Pod的反亲和性)
-
污点和容忍度:Taint、toleration
1、Pod 调动到某些节点上
1、首先通过 kubectl 给 node 打上标签
格式:
kubectl label nodes <node-name> <label-key>=<label-value>
[root@k8s-master ~]# kubectl label nodes k8s-node01 zone=sh
[root@k8s-master ~]# kubectl get nodes --show-labels
2、通过 nodeSelector 调度 pod 到 node
- Pod的定义中通过nodeSelector指定label标签,pod将会只调度到具有该标签的node之上
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
- 这个例子中pod只会调度到具有 disktype=ssd 的 node 上面.
- 验证 节点调度
[root@k8s-master ~]# vim pod-demo.yaml
# 内容为
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeSelector:
disktype: harddisk
[root@k8s-master ~]# kubectl apply -f pod-demo.yaml
[root@k8s-master ~]# kubectl get pods
[root@k8s-master ~]# kubectl describe pod pod-demo
# 运行结果:
Warning FailedScheduling 2m3s (x25 over 3m15s) default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector.
# 打上标签
[root@k8s-master ~]# kubectl label node k8s-node02 disktype=harddisk
# 正常启动
[root@k8s-master ~]# kubectl get pods
2、Node 间亲和性(Affinity)调度
1、Node 亲和性介绍
- Affinity/anti-affinity node 相对于nodeSelector机制更加的灵活和丰富
- 表达的语法:支持In,NotIn,Exists,DoesNotExist,Gt,Lt.
- 支持soft(preference)和hard(requirement),
- hard表示pod sheduler到某个node上时必须满足的亲和性设置.
- soft表示scheduler的时候,当无法满足节点的时候,会选择非 nodeSelector 匹配的节点.
- requiredDuringSchedulingIgnoredDuringExecution 硬亲和性 必须满足亲和性
- preferredDuringSchedulingIgnoredDuringExecution 软亲和性 能满足最好,不满足也没关系。
- nodeAffinity 的基础上添加多个 nodeSelectorTerms 字段,调度的时候 Node 只需要 nodeSelectorTerms 中的某一个符合条件就符合 nodeAffinity 的规则.在nodeSelectorTerms 中添加 matchExpressions,需要可以调度的Node是满足 matchExpressions 中表示的所有规则.
2、硬亲和性
-
matchExpressions : 匹配表达式,这个标签可以指定一段,例如pod中定义的key为zone,operator为In(包含那些),values为 foo和bar。就是在node节点中包含foo和bar的标签中调度
-
matchFields : 匹配字段,不过可以不定义标签值,可以定义匹配在 node 有 zone 标签值为 foo 或 bar 值的节点上运行 pod
[root@k8s-master ~]# vim pod-nodeaffinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-node-affinity-demo
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- foo
- bar
[root@k8s-master ~]# kubectl apply -f pod-nodeaffinity-demo.yaml
[root@k8s-master ~]# kubectl describe pod pod-node-affinity-demo
# 运行结果:
Warning FailedScheduling 2s (x8 over 20s) default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector.
# 给其中一个node打上foo的标签
[root@k8s-master ~]# kubectl label node k8s-node01 zone=foo
# 正常启动
[root@k8s-master ~]# kubectl get pods
3、软亲和性
[root@k8s-master ~]# vim pod-nodeaffinity-demo-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-node-affinity-demo-2
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: zone
operator: In
values:
- foo
- bar
weight: 60
- preference:
matchExpressions:
- key: zone1
operator: In
values:
- foo1
- bar1
weight: 10
[root@k8s-master ~]# kubectl apply -f pod-nodeaffinity-demo-2.yaml
4、软硬亲和性同时存在
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- dev
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: with-node-affinity
image: nginx
-
此节点亲和性规则表示,只能将Pod放在带有标签的键为 zone 值为 dev 的node上,在满足该条件的节点中,应该首选带有键值为 disktype 值为 ssd 的节点.
-
如果同时指定nodeSelector和nodeAffinity,则必须满足两个条件,才能将Pod调度到候选节点上。
-
如果指定了多个nodeSelectorTerms关联nodeAffinity类型,那么pod 可以安排到满足nodeSelectorTerms之一的节点。
-
如果指定matchExpressions与关联的多个nodeSelectorTerms,则只有matchExpressions在满足所有nodeSelectorTerms条件的情况下,才能将Pod调度到节点上。
-
如果删除或更改计划了pod的节点的标签,则该pod不会被删除。亲和性选择仅在安排pod时有效。
-
weight 在场 preferredDuringSchedulingIgnoredDuringExecution 的范围是从1-100,值越大优先级越高,计算节点权重值之和,和 matchExpressions 的匹配度结合,实现调度 pod 节点的选择。
3、Pod 间的亲和性和反亲和性(Affinity/AntiAffinity)调度
- 基于已经运行在 Node 上 pod 的 labels 来决定需要新创建的Pods是否可以调度到node节点上,配置的时候可以指定那个namespace中的pod需要满足pod的亲和性.可以通过 topologyKey 来指定 topology domain, 可以指定为 node/cloud provider zone 的范围.
- 表达的语法:支持In, NotIn, Exists, DoesNotExist
- Pod的亲和性和反亲和性可以分成
- requiredDuringSchedulingIgnoredDuringExecution # 硬要求
- preferredDuringSchedulingIgnoredDuringExecution #软要求
- labelSelector : 选择跟那组Pod亲和
- namespaces : 选择哪个命名空间
- topologyKey : 指定节点上的哪个键,可以设置成如下几种类型(节点标签)
- kubernetes.io/hostname #Node
- failure-domain.beta.kubernetes.io/zone #Zone
- 可以设置node上的label的值来表示node的name,zone,region等信息,pod的规则中指定topologykey的值表示指定topology 范围内的 node 上运行的 pod 满足指定规则
1、pod 亲和性
- Pod亲和性场景,k8s集群的节点分布在不同的区域或者不同的机房,当服务A和服务B要求部署在同一个区域或者同一机房的时候,我们就需要亲和性调度了
[root@k8s-master ~]# kubectl get pods
[root@k8s-master ~]# kubectl delete pod pod-node-affinity-demo pod-node-affinity-demo-2 pod-demo
[root@k8s-master ~]# cd schedule/
[root@k8s-master ~]# vim pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: db
tier: db
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["myapp"]}
topologyKey: kubernetes.io/hostname
[root@k8s-master ~]# kubectl apply -f pod-required-affinity-demo.yaml
[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果,两个 pod 在同一 node 节点上
NAME READY STATUS RESTARTS AGE IP NODE
pod-first 1/1 Running 0 11s 10.244.1.6 k8s-node01
pod-second 1/1 Running 0 11s 10.244.1.5 k8s-node01
2、pod 反亲和性
- Pod反亲和性场景,当应用服务A和数据库服务B要求尽量不要在同一台节点上的时候。
[root@k8s-master ~]# kubectl delete -f pod-required-affinity-demo.yaml
[root@k8s-master ~]# cp pod-required-affinity-demo.yaml pod-required-anti-affinity-demo.yaml
[root@k8s-master ~]# vim pod-required-anti-affinity-demo.yaml
# 内容为
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: backend
tier: db
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["myapp"]}
topologyKey: kubernetes.io/hostname
[root@k8s-master ~]# kubectl apply -f pod-required-anti-affinity-demo.yaml
[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果,两个 pod 不在同一个 node
NAME READY STATUS RESTARTS AGE IP NODE
pod-first 1/1 Running 0 5s 10.244.2.4 k8s-node02
pod-second 1/1 Running 0 5s 10.244.1.7 k8s-node01
[root@k8s-master ~]# kubectl delete -f pod-required-anti-affinity-demo.yaml
3、pod 亲和性和反亲和性
- node01 打标签 zone=test1 node02 打标签 zone=test
apiVersion: v1
kind: Pod
metadata:
name: pod-test1
labels:
security: S1
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeSelector:
zone: test1
---
apiVersion: v1
kind: Pod
metadata:
name: pod-test2
labels:
security: S1
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeSelector:
zone: test
---
apiVersion: v1
kind: Pod
metadata:
name: pod-test3
labels:
security: S2
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeSelector:
zone: test
---
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
security: S2
tier: frontend2
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeSelector:
zone: test1
---
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: nginx
- 例子中指定了pod的亲和性和反亲和性,指定的规则是pod将会调度到的node尽量会满足如下条件:
1、podAffinity 亲和性要求满足
- node上具有 kubernetes.io/hostname区域,并且 node 上运行有一个pod 包含标签 label为securtity=S1.
2、podAntiAffinity 反亲和性要求满足
-
不会调度 pod 到运行包含有 security=S2 的 pod 的 node上.
-
如果这里将topologyKey= kubernetes.io/hostname,那么 pod 将不会调度到 node
-
满足的条件是:node上具有 kubernetes.io/hostname 相同的 value,并且这些相同 zone下的 node 上运行有 security=S2 的 pod
3、对于topologyKey字段具有如下约束
-
topologyKey 定义pod亲和性调度和反亲和性调度中需要各个相关的pod对象是否运行于"同一位置",指定“同一位置” 是通过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称
-
如果topologyKey指定区域已经在运行一个或多个满足LabelSelector规则的Pod,则该Pod应该(或者在非亲和性的情况下不应该)在 topologyKey 中运行
-
对于亲和性和 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,topologyKey 不能为空。
-
对于 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,引入 LimitPodHardAntiAffinityTopology 准入控制器来限制 topologyKey 只能是 kubernetes.io/hostname。如果要使用自定义拓扑域,则需要修改准入控制器,或者直接禁用它。
-
对于 preferredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,空的 topologyKey 表示所有拓扑域。截止 v1.12 版本,所有拓扑域还只能是 kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合。
-
topologyKey 除上述情况外,可以是任何合法的标签 key。规则中可以指定匹配pod所在namespace,如果定义了但是为空,它表示所有namespace范围内的pod.
-
所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后,系统才能将pod调度到某个node上。
4、topologyKey 调度示例
- 需求:当前有两个机房( beijing,shanghai),需要部署一个nginx产品,副本为两个,为了保证机房容灾高可用场景,需要在两个机房分别部署一个副
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-affinity-test
spec:
replicas: 2
selector:
matchLabels:
service: nginx z
template:
metadata:
name: nginx
labels:
service: nginx
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: service
operator: In
values:
- nginx
topologyKey: zone
containers:
- name: nginx
image: busybox:latest
command: ["sh","-c","sleep 3600"]
- 解释:两个node上分别有zone标签,来标注自己属于哪个机房,topologyKey定义为zone,pod所以在调度的时候,会根据node上zone标签来区分拓扑域,当前用的上 反亲和性调度 根据拓扑纬度调度,beijing机房调度完一个pod后,然后控制器判断beijing 拓扑域已经有server=nginx标签的pod,就在下一个拓扑域的node上调度了
4、Pod 亲和性调度常用的场景
1、pod 反亲和性调度
- 创建了一个Deployment,副本数为3,指定了反亲和规则如上所示,pod的label为app:store,那么pod调度的时候将不会调度到node上已经运行了label为app:store的pod了,这样就会使得Deployment的三副本分别部署在不同的host的node上
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
replicas: 3 # 必须有对应的节点数(master不能创建pod)
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
# 每个节点保证有一个pod 必须满足这个 pod 有 app = store 这样的标签,如果存在这样的 pod 就不满足要求
2、pod 亲和性调度
- 在一个例子中基础之上,要求pod的亲和性满足 requiredDuringSchedulingIgnoredDuringExecution 中topologyKey=”kubernetes.io/hostname”,并且 node上需要运行有 app=store 的label.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 4 #必须有对应的节点数(master不能创建pod)
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.12-alpine
- 运行完例子一,例子二,那么pod的分布如下所示
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
redis-cache-1450370735-6dzlj 1/1 Running 0 8m 10.192.4.2 kube-node-3
redis-cache-1450370735-j2j96 1/1 Running 0 8m 10.192.2.2 kube-node-1
redis-cache-1450370735-z73mh 1/1 Running 0 8m 10.192.3.1 kube-node-2
web-server-1287567482-5d4dz 1/1 Running 0 7m 10.192.2.3 kube-node-1
web-server-1287567482-6f7v5 1/1 Running 0 7m 10.192.4.3 kube-node-3
web-server-1287567482-s330j 1/1 Running 0 7m 10.192.3.2 kube-node-2
3、pod 亲和性调度
- 在一些应用中,pod副本之间需要共享cache,需要将pod运行在一个节点之上
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx
- pod 的分布如下所示
web-server-77bfb4575f-bhxvg 1/1 Running 0 11s 10.233.66.79 hzc-slave2 app=web-store,pod-template-hash=3369601319
web-server-77bfb4575f-mkfd9 1/1 Running 0 11s 10.233.66.80 hzc-slave2 app=web-store,pod-template-hash=3369601319
web-server-77bfb4575f-wgjq6 1/1 Running 0 11s 10.233.66.78 hzc-slave2 app=web-store,pod-template-hash=3369601319123
4、污点容忍调度(Taint和Toleration)
- taints and tolerations 允许将某个节点做标记,以使得所有的pod都不会被调度到该节点上。但是如果某个pod明确指定了 tolerates 则可以正常调度到被标记的节点上。
- 使用命令行为 Node 节点添加 Taints
[root@k8s-master ~]# kubectl taint nodes k8s-node01 key=value:NoSchedule
- key: "node-type"
operator: "Equal"
value: "production"
effect: "NoSchedule"
-
operator 可以定义为
- Equal:表示key是否等于value,默认
- Exists:表示key是否存在,此时无需定义value
-
tain 的 effect 定义对 Pod 排斥效果
- NoSchedule:仅影响调度过程,对现存的Pod对象不产生影响;
- NoExecute:既影响调度过程,也影响现有的Pod对象;不容忍的Pod对象将被驱逐
- PreferNoSchedule: 表示尽量不调度
-
查看节点的 taint
[root@k8s-master ~]# kubectl describe node k8s-node01 | grep Taints
- 为 k8s-node01 打上污点
[root@k8s-master ~]# kubectl taint node k8s-node01 node-type=production:NoSchedule
- 创建 pod 验证
[root@k8s-master ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml
[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果:
NAME READY STATUS RESTARTS AGE IP NODE
myapp-deploy-69b47bc96d-cwt79 1/1 Running 0 5s 10.244.2.6 k8s-node02
myapp-deploy-69b47bc96d-qqrwq 1/1 Running 0 5s 10.244.2.5 k8s-node02
- 为 k8s-node02 打上污点
[root@k8s-master ~]# kubectl taint node k8s-node02 node-type=dev:NoExecute
-
NoExecute 将会驱逐没有容忍该污点的 pod,因两个node节点都有污点,pod没有定义容忍,导致没有节点可以启动pod
-
查看pod 运行结果
[root@k8s-master ~]# kubectl get pods -o wide
# 运行结果:
NAME READY STATUS RESTARTS AGE IP NODE
myapp-deploy-69b47bc96d-psl8f 0/1 Pending 0 14s <none> <none>
myapp-deploy-69b47bc96d-q296k 0/1 Pending 0 14s <none> <none>
- 定义Toleration(容忍)
[root@k8s-master ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: defaultm
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
tolerations:
- key: "node-type"
operator: "Equal"
value: "production"
effect: "NoSchedule"
[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml
- pod 容忍 k8s-node01 的 tain ,可以在 k8s-node01 上运行
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myapp-deploy-65cc47f858-tmpnz 1/1 Running 0 10s 10.244.1.10 k8s-node01
myapp-deploy-65cc47f858-xnklh 1/1 Running 0 13s 10.244.1.9 k8s-node01
- 定义Toleration,是否存在 node-type 这个key 且 effect 值为 NoSchedule
[root@k8s-master ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
tolerations:
- key: "node-type"
operator: "Exists"
value: ""
effect: "NoSchedule"
[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myapp-deploy-559f559bcc-6jfqq 1/1 Running 0 10s 10.244.1.11 k8s-node01
myapp-deploy-559f559bcc-rlwp2 1/1 Running 0 9s 10.244.1.12 k8s-node01
- 定义Toleration,是否存在 node-type 这个key 且 effect 值为空,则包含所有的值
[root@k8s-master ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
tolerations:
- key: "node-type"
operator: "Exists"
value: ""
effect: ""
[root@k8s-master ~]# kubectl apply -f deploy-demo.yaml
# 两个 pod 均衡调度到两个节点
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
myapp-deploy-5d9c6985f5-hn4k2 1/1 Running 0 2m 10.244.1.13 k8s-node01
myapp-deploy-5d9c6985f5-lkf9q 1/1 Running 0 2m 10.244.2.7 k8s-node02
7、Pod 扩容和缩容
1、kubectl scale
-
扩容或缩容 Deployment、ReplicaSet、Replication Controller或 Job 中Pod数量。
-
scale 也可以指定多个前提条件,如:当前副本数量或 --resource-version ,进行伸缩比例设置前,系统会先验证前提条件是否成立。
2、scale 语法
[root@k8s-master ~]# kubectl scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)
3、scale 示例
- 将名为 foo 的 rs资源中的 pod 副本数设置为 3。
[root@k8s-master ~]# kubectl scale --replicas=3 deployment foo
- 将配置文件中指定的资源对象和名称标识的Pod资源副本设为3。
[root@k8s-master ~]# kubectl scale --replicas=3 -f foo.yaml
- 配置deployment 资源, 如果当前副本数为2,则将其扩展至3。
[root@k8s-master ~]# kubectl scale --current-replicas=2 --replicas=3 deployment mysql
- 设置多个RC资源中Pod副本数量。
[root@k8s-master ~]# kubectl scale --replicas=5 rc foo bar baz
-
假设 redis-slave 这个 rc 资源中原来定义了5个副本(reolics:5)
-
扩容到10个,执行命令:
[root@k8s-master ~]# kubectl scale rc redis-slave --replicas=10
- 缩容到2个,执行命令:
[root@k8s-master ~]# kubectl scale rc redis-slave --replicas=2
更多推荐
所有评论(0)