k8s资源清单和Pod

k8s资源清单和Pod

  • 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 资源清单-介绍和常用字段

1.1 K8s中的资源分类

  1. 集群资源分类(适用范围进行分类)
    1.名称空间级别(仅在此名称空间下生效):kubectl get pod -n defalut
    2.集群级别资源
    3.元数据类型资源(根据指标进行对应的操作)
  2. K8s中所有的内容都抽象为资源,资源实例化之后,叫做对象
  3. 名称空间级别
    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 (把外部环境中的信息输出给容器)
  4. 集群级别资源:
    1.Namespace、Node、Role、ClusterRole、 RoleBinding、ClusterRoleBinding
  5. 元数据类型资源
    1.HPA、PodTemplate、LimitRange(资源限制)

1.2 YAML格式

  1. YAML是一个可读性高,用来表达数据序列的格式。YAML的意思其实是:仍是一种标记语言, 但为了强调这种语言以数据做为中心,而不是以标记语言为重点
  2. 基本语法
    1.缩进时不允许使用Tab键,只允许使用空格
    2.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
    3.标识注释,从这个字符一直到行尾,都会被解释器忽略
  3. YAML支持的数据结构
    1.对象:键值对的集合,又称为映射(mapping) /哈希(hashes) 1字典(dictionary)
    2.数组: 一组按次序排列的值,又称为序列(sequence) /列表(list)
    3.纯量(scalars) :单个的、不可再分的值

1.3 YAML数据类型

  1. 对象类型:对象的一组键值对,使用冒号结构表示。或者将所有键值对写成一个行内对象
name: Steve
age : 18
# Yaml也允许另一种写法,将所有键值对写成一个行内对象
hash: {name: Steve, age: 18}
  1. 数组类型: 一组连词线开头的行,构成一个数组。或者数组也可以采用行内表示法
animal
- Cat 
- Dog
# 数组也可以采用行内表示法
animal: [Cat, Dog]
  1. 复合结构:对象和数组可以结合使用,形成复合结构
languages:
- Ruby
- Perl
- Python
websites:
 YAML: yaml.org
 Ruby: ruby-lang.org
 Python: python.org
 Perl: use.perl.org
  1. 纯量:纯量是最基本的、不可再分的值。以下数据类型都属于纯量
# 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
  1. 字符串默认不使用引号表示
# 字符串默认不使用引号表示
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 常用字段的解释

  1. 必须存在的属性。如果不存在不允许执行。
参数名 字段类型 说明
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 这里定义要用到的镜像名称
  1. 主要对象,不写会帮我们补上默认值。(这里也不全,主要的),可以通过kubectl命令查看。比如查看pod的。
    1.kubectl explain pod
    2.kubectl explain pod.apiVersion
    k8s资源清单和Pod_第1张图片
    k8s资源清单和Pod_第2张图片
    k8s资源清单和Pod_第3张图片

2.资源清单-容器的生命周期解析

Docker 管理的进程是 pid=1 的主进程,其他进程死掉了就会成为僵尸进程,一个容器最好只干一件事情, 我们应用内部的进程与进程间通信(通过 IPC 或者共享本地文件之类)都是要求在本地进行的,也就是需要在同一个节点上运行。所以我们需要一个更高级别的结构来将这些容器绑定在一起,并将他们作为一个基本的调度单元进行管理,这样就可以保证这些容器始终在同一个节点上面,这也就是 Pod 设计的初衷。
其实 Pod 也只是一个逻辑概念,真正起作用的还是 Linux 容器的 Namespace 和 Cgroup 这两个最基本的概念,Pod 被创建出来其实是一组共享了一些资源的容器而已。首先 Pod 里面的所有容器,都是共享的同一个 Network Namespace,但是涉及到文件系统的时候,默认情况下 Pod 里面的容器之间的文件系统是完全隔离的,但是我们可以通过声明来共享同一个 Volume。
1)自助式
2)控制器管理 (始终维持Pod副本数)

2.1 Pod的生命周期过程

  1. kubectl向kubeApi接口发送指令->通过etcd调度kubelet->通过CLI创建基础容器pause->init C初始化(也可以没有)->Main C主容器刚运行是可以启动start一个命令当然结束后也可以Stop运行一个命令->readness不断检测,检测成功容器状态变成running->Liveness一直检测,如果遇到问题可以进行重新创建Pod
    k8s资源清单和Pod_第4张图片
  2. init C是初始化容器,只用来初始化Pod,完成后它就会死亡。它不能并行运行,两个init C必须线性执行,就是一个执行完成之后另一个才运行。
  3. pause基础容器用来创建init C
  4. Main C容器,主容器可能也有多个。这里假设为一个,它有Start和Stop操作,执行之前和执行之后可以执行自己的操作。
  5. readness是就绪检测,Liveness是生存检测。

2.2 Pod的生命周期-init C介绍

  1. Pod能够具有多个容器,应用运行在容器里而,但是它也可能有一个或多个先于应用容器启动的Init容器
  2. Init容器与普通的容器非常像,除了如下两点:
    1.Init容器总是运行到成功完成为止
    2.每个Init容器都必须在下一个Init容器启动之前成功完成(就是这个init C不执行成功,下一个init C不会执行)
  3. 如果Pod的Init容器失败,Kubernetes 会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy 为Never, 它不会重新启动
  4. init C不像Main C。Main C退出后Pod就结束了,init C退出不会跟Pod的生命周期相关。
  5. 因为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检测先决条件,防止意外发生。

2.3 Pod的生命周期-init C模板

  1. 下面定义了两个init进程。两个初始化容器按顺序执行。
  2. 先删除所有的deployment,这里如果只删除pod, 会为了满足预期重启其他pod
    1.kubectl delete deployment --all
    2.kubectl delete pod --all
    3.kubectl get svc 有其他服务也删了(svc是service的简写)
  3. 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;']
  1. 运行后一定会被卡住,因为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。
  2. 创建myservice的服务:kubectl create -f myservice.yaml
    1.创建完成后看是否有服务:kubectl get svc
    k8s资源清单和Pod_第5张图片
kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80  # 容器内部端口
      targetPort: 9376  # 映射到外部的端口

  1. 创建mydb的服务完成第二个初始化容器:kubectl create -f mydb.yaml
    1.这里和上面init C端口一致不会影响, 因为init C上一个执行完成退出后才会执行这个
  2. 这里注意:镜像能不用latest就不用。因为每次都会访问服务器重新更新。
    k8s资源清单和Pod_第6张图片
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

2.4 Pod的生命周期-init C注意事项

  1. 在Pod启动过程中, init容器会按顺序在网络和数据卷初始化之后(这里就是pause容器的作用,我们动不了它,知道就行)启动.每个容器必须在下一个容器启动之前成功退出
  2. 如果由于运行时或失败退出,将导致容器启动失败,它会根据Pod的restartPolicy 指定的策略进行重试。然而,如果Pod的restartPolicy 设置为Always, Init 容器失败时会使用RestartPolicy策略
  3. 在所有的Init容器没有成功之前,Pod将不会变成Ready状态。Init容器的端口将不会在Service中进行聚集。正在初始化中的 Pod 处于Pending 状态,但应该会将Initializing 状态设置为true
  4. 如果Pod重启,所有Init容器必须重新执行
  5. 对Init容器spec的修改被限制在容器image 字段,修改其他字段都不会生效(只可以修改image字段)。更改Init容器的image字段,等价于重启该Pod。kubectl edit pod myapp-pod
  6. Init容器具有应用容器的所有字段。除了readinessProbe, 因为Init容器无法定义不同于完成
    (completion)的就绪(readiness) 之外的其他状态。这会在验证过程中强制执行
  7. 在Pod中的每个app和Init容器的名称必须唯一; 与任何其它容器共享同一个名称,会在验证时抛出错误

2.5 Pod的生命周期-探针介绍

  1. 探针的提出:如果在init C中做不好,因为init C总会退出,Main C连不上就检测不出来了。
  2. 探针是由kubelet对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的Handler有三种类型的处理程序:
    1.ExecAction: 在容器内执行指定命令。如果命令退出时返回码为0,则认为诊断成功。
    2.TCPSocketAction: 对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的。
    3.HTTPGetAction: 对指定的端口和路径上的容器的IP地址执行HTTP Get请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的
  3. 每次探测都将获得以下三种结果之一:
    1.成功:容器通过了诊断。
    2.失败:容器未通过诊断。
    3.未知:诊断失败,因此不会采取任何行动
  4. 探测方案有两种:
    1.livenessProbe:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success
    2.readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service 的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure.如果容器不提供就绪探针,则默认状态为Success

2.6 Pod的生命周期-探针实现就绪检测

  1. 探针检测-就绪检测。 执行 get 检测,因为根本就没有index1.html这个文件,所以这个剧本执行一定失败
    1.initialDelaySeconds: 1 检测延时:容器启动后一秒后开始执行检测
    2.periodSeconds: 3 重试间隔3秒
  2. 探针的举例
    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指定**
  3. 进入容器后,echo “123” >> /usr/share/nginx/html/index1.html, 退出exit.再次查看:kubectl get pod,发现已经成功Ready
    k8s资源清单和Pod_第7张图片
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的生命周期-探针实现存活检测

  1. 探针检测-存活检测-ExecAction命令探测
  2. 检测意思就是,启动后会创建一个文件 /tmp/live ,60秒后删除这个文件。然后存活检测是查看这个文件是否存在,存在返回值为0即存活,然而60秒后因为删除了这个文件,所以会检测失败,因为检测失败就会触发重启策略,重启后文件又重新创建,检测也就能成功,如此循环
  3. 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 #三秒检测一次

  1. 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
  1. 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

  1. init C也可以和我们的readness、liveness配合使用。

2.8 Pod的生命周期-start、stop启动退出动作

  1. 启动、退出动作。定义一个pod启动时想要做什么,和退出时要做什么
  2. 应用场景举例:数据库容器的退出备份、退出序列化
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的启动状态

  1. 挂起(Pending) : Pod已被Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度Pod的时间和通过网络下载镜像的时间,这可能需要花点时间
  2. 运行中(Running) :该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态
  3. 成功(Succeeded) : Pod中的所有容器都被成功终止,并且不会再重启
  4. 失败(Failed) : Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止
  5. 未知(Unknown) :因为某些原因无法取得Pod的状态,通常是因为与Pod 所在主机通信失败

你可能感兴趣的:(docker,kubernetes,容器,云原生)