diff --git a/README.md b/README.md index 0125522d..63355776 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,21 @@ # 安装kubekey ## kubernetes中安装 ```shell -helm upgrade --install --create-namespace -n kubekey-system kubekey oci://hub.kubesphere.com.cn/kubekey/kubekey +helm upgrade --install --create-namespace -n kubekey-system kubekey kubekey-1.0.0.tgz ``` +然后通过创建Inventory, Config, 和Pipeline资源来执行命令 +**Inventory**: 任务执行的host清单. 用于定义与host相关, 与任务模板无关的变量. 详见[参数定义](docs/zh/201-variable.md) +**Config**: 给任务模板设置全局变量. 用于定义与host无关, 与任务模板相关的变量. 详见[参数定义](docs/zh/201-variable.md) +**Pipeline**: 指定执行的playbook文件 + +## 二进制执行 +可直接用二进制在命令行中执行命令 +```shell +kk run -i inventory.yaml -c config.yaml playbook.yaml +``` +运行命令后, 会在工作目录的runtime下生成对应的Inventory, Config和Pipeline资源 + +# 文档 +**[项目模版编写规范](docs/zh/001-project.md)** +**[模板语法](docs/zh/101-syntax.md)** +**[参数定义](docs/zh/201-variable.md)** diff --git a/builtin/roles/precheck/env_check/tasks/network.yaml b/builtin/roles/precheck/env_check/tasks/network.yaml index 36ee45c9..0727276f 100644 --- a/builtin/roles/precheck/env_check/tasks/network.yaml +++ b/builtin/roles/precheck/env_check/tasks/network.yaml @@ -15,7 +15,7 @@ - name: Guarantee that enough network address space is available for all pods tags: ["network"] assert: - that: "(kubernetes.kubelet.max_pods | integer) <= (2 | pow: {{ 32 - kubernetes.controller_manager.kube_network_node_prefix | integer }} - 2)" + that: "(kubernetes.kubelet.max_pods | integer) <= (2 | pow:{{ 32 - kubernetes.controller_manager.kube_network_node_prefix | integer }} - 2)" fail_msg: "Do not schedule more pods on a node than inet addresses are available." when: - inventory_name in groups['k8s_cluster'] diff --git a/docs/zh/001-project.md b/docs/zh/001-project.md new file mode 100644 index 00000000..01acf678 --- /dev/null +++ b/docs/zh/001-project.md @@ -0,0 +1,39 @@ +# 项目 +项目中存放要执行的任务模板. 由一系列的yaml文件构成 +为了便于使用者快速理解和上手,kk在对任务抽象时,参考借鉴了[ansible](https://github.com/ansible/ansible)任务编排规范 +## 目录结构 +```text +|-- project +| |-- playbooks/ +| |-- playbook1.yaml +| |-- playbook2.yaml +| |-- roles/ +| | |-- roleName1/ +| | |-- roleName2/ +... +``` +**[playbooks](002-playbook.md)**:执行入口, 存放一系列playbook. 一个playbook中, 可定义多个task或role. 每次执行流程模板时, 会按定义顺序执行对应的任务. +**[roles](003-role.md)**:role集合. 一个role是一组task. +## 存放路径 +项目可存放内建, 本地或git服务器上. +### 内建 +内建项目在`builtin`目录. 会集成到kubekey的命令中. +执行示例: +```shell +kk precheck +``` +执行`builtin`目录中的`playbooks/precheck.yaml`流程文件. +### 本地 +执行命令示例: +```shell +kk run playbooks/demo.yaml --project-addr=$(ProjectDir) +``` +执行`$(ProjectDir)`目录中的`playbooks/demo.yaml`流程文件. +### git +执行命令示例: +```shell +kk run playbooks/demo.yaml + --project-addr=$(GIT_URL) \ + --project-branch=$(GIT_BRANCH) +``` +执行git地址为`$(GIT_URL)`, 分支为`$(GIT_BRANCH)`上的`playbooks/demo.yaml`流程文件. diff --git a/docs/zh/002-playbook.md b/docs/zh/002-playbook.md new file mode 100644 index 00000000..f4435d8b --- /dev/null +++ b/docs/zh/002-playbook.md @@ -0,0 +1,62 @@ +# 流程 +## 文件定义 +一个playbook文件中, 按定义顺序执行多个playbook, 每个playbook指定在哪些host上执行哪些任务. +```yaml +- import_playbook: others/playbook.yaml + +- name: Playbook Name + tags: ["always"] + hosts: ["host1", "host2"] + serial: 1 + run_once: false + ignore_errors: false + gather_facts: false + vars: {a: b} + vars_files: ["vars/variables.yaml"] + pre_tasks: + - name: Task Name + debug: + msg: "I'm Task" + roles: + - role: role1 + when: true + tasks: + - name: Task Name + debug: + msg: "I'm Task" + post_tasks: + - name: Task Name + debug: + msg: "I'm Task" +``` +**import_playbooks**: 定义引用的playbook文件名称, 通常为相对路径, 文件查找顺序为:`项目路径/playbooks/`, `当前路径/playbooks/`, `当前路径/` +**name**: playbook名称, 非必填. +**tags**: playbook的标签, 非必填.仅作用于playbook, playbook下的role, task不会继承该标签. +在执行playbook命令时, 通过参数筛选需要执行的playbook. 示例如下: +- `kk run [playbook] --tags tag1 --tags tag2`: 执行带有tag1标签或带有tag2标签的playbook +- `kk run [playbook] --skip-tags tag1 --skip-tags tag2`: 执行时跳过带有tag1标签或带有tag2标签的playbook +其中, 带有`always`标签的playbook始终执行, 带有`never`标签的playbook始终不执行 +传入参数为`all`时, 表示选择所有playbook, 参数参数为`tagged`时, 表示选择打了标签的playbook +**hosts**: 定义在哪些机器上执行, 必填. 所有hosts需要在`inventory`中定义(localhost除外). 可以填host名称, 也可以填group名称. +**serial**: 分批次执行playbook, 可以定义单个值(字符串或数字)或一组值(数组), 非必填. 默认一批执行。 +- serial值为一组数字时, 按固定的数量来给`hosts`分组, 超出`serial`定义范围时, 按最后一个`serial`值扩展. + 比如serial的值为[1, 2], hosts的值为[a, b, c, d]时. 会分3批来执行playbook, 第一批在[a]上执行, 第二批在[b, c]上执行, 第三批 在[d]上执行. +- serial值为百分比时, 按百分比计算出每批次实际的`hosts`数量(下行整数), 然后给`hosts`分组, 超出`serial`定义范围时, 按最后一个`serial`值扩展. + 比如serial的值为[30%, 60%], hosts的值为[a, b, c, d]时. 先计算出serial为[1.2, 2.4], 即为[1, 2]. +百分比和数字可以混合设置. +**run_once**: 是否只执行一次, 非必填, 默认false, 会在第一个hosts上执行. +**ignore_errors**: 该playbook下所关联的task执行失败时, 是否忽略失败, 非必填, 默认false. +**gather_facts**: 是否获取服务器信息, 非必填, 默认false. 针对不同的host获取不同的数据. +- localConnector: 获取release(/etc/os-release), kernel_version(uname -r), hostname(hostname), architecture(arch). 目前仅支持linux系统 +- sshConnector: 获取release(/etc/os-release), kernel_version(uname -r), hostname(hostname), architecture(arch). 目前仅支持linux系统 +- kubernetesConnector:暂无 +**vars**: 配置默认参数, 非必填, yaml格式. +**vars_files**: 配置默认参数, 非必填, yaml文件格式. vars和vars_files定义的字段不能重复. +**pre_tasks**: 定义需要执行的[tasks](004-task.md), 非必填. +**roles**: 定义需要执行的[roles](003-role.md), 非必填. +**tasks**: 定义需要执行的[tasks](004-task.md), 非必填. +**post_tasks**: 定义需要执行的[tasks](004-task.md), 非必填. +## playbook执行顺序 +不同的playbook: 按定义的先后顺序执行. 如果包含了import_playbook, 会将引用的playbook文件, 转成playbook. +同一个playbook中: 任务执行顺序pre_tasks->roles->tasks->post_tasks +当其中一个task失败时(不包含ignore状态), playbook执行失败. diff --git a/docs/zh/003-role.md b/docs/zh/003-role.md new file mode 100644 index 00000000..78f359ed --- /dev/null +++ b/docs/zh/003-role.md @@ -0,0 +1,41 @@ +# 角色 +角色是一个任务组 +## 在playbook文件定义role引用 +```yaml +- name: Playbook Name + #... + roles: + - name: Role Name + tags: ["always"] + when: true + run_once: false + ignore_errors: false + vars: {a: b} + role: Role-ref Name +``` +**name**: role名称, 非必填. 该名称不同于playbook中role的引用名称. +**tags**: playbook的标签, 非必填. 仅作用于playbook, playbook下的role, task不会继承该标签. +**when**: 执行条件, 可以定义单个值(字符串)或多个值(数组), 非必填, 默认执行该role. 对每个的host单独计算值. +**run_once**: 是否只执行一次, 非必填, 默认false, 会在第一个hosts上执行. +**ignore_errors**: 该role下所关联的task执行失败时, 是否忽略失败, 非必填, 默认false. +**role**: playbook中引用的名称, 对应roles目录下的子目录, 必填. +**vars**: 配置默认参数, 非必填, yaml格式. +## 在role目录结构 +```text +|-- project +| |-- roles/ +| | |-- roleName/ +| | | |-- defaults/ +| | | | |-- main.yml +| | | |-- tasks/ +| | | | |-- main.yml +| | | |-- templates/ +| | | | |-- template1 +| | | |-- files/ +| | | | |-- file1 +``` +**roleName**:role的引用名称, 一级或多级目录. +**defaults**:对role下的所有task, 定义默认参数值. 在main.yaml文件中定义. +**[tasks](004-task.md)**:role下所关联的task模板, 一个角色可以有多个task, 在main.yaml文件中定义. +**templates**:模板文件, 文件中通常会引用变量, 在`templates`类型的task中使用 +**files**:原始文件, 在`copy`类型的task中使用 diff --git a/docs/zh/004-task.md b/docs/zh/004-task.md new file mode 100644 index 00000000..066c9f1c --- /dev/null +++ b/docs/zh/004-task.md @@ -0,0 +1,53 @@ +# 任务 +task分为单层级task,和多层级task +单层级task: 包含[module](005-module.md)相关字段, 不包含. 一个task只能包含一个module. +多层级task: 不包含[module](005-module.md)相关字段, 包含block字段. +task执行时, 会在定义的host分别上执行. +## 文件定义 +```yaml +- include_tasks: other/task.yaml + tags: ["always"] + when: true + run_once: false + ignore_errors: false + vars: {a: b} + +- name: Block Name + tags: ["always"] + when: true + run_once: false + ignore_errors: false + vars: {a: b} + block: + - name: Task Name + # [module] + rescue: + - name: Task Name + # [module] + always: + - name: Task Name + # [module] + +- name: Task Name + tags: ["always"] + when: true + loop: [""] + #[module] +``` +**include_tasks**: 该任务中引用其他任务模板文件. +**name**: task名称, 非必填. +**tags**: task的标签, 非必填. 仅作用于playbook, playbook下的role, task不会继承该标签. +**when**: 执行条件, 可以定义单个值(字符串)或多个值(数组), 非必填, 默认执行该role. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**failed_when**: 失败条件, host满足该条件时,判定为执行失败, 可以定义单个值(字符串)或多个值(数组), 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**run_once**: 是否只执行一次, 非必填, 默认false, 会在第一个hosts上执行. +**ignore_errors**: 是否忽略失败, 非必填, 默认false. +**vars**: 配置默认参数, 非必填, yaml格式. +**[module相关字段](005-module.md)**: task实际要执行的操作, 非必填(当未block字段时, 必填). +**loop**: 循环执行module中定义的操作, 每次执行时,以`item: loop-value`的形式将值传递给module. 可以定义单个值(字符串)或多个值(数组), 非必填, 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**retries**: task执行失败时. 需要重新尝试几次. +**register**: 值为字符串, 将执行结果注册到[variable](201-variable.md)中, 传递给后续的task. 如果结果为json字符串, 会尝试将该字符串转成json结构层级存入variable中(key为register的值, value为输出值, 输出值包含: stderr和stdout两个字段) +- stderr: 失败输出 +- stdout: 成功输出 +**block**: task集合, 非必填(当未定义module相关字段时, 必填), 一定会执行. +**rescue**: task集合, 非必填, 当block执行失败(task集合有一个执行失败即为该block失败)时,执行该task集合. +**always**: task集合, 非必填, 当block和rescue执行完毕后(无论成功失败)都会执行该task集合. diff --git a/docs/zh/005-module.md b/docs/zh/005-module.md new file mode 100644 index 00000000..cd86157f --- /dev/null +++ b/docs/zh/005-module.md @@ -0,0 +1,114 @@ +# 任务执行模块 +module定义了一个任务实际要执行的操作 +## assert +用于断言host上的variable是否满足某个条件 +```yaml +assert: + that: I'm assertion statement + success_msg: I'm success message + fail_msg: I'm failed message + msg: I'm failed message +``` +**that**: 断言语句, 必填.值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**success_msg**: 成功时输出, 非必填, 默认值为"True". +**fail_msg**: 失败时输出, 非必填, 默认值为"True". +**msg**: 失败时输出, 非必填, 默认值为"True". 优先输出`fail_msg`. +## command/shell +执行命令, command和shell的用法相同 +```yaml +command: I'm command statement +``` +值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. + +## copy +复制本地文件到host. +```yaml +copy: + src: srcpath + content: srcpath + dest: destpath + mode: 0755 +``` +**src**: 来源地址, 可以为绝对路径或相对路径, 可以是目录或者文件, 非必填(`content`未定义时, 必填). 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +- 绝对路径: 从执行命令的机器上的绝对路径上获取. +- 相对路径: 从`project_dir`中获取, 获取顺序: $(project_dir)/roles/roleName/files/$(srcpath) > $(project_dir)/playbooks/.../$(current_playbook)/roles/$(roleName)/files/$(srcpath) > $(project_dir)/files/$(srcpath). +**content**: 来源文件内容, 非必填(`src`未定义时, 必填). 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**dest**: 目标地址, host上的绝对路径, 可以是目录或者文件(与`src`对应, 如果为文件,需要在末尾添加"/"), 必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**mode**: 复制到host上的文件权限, 非必填, 默认源文件权限. +## fetch +从host上获取文件到本地. +```yaml +fetch: + src: srcpath + dest: destpath +``` +**src**: 来源文件地址, host上的绝对路径, 必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**dest**: 目标文件地址, 本地绝对路径, 可以是目录或者文件(与`src`对应, 如果为文件,需要在末尾添加"/"), 必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +## debug +打印信息 +```yaml +debug: + var: I'm variable statement + msg: I'm message statement +``` +**var**: 打印变量, 非必填, 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**msg**: 打印信息, 非必填, 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +## template +templates中的文件内容采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +将文件内容转换为实际文件后,复制本地文件到host. +```yaml +template: + src: srcpath + dest: destpath + mode: 0755 +``` +**src**: 来源地址, 可以为绝对路径或相对路径, 可以是目录或者文件, 必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +- 绝对路径: 从执行命令的机器上的绝对路径上获取. +- 相对路径: 从`project_dir`中获取, 获取顺序: $(project_dir)/roles/roleName/templates/$(srcpath) > $(project_dir)/playbooks/.../$(current_playbook)/roles/$(roleName)/templates/$(srcpath) > $(project_dir)/templates/$(srcpath). +**dest**: 目标地址, host上的绝对路径, 可以是目录或者文件(与`src`对应, 如果为文件,需要在末尾添加"/"), 必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**mode**: 复制到host上的文件权限, 非必填, 默认源文件权限. +## set_fact +给所有host设置variable. 层级结构保持不变 +```yaml +set_fact: + key: value +``` +**key**: 必填, 可以为可以为多级结构(比如{k1:{k2:value}}). +**value**: 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +## gen_cert +在工作目录生成证书, $(work_dir)/kubekey/pki/ +```yaml +gen_cert: + root_key: keypath + root_cert: certpath + date: 87600h + sans: ["ip1","dns1"] + cn: common name + out_key: keypath + out_cert: certpath +``` +**root_key**: 父证书的key文件绝对路径, 用于生成子证书, 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**root_cert**: 父证书的cert文件绝对路径, 用于生成子证书, 非必填, 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**date**: 证书失效时间, 时间间隔格式(单位: s,m,h), 非必填, 默认10年. +**sans**: Subject Alternate Names, 支持数组或数组类型的json字符串格式, 非必填. +**cn**: Common Name. 必填. +**out_key**: 输出的证书key文件绝对路径, 必填, 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**out_cert**: 输出的证书cert文件绝对路径, 必填, 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +当root_key或root_cert未定义时, 生成自签名证书. +## image +拉取镜像到本地目录, 或推送镜像到远程服务器 +```yaml +image: + pull: ["image1", "image2"] + push: + registry: local.kubekey + username: username + password: password + namespace_override: new_namespace +``` +**pull**: 拉取镜像到本地工作目录, 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**push**: 推送工作目录中的镜像到远程仓库, 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**registry**: 远程仓库地址, 必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**username**: 远程仓库认证用户, 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**password**: 远程仓库认证密码, 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. +**namespace_override**: 是否用新的路径, 覆盖镜像原来的路径, 非必填. 值采用[模板语法](101-syntax.md)编写, 对每个的host单独计算值. diff --git a/docs/zh/101-syntax.md b/docs/zh/101-syntax.md new file mode 100644 index 00000000..482b3edb --- /dev/null +++ b/docs/zh/101-syntax.md @@ -0,0 +1,54 @@ +# 语法 +语法遵循Django-syntax规范.采用[pongo2](https://github.com/flosch/pongo2)实现, 并pongo2的关键字进行了扩展 +# 自定义关键字 +## defined +判断某个参数是否在[variable](201-variable.md)中定义. 值为bool类型 +```yaml +{{ variable | defined }} +``` +## version +比较版本大小. 参数为比较标准, 值为bool类型 +```yaml +# version_variable>v1.0.0 +{{ version_variable | version:'>v1.0.0' }} +# version_variable>=v1.0.0 +{{ version_variable | version:'>=v1.0.0' }} +# version_variable==v1.0.0 +{{ version_variable | version:'==v1.0.0' }} +# version_variable<=v1.0.0 +{{ version_variable | version:'<=v1.0.0' }} +# version_variable 静态变量 +## 静态变量 +静态变量包含节点清单, 全局配置, 模板中定义的参数. +参数优先级为: 全局配置 > 节点清单 > 模版中定义的参数. +### 节点清单 +yaml格式文件, 不包含模板语法, 通过`-i`参数传入(`kk -i inventory.yaml ...`), 在每个host上生效 +**定义规范**: +```yaml +apiVersion: kubekey.kubesphere.io/v1 +kind: Inventory +metadata: + name: default +spec: + hosts: + - hostname1: + k1: v1 + #... + - hostname2: + k2: v2 + #... + - hostname3: + #... + groups: + groupname1: + groups: + - groupname2 + # ... + hosts: + - hostname1 + #... + vars: + k1: v1 + #... + groupname2: + #... + vars: + k1: v1 + #... +``` +**hosts**: key为host名称, value为给该host设置的变量. +**groups**: 给host进行分组. key为组名称, value有groups, hosts和vars +- groups: 该组包含哪些其他组. +- hosts: 该组包含哪些hosts. +- vars: 组级别的变量, 针对组中所有host生效. +groups包含的总hosts为`groups`包含的host + `hosts`中包含的host. +**vars**: 全局变量, 针对所有host生效. +变量优先级为: $(host_variable) > $(group_variable) > $(global_variable) +### 全局配置 +yaml格式文件, 不包含模板语法, 通过`-c`参数传入(`kk -c config.yaml ...`), 在每个host上生效 +```yaml +apiVersion: kubekey.kubesphere.io/v1 +kind: Config +metadata: + name: default +spec: + k: v + #... +``` +任意类型的参数 +### 模板中定义的参数 +模板中定义的var参数包含: +- playbook中`vars`字段和`vars_files`字段定义的参数 +- role中的defaults/main.yaml定义的参数 +- role中`vars`字段定义的参数 +- task中`vars`字段定义的参数 +## 动态变量 +动态变量是节点执行是生成的变量数据, 包含: +- `gather_facts`定义的参数 +- `register`定义的参数 +- `set_fact`定义的参数 +优先级为参数定义的顺序, 后定义参数高于先定义的参数. diff --git a/pkg/apis/core/v1/role.go b/pkg/apis/core/v1/role.go index a7b433cb..3e33b249 100644 --- a/pkg/apis/core/v1/role.go +++ b/pkg/apis/core/v1/role.go @@ -26,6 +26,7 @@ type RoleInfo struct { Taggable `yaml:",inline"` CollectionSearch `yaml:",inline"` + // Role ref in playbook Role string `yaml:"role,omitempty"` Block []Block