kubernetes对象

kubernetes对象,第1张

kubernetes对象 定义kubernetes对象        

创建 Kubernetes 对象时,必须提供对象的规约,用来描述该对象的期望状态, 以及关于对象的一些基本信息(例如名称)。 当使用 Kubernetes API 创建对象时(或者直接创建,或者基于kubectl), API 请求必须在请求体中包含 JSON 格式的信息。 大多数情况下,需要在 .yaml 文件中为 kubectl 提供这些信息。 kubectl 在发起 API 请求时,将这些信息转换成 JSON 格式。

这里有一个 .yaml 示例文件,展示了 Kubernetes Deployment 的必需字段和对象规约:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

然后使用kubectl命令创建该deployment,假设该文件名为nginx-deployment.yaml

kubectl apply -f nginx-deployment.yaml
必需字段 

在想要创建的 Kubernetes 对象对应的 .yaml 文件中,需要配置如下的字段:

  • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
  • kind - 想要创建的对象的类别
  • metadata - 帮助唯一性标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
  • spec - 你所期望的该对象的状态

不同类别资源的spec字段是不同的,例如,Pod 参考文档详细说明了 API 中 Pod 的 spec 字段, Deployment 的参考文档则详细说明了 Deployment 的 spec 字段。

对象名称和 IDs

集群中的每一个对象都有一个名称 来标识在同类资源中的唯一性。

每个 Kubernetes 对象也有一个UID 来标识在整个集群中的唯一性。

比如,在同一个名字空间 中有一个名为 myapp-1234 的 Pod, 但是可以命名一个 Pod 和一个 Deployment 同为 myapp-1234.

对于用户提供的非唯一性的属性,Kubernetes 提供了 标签(Labels)和 注解(Annotation)机制。

名称

某一时刻,只能有一个给定类型的对象具有给定的名称。但是,如果删除该对象,则可以创建同名的新对象。当对象所代表的是一个物理实体(例如代表一台物理主机的 Node)时, 如果在 Node 对象未被删除并重建的条件下,重新创建了同名的物理主机, 则 Kubernetes 会将新的主机看作是老的主机,这可能会带来某种不一致性。

DNS 子域名

很多资源类型需要可以用作 DNS 子域名的名称。 这一要求意味着名称必须满足如下规则:

  • 不能超过253个字符
  • 只能包含小写字母、数字,以及'-' 和 '.'
  • 须以字母数字开头
  • 须以字母数字结尾
路径分段名称 

某些资源类型要求名称能被安全地用作路径中的片段。 其名称不能是 .、..,也不可以包含 / 或 % 这些字符。

UIDs

Kubernetes 系统生成的字符串,唯一标识对象。

在 Kubernetes 集群的整个生命周期中创建的每个对象都有一个不同的 uid,它旨在区分类似实体的历史事件。

Kubernetes UIDs 是全局唯一标识符(也叫 UUIDs)。

命名空间

名字空间为名称提供了一个范围。资源的名称需要在名字空间内是唯一的,但不能跨名字空间。 名字空间不能相互嵌套,每个 Kubernetes 资源只能在一个名字空间中。

名字空间是在多个用户之间划分集群资源的一种方法(通过资源配额)。

设置名字空间偏好

默认的命名空间为default,在创建资源时,如果不指定命名空间时,会将资源创建在default命名空间,设置默认命名空间后,如果不指定命名空间,将会把资源创在设置的命名空间。

kubectl config set-context --current --namespace=<名字空间名称>
# 验证之
kubectl config view | grep namespace:
名字空间和 DNS

当创建一个服务 时, Kubernetes 会创建一个相应的 DNS 条目。

该条目的形式是 <服务名称>.<名字空间名称>.svc.cluster.local,这意味着如果容器只使用 <服务名称>,它将被解析到本地名字空间的服务,也就是默认命名空间。

并非所有资源都在命名空间

可通过以下命令查看

# 位于名字空间中的资源
kubectl api-resources --namespaced=true

# 不在名字空间中的资源
kubectl api-resources --namespaced=false
自动打标签

Kubernetes 控制面会为所有名字空间设置一个不可变更的 标签 kubernetes.io/metadata.name,只要 NamespaceDefaultLabelName 这一 特性门控 被启用,注意,在kunernetes 1.21版本中,该特性属于beta版本

标签和选择算符

标签(Labels) 是附加到 Kubernetes 对象(比如 Pods)上的键值对。只要符合命名规范,标签可以是任意定义,不直接对核心系统有语义含义,只对用户有意义,一般和标签选择器配套使用

命名规范

有效的标签键有两个段:可选的前缀和名称,用斜杠(/)分隔。 名称段是必需的,必须小于等于 63 个字符,以字母数字字符([a-z0-9A-Z])开头和结尾, 带有破折号(-),下划线(_),点( .)和之间的字母数字。 前缀是可选的。如果指定,前缀必须是 DNS 子域:由点(.)分隔的一系列 DNS 标签,总共不超过 253 个字符, 后跟斜杠(/)。

如果省略前缀,则假定标签键对用户是私有的。 向最终用户对象添加标签的自动系统组件(例如 kube-scheduler、kube-controller-manager、 kube-apiserver、kubectl 或其他第三方自动化工具)必须指定前缀。

kubernetes.io/ 和 k8s.io/ 前缀是为 Kubernetes 核心组件保留的。

示例

nodeSelector字段表示该pod必须运行在有accelerator: nvidia-tesla-p100标签的节点上

apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "k8s.gcr.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

比较新的资源,例如 Job、 Deployment、 Replica Set 和 DaemonSet , 也支持 基于集合的 需求。表示会匹配key为tier,value为cache或者cache2并且key为enviroment,value不等于dev的资源

selector:
  matchLabels:
    component: redis
  matchexpressions:
    - {key: tier, operator: In, values: [cache,cache2]}
    - {key: environment, operator: NotIn, values: [dev]}
注解

注解,也就是annotations,和标签一样都是键值对,但标签是用来选择对象和查找满足某些条件的对象集合,而注解不用于标识和选择对象。 注解中的元数据,可以很小,也可以很大,可以是结构化的,也可以是非结构化的,能够包含标签不允许的字符。

一般用于存储资源的附加信息,或标识一些特殊的含义

Finalizers

finalizers在matedata字段里,如果某个资源的metadata.finalizers不为空,则表示告诉控制器,尽管用户已经对该资源进行了delete *** 作,但该资源还不能被删除,而是让它将入 Terminating 状态,等到该字段为空时才能被删除。

finalizers工作原理,当试图删除一个资源时,管理该资源的控制器会注意到 finalizers 字段中的值, 并进行以下 *** 作:

  • 修改对象,将你开始执行删除的时间添加到 metadata.deletionTimestamp 字段。
  • 将该对象标记为只读,直到其 metadata.finalizers 字段为空。

这里用kubebuilder示例里使用finalizers的一段代码来描述

func (r *CronJobReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := r.Log.WithValues("cronjob", req.NamespacedName)

    var cronJob *batchv1.CronJob
    if err := r.Get(ctx, req.NamespacedName, cronJob); err != nil {
        log.Error(err, "unable to fetch CronJob")
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // finalizer名字,可以自定义
    myFinalizerName := "batch.tutorial.kubebuilder.io/finalizer"

    // 在删除资源时,k8s会将开始执行删除的时间添加到 metadata.deletionTimestamp 字段,这样会 
    // 触发一个 Update 动作, 我们的控制器就会监听到这个更新动作。

    // 说明如果该字段为0,那么当前 *** 作就不是删除 *** 作,我们把自定义的finalizer添加到 
    // metadata.finalizers字段中
    if cronJob.Objectmeta.DeletionTimestamp.IsZero() {
        if !containsString(cronJob.GetFinalizers(), myFinalizerName) {
            controllerutil.AddFinalizer(cronJob, myFinalizerName)
            if err := r.Update(ctx, cronJob); err != nil {
                return ctrl.Result{}, err
            }
        }
    } else {
        // 否则就是一个删除 *** 作,先判断该对象有没有我们自己定义的finalizer,如果有,先做一些收尾 
        // 工作,也就是deleteExternalResources
        if containsString(cronJob.GetFinalizers(), myFinalizerName) {
            if err := r.deleteExternalResources(cronJob); err != nil {            
                return ctrl.Result{}, err
            }
            // 然后将自定义的metadata.finalizers字段中我们自定义的finalizer删掉,删掉之后 
            // finalizers如果为空,k8s就不会阻止垃圾收集删除该资源了
            controllerutil.RemoveFinalizer(cronJob, myFinalizerName)
            if err := r.Update(ctx, cronJob); err != nil {
                return ctrl.Result{}, err
            }
        }

        return ctrl.Result{}, nil
    }

    // Your reconcile logic

    return ctrl.Result{}, nil
}

func (r *Reconciler) deleteExternalResources(cronJob *batch.CronJob) error {
    //
    // delete any external resources associated with the cronJob
    //
    // Ensure that delete implementation is idempotent and safe to invoke
    // multiple times for same object.
}

// Helper functions to check and remove string from a slice of strings.
func containsString(slice []string, s string) bool {
    for _, item := range slice {
        if item == s {
            return true
        }
    }
    return false
}

func removeString(slice []string, s string) (result []string) {
    for _, item := range slice {
        if item == s {
            continue
        }
        result = append(result, item)
    }
    return
}
属主引用

在某些情况下,Finalizers 会阻止依赖对象的删除, 这可能导致目标属主对象,保持在只读状态的时间比预期的长,且没有被完全删除。 在这些情况下,你应该检查目标属主和附属对象上的 Finalizers 和属主引用,来排查原因。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5696651.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存