如何 SSH 进入正在运行的容器

SSH 可能不是在容器中运行命令的最佳方式;请尝试这种方法。
250 位读者喜欢这篇文章。
cubes coming together to create a larger cube

Opensource.com

容器改变了我们对虚拟化的看法。您可能还记得(或者您可能仍然生活在)虚拟机是完整堆栈的时代,从虚拟化的 BIOS、操作系统和内核,到每个虚拟化的网络接口控制器(NIC)。您登录虚拟盒子,就像登录您自己的工作站一样。这是一个非常直接和简单的类比。

然后容器出现了,从 LXC 开始,最终形成了开放容器倡议组织 (OCI),事情变得复杂起来。

幂等性

在容器的世界里,“虚拟机”只是大部分是虚拟的。所有不需要虚拟化的东西都从宿主机借用。此外,容器本身通常被设计为短暂的和幂等的,因此它不存储持久性数据,并且它的状态由宿主机上的配置文件定义。

如果您习惯了旧的虚拟机方式,那么您自然会期望登录虚拟机以便与之交互。但是容器是短暂的,因此容器中您所做的任何事情都会被遗忘,这是设计使然,以防容器需要重启或重新生成。

控制您的容器基础设施的命令(例如 oc、crictllxcdocker)提供了一个接口来运行重要的命令,以重启服务、查看日志、确认重要文件的存在和权限模式等等。您应该使用容器基础设施提供的工具与您的应用程序交互,或者编辑配置文件并重新启动。这就是容器的设计目的。

例如,开源论坛软件 Discourse 官方以容器镜像的形式分发。Discourse 软件是无状态的,因此它的安装是自包含在 /var/discourse 中的。只要您备份了 /var/discourse,您始终可以通过重新启动容器来恢复论坛。容器不保存持久性数据,其配置文件是 /var/discourse/containers/app.yml

如果您登录容器并编辑它包含的任何文件,如果容器必须重新启动,所有更改都将丢失。

您从头开始构建的 LXC 容器更加灵活,配置文件(在您定义的位置)在您启动容器时传递给容器。

Jenkins 这样的构建系统通常有一个默认的配置文件,例如 jenkins.yaml,为仅用于构建和运行源代码测试的基础容器镜像提供指令。构建完成后,容器就会消失。

既然您知道您不需要 SSH 来与容器交互,那么这里概述了可用的工具(以及关于尽管有所有使其变得多余的花哨工具,但仍然使用 SSH 的一些注意事项)。

OpenShift Web 控制台

OpenShift 4 为容器的创建和维护提供了一个开源工具链,包括一个交互式 Web 控制台。

当您登录到您的 Web 控制台时,导航到您的项目概览,然后单击 应用程序 选项卡以查看 Pod 列表。选择一个(正在运行的)Pod 以打开应用程序的 详细信息 面板。

Pod details in OpenShift

opensource.com

单击 详细信息 面板顶部的 终端 选项卡,以在您的容器中打开一个交互式 Shell。

A terminal in a running container

opensource.com

如果您更喜欢基于浏览器的 Kubernetes 管理体验,您可以通过 learn.openshift.com 上提供的交互式课程了解更多信息。

OpenShift oc

如果您更喜欢命令行界面体验,您可以使用 oc 命令从终端与容器交互。

首先,获取正在运行的 Pod 列表(或参考 Web 控制台以获取活动 Pod 列表)。要获取该列表,请输入

$ oc get pods

您可以查看资源(Pod、构建或容器)的日志。默认情况下,oc logs 返回您指定的 Pod 中第一个容器的日志。要选择单个容器,请添加 --container 选项

$ oc logs --follow=true example-1-e1337 --container app

您还可以使用以下命令查看 Pod 中所有容器的日志

$ oc logs --follow=true example-1-e1337 --all-containers

执行命令

您可以使用以下命令远程执行命令

$ oc exec example-1-e1337 --container app hostname
	example.local

这类似于以非交互方式运行 SSH:您可以运行您想运行的命令,而无需交互式 Shell 接管您的环境。

远程 Shell

您可以附加到正在运行的容器。这仍然会在容器中打开 Shell,但它会直接运行命令。例如

$ oc attach example-1-e1337 --container app

如果您需要在容器中获得真正的交互式 Shell,只要容器包含 Shell,您就可以使用 oc rsh 命令打开远程 Shell。默认情况下,oc rsh 启动 /bin/sh

$ oc rsh example-1-e1337 --container app

Kubernetes

如果您直接使用 Kubernetes,您可以使用 kubectl exec 命令在您的 Pod 中运行 Bash Shell。

首先,确认您的 Pod 正在运行

$ kubectl get pods

只要列出了包含您的应用程序的 Pod,您就可以使用 exec 命令在容器中启动 Shell。使用名称 example-pod 作为 Pod 名称,输入

$ kubectl exec --stdin=false --tty=false 
  example-pod -- /bin/bash
root@example.local:/# ls
bin   core etc   lib    root  srv
boot  dev  home  lib64  sbin  tmp  var

Docker

docker 命令类似于 kubectl。在 dockerd 守护进程运行的情况下,获取正在运行的容器的名称(如果您不在相应的组中,您可能必须使用 sudo 来提升权限)

$ docker ps
CONTAINER ID    IMAGE       COMMAND      NAME
678ac5cca78e    centos     "/bin/bash"   example-centos

使用容器名称,您可以在容器中运行命令

$ docker exec example/centos cat /etc/os-release
CentOS Linux release 7.6
NAME="CentOS Linux"
VERSION="7"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
[...]

或者您可以启动 Bash Shell 进行交互式会话

$ docker exec -it example-centos /bin/bash

容器和设备

在处理云时,要记住的重要一点是,容器本质上是运行时,而不是虚拟机。虽然它们与 Linux 系统有很多共同之处(因为它们就是 Linux 系统!),但它们很少直接转换为您可能在 Linux 工作站上开发的命令和工作流程。然而,像设备一样,容器有一个界面来帮助您开发、维护和监控它们,因此请熟悉前端命令和服务,直到您可以像与虚拟(或裸机)机器交互一样轻松地与它们交互。很快,您就会想知道为什么一切不是都开发成短暂的。

下一步阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,通常是同时工作。

6 条评论

我在 Linux 上做平面设计。我应该使用容器吗?

不一定,但您可能已经在使用了 Flatpak 或 Snap,它们在很多方面都类似于容器。例如,如果您安装了 GIMP 2.10.x,那么您可能是以 Flatpak 的形式安装的,所以它在一个“沙盒化”的环境中,这在很大程度上借鉴了容器化模型的概念。

回复 的评论,作者 ClaraBDias

很棒的文章

安全很重要,感谢这篇文章

能够获得容器内部的 root 权限也很重要。对于 Docker,我建议添加“-u0”,如下所示
$ docker exec -it -u0 example-centos /bin/bash

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.