### Clone Kubesphere Extension Samples Repository Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/packaging-and-release/packaging This command clones the `extension-samples` repository from GitHub. This repository contains example extension components, such as 'hello-world', which can be used as a starting point for developing your own Kubesphere extensions. ```shell git clone https://github.com/kubesphere/extension-samples.git ``` -------------------------------- ### Install Helm Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/prepare-development-environment 安装 Helm 包管理器,这是部署 KubeSphere Luban Helm Chart 所必需的工具。 ```bash curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash ``` -------------------------------- ### Install KubeSphere Luban Helm Chart Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/prepare-development-environment 使用 Helm 命令安装 KubeSphere Luban Helm Chart。此命令会在指定的命名空间(kubesphere-system)中部署核心组件,并配置 API 服务器的 NodePort。 ```bash helm upgrade --install -n kubesphere-system --create-namespace ks-core https://charts.kubesphere.io/main/ks-core-1.1.0.tgz --set apiserver.nodePort=30881 --debug --wait ``` -------------------------------- ### Create KubeSphere Project CLI Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/references/create-ks-project The `create-ks-project` CLI tool is a scaffolding utility for KubeSphere frontend extensions. It generates a new frontend project directory with necessary dependencies installed. ```APIDOC create-ks-project CLI Reference Description: KubeSphere frontend development scaffolding tool. Executes to create a frontend scaffold folder in the specified directory and installs corresponding frontend dependencies. Usage: yarn create ks-project [project-name] Optional Parameters: -V, --version Print version number -f, --fast-mode Install directly using pre-packaged dependency archives -h, --help Print help information ``` -------------------------------- ### Go OIDC Token Verification Example Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/best-practice/develop-example An example Go application demonstrating the OpenID Connect (OIDC) flow, including obtaining an ID token, verifying it, and extracting claims using the go-oidc library. It handles authentication requests and callback processing. ```go /* This is an example application to demonstrate parsing an ID Token. */ package main import ( "crypto/rand" "encoding/base64" "encoding/json" "io" "log" "net/http" "time" "github.com/coreos/go-oidc/v3/oidc" "golang.org/x/net/context" "golang.org/x/oauth2" ) var ( clientID = "test" clientSecret = "fake" ) func randString(nByte int) (string, error) { b := make([]byte, nByte) if _, err := io.ReadFull(rand.Reader, b); err != nil { return "", err } return base64.RawURLEncoding.EncodeToString(b), nil } func setCallbackCookie(w http.ResponseWriter, r *http.Request, name, value string) { c := &http.Cookie{ Name: name, Value: value, MaxAge: int(time.Hour.Seconds()), Secure: r.TLS != nil, HttpOnly: true, } http.SetCookie(w, c) } func main() { ctx := context.Background() provider, err := oidc.NewProvider(ctx, "http://ks-console.kubesphere-system.svc:30880") if err != nil { log.Fatal(err) } oidcConfig := &oidc.Config{ ClientID: clientID, } verifier := provider.Verifier(oidcConfig) config := oauth2.Config{ ClientID: clientID, ClientSecret: clientSecret, Endpoint: provider.Endpoint(), RedirectURL: "http://10.8.0.2:5556/auth/google/callback", Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { state, err := randString(16) if err != nil { http.Error(w, "Internal error", http.StatusInternalServerError) return } nonce, err := randString(16) if err != nil { http.Error(w, "Internal error", http.StatusInternalServerError) return } setCallbackCookie(w, r, "state", state) setCallbackCookie(w, r, "nonce", nonce) http.Redirect(w, r, config.AuthCodeURL(state, oidc.Nonce(nonce)), http.StatusFound) }) http.HandleFunc("/auth/google/callback", func(w http.ResponseWriter, r *http.Request) { state, err := r.Cookie("state") if err != nil { http.Error(w, "state not found", http.StatusBadRequest) return } if r.URL.Query().Get("state") != state.Value { http.Error(w, "state did not match", http.StatusBadRequest) return } oauth2Token, err := config.Exchange(ctx, r.URL.Query().Get("code")) if err != nil { http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError) return } rawIDToken, ok := oauth2Token.Extra("id_token").(string) if !ok { http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError) return } idToken, err := verifier.Verify(ctx, rawIDToken) if err != nil { http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError) return } nonce, err := r.Cookie("nonce") if err != nil { http.Error(w, "nonce not found", http.StatusBadRequest) return } if idToken.Nonce != nonce.Value { http.Error(w, "nonce did not match", http.StatusBadRequest) return } oauth2Token.AccessToken = "*REDACTED*" resp := struct { OAuth2Token *oauth2.Token IDTokenClaims *json.RawMessage // ID Token payload is just JSON. }{oauth2Token, new(json.RawMessage)} if err := idToken.Claims(&resp.IDTokenClaims); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } data, err := json.MarshalIndent(resp, "", " ") if err != nil { ``` -------------------------------- ### Run KubeSphere Console Locally Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/hello-world-extension Command to start the KubeSphere Console in development mode. After running this, the console can be accessed via a web browser, and the created extension will be loaded. ```shell yarn dev ``` -------------------------------- ### Implement Extension Component UI (React) Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/hello-world-extension-anatomy Implements the user interface for an extension component. This example demonstrates rendering a simple 'Hello World!' message using React and styled-components. ```javascript import React from 'react'; import styled from 'styled-components'; const Wrapper = styled.h3` margin: 8rem auto; text-align: center; `; export default function App() { return Hello World!; } ``` -------------------------------- ### ksbuilder CLI Reference Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/references/ksbuilder Reference for the ksbuilder command-line interface, used for managing KubeSphere extensions. It covers commands for creating, packaging, publishing, unpublishing, and versioning extensions. ```APIDOC ksbuilder [flags] ksbuilder is the command-line interface for KubeSphere extensions. Options: -h, --help help for ksbuilder ``` ```APIDOC ksbuilder create [flags] Execute the following command to create a new KubeSphere component. ``` ```APIDOC ksbuilder package [flags] Execute the following command to package the component. ``` ```APIDOC ksbuilder publish [flags] Execute the following command to publish the component to the extension market. ``` ```APIDOC ksbuilder unpublish [flags] Execute the following command to remove the component from the extension market. ``` ```APIDOC ksbuilder version [flags] Execute the following command to view the component version. ``` -------------------------------- ### Kubernetes RBAC Role Definition Example Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/access-control Provides a YAML manifest for a Kubernetes Role named 'pod-reader' within the 'default' namespace. This Role grants read-only access (get, watch, list) to Pod resources. ```yaml apiVersion: iam.kubesphere.io/v1beta1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] ``` -------------------------------- ### Initialize KubeSphere Extension Project Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/hello-world-extension Commands to create a new KubeSphere extension development project using yarn. This involves adding the create-ks-project tool globally and then using it to scaffold a new console project. ```shell mkdir -p ~/kubesphere-extensions cd ~/kubesphere-extensions yarn add global create-ks-project yarn create ks-project ks-console ``` -------------------------------- ### Webpack Configuration for Kubesphere Proxy Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/extending-api Provides a webpack.config.js example for local Kubesphere Console development. It configures the dev server to proxy requests to the ks-apiserver, including setting up basic authentication headers for the proxy request. ```javascript const { merge } = require('webpack-merge'); const baseConfig = require('@ks-console/bootstrap/webpack/webpack.dev.conf'); const webpackDevConfig = merge(baseConfig, { devServer: { proxy: { '/proxy': { target: 'http://172.31.73.3:30881', // Modify to the target ks-apiserver address onProxyReq: (proxyReq, req, res) => { const username = 'admin' // User credentials for proxy requests const password = 'P@88w0rd' const auth = Buffer.from(`${username}:${password}`).toString("base64"); proxyReq.setHeader('Authorization', `Basic ${auth}`); }, }, }, }, }); module.exports = webpackDevConfig; ``` -------------------------------- ### 推送和安装扩展组件 Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/packaging-and-release/testing 使用 `ksbuilder publish` 命令将扩展组件推送到远端商店,并在 KubeSphere Console 中进行安装和启用测试。 ```bash ➜ extension-samples git:(master) ✗ cd extensions ➜ extensions git:(master) ✗ ksbuilder package hello-world package extension hello-world package saved to /Users/hongming/GitHub/extension-samples/extensions/hello-world-0.1.0.tgz ➜ extensions git:(master) ✗ ksbuilder publish hello-world-0.1.0.tgz publish extension hello-world-0.1.0.tgz creating Extension hello-world creating ExtensionVersion hello-world-0.1.0 creating ConfigMap extension-hello-world-0.1.0-chart ``` -------------------------------- ### Kubesphere ReverseProxy CRD Example Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/extending-api Illustrates a complete Kubesphere ReverseProxy Custom Resource (CR) definition. It specifies the matching rules for incoming requests and defines the upstream service, including directives for path manipulation and header injection. ```yaml apiVersion: extensions.kubesphere.io/v1alpha1 kind: ReverseProxy metadata: name: weave-scope spec: directives: headerUp: - '-Authorization' stripPathPrefix: /proxy/weave.works matcher: method: '*' path: /proxy/weave.works/* upstream: url: http://app.weave.svc # service: # namespace: example-system # name: apiserver # port: 443 ``` -------------------------------- ### Create Hello World Extension Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/hello-world-extension Steps to create a 'Hello World' extension within an existing KubeSphere console project. This involves navigating into the project directory and running the extension creation command, followed by providing basic extension details. ```shell cd ks-console yarn create:ext ``` ```shell Extension Name hello-world Display Name Hello World Description Hello World! Author demo Language JavaScript Create extension [hello-world]? Yes ``` -------------------------------- ### Kubesphere DataTable Toolbar Action Example Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/access-control Demonstrates integrating KubeSphere's permission control into a React component using the `useActionMenu` hook. This example shows how to define table actions with specific `authKey` and `action` properties to conditionally render buttons based on user roles. ```javascript import { useActionMenu, DataTable } from '@ks-console/shared'; // Assuming authKey, params, t, openCreate are defined elsewhere const renderTableAction = useActionMenu({ autoSingleButton: true, authKey, params, actions: [ { key: 'invite', text: t('INVITE'), action: 'create', // Specific action for permission check props: { color: 'secondary', shadow: true, }, onClick: openCreate, }, ], }); return ( ); ``` -------------------------------- ### Prepare Kubernetes Cluster Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/quickstart/prepare-development-environment 准备 Kubernetes 集群以部署 KubeSphere Luban。此步骤使用 KubeKey 快速部署一个 Kubernetes 集群,并配置本地存储和容器运行时。 ```bash curl -sfL https://get-kk.kubesphere.io | sh - ./kk create cluster --with-local-storage --with-kubernetes v1.31.0 --container-manager containerd -y ``` -------------------------------- ### 前端扩展组件开发 - 打开外部链接 Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/examples/external-link-example 演示了如何在 KubeSphere 前端扩展组件中打开外部链接。代码使用 `react-router-dom` 的 `useNavigate` 和 `window.open()` 方法在新标签页打开指定 URL,并导航回前一页。提供了使用 `` 标签作为替代方案的说明,并指出直接使用 `window.open` 可能导致页面状态丢失。 ```javascript import React, { useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { Loading } from "@kubed/components"; const LINK = "https://dev-guide.kubesphere.io/"; export default function App() { const navigate = useNavigate(); useEffect(() => { window.open(LINK); navigate(-1, { replace: true }); }, []); return ; } ``` -------------------------------- ### Get ServiceAccount Token Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/references/kubesphere-api Retrieves the token associated with a ServiceAccount by querying Kubernetes secrets. This token can be used for authentication. ```bash kubectl get secrets $(kubectl get serviceaccounts.kubesphere.io sample -n default -o jsonpath={.secrets[].name}) -n default -o jsonpath={.data.token} | base64 -d ``` -------------------------------- ### Create Extension Component Package with ksbuilder Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/examples/gatekeeper-extension Initializes a KubeSphere extension component package using the `ksbuilder create` command. It prompts for essential details like the extension name, author, and email to set up the basic directory structure. ```shell ➜ charts git:(master) ksbuilder create Please input extension name: gatekeeper ✔ security Please input extension author: hongming Please input Email (optional): hongming@kubesphere.io Please input author's URL (optional): Directory: /Users/hongming/GitHub/gatekeeper/charts/gatekeeper ``` -------------------------------- ### KubeSphere Cloud API Key 格式 Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/packaging-and-release/release 用于身份验证和授权的 KubeSphere Cloud API Key 示例格式。此 Key 用于与 KubeSphere Cloud 服务进行交互,例如提交扩展组件。 ```APIDOC Cloud API Key: Format: kck- Example: kck-1e63267b-cb3c-4757-b739-3d94a06781aa Purpose: Authentication and authorization for KubeSphere Cloud services, specifically for extension submission. ``` -------------------------------- ### Get Gatekeeper License Secret Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/license Retrieves the Gatekeeper license secret in YAML format from the 'kubesphere-system' namespace. This command is essential for accessing the encoded license data required for customization. ```shell root@kse:~# kubectl get secret -n kubesphere-system kubesphere.license.gatekeeper -oyaml ``` -------------------------------- ### Search Helm Repository for Extensions Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/packaging-and-release/release Searches for Helm charts within the configured Helm repositories, specifically looking for the 'alc' extension. This command helps locate the installation package for an extension. ```shell ➜ helm search repo alc NAME CHART VERSION APP VERSION DESCRIPTION kscloud-beta/alc 1.1.0 alc is an example extension ``` -------------------------------- ### Prepare Extension Package Directory and Add Sub-Chart Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/examples/gatekeeper-extension Demonstrates steps to clean up the initial extension package directory by removing unused files and directories. It also shows how to download and include a Gatekeeper Helm chart as a sub-chart for deployment. ```shell cd gatekeeper # 移除用不到的 subchart、静态资源目录、模板文件等等 rm -rf charts/* static applicationclass.yaml # 将 gatekeeper chart 保存到 charts 目录中 curl -o charts/gatekeeper-3.14.0.tgz https://open-policy-agent.github.io/gatekeeper/charts/gatekeeper-3.14.0.tgz ``` -------------------------------- ### Get Extension Details with ksbuilder Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/packaging-and-release/release Retrieves detailed information about a specific extension component, including its name, ID, status, and version history. This is useful for monitoring the submission and approval process. ```shell ➜ ksbuilder get alc Name: alc ID: 516955082294618939 Status: draft SNAPSHOT ID VERSION STATUS UPDATE TIME 516955082311396155 1.1.0 submitted 2024-06-06 07:27:20 ``` -------------------------------- ### 克隆示例代码并设置扩展组件 Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/examples/external-link-example 用于准备 KubeSphere 扩展组件开发环境的 shell 命令。首先切换到指定目录,然后从 GitHub 克隆示例代码库,最后将 'external-link' 示例组件复制到 KubeConsole 的扩展目录中。 ```shell cd ~/kubesphere-extensions git clone https://github.com/kubesphere/extension-samples.git cp -r ~/kubesphere-extensions/extension-samples/extensions-frontend/extensions/external-link ~/kubesphere-extensions/ks-console/extensions ``` -------------------------------- ### Kubernetes RBAC RoleBinding Example Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/access-control Demonstrates a YAML manifest for a RoleBinding named 'read-pods' in the 'default' namespace. It binds the 'pod-reader' Role to a user named 'jane', granting her the permissions defined in the 'pod-reader' Role within that namespace. ```yaml apiVersion: iam.kubesphere.io/v1beta1 kind: RoleBinding metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: iam.kubesphere.io roleRef: kind: Role name: pod-reader apiGroup: iam.kubesphere.io ``` -------------------------------- ### KubeSphere API 概念与路径示例 Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/references/kubesphere-api-concepts KubeSphere API 是 Kubernetes API 的超集,沿用了 K8s API 的设计,通过 HTTP 提供基于资源的 RESTful 编程接口。它支持标准 HTTP 动词(POST、PUT、PATCH、DELETE、GET)来操作资源。KubeSphere 在 K8s API 的基础上增加了平台级(如用户、集群)和企业空间级资源,其扩展 API 通常以 `/kapis` 为前缀。此外,通过在请求路径前添加集群标识,可以访问 member 集群的 API。 ```APIDOC KubeSphere API 概念: KubeSphere API 是 K8s API 的超集,沿用了 K8s API 的设计,通过 HTTP 提供了基于资源 (RESTful) 的编程接口。 它支持通过标准 HTTP 动词(POST、PUT、PATCH、DELETE、GET)来检索、创建、更新和删除主要资源。 在使用 KubeSphere API 之前,需要先阅读并理解 K8s API 的概念。 KubeSphere 提供了 K8s API 代理,通过 `/apis`、`/api` 前缀可以直接访问 K8s 的 API。 此外,KubeSphere 在 K8s 的基础上支持额外的资源层级,包括平台级资源(例如用户、集群、企业空间等),以及企业空间级资源。 KubeSphere 扩展的 API 通常以 `/kapis` 为前缀。 KubeSphere API 路径示例: # K8s API 路径 /api/v1/namespaces /api/v1/pods /api/v1/namespaces/my-namespace/pods /apis/apps/v1/deployments /apis/apps/v1/namespaces/my-namespace/deployments /apis/apps/v1/namespaces/my-namespace/deployments/my-deployment # KubeSphere 扩展 API 路径 /kapis/iam.kubesphere.io/v1beta1/users /kapis/tenant.kubesphere.io/v1alpha2/workspaces/my-workspace/namespaces 多集群 API 访问: 通过在请求路径之前添加集群标识作为前缀,可以访问 member 集群。 /clusters/host/api/v1/namespaces /clusters/member/api/v1/namespaces ``` -------------------------------- ### Access KubeSphere API with ServiceAccount Token Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/references/kubesphere-api Shows how to obtain a ServiceAccount token and use it with `curl` to access KubeSphere APIs. It retrieves the token and the API server's cluster IP, then makes a GET request. ```bash token=$(kubectl get secrets $(kubectl get serviceaccounts.kubesphere.io sample -n default -o jsonpath={.secrets[].name}) -n default -o jsonpath={.data.token} | base64 -d) [root@ks ~]# kubectl get svc ks-apiserver -n kubesphere-system -o jsonpath={.spec.clusterIP} 10.233.56.50 [root@ks ~]# curl --location 'http://10.233.56.50:80/kapis/tenant.kubesphere.io/v1beta1/clusters' \ --header 'Accept: application/json, text/plain, */*' \ --header "Authorization: Bearer $token" # 可访问 KubeSphere API 但是显示权限不够 { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "clusters.tenant.kubesphere.io is forbidden: User \"kubesphere:serviceaccount:default:sample\" cannot list resource \"clusters\" in API group \"tenant.kubesphere.io\" at the cluster scope", "reason": "Forbidden", "details": { "group": "tenant.kubesphere.io", "kind": "clusters" }, "code": 403 } ``` -------------------------------- ### 克隆示例代码并复制 Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/examples/third-party-component-integration-example 克隆 KubeSphere 扩展示例代码库,并将 Weave Scope 前端扩展组件复制到 KubeSphere 控制台的扩展目录中,为本地开发和调试做准备。 ```shell cd ~/kubesphere-extensions git clone https://github.com/kubesphere/extension-samples.git cp -r ~/kubesphere-extensions/extension-samples/extensions-frontend/extensions/weave-scope ~/kubesphere-extensions/ks-console/extensions ``` -------------------------------- ### Extension Component License Format Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/feature-customization/license An example of an extension component license, which is compressed and compiled to activate a component in KubeSphere Enterprise Edition. Licenses are stored as secrets in the host cluster's `kubesphere-system` namespace, named `kubesphere.license.`. ```license -----BEGIN LICENSE----- H4sIAAAAAAAA/2SQydKyOgOEr8hTDIKyZCZRUIYwbSwJIIlMr4IBrv4v3/+rU1/V WfQinc5Tna5W2BQ2JhcCQ7QB3iPgDfpAwjqQwXNMYx0q/1QrHPOvQRG7GGi5RA/e +4apzy4GYG7455GNvqCtTOCWiXDETjAWwp6c9V/vJ088DtDxADrvA+hAQt6zpFdy lk+7WD7JeynbfeTTTgM99wZdu2ExbjEBcrVCWqxABt3EZ128YbtpcYfmTFg+ZeKT OmSk6BTO7+KuEGH7ZbtUXT2dY+7Kba7ls0s0cN42MC8evn3mQgy0vA9++YAC5lJ/ cg00uZuGXEOV/y/tDggj99TbyiTWSv3v7Fctcg0ge5Eqe5E/e5G7dynYu5G/T75D dt6nSLVP0cVzaUpNkfzu8yxS9dthzVPvU6aQ5mgZi6T9sw3fVFZuYAeRC0XMdbg3 6GGLBYXHndfGTsvyEMigzQ1koS+HlqnHFQLvZylsiiTm8hRu3w0qnpHy6bHyDz/9 9ncmDLqpybup+T0bJjtbjBRpu+FkwYAODzdS36kOP9iO5yJR5lxQ/uNjIW5w5w1/ M7Bd/p1bswSSexpMOGbkQtTF1Rf8/Utut1smLDwWgxa3/73DQjyXdjvn//bRlDqE Yj8ndzBZrHKSccKLDEOvDBd483n28xM774ehwIPELfcbtDOFN0u8Kn04qc6hyGkn ti+ZUleOBrJeVyO8KLY3PwaewAhEM+DKc3ruCzlyDm1DZcptp5XDqaOGuLsSrPOv 40tX9Up6HlGdYqJ1p4djYcOlrPcya3LsnTJwUnJ2xya+VvUbyUs5nqf34uzZeJLE T2aejaNG5btj9eimIc0SDeboR6bMYuHOoRuwG6pMKdzodBkKgG5Kc6+y4xNJ9foY -----END LICENSE----- ``` -------------------------------- ### Package Kubesphere Extension with ksbuilder Source: https://dev-guide.kubesphere.io/extension-dev-guide/zh/packaging-and-release/packaging This command utilizes the `ksbuilder package` tool to package a Kubesphere extension component into a compressed `.tgz` file. This packaged file is suitable for distribution and deployment, simplifying the extension management process. ```shell cd extensions ksbuilder package hello-world ```