kubernetes学习之路(八)资源清单

文章内容:

资源类型介绍、YAML格式介绍、常用字段说明、Pod生命周期、initC、initC特殊说明、探针-1、探针-2、start、stop、相位

 

资源清单,简单来说就是通过资源清单中的资源项编写剧本yaml文件,实现服务pod化、service、volume等等。

 

资源清单类型

名称空间级别:

工作负载型资源(workload)

Pod

ReplicaSet  用于通过标签创建pod

Deployment  用于通过ReplicaSet创建pod

StatefulSet  无状态服务管理器

DaemonSet  用于在每个节点都创建一个组件,例如部署监控

Job  任务

CronJob  计划任务

服务发现及负载均衡型资源(ServiceDiscovery LoadBalance)

Service

Ingress

配置与存储型资源

Volume(存储卷)

CSI (容器存储接口,可以扩展各种各样的第三方存储卷)

特殊类型的存储卷

ConfigMap (配置资源类型,部分应用的配置文件管理,达到热提交)

Secret  (保存敏感数据)

DownwardAPI (吧外部环境中的信息输出给容器,下载或上传文件的接口)

集群级别资源:

Namespace  命名空间

Node  节点

Role  角色

ClusterRole  集群角色

RoleBinding

ClusterRoleBinding

元数据型资源: 

根据指标进行操作

HPA  根据cpu 内存占用情况自动扩展缩减节点

PodTemplate   pod模板

LimitRange  资源限制

 

 

YAML格式语法

yaml语言是一种可读性高,用来表达数据序列的格式语言。其意思是:仍是一种标记型语言,但为了强调这种语言一数据作为中心,而不是以标记语言为重点。

基本语法:

  • 缩进时不允许使用Tab键,只允许使用空格
  • 缩进的空格数目不重要,但要相同层级的元素左对齐
  • #表示注释

yaml支持的数据结构

  • 对象:键值对的集合,又称为映射/哈希/字典
  • 数组:一组按次序排列的值,又称为序列/列表
  • 纯量:单个的,不可再分的值

对象类型:对象的一组键值对,使用冒号结构表示

name: Steve

age: 18

 另一种写法

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

纯量:纯量是最基本的、不可再分的值。一下数据类型都属于纯量

字符串、布尔值、整数、浮点数、null

时间、日期

数值直接以字面量的形式表示:

number: 12.13

布尔值用true和false表示:

isSet: true

null用 ~ 表示,不写也是null:

parent: ~

时间采用ISO8601格式:

iso8601: 2020-06-30t11:20:40.10-05:00

日期采用复合 iso8601 格式的年、月、日表示

date: 1999-06-30

YAML允许使用两个感叹号,强制转换数据类型:

e: !!str 123  转换为字符类型

f: !!str true 转换为字符类型

字符串

字符串默认不使用引号表示:

str: 这是一行字符串

如果字符串之中包含空格或特殊字符,需要放在引号之中:

str: '这是  一行字符串'

单引号和双引号都可以使用,双引号不会对特殊字符进行转义:

s1: '这是\n字符串‘

s2: "这是\n字符串"

单引号之中如果还有单引号,必须连续使用两个单引号转义:

str: 'labor ''s day'

字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符挥别转为空格:

str: 这是一段

 多行

 字符串

多行字符串可以使用 | 保留换行符,也可以使用 > 折叠换行:

this: |

Foo

Bar

thar: >

Foo

Bar

+ 表示保留文字块末尾的换行,-表示删除字符串末尾的换行:

s1: |

  Foo

s2: |+

  Foo

s3: |-

  Foo

 

常用字段解释

必须存在的属性表

参数名字段类型说明
versionString这里指的是K8S API的版本,目前基本上是V1,可以用kubectl api-versions命令查询
kindString这里指的是yaml文件定义的资源类型和角色,比如:Pod
metadataObject 元数据对象,固定值就写metadata
metadata.nameString元数据对象的名字,这里由我们编写,比如命名Pod的名字
metadata.namespaceString元数据对象的命名空间,由我们自身定义
SpecObject详细定义对象,固定值就写Spec
spec.containers[]list这里是Spec对象的容器列表定义,是个列表
spec.containers[].nameString这里定义容器的名字
spec.containers[].imageString这里定义要用到的镜像名称

主要对象

参数名字段类型说明
spec.containers[].nameString定义容器的名字
spec.containers[].imageString定义要用到的镜像名称
spec.containers[].imagePullPolicyString

定义镜像拉取策略,有Always、Never、ifNotPresent三个值可选

Always:意思是每次都尝试重新拉取镜像

Never:表示仅使用本地镜像

ifNotPresent:如果本地有镜像就使用本地镜像,没有就拉取镜像

默认值:Always

最佳选择是:ifNotPresent

spec.containers[].command[]List指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令
spec.containers[].args[]List指定容器启动命令参数,因为是数组可以指定多个
spec.containers[].workingDirString指定容器的工作目录
spec.containers[].env[].nameString指定环境变量名称
spec.containers[].env[].valueString指定环境变量值
spec.containers[].resourcesObject指定资源限制和资源请求的值(这里开始就是设置容器的资源上限)
spec.containers[].resources.limitsObject指定设置容器运行时的资源使用上限
spec.containers[].resources.limits.cpuString指定CPU的限制,单位为core,将用于docker run --cpu-shares参数
spec.containers[].resources.limits.memoryString指定MEM内存的限制,单位为MIB、GiB
spec.containers[].resources.requestsObject指定容器启动和调度是的限制设置
spec.containers[].resources.requests.cpuStringCPU请求,单位为core数,容器启动是初始化可用数量
spec.containers[].resources.requests.memoryString内存请求,单位为MIB、GiB,容器启动时初始化可用数量

额外的参数项

参数名字段类型说明
spec.restartPolicyString

定义Pod的重启策略,可选值为Always、OnFailure,默认值为Always

Always:Pod一旦终止运行,则无论容器是如何终止的,kubelet服务都会将其重启

OnFailure:只要Pod以非0退出码终止时,kubelet才会重启该容器

Never:Pod终止后,kubelete将退出码报告给Master,不会重启该Pod

spec.nodeSelectorObject定义Node的Label过了标签,以key:value格式指定
spec.imagePullSecretsObject定义pull镜像时使用secret名称,以name:secretkey格式指定
spec.hostNetworkBoolean

定义是否使用主机网络模式,默认值为false

设置true表示使用苏主机网络,不实用docker网桥,同时设置了true将无法在同一台宿主机上启动第二个副本

除了上面常用的以外还有很多,可以通过命令查看

查看pod的字段

kubectl create pod

FIELDS下面就是创建pod的一些模板字段

继续查看字段的详细描述信息

例如查看apiVersion

kubectl create pod.apiVersion

pod yaml文件示例:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: app
    image: docker.harbor.com/library/myapp:v1
  - name: test
    image: docker.harbor.com/library/myapp:v1

注意,上面的示例代码创建出来的pod实际上是个故障pod,原因是个pod中两个容器没有问题,问题是两个容器使用了同一个镜像,同一个镜像使用的端口一样,所以会造成端口冲突。

故障排查:

根据上面的文件创建出来的pod通过 kubectl get pod 会发现pod状态不断改变并重启,RESTARTS下的重启数值会增加

查看pod信息

kubectl describe pod myapp-pod 会发现是第二个容器 test 在重启

查看test容器日志报错信息

kubectl log myapp-pod -c test 会发现是因为端口被占用

 

Pod生命周

initC:容器启动时的初始化工作,不止有一个initC,初始化后将丢弃initC,多个initC则必须是前一个initC完成后才执行下一个

Main C:初始化后运行的主程序

START:启动时执行一个指令

STOP:停止时执行一个指令

readiness:pod启动后假设pod中有个容器运行了一个程序,程序启动即running,而running的pod将可以让外部访问,但是程序                     有可能正在启动而无法提供给用户想要的返回结果,而readiness就是判断服务是否真正启动完成

Liveness:pod中容器运行期间如果容器中进程出现假死,僵尸进程z,则Liveness可以通过预设检测Main C 判断该pod是否正常

 

initC

pod能够具有多个容器,应用运行在容器中,但是他也可能有一个或多个先于应用容器启动的 init 容器

init 容器与普通的容器非常像,除了如下亮点:

  • init 容器总是运行到成功完成为止
  • 每个 init 容器都必须在下一个init容器启动之前成功完成

如果 pod 的 init 容器失败,kubernetes 会不断的重启该pod,直到 init 容器成功为止,除非 pod 对应的 restartPolicy 为 Never。

举例说明:

有下面一个文件 init-pod.yaml

首先运行一个容器 myapp-container,运行一条命令,等待6分钟

然后initContainers运行init,执行一条命令,解析域名myservice,每两秒循环一次,直到解析成功才退出

前一个 init-myservice init执行完成后执行 init-mydb的init

解析域名mydb,同样解析成功退出

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: docker.harbor.com/library/busybox:v1
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: docker.harbor.com/library/busybox:v1
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: docker.harbor.com/library/busybox:v1
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

运行:

kubectl create -f init-pod.yaml

此时因为没有创建 myservice 和 mydb 这两个 service,所以会出现下面的状态

[root@m1 ymal]# kubectl get pod

NAME        READY   STATUS     RESTARTS   AGE

myapp-pod   0/1     Init:0/2   0          6s

查看故障原因

可以看到在 init-myservice 处 ready 为False

[root@m1 ymal]# kubectl describe pod myapp-pod
Name:         myapp-pod
Namespace:    default
Priority:     0
Node:         m3-n2/172.26.220.94
Start Time:   Wed, 01 Jul 2020 18:03:46 +0800
Labels:       app=myapp
Annotations:  <none>
Status:       Pending
IP:           10.244.2.2
Init Containers:
  init-myservice:
    Container ID:  docker://b2d3ffc1b3fc6309c2ee1ca2f268eb03638d97f8b18dfe26c787ba1045481e5f
    Image:         docker.harbor.com/library/busybox:v1
    Image ID:      docker-pullable://docker.harbor.com/library/busybox@sha256:2131f09e4044327fd101ca1fd4043e6f3ad921ae7ee901e9142e6e36b354a907
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      until nslookup myservice; do echo waiting for myservice; sleep 2; done;
    State:          Running
      Started:      Wed, 01 Jul 2020 18:03:47 +0800
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-wprng (ro)
  init-mydb:
    Container ID:  
    Image:         docker.harbor.com/library/busybox:v1
    Image ID:      
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      until nslookup mydb; do echo waiting for mydb; sleep 2; done;
    State:          Waiting
      Reason:       PodInitializing
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-wprng (ro)

查看故障故障点

可以看到是因为域名解析失败了

[root@m1 ymal]# kubectl log myapp-pod -c init-myservice


log is DEPRECATED and will be removed in a future version. Use logs instead.
Server:		10.96.0.10
Address:	10.96.0.10:53

** server can't find myservice.default.svc.cluster.local: NXDOMAIN

*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer

好的我们创建 myservice.yaml 并启动

kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80  # 容器内部端口
      targetPort: 9376  # 映射到外部的端口



运行
# kubectl create -f myservice.yaml

稍微等待一会再次查看 pod 会发现变成了下面的状态, Init 变成了 1/2,表示第一个init已经运行成功了

[root@m1 ymal]# kubectl get pod

NAME        READY   STATUS     RESTARTS   AGE

myapp-pod   0/1     Init:1/2   0          10m

我们再继续创建下一个 service, mydb.yaml

kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377


运行
# kubectl create -f mydb.yaml

等待一会再次查看 pod

成功运行

[root@m1 ymal]# kubectl get pod

NAME        READY   STATUS    RESTARTS   AGE

myapp-pod   1/1     Running   0          10m

init C 特殊说明

  1. pod启动过程中,第一个启动的不是init,而是pause
  2. 如果init运行失败退出,将导致容器启动失败,它会根据pod的 restartPolicy 指定的策略进行重试。如果pod的 restartPolicy设置为Always,Init 容器失败时会使用 RestartPolicy 策略。
  3. 在所有init容器没有成功之前,pod不会变成Ready状态,正在初始化的pod处于Pending状态
  4. 如果pod重启,所有init容器必须重新执行
  5. 更改init容器的image字段,等价于重启该pod
  6. Init 容器具有应用容器的所有字段,除了 readinessProbe ,因为 init 容器无法定义不同于完成(completion)的就绪(readiness)之外的其它状态。这回在验证过程中强制执行
  7. 在pod中的每个app和init容器名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误

 

探针

探针概念:

探针是由kubelet 对容器执行的定期诊断,要执行诊断,kubelet调用由容器实现的Handler。

有三种类型的处理程序:

  • ExecAction:在容器内执行指定的命令,退出码为 0 表示诊断成功
  • TCPSocketAction:对指定端口上的容器IP地址进行TCP检查,端口通则表示诊断成功
  • HTTPGetAction:对指定容器的ip和端口执行HTTP Get请求,状态吗返回结果大于等于200 小于400,表示诊断成功

每次探测都将获得一下三种结果之一:

  • 成功:容器通过诊断
  • 失败:容器未通过诊断
  • 未知:诊断失败,因此不会采取任何行动

探测方式:

readinessProbe:指示容器是否做好服务请求,如果就绪探测失败,端点控制器将从Pod匹配的所有Service的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success。。简单来说就是如果配置此探针但是诊断失败,Main C网络不会对外开放访问。

livenessProbe:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其 重启策略 的影响。如果容器不提供存活探针,则默认状态为Success。

示例:

探针检测-就绪检测

执行 get 检测,因为根本就没有index1.html这个文件,所以这个剧本执行一定失败

initialDelaySeconds: 1  表示启动后一秒执行检测
periodSeconds: 3  重试间隔3秒

[root@m1 yaml]# cat readiness-httpget-pod.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-pod
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: docker.harbor.com/library/nginx:v1
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3


[root@m1 yaml]# kubectl create -f readiness-httpget-pod.yaml

启动后查看pod状态

会发现状态为Running,但是READY状态显示为成功

[root@m1 yaml]# kubectl get pod

NAME                    READY   STATUS    RESTARTS   AGE

readiness-httpget-pod   0/1     Running   0          5s

查看pod详细信息

[root@m1 yaml]# kubectl describe pod readiness-httpget-pod

会发现最后显示为:

Events:

  Type     Reason     Age                     From               Message

  ----     ------     ----                    ----               -------

  Normal   Scheduled  3m33s                   default-scheduler  Successfully assigned default/readiness-httpget-pod to m3-n2

  Normal   Pulling    3m33s                   kubelet, m3-n2     Pulling image "docker.harbor.com/library/nginx:v1"

  Normal   Pulled     3m30s                   kubelet, m3-n2     Successfully pulled image "docker.harbor.com/library/nginx:v1"

  Normal   Created    3m30s                   kubelet, m3-n2     Created container readiness-httpget-container

  Normal   Started    3m29s                   kubelet, m3-n2     Started container readiness-httpget-container

  Warning  Unhealthy  2m27s (x21 over 3m27s)  kubelet, m3-n2     Readiness probe failed: HTTP probe failed with statuscode: 404

状态码为 404

我们进入容器创建一个 index1.html

[root@m1 yaml]# kubectl exec readiness-httpget-pod -it -- /bin/sh

# cd /usr/share/nginx/html

# echo '123' >> index1.html

# exit

再次查看pod,发现已经就绪

[root@m1 yaml]# kubectl get pod

NAME                    READY   STATUS    RESTARTS   AGE

readiness-httpget-pod   1/1     Running   0          6m5s

 

探针检测-存活检测-ExecAction命令探测

检测意思就是,启动后会创建一个文件 /tmp/live ,60秒后删除这个文件

然后存活检测是查看这个文件是否存在,存在即存活,然而60秒后因为删除了这个文件,所以会检测失败

[root@m1 yaml]# cat live-exec.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: docker.harbor.com/library/busybox:v1
    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
      periodSeconds: 3



[root@m1 yaml]# kubectl create -f live-exec.yaml

启动后持续观察这个pod状态

会发现每隔一段时间就会重启一次,因为检测失败就会触发重启策略,重启后文件又重新创建,检测也就能成功,如此循环。

[root@m1 yaml]# kubectl get pod -w

NAME                    READY   STATUS    RESTARTS   AGE

liveness-exec-pod       1/1     Running   5          8m14s

liveness-exec-pod       1/1     Running   6          9m54s

 

探针检测-存活检测-HTTPGetAction

检测访问index.html

timeoutSeconds: 10  超时时间10秒

[root@m1 yaml]# cat liveness-httpget-pod.yaml 


apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: docker.harbor.com/library/nginx:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10



[root@m1 yaml]# kubectl create -f liveness-httpget-pod.yaml

删除 index.html文件

[root@m1 yaml]# kubectl exec liveness-httpget-pod -it -- /bin/sh

# cd /usr/share/nginx/html

# ls

50x.html  index.html

# rm -rf index.html

# ls

50x.html

# exit

查看pod状态,发生重启,重启后容器会自动建立index.html所以会成功

[root@m1 yaml]# kubectl get pod -w

NAME                    READY   STATUS    RESTARTS   AGE

liveness-httpget-pod    1/1     Running   0          4m44s

liveness-httpget-pod    1/1     Running   1          4m46s

 

探针检测-存活检测-TCPSocketAction

初始化后五秒开始检测 80 端口,超时时间 1 秒,检测失败重启三秒

# cat livenessProbe-tcp.yaml

apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: docker.huarbor.com/library/nginx:v1
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 80
      periodSeconds: 3


# kubectl create -f livenessProbe-tcp.yaml

以上的检测方式可以合并到一个文件中进行多重条件检测。

 

start、stop

启动、退出动作

定义一个pod启动时想要做什么,和退出时要做什么

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ['/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/usr/sbin/nginx", "-s", "quit"]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值