Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions apps/rlark/docs/examples/agent-rbac.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Agent RBAC
# Applied by quickstart.sh to each kind data plane cluster.
# Applied by quickstart.sh and quickstart-dp.sh to each kind data plane cluster.
apiVersion: v1
kind: ServiceAccount
metadata:
Expand All @@ -14,6 +14,10 @@ rules:
- apiGroups: [""]
resources: ["nodes", "pods", "pods/log", "services", "configmaps", "secrets", "namespaces", "persistentvolumeclaims", "events"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# WebTerminal opens a container session with POST pods/exec.
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
Expand All @@ -38,4 +42,4 @@ roleRef:
subjects:
- kind: ServiceAccount
name: rlark-agent
namespace: rlark-system
namespace: rlark-system
12 changes: 12 additions & 0 deletions apps/rlark/docs/user-guide/jobs.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ You can open an interactive terminal directly into the main container of any run

From the Worker list, click **Terminal** on any running Worker. This opens `/bin/bash` by default in the Worker's main container. The browser establishes a WebSocket to Gateway, which proxies the session through Server to Agent and then execs into the container. The user does not need to log in with SSH.

### Troubleshooting Permission Errors

If the terminal reports `cannot create resource "pods/exec"`, the data-plane Agent's ServiceAccount lacks permission to execute commands in containers. Ask an administrator to grant the Agent `create` access to `pods/exec` in the target data-plane cluster. For quickstart deployments, reapply the updated RBAC manifest from the repository root:

```bash
kubectl --kubeconfig <data-plane-kubeconfig> apply -f apps/rlark/docs/examples/agent-rbac.yaml
kubectl --kubeconfig <data-plane-kubeconfig> auth can-i create pods --subresource=exec \
-n rlark-system --as=system:serviceaccount:rlark-system:rlark-agent
```

Once the check returns `yes`, reopen the terminal; no Agent or Worker restart is required. Apply these permissions to the data-plane Kubernetes cluster, not the control-plane kcp instance.

### Diagnostic Commands

Once inside the terminal, you can run diagnostic commands to inspect the container environment:
Expand Down
12 changes: 12 additions & 0 deletions apps/rlark/docs/zh/user-guide/jobs.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ RLark 支持以下任务类型,每种类型预配置了适合该工作负载

在 Worker 列表中点击任意运行中 Worker 的**终端**操作,默认会在其主容器中打开 `/bin/bash`。浏览器通过 WebSocket 连接 Gateway,再由 Gateway 经 Server 代理到 Agent,最终 exec 进入容器;用户无需进行 SSH 登录。

### 权限错误排查

如果终端提示 `cannot create resource "pods/exec"`,说明数据面 Agent 的 ServiceAccount 缺少执行容器命令的权限。请管理员在目标数据面集群为 Agent 授予 `pods/exec` 的 `create` 权限。使用快速开始部署的集群,可以在仓库根目录重新应用更新后的 RBAC 清单:

```bash
kubectl --kubeconfig <数据面-kubeconfig> apply -f apps/rlark/docs/examples/agent-rbac.yaml
kubectl --kubeconfig <数据面-kubeconfig> auth can-i create pods --subresource=exec \
-n rlark-system --as=system:serviceaccount:rlark-system:rlark-agent
```

确认返回 `yes` 后重新打开终端,无需重启 Agent 或 Worker。该权限配置在数据面 Kubernetes 集群中,不是在控制面的 kcp 中。

### 诊断命令

进入终端后可运行诊断命令检查容器环境:
Expand Down
77 changes: 77 additions & 0 deletions apps/rlark/pkg/agent/rbac_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package agent

import (
"io"
"os"
"slices"
"testing"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/kubernetes/scheme"
)

func TestQuickstartAgentTerminalRBAC(t *testing.T) {
manifest, err := os.Open("../../docs/examples/agent-rbac.yaml")
require.NoError(t, err)
defer func() { require.NoError(t, manifest.Close()) }()

var account *corev1.ServiceAccount
var role *rbacv1.ClusterRole
var binding *rbacv1.ClusterRoleBinding
decoder := yaml.NewYAMLOrJSONDecoder(manifest, 4096)
for {
var raw runtime.RawExtension
err := decoder.Decode(&raw)
if err == io.EOF {
break
}
require.NoError(t, err)
obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(raw.Raw, nil, nil)
require.NoError(t, err)
switch obj := obj.(type) {
case *corev1.ServiceAccount:
account = obj
case *rbacv1.ClusterRole:
role = obj
case *rbacv1.ClusterRoleBinding:
binding = obj
}
}
require.NotNil(t, account)
require.NotNil(t, role)
require.NotNil(t, binding)
require.Equal(t, "rlark-agent", account.Name)
require.Equal(t, "rlark-system", account.Namespace)
require.Equal(t, rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: role.Name}, binding.RoleRef)
require.Contains(t, binding.Subjects, rbacv1.Subject{Kind: "ServiceAccount", Name: account.Name, Namespace: account.Namespace})

// handleTerminal uses POST pods/exec. Ordinary Pod access does not grant
// access to this subresource, and exec does not need mutation verbs other
// than create.
for _, tt := range []struct {
verb string
want bool
}{
{"create", true},
{"delete", false},
{"patch", false},
{"update", false},
} {
t.Run(tt.verb, func(t *testing.T) {
allowed := false
for _, rule := range role.Rules {
if len(rule.ResourceNames) == 0 &&
(slices.Contains(rule.APIGroups, "") || slices.Contains(rule.APIGroups, "*")) &&
(slices.Contains(rule.Resources, "pods/exec") || slices.Contains(rule.Resources, "*")) &&
(slices.Contains(rule.Verbs, tt.verb) || slices.Contains(rule.Verbs, "*")) {
allowed = true
}
}
require.Equal(t, tt.want, allowed)
})
}
}