From 03853f127d9d6cb3c33318ee13c6ed73bbfe61d5 Mon Sep 17 00:00:00 2001 From: "li.wei9" Date: Thu, 9 Nov 2023 14:00:47 +0800 Subject: [PATCH] Adjust the directory structure --- docs/core/roadmap.md | 25 -- docs/core/userguide/component-dev.md | 40 --- docs/core/userguide/helmtofuture.md | 91 ------ docs/develop-guid/_category_.json | 4 + .../building-base/_category_.json | 2 +- .../building-base/add-cluster.md | 2 +- .../configuration/3rd-party-account.md | 0 .../configuration/_category_.json | 0 .../configuration/audit-config.md | 2 +- .../configuration/customize-menu.md | 0 .../configuration/customize-portal.md | 0 ...dbc309014fac7a9f1f502854b9c6251eea03be.png | Bin ...38c5792dab1fe153770917e42a5888a7ebebdc.png | Bin ...6cb8c55e3bd650bc3beede41ea1622211d02bd.png | Bin ...fafa2583f60d9376d5efc7d03cb7faa4092fbf.png | Bin ...3f27606ed0d473e32d5eb511feff0513e4ff11.png | Bin .../configuration/issue-oidc-proxy-certs.md | 0 .../configuration/oidc-integration.md | 0 .../building-base/images/dev_arch.png | Bin .../{ => develop-guid}/building-base/intro.md | 0 .../component-market/_category_.json | 0 .../component-market/blockchain.md | 0 .../component-market/kubedashboard.md | 0 .../component-market/kubelogin.md | 0 .../component-market/logging.md | 0 .../component-market/monitoring.md | 0 docs/{ => develop-guid}/core/_category_.json | 2 +- .../core/concepts/_category_.json | 0 .../core/concepts/buildingbase_resources.md | 0 .../core/concepts/component.md | 0 .../core/concepts/componentplan.md | 2 +- .../core/concepts}/imageoverride.md | 2 +- .../core/concepts/rating.md | 0 .../core/concepts/repository.md | 0 .../core/concepts/subscription.md | 0 .../componentplan-helm-release.excalidraw | 0 .../images/componentplan-helm-release.png | Bin .../core/images/image-changed.excalidraw | 0 .../core/images/image-changed.png | Bin .../core/images/rating_flow.drawio.png | Bin docs/{ => develop-guid}/core/intro.md | 0 .../core/rating}/_category_.json | 4 +- .../core/rating}/enablerating.md | 4 +- .../core/rating}/rating.md | 4 +- ...5c5b3379940f8714667f8fb2dc780f3442b8f0.png | Bin .../images/component-lifecycle.drawio.png | Bin .../images/kubebb_overview.drawio.png | Bin .../images/kubebb_portal.png | Bin .../images/lowcode-development.png | Bin docs/develop-guid/intro.md | 104 ++++++ .../lowcode-development/_category_.json | 2 +- .../development/_category_.json | 0 .../development/bff-apis.md | 0 .../development/develop-hello-world.md | 0 .../development/frontend-low-code.md | 0 .../development/frontend.md | 0 .../development/images/app-publish.png | Bin .../development/images/app_create.png | Bin .../development/images/app_publish_tab.png | Bin .../images/assets_component_add.png | Bin .../development/images/assets_npm_add.png | Bin .../development/images/assets_npm_bff.png | Bin .../development/images/bff_lowcode.drawio | 0 .../development/images/bff_lowcode.png | Bin .../development/images/branches_create.png | Bin .../development/images/fe_arch.svg | 0 .../development/images/git-commit.png | Bin .../development/images/global_add_func.png | Bin .../development/images/global_config.png | Bin .../development/images/members_create.png | Bin .../development/images/menu_create.png | Bin .../development/images/page_add_api.png | Bin .../development/images/page_add_func.png | Bin .../development/images/page_bind_data.png | Bin .../development/images/page_bind_func.png | Bin .../development/images/page_code.png | Bin .../development/images/page_commit.png | Bin .../development/images/page_create.png | Bin .../development/images/page_edit.png | Bin .../development/images/page_edit_props.png | Bin .../development/images/page_entry.png | Bin .../development/images/page_preview.png | Bin .../development/images/playground_graphql.jpg | Bin .../development_pattern.md | 0 .../lowcode-development/images/dev_arch.png | Bin .../lowcode-development/images/yunti_arch.svg | 0 .../lowcode-development/intro.md | 0 .../privatecluster.md | 2 +- docs/{user-guid/image => images}/struc.png | Bin docs/intro.md | 162 ++++------ docs/quick-start/buildingbase_quickstart.md | 160 ---------- docs/quick-start/prerequisite.md | 106 ------- ...core_quickstart.md => quick-experience.md} | 142 ++++++--- docs/quick-start/quick-install.md | 295 ++++++++++++++++++ docs/quick-start/try_customization.md | 93 ------ docs/user-guid/_category_.json | 2 +- docs/user-guid/component_anagement.md | 28 +- docs/user-guid/image/advanced-config.png | Bin 82684 -> 31621 bytes docs/user-guid/intro.md | 70 ----- docusaurus.config.js | 10 +- 100 files changed, 607 insertions(+), 753 deletions(-) delete mode 100644 docs/core/roadmap.md delete mode 100644 docs/core/userguide/component-dev.md delete mode 100644 docs/core/userguide/helmtofuture.md create mode 100644 docs/develop-guid/_category_.json rename docs/{ => develop-guid}/building-base/_category_.json (89%) rename docs/{ => develop-guid}/building-base/add-cluster.md (92%) rename docs/{ => develop-guid}/building-base/configuration/3rd-party-account.md (100%) rename docs/{ => develop-guid}/building-base/configuration/_category_.json (100%) rename docs/{ => develop-guid}/building-base/configuration/audit-config.md (98%) rename docs/{ => develop-guid}/building-base/configuration/customize-menu.md (100%) rename docs/{ => develop-guid}/building-base/configuration/customize-portal.md (100%) rename docs/{ => develop-guid}/building-base/configuration/images/19b4c83b8381c4f6c82d3526ccdbc309014fac7a9f1f502854b9c6251eea03be.png (100%) rename docs/{ => develop-guid}/building-base/configuration/images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png (100%) rename docs/{ => develop-guid}/building-base/configuration/images/73946089d53ccbedf6b6c58cbb6cb8c55e3bd650bc3beede41ea1622211d02bd.png (100%) rename docs/{ => develop-guid}/building-base/configuration/images/7ef885f51a16d83577089c409efafa2583f60d9376d5efc7d03cb7faa4092fbf.png (100%) rename docs/{ => develop-guid}/building-base/configuration/images/94ca51f03578085968c8e1ffd03f27606ed0d473e32d5eb511feff0513e4ff11.png (100%) rename docs/{ => develop-guid}/building-base/configuration/issue-oidc-proxy-certs.md (100%) rename docs/{ => develop-guid}/building-base/configuration/oidc-integration.md (100%) rename docs/{ => develop-guid}/building-base/images/dev_arch.png (100%) rename docs/{ => develop-guid}/building-base/intro.md (100%) rename docs/{ => develop-guid}/component-market/_category_.json (100%) rename docs/{ => develop-guid}/component-market/blockchain.md (100%) rename docs/{ => develop-guid}/component-market/kubedashboard.md (100%) rename docs/{ => develop-guid}/component-market/kubelogin.md (100%) rename docs/{ => develop-guid}/component-market/logging.md (100%) rename docs/{ => develop-guid}/component-market/monitoring.md (100%) rename docs/{ => develop-guid}/core/_category_.json (87%) rename docs/{ => develop-guid}/core/concepts/_category_.json (100%) rename docs/{ => develop-guid}/core/concepts/buildingbase_resources.md (100%) rename docs/{ => develop-guid}/core/concepts/component.md (100%) rename docs/{ => develop-guid}/core/concepts/componentplan.md (99%) rename docs/{core/userguide => develop-guid/core/concepts}/imageoverride.md (99%) rename docs/{ => develop-guid}/core/concepts/rating.md (100%) rename docs/{ => develop-guid}/core/concepts/repository.md (100%) rename docs/{ => develop-guid}/core/concepts/subscription.md (100%) rename docs/{ => develop-guid}/core/images/componentplan-helm-release.excalidraw (100%) rename docs/{ => develop-guid}/core/images/componentplan-helm-release.png (100%) rename docs/{ => develop-guid}/core/images/image-changed.excalidraw (100%) rename docs/{ => develop-guid}/core/images/image-changed.png (100%) rename docs/{ => develop-guid}/core/images/rating_flow.drawio.png (100%) rename docs/{ => develop-guid}/core/intro.md (100%) rename docs/{core/userguide => develop-guid/core/rating}/_category_.json (54%) rename docs/{core/userguide => develop-guid/core/rating}/enablerating.md (98%) rename docs/{core => develop-guid/core/rating}/rating.md (99%) rename docs/{ => develop-guid}/images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png (100%) rename docs/{ => develop-guid}/images/component-lifecycle.drawio.png (100%) rename docs/{ => develop-guid}/images/kubebb_overview.drawio.png (100%) rename docs/{ => develop-guid}/images/kubebb_portal.png (100%) rename docs/{ => develop-guid}/images/lowcode-development.png (100%) create mode 100644 docs/develop-guid/intro.md rename docs/{ => develop-guid}/lowcode-development/_category_.json (91%) rename docs/{ => develop-guid}/lowcode-development/development/_category_.json (100%) rename docs/{ => develop-guid}/lowcode-development/development/bff-apis.md (100%) rename docs/{ => develop-guid}/lowcode-development/development/develop-hello-world.md (100%) rename docs/{ => develop-guid}/lowcode-development/development/frontend-low-code.md (100%) rename docs/{ => develop-guid}/lowcode-development/development/frontend.md (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/app-publish.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/app_create.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/app_publish_tab.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/assets_component_add.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/assets_npm_add.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/assets_npm_bff.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/bff_lowcode.drawio (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/bff_lowcode.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/branches_create.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/fe_arch.svg (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/git-commit.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/global_add_func.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/global_config.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/members_create.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/menu_create.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_add_api.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_add_func.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_bind_data.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_bind_func.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_code.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_commit.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_create.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_edit.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_edit_props.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_entry.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/page_preview.png (100%) rename docs/{ => develop-guid}/lowcode-development/development/images/playground_graphql.jpg (100%) rename docs/{ => develop-guid}/lowcode-development/development_pattern.md (100%) rename docs/{ => develop-guid}/lowcode-development/images/dev_arch.png (100%) rename docs/{ => develop-guid}/lowcode-development/images/yunti_arch.svg (100%) rename docs/{ => develop-guid}/lowcode-development/intro.md (100%) rename docs/{core/userguide => develop-guid}/privatecluster.md (99%) rename docs/{user-guid/image => images}/struc.png (100%) delete mode 100644 docs/quick-start/buildingbase_quickstart.md delete mode 100644 docs/quick-start/prerequisite.md rename docs/quick-start/{core_quickstart.md => quick-experience.md} (58%) create mode 100644 docs/quick-start/quick-install.md delete mode 100644 docs/quick-start/try_customization.md delete mode 100644 docs/user-guid/intro.md diff --git a/docs/core/roadmap.md b/docs/core/roadmap.md deleted file mode 100644 index 00b9a12c6..000000000 --- a/docs/core/roadmap.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -sidebar_position: 5 ---- - -# 路线图 - -## v0.1.0 - -- 支持管理组件仓库 **Repository** - - 支持与 Helm 仓库兼容的 **Repository Server** - - **Watcher** 监视 **Repository** -- 实现 **Component** 管理 - - **Watcher** 实现 **Components** 的 CRUD 操作 -- 支持 **ComponentPlan** 和 **Subscription** - - 允许用户订阅 **Component** 的最新版本更改 - - 使用与 Helm Chart 兼容的 **ComponentPlan** 计划组件部署 - -## v0.2.0 - -- 支持内核各控制器的**Events**记录 -- 适配 Kubebb 底座服务 -- 基于[Tekton Pipeline](https://tekton.dev/) 从 **安全性**、**可靠性** 和 **可用性** 三个维度对 **Component** 进行评级**Rating** -- 基于[Tekton Pipeline](https://tekton.dev/)实现**ComponentPlan**组件部署前的预先校验**Check** -- 组件仓库**Repository** 中启用 **auth** 和 **OCI** -- 实现与低代码平台集成 diff --git a/docs/core/userguide/component-dev.md b/docs/core/userguide/component-dev.md deleted file mode 100644 index cb866bc0e..000000000 --- a/docs/core/userguide/component-dev.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -sidebar_position: 5 ---- - -# 组件开发 - -Kubebb的组件安装包采用`Helm`模式,遵循Helm charts开发规则。除此之外,我们额外定义添加了一些特殊字段来满足一些组件的特殊性。 - - -## 组件类型 - -从功能角度,我们将组件划分为两类: - -- 系统组件,如U4A、TMF等,组件的运行需要系统管理权限 - -- 普通功能组件,如minio、weaviate等,组件可运行在任何`租户-项目`中,没有特殊限制 - - -## 通用配置 - -参考[Helm官方文档](https://helm.sh/docs/) - -## 组件高级配置 - -为支持不同组件对安装位置、权限的可控,特此额外约定了多个配置字段 - -### Chart.yaml - -`Chart.yaml`中包含组件的核心定义、版本、维护者等信息,属于`Helm`预定义的内容。为了支持额外的特殊需求,我们决定通过`annotations`来自由定义。如下所示: - -```yaml -annotations: - core.kubebb.k8s.com.cn/displayname: "内核" - core.kubebb.k8s.com.cn/restricted-tenants: "system-tenant" - core.kubebb.k8s.com.cn/restricted-namespaces: "msa-system" -``` - -- `core.kubebb.k8s.com.cn/displayname`: 用于填充组件的展示名,支持中英文 -- `core.kubebb.k8s.com.cn/restrict-tenants`: 用于设置组件安装位置的限制租户,多个租户需要通过`,`隔开 -- `ore.kubebb.k8s.com.cn/restricted-namespaces`: 用于设置组件安装位置的限制项目/命名空间,多个命名空间通过`,`隔开 diff --git a/docs/core/userguide/helmtofuture.md b/docs/core/userguide/helmtofuture.md deleted file mode 100644 index a2f2ff174..000000000 --- a/docs/core/userguide/helmtofuture.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -sidebar_position: 4 ---- -# 从 Helm 命令迁移 - -内核被设计为尽量兼容 Helm 命令,对于一个熟悉 Helm 命令的开发者或者用户,使用内核将变得很容易。 - -## helm repo add 添加仓库 - -```bash -helm repo add bitnami https://charts.bitnami.com/bitnami -``` - -添加仓库对应创建 `Repository` 资源 - -```yaml -apiVersion: core.kubebb.k8s.com.cn/v1alpha1 -kind: Repository -metadata: - name: bitnami -spec: - url: https://charts.bitnami.com/bitnami -``` - -## helm install 安装 chart - -```bash -cat << EOF > values.yaml -replicaCount: 2 -EOF - -helm install nginx bitnami/nginx --version 15.0.2 -f values.yaml --set image.registry=ddd.ccc -``` - -安装 Chart 对应创建 `ComponentPlan` 资源。 - -```yaml -apiVersion: core.kubebb.k8s.com.cn/v1alpha1 -kind: ComponentPlan -metadata: - name: nginx -spec: - approved: true - component: - name: bitnami.nginx - namespace: default - name: nginx - override: - valuesFrom: - - kind: ConfigMap - name: nginx - valuesKey: values.yaml - set: - - image.registry=ddd.ccc - version: 15.0.2 ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: nginx -data: - values.yaml: | - replicaCount: 2 -``` - -## helm upgrade 更新版本 - -```bash -helm upgrade nginx bitnami/nginx --set image.registry=docker.io -``` - -升级版本,这里有 2 个方法: - -1. 用新的配置创建一个 `ComponentPlan`,只要保证 `metadata.namespace`(对应 `helm release` 的 `namespace`)和 `spec.name`(对应 `helm release` 的 `name`)一致,就会升级对应的 `helm release`。 -2. 在原来的 `ComponentPlan` 基础上修改。相比较前者,这种方式不会保留历史,更灵活。前一种方式可以进行回滚。 - -## helm uninstall 删除 release - -```bash -helm uninstall nginx -``` - -删除 release,对应删除 `ComponentPlan`。因为 `ComponentPlan` 和 `helm release` 的关系是可以多对一,要注意,需要删除 `status.latest` 为 `True`(表明当前 `ComponentPlan` 对应 `helm release` 的最新版本)或者 `status.installedRevision` 和当前 `helm release` 版本一致的 `Componentplan` - -## helm rollback 回滚 release - -```bash -helm rollback nginx 1 -``` - -回滚,只需要在想要回滚到的 `ComponentPlan` 上增加一个 label:`core.kubebb.k8s.com.cn/rollback: ture` 即可。 diff --git a/docs/develop-guid/_category_.json b/docs/develop-guid/_category_.json new file mode 100644 index 000000000..e6a15e6a6 --- /dev/null +++ b/docs/develop-guid/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "开发指南", + "position": 4 +} \ No newline at end of file diff --git a/docs/building-base/_category_.json b/docs/develop-guid/building-base/_category_.json similarity index 89% rename from docs/building-base/_category_.json rename to docs/develop-guid/building-base/_category_.json index 430b6b7ac..11a000e6c 100644 --- a/docs/building-base/_category_.json +++ b/docs/develop-guid/building-base/_category_.json @@ -1,6 +1,6 @@ { "label": "底座Kit", - "position": 4, + "position": 3, "link": { "type": "generated-index", "description": "提供底座服务,快速开始搭建服务门户" diff --git a/docs/building-base/add-cluster.md b/docs/develop-guid/building-base/add-cluster.md similarity index 92% rename from docs/building-base/add-cluster.md rename to docs/develop-guid/building-base/add-cluster.md index e636827ad..fe782b18d 100644 --- a/docs/building-base/add-cluster.md +++ b/docs/develop-guid/building-base/add-cluster.md @@ -14,7 +14,7 @@ export TOKENNAME=$(kubectl get serviceaccount/host-cluster-reader -n u4a-system kubectl get secret $TOKENNAME -n u4a-system -o jsonpath='{.data.token}' | base64 -d ``` -3. 登录管理平台,进入 “集群管理”,参考 [安装底座](../quick-start/buildingbase_quickstart.md),点击“添加集群”。 +3. 登录管理平台,进入 “集群管理”,参考 [安装底座](docs/quick-start/buildingbase_quickstart.md),点击“添加集群”。 4. 输入集群名称,按需修改集群后缀,这里使用“API Token”方式接入集群。 diff --git a/docs/building-base/configuration/3rd-party-account.md b/docs/develop-guid/building-base/configuration/3rd-party-account.md similarity index 100% rename from docs/building-base/configuration/3rd-party-account.md rename to docs/develop-guid/building-base/configuration/3rd-party-account.md diff --git a/docs/building-base/configuration/_category_.json b/docs/develop-guid/building-base/configuration/_category_.json similarity index 100% rename from docs/building-base/configuration/_category_.json rename to docs/develop-guid/building-base/configuration/_category_.json diff --git a/docs/building-base/configuration/audit-config.md b/docs/develop-guid/building-base/configuration/audit-config.md similarity index 98% rename from docs/building-base/configuration/audit-config.md rename to docs/develop-guid/building-base/configuration/audit-config.md index dce88b0de..59e447dc8 100644 --- a/docs/building-base/configuration/audit-config.md +++ b/docs/develop-guid/building-base/configuration/audit-config.md @@ -5,7 +5,7 @@ sidebar_position: 3 # 配置审计能力 :::tip -注意,审计功能依赖对审计日志的采集功能,需要在集群设置中配置日志服务 ElasticSearch 的地址,日志服务的配置参考[日志组件](../../component-market/logging.md) +注意,审计功能依赖对审计日志的采集功能,需要在集群设置中配置日志服务 ElasticSearch 的地址,日志服务的配置参考[日志组件](docs/component-market/logging.md) ::: 1、编辑 audit-policy.yaml 文件对审计进行配置,```kubectl edit cm audit-policy-conf -n u4a-system``` diff --git a/docs/building-base/configuration/customize-menu.md b/docs/develop-guid/building-base/configuration/customize-menu.md similarity index 100% rename from docs/building-base/configuration/customize-menu.md rename to docs/develop-guid/building-base/configuration/customize-menu.md diff --git a/docs/building-base/configuration/customize-portal.md b/docs/develop-guid/building-base/configuration/customize-portal.md similarity index 100% rename from docs/building-base/configuration/customize-portal.md rename to docs/develop-guid/building-base/configuration/customize-portal.md diff --git a/docs/building-base/configuration/images/19b4c83b8381c4f6c82d3526ccdbc309014fac7a9f1f502854b9c6251eea03be.png b/docs/develop-guid/building-base/configuration/images/19b4c83b8381c4f6c82d3526ccdbc309014fac7a9f1f502854b9c6251eea03be.png similarity index 100% rename from docs/building-base/configuration/images/19b4c83b8381c4f6c82d3526ccdbc309014fac7a9f1f502854b9c6251eea03be.png rename to docs/develop-guid/building-base/configuration/images/19b4c83b8381c4f6c82d3526ccdbc309014fac7a9f1f502854b9c6251eea03be.png diff --git a/docs/building-base/configuration/images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png b/docs/develop-guid/building-base/configuration/images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png similarity index 100% rename from docs/building-base/configuration/images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png rename to docs/develop-guid/building-base/configuration/images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png diff --git a/docs/building-base/configuration/images/73946089d53ccbedf6b6c58cbb6cb8c55e3bd650bc3beede41ea1622211d02bd.png b/docs/develop-guid/building-base/configuration/images/73946089d53ccbedf6b6c58cbb6cb8c55e3bd650bc3beede41ea1622211d02bd.png similarity index 100% rename from docs/building-base/configuration/images/73946089d53ccbedf6b6c58cbb6cb8c55e3bd650bc3beede41ea1622211d02bd.png rename to docs/develop-guid/building-base/configuration/images/73946089d53ccbedf6b6c58cbb6cb8c55e3bd650bc3beede41ea1622211d02bd.png diff --git a/docs/building-base/configuration/images/7ef885f51a16d83577089c409efafa2583f60d9376d5efc7d03cb7faa4092fbf.png b/docs/develop-guid/building-base/configuration/images/7ef885f51a16d83577089c409efafa2583f60d9376d5efc7d03cb7faa4092fbf.png similarity index 100% rename from docs/building-base/configuration/images/7ef885f51a16d83577089c409efafa2583f60d9376d5efc7d03cb7faa4092fbf.png rename to docs/develop-guid/building-base/configuration/images/7ef885f51a16d83577089c409efafa2583f60d9376d5efc7d03cb7faa4092fbf.png diff --git a/docs/building-base/configuration/images/94ca51f03578085968c8e1ffd03f27606ed0d473e32d5eb511feff0513e4ff11.png b/docs/develop-guid/building-base/configuration/images/94ca51f03578085968c8e1ffd03f27606ed0d473e32d5eb511feff0513e4ff11.png similarity index 100% rename from docs/building-base/configuration/images/94ca51f03578085968c8e1ffd03f27606ed0d473e32d5eb511feff0513e4ff11.png rename to docs/develop-guid/building-base/configuration/images/94ca51f03578085968c8e1ffd03f27606ed0d473e32d5eb511feff0513e4ff11.png diff --git a/docs/building-base/configuration/issue-oidc-proxy-certs.md b/docs/develop-guid/building-base/configuration/issue-oidc-proxy-certs.md similarity index 100% rename from docs/building-base/configuration/issue-oidc-proxy-certs.md rename to docs/develop-guid/building-base/configuration/issue-oidc-proxy-certs.md diff --git a/docs/building-base/configuration/oidc-integration.md b/docs/develop-guid/building-base/configuration/oidc-integration.md similarity index 100% rename from docs/building-base/configuration/oidc-integration.md rename to docs/develop-guid/building-base/configuration/oidc-integration.md diff --git a/docs/building-base/images/dev_arch.png b/docs/develop-guid/building-base/images/dev_arch.png similarity index 100% rename from docs/building-base/images/dev_arch.png rename to docs/develop-guid/building-base/images/dev_arch.png diff --git a/docs/building-base/intro.md b/docs/develop-guid/building-base/intro.md similarity index 100% rename from docs/building-base/intro.md rename to docs/develop-guid/building-base/intro.md diff --git a/docs/component-market/_category_.json b/docs/develop-guid/component-market/_category_.json similarity index 100% rename from docs/component-market/_category_.json rename to docs/develop-guid/component-market/_category_.json diff --git a/docs/component-market/blockchain.md b/docs/develop-guid/component-market/blockchain.md similarity index 100% rename from docs/component-market/blockchain.md rename to docs/develop-guid/component-market/blockchain.md diff --git a/docs/component-market/kubedashboard.md b/docs/develop-guid/component-market/kubedashboard.md similarity index 100% rename from docs/component-market/kubedashboard.md rename to docs/develop-guid/component-market/kubedashboard.md diff --git a/docs/component-market/kubelogin.md b/docs/develop-guid/component-market/kubelogin.md similarity index 100% rename from docs/component-market/kubelogin.md rename to docs/develop-guid/component-market/kubelogin.md diff --git a/docs/component-market/logging.md b/docs/develop-guid/component-market/logging.md similarity index 100% rename from docs/component-market/logging.md rename to docs/develop-guid/component-market/logging.md diff --git a/docs/component-market/monitoring.md b/docs/develop-guid/component-market/monitoring.md similarity index 100% rename from docs/component-market/monitoring.md rename to docs/develop-guid/component-market/monitoring.md diff --git a/docs/core/_category_.json b/docs/develop-guid/core/_category_.json similarity index 87% rename from docs/core/_category_.json rename to docs/develop-guid/core/_category_.json index 0305f9d16..8d726ccf5 100644 --- a/docs/core/_category_.json +++ b/docs/develop-guid/core/_category_.json @@ -1,6 +1,6 @@ { "label": "内核Kit", - "position": 3, + "position": 2, "link": { "type": "generated-index", "description": "管理组件生命周期" diff --git a/docs/core/concepts/_category_.json b/docs/develop-guid/core/concepts/_category_.json similarity index 100% rename from docs/core/concepts/_category_.json rename to docs/develop-guid/core/concepts/_category_.json diff --git a/docs/core/concepts/buildingbase_resources.md b/docs/develop-guid/core/concepts/buildingbase_resources.md similarity index 100% rename from docs/core/concepts/buildingbase_resources.md rename to docs/develop-guid/core/concepts/buildingbase_resources.md diff --git a/docs/core/concepts/component.md b/docs/develop-guid/core/concepts/component.md similarity index 100% rename from docs/core/concepts/component.md rename to docs/develop-guid/core/concepts/component.md diff --git a/docs/core/concepts/componentplan.md b/docs/develop-guid/core/concepts/componentplan.md similarity index 99% rename from docs/core/concepts/componentplan.md rename to docs/develop-guid/core/concepts/componentplan.md index 73c0e5372..7a44c0679 100644 --- a/docs/core/concepts/componentplan.md +++ b/docs/develop-guid/core/concepts/componentplan.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- # 组件部署 diff --git a/docs/core/userguide/imageoverride.md b/docs/develop-guid/core/concepts/imageoverride.md similarity index 99% rename from docs/core/userguide/imageoverride.md rename to docs/develop-guid/core/concepts/imageoverride.md index cb0a68eb8..ee19ebe62 100644 --- a/docs/core/userguide/imageoverride.md +++ b/docs/develop-guid/core/concepts/imageoverride.md @@ -1,7 +1,7 @@ --- sidebar_position: 3 --- -# “镜像替换”功能的完整说明 +# 镜像替换 ## 介绍 diff --git a/docs/core/concepts/rating.md b/docs/develop-guid/core/concepts/rating.md similarity index 100% rename from docs/core/concepts/rating.md rename to docs/develop-guid/core/concepts/rating.md diff --git a/docs/core/concepts/repository.md b/docs/develop-guid/core/concepts/repository.md similarity index 100% rename from docs/core/concepts/repository.md rename to docs/develop-guid/core/concepts/repository.md diff --git a/docs/core/concepts/subscription.md b/docs/develop-guid/core/concepts/subscription.md similarity index 100% rename from docs/core/concepts/subscription.md rename to docs/develop-guid/core/concepts/subscription.md diff --git a/docs/core/images/componentplan-helm-release.excalidraw b/docs/develop-guid/core/images/componentplan-helm-release.excalidraw similarity index 100% rename from docs/core/images/componentplan-helm-release.excalidraw rename to docs/develop-guid/core/images/componentplan-helm-release.excalidraw diff --git a/docs/core/images/componentplan-helm-release.png b/docs/develop-guid/core/images/componentplan-helm-release.png similarity index 100% rename from docs/core/images/componentplan-helm-release.png rename to docs/develop-guid/core/images/componentplan-helm-release.png diff --git a/docs/core/images/image-changed.excalidraw b/docs/develop-guid/core/images/image-changed.excalidraw similarity index 100% rename from docs/core/images/image-changed.excalidraw rename to docs/develop-guid/core/images/image-changed.excalidraw diff --git a/docs/core/images/image-changed.png b/docs/develop-guid/core/images/image-changed.png similarity index 100% rename from docs/core/images/image-changed.png rename to docs/develop-guid/core/images/image-changed.png diff --git a/docs/core/images/rating_flow.drawio.png b/docs/develop-guid/core/images/rating_flow.drawio.png similarity index 100% rename from docs/core/images/rating_flow.drawio.png rename to docs/develop-guid/core/images/rating_flow.drawio.png diff --git a/docs/core/intro.md b/docs/develop-guid/core/intro.md similarity index 100% rename from docs/core/intro.md rename to docs/develop-guid/core/intro.md diff --git a/docs/core/userguide/_category_.json b/docs/develop-guid/core/rating/_category_.json similarity index 54% rename from docs/core/userguide/_category_.json rename to docs/develop-guid/core/rating/_category_.json index 3f3f4eac1..5a5048135 100644 --- a/docs/core/userguide/_category_.json +++ b/docs/develop-guid/core/rating/_category_.json @@ -1,8 +1,8 @@ { - "label": "用户指南", + "label": "组件评测", "position": 3, "link": { "type": "generated-index", - "description": "用户指南" + "description": "组件评测" } } \ No newline at end of file diff --git a/docs/core/userguide/enablerating.md b/docs/develop-guid/core/rating/enablerating.md similarity index 98% rename from docs/core/userguide/enablerating.md rename to docs/develop-guid/core/rating/enablerating.md index dd76ff175..0013c6bca 100644 --- a/docs/core/userguide/enablerating.md +++ b/docs/develop-guid/core/rating/enablerating.md @@ -2,12 +2,12 @@ sidebar_position: 1 --- -# 启用Rating +# 快速部署 默认情况下,Rating组件评级功能是关闭的,需要手动启用。我们建议按照以下步骤启用Rating: :::tip -详细了解更多Rating有关内容,请参考[组件评级设计](../rating)和[Rating CRD定义](../concepts/rating) +详细了解更多Rating有关内容,请参考[组件评测设计](../rating)和[Rating CRD定义](../concepts/rating) ::: **Rating**依赖两个组件,分别是: diff --git a/docs/core/rating.md b/docs/develop-guid/core/rating/rating.md similarity index 99% rename from docs/core/rating.md rename to docs/develop-guid/core/rating/rating.md index 0ff721e24..22cef8b4f 100644 --- a/docs/core/rating.md +++ b/docs/develop-guid/core/rating/rating.md @@ -1,8 +1,8 @@ --- -sidebar_position: 4 +sidebar_position: 2 --- -# 组件评测 +# 功能介绍 **组件评测**的目的是通过尽可能多的自动化测试从多个维度来评估一个组件。因此,**组件评测**三个部分的内容: diff --git a/docs/images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png b/docs/develop-guid/images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png similarity index 100% rename from docs/images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png rename to docs/develop-guid/images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png diff --git a/docs/images/component-lifecycle.drawio.png b/docs/develop-guid/images/component-lifecycle.drawio.png similarity index 100% rename from docs/images/component-lifecycle.drawio.png rename to docs/develop-guid/images/component-lifecycle.drawio.png diff --git a/docs/images/kubebb_overview.drawio.png b/docs/develop-guid/images/kubebb_overview.drawio.png similarity index 100% rename from docs/images/kubebb_overview.drawio.png rename to docs/develop-guid/images/kubebb_overview.drawio.png diff --git a/docs/images/kubebb_portal.png b/docs/develop-guid/images/kubebb_portal.png similarity index 100% rename from docs/images/kubebb_portal.png rename to docs/develop-guid/images/kubebb_portal.png diff --git a/docs/images/lowcode-development.png b/docs/develop-guid/images/lowcode-development.png similarity index 100% rename from docs/images/lowcode-development.png rename to docs/develop-guid/images/lowcode-development.png diff --git a/docs/develop-guid/intro.md b/docs/develop-guid/intro.md new file mode 100644 index 000000000..f5a69e12e --- /dev/null +++ b/docs/develop-guid/intro.md @@ -0,0 +1,104 @@ +--- +sidebar_position: 1 +--- + +# 总览 + +KubeBB(Kubernetes Building Blocks)是一种由[**内核**](./core/intro)驱动的组件生命周期管理平台,集成开箱即用的[**云原生底座**](./building-base/intro)和[**低码组件开发**](./lowcode-development/intro)能力,整合实现[**云原生三层组件模式**](./lowcode-development/development_pattern)。 + +![overview](./images/kubebb_overview.drawio.png) + +Kubebb提供三个**套件**: + +- [**内核 Kit**](./core/intro) + +提供**声明式的组件生命周期管理和组件市场**,并通过**Tekton流水线**强化低代码平台组件与底座服务的集成。 + +- [**底座 Kit**](./building-base/intro) + +提供开箱即用的云原生服务门户,包括**用户、OIDC认证、权限、审计、租户管理、门户服务等基础组件以及证书管理、Nignx Ingress**等集群组件。 + +- [**低码 Kit**](./lowcode-development/intro) + +低码 Kit 即云梯低代码平台,依托 [**Low-Code Engine**](https://lowcode-engine.cn/index) 和具有 Git 特性的关系数据库 [**Dolt**](https://www.dolthub.com/) 打造,并借助底座门户的**菜单和路由资源**以及内核套件的**组件管理**能力,实现组件开发、测试到上线的全链路能力。 + +三个核心套件之间的关系可以类比一下**操作系统**: + +- **Kubernetes** ~ **操作系统内核** +- **Core** ~ **软件安装器** +- **底座Kit** ~ **操作系统的系统软件,如GUI、用户系统、网络等** +- **低码组件开发Kit** ~ **操作系统软件开发工具** + +## 内核Kit + +**内核Kit**的是现阶段我们重点关注并研发的[**项目**](https://github.com/kubebb/core),完全遵循开源项目管理规范。现阶段我们的目标: + +### 1. 声明式的组件全生命周期管理 + +基于[**Operator Pattern**](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)开发,实现声明式的组件全生命周期管理。 + +![component-lifecycle](./images/component-lifecycle.drawio.png) + +#### 提供四个核心的CRD实现: + +- [**Repository组件仓库**](./core/concepts/repository) + +定义了组件仓库的访问信息、轮询策略和过滤选项,从而实现周期性地向仓库服务获取最新的组件列表信息。 + +- [**Component组件**](./core/concepts/component) + +记录组件的基础描述、版本列表、是否废弃等信息 + +- [**ComponentPlan组件部署**](./core/concepts/componentplan) + +定义组件安装部署的手动批准、组件引用、版本设置、类helm的配置覆盖策略,从而实现组件的可追踪部署、升级和回滚。 + +- [**Subscription组件订阅**](./core/concepts/subscription) + +定义了用户订阅组件版本更新 + +#### 一个扩展CRD实现,集成[**Tekton Pipeline**](https://tekton.dev/): + +- [**Rating组件评级**](./core/rating) + +### 2. 开放组件市场 + +组件市场是内核能力的**产品化**,作为一个适配**底座服务的组件**发布到官方组件仓库中使用,扩展KubeBB生态。 + +## 底座Kit + +**底座Kit**通过集成以下组件从而提供统一的认证中心和门户入口: + +- `u4a-component` 提供账号、认证、权限及审计管理功能,包含以下主要资料 + - [nginx ingress](https://docs.nginx.com/nginx-ingress-controller/) + - [cert-manager](https://cert-manager.io/) + - [基于 dex 构建](https://github.com/dexidp/dex) + - [多租户基于 capsule 构建](https://github.com/clastix/capsule) + - [oidc-proxy 基于 kube-oidc-proxy 构建](https://github.com/jetstack/kube-oidc-proxy) + +![portal](./images/kubebb_portal.png) + +## 低码 Kit + +**低码 Kit**提供[**三层组件开发模式**](./lowcode-development/development_pattern)中的[**前端模块研发**](./lowcode-development/development/frontend)、出码能力,并借助**内核 Kit**完成标准化打包、测试、发布,后续 BFF 层也会探索低码的开发模式。 + +![lowcode_development](./images/lowcode-development.png) + +## 技术架构 +平台开发采取前后端分离,以 K8S 为核心的开发框架,遵循 K8S 的扩展机制及 API 规范,整体开发架构的基本逻辑如下图所示: +![图 2](images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png) + +1. 所有组件的开发、扩展的认证都通过统一认证中心进行认证 +2. 认证由微前端的主框架 DockApp 统一进行,其他微前端的扩展不需要单独支持同认证中心的处理 +3. 开发架构上整体可以按照三层来看 +- 第一层,前端采用微前端架构,尽量采用低代码方式进行开发,提高代码自动化生成比例 +- 第二层,根据业务需求增加 OpenAPI,形成统一的 BFF 层,对 API 进行聚合,提供前端所需要的业务场景数据 +- 后端采用 CRD + controller 的 Operator 模式进行开发,形成数据驱动的流程开发模式 +1. 对外 API 主要包括两部分: +- 从 BFF 层提供的 OpenAPI +- 从 K8S 层提供的资源 API + +## 获取更多组件 +浏览 [组件市场](/docs/category/组件市场),安装更多需要的服务组件到门户中,比如: +* [kubedashboard](/docs/component-market/kubedashboard) +* [kubelogin](/docs/component-market/kubelogin) diff --git a/docs/lowcode-development/_category_.json b/docs/develop-guid/lowcode-development/_category_.json similarity index 91% rename from docs/lowcode-development/_category_.json rename to docs/develop-guid/lowcode-development/_category_.json index 8903d671e..ee68f00bc 100644 --- a/docs/lowcode-development/_category_.json +++ b/docs/develop-guid/lowcode-development/_category_.json @@ -1,6 +1,6 @@ { "label": "低码 Kit", - "position": 5, + "position": 4, "link": { "type": "generated-index", "description": "可使用低码 Kit 开发自己服务组件,并添加到服务门户中。" diff --git a/docs/lowcode-development/development/_category_.json b/docs/develop-guid/lowcode-development/development/_category_.json similarity index 100% rename from docs/lowcode-development/development/_category_.json rename to docs/develop-guid/lowcode-development/development/_category_.json diff --git a/docs/lowcode-development/development/bff-apis.md b/docs/develop-guid/lowcode-development/development/bff-apis.md similarity index 100% rename from docs/lowcode-development/development/bff-apis.md rename to docs/develop-guid/lowcode-development/development/bff-apis.md diff --git a/docs/lowcode-development/development/develop-hello-world.md b/docs/develop-guid/lowcode-development/development/develop-hello-world.md similarity index 100% rename from docs/lowcode-development/development/develop-hello-world.md rename to docs/develop-guid/lowcode-development/development/develop-hello-world.md diff --git a/docs/lowcode-development/development/frontend-low-code.md b/docs/develop-guid/lowcode-development/development/frontend-low-code.md similarity index 100% rename from docs/lowcode-development/development/frontend-low-code.md rename to docs/develop-guid/lowcode-development/development/frontend-low-code.md diff --git a/docs/lowcode-development/development/frontend.md b/docs/develop-guid/lowcode-development/development/frontend.md similarity index 100% rename from docs/lowcode-development/development/frontend.md rename to docs/develop-guid/lowcode-development/development/frontend.md diff --git a/docs/lowcode-development/development/images/app-publish.png b/docs/develop-guid/lowcode-development/development/images/app-publish.png similarity index 100% rename from docs/lowcode-development/development/images/app-publish.png rename to docs/develop-guid/lowcode-development/development/images/app-publish.png diff --git a/docs/lowcode-development/development/images/app_create.png b/docs/develop-guid/lowcode-development/development/images/app_create.png similarity index 100% rename from docs/lowcode-development/development/images/app_create.png rename to docs/develop-guid/lowcode-development/development/images/app_create.png diff --git a/docs/lowcode-development/development/images/app_publish_tab.png b/docs/develop-guid/lowcode-development/development/images/app_publish_tab.png similarity index 100% rename from docs/lowcode-development/development/images/app_publish_tab.png rename to docs/develop-guid/lowcode-development/development/images/app_publish_tab.png diff --git a/docs/lowcode-development/development/images/assets_component_add.png b/docs/develop-guid/lowcode-development/development/images/assets_component_add.png similarity index 100% rename from docs/lowcode-development/development/images/assets_component_add.png rename to docs/develop-guid/lowcode-development/development/images/assets_component_add.png diff --git a/docs/lowcode-development/development/images/assets_npm_add.png b/docs/develop-guid/lowcode-development/development/images/assets_npm_add.png similarity index 100% rename from docs/lowcode-development/development/images/assets_npm_add.png rename to docs/develop-guid/lowcode-development/development/images/assets_npm_add.png diff --git a/docs/lowcode-development/development/images/assets_npm_bff.png b/docs/develop-guid/lowcode-development/development/images/assets_npm_bff.png similarity index 100% rename from docs/lowcode-development/development/images/assets_npm_bff.png rename to docs/develop-guid/lowcode-development/development/images/assets_npm_bff.png diff --git a/docs/lowcode-development/development/images/bff_lowcode.drawio b/docs/develop-guid/lowcode-development/development/images/bff_lowcode.drawio similarity index 100% rename from docs/lowcode-development/development/images/bff_lowcode.drawio rename to docs/develop-guid/lowcode-development/development/images/bff_lowcode.drawio diff --git a/docs/lowcode-development/development/images/bff_lowcode.png b/docs/develop-guid/lowcode-development/development/images/bff_lowcode.png similarity index 100% rename from docs/lowcode-development/development/images/bff_lowcode.png rename to docs/develop-guid/lowcode-development/development/images/bff_lowcode.png diff --git a/docs/lowcode-development/development/images/branches_create.png b/docs/develop-guid/lowcode-development/development/images/branches_create.png similarity index 100% rename from docs/lowcode-development/development/images/branches_create.png rename to docs/develop-guid/lowcode-development/development/images/branches_create.png diff --git a/docs/lowcode-development/development/images/fe_arch.svg b/docs/develop-guid/lowcode-development/development/images/fe_arch.svg similarity index 100% rename from docs/lowcode-development/development/images/fe_arch.svg rename to docs/develop-guid/lowcode-development/development/images/fe_arch.svg diff --git a/docs/lowcode-development/development/images/git-commit.png b/docs/develop-guid/lowcode-development/development/images/git-commit.png similarity index 100% rename from docs/lowcode-development/development/images/git-commit.png rename to docs/develop-guid/lowcode-development/development/images/git-commit.png diff --git a/docs/lowcode-development/development/images/global_add_func.png b/docs/develop-guid/lowcode-development/development/images/global_add_func.png similarity index 100% rename from docs/lowcode-development/development/images/global_add_func.png rename to docs/develop-guid/lowcode-development/development/images/global_add_func.png diff --git a/docs/lowcode-development/development/images/global_config.png b/docs/develop-guid/lowcode-development/development/images/global_config.png similarity index 100% rename from docs/lowcode-development/development/images/global_config.png rename to docs/develop-guid/lowcode-development/development/images/global_config.png diff --git a/docs/lowcode-development/development/images/members_create.png b/docs/develop-guid/lowcode-development/development/images/members_create.png similarity index 100% rename from docs/lowcode-development/development/images/members_create.png rename to docs/develop-guid/lowcode-development/development/images/members_create.png diff --git a/docs/lowcode-development/development/images/menu_create.png b/docs/develop-guid/lowcode-development/development/images/menu_create.png similarity index 100% rename from docs/lowcode-development/development/images/menu_create.png rename to docs/develop-guid/lowcode-development/development/images/menu_create.png diff --git a/docs/lowcode-development/development/images/page_add_api.png b/docs/develop-guid/lowcode-development/development/images/page_add_api.png similarity index 100% rename from docs/lowcode-development/development/images/page_add_api.png rename to docs/develop-guid/lowcode-development/development/images/page_add_api.png diff --git a/docs/lowcode-development/development/images/page_add_func.png b/docs/develop-guid/lowcode-development/development/images/page_add_func.png similarity index 100% rename from docs/lowcode-development/development/images/page_add_func.png rename to docs/develop-guid/lowcode-development/development/images/page_add_func.png diff --git a/docs/lowcode-development/development/images/page_bind_data.png b/docs/develop-guid/lowcode-development/development/images/page_bind_data.png similarity index 100% rename from docs/lowcode-development/development/images/page_bind_data.png rename to docs/develop-guid/lowcode-development/development/images/page_bind_data.png diff --git a/docs/lowcode-development/development/images/page_bind_func.png b/docs/develop-guid/lowcode-development/development/images/page_bind_func.png similarity index 100% rename from docs/lowcode-development/development/images/page_bind_func.png rename to docs/develop-guid/lowcode-development/development/images/page_bind_func.png diff --git a/docs/lowcode-development/development/images/page_code.png b/docs/develop-guid/lowcode-development/development/images/page_code.png similarity index 100% rename from docs/lowcode-development/development/images/page_code.png rename to docs/develop-guid/lowcode-development/development/images/page_code.png diff --git a/docs/lowcode-development/development/images/page_commit.png b/docs/develop-guid/lowcode-development/development/images/page_commit.png similarity index 100% rename from docs/lowcode-development/development/images/page_commit.png rename to docs/develop-guid/lowcode-development/development/images/page_commit.png diff --git a/docs/lowcode-development/development/images/page_create.png b/docs/develop-guid/lowcode-development/development/images/page_create.png similarity index 100% rename from docs/lowcode-development/development/images/page_create.png rename to docs/develop-guid/lowcode-development/development/images/page_create.png diff --git a/docs/lowcode-development/development/images/page_edit.png b/docs/develop-guid/lowcode-development/development/images/page_edit.png similarity index 100% rename from docs/lowcode-development/development/images/page_edit.png rename to docs/develop-guid/lowcode-development/development/images/page_edit.png diff --git a/docs/lowcode-development/development/images/page_edit_props.png b/docs/develop-guid/lowcode-development/development/images/page_edit_props.png similarity index 100% rename from docs/lowcode-development/development/images/page_edit_props.png rename to docs/develop-guid/lowcode-development/development/images/page_edit_props.png diff --git a/docs/lowcode-development/development/images/page_entry.png b/docs/develop-guid/lowcode-development/development/images/page_entry.png similarity index 100% rename from docs/lowcode-development/development/images/page_entry.png rename to docs/develop-guid/lowcode-development/development/images/page_entry.png diff --git a/docs/lowcode-development/development/images/page_preview.png b/docs/develop-guid/lowcode-development/development/images/page_preview.png similarity index 100% rename from docs/lowcode-development/development/images/page_preview.png rename to docs/develop-guid/lowcode-development/development/images/page_preview.png diff --git a/docs/lowcode-development/development/images/playground_graphql.jpg b/docs/develop-guid/lowcode-development/development/images/playground_graphql.jpg similarity index 100% rename from docs/lowcode-development/development/images/playground_graphql.jpg rename to docs/develop-guid/lowcode-development/development/images/playground_graphql.jpg diff --git a/docs/lowcode-development/development_pattern.md b/docs/develop-guid/lowcode-development/development_pattern.md similarity index 100% rename from docs/lowcode-development/development_pattern.md rename to docs/develop-guid/lowcode-development/development_pattern.md diff --git a/docs/lowcode-development/images/dev_arch.png b/docs/develop-guid/lowcode-development/images/dev_arch.png similarity index 100% rename from docs/lowcode-development/images/dev_arch.png rename to docs/develop-guid/lowcode-development/images/dev_arch.png diff --git a/docs/lowcode-development/images/yunti_arch.svg b/docs/develop-guid/lowcode-development/images/yunti_arch.svg similarity index 100% rename from docs/lowcode-development/images/yunti_arch.svg rename to docs/develop-guid/lowcode-development/images/yunti_arch.svg diff --git a/docs/lowcode-development/intro.md b/docs/develop-guid/lowcode-development/intro.md similarity index 100% rename from docs/lowcode-development/intro.md rename to docs/develop-guid/lowcode-development/intro.md diff --git a/docs/core/userguide/privatecluster.md b/docs/develop-guid/privatecluster.md similarity index 99% rename from docs/core/userguide/privatecluster.md rename to docs/develop-guid/privatecluster.md index 49e692647..63cf879f5 100644 --- a/docs/core/userguide/privatecluster.md +++ b/docs/develop-guid/privatecluster.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 5 --- # 私有集群部署方案 diff --git a/docs/user-guid/image/struc.png b/docs/images/struc.png similarity index 100% rename from docs/user-guid/image/struc.png rename to docs/images/struc.png diff --git a/docs/intro.md b/docs/intro.md index f5a69e12e..9d1edebc7 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -1,104 +1,70 @@ --- sidebar_position: 1 +title: 产品介绍 +sidebar_label: 产品介绍 --- -# 总览 -KubeBB(Kubernetes Building Blocks)是一种由[**内核**](./core/intro)驱动的组件生命周期管理平台,集成开箱即用的[**云原生底座**](./building-base/intro)和[**低码组件开发**](./lowcode-development/intro)能力,整合实现[**云原生三层组件模式**](./lowcode-development/development_pattern)。 +# 产品介绍 + +Kubebb(Kubernetes Building Blocks) 是一种由内核驱动的组件生命周期管理平台,集成了开箱即用的云原生底座和低码组件开发能力。 + +- **提供底座服务,快速开启搭建**:提供账号、认证(OIDC)、权限(RBAC)、审计(Audit)的基础功能,采用更加标准的技术方式提供构建的底座服务 +- **内核驱动的声明式组件管理**:提供声明式的组件仓库管理、组件同步、组件订阅、部署以及多维度的组件评级,完整适配 Helm 生态,集成微前端框架 +- **灵活的组件开发模式**:基于微前端框架和低代码开发,定义了标准的组件封装及发布模式,让开发者可以在底座之上按照开发规范进行组件的快速开发和发布,并在统一的服务门户上对外提供服务 + +官方提供的组件包括微服务治理、服务网格、API网关、应用性能监控的开源社区版本,详细介绍参见[**开源文档**](https://docs.tenxcloud.com/) + +## 功能说明 + +Kubebb 部署后主要有管理工作台、组件市场两部分能力。管理工作台用户指南详见[管理工作台](https://docs.tenxcloud.com/) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
模块说明
组件市场组件市场组件的商店,支持浏览、订阅、下载、安装组件
组件管理1. 我发布的:支持手动发布组件到仓库;支持发布多版本
2. 我安装的:支持安装、更新、卸载组件;支持历史版本管理和版本回滚
3. 我订阅的:支持订阅、取消订阅组件;支持版本更新推送
组件仓库管理1. 支持添加、编辑、删除组件仓库
2. 支持配置仓库安全认证、仓库同步设置、仓库组件过滤规则、镜像仓库替换规则、开启组件评测等
组件评测使用智能 AI 对组件从安全性、可靠性、可用性三方面进行综合评测,为您的选择提供参考数据
管理工作台集群管理1. 多集群统一视图管理
2. 资源管理:分内置和自定义资源,各资源支持yaml方式查看编辑
3. 集群角色和角色模板管理:集群角色支持绑定角色主体有成员、组和服务账号,均支持yaml方式查看和编辑
租户和项目管理1. 多租户、多项目统一视图管理:查看租户或项目标签、授权集群等
2. 租户授权集群,设置租户管理员
3. 项目授权集群,设置项目管理员
4. 项目内角色和成员管理、项目内服务账号管理
5. 对应资源均支持yaml方式编辑
主体管理管理成员和组:创建、查看、删除成员;修改成员密码;创建、查看、删除组,组内加入或移出成员
菜单管理1. 多级菜单管理,支持管理菜单名称、图标、行列排序、路径等
2. 支持默认、iframe嵌入、链接跳转三种类型的菜单样式
3. 支持设置是否可见;设置菜单的角色权限等
4. 支持使用JSON格式的菜单数据实现更多自定义菜单配置
设置管理1. 账户中心,支持查看编辑手机、邮箱;修改密码等;支持查看所属租户项目
2. 平台信息:查看正版授权信息、更新许可证等
3. API 凭证,支持查看、下载Kubeconfig
操作审计统一查看对资源的操作记录,支持租户、项目、集群、操作类型、状态、发起者等过滤查询
+ + + +## 应用场景 + +### 快速搭建您的云原生平台 + +Kubebb 提供了多集群多租户管理、菜单管理、角色和成员管理、OIDC 认证等完善的平台基础能力。内置官方组件,通过云梯低代码组件可快速发布您的应用;通过微服务框架或服务网格统一管理和治理您的应用;通过应用性能监控统一观测服务调用,设置链路告警。同时您可发布自定义组件,例如容器服务组件,形成应用的全生命周期的管理和治理。 +![overview](./images/struc.png) -![overview](./images/kubebb_overview.drawio.png) - -Kubebb提供三个**套件**: - -- [**内核 Kit**](./core/intro) - -提供**声明式的组件生命周期管理和组件市场**,并通过**Tekton流水线**强化低代码平台组件与底座服务的集成。 - -- [**底座 Kit**](./building-base/intro) - -提供开箱即用的云原生服务门户,包括**用户、OIDC认证、权限、审计、租户管理、门户服务等基础组件以及证书管理、Nignx Ingress**等集群组件。 - -- [**低码 Kit**](./lowcode-development/intro) - -低码 Kit 即云梯低代码平台,依托 [**Low-Code Engine**](https://lowcode-engine.cn/index) 和具有 Git 特性的关系数据库 [**Dolt**](https://www.dolthub.com/) 打造,并借助底座门户的**菜单和路由资源**以及内核套件的**组件管理**能力,实现组件开发、测试到上线的全链路能力。 - -三个核心套件之间的关系可以类比一下**操作系统**: - -- **Kubernetes** ~ **操作系统内核** -- **Core** ~ **软件安装器** -- **底座Kit** ~ **操作系统的系统软件,如GUI、用户系统、网络等** -- **低码组件开发Kit** ~ **操作系统软件开发工具** - -## 内核Kit - -**内核Kit**的是现阶段我们重点关注并研发的[**项目**](https://github.com/kubebb/core),完全遵循开源项目管理规范。现阶段我们的目标: - -### 1. 声明式的组件全生命周期管理 - -基于[**Operator Pattern**](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)开发,实现声明式的组件全生命周期管理。 - -![component-lifecycle](./images/component-lifecycle.drawio.png) - -#### 提供四个核心的CRD实现: - -- [**Repository组件仓库**](./core/concepts/repository) - -定义了组件仓库的访问信息、轮询策略和过滤选项,从而实现周期性地向仓库服务获取最新的组件列表信息。 - -- [**Component组件**](./core/concepts/component) - -记录组件的基础描述、版本列表、是否废弃等信息 - -- [**ComponentPlan组件部署**](./core/concepts/componentplan) - -定义组件安装部署的手动批准、组件引用、版本设置、类helm的配置覆盖策略,从而实现组件的可追踪部署、升级和回滚。 - -- [**Subscription组件订阅**](./core/concepts/subscription) - -定义了用户订阅组件版本更新 - -#### 一个扩展CRD实现,集成[**Tekton Pipeline**](https://tekton.dev/): - -- [**Rating组件评级**](./core/rating) - -### 2. 开放组件市场 - -组件市场是内核能力的**产品化**,作为一个适配**底座服务的组件**发布到官方组件仓库中使用,扩展KubeBB生态。 - -## 底座Kit - -**底座Kit**通过集成以下组件从而提供统一的认证中心和门户入口: - -- `u4a-component` 提供账号、认证、权限及审计管理功能,包含以下主要资料 - - [nginx ingress](https://docs.nginx.com/nginx-ingress-controller/) - - [cert-manager](https://cert-manager.io/) - - [基于 dex 构建](https://github.com/dexidp/dex) - - [多租户基于 capsule 构建](https://github.com/clastix/capsule) - - [oidc-proxy 基于 kube-oidc-proxy 构建](https://github.com/jetstack/kube-oidc-proxy) - -![portal](./images/kubebb_portal.png) - -## 低码 Kit - -**低码 Kit**提供[**三层组件开发模式**](./lowcode-development/development_pattern)中的[**前端模块研发**](./lowcode-development/development/frontend)、出码能力,并借助**内核 Kit**完成标准化打包、测试、发布,后续 BFF 层也会探索低码的开发模式。 - -![lowcode_development](./images/lowcode-development.png) - -## 技术架构 -平台开发采取前后端分离,以 K8S 为核心的开发框架,遵循 K8S 的扩展机制及 API 规范,整体开发架构的基本逻辑如下图所示: -![图 2](images/6b8d0cb645caee89c8df55940f5c5b3379940f8714667f8fb2dc780f3442b8f0.png) - -1. 所有组件的开发、扩展的认证都通过统一认证中心进行认证 -2. 认证由微前端的主框架 DockApp 统一进行,其他微前端的扩展不需要单独支持同认证中心的处理 -3. 开发架构上整体可以按照三层来看 -- 第一层,前端采用微前端架构,尽量采用低代码方式进行开发,提高代码自动化生成比例 -- 第二层,根据业务需求增加 OpenAPI,形成统一的 BFF 层,对 API 进行聚合,提供前端所需要的业务场景数据 -- 后端采用 CRD + controller 的 Operator 模式进行开发,形成数据驱动的流程开发模式 -1. 对外 API 主要包括两部分: -- 从 BFF 层提供的 OpenAPI -- 从 K8S 层提供的资源 API - -## 获取更多组件 -浏览 [组件市场](/docs/category/组件市场),安装更多需要的服务组件到门户中,比如: -* [kubedashboard](/docs/component-market/kubedashboard) -* [kubelogin](/docs/component-market/kubelogin) diff --git a/docs/quick-start/buildingbase_quickstart.md b/docs/quick-start/buildingbase_quickstart.md deleted file mode 100644 index 6b9cb9524..000000000 --- a/docs/quick-start/buildingbase_quickstart.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -sidebar_position: 3 ---- - -# 安装底座 - -本章节主要介绍底座组件的部署步骤,包括相关的开源技术组件、前提条件以及快速部署,并将部署的集群添加到服务门户上。 - -:::tip -安装前需完成[安装内核](./core_quickstart)。 -::: - -## 部署 - -### 1. 创建官方组件仓库 - -> 可参考[使用官方组件仓库](./core_quickstart#%E4%BD%BF%E7%94%A8%E5%AE%98%E6%96%B9%E7%BB%84%E4%BB%B6%E4%BB%93%E5%BA%93) - -### 2. 创建底座组件空间 - -:::tip -目前仅支持使用命名空间`u4a-system` -::: - -```shell - kubectl create namespace u4a-system -``` - -### 3. 部署Cluster Component - -组件部署信息`cluster_componentplan.yaml`如下: - -> 详细可[参考](https://github.com/kubebb/components/tree/main/examples/cluster-component) - -```yaml -apiVersion: core.kubebb.k8s.com.cn/v1alpha1 -kind: ComponentPlan -metadata: - name: cluster-component - namespace: u4a-system -spec: - approved: true - name: cluster-component - version: 0.1.3 - override: - set: - - ingress-nginx.controller.nodeSelector.kubernetes\.io/hostname=kubebb-core-control-plane - component: - name: kubebb.cluster-component - namespace: kubebb-system -``` - -需调整参数: - -- `override.set.ingress-nginx.controller.nodeSelector.kubernetes\.io/hostname` 将作为[ingress-nginx](https://github.com/kubebb/components/tree/main/charts/cluster-component/charts/ingress-nginx)服务节点 - -> 此处基于[kind开发集群](./prerequisite#kind开发集群)的`kubebb-core-control-plane`节点。 - -通过一下命令部署: - -```shell - kubectl apply -nu4a-system -f cluster_componentplan.yaml -``` - -`Cluster Component`部署完成后,可通过以下命令查看组件部署状态: - -```shell - kubectl get componentplan -nu4a-system cluster-component -oyaml -``` - -当组件部署状态如下时,表示组件部署成功: - -```yaml -status: - conditions: - - lastTransitionTime: "2023-07-25T08:15:41Z" - reason: "" - status: "True" - type: Approved - - lastTransitionTime: "2023-07-25T08:15:44Z" - reason: InstallSuccess - status: "True" - type: Actioned - - lastTransitionTime: "2023-07-25T08:15:44Z" - reason: "" - status: "True" - type: Succeeded -``` - -### 4. 部署U4A Component - -组件部署信息`u4a_componentplan.yaml`如下: - -```yaml -apiVersion: core.kubebb.k8s.com.cn/v1alpha1 -kind: ComponentPlan -metadata: - name: u4a-component - namespace: u4a-system -spec: - approved: true - name: u4a-component - version: 0.1.5 - wait: true - override: - valuesFrom: - - kind: ConfigMap - name: u4acm - valuesKey: "values.yaml" - component: - name: kubebb.u4a-component - namespace: kubebb-system -``` - -其中,组件`U4A-Component`的参数通过`ConfigMap`方式注入,`ConfigMap`的创建流程可参考[U4A组件部署流程](https://github.com/kubebb/components/tree/main/examples/u4a-component#install-u4a-component) - -通过一下命令部署: - -```shell - kubectl apply -nu4a-system -f u4a_componentplan.yaml -``` - -`U4A Component`部署完成后,可通过以下命令查看组件部署状态: - -```shell - kubectl get componentplan -nu4a-system u4a-component -oyaml -``` - -### 5. 访问底座服务门户 - -通过以下命令获取门户服务的访问地址: - -```shell -(base) ➜ ~ kubectl get ingress -nu4a-system -NAME CLASS HOSTS ADDRESS PORTS AGE -bff-server-ingress portal.172.18.0.2.nip.io 80, 443 4h55m -bff-server-ingress-socket portal.172.18.0.2.nip.io 80, 443 4h55m -kube-oidc-proxy-server-ingress k8s.172.18.0.2.nip.io 80, 443 4h55m -``` - -通过浏览器访问`https://portal.172.18.0.2.nip.io`即可进入服务门户。默认的用户名密码为 - -- 用户名: `admin` -- 密码: `kubebb-admin` - -> 注意: 由于使用了[nip.io](https://nip.io/)作为域名解析服务,因此需要将`HOSTS`中的域名解析到`ADDRESS`对应的IP地址上。 - -## 卸载 - -### 1. 卸载U4A Component - -```shell - kubectl delete componentplan -nu4a-system u4a-component -``` - -### 2. 卸载Cluster Component - -```shell - kubectl delete componentplan -nu4a-system cluster-component -``` diff --git a/docs/quick-start/prerequisite.md b/docs/quick-start/prerequisite.md deleted file mode 100644 index 1d54bad58..000000000 --- a/docs/quick-start/prerequisite.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -sidebar_position: 1 ---- - -# 预先准备 - -## 基础环境 - -- [Helm](https://helm.sh/docs/intro/install/) +3.0 客户端 -- [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) 客户端 - -## Kubernetes集群 - -:::tip -如果没有kubernets集群,可按照下述教程通过[kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)部署一个开发集群。默认情况下,为适配`building base`,集群至少有一个节点需要为`Ingress Controller`服务节点,并暴露`80`和`443`端口。 -::: - -### Kind开发集群 - -1. 安装kind - -> 参考: https://kind.sigs.k8s.io/docs/user/quick-start/#installation - -Linux环境为例: - -```shell -# For AMD64 / x86_64 -[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 -# For ARM64 -[ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-arm64 -chmod +x ./kind -sudo mv ./kind /usr/local/bin/kind -``` - -2. 准备单节点集群[配置文件](https://github.com/kubebb/core/blob/main/tests/kind-config.yaml)`kind-config.yaml` - -:::tip - -- 此处采用v1.24.13版本,其他版本请自行替换. [版本列表](https://hub.docker.com/r/kindest/node/tags?page=1&ordering=last_updated)。 -- 如需创建多节点集群,可参考[3节点配置文件](https://github.com/kubebb/core/blob/main/tests/kind-config-3nodes.yaml) - -::: - -```yaml -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -name: kubebb-core -nodes: - - role: control-plane - image: kindest/node:v1.24.13 - kubeadmConfigPatches: - - | - kind: InitConfiguration - nodeRegistration: - kubeletExtraArgs: - node-labels: "ingress-ready=true" - extraPortMappings: - - containerPort: 80 - hostPort: 80 - protocol: TCP - - containerPort: 443 - hostPort: 443 - protocol: TCP -``` - -3. 创建集群 - -```shell -kind create cluster --config=kind-config.yaml -``` - -4. 查看集群状态 - -```shell -kubectl cluster-info --context kind-kubebb-core -``` - -如果一切正常,输出如下: - -```shell -Kubernetes control plane is running at https://127.0.0.1:42607 -CoreDNS is running at https://127.0.0.1:42607/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy - -To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. -``` - -5. 查看集群节点 - -```shell -kubectl get nodes -``` - -如果一切正常,输出如下: - -```shell -NAME STATUS ROLES AGE VERSION -kubebb-core-control-plane Ready control-plane 21m v1.24.13 -``` - -通过`docker ps`可发现该节点已经暴露了`80`和`443`端口: - -```shell -(base) ➜ building-base git:(azure) docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -e4e3820cdb5a kindest/node:v1.24.13 "/usr/local/bin/entr…" 22 minutes ago Up 22 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 127.0.0.1:33611->6443/tcp kubebb-core-control-plane -``` diff --git a/docs/quick-start/core_quickstart.md b/docs/quick-start/quick-experience.md similarity index 58% rename from docs/quick-start/core_quickstart.md rename to docs/quick-start/quick-experience.md index 9c3188cf2..f2a97c5c1 100644 --- a/docs/quick-start/core_quickstart.md +++ b/docs/quick-start/quick-experience.md @@ -1,54 +1,8 @@ --- -sidebar_position: 2 +sidebar_position: 4 --- -# 安装内核 - -:::tip -安装前需完成[预先准备](./prerequisite)。 -::: - -## 安装 - -:::tip -Kubebb官方提供了helm仓库,方便用户安装: https://kubebb.github.io/components/ -::: - -1. 添加helm仓库 - -```shell -helm repo add kubebb https://kubebb.github.io/components/ -helm repo update -``` - -2. 创建命名空间 - -> 请根据实际情况修改命名空间名称 - -```shell -kubectl create namespace kubebb-system -``` - -3. 安装 - -```shell -helm install -nkubebb-system kubebb-core kubebb/kubebb-core -``` - -4. 查看安装状态 - -```shell -kubectl get pods -nkubebb-system -``` - -如果一切正常,输入如下: - -```shell -NAME READY STATUS RESTARTS AGE -kubebb-core-6bd7c5f679-742mq 1/1 Running 0 21h -``` - -## 快速体验 +# 发布 HelloWorld 组件 内核安装完成后可通过[官方组件仓库](https://github.com/kubebb/components)快速体验组件化的部署: @@ -189,4 +143,94 @@ curl --data-binary "@mychart-0.1.0.tgz" http://localhost:8080/api/charts kubectl get component -l kubebb.component.repository=chartmuseum -nkubebb-system NAME AGE chartmuseum.mychart 4m27s -``` \ No newline at end of file +``` + +## 体验自定义配置 + +1. 自定义门户的主色调 +```shell +kubectl edit cm portal-global-configs -n u4a-system +``` +修改 primaryColor 即可自定义门户主色调 +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: portal-global-configs +data: + global-configs: | + {"theme": {"primaryColor": "#FE8F35"}} +``` + +2. 自定义菜单 + +kubebb 的所有菜单均基于 menu 的 CRD 进行定义,如果需要添加自己的菜单,可以参考以下 memnu 示例: +```yaml +# 主菜单 +apiVersion: component.t7d.io/v1beta1 +kind: Menu +metadata: + name: demo-menu +spec: + column: 1 + isRenderSelectCurrent: false + parentOwnerReferences: + apiVersion: "" + kind: "" + name: "" + uid: "" + rankingInColumn: 100 + tenant: true + text: 测试菜单 + textEn: "Test Menu" +--- +# 测试菜单索引菜单 +apiVersion: component.t7d.io/v1beta1 +kind: Menu +metadata: + name: demo-menu-index +spec: + getTitleForReplaceSider: {} + parentOwnerReferences: + apiVersion: component.t7d.io/v1beta1 + blockOwnerDeletion: false + controller: false + kind: Menu + name: demo-menu + uid: "" + rankingInColumn: 100 + tenant: true + text: 菜单索引项 + textEn: “Menu Index Item" +--- +# 子菜单,具备实际链接功能 +apiVersion: component.t7d.io/v1beta1 +kind: Menu +metadata: + name: demo-menu-submenu1 +spec: + getTitleForReplaceSider: {} + isRenderSelectCurrent: false + parentOwnerReferences: + apiVersion: component.t7d.io/v1beta1 + blockOwnerDeletion: false + controller: false + kind: Menu + name: demo-menu-index + uid: "" + pathname: /demo-feature1 + rankingInColumn: 200 + text: 测试子菜单 + textEn: "Test Submenu" +``` + +使用 `kubectl apply -f` 即可将菜单项部署到环境中,如下图所示: +![图 1](images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png) + +* 详细介绍参考 [自定义菜单](docs/develop-guid/building-base/configuration/customize-menu.md) + +3. 多语言 & 白天/黑夜模式 + +1)通过右上角的语言切换按钮进行多语言切换,目前支持中文、英文两种语言 + +2)通过右上角的按钮切换白天/黑夜模式 diff --git a/docs/quick-start/quick-install.md b/docs/quick-start/quick-install.md new file mode 100644 index 000000000..2f914c8de --- /dev/null +++ b/docs/quick-start/quick-install.md @@ -0,0 +1,295 @@ +--- +sidebar_position: 1 +--- + +# 安装 Kubebb + +## 准备环境 + +准备基础环境 + +- [Helm](https://helm.sh/docs/intro/install/) +3.0 客户端 +- [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) 客户端 + +准备Kubernetes集群 + +:::tip +如果没有kubernets集群,可按照下述教程通过[kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)部署一个开发集群。默认情况下,为适配`building base`,集群至少有一个节点需要为`Ingress Controller`服务节点,并暴露`80`和`443`端口。 +::: + +1. 安装kind + +> 参考: https://kind.sigs.k8s.io/docs/user/quick-start/#installation + +Linux环境为例: + +```shell +# For AMD64 / x86_64 +[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 +# For ARM64 +[ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-arm64 +chmod +x ./kind +sudo mv ./kind /usr/local/bin/kind +``` + +2. 准备单节点集群[配置文件](https://github.com/kubebb/core/blob/main/tests/kind-config.yaml)`kind-config.yaml` + +:::tip + +- 此处采用v1.24.13版本,其他版本请自行替换. [版本列表](https://hub.docker.com/r/kindest/node/tags?page=1&ordering=last_updated)。 +- 如需创建多节点集群,可参考[3节点配置文件](https://github.com/kubebb/core/blob/main/tests/kind-config-3nodes.yaml) + +::: + +```yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +name: kubebb-core +nodes: + - role: control-plane + image: kindest/node:v1.24.13 + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP +``` + +3. 创建集群 + +```shell +kind create cluster --config=kind-config.yaml +``` + +4. 查看集群状态 + +```shell +kubectl cluster-info --context kind-kubebb-core +``` + +如果一切正常,输出如下: + +```shell +Kubernetes control plane is running at https://127.0.0.1:42607 +CoreDNS is running at https://127.0.0.1:42607/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy + +To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. +``` + +5. 查看集群节点 + +```shell +kubectl get nodes +``` + +如果一切正常,输出如下: + +```shell +NAME STATUS ROLES AGE VERSION +kubebb-core-control-plane Ready control-plane 21m v1.24.13 +``` + +通过`docker ps`可发现该节点已经暴露了`80`和`443`端口: + +```shell +(base) ➜ building-base git:(azure) docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +e4e3820cdb5a kindest/node:v1.24.13 "/usr/local/bin/entr…" 22 minutes ago Up 22 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 127.0.0.1:33611->6443/tcp kubebb-core-control-plane +``` + +## 安装内核 + +:::tip +Kubebb官方提供了helm仓库,方便用户安装: https://kubebb.github.io/components/ +::: + +1. 添加helm仓库 + +```shell +helm repo add kubebb https://kubebb.github.io/components/ +helm repo update +``` + +2. 创建命名空间 + +> 请根据实际情况修改命名空间名称 + +```shell +kubectl create namespace kubebb-system +``` + +3. 安装 + +```shell +helm install -nkubebb-system kubebb-core kubebb/kubebb-core +``` + +4. 查看安装状态 + +```shell +kubectl get pods -nkubebb-system +``` + +如果一切正常,输入如下: + +```shell +NAME READY STATUS RESTARTS AGE +kubebb-core-6bd7c5f679-742mq 1/1 Running 0 21h +``` + +## 安装底座 + +### 1. 创建官方组件仓库 + +> 可参考[使用官方组件仓库](#安装内核) + +### 2. 创建底座组件空间 + +:::tip +目前仅支持使用命名空间`u4a-system` +::: + +```shell + kubectl create namespace u4a-system +``` + +### 3. 部署Cluster Component + +组件部署信息`cluster_componentplan.yaml`如下: + +> 详细可[参考](https://github.com/kubebb/components/tree/main/examples/cluster-component) + +```yaml +apiVersion: core.kubebb.k8s.com.cn/v1alpha1 +kind: ComponentPlan +metadata: + name: cluster-component + namespace: u4a-system +spec: + approved: true + name: cluster-component + version: 0.1.3 + override: + set: + - ingress-nginx.controller.nodeSelector.kubernetes\.io/hostname=kubebb-core-control-plane + component: + name: kubebb.cluster-component + namespace: kubebb-system +``` + +需调整参数: + +- `override.set.ingress-nginx.controller.nodeSelector.kubernetes\.io/hostname` 将作为[ingress-nginx](https://github.com/kubebb/components/tree/main/charts/cluster-component/charts/ingress-nginx)服务节点 + +> 此处基于[kind开发集群](./prerequisite#kind开发集群)的`kubebb-core-control-plane`节点。 + +通过一下命令部署: + +```shell + kubectl apply -nu4a-system -f cluster_componentplan.yaml +``` + +`Cluster Component`部署完成后,可通过以下命令查看组件部署状态: + +```shell + kubectl get componentplan -nu4a-system cluster-component -oyaml +``` + +当组件部署状态如下时,表示组件部署成功: + +```yaml +status: + conditions: + - lastTransitionTime: "2023-07-25T08:15:41Z" + reason: "" + status: "True" + type: Approved + - lastTransitionTime: "2023-07-25T08:15:44Z" + reason: InstallSuccess + status: "True" + type: Actioned + - lastTransitionTime: "2023-07-25T08:15:44Z" + reason: "" + status: "True" + type: Succeeded +``` + +### 4. 部署U4A Component + +组件部署信息`u4a_componentplan.yaml`如下: + +```yaml +apiVersion: core.kubebb.k8s.com.cn/v1alpha1 +kind: ComponentPlan +metadata: + name: u4a-component + namespace: u4a-system +spec: + approved: true + name: u4a-component + version: 0.1.5 + wait: true + override: + valuesFrom: + - kind: ConfigMap + name: u4acm + valuesKey: "values.yaml" + component: + name: kubebb.u4a-component + namespace: kubebb-system +``` + +其中,组件`U4A-Component`的参数通过`ConfigMap`方式注入,`ConfigMap`的创建流程可参考[U4A组件部署流程](https://github.com/kubebb/components/tree/main/examples/u4a-component#install-u4a-component) + +通过一下命令部署: + +```shell + kubectl apply -nu4a-system -f u4a_componentplan.yaml +``` + +`U4A Component`部署完成后,可通过以下命令查看组件部署状态: + +```shell + kubectl get componentplan -nu4a-system u4a-component -oyaml +``` + +### 5. 访问底座服务门户 + +通过以下命令获取门户服务的访问地址: + +```shell +(base) ➜ ~ kubectl get ingress -nu4a-system +NAME CLASS HOSTS ADDRESS PORTS AGE +bff-server-ingress portal.172.18.0.2.nip.io 80, 443 4h55m +bff-server-ingress-socket portal.172.18.0.2.nip.io 80, 443 4h55m +kube-oidc-proxy-server-ingress k8s.172.18.0.2.nip.io 80, 443 4h55m +``` + +通过浏览器访问`https://portal.172.18.0.2.nip.io`即可进入服务门户。默认的用户名密码为 + +- 用户名: `admin` +- 密码: `kubebb-admin` + +> 注意: 由于使用了[nip.io](https://nip.io/)作为域名解析服务,因此需要将`HOSTS`中的域名解析到`ADDRESS`对应的IP地址上。 + +## 卸载 + +### 1. 卸载U4A Component + +```shell + kubectl delete componentplan -nu4a-system u4a-component +``` + +### 2. 卸载Cluster Component + +```shell + kubectl delete componentplan -nu4a-system cluster-component +``` diff --git a/docs/quick-start/try_customization.md b/docs/quick-start/try_customization.md deleted file mode 100644 index 27c888a39..000000000 --- a/docs/quick-start/try_customization.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -sidebar_position: 4 ---- - -# 体验自定义配置 - -1. 自定义门户的主色调 -```shell -kubectl edit cm portal-global-configs -n u4a-system -``` -修改 primaryColor 即可自定义门户主色调 -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: portal-global-configs -data: - global-configs: | - {"theme": {"primaryColor": "#FE8F35"}} -``` - -2. 自定义菜单 - -kubebb 的所有菜单均基于 menu 的 CRD 进行定义,如果需要添加自己的菜单,可以参考以下 memnu 示例: -```yaml -# 主菜单 -apiVersion: component.t7d.io/v1beta1 -kind: Menu -metadata: - name: demo-menu -spec: - column: 1 - isRenderSelectCurrent: false - parentOwnerReferences: - apiVersion: "" - kind: "" - name: "" - uid: "" - rankingInColumn: 100 - tenant: true - text: 测试菜单 - textEn: "Test Menu" ---- -# 测试菜单索引菜单 -apiVersion: component.t7d.io/v1beta1 -kind: Menu -metadata: - name: demo-menu-index -spec: - getTitleForReplaceSider: {} - parentOwnerReferences: - apiVersion: component.t7d.io/v1beta1 - blockOwnerDeletion: false - controller: false - kind: Menu - name: demo-menu - uid: "" - rankingInColumn: 100 - tenant: true - text: 菜单索引项 - textEn: “Menu Index Item" ---- -# 子菜单,具备实际链接功能 -apiVersion: component.t7d.io/v1beta1 -kind: Menu -metadata: - name: demo-menu-submenu1 -spec: - getTitleForReplaceSider: {} - isRenderSelectCurrent: false - parentOwnerReferences: - apiVersion: component.t7d.io/v1beta1 - blockOwnerDeletion: false - controller: false - kind: Menu - name: demo-menu-index - uid: "" - pathname: /demo-feature1 - rankingInColumn: 200 - text: 测试子菜单 - textEn: "Test Submenu" -``` - -使用 `kubectl apply -f` 即可将菜单项部署到环境中,如下图所示: -![图 1](images/4a52ae49bf01baee581357a57038c5792dab1fe153770917e42a5888a7ebebdc.png) - -* 详细介绍参考 [自定义菜单](../building-base/configuration/customize-menu.md) - -3. 多语言 & 白天/黑夜模式 - -1)通过右上角的语言切换按钮进行多语言切换,目前支持中文、英文两种语言 - -2)通过右上角的按钮切换白天/黑夜模式 diff --git a/docs/user-guid/_category_.json b/docs/user-guid/_category_.json index f5afb223d..9dd417158 100644 --- a/docs/user-guid/_category_.json +++ b/docs/user-guid/_category_.json @@ -1,4 +1,4 @@ { "label": "用户指南", - "position": 12 + "position": 3 } \ No newline at end of file diff --git a/docs/user-guid/component_anagement.md b/docs/user-guid/component_anagement.md index 86734f208..21fb14bc6 100644 --- a/docs/user-guid/component_anagement.md +++ b/docs/user-guid/component_anagement.md @@ -28,6 +28,32 @@ sidebar_label: 组件管理 - 用户主动将组件所有版本均设置为“废弃”状态,则不会显示在“我发布的”列表及组件市场中 ::: +### 发布自定义组件 + +此章节主要对上述 “上传 helm 包” 中包结构或重点内容的说明。Kubebb 的组件安装包采用`Helm`模式,遵循 Helm charts 开发规则。除此之外,我们额外定义了一些特殊字段来满足组件的多样性。 + +通用配置:参考[Helm官方文档](https://helm.sh/docs/) + +高级配置:为支持不同组件对安装位置、权限的可控,特此额外约定了多个配置字段。 + +- Chart.yaml + +`Chart.yaml`中包含组件的核心定义、版本、维护者等信息,属于`Helm`预定义的内容。为了支持额外的特殊需求,我们决定通过`annotations`来自由定义。如下所示: + +```yaml +annotations: + core.kubebb.k8s.com.cn/classification: "开发工具" # 组件分类,便于用户筛选,需选填“容器、服务治理、API 网关、数据库、网络、安全、存储、消息队列、云原生可观测、大数据计算、人工智能与机器学习、媒体服务、开发工具、其它” + core.kubebb.k8s.com.cn/displayname: "示例组件" # 用于填充组件的展示名,支持中英文 + core.kubebb.k8s.com.cn/restricted-namespaces: "pro1" # 用于设置组件安装位置的限制租户,多个租户需要通过`,`隔开 + core.kubebb.k8s.com.cn/restricted-tenants: "tenant1" # 用于设置组件安装位置的限制项目/命名空间,多个命名空间通过`,`隔开 +``` + +- README.md + +说明安装部署的注意事项和需要按实际环境调整的参数等。此内容会显示到 <组件市场> 组件的详情页面,便于用户查看。 + +按上面说明对您的组件进行调整后,即可按上述“我发布的”操作流程上传 Helm 包,完成组件发布。 + ## 我安装的 在“组件市场”浏览组件,按需安装组件,当组件有新版本推送时可选择手动或自动更新。 @@ -38,7 +64,7 @@ sidebar_label: 组件管理 1. 进入[组件市场/组件管理/我安装的]页面,点击** +组件安装 **,跳转到“组件市场”页面,选择目标集群,浏览组件 2. 找到目标组件,点击**安装**,进入安装页面,填写部署名称、选择组件版本、更新方式、选择租户&项目、查看或调整配置文件、按需添加镜像替换规则 - **建议安装前仔细阅读安装说明**,助您快速正确的安装组件,进行体验 -- 部署名称:由3~56个小写字母、数字、中划线“-”或点“.”组成,并以字母、数字开头或结尾。项目&集群内唯一。 +- 部署名称:`由3~53个小写字母、数字、中划线“-”组成,并以字母、数字开头或结尾`。项目&集群内唯一。 - 组件名称和组件仓库自动回显,只读 - 组件版本:下拉列表选择要安装的版本 - 更新方式:默认手动更新。 diff --git a/docs/user-guid/image/advanced-config.png b/docs/user-guid/image/advanced-config.png index 3fdb15b7f9ca3d2ef02bc42ce7a59d1fca02294a..895e218d8a9b5f761d43b212078c966861efac5c 100644 GIT binary patch literal 31621 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%0A&>1rbCMPA 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 ~|AVWBC&fUI#cLMv{Tn3CG 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 z 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 Ifo}_c1N@n^XaE2J diff --git a/docs/user-guid/intro.md b/docs/user-guid/intro.md deleted file mode 100644 index 74e703158..000000000 --- a/docs/user-guid/intro.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -sidebar_position: 2 -title: 产品介绍 -sidebar_label: 产品介绍 ---- - - -# 产品介绍 - -KubeBB(Kubernetes Building Blocks)是一种由内核驱动的组件生命周期管理平台,集成了开箱即用的云原生底座和低码组件开发能力。 - -- **提供底座服务,快速开启搭建**:提供账号、认证(OIDC)、权限(RBAC)、审计(Audit)的基础功能,采用更加标准的技术方式提供构建的底座服务 -- **内核驱动的声明式组件管理**:提供声明式的组件仓库管理、组件同步、组件订阅、部署以及多维度的组件评级,完整适配 Helm 生态,集成微前端框架 -- **灵活的组件开发模式**:基于微前端框架和低代码开发,定义了标准的组件封装及发布模式,让开发者可以在底座之上按照开发规范进行组件的快速开发和发布,并在统一的服务门户上对外提供服务 - -官方提供的组件包括微服务治理(TMF)、服务网格(TDSF)、API网关(TAMP)、应用性能监控(TAPM)的开源社区版本,详细介绍参见[**开源文档**](https://docs.tenxcloud.com/) - -## 功能说明 - -Kubebb 部署后主要有管理工作台、组件市场两部分能力。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
模块说明
组件市场组件市场组件的商店,支持浏览、订阅、下载、安装组件
组件管理1. 我发布的:支持手动发布组件到仓库;支持发布多版本
2. 我安装的:支持安装、更新、卸载组件;支持历史版本管理和版本回滚
3. 我订阅的:支持订阅、取消订阅组件;支持版本更新推送
组件仓库管理1. 支持添加、编辑、删除组件仓库
2. 支持配置仓库安全认证、仓库同步设置、仓库组件过滤规则、镜像仓库替换规则、开启组件评测等
组件评测使用智能 AI 对组件从安全性、可靠性、可用性三方面进行综合评测,为您的选择提供参考数据
管理工作台集群管理1. 多集群统一视图管理
2. 资源管理:分内置和自定义资源,各资源支持yaml方式查看编辑
3. 集群角色和角色模板管理:集群角色支持绑定角色主体有成员、组和服务账号,均支持yaml方式查看和编辑
租户和项目管理1. 多租户、多项目统一视图管理:查看租户或项目标签、授权集群等
2. 租户授权集群,设置租户管理员
3. 项目授权集群,设置项目管理员
4. 项目内角色和成员管理、项目内服务账号管理
5. 对应资源均支持yaml方式编辑
主体管理管理成员和组:创建、查看、删除成员;修改成员密码;创建、查看、删除组,组内加入或移出成员
菜单管理1. 多级菜单管理,支持管理菜单名称、图标、行列排序、路径等
2. 支持默认、iframe嵌入、链接跳转三种类型的菜单样式
3. 支持设置是否可见;设置菜单的角色权限等
4. 支持使用JSON格式的菜单数据实现更多自定义菜单配置
设置管理1. 账户中心,支持查看编辑手机、邮箱;修改密码等;支持查看所属租户项目
2. 平台信息:查看正版授权信息、更新许可证等
3. API 凭证,支持查看、下载Kubeconfig
操作审计统一查看对资源的操作记录,支持租户、项目、集群、操作类型、状态、发起者等过滤查询
- -管理工作台用户指南详见[管理工作台](https://docs.tenxcloud.com/) - -## 应用场景 - -### 快速搭建您的云原生平台 - -Kubebb 提供了多集群多租户管理、菜单管理、角色和成员管理、OIDC 认证等完善的平台基础能力。内置官方组件,通过云梯低代码组件可快速发布您的应用;通过微服务框架或服务网格统一管理和治理您的应用;通过应用性能监控统一观测服务调用,设置链路告警。同时您可发布自定义组件,例如容器服务组件,形成应用的全生命周期的管理和治理。 -![overview](./image/struc.png) - diff --git a/docusaurus.config.js b/docusaurus.config.js index fe60bfc8d..1293a818f 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -108,19 +108,19 @@ const config = { items: [ { label: '快速开始', - to: '/docs/quick-start/prerequisite', + to: '/docs/quick-start/quick-install', }, { label: '内核 Kit', - to: '/docs/core/intro', + to: '/docs/develop-guid/core/intro', }, { label: '底座 Kit', - to: '/docs/building-base/intro', + to: '/docs/develop-guid/building-base/intro', }, { label: '低码 Kit', - to: '/docs/lowcode-development/intro', + to: '/docs/develop-guid/lowcode-development/intro', }, ], }, @@ -145,7 +145,7 @@ const config = { }, { label: '云梯低代码平台', - to: '/docs/lowcode-development/intro', + to: '/docs/develop-guid/lowcode-development/intro', }, ], },