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

Posted

技术标签:

【中文标题】如何在容器内运行 kubectl 命令?【英文标题】:How to run kubectl commands inside a container? 【发布时间】:2017-07-27 07:11:15 【问题描述】:

在 pod 内的容器中,如何使用 kubectl 运行命令?例如,如果我需要在容器内做这样的事情:

kubectl 获取 pod

我试过这个:在我的 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 - 我在 minikube 上本地运行 kubernetes,它建议在 kubernetes VM 中使用 docker 守护进程。 【参考方案1】:

我会使用kubernetes api,你只需要安装curl,而不是kubectl,其余的就安静了。

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

我在我的一个 apiserver 上运行上面的命令。将 localhost 更改为 apiserver ip 地址/dns 名称

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

为了找到 api 端点,您可以使用 --v=8kubectl

示例:

kubectl get pods --v=8

资源:

Kubernetes API documentation

RBAC 更新:

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

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

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

要向 apiserver 发出请求,在容器内运行:

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 上没有显示打开的端口。 @Tarun 192.168.99.100 是api服务器IP地址吗?顺便说一句,我刚刚在我的设置上对其进行了测试,它工作正常。 是的,我在 minikube 上运行 kubernetes。它的minikube ip。我犯了一个错误,我正在尝试端口 8080。但是,当我尝试 kubectl 配置视图时,它显示端口 8443。此外,当我检查 api 端点时,它显示我的“https”。你也一样吗?当我尝试使用 https 时,我收到一个 ssl 错误(curl:(60)SSL 证书问题:证书链无效)。我正在尝试解决它,将在我解决错误后立即更新。 @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 我试过 --insecure 但它不能解决问题,是的,我没有 .pem 文件,将尝试添加它们并尽快更新。再次,非常感谢:)【参考方案2】:

在这里聚会有点晚了,但这是我的两分钱:

我发现在容器中使用kubectl 比调用集群的 api 容易得多

(为什么?自动认证!)

假设您正在部署一个需要使用 kubectl 的 Node.js 项目。

    在容器内下载并构建kubectl 构建您的应用程序,将kubectl 复制到您的容器中 瞧!kubectl 提供了一个丰富的 cli 来管理您的 kubernetes 集群

Helpful documentation

--- 编辑 ---

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

    为您的 pod 创建一个 ServiceAccount,并将您的 pod 配置为使用该帐户。 k8s Service Account docs 配置RoleBindingClusterRoleBinding 以允许服务具有与k8s API 通信的权限。 k8s Role Binding docs 直接调用 API,或使用k8s-client 为您管理 API 调用。我强烈建议使用客户端,它具有自动配置 pod 的功能,消除了正常请求所需的身份验证令牌步骤。

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

如果您需要更清晰的方向,请随时发表评论,我会尽力提供帮助:)

综合例子

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 确定!所有kubectl 命令都可以通过命令行输入。使用 Node 的 fork 子进程,您可以执行这些命令。确保在执行其他命令之前初始化kubectl proxy。使用kubectl构建docker镜像:pastebin.com/6a8kp6aR 作为一个 k8s 初学者,上面的这些指令听起来很神奇,但我找到了一些帮助来将其转换为一些配置 - kubernetes.slack.com/archives/C09NXKJKA/…。因此,我将进行编辑以提供示例。 @mster 你能帮我处理一下 Dockerfile 吗?我想在出现错误的容器中安装 kubectl:failed to solve with frontend dockerfile.v0: failed to create LLB definition: circular dependency detected on stage: kubectl。这是我的 Dockerfile:pastebin.com/Lqb1py64 如果不需要,永远不要给集群管理员。除此之外,该解决方案似乎是可行的。【参考方案3】:

第一个问题

/usr/local/bin/kubectl: cannot execute binary file

您似乎下载了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 定义的一部分运行。 使用authorization plugin(不是默认值)限制访问。 服务帐户凭据被pod definition (spec.serviceAccountName) 覆盖。

【讨论】:

是的,感谢您指出。我为 linux 做了必要的更改。但是,我仍然收到另一个错误,将更新问题。 :) 我更新了答案。不确定我是否正确理解了这个问题。 这个没试过,尽快更新。但是,感谢您的回复,这无疑让我对这个问题有了更好的理解:) 有趣的是,我发现 linux kubectl(根据你提到的链接)可以在 big sur 上运行...【参考方案4】:

我刚刚再次面对这个概念。这是绝对可能的,但出于安全原因,我们不要在 ClusterRole 容器中授予“cluster-admin 权限。

假设我们想在集群中部署一个 pod,它只能在集群中的特定命名空间中访问 viewcreate 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.InfoMajor:"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.InfoMajor:"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"

【讨论】:

【参考方案5】:

综合以上。这对我有用。 从容器中检索所有 pod。

curl --insecure -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"  https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/default/pods

请参阅https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#-strong-read-operations-pod-v1-core-strong- 了解 REST API。

【讨论】:

【参考方案6】:

在容器内运行 kubectl 命令。 需要3个步骤

    安装 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

    为服务帐户创建 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"]

【讨论】:

【参考方案7】:
    要在具有单个容器的 pod 内运行命令,请使用以下命令

kubectl --exec -it --

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

kubectl --exec -it -c --

【讨论】:

以上是关于如何在容器内运行 kubectl 命令?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 kubectl 命令用于在 Rancher 中使用 docker 运行的 kubernetes?

如何在 terraform 中运行 kubectl apply 命令

k8s kubectl复制命令曝目录遍历漏洞

如何在 gcloud 和 minikube 之间切换 kubectl 集群

AKS:当进程仍在容器中运行时,kubectl exec 和 kubectl 日志退出

如何在 docker 容器中运行 npm 命令?