github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/docs/design/build_zh.md (about)

     1  # 集群镜像 build
     2  
     3  ## Build 类型层
     4  
     5  该模块主要通过对不同构建类型的区分,完成对集群镜像构建前期环境的准备,例如启动K8S 集群,启动sealer registry,以及拉取用于构建的镜像,从而分别实现Build接口,完成对集群镜像的构建。
     6  
     7  ### 类型介绍
     8  
     9  目前sealer 支持4种构建方式,用户可以通过命令行`-m` 参数指定,详细使用文档见[build 使用文档](../site/src/docs/getting-started/build-cloudimage.md) 。
    10  
    11  #### lite build
    12  
    13  该种构建模式,根据Kubefile的定义,实现不用拉起kubernetes集群的轻量化构建。用于已知镜像清单,或者没有特殊的资源需求的场景。
    14  
    15  核心功能介绍
    16  
    17  1. 基础集群镜像的拉取和挂载。
    18  2. 本地缓存registry的启动和挂载。
    19  3. 根据kubefile执行构建指令,收集相关产物。
    20  4. 收集缓存的容器镜像。
    21  5. 清理环境,本地缓存registry的回收。
    22  
    23  ### 接口定义
    24  
    25  `Build(name string, context string, kubefileName string) error`
    26  
    27  参数解释
    28  
    29  ```yaml
    30  name: 新构建的集群镜像名字,不支持大写和特殊字符。
    31  context: 用于构建集群镜像的上下文,默认为当前目录。
    32  kubefilename: kubefile 用于描述集群镜像的构建过程,和Dockerfile类似。该参数为用户自定义的kubefile文件路径。
    33  error: 当执行构建时候,如有发生错误,则会返回该错误。
    34  ```
    35  
    36  ## Build 镜像层
    37  
    38  集群构建流程的核心的实现,主要通过解析kubefile,初始化镜像模块接口,根据集群镜像的layer层定义,执行对应的指令内容和收集对应的产物,从而生成完整的集群镜像。
    39  
    40  核心功能介绍
    41  
    42  1. kubefile 文件的解析。
    43  2. 镜像模块接口初始化,获取当前镜像的基础镜像信息和当前镜像层。
    44  3. 根据文件目录生成新的镜像层
    45  4. 构建指令的执行,以及对应的layer内容的预处理,对应的指令产物收集。
    46  5. 新集群镜像的生成和提供对文件系统的存储功能。
    47  
    48  ### 接口定义
    49  
    50  ```shell
    51  SaveBuildImage(name string) error
    52  ExecBuild(ctx Context) error
    53  Cleanup() error
    54  ```
    55  
    56  参数解释
    57  
    58  Context 结构体
    59  
    60  ```yaml
    61  BuildContext: 构建的上下文。
    62  BuildType: 构建的类型。
    63  UseCache: 标志位,用于检测是否使用缓存。
    64  ```
    65  
    66  ### 构建流程介绍
    67  
    68  Kubefile 举例如下:
    69  
    70  ```shell
    71  FROM registry.cn-qingdao.aliyuncs.com/sealer-io/kubernetes:v1.19.8
    72  COPY recommended.yml manifests
    73  COPY imageList manifests
    74  COPY traefik ./charts
    75  COPY bin/helm /bin
    76  RUN helm --help
    77  CMD kubectl apply -f manifests/recommended.yml
    78  CMD helm install mytest charts/traefik
    79  ```
    80  
    81  1. 根据Kubefile 初始化对应的BuildImage `NewBuildImage(kubefileName string)`,得到一个BuildImage结构体。
    82  2. 根据Kubefile的内容,判断是否需要获取基础镜像,是否需要启动缓存registry,并且初始化镜像模块的接口。
    83  3. 按照Kubefile对应的每一层内容,初始化不同的build指令,并且执行该指令,收集对应的产物。
    84  4. 根据该层指令内容触发对应的layer 层的handler。例如 `COPY imageList manifests` 则会解析imageList中的镜像,并且缓存起来。
    85  5. 待Kubefile对应的每一层内容执行完成后,根据是否启动缓存registry,判断是否需要收集对应的docker 镜像。
    86  6. 待所有产物收集完毕,调用镜像模块接口将新构建的镜像保存到文件系统。
    87  7. 环境清理,例如构建时候产生的临时文件,缓存registry的回收等。
    88  
    89  ## Build 指令层
    90  
    91  该模块主要完成对不同的构建指令的生成和执行,包括 `copy`,`cmd`,`run` 等具体指令的实现,以及集群镜像的层级挂载,集群镜像的缓存判断,指令层的对应layer id生成,对应layer层产物的存储等等。
    92  
    93  ### 指令介绍
    94  
    95  copy 指令
    96  
    97  * 实现构建上下文的copy功能。
    98  * 根据指令内容,实现对应的layer层功能。
    99  * 根据指令产物,计算对应指令的layer id。
   100  
   101  cmd 指令
   102  
   103  * 挂载基础镜像和该指令之前所以指令层产物。
   104  * 根据指令内容,实现对应的layer层功能。
   105  * 根据挂载的指令层产物,实现对应的系统命令的调用。
   106  * 一个kubefile,可以有多个cmd指令,但cmd指令没有产物,即不会计算对应的指令layer id。
   107  
   108  run 指令
   109  
   110  * 实现逻辑同cmd指令一致,但是会根据指令产物计算对应指令的layer id。
   111  
   112  ### 指令缓存
   113  
   114  #### 概念介绍
   115  
   116  * layer id : 根据每一层指令运行的产物,根据时间,文件内容,文件权限等计算出该层指令独一无二的ID。
   117  * cache id : 根据context 中文件的内容,时间权限等计算出该层指令独一无二的ID,如没有命中,则会在该指令层,生成对应的cacheID文件,内容为cache id。
   118  * cache layer: 包括cache id和layer value,layer type的新结构体。
   119  * parent id : 不包括当前层之前的所有指令的chain id计算结果。
   120  * chain id : 根据parent id 和cache layer计算得出,用与匹配文件系统已经缓存的集群镜像。
   121  
   122  #### 缓存计算方式
   123  
   124  默认的parent id 起始值为"",系统会在初始化时候,按照以下生成逻辑,遍历当前文件系统存在的所有集群镜像。格式为map,key 是当前层的chain id,value为当前层对应的cache layer.
   125  
   126  Copy指令 chain id 生成举例
   127  
   128  ```yaml
   129  chain id = ChainID("parent id"+"cache id"+"COPY:recommended.yaml manifests")
   130  ```
   131  
   132  非Copy指令 chain id 生成举例
   133  
   134  非Copy指令没有cache id,则计算时候为""。
   135  
   136  ```yaml
   137  chain id = ChainID("parent id" +""+"CMD:kubectl apply -f etc/tigera-operator.yaml")
   138  ```
   139  
   140  #### 缓存命中逻辑
   141  
   142  1. 根据cache 标志位判断是否需要进行缓存。若是则走以下流程,若否则走常规计算流程。
   143  2. 计算context 中文件的对应的cache id,并且和当前对应的parent id进行计算,得到当前指令层的chain id。
   144  3. 根据 chain id 和系统中存在的所有缓存map,进行比较。
   145  4. 若命中,返回当前的layer id ,cache 标志设置为true,并将当前parent id替换为最新的chain id。
   146  5. 若没有命中,返回当前的layer id ,cache 标志设置为false,当前parent id不发生变化,并将该层对应的cache id 写入文件系统,用于下次缓存计算使用。
   147  
   148  ### 接口定义
   149  
   150  ```shell
   151  Exec(ctx ExecContext) (out Out, err error)
   152  ```
   153  
   154  参数解释
   155  
   156  ExecContext 结构体
   157  
   158  ```yaml
   159  BuildContext: 构建的上下文。
   160  BuildType: 构建的类型。
   161  ContinueCache: 标志位,用于检测是否继续使用缓存,会在每一层layer执行的时候修改。
   162  ParentID cache.ChainID: 缓存chain id,起始值为 ""。会在每一层layer执行的时候修改为包括当前layer的chain id。
   163  CacheSvc cache.Service: 缓存layer生成接口,根据当前layer和cache id,生成对应的缓存layer。用于和ParentID一起,生成当前的chain id。
   164  Prober image.Prober: 缓存探测接口,用于判断对应的chain id 是否和系统中存在的缓存map命中。
   165  LayerStore store.LayerStore: 构建产物存储接口,会根据当前指令执行的结果,计算对应的layerid,并将产物复制到对应的文件系统路径中。
   166  ```
   167  
   168  Out 结构体
   169  
   170  ```yaml
   171  LayerID digest.Digest: 当前指令执行的产物hash,独一无二,将会用于当前layer的存储。
   172  ParentID cache.ChainID: 缓存chain id,与ExecContext 中ParentID一致,用于下一层指令的缓存判断。
   173  ContinueCache bool: 标志位,用于判断下一层指令是否继续使用缓存。
   174  ```
   175  
   176  ## Build layer层
   177  
   178  该模块主要完成对layer层内容的解析以及对应的处理函数的初始化。
   179  
   180  ### 功能介绍
   181  
   182  #### 解析 imageList
   183  
   184  使用方式
   185  
   186  如果对应的Kubefile中有以下字段,则会触发解析 imageList功能。其中COPY的 src 名字为`imageList`,dest 为`manifests`。
   187  
   188  ```shell
   189  COPY imageList manifests
   190  ```
   191  
   192  功能介绍
   193  
   194  1. imageList 解析,将对应`imageList`中的内容逐行获取。
   195  2. 镜像拉取,将解析到的对应docker镜像,使用docker client拉取到本地。
   196  
   197  #### 解析helm charts
   198  
   199  使用方式
   200  
   201  如果对应的Kubefile中有以下字段,则会触发解析helm charts功能。其中COPY的 src 名字为charts 包,dest 为`charts`。
   202  
   203  ```shell
   204  COPY traefik charts
   205  ```
   206  
   207  功能介绍
   208  
   209  1. charts包 解析,将对应 charts 包 中的内容使用helm引擎获取docker 镜像列表。
   210  2. 镜像拉取,将解析到的对应docker镜像,使用docker client拉取到本地。
   211  
   212  #### 解析yaml 文件
   213  
   214  使用方式
   215  
   216  如果对应的Kubefile中有以下字段,则会触发解析yaml 文件缓存镜像功能。其中COPY的 src 名字为 yaml文件格式为"yaml"或者"yml",dest 为`manifests`。
   217  
   218  ```shell
   219  COPY recommended.yml manifests
   220  ```
   221  
   222  功能介绍
   223  
   224  1. yaml文件解析,读取对应yaml文件中的内容,解析`image`字段获取docker镜像列表。
   225  2. 镜像拉取,将解析到的对应docker镜像,使用docker client拉取到本地。
   226  
   227  ### 接口定义
   228  
   229  ```shell
   230  LayerValueHandler(buildContext string, layer v1.Layer) error
   231  ```
   232  
   233  参数解释
   234  
   235  ```yaml
   236  buildContext: 用于构建集群镜像的上下文,默认为当前目录。
   237  layer: 构建阶段,对应的集群镜像层的内容,包括layer value,layer type。
   238  error: 当执行构建时候,如有发生错误,则会返回该错误。
   239  ```
   240  
   241  ### docker镜像缓存
   242  如果使用的是sealer定制的docker,则docker镜像缓存到私有仓库只需要一步:从官方仓库pull镜像。因为sealer把私有仓库设置为代理,所有镜像都会先pull到私有仓库,然后才会再从私有仓库pull到本地。
   243  
   244  如果使用的是原生的docker,则docker镜像缓存到私有仓库需要两步:首先,从官方仓库pull镜像。然后,将pull到本地的镜像再push到私有仓库中。
   245  
   246  在每一个镜像的拉取操作之前加入一个判断docker引擎版本的步骤来进行区分。具体实现方式是:调用docker的sdk函数,得到docker引擎的版本信息,若docker引擎的版本中包含`sealer`字符串,则标示是sealer定制的docker,只进行pull操作。若docker引擎的版本中,不包含`sealer`字符串,则pull和push操作都会执行。