K8S实战笔记--6(标签 + 字段选择器 + 容器镜像 + Hook)

K8S实战笔记–4中,我们对名称空间及其操作有了基础了解。本篇将对K8S的另一个重要概念–Label(标签)做介绍。

1. Label

标签是用来标识K8S对象的一组附加在其上的键值对,通过标签我们可以方便地筛选或排除一组对象。借鉴资料中的话来讲,集群中的应用部署或是批处理的程序部署通常都是多维度的,为了实现对这些对象的管理,往往需要对某一特定维度的对象进行操作,而标签可以通过用户的意愿组织集群中的对象之间的结构,而不需要对集群进行修改。

在同一个对象之下标签的Key值必须唯一的。名称方面,标签名不得多于63个字符且必须由字母或数字开头或结尾,可以包含字母、数字、-_.;标签前缀是可选的,必须以DNS子域名的方式指定,例如:kubernetes.io,后用/将其与标签名分隔。通常情况下,若不使用标签前缀,那么该标签的Key将被视为专属于用户的,在K8S的系统组件向对象添加标签时,必须指定前缀。在标签值方面,若标签值不为空,则其长度不得多于63个字符且必须由字母或数字开头或结尾,可以包含字母、数字、-_.

标签选择器可以用来选择一组对象(标签并不能唯一标识一个对象),APIServer支持基于等式与基于集合的标签选择方式:

  1. 基于等式的标签选择方式:在这种选择方式下可以使用===!=三种操作符来进行选择,前两个的含义是一样的,都代表相等,第三种代表不等。选择条件可以通过,叠加,例如date=day1,name!=build代表选择date值为day1且name值不为build的对象。
  2. 基于集合的标签选择方式:这种选择器可以同时选择一组对象。支持的操作符有:innotinexists。具体的使用方法为:
    • 选择date包含有值为day1、day2、day3的标签:date in (day1, day2, day3)
    • 选择name值不为build、pipline的标签:name notin (build, pipline)
    • 选择所有包含test的标签:test
    • 选择所有不包含test的标签:!test
      这种标签选择器也支持使用,分隔以同时叠加选择,相同意义上的选择条件在这两种选择方式之间是等价的。

在我们查看集群内的对象时,我们可以通过参数-l来约束选择条件。例如:

kubectl get pods -l `date in (day1, day2, day3)`

基于等式的选择方式不需要加单引号。在K8S中,JobDeploymentReplicaSetDaemonSet同时支持基于等式与基于集合的选择方式。与Label相对,还有一种annotation(注解),注解不能用来选择对象,通常,注解包含的是如下一些信息:

  • build信息、release信息、Docker镜像信息等,例如时间戳、release id号、PR号、镜像hash值、docker registry地址等。
  • 日志库、监控库、分析库等资源库的地址信息。
  • 程序调试工具信息,例如工具、版本号等。
  • 团队等联系信息,例如电话号码、负责人名称、网址等。

2. 字段选择器

field selector是可以根据一个或多个字段来选择一组对象的选择器,使用时,只需要在查询时使用参数--field-selector来对对象中的字段进行选取即可。支持的操作符与基于等式的标签选择方式一样,也可以使用,进行多个字段的叠加。但是,不同类型的对象,所支持选择的字段不一样,除了所有对象都支持的metadata.namemetadata.namespace,在命令行中使用了不支持的字段,会报错。字段选择器也支持跨多种资源类型使用。

3. 容器镜像

我们曾在DevOps实战笔记–23.2推送本地镜像至Harbor提到,在Docker中使用Harbor时,需要按照:Harbor的地址/Harbor中建立的项目名/镜像名称:版本号对容器镜像命名来完成操作。在Kubernetes使用镜像时,我们也应当按照与Docker命令一样的语法来执行。若我们使用的是docker.hub.com仓库中的镜像,我们则可以省略仓库地址或仓库端口,例如,直接使用nginx:last来完成镜像的拉取。在Kubernetes中,默认的镜像拉取策略是IfNotPresent,它代表着若本地存在目标容器的镜像,则不从远端仓库拉取镜像。若我们希望容器每次启动时,都默认从仓库拉取镜像,那么可以采取以下几种方式:

  1. 将容器镜像拉取策略imagePullPolicy设置为Always
  2. 省略imagePullPolicy字段,并使用tag为latest的镜像;
  3. 直接将imagePullPolicy字段与tag省去。

需要注意的是,在imagePullPolicy未填写且tag为一个确定值(不包括latest)此时拉取策略同IfNotPresent;若拉取策略为Never,则集群假定本地存在镜像,不会尝试从远端拉取镜像。

4. 容器的钩子函数

K8S实战笔记–34.容器生命周期我们了解到,在init容器启动成功后,Pod会进入主容器的启动。在主容器的启动和退出时,分别会执行启动和退出命令。这两条命令分别调用两个Hook(也就是钩子函数)PostStartPreStopPostStart在容器创建后将立刻执行,PreStop在容器被terminate之前执行,K8S将在此函数执行完成后才删除容器。在K8S中,为了使用Hook,需要注册Hook Handler,通常有入下两种形式的handler:

  1. Exec:在容器的名称空间或是在cgroup(Control Group的缩写,由Linux内核提供,用于限制、记录和隔离进程组使用的物理资源)中执行一个指定的命令;
  2. HTTP:向容器的指定端口发送一个HTTP请求。

K8S通过调用Hook,使得容器可以得知所在运行环境对其进行管理的生命周期事件,并可以相应这些事件,以执行对应的代码。在上述Hook运行时,若某一Hook运行失败,K8S就会杀死这个容器。在容器运行的过程中,Hook会被至少触发一次,当PostStartPreStop执行时,Hook也可能被触发了多次,所以Hook Handler在实现时需要保证即使多次触发,也不会出现错误,同时,用户也应当使他们的Hook Handler越轻量级越好。Hook handler的日志并没有在 Pod 的 events 中发布。如果 handler 因为某些原因失败了,kubernetes 将广播一个事件 PostStart hook 发送 FailedPreStopHook 事件。可以执行命令kubectl describe pod以查看这些事件。

那么如何为容器添加Handler呢?我们在编写Pod的YAML文件时,可以在容器的详细描述中添加lifecycle字段来定义我们需要的处理程序。例如,我们为只运行单一容器的Pod添加Handler:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
spec:
  containers:
    name: nginx-container
    image: nginx:latest
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Executing command from postStart handler > /usr/local/message"]

我们使用kubectl apply应用此YAML,待容器启动后,我们使用kubectl exec获得容器内终端,可以在/usr/local/message中查看到输出内容:

Executing command form postStart handler

one-container-per-pod(一个Pod运行一个容器)是Pod最为常见的使用方式。Pod可以看作集群节点中运行的进程,进程的结束方式有两种:gracefull terminate(优雅地终止)或kill。在用户发起删除Pod的指令后,集群需要让用户知道Pod何时被删除并且确保删除Pod的指令能够被正常完成,执行如下操作:

  1. 记录强制终止前的等待时常;
  2. 向Pod中所有容器的主进程发送TERM信号;
  3. 等待超时后向超时容器主进程发送KILL信号;
  4. 删除APIServer中该Pod的记录。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值