- 1 资源清单-介绍和常用字段
- 1.1 K8s中的资源分类
- 1.2 YAML格式
- 1.3 YAML数据类型
- 1.4 常用字段的解释
- 2.资源清单-容器的生命周期解析
- 2.1 Pod的生命周期过程
- 2.2 Pod的生命周期-init C介绍
- 2.3 Pod的生命周期-init C模板
- 2.4 Pod的生命周期-init C注意事项
- 2.5 Pod的生命周期-探针介绍
- 2.6 Pod的生命周期-探针实现就绪检测
- 2.7 Pod的生命周期-探针实现存活检测
- 2.8 Pod的生命周期-start、stop启动退出动作
- 2.9 Pod的生命周期-Pod的启动状态
- 集群资源分类(适用范围进行分类)
1.名称空间级别(仅在此名称空间下生效):kubectl get pod -n defalut
2.集群级别资源
3.元数据类型资源(根据指标进行对应的 *** 作) - K8s中所有的内容都抽象为资源,资源实例化之后,叫做对象
- 名称空间级别
1.工作负载型资源( workload ):Pod、ReplicaSet、 Deployment、 StatefulSet、 DaemonSet、 Job、CronJob ( ReplicationController 在v1. 11版本被废弃)
2.服务发现及负载均衡型资源( ServiceDi scovery LoadBalance ): Service、 Ingress、 …
3.配置与存储型资源: Volume( 存储卷)、CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
4.特殊类型的存储卷: ConfigMap( 当配置中心来使用的资源类型)、Secret (保存敏感数据)、DownwardAPI (把外部环境中的信息输出给容器) - 集群级别资源:
1.Namespace、Node、Role、ClusterRole、 RoleBinding、ClusterRoleBinding - 元数据类型资源
1.HPA、PodTemplate、LimitRange(资源限制)
- YAML是一个可读性高,用来表达数据序列的格式。YAML的意思其实是:仍是一种标记语言, 但为了强调这种语言以数据做为中心,而不是以标记语言为重点
- 基本语法
1.缩进时不允许使用Tab键,只允许使用空格
2.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
3.标识注释,从这个字符一直到行尾,都会被解释器忽略 - YAML支持的数据结构
1.对象:键值对的集合,又称为映射(mapping) /哈希(hashes) 1字典(dictionary)
2.数组: 一组按次序排列的值,又称为序列(sequence) /列表(list)
3.纯量(scalars) :单个的、不可再分的值
- 对象类型:对象的一组键值对,使用冒号结构表示。或者将所有键值对写成一个行内对象
name: Steve
age : 18
# Yaml也允许另一种写法,将所有键值对写成一个行内对象
hash: {name: Steve, age: 18}
- 数组类型: 一组连词线开头的行,构成一个数组。或者数组也可以采用行内表示法
animal
- Cat
- Dog
# 数组也可以采用行内表示法
animal: [Cat, Dog]
- 复合结构:对象和数组可以结合使用,形成复合结构
languages:
- Ruby
- Perl
- Python
websites:
YAML: yaml.org
Ruby: ruby-lang.org
Python: python.org
Perl: use.perl.org
- 纯量:纯量是最基本的、不可再分的值。以下数据类型都属于纯量
# 1 字符串布尔值整数浮点数Null
# 2 时间日期
# 数值直接以字面量的形式表示
number: 12.30
# 布尔值用true和false表示
isSet: true
# nu11用~表示
parent: ~
# 时间采用IS08601格式
iso8601: 2008-09-03T20:56:35.450686
# 日期采用复合iso8601 格式的年、月、日表示
date: 1976-07-31
# YAML允许使用两个感叹号,强制转换数据类型
e: !!str 123
f: !!str true
- 字符串默认不使用引号表示
# 字符串默认不使用引号表示
str: 这是一行字符串
# 如果字符串之中包含空格或特殊字符,需要放在引号之中
str: '内容: 字符串'
# 单引号和双引号都可以使用,双引号不会对特殊字符转义
s1 : '内容\n字符串'
s2 : "内容\n字符串”
# 单引号之中如果还有单引号,必须连续使用两个单引号转义
str: 'labor''s day'
# 字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格
str:这是一段
多行
字符串
# 多行字符串可以使用|保留换行符,也可以使用>折叠换行
this: |
Foo
Bar
that: >
Foo
Bar
# +表示保留文字块末尾的换行,表示删除字符串末尾的换行
s1:|
Foo
s2:| +
Foo
s3:|-
Foo
1.4 常用字段的解释
- 必须存在的属性。如果不存在不允许执行。
参数名 | 字段类型 | 说明 |
---|---|---|
version | String | 这里是指的是K8S API的版本,目前基本上是v1, 可以用kubectl api-versions的命令查看 |
kind | String | 这里指的是yaml文件定义的资源类型和角色,比如: Pod |
metadata | Object | 元数据对象,固定值就写metadata |
metadata.name | String | 元数据对象的名字,这里由我们编写,比如命名Pod的名字 |
metadata. namespace | String | 元数据对象的命名空间,由我们自身定义 |
Spec | Object | 详细定义对象,固定值就写Spec |
spec. containers[] | list | 这里是Spec对象的容器列表定义,是个列表 |
spec.containers[].name | String | 这里定义容器的名字 |
spec.containers[].image | String | 这里定义要用到的镜像名称 |
- 主要对象,不写会帮我们补上默认值。(这里也不全,主要的),可以通过kubectl命令查看。比如查看pod的。
1.kubectl explain pod
2.kubectl explain pod.apiVersion
Docker 管理的进程是 pid=1 的主进程,其他进程死掉了就会成为僵尸进程,一个容器最好只干一件事情, 我们应用内部的进程与进程间通信(通过 IPC 或者共享本地文件之类)都是要求在本地进行的,也就是需要在同一个节点上运行。所以我们需要一个更高级别的结构来将这些容器绑定在一起,并将他们作为一个基本的调度单元进行管理,这样就可以保证这些容器始终在同一个节点上面,这也就是 Pod 设计的初衷。
其实 Pod 也只是一个逻辑概念,真正起作用的还是 Linux 容器的 Namespace 和 Cgroup 这两个最基本的概念,Pod 被创建出来其实是一组共享了一些资源的容器而已。首先 Pod 里面的所有容器,都是共享的同一个 Network Namespace,但是涉及到文件系统的时候,默认情况下 Pod 里面的容器之间的文件系统是完全隔离的,但是我们可以通过声明来共享同一个 Volume。
1)自助式
2)控制器管理 (始终维持Pod副本数)
- kubectl向kubeApi接口发送指令->通过etcd调度kubelet->通过CLI创建基础容器pause->init C初始化(也可以没有)->Main C主容器刚运行是可以启动start一个命令当然结束后也可以Stop运行一个命令->readness不断检测,检测成功容器状态变成running->Liveness一直检测,如果遇到问题可以进行重新创建Pod
- init C是初始化容器,只用来初始化Pod,完成后它就会死亡。它不能并行运行,两个init C必须线性执行,就是一个执行完成之后另一个才运行。
- pause基础容器用来创建init C
- Main C容器,主容器可能也有多个。这里假设为一个,它有Start和Stop *** 作,执行之前和执行之后可以执行自己的 *** 作。
- readness是就绪检测,Liveness是生存检测。
- Pod能够具有多个容器,应用运行在容器里而,但是它也可能有一个或多个先于应用容器启动的Init容器
- Init容器与普通的容器非常像,除了如下两点:
1.Init容器总是运行到成功完成为止
2.每个Init容器都必须在下一个Init容器启动之前成功完成(就是这个init C不执行成功,下一个init C不会执行) - 如果Pod的Init容器失败,Kubernetes 会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy 为Never, 它不会重新启动
- init C不像Main C。Main C退出后Pod就结束了,init C退出不会跟Pod的生命周期相关。
- 因为Init容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:
1.它们可以包含并运行实用工具,出于安全考虑,是不建议在应用程序容器镜像(Main C镜像) 中包含这些实用工具。避免Main C过于冗余,可以把工具写在init C中。解决了Main C的冗余性问题。
2.它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像(Main C镜像)中。例如,创建镜像没必要FROM另一个镜像, 只需要在安装过程中使用类似sed、awk、 python 或dig这样的工具。解决了Main C的安全性问题。
3.应用程序镜像Main C可以分离出创建和部署的角色(放入到init C中),而没有必要联合它们构建一个单独的镜像。
4.Init 容器使用Linux Namespace,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret 的权限,而应用程序容器则不能。就是说:如果Main C需要访问有权限的文件时,获取权限可能会对其他文件进行 *** 作不安全,可以把这个权限给init C由它完成文件 *** 作回写给Main C。
5.它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以Init容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。如果两个Main C容器存在强依赖,可能会导致报错崩溃退出。这种情况下可以加个init C检测先决条件,防止意外发生。
- 下面定义了两个init进程。两个初始化容器按顺序执行。
- 先删除所有的deployment,这里如果只删除pod, 会为了满足预期重启其他pod
1.kubectl delete deployment --all
2.kubectl delete pod --all
3.kubectl get svc 有其他服务也删了(svc是service的简写) - init_pod.yaml : kubectl create -f init_pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
- 运行后一定会被卡住,因为init C没有完成。它需要借助其他的myservice的服务。
1.首先:查看一下详细信息没有其他报错 kubectl describe pod myapp-pod
2.然后:查看init C的init-myservice容器的日志 kubectl logs myapp-pod -c init-myservice
3.发现一直重新运行,创建myservice的服务让它完成自己的init C。 - 创建myservice的服务:kubectl create -f myservice.yaml
1.创建完成后看是否有服务:kubectl get svc
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80 # 容器内部端口
targetPort: 9376 # 映射到外部的端口
- 创建mydb的服务完成第二个初始化容器:kubectl create -f mydb.yaml
1.这里和上面init C端口一致不会影响, 因为init C上一个执行完成退出后才会执行这个 - 这里注意:镜像能不用latest就不用。因为每次都会访问服务器重新更新。
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
2.4 Pod的生命周期-init C注意事项
- 在Pod启动过程中, init容器会按顺序在网络和数据卷初始化之后(这里就是pause容器的作用,我们动不了它,知道就行)启动.每个容器必须在下一个容器启动之前成功退出
- 如果由于运行时或失败退出,将导致容器启动失败,它会根据Pod的restartPolicy 指定的策略进行重试。然而,如果Pod的restartPolicy 设置为Always, Init 容器失败时会使用RestartPolicy策略
- 在所有的Init容器没有成功之前,Pod将不会变成Ready状态。Init容器的端口将不会在Service中进行聚集。正在初始化中的 Pod 处于Pending 状态,但应该会将Initializing 状态设置为true
- 如果Pod重启,所有Init容器必须重新执行
- 对Init容器spec的修改被限制在容器image 字段,修改其他字段都不会生效(只可以修改image字段)。更改Init容器的image字段,等价于重启该Pod。kubectl edit pod myapp-pod
- Init容器具有应用容器的所有字段。除了readinessProbe, 因为Init容器无法定义不同于完成
(completion)的就绪(readiness) 之外的其他状态。这会在验证过程中强制执行 - 在Pod中的每个app和Init容器的名称必须唯一; 与任何其它容器共享同一个名称,会在验证时抛出错误
- 探针的提出:如果在init C中做不好,因为init C总会退出,Main C连不上就检测不出来了。
- 探针是由kubelet对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的Handler有三种类型的处理程序:
1.ExecAction: 在容器内执行指定命令。如果命令退出时返回码为0,则认为诊断成功。
2.TCPSocketAction: 对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的。
3.HTTPGetAction: 对指定的端口和路径上的容器的IP地址执行HTTP Get请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的 - 每次探测都将获得以下三种结果之一:
1.成功:容器通过了诊断。
2.失败:容器未通过诊断。
3.未知:诊断失败,因此不会采取任何行动 - 探测方案有两种:
1.livenessProbe:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success
2.readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service 的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure.如果容器不提供就绪探针,则默认状态为Success
- 探针检测-就绪检测。 执行 get 检测,因为根本就没有index1.html这个文件,所以这个剧本执行一定失败
1.initialDelaySeconds: 1 检测延时:容器启动后一秒后开始执行检测
2.periodSeconds: 3 重试间隔3秒 - 探针的举例
1.kubectl create -f read.yaml
2.kubectl get pod
3.kubectl describe pod readiness-httpget-pod
4.进入pod容器中:kubectl exec readiness-httpget-pod -it – /bin/sh
5.多个容器需要加**-c指定** - 进入容器后,echo “123” >> /usr/share/nginx/html/index1.html, 退出exit.再次查看:kubectl get pod,发现已经成功Ready
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget-pod
namespace: default
spec:
containers:
- name: readiness-httpget-container
image: hub.qnhyn.com/library/myapp:latest
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 80
path: /index1.html
initialDelaySeconds: 1
periodSeconds: 3
2.7 Pod的生命周期-探针实现存活检测
- 探针检测-存活检测-ExecAction命令探测
- 检测意思就是,启动后会创建一个文件 /tmp/live ,60秒后删除这个文件。然后存活检测是查看这个文件是否存在,存在返回值为0即存活,然而60秒后因为删除了这个文件,所以会检测失败,因为检测失败就会触发重启策略,重启后文件又重新创建,检测也就能成功,如此循环
- Exec方案的存活检测:kubectl create -f live-exec.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
namespace: default
spec:
containers:
- name: liveness-exec-container
image: hub.qnhyn.com/library/busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "touch /tmp/live; sleep 60; rm -rf /tmp/live; sleep 3600"]
livenessProbe:
exec:
command: ["test", "-e", "/tmp/live"]
initialDelaySeconds: 1 # 启动后1秒开始检测
periodSeconds: 3 #三秒检测一次
- HTTPGetAction方案的存活检测:
kubectl create -f liveness-httpget-pod.yaml
timeoutSeconds: 10 # 超时时间10秒代表失败啦
# 查看地址
kubectl get pod -o wide
# curl 10.244.2.11 访问服务
curl 10.244.2.11
# 交互到pod内的容器中
kubectl exec liveness-httpget-pod -it -- /bin/sh
# 删除文件 pod执行不成功啦 就重新pod啦
rm -rf /usr/share/nginx/html/index.html
exit
# 回来查看发现重启次数变成1
kubectl get pod
# 删除所有pod
kubectl delete pod --all
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-pod
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: hub.qnhyn.com/library/myapp
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
- TCPSocketAction存活检测方案:初始化后五秒开始检测80端口,超时时间1秒,检测失败重启三秒。
kubectl create -f livenessProbe-tcp.yaml
kubectl create -f livenessProbe-tcp.yaml
# 持续动态观察pod 发现检测不到 一直重启
kubectl get pod -w
apiVersion: v1
kind: Pod
metadata:
name: probe-tcp
spec:
containers:
- name: nginx
image: hub.qnhyn.com/library/myapp
livenessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 8080
periodSeconds: 3
7.以上所有检测方式可以合并到一个文件中进行多重条件检测。
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-pod
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: hub.qnhyn.com/library/myapp
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
readinessProbe: # 这里一个就绪检测
httpGet:
port: 80
path: /index1.html
initialDelaySeconds: 1
periodSeconds: 3
livenessProbe: # 这里一个HTTPGetAction存活检测
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
livenessProbe: # 这里一个TCPSocketAction存活检测
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 8080
periodSeconds: 3
- init C也可以和我们的readness、liveness配合使用。
- 启动、退出动作。定义一个pod启动时想要做什么,和退出时要做什么
- 应用场景举例:数据库容器的退出备份、退出序列化
kubectl create -f post.yaml
# 交互到pod的容器中
kubectl exec lifecycle-demo -it -- /bin/sh
# 查看输出
cat /usr/share/message
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: hub.qnhyn.com/library/myapp
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx", "-s", "quit"]
2.9 Pod的生命周期-Pod的启动状态
- 挂起(Pending) : Pod已被Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度Pod的时间和通过网络下载镜像的时间,这可能需要花点时间
- 运行中(Running) :该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态
- 成功(Succeeded) : Pod中的所有容器都被成功终止,并且不会再重启
- 失败(Failed) : Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止
- 未知(Unknown) :因为某些原因无法取得Pod的状态,通常是因为与Pod 所在主机通信失败
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)