yaml 编写

可以通过 kubectl explain 查看资源清单包含了那些字段

kubectl explain Pod

查看k8s ingress收到的请求_java

可以通过提供的More info 网页查看具体的配置样例

apiVersion 定义了对象版本

Kind 定义了资源类型

matadata 定义了元属性信息 <资源名称>

spec 定义了Pod的规格,具体容器信息 

status 定义了状态,不可修改,不需要定义。

查看matadata对象该如何定义

kubectl explain Pod.metadata

查看对象该如何定义直接在后面.+对象名即可。

字段类型为 <string> 字符串

apiVersion: v1

字段类型为 <Object> 对象

metadata:

字段类型为 <map[string]string> map集合

key: value

字段类型为 <[]Object> 对象列表

- name: tomcat-pod-java

 带有required 为必填 

查看k8s ingress收到的请求_查看k8s ingress收到的请求_02

常见属性:

metadate:

  • labels 创建资源具有的标签
  • namespace 资源所属命名空间(默认default)

 spec: 

  • activeDeadlineSeconds  pod可运行的最长时间
  • affinity pod亲和性
  • containers 定义容器必填字段,至少要有一个容器
  • dnsConfig
  • dnsPolicy 

 pod.spec.containers 

  • args 
  • command
  • env
  • envFrom
  • image 用来指定容器需要的镜像
  • imagePullPolicy 镜像拉取策略,Always 一直重新拉取、Never 从不拉取镜像、IfNotPresent优先使用本地镜像,没有在拉取镜像。
  • name
  • ports 端口

pod.spec.containers.ports

  • containerPort 必须字段,端口号
  • hostIP 将容器中的服务暴露到宿主机的端口上时,可以指定绑定的宿主机 IP
  • hostPort 容器中的服务在宿主机上映射的端口
  • name 端口名称

样例:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  labels:
    app: myapp
spec:
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat

命名空间

k8s中物理集群中的虚拟集群。可以给不同用户、租户、环境或项目创建对应的命名空间。

命名空间的名称仅能是字母、数字、下划线、连接线等字符组成。

命名空间通过资源配额可以限制资源。

删除命名空间,级联下的资源对象也会被删除。

# 创建命名空间
kubectl create namespace test
# 切换当前命名空间。切换命名空间后,kubectl get pods 如果不指定-n,查看的就是test命名空间的资源了。
kubectl  config set-context --current --namespace=test
# 查看哪些资源属于命名空间级别的
kubectl api-resources --namespaced=true

资源限额

命名空间可以通过ResourceQuota限制空间资源

kubectl explain resourcequotas

apiVersion: v1
kind: ResourceQuota
metadata:
  name: test-rq
  # 指定名称空间
  namespace: test
spec:
  hard:
# 所有容器的内存请求总额不得超过
    requests.cpu: "1"
# 所有容器的CPU请求总额不得超过
    requests.memory: 1Gi
# 所有容器的内存限额总额不得超过
    limits.cpu: "2"
# 所有容器的CPU限额总额不得超过
    limits.memory: 2Gi

名称空间下的每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。

查看限额

kubectl get quota -n test

标签

标签是一对 key/value, 被关联到对象。标签可以用来划分特定的对象,一个对象可以有多个标签。但是key值必须是唯一的。通过标签可以方便的对资源进行分组管理。k8s中大部分资源都可以打标签。

# 查看pods 标签,其他资源也可以用--show-labels查看标签
kubectl get pods --show-labels
# 对已经存在的pod打标签
kubectl label pod pod名称  key=value

# 列出默认命名空间下所有标签 key=app,不显示标签
kubectl get pods -l app
# 列出默认命名空间下所有标签 key是app,value是myapp 不显示标签
kubectl get pods -l app=myapp
# 列出默认名称空间下标签key是app的所有pod,并打印对应的标签值
kubectl get pods -L app
# 查看所有名称空间下的所有pod的标签
kubectl get pods --all-namespace --show-labels

查看k8s ingress收到的请求_运维_03

 

查看k8s ingress收到的请求_java_04

node节点选择器

我们创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或调度到一些具有相同特点的node节点可以使用pod中的nodeName或nodeSelector字段指定调度到的节点

nodeName

kubectl explain pod.spec

通过nodeName 可以直接指定调度到那个节点

查看k8s ingress收到的请求_linux_05

样例:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  labels:
    app: myapp
spec:
  nodeName: k8snode02
  containers:
  - name: tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat

 nodeSelector

通过node节点标签选择器,进行调度

查看k8s ingress收到的请求_Pod_06

 样例:

# 节点打标签
kubectl label node k8snode01 dome=test
# dome yaml文件
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  labels:
    app: myapp
spec:
  nodeSelector:
    dome: test
  containers:
  - name: tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat

 

查看k8s ingress收到的请求_Pod_07

污点和容忍度 

亲和性(affinity)

kubectl explain pod.spec.affinity

查看k8s ingress收到的请求_java_08

node节点亲和性(nodeAffinity)

Node节点亲和性针对的是pod和node的关系,Pod调度到node节点的时候匹配的条件

preferredDuringSchedulingIgnoredDuringExecution (软亲和性)

requiredDuringSchedulingIgnoredDuringExecution (硬亲和性,必须满足)

查看文档可以获得填写规则

kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions

查看k8s ingress收到的请求_linux_09

填写筛选条件 values 可以设置多个 满足其中一个即可。

查看k8s ingress收到的请求_linux_10

 样例:根据节点标签dome=test完成调度

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  labels:
    app: myapp
spec:
  containers:
  - name: tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: dome
            operator: In
            values:
            - test
            - dev

Pod节点亲和性

kubectl explain pod.spec.affinity

pod 自身亲和性调度有两种表现形式

podAffinity (pod亲和性)

podAntiAffinity (pod反亲和性)

查看k8s ingress收到的请求_linux_11

 使用pod亲和性必须添加位置拓扑键 topologyKey,完成调度的参照。

样例:

节点亲和性

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  labels:
    dome: aff
spec:
  containers:
  - name: tomcat-pod
    ports:
    - containerPort: 8080
    image: tomcat
  affinity:
    # 节点亲和性
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      # 列表字段有同级属性时,子属性多缩进两个空格
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp
        # 位置拓扑键参照主机名调度
        topologyKey: kubernetes.io/hostname

节点反亲和性:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod2
  labels:
    dome2: noaff
spec:
  containers:
  - name: tomcat-pod2
    ports:
    - containerPort: 8080
    image: tomcat
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp
        topologyKey: kubernetes.io/hostname

查看k8s ingress收到的请求_查看k8s ingress收到的请求_12

污点

给节点选择的主动权,我们给节点打个污点,不能容忍的pod就运行不上来。

污点是定义在节点上的键值属性数据。taints是键值对数据。

污点等级

  • NoSchedule (仅影响pod调度,后来的pod不容忍这个污点无法调度到该节点,已存在的pod不受影响)
  • NoExecute(既影响现有pod也影响pod调度,节点中现有pod会被剔除)
  • PreferNoSchedule (最好不也可以是NoSchedule的柔性版本)
# 查看污点 
kubectl describe nodes |grep Taints
# 给节点打污点
kubectl taint nodes 节点名 key=value:NoSchedule
# 删除污点
kubectl taint nodes 节点名 key-

污点容忍

kubectl explain pod.spec.tolerations

查看k8s ingress收到的请求_linux_13

如果 operator 的值是 Exists,则 value 属性可省略
如果 operator 的值是 Equal,则表示其 key 与 value 之间的关系是 equal(等于)
如果不指定 operator 属性,则默认值为 Equal
另外,还有两个特殊值:

空的 key 如果再配合 Exists 就能匹配所有的 key 与 value,也是是能容忍所有 node 的所有 Taints
空的 effect 匹配所有的 effect

样例:

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
  labels:
    app: myapp
spec:
  containers:
  - name: tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: dome
            operator: In
            values:
            - test
  tolerations:
  - key: "taint"
    operator: "Equal"
    value: "node02"
    effect: "NoSchedule"

pod常见状态

查看k8s ingress收到的请求_java_14

 pod的status简述了其生命周期的阶段。

挂起(pending): pod创建时调度条件不满足,多会处于此状态。

运行中(running): pod正常运行。

成功(succeeded): pod成功运行结束,并且不在重启

失败(failed): pod中容器异常终止,或者说容器以非0状态推出

未知(unknown):未知状态,pod所在节点kubelet故障未上报pod信息,

Evicted: 这种状态多见系统内存不足

CrashLoopBackOff: 容器启动又异常退出,重启次数过多也会出现此状态

Error 状态:Pod 启动过程中发生了错误

ready 代表pod的容器状态

问题排查命令

查看pod详情

kubectl describe pod  pod名称 (如果不是默认空间需要指定空间名)

查看pod容器日志

kubectl logs test-host -c test-host

pod 重启策略

pod重启策略(RestartPolicy)应用于pod内的所有容器,pod所在的node上的kubelet会进行判断和重启操作。某个容器异常推出或健康检测失败会。kubelet会根据重启策略进行操作

pod的重启策略包括: Always、OnFailure、Never 默认是Always

Always:当容器失败时,由kubelet自动重启该容器。

OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。

Never:不论容器运行状态如何,kubelet都不会重启该容器

示例:

apiVersion: v1
kind: Pod
metadata:
  name: test2
spec:
  restartPolicy: Never
  containers:
  - name: test2
    image: nginx

生命周期

init容器

pod中可以定义多个容器,部署应用的容器称为主容器。pod创建时可以有一个或多个先于主容器启动的init容器,init容器中的程序执行完了才会运行主容器,由于pod中共享存储,多用于主容器启动前的一些初始化工作

init容器与主容器区别:

1 init容器运行完,主容器才会启动。

2 每个init容器必须运行成功,才可以执行下一个init容器

3 如果init容器运行失败,pod会不断重启,知道运行成功,如果重启策略设置为Never,他不会重启

示例:

apiVersion: v1
kind: Pod
metadata:
  name: init-test
spec:
  initContainers:
  - name: init-con
    image: centos
    command: ["sh", "-c", "echo '123' > /temdir/123"]
    volumeMounts:
    - mountPath: "/temdir"
      name: vol
  containers:
  - name: zhu-con
    image: centos
    command: ["sh", "-c", "cat /temdir/123 && sleep 3600"]
    volumeMounts:
    - mountPath: "/temdir"
      name: vol
  volumes:
  - name: vol
    emptyDir: {}

容器探测

容器钩子

初始化容器启动之后,开始启动主容器,在主容器启动之前有一个post start hook(容器启动后钩子)和pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放两个钩子,这个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的清理,如awk有begin,end,和这个效果类似;

postStart:该钩子在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的hook handler执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。

preStop:该钩子在容器被删除前触发,其所对应的hook handler必须在删除该容器的请求发送给Docker daemon之前完成。在该钩子对应的hook handler完成后不论执行的结果如何,Docker daemon会发送一个SGTERN信号量给Docker daemon来删除该容器,这个钩子不需要传递任何参数。

在k8s中支持两类对pod的检测,第一类叫做livenessprobe(pod存活性探测):

存活探针主要作用是,用指定的方式检测pod中的容器应用是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的 restartPolicy来判断Pod 是否要进行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测一直为成功状态。

第二类是状态检readinessprobe(pod就绪性探测):用于判断容器中应用是否启动完成,当探测成功后才使Pod对外提供网络访问,设置容器Ready状态为true,如果探测失败,则设置容器的Ready状态为false。

postStart:容器创建成功后,运行前的任务,用于资源部署、环境准备等。

preStop:在容器被终止前的任务,用于优雅关闭应用程序、通知其他系统等。

lifecycle

查看k8s ingress收到的请求_Pod_15

查看k8s ingress收到的请求_Pod_16

......
containers:
- image: sample:v2  
     name: war
     lifecycle:
      postStart:
       exec:
         command:
          - “cp”
          - “/sample.war”
          - “/app”
      prestop:
       httpGet:
        host: monitor.com
        path: /waring
        port: 8080
        scheme: HTTP
......

而在容器终止之前,发送HTTP警告请求到监控系统。

优雅的删除资源对象

当用户请求删除含有pod的资源对象时(如RC、deployment等),K8S为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:

1)、默认:K8S通知node执行docker stop命令,docker会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行kill掉进程。

2)、使用pod生命周期(利用PreStop回调函数),它执行在发送终止信号之前。默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户来修改默认值。0表示删除立即执行,并且立即从API中删除pod。在节点上,被设置了立即结束的的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。

spec:
      containers:
      - name: nginx-demo
        image: centos:nginx
        lifecycle:
          preStop:
            exec:
              # nginx -s quit gracefully terminate while SIGTERM triggers a quick exit
              command: ["/usr/local/nginx/sbin/nginx","-s","quit"]
        ports:
          - name: http
            containerPort: 80

pod阶段

当用户创建pod时,这个请求给apiserver,apiserver把创建请求的状态保存在etcd中;接下来apiserver会请求scheduler来完成调度,如果调度成功,会把调度的结果(如调度到哪个节点上了,运行在哪个节点上了,把它更新到etcd的pod资源状态中)保存在etcd中,一旦存到etcd中并且完成更新以后,节点上的kubelet通过apiserver当中的状态变化知道有一些任务被执行了,所以此时此kubelet会拿到用户创建时所提交的清单,这个清单会在当前节点上运行或者启动这个pod,如果创建成功或者失败会有一个当前状态,当前这个状态会发给apiserver,apiserver在存到etcd中;在这个过程中,etcd和apiserver一直在打交道,不停的交互,scheduler也参与其中,负责调度pod到合适的node节点上,这个就是pod的创建过程。

pod探测

三种探测方法:

1、ExecAction:在容器中执行指定的命令,如果执行成功,退出码为 0 则探测成功。

2、TCPSocketAction:通过容器的 IP 地址和端口号执行 TCP 检 查,如果能够建立 TCP 连接,则表明容器健康。

3、HTTPGetAction:通过容器的IP地址、端口号及路径调用 HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器健康

存活性探测livenessProbe

K8S提供livenessProbe来检测容器是否正常运行,许多应用程序经过长时间运行,最终过渡到无法运行的状态。这时候检测到容器异常,kubelet会根据重启策略重启容器。

示例:

Exec:

apiVersion: v1
kind: Pod
metadata:
  name: liveness
spec:
  containers:
  - image: centos
    name: test-liv
    command: ["sh", "-c", "touch /123 && sleep 120 && rm -rf /123 && sleep 600"]
    livenessProbe:
      initialDelaySeconds: 10
      periodSeconds: 5
      exec:
        command: ["sh", "-c", "cat /123"]


# #netstat -an|grep 80
# #echo $? 查看上面命令执行后的状态码



# 相关属性:
# initialDelaySeconds: Pod启动后首次进行检查的等待时间,单位“秒”。
# periodSeconds: 检查的间隔时间,默认为10s,单位“秒”。
# timeoutSeconds: 探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”。
# successThreshold:连续探测几次成功,才认为探测成功,默认为 1,在 Liveness 探针中必须为1,最小值为1。
# failureThreshold: 探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3,最小值为

tcp

apiVersion: v1
kind: Pod
metadata:
  name: test-tcp
spec:
  containers:
  - name: test-tcp
    image: nginx
    # 存活性探测
    livenessProbe:
      # 容器启动多长时间后开始探测,默认是秒
      initialDelaySeconds: 10
      # 探测间隔时间,默认是秒
      periodSeconds: 5
      # 探测超时时间
      timeoutSeconds: 10
      # 探测端口
      tcpSocket:
        port: 80
        # host 默认是本机

#TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds 参数设定的时间后,kubelet将发送第一个 livenessProbe 探针,尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。

查看k8s ingress收到的请求_查看k8s ingress收到的请求_17

http 

apiVersion: v1
kind: Pod
metadata:
  name: test-http
spec:
  containers:
  - name: test-http
    image: nginx
    livenessProbe:
      initialDelaySeconds: 10
      periodSeconds: 5
      httpGet:
        port: 80

# httpGet探测方式有如下可选的控制字段:
# scheme: 用于连接host的协议,默认为HTTP。
# host:要连接的主机名,默认为Pod IP,可以在http request head中设置host头部。
# port:容器上要访问端口号或名称。
# path:http服务器上的访问URI。
# httpHeaders:自定义HTTP请求headers,HTTP允许重复headers。

查看k8s ingress收到的请求_java_18

就绪性探测readinessProbe

没有配置就绪性探测,pod中容器运行后默认成功。

就绪性探测和存活性探测配置方法类似。

区别在于:

存活性探测失败后会由kubelet根据重启策略操作pod.

就绪性探测失败后会从EndPoint中移除。

存活性探测和就绪性探测配合使用案例:

apiVersion: v1
kind: Pod
metadata:
  name: test-live-read
spec:
  containers:
  - name: test-live-read
    image: nginx
    livenessProbe:
      initialDelaySeconds: 10
      periodSeconds: 5
      httpGet:
        port: 80
    readinessProbe:
      initialDelaySeconds: 10
      periodSeconds: 5
      httpGet:
        port: 80

查看k8s ingress收到的请求_运维_19