一、 kubernetes带来的变革
1. 对于开发人员
由于公司业务多,开发环境、测试环境、预生产环境和生产环境都是隔离的,而且除了生产环境,为了节省成本,其他环境可能是没有日志收集的,在没有用k8s的时候,查看线下测试的日志,需要开发或者测试人员,找到对应的机器,在找到对应的容器,然后才能查看日志,在用了k8s之后,开发和测试可以直接在k8s的dashboard到对应的namespace,即可定位到业务的容器,然后可以直接通过控制台查看到对应的日志,大大降低了操作时间。
把应用部署到k8s之后,代码的发布、回滚,以及蓝绿发布、金丝雀发布等都变得特别简单,不仅加快了业务代码迭代的速度,而且全程无需人工干预。目前我们使用jenkins、gitrunner进行发版或者回滚等,从开发环境到测试环境,到生产环境,完全遵守一次构建,多集群、多环境部署,通过不同的启动参数、不同的环境变量、不同的配置文件实现区分不同的环境。目前已经实现Python、Java、PHP、NodeJS、Go、.NET Core、Python等多种语言的一键式发版、一键式回滚,大大提高了开发人员的开发效率。
在使用服务网格后,开发人员在开发应用的过程中,不用再关心代码的网络部分,这些功能都被服务网格实现,让开发人员可以只关心代码逻辑部分,即可实现网络部分的功能,比如:断流、分流、路由、负载均衡、限速和触发故障等功能。
测试过程中,可能同时多套环境,当然也会需要再创建一套测试环境,之前测试环境的创建,需要找运维或者自行手工搭建。在迁移至k8s集群后,只需要在jenkins上点点鼠标即可在k8s集群上创建一套新的测试环境。
2. 对于运维人员
如果你是一名运维人员,可能经常因为一些重复、繁琐的工作感觉厌倦。比如:这个需要一套新的测试环境,那个需要一套新的测试环境,之前可能需要装系统、装依赖环境、开通权限等等。而如今,可以直接用镜像直接部署一套新的测试环境,甚至全程无需自己干预,开发人员通过jenkins或者自动化运维平台即可一键式创建,大大降低了运维成本。
一开始,公司业务故障,可能是因为基础环境不一致、依赖不一致、端口冲突等等问题,现在实现Docker镜像部署,k8s编排,所有的依赖、基础都是一样的,并且环境的自动化扩容、健康检查、容灾、恢复都是全自动的,大大减少了因为这类基础问题引发的故障。也有可能公司业务是由于服务器宕机、网络等问题,造成服务不可用,此类情况均需要运维人员及时去修复,而如今,可能在你收到告警信息的时候,k8s已经帮你恢复了。
在没有使用k8s时,业务应用的扩容和缩容,都需要人工去处理,从采购服务器、上架、到部署依赖环境,不仅需要大量的人力物力,而且非常容易在中间过程出现问题,又要花费大量的时间去查找问题。成功上架后,还需要在前端反代端添加或该服务器,而如今,可以利用k8s的弹性计算,一键式进行扩容和缩容,不仅大大提高了运维效率,而且还节省了不少的服务器资源,提高了资源利用率。
对于反代配置方面,比如可能你并不会,或者对nginx的配置规则并不熟悉,一些高级的功能你也不会实现,而如今,利用k8s的ingress即可简单的实现那些复杂的逻辑。并且也不会在遇到nginx少加一个斜杠和多加一个斜杠的问题。
对于负载均衡方面,之前负载均衡可能是Nginx、LVS、HAProxy、F5等,云上可能是云服务商提供的不在均衡机制。每次添加删除节点时,都需要手动去配置前端负载均衡,手动去匹配后端节点,而如今,使用k8s内部的service可以动态发现实现自动管理节点,并且支持自动扩容缩容。之前遇到高峰流量时,经常服务器性能不够,需要临时加服务器面对高峰流量,而如今对于高性能k8s集群加上serverless,基本实现无需管理,自动扩容。
对于高可用方面,k8s天生的高可用功能,彻底释放了双手,无需再去创建各类高可用工具、检测检查脚本。k8s支持进程接口级别的健康检查,如发现接口超时或者返回值不正确,会自动处理该问题。
对于中间件搭建方面,根据定义好的资源文件,可以实现秒级搭建各类中间件高可用集群,并且支持一键式扩缩容,如Redis、RabbitMQ、Zookeeper等,并且大大减少了出错的概率。
对于应用端口方面,传统行业中,一个服务器可能跑了很多进程,每个进程都有一个端口,需要人为的去配置端口,并且还需要考虑端口冲突的问题,如果有防火墙的话,还需要配置防火墙,在k8s中,端口统一管理,统一配置,每个应用的端口都可设置成一样的,之后通过service进行负载均衡,大大降低了端口管理的复杂度和端口冲突。
无论是对于开发人员、测试人员还是运维人员,k8s的诞生,不仅减少了工作的复杂性,还减少了各种成本。上述带来的变革只是其中比较小的一部分,更多优点只有用了才能体会到。
二、 kubernetes带来的挑战
首先是对于k8s的学习本身就是很难的,概念太多,无从入手,可能学习了一个月也无法入门,甚至连集群也搭建不出来,使人望而却步。并且k8s对运维的技术能力要求比较高,已经不仅仅局限于传统运维,有时候你可能要修改业务代码等。并且需要掌握的知识也需要很多,你可能需要掌握公司所有使用到的代码,比如代码是如何进行编译的、如何正确发布、如何修改代码配置文件等,这对于运维人员,也是一种挑战。Kubernetes之所以被叫做k8s,业界有两种说法,通俗的说法是k和s之间有8个字母,另一种比较说法是k8s集群至少需要搭建8遍才能搭建成功。当然,在实际使用时,可能不止8遍。k8s的诞生,把运维从传统转变到了DevOps方向,需要面临的问题会更多,需要面临的新技术也有很多,但是当你掌握到了k8s的核心使用,就会受益终身。
三、Pod初体验
1.pod简单介绍
K8s有很多技术概念,同时对应很多API对象,最重要的也是最基础的是微服务Pod。Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod*享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8s最基础的设计理念。比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。这就是K8S中的POD。
Pod是K8s集群中所有业务类型的基础,可以看作运行在K8s集群中的小机器人,不同类型的业务就需要不同类型的小机器人去执行。目前K8s中的业务主要可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application);分别对应的小机器人控制器为Deployment、Job、DaemonSet和StatefulSet。
总结来说,Pod 是 k8s 系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume资源对象是用来为 Pod 提供存储等等,k8s 不会直接处理容器,而是 Pod,Pod 是由一个或多个 container 组成。
Pod 是 Kubernetes 的最重要概念,每一个 Pod 都有一个特殊的被称为”根容器“的 Pause 容器。Pause 容器对应的镜 像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器
2.Pod实现机制
#1.共享网络(通过Pause容器。把其他业务容器加入到Pause容器里面,让所有业务容器在同—个名称空间中,可以实现网络共享)
Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个 node 上。同一个Pod中的容器共享资源、网络环境和依赖,所以它们总是被同时调度。在一个Pod中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。
#2.共享存储(引入数据卷概念Volumn,使用数据卷进行持久化存储)
Pod在设计⽀持就不是作为持久化实体的。在调度失败、节点故障、缺少资源或者节点维护的状态下都会死掉会被驱逐。通常,我们是需要借助类似于Docker存储卷这样的资源来做Pod的数据久化的。
3.Pod vs 应用
每个 Pod 都是应用的一个实例,有专用的 IP
4.Pod vs 容器
一个 Pod 可以有多个容器,彼此间共享网络和存储资源,每个 Pod 中有一个 Pause 容器保存所有的容器状态, 通过管理 pause 容器,达到管理 pod 中所有容器的效果
5.Pod vs 节点
同一个 Pod 中的容器总会被调度到相同 Node 节点,不同节点间 Pod 的通信基于虚拟二层网络技术实现
6.Pod vs Pod
普通的 Pod 和静态 Pod
四、Pod存在的意义及好处
1.意义
#1.创建容器使用doeker,一个docker对应一个容器,一个容器有进程。一个容器运行一个应用程序
#2.Pod是多进程设计,运行多个应用程序
一个Pod有多个容器,一个容器里面运行一个应用程序
#3.Pod存在为了亲密性应用
两个应用之间进行交互
网络之间调用
两个应用需要频繁调用
2.好处
#1.Pod做为一个可以独立运行的服务单元,简化了应用部署的难度,以更高的抽象层次为应用部署管提供了极大的方便。
#2.Pod做为最小的应用实例可以独立运行,因此可以方便的进行部署、水平扩展和收缩、方便进行调度管理与资源的分配。
#3.Pod中的容器共享相同的数据和网络地址空间,Pod之间也进行了统一的资源管理与分配。
五、Pod特性
1.资源共享
一个 Pod 里的多个容器可以共享存储和网络,可以看作一个逻辑的主机。共享的如namespace,cgroups 或者其他的隔离资源。
多个容器共享同一network namespace,由此在一个 Pod 里的多个容器共享 Pod 的 IP 和端口 namespace,所以一个 Pod 内的多个容器之间可以通过 localhost 来进行通信,所需要注意的是不同容器要注意不要有端口冲突即可。不同的 Pod 有不同的 IP,不同 Pod 内的多个容器之前通信,不可以使用 IPC(如果没有特殊指定的话)通信,通常情况下使用 Pod 的 IP 进行通信。
一个 Pod 里的多个容器可以共享存储卷,这个存储卷会被定义为 Pod 的一部分,并且可以挂载到该 Pod 里的所有容器的文件系统上。
2.生命周期短暂
Pod 属于生命周期比较短暂的组件,比如,当 Pod 所在节点发生故障,那么该节点上的 Pod 会被调度到其他节点,但需要注意的是,被重新调度的 Pod 是一个全新的 Pod,跟之前的Pod 没有半毛钱关系。
3.平坦的网络
K8s 集群中的所有 Pod 都在同一个共享网络地址空间中,也就是说每个 Pod 都可以通过其他 Pod 的 IP 地址来实现访问。
六、Pod的资源清单详解
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
namespace: web-testing # 可选,不指定默认为default,Pod所在的命名空间
labels: # 可选,标签选择器,一般用于Selector
- app: nginx
annotations: # 可选,注释列表
- app: nginx
spec: # 必选,用于定义容器的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: nginx:v1 # 必选,容器所用的镜像的地址
imagePullPolicy: Always # 可选,镜像拉取策略
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
volumeMounts: # 可选,存储卷配置
- name: webroot # 存储卷名称
mountPath: /usr/share/nginx/html # 挂载目录
readOnly: true # 只读
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置
- name: TZ # 变量名
value: Asia/Shanghai
- name: LANG
value: en_US.utf8
resources: # 可选,资源限制和资源请求限制
limits: # 最大限制设置
cpu: 1000m
memory: 1024MiB
requests: # 启动所需的资源
cpu: 100m
memory: 512MiB
readinessProbe: # 可选,容器状态检查
httpGet: # 检测方式
path: / # 检查路径
port: 80 # 监控端口
timeoutSeconds: 2 # 超时时间
initialDelaySeconds: 60 # 初始化时间
livenessProbe: # 可选,监控状态检查
exec: # 检测方式
command:
- cat
- /health
httpGet: # 检测方式
path: /_health
port: 8080
httpHeaders:
- name: end-user
value: jason
tcpSocket: # 检测方式
port: 80
initialDelaySeconds: 60 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 2 # 检查成功为2次表示就绪
failureThreshold: 1 # 检测失败1次表示未就绪
securityContext: # 可选,限制容器不可信的行为
provoleged: false
restartPolicy: Always # 可选,默认为Always
nodeSelector: # 可选,指定Node节点
region: subnet7
imagePullSecrets: # 可选,拉取镜像使用的secret
- name: default-dockercfg-86258
hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口
volumes: # 共享存储卷列表
- name: webroot # 名称,与上述对应
emptyDir: {} # 共享卷类型,空
hostPath: # 共享卷类型,本机目录
path: /etc/hosts
secret: # 共享卷类型,secret模式,一般用于密码
secretName: default-token-tf2jp # 名称
defaultMode: 420 # 权限
configMap: # 一般用于配置文件
name: nginx-conf
defaultMode: 420
七、Pod 的基本使用
在 kubernetes 中对运行容器的要求为:容器的主程序需要一直在前台运行,而不是后台运行。应用需要改造成前台运行的方式。如果我们创建的 Docker 镜像的启动命令是后台执行程序,则在 kubelet 创建包含这个容器的 pod 之后运行完该命令,即认为 Pod 已经结束, 将立刻销毁该Pod。如果为该 Pod 定义了 RC,则创建、销毁会陷入一个无限循环的过程中。
Pod 可以由 1 个或多个容器组合而成。
1.一个容器组成的 Pod 的 yaml 示例
[root@k8s-master-001 ~]# vi first-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: first-pod
labels:
app: bash
spec:
containers:
- name: bash-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']
2.多个容器组成的 Pod 的 yaml 示例
[root@k8s-master-001 ~]# vi second-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myweb
labels:
name: tomcat-redis
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containerPort: 8080
- name: redis
image: redis
ports:
- containerPort: 6379
3.创建
[root@k8s-master-001 ~]# kubectl apply -f first-pod.yaml
pod/first-pod created
[root@k8s-master-001 ~]# kubectl apply -f second-pod.yaml
pod/myweb created
4.查看
[root@k8s-master-001 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
first-pod 0/1 Completed 3 5m2s
myweb 2/2 Running 0 4m49s
[root@k8s-master-001 ~]# kubectl logs first-pod
Hello Kubernetes
[root@k8s-master-001 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-pod 0/1 CrashLoopBackOff 6 14m 10.241.184.2 k8s-node-002 <none> <none>
myweb 2/2 Running 0 13m 10.241.184.3 k8s-node-002 <none> <none>
[root@k8s-master-001 ~]# kubectl describe pod first-pod
Name: first-pod
Namespace: default
Priority: 0
Node: k8s-node-002/172.16.1.114
Start Time: Tue, 28 Sep 2021 14:54:47 +0800
Labels: app=bash
Annotations: Status: Running
IP: 10.241.184.2
IPs:
IP: 10.241.184.2
Containers:
bash-container:
Container ID: docker://6560a18d58bc165464ee7155ab3001a4337a5108098f47fa7f9dfee6b9deed07
Image: busybox
Image ID: docker-pullable://busybox@sha256:f7ca5a32c10d51aeda3b4d01c61c6061f497893d7f6628b92f822f7117182a57
Port: <none>
Host Port: <none>
Command:
sh
-c
echo Hello Kubernetes! && sleep 10
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Tue, 28 Sep 2021 15:05:52 +0800
Finished: Tue, 28 Sep 2021 15:06:02 +0800
Ready: False
Restart Count: 6
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cvczf (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-cvczf:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-cvczf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 360s
node.kubernetes.io/unreachable:NoExecute for 360s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/first-pod to k8s-node-002
Normal Started 10m (x4 over 14m) kubelet, k8s-node-002 Started container bash-container
Normal Pulling 9m30s (x5 over 14m) kubelet, k8s-node-002 Pulling image "busybox"
Normal Pulled 9m14s (x5 over 14m) kubelet, k8s-node-002 Successfully pulled image "busybox"
Normal Created 9m14s (x5 over 14m) kubelet, k8s-node-002 Created container bash-container
Warning BackOff 4m48s (x26 over 11m) kubelet, k8s-node-002 Back-off restarting failed container
[root@k8s-master-001 ~]# kubectl describe pod myweb
Name: myweb
Namespace: default
Priority: 0
Node: k8s-node-002/172.16.1.114
Start Time: Tue, 28 Sep 2021 14:55:01 +0800
Labels: name=tomcat-redis
Annotations: Status: Running
IP: 10.241.184.3
IPs:
IP: 10.241.184.3
Containers:
tomcat:
Container ID: docker://5659eaf2061c015c57274881b0a95a76edcc88b3d6b2b5c99e15f5da2bc6510b
Image: tomcat
Image ID: docker-pullable://tomcat@sha256:54876d82d30746c5b625a784938864d5b726219e0aace09b3e57ef4dfa85d594
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 28 Sep 2021 14:57:45 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cvczf (ro)
redis:
Container ID: docker://6e8a571baf372571de70d9e672c3ef8a8e9cfeeab9845d661abd2a80b084585b
Image: redis
Image ID: docker-pullable://redis@sha256:e595e79c05c7690f50ef0136acc9d932d65d8b2ce7915d26a68ca3fb41a7db61
Port: 6379/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 28 Sep 2021 14:58:18 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cvczf (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-cvczf:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-cvczf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 360s
node.kubernetes.io/unreachable:NoExecute for 360s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/myweb to k8s-node-002
Normal Pulling 15m kubelet, k8s-node-002 Pulling image "tomcat"
Normal Pulled 12m kubelet, k8s-node-002 Successfully pulled image "tomcat"
Normal Created 12m kubelet, k8s-node-002 Created container tomcat
Normal Started 12m kubelet, k8s-node-002 Started container tomcat
Normal Pulling 12m kubelet, k8s-node-002 Pulling image "redis"
Normal Pulled 11m kubelet, k8s-node-002 Successfully pulled image "redis"
Normal Created 11m kubelet, k8s-node-002 Created container redis
Normal Started 11m kubelet, k8s-node-002 Started container redis
5.删除
[root@k8s-master-001 ~]# kubectl delete -f first-pod.yaml
pod "first-pod" deleted
[root@k8s-master-001 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myweb 2/2 Running 0 24m
nginx-f89759699-knhc6 1/1 Running 0 26m
[root@k8s-master-001 ~]# kubectl delete pod --all
pod "myweb" deleted
[root@k8s-master-001 ~]# kubectl get pod
No resources found in default namespace.
八、Pod 的分类
1.普通 Pod
普通 Pod 一旦被创建,就会被放入到 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定,随后该 Pod 对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动起来。在默认情 况下,当 Pod 里某个容器停止时,Kubernetes 会自动检测到这个问题并且重新启动这个 Pod 里某所有容器, 如果 Pod 所在的 Node 宕机, 则会将这个 Node 上的所有 Pod 重新调度到其它节点上。
2.静态 Pod
静态 Pod 是由 kubelet 进行管理的仅存在于特定 Node 上的 Pod,它们不能通过 API Server 进行管理,无法与 ReplicationController、Deployment 或 DaemonSet 进行关联,并且kubelet 也无法对它们进行健康检查。
九、Pod的生命周期和重启策略
Pod 在整个生命周期过程中被系统定义为各种状态,熟悉 Pod 各种状态对于理解如何设置 Pod的调度策略、重启策略是很有必要的。
1.Pod的状态
状态值 |
描述 |
挂起(Pending) |
API Server创建了pod资源对象已存入etcd中,但它尚未被调度完成,或者仍处于从仓库下载镜像的过程中。 |
运行中(Running) |
Pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成 |
成功(Successed/Completed) |
Pod中的所有容器都已经成功终止并且不会被重启 |
失败(Failed) |
Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。即容器以非0状态退出或者被系统禁止。 |
未知(Unknown) |
Api Server无法正常获取到Pod对象的状态信息,通常是由于无法与所在工作节点的kubelet通信所致。 |
2.Pod的重启策略
Pod 重启策略( RestartPolicy )应用于 Pod 内的所有容器,井且仅在 Pod 所处的 Node 上由kubelet 进行判断和重启操作。当某个容器异常退出或者健康检查失败时, kubelet将根据 RestartPolicy 设置来进行相应的操作。Pod的重启策略包括:Always、OnFailure和Never,默认值为Always
状态值 |
说明 |
Always |
当容器失效时,由kubelet自动重启该容器。 |
OnFailure |
当容器终止运行且退出码不为0时,由kubelet自动重启该容器。 |
Never |
不论容器运行状态如何,kubelet都不会重启该容器。 |
kubelet 重启失效容器的时间间隔以 sync-frequency 乘以 2n 来计算;例如1、2、4、8倍等,最长延时 5min ,并且在成功重启后的 10 min 后重置该时间。
Pod的重启策略与控制方式息息相关,当前可用于管理Pod的控制器包括ReplicationController、Job、DaemonSet及直接通过kubelet管理(静态Pod)。每种控制器对Pod的重启策略要求如下:
1.RC和DaemonSet:必须设置为Always,需要保证该容器持续运行。
2.Job和CronJob:OnFailure或Never,确保容器执行完成后不再重启。
3.kubelet:在Pod失效时自动重启它,不论将RestartPolicy设置为什么值,也不会对Pod进行健康检查。
3.常见状态转换
Pod包含的容器数 |
Pod当前的状态 |
发生事件 |
Pod的结果状态 |
|
|
|
|
|
RestartPolicy=Always |
RestartPolicy=OnFailure |
RestartPolicy=Never |
包含一个容器 |
Running |
容器成功退出 |
Running |
Succeeded |
Succeeded |
包含一个容器 |
Running |
容器失败退出 |
Running |
Running |
Failure |
包含两个容器 |
Running |
1个容器失败退出 |
Running |
Running |
Running |
包含两个容器 |
Running |
容器被OOM杀掉 |
Running |
Running |
Failure |
十、Pod 资源配置
每个 Pod 都可以对其能使用的服务器上的计算资源设置限额,Kubernetes 中可以设置限额的计算资源有 CPU 与 Memory 两种,其中 CPU 的资源单位为 CPU 数量,是一个绝对值而非相对值。Memory 配额也是一个绝对值,它的单 位是内存字节数。
Kubernetes 里,一个计算资源进行配额限定需要设定以下两个参数: Requests 该资源最小申请数量,系统必须满足要求 Limits 该资源最大允许使用的量,不能突破,当容器试图使用超过这个量的资源时,可能会被 Kubernetes Kill 并重启。
1.举例
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
namespace: web-testing # 可选,不指定默认为default,Pod所在的命名空间
labels: # 可选,标签选择器,一般用于Selector
- app: nginx
annotations: # 可选,注释列表
- app: nginx
spec: # 必选,用于定义容器的详细信息
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: nginx:v1 # 必选,容器所用的镜像的地址
imagePullPolicy: Always # 可选,镜像拉取策略
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
volumeMounts: # 可选,存储卷配置
- name: webroot # 存储卷名称
mountPath: /usr/share/nginx/html # 挂载目录
readOnly: true # 只读
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置
- name: TZ # 变量名
value: Asia/Shanghai
- name: LANG
value: en_US.utf8
resources: # 可选,资源限制和资源请求限制
limits: # 最大限制设置
cpu: 1000m
memory: 1024MiB
requests: # 启动所需的资源
cpu: 100m
memory: 512MiB
上述代码表明 nginx 容器申请最少 0.1 个 CPU 以及 512MiB 内存,在运行过程中容器所能使用的资源配额为 1 个 CPU 以及 1G 内存。