Skip to content

Curated kubernetes helm charts with well-defined structures

Notifications You must be signed in to change notification settings

caicloud/charts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Table of Contents generated with DocToc

Chart 模版配置规范定义(v1.0.0)

概述

规范主要用于定义 Chart 配置文件 values.yaml 的逻辑结构和类型。
我们将一个 Chart 包含的内容定义为一个应用,一个应用通常包含 Pod Controller,Service,Config,Volume 四块主要内容:

  • Pod Controller:Deployment,StatefulSet,DaemonSet,Job,CronJob
  • Service:Service
  • Config:ConfigMap,Secret
  • Volume:PVC,ConfigMap,Secret,EmptyDir

上述的对应关系并没有包含所有的 Kubernetes 资源,即我们认为其他资源是与应用是弱/无耦合的。
并且其中 ConfigMap,Secret 也不是由 Chart 主动创建的,而是应当在应用创建之前就应该在集群中存在,并由应用引用,产生单向依赖。

基础结构描述

配置文件使用 yaml 格式,并且在实际使用中转换为 json 格式。
标准配置文件结构如下:

# 顶级配置 key ,固定为 _config
_config: 
  # 在配置文件中,所有以 _ 开头的字段用于存储特殊信息。  
  # 模板元数据,表示当前配置所属的 Chart 信息,此处数据用于存储模版最原始的信息
  _metadata:
    name: string          # Chart 创建时的名称,不随 Chart 更新而更新
    version: semvar       # Chart 创建时的版本号,不随 Chart 更新而更新
    description: string   # Chart 创建时的描述,不随 Chart 更新而更新
    template:             # Chart 模板信息,为模板自动升级提供信息
      type: string        # Chart 模板类型
      version: semvar     # Chart 模板版本号
    appVersion: string    # Chart 创建 workload 时的版本号,会添加到 pod 的 label 中,目前多用于灰度发布。
  # 配置控制器组,配置控制器组可以包含多个配置控制器
  # 此处的配置控制器与上面所描述的 Pod Controller 不同,此处的配置控制器具有如下等价关系:
  # 配置控制器 = 1个 Pod Controller 配置 +
  #             1个 调度 配置 +
  #             1个 容器组 配置 +
  #             0个或多个 初始化容器 配置 +
  #             1个或多个 基本容器 配置 +
  #             0个或多个 数据卷 配置 +
  #             0个或多个 服务 配置
  controllers:
  - type: string          # 指定控制器的类型,可以是 Deployment,StatefulSet,DaemonSet,Job,CronJob
    controller:           # 控制器信息,对应特定 type 的控制器信息
      ...
    schedule:             # 调度信息,用于控制容器组的调度
      ...
    pod:                  # 容器组信息,指定当前控制器下的所有容器(包括 initializers 和 containers)共享的设置内容
      ...
    initContainers:       # 初始化容器数组,可用于放置仅用于初始化阶段的容器,比如初始化数据
    - ...
    containers:           # 基本容器数组,用于放置真正执行工作的容器
    - ...
    volumes:              # 数据卷描述信息数组,这部分数据卷可以被多个容器共享访问
    - ...
    services:             # 服务信息数组,当前控制器内的容器需要暴露服务时,在这里添加服务。一个控制器可有多个服务
    - ...
    configs:              # 配置信息数组
    - ...
    secrets:              # 加密配置信息数组
    - ...
chartX:
  # 子模版 chartX 的配置,其结构与上面的 _config 相同
  _config:
    ...

_metadata仅仅用于描述模板的基本信息。

  • name,version,description 用于描述 Chart 的原始信息。用于从配置直接创建 Chart。
  • template 用于描述 Chart 的模板信息。主要用于实现 Chart 的创建和升级。template 发生功能变更后,可依据模板名称和版本号进行升级。

配置控制器定义

字段类型定义:

int:     整数
uint:    自然数
pint:    正整数
float:   实数
string:  字符串
bool:    布尔值,只能是 true 或 false

默认值声明方式:

类型(默认值)
int(-1)
uint(0)
pint(1)
float(3.14)
string("default value")
bool(true)

所有有默认值的字段都是 Optional 的。

类型:controller

所有类型的 controller 共有字段如下:

annotations:                           # 控制器附加信息,仅用于保存控制器额外信息
  - key: string                        #
    value: string                      #

key 必须符合如下要求:

1. `前缀/键`或者`键`,比如 `caicloud.io/apple`和`apple`
2. 前缀是域名形式,必须符合 DNS_SUBDOMAIN,即`(([A-Za-z0-9][-A-Za-z0-9]*)?[A-Za-z0-9]\.)*([A-Za-z0-9][-A-Za-z0-9]*)?[A-Za-z0-9]`
3. 键必须符合 ([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]
controller:Deployment
name: string("")                       # 实例前缀名,控制器名称
replica: uint(1)                       # 实例数量
strategy:                              # 实例滚动更新策略,两个选项不能同时为0
  type: string("RollingUpdate")        # 更新策略,只能为 RollingUpdate(滚动更新) 或者 Recreate(重新创建)
  unavailable: uint(0)                 # 最大不可用数量
  surge: uint(1)                       # 最大超量
ready: uint(0)                         # 实例从 Available 到 Ready 的最短时间

一个实例在运行时等价于一个容器组,可以通过 replica 指定需要的实例数量,即可在集群中同时跑多个实例。
当实例的配置需要更新时,根据更新策略决定如何重启实例。unavailable 表明当前控制器可以先关闭多少个运行中的实例。surge 表示当前控制器可以在 replica 的基础上多创建多少个新的实例。即在滚动更新过程中,实例的数量可能在[max(replica-unavailable,0),replica+surge]区间。

controller:StatefulSet
replica: uint(1)                              # 实例数量
name: string("")                              # 实例前缀名,控制器名称
domain: string("")                            # 实例域名
strategy:                                     # 实例滚动更新策略
  type: string("RollingUpdate")               # 更新策略,只能为 RollingUpdate(滚动更新) 或者 OnDelete(删除时更新)
  rollingUpdate:                              # 滚动更新配置,只有当 RollingUpdate 时才可以此选项
    partition: uint(0)                        # 分段更新序号
podManagementPolicy: string("OrderedReady")   # Pod 管理策略, 只能为 OrderedReady 或 Parallel

指定 name 和 domain 后,可通过 name-序号.domain 的形式访问每个实例。 比如 replica = 2, name = "web", domain = "cluster", 那么同一个分区内可使用 web-0.cluster,web-1.cluster 访问两个实例,同时能够直接使用 cluster 访问任意一个实例(RoundRobin)。
由于前缀名称和域名具有分区范围内的唯一性,因此同一个分区内的应用不能具有相同的 name 和 domain。同时由于 domain 能够被用于访问任意一个实例,因此也不能与同一分区下的 services 冲突。

controller:DaemonSet
name: string("")                       # 实例前缀名,控制器名称
strategy:                              # 实例滚动更新策略,两个选项不能同时为0
  unavailable: pint(1)                 # 最大不可用数量
ready: uint(0)                         # 实例从 Available 到 Ready 的最短时间
controller:Job
name: string("")                       # 实例前缀名,控制器名称
parallelism: pint(1)                   # 最大并行实例数量
backoffLimit: pint(1)                  # 失败重试次数
completions: pint(1)                   # 总共需要完成的实例数量
active: uint(0)                        # 单个实例执行的最长时间,0表示不限制

一个任务可以同时执行多个实例,通过 parallelism 和 completions 可以控制任务是串行执行还是并行执行或是控制并行执行。

  • 串行:completions = n, parallelism = 1 即可让 n 个实例串行执行,只有前一个完成后下一个才会执行
  • 并行:completions = n, parallelism >= n 即可让 n 个实例同时并行执行
  • 控制并行:completions = n, parallelism = k, k < n 即可让 n 个实例同时只有 k 个在执行。其中一个实例完成才能让下一个实例开始执行
controller:CronJob
name: string("")                       # 实例前缀名,控制器名称
rule: string                           # 定时规则,比如 "*/1 * * * *"
deadline: uint(0)                      # 任务启动超时时间
policy: string("Allow")                # 任务并发策略,Allow,Forbid,Replace
suspend: bool(false)                   # 是否暂停当前定时任务
history:                               # 任务执行历史保留选项
  success: uint(0)                     # 执行成功的任务保留数量
  fail: uint(0)                        # 执行失败的任务保留数量
parallelism: pint(1)                   # 最大并行实例数量
backoffLimit: pint(1)                  # 失败重试次数
completions: pint(1)                   # 总共需要完成的实例数量
active: uint(0)                        # 单个实例执行的最长时间,0表示不限制

定时任务规则格式参考:https://en.wikipedia.org/wiki/Cron
定时任务启动超时时间: 举个例子,定时任务设置在每天 8:00:00 执行一次,然后这个字段设置为 10 秒,那么在 8:00:00 - 8:00:10 这个期间内,如果发生了某个特殊的事情,比如 kubernetes 的 定时器 在 7:59:59 - 8:00:11 这个时间段内一直是崩溃的,那么这个定时任务的这一次触发就会被错过,然后就会在定时任务的失败任务数量上加1。
定时任务使用一个 rule 来控制任务的执行。当一个任务未尚未完成,定时器又触发的时候通过 policy 来控制任务的执行方式:

  • Allow:上次触发的任务和本次触发的任务一起执行
  • Forbid:如果上次的任务尚未完成,那么跳过本次任务的执行
  • Replace:取消上次的任务,并开始执行本次的任务

类型:schedule

scheduler: string("")                                  # 调度器名称,可选项为 空字符串,为空表示使用默认调度器
labels:                                                # 控制器及 容器组 标签
  string: string
affinity:                                              # 亲和性设置
  pod:
    type: string("Required")                           # 类型可以为 Required 或 Prefered
    terms:
    - weight: pint                                     # 权重,只有类型为 Prefered 时可以设置该字段,[1-100]
      topologyKey: string("kubernetes.io/hostname")    # 拓补域
      namespaces:                                      # 指定分区,不指定表示仅在当前分区
      - string                                       
      selector:                                        # 选择器,用于设置匹配的标签
        labels:                                        # 直接指定标签值
          string: string
        expressions:                                   # 通过表达式查找标签
        - key: string                                
          operator: string                             # 操作符 In,NotIn,Exists,DoesNotExist
          values:                                      # 标签值列表
          - string                                   
  node:                                              
    type: string("Required")                           # 类型可以为 Required 或 Prefered
    terms:
    - weight: 10                                       # 权重,只有类型为 Prefered 时可以设置该字段,[1-100]
      expressions:                                     # 通过表达式查找标签,表达式为 AND 表达式
      - key: string                                    # 这里的 key 不会自动加上前缀
        operator: string                               # 操作符 In,NotIn,Exists,DoesNotExist,Gt,Lt
        values:
        - string                                     
antiaffinity:                                        
  pod:                                                 # 反亲和性设置与亲和性设置相同
    ...                                              

tolerations:                                            # 节点容忍设置
- key: string("key")                                    # key 值
  operator: string("Equal")                             # 与 taint value 值的关系,可以为 Equal,Exists 默认为 Equal
  value: string("value")                                # value 值
  effect: string("NoSchedule")                          # 与 taint value 不匹配的之后的调度策略,可以为 NoSchedule PreferNoSchedule NoExecute
  tolerationSeconds: uint(60)                           # 在 effect 为 NoExecute 时,如果不能忍受 taint, pod 在被驱逐之前可以继续在这个节点运行的时间。

topologyKey 具有如下值:

kubernetes.io/hostname
failure-domain.beta.kubernetes.io/zone
failure-domain.beta.kubernetes.io/region

拓补域用于定义一个节点集合。目前常用的拓补域的 key 有如上三种。拓补域与 Pod 的 亲和性/反亲和性 相关。
一个拓补域至少有一个节点,所有的 亲和性/反亲和性 的权重计算都是在一个域中进行。
比如有多个域,当一个 Pod 在调度时,调度器会根据 亲和性/反亲和性 的设置,在多个域中寻找一个权重最高的域,然后将 Pod 调度到该域中的一个节点上。
kubernetes.io/hostname与其他两个稍有不同。这个 key 在每个节点上都有不同的值,也就是说,集群里的每个节点都构成了只有一个节点的域。

容忍策略 NoExecute 尚未实现。

类型:pod

restart: string("Always")              # 重启策略,可以为 Always,OnFailure,Never
dns: string("ClusterFirst")            # DNS 策略,可以为 Default,ClusterFirstWithHostNet,ClusterFirst
hostname: string("")                   # 主机名
subdomain: string("")                  # 子域名
termination: uint(30)                  # 优雅退出时间
serviceAccountName: string("")         # ServiceAccount
priorityClassName: string("")          # PriorityClassName
host:
  network: bool(false)                 # 与主机共享 network namespace
  pid: bool(false)                     # 与主机共享 pid namespace
  ipc: bool(false)                     # 与主机共享 ipc namespace
hostAliases:                           # 向容器组的 /etc/hosts 文件添加条目
  - ip: string                         # IP 地址
    hostnames:                         # 主机名列表
    - string
securityContext:
  runAsNonRoot: bool(false)            # 是否以非 root 用户运行
annotations:                           # 容器组附加信息,仅用于保存容器组额外信息
  - key: string                        #
    value: string                      #

在 controller 类型为 Deployment 时,restart 只能为 Always。
主机名和子域名构成 Pod 的访问域名:hostname.subdomain.namespace.svc.clusterdomain。
容器组的 annotations 用于存放用于扩展容器组能力的额外信息。可以被其他组件读取和识别,实现其他功能。 key 的规范参考 controller 的 annotations

类型:initContainer,container

name: string("")                       # 容器名称
image: string                          # 镜像地址
imagePullPolicy: string(Always)        # 镜像拉取策略,可以设置为 Always,IfNotPresent
tty: bool(false)                       # 是否使用 tty
command:                               # 即 Docker EntryPoint
- string    
args:                                  # 即 Docker CMD
- string
workingDir: string("")                 # 工作目录
securityContext:
  privileged: bool(false)              # 是否启动特权模式
  capabilities:                        # POISX CAP
    add:                               # 添加 POISX CAP
    - string
    drop:                              # 移除 POISX CAP
    - string
ports:                                 # 容器端口
- port: pint(80)                       # 端口
  hostPort: pint(0)                    # 暴露到主机端口
  protocol: string("HTTP")             # 端口协议,可以是 HTTP,HTTPS,TCP,UDP
envFrom:                               # env from,来自 Config 或 Secret
- prefix: string("")                   # 所有来自 目标 的 key 都会加这个前缀
  type: string("Config")               # 配置来源,可以是 Config 或 Secret
  name: string                         # Config 或 Secret 的名称
  optional: bool(false)                # 是否可选,即目标不存在也就忽略而不是报错
downwardPrefix: string("")             # 默认环境变量前缀
env:                                   # env
- name: string                         # 环境变量名称
  value: string                        # 环境变量值
  from:                                # value 和 from 只能二选其一
    type: string("Config")             # 来源类型
    name: string                       # Config 或 Secret 的名称
    key: string                        # data 的 key
    resource: string                   # type 为 ResourceFieldRef 时用的值
    optional: bool(false)              # 是否可选,即目标不存在也就忽略而不是报错
resources:                             # 资源限制
  requests:                            # 请求的资源下限
    cpu: string("100m")                # CPU 资源
    memory: string("100Mi")            # 内存资源
    storage: string("")                # 存储资源
    gpu: string("")                    # GPU 资源,Deprecated。建议使用 nvidia.com/gpu
    nvidia.com/gpu: string("")         # NVIDIA GPU 资源
    caicloud.io/local-storage: "0"     # 本地存储资源,只是作为标记、影响调度,并无实际意义
  limits:                              # 请求的资源上限
    cpu: string("100m")                # CPU 资源
    memory: string("100Mi")            # 内存资源
    storage: string("")                # 存储资源
    gpu: string("")                    # GPU 资源,Deprecated。建议使用 nvidia.com/gpu
    nvidia.com/gpu: string("")         # NVIDIA GPU 资源
    caicloud.io/local-storage: "0"     # 本地存储资源,只是作为标记、影响调度,并无实际意义
mounts:                                # 挂载数据卷位置
- name: string                         # 数据卷名称
  readonly: bool(false)                # 是否只读
  path: string                         # 挂载路径
  subpath: string("")                  # 挂载的数据卷子路径
  propagation: string("None")          # 挂载传播类型,可选项为 None,HostToContainer,Bidirectional
probe:                                 # 健康检查
  liveness:                            # 存活检查(参考 probe 设置)
    ...
  readiness:                           # 可读检查(参考 probe 设置)
    ...
lifecycle:                             # 生命周期(参考 handler 设置)
  postStart:                           # 启动后调用,调用失败则重启容器
    ...
  preStop:                             # 停止前调用,调用后无论成功失败都会终止容器
    ...

initContainer 不支持 readiness probe 和 lifecycle,因此在 initContainer 中不能设置这几项。
initContainer 是串行执行的,一个成功后才能执行下一个。 默认的环境变量包括:

  • POD_NAMESPACE
  • POD_NAME
  • POD_IP
  • NODE_NAME

可以通过 downwardPrefix 为上述环境变量增加前缀。比如 downwardPrefix 为 ENV_ 时:POD_NAMESPACE 变为 ENV_POD_NAMESPACE

probe:liveness,readiness
handler:                               # 调用 handler 检查方式
  ... 
delay: uint(0)                         # 从容器启动到发送健康检查请求的时间间隔(秒)
timeout: pint(1)                       # 单次请求的超时时间(秒)
period: pint(10)                       # 请求时间间隔(秒)
threshold:
  success: pint(1)                     # 连续多少次请求成功则认为健康
  failure: pint(3)                     # 连续多少次请求失败则认为不健康
handler:liveness,readiness,postStart,preStop
type: string(HTTP)                     # handler 类型,可以为 HTTP,EXEC,TCP
method:                                # handler 方法
  ...
method:EXEC
command:                               # 执行命令
- string
method:HTTP
scheme: string(HTTP)                   # HTTP 或 HTTPS
host: string("")                       # Host 字段,默认是 pod ip, 如果只是想使用域名,请填在 headers 里面
port: pint                             # 容器端口
path: string                           # HTTP Path
headers:                               # 请求头
- name: string                         # Header 名称
  value: string                        # Header 值

对于 host 这个字段,在 kubernetes 官网的解释里面说明,大部分情况下是用不上的,有一种情况是,如果你的 container 监听了 127.0.0.1 并且 pod 使用了 hostNetwork,则这个 host 需要修改成 127.0.0.1 。在其他通用的使用场景中,你的 container 里面提供了多个虚拟域名(如 nginx 反向代理),那么你应该在 headers 里面设置 Host 的值,而不是使用 host

method:TCP
port: pint                             # TCP 端口

类型:volume

name: string                           # 数据卷名称,在容器中被引用
type: string("Scratch")                # 可选项为 Dedicated,Dynamic,Static,Scratch,Config,Secret,HostPath。Dedicated 仅在控制器为 StatefulSet 时可用
source:                                # source 的设置与 type 有关
  ... 
storage:                               # 存储需求
  request: string("5Gi")               # 请求的最小存储容量
  limit: string("10Gi")                # 请求的最大存储容量
source:Dynamic,Dedicated
class: string                          # 存储方案名称
modes:
- string("ReadWriteOnce")              # 数据卷读写模式,可以为 ReadWriteOnce,ReadOnlyMany,ReadWriteMany

Dynamic 和 Dedicated 两种类型的数据卷实际上都是使用存储方案来实现,即通过创建 PVC 并关联 storage class。
但是 Dynamic 只用于创建单一的 PVC,如果多个容器引用同一个 Dynamic,那么实际上多个副本是共享数据卷的(多副本时 mode 不能为 ReadWriteOnce)。
Dedicated 类型仅用于 StatefulSet 类型的控制器。StatefulSet 会根据 Dedicated 的设置动态创建多个 PVC,并且每个 Pod 会绑定不同的 PVC,即每个 Pod 的数据卷是独立的。 这两种类型的数据卷在部署后,volume 中的所有字段值都不能进行更改。

source:Static
target: string                         # 已创建的数据卷名称
readonly: bool(false)                  # 是否以只读形式挂载

Static 类型的数据卷只能用于使用已经创建好数据卷(PVC)。

source:Scratch
medium: string("")                     # 存储介质,可以为 空字符串 或 Memory

Scratch 表示使用临时数据卷 EmptyDir。

source:Config,Secret
target: string                         # 已创建的 Config 或 Secret
items:
- key: string                          # 配置文件 data 中的 key
  path: string                         # 设置 key 对应的值在数据卷中的绝对路径
  mode: string("0644")                 # 文件读写模式,如果这里为空则使用默认文件读写模式
default: string("0644")                # 默认文件读写模式
optional: bool(false)                  # 是否允许指定的 Config 或 Secret 不存在

Config 和 Secret 表示使用 配置 或 秘钥 作为数据卷。能够指定 配置 和 秘钥 的多个 key 作为文件使用。

source:HostPath
path: string                           # 本地文件路径
source:Glusterfs
endpoints: string                      # glusterfs endpoints
path: string                           # glusterfs volume path
readonly: bool(false)                  # 是否以只读形式挂载

类型:service

name: string                           # 服务名称
type: string(ClusterIP)                # 服务类型,可以是 ClusterIP,NodePort
ports:
- protocol: string(HTTP)               # 端口协议,可以是 HTTP,HTTPS,TCP,UDP
  targetPort: pint                     # 容器端口
  port: pint                           # 服务端口
  nodePort: uint(0)                    # 节点端口,[30000,32767]
annotations:                           # 服务附加信息,仅用于保存服务额外信息
- key: string                          #
  value: string                        #
selector:                              # 服务会将流量路由到标签匹配的 Pod
  string: string                       # 直接指定标签值
sessionAffinity: ClientIP              # 会话保持类型 仅支持 ClientIP 和 None
affinityTimeout: 10800                 # 会话保持超时时间 单位秒 默认 10800 范围是 (0, 86400]

服务可以以两种形式暴露给外部:

  • ClusterIP:使用该形式暴露的服务,其它应用可以通过服务名访问当前服务
  • NodePort:使用该形式暴露的服务,其它应用可以通过节点 IP 访问当前服务

服务类型为 NodePort 时,才可以设置 ports 中的 nodePort 字段。
服务在部署后,服务名称不可变更。

类型:config

name: string                           # 配置名称
data:
- key: string                          #
  value: string                        #

类型:secret

name: string                           # 加密配置名称
type: string(Opaque)                   # 加密配置类型
data:
- key: string                          #
  value: string                        # 值,必须是原始值经过 base64 编码后的字符串

加密配置的类型包括:

  • Opaque:默认加密配置类型,key 可以是任意有效的字符串
  • kubernetes.io/service-account-token: ServiceAccount,key 包括
    • kubernetes.io/service-account.name
    • kubernetes.io/service-account.uid
    • token
    • kubernetes.kubeconfig
    • ca.crt
    • namespace
  • kubernetes.io/dockercfg: Docker config,key 包括
    • .dockercfg
  • kubernetes.io/dockerconfigjson: Docker config json,key 包括
    • .dockerconfigjson
  • kubernetes.io/basic-auth: Basic auth,key 包括
    • username
    • password
  • kubernetes.io/ssh-auth: SSH auth,key 包括
    • ssh-privatekey
  • kubernetes.io/tls: TLS 证书密钥(PEM),key 包括
    • tls.crt
    • tls.key

一个配置文件的例子

_config:
  _metadata:
    name: template
    version: 1.0.0
    description: "A basic template for application"
    creationTime: "2017-07-14 12:00:00"
    source: "/library/template/1.0.0"
    class: Default
    template:
      type: "template.caicloud.io/application"
      version: 1.0.0
  controllers:
  - type: StatefulSet
    controller:
      replica: 3
      name: "mysqlcluster"
      domain: "mysql"
    schedule:
      labels:
        cpu: heavy
        io: heavy
      affinity:
        node:
          type: Prefered
          terms:
          - weight: 10
            expressions:
            - key: cpu
              operator: NotIn
              values:
              - heavy
              - midium
        pod:
          type: Required
          terms:
          - selector:
              labels:
                cpu: heavy
      antiaffinity:
        pod:
          type: Prefered
          terms:
          - weight: 10
            selector:
              expressions:
              - key: cpu
                operator: In
                values:
                - heavy
                - midium
    pod:
      host:
        network: true
    initContainers:
    - image: mysql-init:v1.0.0
      mounts:
      - name: db-volume
        path: /var/lib/mysql
      resources:
        requests:
          cpu: 100m
          memory: 100Mi
        limits:
          cpu: 100m
          memory: 100Mi
    containers:
    - image: mysql:v5.6
      ports:
      - protocol: TCP
        port: 3306
      mounts:
      - name: db-volume
        path: /var/lib/mysql
      - name: shared-volume
        path: /var/lib/logs
      envFrom:
      - type: Config
        name: someconfigmap
        prefix: XXXX_
        optional: false
      downwardPrefix: MY_ENV
      env:
      - name: XXSS_
        value: "sd"
      resources:
        requests:
          cpu: 100m
          memory: 100Mi
        limits:
          cpu: 100m
          memory: 100Mi
      probe:
        liveness:
          handler:
            type: HTTP
            method:
              port: 80
              path: /liveness
          delay: 10
        readiness:
          handler:
            type: EXEC
            method:
              command:
              - curl
              - http://localhost
          delay: 15
    volumes:
    - name: db-volume
      type: Dedicated
      source:
        class: hdd
        modes:
        - ReadWriteOnce
      storage:
        request: 5Gi
      propagation: None
    - name: shared-volume
      type: Dynamic
      source:
        class: ssd
        modes:
        - ReadWriteMany
      storage:
        request: 5Gi
        limit: 100Gi
    services:
    - name: mysql1
      type: ClusterIP
      ports:
      - protocol: HTTP
        targetPort: 80
        port: 80
      sessionAffinity: ClientIP
      affinityTimeout: 10800
    - name: mysql2
      type: NodePort
      ports:
      - protocol: HTTPS
        targetPort: 443
        port: 443
        nodePort: 31222
  - type: Deployment
    controller:
      replica: 1
      name: simplelog
    containers:
    - image: cargo.caicloudprivatetest.com/caicloud/simplelog
      mounts:
      - name: cfgvolume
        path: /etc/simplelog
      resources:
        requests:
          cpu: 100m
          memory: 100Mi
        limits:
          cpu: 100m
          memory: 100Mi
    services:
    - name: log1
      type: ClusterIP
      ports:
      - protocol: HTTP
        targetPort: 80
        port: 80
    volumes:
      name: cfgvolume
      type: Config
      source:
        target: simplecfg
        items:
        - key: "config.yaml"
          path: "config.yaml"
    configs:
    - name: simplecfg
      data:
      - key: "config.yaml"
        value: |
          sync: "5m"
          deadline: "3h"
    secrets:
    - name: simplesecret
      data:
      - key: "encrypted.cfg"
        value: c3luYzogIjVtIgpkZWFkbGluZTogIjNoIgo=
subchart:
  _config: