Skip to content

Commit

Permalink
local debug web terminal
Browse files Browse the repository at this point in the history
  • Loading branch information
stringang committed Apr 9, 2024
1 parent 77e4a2c commit bab7c0a
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 48 deletions.
56 changes: 56 additions & 0 deletions docs/local-dev-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# local dev guide
基于 `release-4.11` 版本

1. 根据[文档说明](../README.md#build-everything)进行编译(frontend/backend)
2. [配置参数启动](../README.md#native-kubernetes)

本地运行示例:
```shell
KUBERNETES_SERVICE_HOST=10.255.0.50 KUBERNETES_SERVICE_PORT=6443 ./bin/bridge \
--base-address=http://localhost:9000 \
--k8s-auth=bearer-token \
--k8s-mode=off-cluster \
--k8s-mode-off-cluster-endpoint="https://10.255.0.50:6443" \
--k8s-mode-off-cluster-skip-verify-tls=true \
--listen=http://127.0.0.1:9000 \
--public-dir=./frontend/public/dist \
--user-auth=disabled \
--k8s-auth-bearer-token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjhLUWZxcXo3UjNyejJjOVNHNFlrVldBN2JWXzUwOTByeU9namNRQU5QLTQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tbnQybm0iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImQ0MDJkMTFiLWE4NmUtNGQ3Yi1iYTc2LTQyNTgxYjM0NDJlNSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.am-jsAALyXMGjxZJ7Sh5302EI4a061ekUfY_CcRD3f8y7JLdOTpKB-SqxaPRexFKZQ3RbM3egZnoz5iTa2NXwkQGvmd5c66Er57rrEKZOU7OenKGcnBuVej-F5VdIpYfM93Zdz7FKUFx07L_PlHTw-taA8y4PRfsHn14aOnUB8pma3sv1ri8O3SGiEga7489XbyMQmbM1FdyfFol5aO13JqGn2o_avFtFH7fGgfoL5BgW6aaMoPGiAPn86qDnKqEHvqNWsCfQMEo7c5LukK1Fr2xc8qTHqCy4I2suGtOwf5GMLhnmvdxkQXNgHljjPZ9Z2YnLNNrl8xDqOPzgAywYw
```

## web-terminal 插件

运行 web-terminal 前置条件:
1. 机器安装 [operator-sdk](https://github.com/operator-framework/operator-sdk/releases)
2. 通过 operator-sdk 安装 OLM(`operator-sdk olm install`)
i. 会部署 olm operator
3. 通过 OLM 安装 web-terminal-operator
i. 添加 [CatalogSource](https://github.com/redhat-developer/web-terminal-operator/blob/main/catalog-source.yaml)
i. web-terminal-operator 会自动安装 devworkspace-operator 依赖
4. 【省略】通过 OLM 安装 devworkspace-operator 或者直接通过 [manifests](https://github.com/devfile/devworkspace-operator/blob/v0.26.0/deploy/deployment/kubernetes/combined.yaml) 文件直接部署
i. 添加 CatalogSource
i. 再通过 OperatorHub 安装 devworkspace operator
i. 手动添加 devworkspace operator webhook cert-manager 配置后,安装成功
5. 默认以 in-cluster 运行模式,配置 serviceaccount 信息(`kubernetes.default`)
```shell
sudo mkdir -p /var/run/secrets/kubernetes.io/serviceaccount
sudo vim /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
sudo vim /var/run/secrets/kubernetes.io/serviceaccount/token
```

### [代码逻辑](../pkg/terminal/proxy.go#L179)
1. terminal icon 显示
i. [web terminal 插件路由注册](../pkg/server/server.go#L337)
i. 判断是否安装 web-terminal-operator(`kubectl get subscriptions -A --field-selector='metadata.name=web-terminal'`)
i. 判断 webhook 是否启动
i. 创建 kubernetes REST client(service account),判断是否运行在集群内(根据 `KUBERNETES_SERVICE_HOST`,`KUBERNETES_SERVICE_PORT` 判断),读取 Pod `serviceaccount` 证书信息。每个 pod 会默认生成 `serviceaccount` 并注入到 pod 中。(用于 `api-server` 认证 )`/var/run/secrets/kubernetes.io/serviceaccount/token`
i. `kubectl get mutatingwebhookconfigurations controller.devfile.io`
i. `kubectl get validatingwebhookconfigurations controller.devfile.io`
2. 运行 terminal
i. 前端请求 `/api/kubernetes/apis/workspace.devfile.io/v1alpha2/namespaces/openshift-terminal/devworkspaces`
i.

### 问题:
1. 影响 Pod exec(`kubectl exec -ti`),需要删除 webhook,原因是 webhook 证书问题
i. `kubectl delete mutatingwebhookconfigurations controller.devfile.io`
i. `kubectl delete validatingwebhookconfigurations controller.devfile.io`
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,19 @@ const CloudShellTerminal: React.FC<CloudShellTerminalProps &
setWorkspaceName,
setWorkspaceNamespace,
}) => {
// web-terminal operator 安装 namespace,用于判断 plugin 资源
const [operatorNamespace, namespaceLoadError] = useCloudShellNamespace();
const [initData, setInitData] = React.useState<TerminalInitData>();
const [initError, setInitError] = React.useState<string>();
// 判断权限
const [isAdmin, isAdminCheckLoading] = useAccessReview2({
namespace: 'openshift-terminal',
verb: 'create',
resource: 'pods',
});
const isv1Alpha2Available = useFlag(FLAG_V1ALPHA2DEVWORKSPACE);
const workspaceModel = !isv1Alpha2Available ? v1alpha1WorkspaceModel : WorkspaceModel;
// 查询正在使用的 workspace Pod 资源
const [workspace, loaded, loadError] = useCloudShellWorkspace(
user,
isAdmin,
Expand Down Expand Up @@ -137,11 +140,13 @@ const CloudShellTerminal: React.FC<CloudShellTerminalProps &
}, [unrecoverableErrorFound, username, workspaceName, workspaceNamespace]);

// initialize the terminal once it is Running
// workspace 运行后,初始化 terminal
React.useEffect(() => {
let unmounted = false;
const defaultError = t('console-app~Failed to connect to your OpenShift command line terminal');

if (workspacePhase === CLOUD_SHELL_PHASE.RUNNING) {
// 初始化
initTerminal(username, workspaceName, workspaceNamespace)
.then((res: TerminalInitData) => {
if (!unmounted) setInitData(res);
Expand Down Expand Up @@ -223,6 +228,7 @@ const CloudShellTerminal: React.FC<CloudShellTerminalProps &
);
}

// 创建 workspace
if (isAdmin) {
return (
<CloudShellAdminSetup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const newCloudShellWorkSpace = (
namespace: workspaceNamespace,
labels: {
[CLOUD_SHELL_LABEL]: 'true',
[CLOUD_SHELL_CREATOR_LABEL]: 'liugang-test',
},
annotations: {
[CLOUD_SHELL_RESTRICTED_ANNOTATION]: 'true',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const useCloudShellWorkspace = (
selector: {
matchLabels: {
[CLOUD_SHELL_LABEL]: 'true',
[CLOUD_SHELL_CREATOR_LABEL]: isKubeAdmin ? '' : uid,
[CLOUD_SHELL_CREATOR_LABEL]: isKubeAdmin ? 'liugang-test' : 'liugang-test',
},
},
};
Expand All @@ -82,6 +82,7 @@ const useCloudShellWorkspace = (
]);

// call k8s api to fetch workspace
// 查询 workspace pod 资源
const [data, loaded, loadError] = useK8sWatchResource<CloudShellResource[]>(resource);
const workspace = findWorkspace(data);

Expand Down
25 changes: 0 additions & 25 deletions pkg/terminal/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

Expand All @@ -34,30 +33,6 @@ const (
// checkWebTerminalOperatorIsRunning checks if the workspace operator is running and webhooks are enabled,
// which is a prerequisite for sending a user's token to a workspace.
func checkWebTerminalOperatorIsRunning() (bool, error) {
config, err := rest.InClusterConfig()
if err != nil {
return false, err
}
client, err := kubernetes.NewForConfig(config)
if err != nil {
return false, err
}

_, err = client.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), webhookName, metav1.GetOptions{})
if err != nil {
if k8sErrors.IsNotFound(err) {
return false, nil
}
return false, err
}

_, err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), webhookName, metav1.GetOptions{})
if err != nil {
if k8sErrors.IsNotFound(err) {
return false, nil
}
return false, err
}
return true, nil
}

Expand Down
26 changes: 4 additions & 22 deletions pkg/terminal/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ func (p *Proxy) HandleProxy(user *auth.User, w http.ResponseWriter, r *http.Requ
return
}

println(user)

isClusterAdmin, err := p.isClusterAdmin(user.Token)
if err != nil {
http.Error(w, "Failed to check the current users privileges. Cause: "+err.Error(), http.StatusInternalServerError)
Expand All @@ -119,7 +121,7 @@ func (p *Proxy) HandleProxy(user *auth.User, w http.ResponseWriter, r *http.Requ
return
}

userId := user.ID
userId := "liugang-test"
if userId == "" {
// user id is missing, auth is used that does not support user info propagated, like OpenShift OAuth
userInfo, err := client.Resource(UserGroupVersionResource).Get(context.TODO(), "~", metav1.GetOptions{})
Expand Down Expand Up @@ -183,28 +185,8 @@ func (p *Proxy) HandleProxyEnabled(w http.ResponseWriter, r *http.Request) {
return
}

isWebTerminalOperatorInstalled, err := checkWebTerminalOperatorIsInstalled()
if err != nil {
klog.Errorf("Failed to check if the web terminal operator is installed: %s", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !isWebTerminalOperatorInstalled {
klog.Error("web terminal operator is not installed")
w.WriteHeader(http.StatusServiceUnavailable)
return
}
isWebTerminalOperatorRunning, err := checkWebTerminalOperatorIsRunning()
if err != nil {
klog.Errorf("Failed to check if web terminal operator is running: %s", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !isWebTerminalOperatorRunning {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusNoContent)
return
}

func (p *Proxy) HandleTerminalInstalledNamespace(w http.ResponseWriter, r *http.Request) {
Expand Down

0 comments on commit bab7c0a

Please sign in to comment.