KubeSphere 扩展组件开发笔记

前段时间参加了云原生 Meetup 杭州站活动,正好在这次活动上了解到了 KubeSphere 正在开展扩展组件开发训练营于是报名了这个活动,记录下学习过程。

0x00 说明

资料来源:

0x01 开发环境搭建

开发需要一个 ks 集群,可以使用 KubeSphere 官方提供的ks-dev环境,也可以自己搭建一个 ks 集群。

使用ks-dev环境

https://kubesphere.cloud/sign-up/?ref=REAwGESiNA 可以在这里注册一个账号,然后在控制台创建一个 ks 集群。

官方每个月会赠送 10h 的免费使用时间,可以用来开发测试。

本地安装

Node 使用 nvm 安装

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 18

安装 yarn

npm install --global yarn

安装 helm

这里官方提供了文件和脚本两种安装方式,因为是专门为了开发扩展组件开的环境所以为了省事直接脚本安装

https://helm.sh/docs/intro/install/

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

安装 kubectl

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo chmod +x kubectl 
sudo mv kubectl /usr/local/bin

安装完成以后去 ks 面板下载 kubeconfig 文件放到 ~/.kube/config 目录下

安装 `ksbuilder

wget https://github.com/kubesphere/ksbuilder/releases/download/v0.3.13/ksbuilder_0.3.13_linux_amd64.tar.gz
tar -zxf ksbuilder_0.3.13_linux_amd64.tar.gz
sudo mv ksbuilder /usr/local/bin

检查安装版本

sonui@server:~$ ksbuilder --version
ksbuilder version 0.3.13
sonui@server:~$ node --version
v18.20.2
sonui@server:~$ yarn --version
1.22.22
sonui@server:~$ helm version
version.BuildInfo{Version:"v3.14.4", GitCommit:"81c902a123462fd4052bc5e9aa9c513c4c8fc142", GitTreeState:"clean", GoVersion:"go1.21.9"}
sonui@server:~$ kubectl version
Client Version: v1.30.0
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
sonui@server:~$ kubectl get node
NAME   STATUS   ROLES                         AGE   VERSION
ks     Ready    control-plane,master,worker   15d   v1.23.10
sonui@server:~$ kubectl -n kubesphere-system get po
NAME                                     READY   STATUS    RESTARTS        AGE
ks-apiserver-754d47ffcc-fx5fz            1/1     Running   2 (6d21h ago)   15d
ks-console-54958f4674-8s225              1/1     Running   2 (6d21h ago)   15d
ks-controller-manager-59d55bc77b-vgnl7   1/1     Running   2 (6d21h ago)   15d

编写 ks-apiserver 反向代理

参考官方示例

https://raw.githubusercontent.com/kubesphere/extension-samples/master/extensions-backend/weave-scope/weave-scope-reverse-proxy.yaml

修改为 argocd

apiVersion: extensions.kubesphere.io/v1alpha1
kind: ReverseProxy
metadata:
  name: argocd-scope
spec:
  matcher:
    method: '*'
    path: /proxy/argocd.works/*
  upstream:
    url: http://argocd-server.argocd.svc/proxy/argocd.works/
    # url: http://192.168.2.128:8080/proxy/argocd.works/ # 后面调试用到的
  directives:
    authProxy: true
    headerUp:
    - '-Authorization'
status:
  state: Available

其中 upstream.url 为 argocd 的服务地址

http://[service name].[namespace].svc

部署 ArgoCD

部署 ArgoCD 时需要修改下部署参数

首先创建一个 kustomization.yaml 文件

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
resources:
- github.com/argoproj/argo-cd/manifests/cluster-install?ref=v2.10.0 # 使用稳定版本

# 配置patches来修改argocd-server的配置
patches:
- path: argocd-server-config-patch.yaml
  target:
    kind: ConfigMap
    name: argocd-cmd-params-cm

argocd-server-config-patch.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  # 设置UI Base Path
  server.basehref: "/proxy/argocd.works/"  # 注意结尾的斜杠
  server.insecure: "true"      # 禁用 TLS
  server.rootpath: "/proxy/argocd.works"

basehref 配置说明
about basehref config

If the Argo CD UI is available under a non-root path (e.g. /argo-cd instead of /) then the UI path should be configured in the API server. To configure the UI path add the --basehref flag into the argocd-server deployment command
https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#ui-base-path

然后执行 kubectl apply -k . 重新部署 ArgoCD

如果这个配置没有生效可以执行 kubectl rollout restart deployment argocd-server -n argocd 重启下服务使更改生效

设置前端反向代理

插件设置下 webpack.config.js,如果不设置的话在浏览器中访问 ArgoCD 面板会提示404错误

ks-console/configs/webpack.config.js

const { merge } = require('webpack-merge');
const baseConfig = require('@ks-console/bootstrap/webpack/webpack.dev.conf');

const webpackDevConfig = merge(baseConfig, {
  devServer: {
    proxy: {
      '/proxy': {
        target: 'http://192.168.2.128:30880', // 修改为目标 ks-apiserver 的地址
        onProxyReq: (proxyReq, req, res) => {
            const username = 'admin'        // 请求代理时的用户凭证
            const password = 'P@88w0rd'
            const auth = Buffer.from(`${username}:${password}`).toString("base64");
            proxyReq.setHeader('Authorization', `Basic ${auth}`);
          },
      },
    },
  },
});

module.exports = webpackDevConfig;

设置好以后需要重启下 yarn dev 使更改生效

0x02 调试

全部完成后访问控制面板可以看到弹出 ArgoCD 登录界面

ArgoCD login page in KubeSphere dashboard

按照文档说明尝试登录出现进入面板后又回到登录界面的问题,F12 查看有接口返回 401 错误,猜测可能是传递给 ArgoCD 服务的这两个请求没有认证信息

f12 dashboard

根据官方调试教程本地起了一个 ArgoCD 服务,然后修改 ReverseProxyupstream.url 为本地 ArgoCD 服务地址

对官方文档中的 vscode 调试配置做了下修改

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug ArgoCD Server",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspaceFolder}/argo-cd/cmd/main.go",
            "env": {
                "ARGOCD_BINARY_NAME": "argocd-server",
                "CGO_ENABLED": "0",
                "KUBECONFIG": "/home/sonui/.kube/config",
            },
            "envFile": [
                "${workspaceFolder}/.envrc.remote",
            ],
            "args": [
                "--insecure",
                "--rootpath",
                "/proxy/argocd.works/",
                "--basehref",
                "/proxy/argocd.works/"
            ]
        }
    ]
}

https://github.com/argoproj/argo-cd/blob/a7637cd106f615119930439d963ec0a9618b404d/server/server.go#L1037 添加请求头打印

    gwMuxOpts := runtime.WithMarshalerOption(runtime.MIMEWildcard, new(grpc_util.JSONMarshaler))
    gwCookieOpts := runtime.WithForwardResponseOption(a.translateGrpcCookieHeader)
    gwmux := runtime.NewServeMux(gwMuxOpts, gwCookieOpts)

    var handler http.Handler = gwmux
    if a.EnableGZip {
        handler = compressHandler(handler)
    }
    if len(a.ContentTypes) > 0 {
        handler = enforceContentTypes(handler, a.ContentTypes)
    } else {
        log.WithField(common.SecurityField, common.SecurityHigh).Warnf("Content-Type enforcement is disabled, which may make your API vulnerable to CSRF attacks")
    }

    logMiddleware := func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // 打印基本请求信息
            log.WithFields(log.Fields{
                "method":     r.Method,
                "url":        r.URL.String(),
                "headers":    r.Header,
                "remoteAddr": r.RemoteAddr,
                "host":       r.Host,
                "requestURI": r.RequestURI,
            }).Info("Incoming HTTP request")

            next.ServeHTTP(w, r)
        })
    }
    handler = logMiddleware(handler)
    mux.Handle("/api/", handler)

发起请求

request header

可以在浏览器开发者工具中看到请求头中有 Cookie 信息,而 ArgoCD 打印的日志没有

argocd log

如果在上面的日志代码中手动写死一个 Cookie 信息再请求能看到接口返回正常,确定是反向代理的问题,待联系ks技术问问,这里先写死继续后续开发

刷新页面提示 open dist/app/index.html: file does not exist 错误,添加下启动配置

进入 ArgoCD 代码目录下的 ui 目录,执行 build 命令生成 dist 目录,拷贝出来绝对地址填入下面的位置

          "args": [
                // ... 其它配置
                "--staticassets",
                "/path/to/argo-cd"
          ]

重启 ArgoCD 服务,刷新浏览器页面可以看到正常进入 ArgoCD 面板

ArgoCD dashboard

待解决 Cookie 问题后再对接 OAuth 认证
OAuth 对接文档

posted @ 2024-07-17 10:00  Sonui  阅读(7)  评论(0编辑  收藏  举报