我正在尝试将命令执行到 pod 中,但我不断收到错误消息 unable to upgrade connection: Forbidden
我正在尝试通过kubectl proxy对所有其他操作(例如创建部署或删除它)有效的方法来测试我在开发中的代码,但是它不适用于执行命令,我读到我需要pods/exec,所以我创建了一个具有此类角色的服务帐户喜欢
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dev-sa
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-view-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-exec-view-role
rules:
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["get","create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods-svc-account
namespace: default
subjects:
- kind: ServiceAccount
name: dev-sa
roleRef:
kind: Role
name: pod-view-role
apiGroup: rbac.authorization.k8s.io
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods-exec-svc-account
namespace: default
subjects:
- kind: ServiceAccount
name: dev-sa
roleRef:
kind: Role
name: pod-exec-view-role
apiGroup: rbac.authorization.k8s.io
然后我检索服务帐户的不记名令牌并尝试在我的代码中使用它
func getK8sConfig() *rest.Config {
// creates the in-cluster config
var config *rest.Config
fmt.Println(os.Getenv("DEVELOPMENT"))
if os.Getenv("DEVELOPMENT") != "" {
//when doing local development, mount k8s api via `kubectl proxy`
fmt.Println("DEVELOPMENT")
config = &rest.Config{
Host: "http://localhost:8001",
TLSClientConfig: rest.TLSClientConfig{Insecure: true},
APIPath: "/",
BearerToken: "eyJhbGciOiJSUzI1NiIsImtpZCI6InFETTJ6R21jMS1NRVpTOER0SnUwdVg1Q05XeDZLV2NKVTdMUnlsZWtUa28ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRldi1zYS10b2tlbi14eGxuaiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZXYtc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmZDVhMzRjNy0wZTkwLTQxNTctYmY0Zi02Yjg4MzIwYWIzMDgiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZXYtc2EifQ.woZ6Bmkkw-BMV-_UX0Y-S_Lkb6H9zqKZX2aNhyy7valbYIZfIzrDqJYWV9q2SwCP20jBfdsDS40nDcMnHJPE5jZHkTajAV6eAnoq4EspRqORtLGFnVV-JR-okxtvhhQpsw5MdZacJk36ED6Hg8If5uTOF7VF5r70dP7WYBMFiZ3HSlJBnbu7QoTKFmbJ1MafsTQ2RBA37IJPkqi3OHvPadTux6UdMI8LlY7bLkZkaryYR36kwIzSqsYgsnefmm4eZkZzpCeyS9scm9lPjeyQTyCAhftlxfw8m_fsV0EDhmybZCjgJi4R49leJYkHdpnCSkubj87kJAbGMwvLhMhFFQ",
}
} else {
var err error
config, err = rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
}
return config
}
然后我尝试运行OpenShift 示例以执行到 pod
// Determine the Namespace referenced by the current context in the
// kubeconfig file.
namespace := "default"
// Get a rest.Config from the kubeconfig file. This will be passed into all
// the client objects we create.
restconfig := getK8sConfig()
// Create a Kubernetes core/v1 client.
coreclient, err := corev1client.NewForConfig(restconfig)
if err != nil {
panic(err)
}
// Create a busybox Pod. By running `cat`, the Pod will sit and do nothing.
var zero int64
pod, err := coreclient.Pods(namespace).Create(&corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "busybox",
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "busybox",
Image: "busybox",
Command: []string{"cat"},
Stdin: true,
},
},
TerminationGracePeriodSeconds: &zero,
},
})
if err != nil {
panic(err)
}
// Delete the Pod before we exit.
defer coreclient.Pods(namespace).Delete(pod.Name, &metav1.DeleteOptions{})
// Wait for the Pod to indicate Ready == True.
watcher, err := coreclient.Pods(namespace).Watch(
metav1.SingleObject(pod.ObjectMeta),
)
if err != nil {
panic(err)
}
for event := range watcher.ResultChan() {
switch event.Type {
case watch.Modified:
pod = event.Object.(*corev1.Pod)
// If the Pod contains a status condition Ready == True, stop
// watching.
for _, cond := range pod.Status.Conditions {
if cond.Type == corev1.PodReady &&
cond.Status == corev1.ConditionTrue {
watcher.Stop()
}
}
default:
panic("unexpected event type " + event.Type)
}
}
// Prepare the API URL used to execute another process within the Pod. In
// this case, we'll run a remote shell.
req := coreclient.RESTClient().
Post().
Namespace(pod.Namespace).
Resource("pods").
Name(pod.Name).
SubResource("exec").
VersionedParams(&corev1.PodExecOptions{
Container: pod.Spec.Containers[0].Name,
Command: []string{"date"},
Stdin: true,
Stdout: true,
Stderr: true,
TTY: true,
}, scheme.ParameterCodec)
exec, err := remotecommand.NewSPDYExecutor(restconfig, "POST", req.URL())
if err != nil {
panic(err)
}
// Connect this process' std{in,out,err} to the remote shell process.
err = exec.Stream(remotecommand.StreamOptions{
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
Tty: true,
})
if err != nil {
panic(err)
}
fmt.Println("done")
所以看起来不记名令牌被忽略了,而不是我获得了 kubectl 管理员的权限。
如何强制其余客户端使用提供的不记名令牌?这是在 pod 中执行命令的正确方法吗?