如何在容器内运行 kubectl 命令?

72
在一个Pod内的容器中,如何使用kubectl运行命令?例如,在容器内需要执行以下命令:
kubectl get pods
我尝试过在我的Dockerfile中添加以下命令:
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
RUN chmod +x ./kubectl
RUN sudo mv ./kubectl /usr/local/bin/kubectl

编辑:我一开始使用的是OSX文件,现已更正为Linux二进制文件。(由@svenwltr更正)

在创建Docker文件时成功了,但是当我在容器内运行 kubectl get pods 命令时出错。

kubectl get pods

我遇到了这个错误:

连接服务器被拒绝 - 您是否指定了正确的主机或端口?

当我在本地部署时,如果我的docker-machine没有运行,我就会遇到这个错误,但在容器内部,docker-machine如何运行呢?

在本地,我通过运行以下命令来解决此错误:(dev是docker-machine的名称)

docker-machine env dev
eval $(docker-machine env dev)

有人能告诉我需要做什么吗?


我很困惑。你是在Kubernetes中运行那个容器还是在Docker机器中? - svenwltr
@svenwltr - 我正在本地的minikube上运行kubernetes,并建议在kubernetes VM中使用docker守护程序。 - Dreams
7个回答

48

我会使用Kubernetes API,你只需要安装curl,而不是使用kubectl,其余的就是restful。

curl http://localhost:8080/api/v1/namespaces/default/pods

我正在我的一个API服务器上运行以上命令。将 localhost 更改为 apiserver IP地址/ DNS名称

根据您的配置,您可能需要使用SSL或提供客户端证书。

为了查找API端点,您可以在kubectl中使用--v=8

示例:

kubectl get pods --v=8

资源:

Kubernetes API 文档

RBAC 更新:

我假设您已经配置了 RBAC,并为您的 Pod 创建了一个服务帐户并使用它运行。此服务帐户应该在所需的命名空间中具有对 Pod 的列表权限。为此,您需要为该服务帐户创建角色和角色绑定。

集群中的每个容器都填充有一个令牌,可用于对 API 服务器进行身份验证。要验证,请在容器内部运行:

cat /var/run/secrets/kubernetes.io/serviceaccount/token

要向API服务器发出请求,在容器内运行:

curl -ik \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/api/v1/namespaces/default/pods

我尝试了您建议的答案,但是它给了我另一个错误 - curl: (7) 无法连接到192.168.99.100端口8080:连接被拒绝。虽然我能够执行kubectl get pods命令。此外,当我运行netstat -atn命令检查打开的端口时,在特定IP上没有显示打开的端口。 - Dreams
@Tarun 192.168.99.100 是API服务器的IP地址,对吧?顺便说一下,我刚刚在我的设置中测试了一下,它运行正常。 - Farhad Farahi
是的,我正在minikube上运行kubernetes。这是minikube的ip。我犯了一个错误,我试图使用端口8080。但是,当我尝试 kubectl config view 时,它显示端口8443。此外,当我检查API端点时,它显示我的是“https”。你的情况也是这样吗?当我尝试使用https时,我遇到了ssl错误(curl: (60) SSL证书问题:无效的证书链)。我正在努力解决它,解决错误后会立即更新。 - Dreams
@Tarun 我正在生产环境中,尝试在你的curl命令中加入--insecure选项。你是否有ca.pemclient.pemclient-key.pem这些文件?如果有,你可以尝试使用以下命令:curl https://ip:8443/api/v1/namespaces/default/pods --cacert ca.pem --insecure --key client-key.pem --cert client.pem - Farhad Farahi
我尝试了--insecure,但它并没有解决问题。是的,我没有.pem文件,我会尝试添加它们并尽快更新。再次感谢! :) - Dreams
虽然这个答案允许您查询API,但它并没有解决问题。请参见https://dev59.com/aVgQ5IYBdhLWcg3whERn#42651673获取真正的答案。 为了玩弄API,我建议使用“kubectl代理”,您可以在本地计算机上运行它。 - tamerlaha

42

有点晚了,但这是我的意见:

我发现在容器内使用 kubectl 比调用集群的 API 更方便。

(为什么呢?自动认证!)

比如你要部署一个需要使用 kubectl 的 Node.js 项目。

  1. 在容器内下载并构建 kubectl
  2. 构建你的应用程序,并将 kubectl 复制到容器中
  3. 完成! kubectl 提供了一个丰富的 CLI,用于管理你的 Kubernetes 集群

有用的文档

--- 编辑 ---

在我的集群 pod 中使用 kubectl 后,我发现了一种更有效的方法来验证 pod 能够进行 k8s API 调用。这种方法提供了更严格的身份验证。

  1. 为你的 pod 创建一个 ServiceAccount 并配置你的 pod 使用该帐户。k8s Service Account 文档
  2. 配置一个 RoleBindingClusterRoleBinding,以允许服务授权与 k8s API 通信。k8s Role Binding 文档
  3. 直接调用 API,或者使用 k8s-client 为您管理 API 调用。我强烈推荐使用客户端,它具有自动配置 pod 的功能,可以省去常规请求所需的身份验证令牌步骤。

完成后,你将拥有以下内容:ServiceAccountClusterRoleBindingDeployment(你的 pod)

如果需要更清晰的指导,请随时评论,我会尽力帮助 :)

全功能示例

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: k8s-101
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: k8s-101
    spec:
      serviceAccountName: k8s-101-role
      containers:
      - name: k8s-101
        imagePullPolicy: Always
        image: salathielgenese/k8s-101
        ports:
        - name: app
          containerPort: 3000
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: k8s-101-role
subjects:
- kind: ServiceAccount
  name: k8s-101-role
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: k8s-101-role

salathielgenese/k8s-101镜像包含kubectl。因此,可以直接登录到Pod容器并执行kubectl,就好像在k8s主机上运行它一样:kubectl exec -it pod-container-id -- kubectl get pods


你能详细描述一下如何连接 API 的部分吗? - Berndinox
1
@Berndinox 当然可以!所有的 kubectl 命令都可以通过命令行输入。使用 Node 的 fork 子进程,您可以执行这些命令。在执行其他命令之前,请确保初始化 kubectl proxy。要使用 kubectl 构建 Docker 镜像:https://pastebin.com/6a8kp6aR - mster
1
作为一个k8s初学者,上述指令听起来很神奇,但我找到了一些帮助将其翻译成一些配置 - https://kubernetes.slack.com/archives/C09NXKJKA/p1555058986037900?thread_ts=1555049081.017200&cid=C09NXKJKA。因此,我将进行编辑以提供一个示例。 - Salathiel Genèse
@mster,你能帮我看一下这个Dockerfile吗?我想在容器里安装kubectl,但是出现了错误:“failed to solve with frontend dockerfile.v0: failed to create LLB definition: circular dependency detected on stage: kubectl”。这是我的Dockerfile链接:https://pastebin.com/Lqb1py64。 - Lucas Scheepers
1
永远不要给予集群管理员权限,除非确实需要。除此之外,该解决方案似乎是可行的。 - Dorian Gaensslen

21

第一个问题

/usr/local/bin/kubectl: 无法执行二进制文件

看起来您下载了kubectl的OSX二进制文件。在Docker中运行时,您可能需要Linux版本:

https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

第二个问题

如果在正确配置的 Kubernetes 群集中运行 kubectl,它应该能够连接到 apiserver。

kubectl 基本上使用此代码来查找 apiserver 和进行身份验证:github.com/kubernetes/client-go/rest.InClusterConfig

这意味着:

  • apiserver 的主机和端口存储在环境变量 KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT 中。
  • 访问令牌挂载到 var/run/secrets/kubernetes.io/serviceaccount/token
  • 服务器证书挂载到 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

这是 kubectl 所需了解的所有数据以连接到 apiserver。

一些思考,为什么可能不起作用:

  • 容器在 Kubernetes 中无法运行。
    • 仅仅使用相同的 Docker 主机是不够的,容器需要作为 pod 定义的一部分运行。
  • 使用 授权插件(非默认)限制了访问。
  • Pod 定义spec.serviceAccountName)覆盖了服务账户凭据。

是的,谢谢你指出来。我已经为Linux做了必要的更改。但是,我仍然遇到另一个错误,我会更新问题的描述。 :) - Dreams
我更新了答案。不确定我是否正确理解了问题。 - svenwltr
1
还没有尝试过这个,会尽快更新。但是,感谢您的回复,它确实让我更好地理解了这个问题 :) - Dreams
有趣的是,我发现 Linux kubectl(根据您提到的链接)可以在 Big Sur 上运行... - Remigius Stalder

9

我又遇到了这个概念。出于安全考虑,我们不应该将cluster-admin权限与包含它的ClusterRole一起使用。

假设我们想在集群中部署一个pod,只能访问集群中特定命名空间中的查看创建pod。在这种情况下,ServiceAccount可能如下所示:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: spinupcontainers
subjects:
- kind: ServiceAccount
  name: spinupcontainers
  namespace: <YOUR_NAMESPACE>
roleRef:
  kind: Role
  name: spinupcontainers
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: spinupcontainers
  # "namespace" omitted if was ClusterRoles because are not namespaced
  namespace: <YOUR_NAMESPACE>
  labels:
    k8s-app: <YOUR_APP_LABEL>
rules:
#
# Give here only the privileges you need
#
- apiGroups: [""]
  resources:
  - pods
  verbs:
  - create
  - update
  - patch
  - delete
  - get
  - watch
  - list
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: spinupcontainers
  namespace: <MY_NAMESPACE>
  labels:
    k8s-app: <MY_APP_LABEL>
---

如果您在部署中使用serviceAccountName: spinupcontainers来应用服务账户到容器规格,那么您不需要挂载额外的卷密钥或手动附加证书。 kubectl客户端将从/var/run/secrets/kubernetes.io/serviceaccount获取所需的令牌。然后,您可以使用类似以下命令测试它是否正常工作:
$ kubectl exec -it <your-container-with-the-attached-privs> -- /kubectl get pods -n <YOUR_NAMESPACE>
NAME.        READY   STATUS    RESTARTS   AGE
pod1-0       1/1     Running   0          6d17h
pod2-0       1/1     Running   0          6d16h
pod3-0       1/1     Running   0          6d17h
pod3-2       1/1     Running   0          67s

或者权限被拒绝:

$ kubectl exec -it <your-container-with-the-attached-privs> -- /kubectl get pods -n kube-system
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:spinupcontainers" cannot list resource "pods" in API group "" in the namespace "kube-system"
command terminated with exit code 1

测试环境:

$ kubectl exec -it <your-container-with-the-attached-privs> -- /kubectl versionClient Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-07T21:20:10Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-07T21:12:17Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"linux/amd64"}

你能展示一下你配置的Dockerfile(spinupcontainers)吗? - Dani

2

0
在容器内运行 kubectl 命令需要三个步骤:
  1. 安装 kubectl
RUN printf '[kubernetes] \nname = Kubernetes\nbaseurl = https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64\nenabled = 1\ngpgcheck = 1\nrepo_gpgcheck=1\ngpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg' \
  | tee /etc/yum.repos.d/kubernetes.repo \
  && cat  /etc/yum.repos.d/kubernetes.repo \
  && yum install -y kubectl

  1. 为服务账户创建ClusterAdminRole绑定角色
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mysa-admin-sa
  namespace: mysa
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: mysa-admin-sa
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: mysa-admin-sa
    namespace: mysa

3- cronjob配置示例

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: scaleup
  namespace: myapp
spec:
  schedule: "00 5 * * 1-5"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: mysa-admin-sa
          restartPolicy: OnFailure
          containers:
          - name: scale-up
            image: myimage:test
            imagePullPolicy: Always
            command: ["/bin/sh"]
            args: ["-c", "mykubcmd_script >>/mylog.log"]

你如何为Docker镜像配置Dockerfile以供kubectl等使用... - Dani
您需要在Docker镜像上安装kubectl客户端。例如,对于基于CentOS的操作系统,您需要在Dockerfile中添加以下行。RUN printf '[kubernetes] \nname = Kubernetes\nbaseurl = https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64\nenabled = 1\ngpgcheck = 1\nrepo_gpgcheck=1\ngpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg' \ | tee /etc/yum.repos.d/kubernetes.repo \ && cat /etc/yum.repos.d/kubernetes.repo \ && yum install -y kubectl - Amit Singh

-5
  1. 要在只有一个容器的 pod 中运行命令,请使用下面的命令:

kubectl --exec -it <pod-name> -- <command-name>

  1. 要在具有多个容器的 pod 中运行命令,请使用下面的命令:

kubectl --exec -it <pod-name> -c <container-name> -- <command-name>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接