Skip to content

Commit

Permalink
Add pluggable architecture docs
Browse files Browse the repository at this point in the history
  • Loading branch information
wansir committed Jan 14, 2022
1 parent d783c94 commit 789adc9
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 0 deletions.
117 changes: 117 additions & 0 deletions sig-architecture/concepts-and-designs/pluggable-architecture-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Summary

可插拔架构是 KubeSphere 4.0 中最重要的改动,目的是让 KubeSphere 可以动态的进行功能扩展,提供完善的插件机制便于第三方的应用接入,构建更加完善的生态。

- Data Management
- Project Management
- DevOps
- ...

## Core Capabilities

1. 前端插件化:前端项目支持插件化,可通过插件在各级导航栏插入新的功能入口,实现功能页面的动态添加。
2. 后端插件化:后端支持 API 拓展机制,提供统一的 API 聚合,认证鉴权框架。
3. 插件管理:提供可视化的插件管理机制,支持插件的安装、卸载、启用、停用、配置、升级
4. 插件仓库:提供插件的打包、发布机制,提供内置的插件仓库。
5. 插件框架:提供插件开发、打包、发布相关的脚手架,提供完善的插件开发文档。

## Architecture

![plugin-arch](../images/pluggable-arch.png)

## Frontend

TBD

## Backend

后端的插件化主要包含 API 的注册、静态资源的代理两个部分,可以把 ks-apiserver 看作一个可拓展的 API 网关,由 ks-apiserver 提供统一的 API 认证鉴权能力,支持动态的 API 拓展。

![backend](../images/backend.svg)

### Plugin Model

**插件** 通过 CRD 进行定义,主要包含三个部分:`APIService``JSBundle``ReverseProxy`

#### APIService

APIService 是一种类似于 [K8s Aggregated API](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) 的一种 API 拓展机制,可以声明式的注册[资源型的 API](https://kubernetes.io/zh/docs/reference/using-api/api-concepts/),便于通过 [KubeSphere 的权限控制体系](#TODO)进行统一的 API 权限控制,一个插件中可以包含多个 APIService。

```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: APIService
metadata:
name: v1alpha1.devops.kubesphere.io
annotations:
meta.helm.sh/release-name: devops-0.10.0 # 通过 Subscription 订阅插件之后,插件 chart 中包含的 APIService 通过 helm 创建出来
spec:
group: devops.kubesphere.io # API Group
version: v1alpha1 # API Version
endpoint: https://ks-devops.kubesphere-devops-system.svc # backend
insecureSkipTLSVerify: true
status:
enabled: true
```
#### JSBundle
JSBundle 定义了需要注入到前端框架中的 js bundle。为了便于开发,体积较小的 js 文件可以直接嵌入到 ConfigMap 或 Secret 中,体积较大的 js 文件则需要通过额外的后端服务来提供。插件被启用之后,ks-apiserver 会代理相关的静态资源请求,前端框架则借助此 API 动态的加载 js 文件。
```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: JSBundle
metadata:
name: v1alpha1.devops.kubesphere.io
annotations:
meta.helm.sh/release-name: devops-0.10.0
spec:
rawFrom:
url: https://ks-devops.kubesphere-devops-system.svc/dist/devops.kubesphere.io/v1alpha1/index.js
# configMapKeyRef:
# name: devops
# key: index.js
# namespace: kubesphere-devops-system
# secretKeyRef:
# name:
# key:
# namespace: kubesphere-devops-system
# TODO(@chenz24)
status:
enabled: true
link: /dist/devops.kubesphere.io/v1alpha1/index.js
```
#### ReverseProxy
提供非资源型 API 的方向代理,可以用来代理一些静态的资源文件,支持路径的 Rewrite,支持请求头的注入。
API 的路径会在解析插件的时候就进行检查,避免冲突。
```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: ReverseProxy
metadata:
name: devops.kubesphere.io
spec:
matcher:
- path: /res/devops.kubesphere.io/images/*
method: GET
upstream:
insecureSkipVerify: false
caBudle: <Base64Data>
backend: https://ks-devops.kubesphere-system.svc
healthCheck:
url: /healthz
interval: 15s
status: 200
timeout: 15s
rewrite:
- '/old-prefix/* /new-prefix{path}'
header:
up:
- 'Foo: Bar'
down:
- 'Foo: Bar'
status:
enabled: true
```
107 changes: 107 additions & 0 deletions sig-architecture/concepts-and-designs/plugin-development-guide-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# 插件开发指南

## 开发插件

### 项目初始化

1. 通过 CLI 创建一个项目脚手架

TBD

### 前端页面的开发

1. 如何插入一个新的功能页面
2. 前端设计风格指南

TBD

### 后端 API 的开发

1. 后端 API 风格指南
2. API 权限控制

TBD

## 插件的打包与发布

插件开发完成之后,需要与依赖组件一起打包为 Helm Chart。

1. 一个插件打包为一个 Helm Chart
2. 一组插件打包为 Docker Iamge 之后可以进行发布

### Helm Chart 的目录结构

```bash
devops/
├── .helmignore
├── Chart.yaml # Helm chart 基本信息
├── LICENSE
├── README.md
├── values.yaml # 默认的配置信息
├── charts/
└── templates/
├── workloads.yaml # 需要部署的工作负载
├── services.yaml # 需要创建的 service
├── extensions.yaml # 定义 APIService, JSBundle 用于注册 API 与 js 文件
├── roletemplates.yaml # 通过 role template CRD 动态注册权限控制项
└── tests/
dmp/ # 可以同时打包发布多个插件
├── .helmignore
├── Chart.yaml
├── LICENSE
├── README.md
├── values.yaml
├── charts/
└── templates/
├── workloads.yaml
├── services.yaml
├── extensions.yaml
├── roletemplates.yaml
└── tests/
Dockerfile # 将 charts 打包到 docker image 进行发布
```

### Chart.yaml 的定义

```yaml
apiVersion: v2
name: devops
version: v0.10.0
kubeVersion: v1.17.0
description: DevOps Plugin for KubeSphere.
type: application
keywords:
- DevOps
home: https://kubesphere.io
sources:
- https://github.com/kubesphere/ks-devops
dependencies: # chart 必要条件列表 (可选)
- name: jenkins
version: v0.0.1
# repository: (可选)仓库URL () 或别名 ("@repo-name")
# condition: (可选) 解析为布尔值的yaml路径,用于启用/禁用chart (e.g. subchart1.enabled )
# tags: (可选)
# - 用于一次启用/禁用 一组chart的tag
# import-values: (可选)
# - ImportValue 保存源值到导入父键的映射。每项可以是字符串或者一对子/父列表项
# alias: (可选) chart中使用的别名。当你要多次添加相同的chart时会很有用
maintainers:
- name: kubesphere
email: [email protected]
url: https://github.com/linuxsuren
icon: 'data:image/png;base64, PHN2ZyBoZWlnaHQ9IjUxMnB0IiB2aWV3Qm94PSIwIDAgNTEyIDUxMi4wMDEiIHdpZHRoPSI1MTJwdCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNTEyIDI1NmMwIDE0MS4zODY3MTktMTE0LjYxMzI4MSAyNTYtMjU2IDI1Ni0xNDEuMzgyODEyIDAtMjU2LTExNC42MTMyODEtMjU2LTI1NnMxMTQuNjE3MTg4LTI1NiAyNTYtMjU2YzE0MS4zODY3MTkgMCAyNTYgMTE0LjYxMzI4MSAyNTYgMjU2em0wIDAiIGZpbGw9IiM1YTU0ZTAiLz48cGF0aCBkPSJtNTEwLjkyOTY4OCAyNzkuMzQ3NjU2LTkxLjM1NTQ2OS05MS4zNTkzNzUtNy41OTc2NTcgMTAuMTA5Mzc1LTEwNC45ODA0NjgtMTA0Ljk4NDM3NS02NC4xODc1IDEyMi45MTAxNTctMTQ0LjAwNzgxMyAyNi44MzU5MzcgMTI1Ljk5MjE4OCAxMjUuOTkyMTg3LTY2LjI4OTA2MyA0Ni44MTY0MDcgOTYuMzIwMzEzIDk2LjMxNjQwNmMuMzk0NTMxLjAwMzkwNi43ODUxNTYuMDE1NjI1IDEuMTc1NzgxLjAxNTYyNSAxMzMuNTExNzE5IDAgMjQzLjEzMjgxMi0xMDIuMjE0ODQ0IDI1NC45Mjk2ODgtMjMyLjY1MjM0NHptMCAwIiBmaWxsPSIjMzgzOGJhIi8+PHBhdGggZD0ibTE4NCA1MDEuNzE4NzVjMjIuODM5ODQ0IDYuNjc5Njg4IDQ3IDEwLjI4MTI1IDcyIDEwLjI4MTI1czQ5LjE2MDE1Ni0zLjYwMTU2MiA3Mi0xMC4yODEyNXYtMTQyLjcxODc1aC0xNDR6bTAgMCIgZmlsbD0iI2ZmYmVhYSIvPjxwYXRoIGQ9Im0yNTUuOTA2MjUgMzU5djE1M2guMDkzNzVjMjUgMCA0OS4xNjAxNTYtMy42MDE1NjIgNzItMTAuMjgxMjV2LTE0Mi43MTg3NXptMCAwIiBmaWxsPSIjZmFhNjhlIi8+PHBhdGggZD0ibTM4NS4xMjUgMTY5LjkxNzk2OWgtMjU4LjI1Yy0yMy4xMjUgMC00MS44NzUgMTguNzQ2MDkzLTQxLjg3NSA0MS44NzUgMCAyMy4xMjUgMTguNzUgNDEuODc1IDQxLjg3NSA0MS44NzVoMzEuNjI4OTA2djE2MmgxOTQuOTkyMTg4di0xNjJoMzEuNjI4OTA2YzIzLjEyODkwNiAwIDQxLjg3NS0xOC43NSA0MS44NzUtNDEuODc1IDAtMjMuMTI4OTA3LTE4Ljc0NjA5NC00MS44NzUtNDEuODc1LTQxLjg3NXptMCAwIiBmaWxsPSIjZmZkYTAwIi8+PHBhdGggZD0ibTM4NS4xMjUgMTY5LjkxNzk2OWgtMTI5LjIxODc1djI0NS43NWg5Ny41ODk4NDR2LTE2MmgzMS42Mjg5MDZjMjMuMTI4OTA2IDAgNDEuODc1LTE4Ljc1IDQxLjg3NS00MS44NzUgMC0yMy4xMjg5MDctMTguNzQ2MDk0LTQxLjg3NS00MS44NzUtNDEuODc1em0wIDAiIGZpbGw9IiNmZmIwMDAiLz48cGF0aCBkPSJtMzIwLjMzMjAzMSAxMzIuMzMyMDMxYzAgMzUuNTMxMjUtMjguODAwNzgxIDY0LjMzMjAzMS02NC4zMzIwMzEgNjQuMzMyMDMxcy02NC4zMzIwMzEtMjguODAwNzgxLTY0LjMzMjAzMS02NC4zMzIwMzFjMC0zNS41MjczNDMgMjguODAwNzgxLTY0LjMzMjAzMSA2NC4zMzIwMzEtNjQuMzMyMDMxczY0LjMzMjAzMSAyOC44MDQ2ODggNjQuMzMyMDMxIDY0LjMzMjAzMXptMCAwIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0ibTI1NiA2OGMtLjAzMTI1IDAtLjA2MjUuMDAzOTA2LS4wOTM3NS4wMDM5MDZ2MTI4LjY2MDE1NmguMDkzNzVjMzUuNTMxMjUgMCA2NC4zMzIwMzEtMjguODAwNzgxIDY0LjMzMjAzMS02NC4zMzIwMzEgMC0zNS41MjczNDMtMjguODAwNzgxLTY0LjMzMjAzMS02NC4zMzIwMzEtNjQuMzMyMDMxem0wIDAiIGZpbGw9IiNlOWVkZjUiLz48cGF0aCBkPSJtMjMzLjY2MDE1NiAxMzIuMzMyMDMxYzAgNy45MTQwNjMtNi40MTQwNjIgMTQuMzI4MTI1LTE0LjMyODEyNSAxNC4zMjgxMjUtNy45MTAxNTYgMC0xNC4zMjgxMjUtNi40MTQwNjItMTQuMzI4MTI1LTE0LjMyODEyNSAwLTcuOTE0MDYyIDYuNDE3OTY5LTE0LjMyODEyNSAxNC4zMjgxMjUtMTQuMzI4MTI1IDcuOTE0MDYzIDAgMTQuMzI4MTI1IDYuNDE0MDYzIDE0LjMyODEyNSAxNC4zMjgxMjV6bTAgMCIgZmlsbD0iI2ZlODIwNSIvPjxwYXRoIGQ9Im0zMDYuOTk2MDk0IDEzMi4zMzIwMzFjMCA3LjkxNDA2My02LjQxNDA2MyAxNC4zMjgxMjUtMTQuMzI4MTI1IDE0LjMyODEyNS03LjkxNDA2MyAwLTE0LjMyODEyNS02LjQxNDA2Mi0xNC4zMjgxMjUtMTQuMzI4MTI1IDAtNy45MTQwNjIgNi40MTQwNjItMTQuMzI4MTI1IDE0LjMyODEyNS0xNC4zMjgxMjUgNy45MTQwNjIgMCAxNC4zMjgxMjUgNi40MTQwNjMgMTQuMzI4MTI1IDE0LjMyODEyNXptMCAwIiBmaWxsPSIjZmU2YTE2Ii8+PC9zdmc+'
appVersion: v0.10.0
annotations:
extensions.kubesphere.io/foo: bar # 额外的注释信息
```
### 打包为 Docker Iamge 对插件进行分发
```dockerfile
FROM baseimage # Framwork 提供的 baseimage

WORKDIR /charts
COPY . /charts
RUN helm index .
CMD ["serve"] # serve 一个 helm repo,并提供 grpc 接口,配合 Repository 实现 API Aggregation
```
133 changes: 133 additions & 0 deletions sig-architecture/concepts-and-designs/plugin-management-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
### Plugin

插件仓库部署完成后,plugin-controller-mamnager 会定时拉取最新的 Chart 解析后生成 Plugin 对象,以供订阅。

```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: Plugin
metadata:
name: devops
labels:
extensions.kubesphere.io/category=devops
status:
phase: deployed
currentVersion: v0.10.1
versions:
- description: DevOps plugin for KubeSphere.
keywords:
- devops
maintainers:
- email: devops.kubesphere.io
name: kubesphere
repo: builtin
version: 0.10.0
minKubeVersion: 1.17.0
- description: DevOps plugin for KubeSphere.
keywords:
- devops
maintainers:
- email: devops.kubesphere.io
name: kubesphere
repo: builtin
version: 0.10.1
minKubeVersion: 1.17.0
```
### PluginVersion
插件可以同时存在多个版本,插件名称在同一个 Repo 中是唯一值
```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: PluginVersion
metadata:
name: devops-v0.10.1
spec:
description: DevOps plugin for KubeSphere.
keywords:
- devops
maintainers:
- email: devops.kubesphere.io
name: kubesphere
repo: builtin
version: 0.10.0
minKubeVersion: 1.17.0
files:
- NOTES.yaml
- templates/deployments.yaml
```
### PluginVersion Files
Aggregated API,用于从 Repo 中直接加载 Helm Chart 中的数据
文件列表
```
$ kubectl get --raw=/apis/packages.extensions.kubesphere.io/v1alpha1/pluginversions/devops-0.10.0/files
[
"Chart.yaml",
"README.md",
"templates/NOTES.txt",
"templates/deployment.yaml",
"templates/hpa.yaml",
"templates/ingress.yaml",
"templates/service.yaml",
"templates/serviceaccount.yaml",
"templates/tests/test-connection.yaml",
"values.yaml"
]%
```

获取单个文件

```
$ kubectl get --raw=/apis/packages.extensions.kubesphere.io/v1alpha1/pluginversions/xxx/files\?name=values.yaml
# Default values for test.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
```

### Subscription

通过订阅的方式安装插件,通过 Subscription 来控制安装卸载,启用、停用,状态同步,版本升级。

```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: Subscription
metadata:
name: devops-0.10.0
spec:
enabled: true
plugin:
name: devops
version: 0.10.0 # 通过更新版本触发 upgrade, rollback
targetNamespace: kubesphere-devops-system
config:
foo: bar # 插件的配置信息
status:
phase: deployed # unknown, superseded, failed, uninstalling, pending-install, pending-upgrade 或 pending-rollback
```
### Upgrade
TBD
### Dependency
TBD
35 changes: 35 additions & 0 deletions sig-architecture/concepts-and-designs/plugin-repository-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 插件仓库

当我们通过 Docker Image 对 Helm Chart 进行打包的插件进行打包之后,可以将这个 Repo 部署到集群中

### Repository

定义 Repository 用于加载打包为 Docker Image 的插件,创建好 Repository 对象后,plugin-controller-manager 会部署该 Docker Image,以提供 Helm Repo(HTTP)、Plugin(Aggregated API) 相关的 API。

```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: Repository
metadata:
name: builtin
spec:
image: docker.io/kubespheredev/builtin:latest # 内置的仓库
displayName: Builtin Repository
publisher: [email protected]
updateStrategy: # 仓库的更新策略
registryPoll:
interval: 10m
```
plugin-controller-manager 会部署 `docker.io/kubespheredev/builtin:latest`,并创建 builtin.kubesphere-system.svc 这个 Service,定时从 helm repo 拉取 Helm Chart, 读取 Helm Chart 中的元数据,进行数据校验,同时写入 Plugin、PluginVersion 对象,通过 Aggregated API 实现 pluginversions/files 这个 Aggregated API。

### Category

```yaml
apiVersion: extensions.kubesphere.io/v1alpha1
kind: Category
metadata:
name: devops
spec:
displayName: "DevOps"
description: "DevOps"
```
Loading

0 comments on commit 789adc9

Please sign in to comment.