《Kubernetes设计与实现》
  • Introduction
  • 内容简介
  • 前言
  • [第二章:Kubernetes基础]
    • 2.3 Kubernetes API
  • [第三章:工作负载管理]
    • [3.1 Pod]
      • 3.1.1 Pod概述
      • 3.1.1 Pod初体验
    • [3.2 ReplicationController]
      • 3.2.1 ReplicationController概述
      • 3.2.2 ReplicationController初体验
    • [3.3 ReplicaSet]
      • 3.3.1 ReplicaSet概述
      • 3.3.2 ReplicaSet初体验
    • [3.4 Deployment]
      • 3.4.1 Deployment概述
      • 3.4.2 Deployment初体验
    • [3.5 DaemonSet]
      • 3.5.1 DaemonSet概述
      • 3.5.2 DaemonSet初体验
  • [第四章:服务]
    • [4.1 Service]
      • 4.1.1 Service概述
      • 4.1.1 Service上手体验
  • [第六章:配置管理]
    • [6.1 Secret--机密信息管理]
      • 6.1.1 Secret概述
  • [第七章:集群认证]
    • [7.1 证书]
      • 7.1.1 证书基础
      • 7.1.2 证书签发流程
  • [第九章:准入控制器]
    • [9.1 准入控制器概述]
      • 9.1.1 概述
      • [9.1.2 内置默认启动的插件]
        • 9.1.2.1 NamespaceLifecycle
        • 9.1.2.15 MutatingAdmissionWebhook
  • [第十章:ResourceQuota]
    • 10.1 ResourceQuota概述
  • [第十六章:API设计约定]
    • 16.1 字段可选性设计约定
    • 16.2 condition设计约定
    • 16.3 event设计约定
  • [第十九章:Kubernetes生态]
    • [19.1 Kind]
      • [19.1.1 Kind概述]
      • 19.1.2 映射端口到主机
      • 19.1.3 配置端口转发
由 GitBook 提供支持
在本页
  • 导读
  • optional标记的作用
  • 字段可选性约定
  • 关于omitempty标记
  • 如何区别空值和零值

这有帮助吗?

  1. [第十六章:API设计约定]

16.1 字段可选性设计约定

导读

在阅读 Kubernetes API 或 其他项目的 API时,细心的读者会发现这些 API 中有些字段包含了 // +optional 标记(下面简称optional标记),比如 Deployment API中的 Replicas 字段就包含这个标记:

// DeploymentSpec is the specification of the desired behavior of the Deployment.
type DeploymentSpec struct {
    // Number of desired pods. This is a pointer to distinguish between explicit
    // zero and not specified. Defaults to 1.
    // +optional
    Replicas *int32 `json:"replicas,omitempty"`
    ...
    // Template describes the pods that will be created.
    Template v1.PodTemplateSpec `json:"template"`
    ...
}

作为对比,Deployment API中的 Template 字段就没有optional标记,你知道他们的区别吗?

读者可能会说,这还不简单,包含optional标记的字段是可选的,反之就是必选的。事实确实如此,不过,对于API设计者还需要思考下面的问题:

  • optional标记除了提高可读性以外,还有什么作用?

  • 在设计API时,字段是否应该包含omitempty 标签?

  • 在设计API时,字段是否应该定义为指针类型?

笔者最初没有深入地了解optional标记,直到自己设计API时走了一些弯路才意识到这里面大有学问,更准确地说是前人经验的总结。本文站在API设计者角度来介绍应该如何处理字段的可选性。

本节内容由Kubernetes社区相关讨论、案例中总结而来,需要说明的是,在Kubernetes项目早期,关于API字段的可选性设计并没有统一的原则,这也导致了目前仍有部分API并不是十分规范。

optional标记的作用

optional标记本身是一个特殊格式的注释,其特殊性体现在两方面:

  • 该标记占用单行注释

  • 注释以空格开始,然后附加以“+”为前缀的标记(类似Golang语言中的build 标签)。

该标记除了提高代码可读性以外,主要用于生成OpenAPI文档以及相应的校验规则。比如controller-gen 工具就会根据这个标记生成CRD的校验规则。

optional标记仅用于标记字段的可选性,除此之外,API设计者还需要了解一些字段设计的约定,或者说是经验之谈。

字段可选性约定

可选字段通常具备以下特征:

  • 注释中包含optional标记;

  • 字段类型通常为指针、map、slice;

  • 字段的Tag中通常包含omitempty标记;

必选字段通常具备以下特征:

  • 注释中没有optional标记;

  • 字段类型不是指针;

  • 字段的Tag中没有omitempty标记;

关于omitempty标记

在optional标记出现以前,Kubernetes的API中广泛依赖字段的omitempty标记来判断字段的可选性,拥有omitempty标记的被自动识别的可选字段,反之则为必选字段。现在慢慢过渡到使用optional标记来识别可选性。

如何区别空值和零值

对于下面的可选字段而言,如果用户设置字段为0(空值),由于该值等同于类型的零值,开发者无法区别出用户到底有没有设置。

    // +optional
    Foo int32 `json:"foo,omitempty"`

所以,对于可选字段,建议使用指针,如果指针为nil表示用户没有设置,反之则代表用户显式地设置了字段值。

除此之外,如果可选字段类型为自定义结构体类型,使用指针还可以简化JSON编码。参考下面的例子:

type DummyStruct struct {
    // +optional
    Foo *int `json:"foo,omitempty"`
}

type MyStruct struct {
    // +optional
    Dummy DummyStruct `json:"dummy,omitempty"`
}

尽管Dummy字段标签中包含omitempty标记,在将其JSON编码(json.Marshal)时,仍然为出现一个空的JSON键,如下所示

{"dummy":{}}

如果API中包含大量这样的字段,则在JSON编码时会比较丑陋,而将其定义为指针类型可消除这个问题。

参考资料:

上一页[第十六章:API设计约定]下一页16.2 condition设计约定

最后更新于4年前

这有帮助吗?

《API Conventions》

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#optional-vs-required