标签 容器 下的文章

Docker 平台和容器已经成为打包、部署、和管理应用程序的标准。为了在一个集群内协调跨节点的容器,必须有一个关键的能力:一个容器编排器。

container orchestrator

对于关键的集群化以及计划的任务,编排器是起重大作用的,比如:

  • 管理容器计划和资源分配。
  • 支持服务发现和无缝的应用程序部署。
  • 分配应用程序运行必需的资源。

不幸的是,在这种环境下,编排器的分布式特性和资源的短暂性使得确保编排器的安全是一个极具挑战性的任务。在这篇文章中,我们将讨论容器编排器安全模型中没有考虑到的、但是很重要的这方面的详细情况,以及 Docker 企业版中如何使用内置的编排性能、Swarm 模式,去克服这些问题。

诱因和威胁模型

使用 swarm 模式的 Docker 企业版的其中一个主要目标是提供一个内置安全特性的编排器。为达到这个目标,我们部署了第一个在我们心目中认为的以最小权限原则设计的容器编排器。

在计算机科学中,一个分布式系统所要求的最小权限原则是,系统中的每个参与者仅仅能访问它正当目的所需要的信息和资源。不是更多,也不是更少。

“一个进程必须仅仅能去访问它的正当目的所需要的信息和资源”

最小权限原则

在一个 Docker 企业版集群中的每个节点分配的角色:既不是管理者(manager),也不是工人(worker)。这些角色为节点定义了一个很粗粒度的权限级别:分别进行管理和任务执行。尽管如此,不用理会它的角色,通过使用加密的方式,来保证一个节点仅仅有执行它的任务所需要的信息和资源。结果是,确保集群安全变得更容易了,甚至可以防止大多数的有经验的攻击者模式:攻击者控制了底层通讯网络,或者甚至攻陷了集群节点。

内核缺省安全

这是一个很老的安全最大化状态:如果它不是缺省的,就没人用它。Docker Swarm 模式将缺省安全这一概念融入了核心,并且使用这一机制去解决编排器生命周期中三个很难并且很重要的部分:

  1. 可信引导和节点引入。
  2. 节点身份发布和管理。
  3. 认证、授权和加密的信息存储和传播。

我们来分别看一下这三个部分:

可信引导和节点引入

确保集群安全的第一步,没有别的,就是严格控制成员和身份。管理员不能依赖它们节点的身份,并且在节点之间强制实行绝对的负载隔离。这意味着,未授权的节点不能允许加入到集群中,并且,已经是集群一部分的节点不能改变身份,突然去伪装成另一个节点。

为解决这种情况,通过 Docker 企业版 Swarm 模式管理的节点,维护了健壮的、不可改变的身份。期望的特性是,通过使用两种关键的构建块去保证加密:

  1. 为集群成员使用 安全加入令牌 Secure join token
  2. 从一个集中化的认证机构发行的内嵌唯一身份的证书。
加入 Swarm

要加入 Swarm,节点需要一份 安全加入令牌 Secure join token 的副本。在集群内的每个操作角色的令牌都是独一无二的 —— 现在有两种类型的节点:工人(workers)和管理者(managers)。由于这种区分,拥有一个工人令牌的节点将不允许以管理者角色加入到集群。唯一得到这个特殊令牌的方式是通过 swarm 的管理 API 去向集群管理者请求一个。

令牌是安全的并且是随机生成的,它还有一个使得令牌泄露更容易被检测到的特殊语法:一个可以在你的日志和仓库中很容易监视的特殊前缀。幸运的是,即便发现一个泄露,令牌也可以很容易去更新,并且,推荐你经常去更新它们 —— 特别是,在一段时间中你的集群不进行扩大的情况下。

Docker Swarm

引导信任

作为它的身份标识创建的一部分,一个新的节点将向任意一个网络管理者请求发布一个新的身份。但是,在我们下面的威胁模型中,所有的通讯可以被一个第三方拦截。这种请求存在的问题是:一个节点怎么知道与它进行对话的对方是合法的管理者?

Docker Security

幸运的是,Docker 有一个内置机制可以避免这种情况。这个加入令牌被主机用于加入 Swarm,包含了一个根 CA 证书的哈希串。所以,主机可以使用单向 TLS,并且使用这个哈希串去验证它加入的 Swarm 是否正确:如果管理者持有的证书没有被正确的 CA 哈希串签名,节点就知道它不可信任。

节点身份发布和管理

在一个 Swarm 中,身份标识是内嵌在每个节点都单独持有的一个 x509 证书中。在一个最小权限原则的表现形式中,证书的私钥被绝对限制在主机的原始位置。尤其是,管理者不能访问除了它自己的私钥以外的任何一个私钥。

身份发布

要接收它们的证书而无需共享它们的私钥,新的主机通过发布一个证书签名请求(CSR)来开始,管理者收到证书签名请求之后,转换成一个证书。这个证书成为这个新的主机的身份标识,使这个节点成为 Swarm 的一个完全合格成员!

当和安全引导机制一起使用时,发行身份标识的这个机制来加入节点是缺省安全的:所有的通讯部分都是经过认证的、授权的,并且非敏感信息从来都不会以明文方式进行交换。

身份标识延期

尽管如此,给一个 Swarm 中安全地加入节点,仅仅是 “故事” 的一部分。为降低证书的泄露或者失窃造成的影响,并且移除管理 CRL 列表的复杂性,Swarm 模式为身份标识使用了较短存活周期的证书。这些证书缺省情况下三个月后将过期,但是,也可以配置为一个小时后即刻过期!

Docker secrets

较短的证书过期时间意味着不能手动去处理证书更新,所以,通常会使用一个 PKI 系统。对于 Swarm,所有的证书是以一种不中断的方式进行自动更新的。这个过程很简单:使用一个相互认证的 TLS 连接去证明一个特定身份标识的所有者,一个 Swarm 节点定期生成一个新的公钥/私钥密钥对,并且用相关的 CSR 去签名发送,创建一个维持相同身份标识的完整的新证书。

经过认证、授权、和加密的信息存储和传播。

在一个正常的 Swarm 的操作中,关于任务的信息被发送给去运行的工人(worker)节点。这里不仅仅包含将被一个节点运行的容器的信息;也包含那个容器运行所必需的资源的所有信息,包括敏感的机密信息,比如,私钥、密码和 API 令牌。

传输安全

事实上,参与 Swarm 的每个节点都拥有一个独一无二的 X509 格式的证书,因此,节点之间的通讯安全是没有问题的:节点使用它们各自的证书,与另一个连接方进行相互认证、继承机密、真实性、和 TLS 的完整性。

Swarm Mode

关于 Swarm 模式的一个有趣的细节是,本质上它是使用了一个推送模式:仅管理者被允许去发送信息到工人们(workers)—— 显著降低了暴露在低权限的工人节点面前的管理者节点的攻击面。

将负载严格隔离进安全区域

管理者节点的其中一个责任是,去决定发送到每个工人(worker)节点的任务是什么。管理者节点使用多种策略去做这个决定;根据每个节点和每个负载的特性,去跨 Swarm 去安排负载。

在使用 Swarm 模式的 Docker 企业版中,管理者节点通过使用附加到每个单个节点标识上的安全标签,去影响这些安排决定。这些标签允许管理者将节点组与不同的安全区域连接到一起,以限制敏感负载暴露,以及使相关机密信息更安全。

Docker Swarm Security

安全分发机密

除了加快身份标识发布过程之外,管理者节点还有存储和分发工人节点所需要的任何资源的任务。机密信息像任何其它类型的资源一样处理,并且基于安全的 mTLS 连接,从管理者推送到工人节点。

Docker Secrets

在主机上,Docker 企业版能确保机密仅提供给它们指定的容器。在同一个主机上的其它容器并不能访问它们。Docker 以一个临时文件系统的方式显露机密给一个容器,确保机密总是保存在内存中,并且从不写入到磁盘。这种方式比其它竞争的替代者更加安全,比如,在环境变量中存储它们。一旦这个任务完成,这个机密将永远消失。

存储机密

在管理者主机上的机密总是保持加密的。缺省情况下,加密这些机密的密钥(被称为数据加密密钥,DEK)是以明文的方式存储在硬盘上的。这使得那些对安全性要求较低的人可以轻松地去使用 Docker Swarm 模式。

但是,如果你运行一个生产集群,我们推荐你启用自动锁定模式。当自动锁定模式启用后,一个重新更新过的 DEK 被一个独立的加密密钥的密钥(KEK)所加密。这个密钥从不被存储在集群中;管理者有责任将它存储在一个安全可靠的地方,并且当集群启动的时候可以提供它。这就是所谓的 “解锁” Swarm。

根据 Raft 故障容错一致性算法,Swarm 模式支持多个管理者。在这个场景中,无缝扩展了机密存储的安全性。每个管理者主机除了共享密钥之外,还有一个唯一的磁盘加密密钥。幸运的是,Raft 日志在磁盘上也是加密的,并且,在自动锁定模式下,没有 KEK 同样是不可访问的。

当一个节点被攻陷后发生了什么?

Docker Secrets

在传统的编排器中,挽回一台被攻陷的主机是一个缓慢而复杂的过程。使用 Swarm 模式,恢复它就像运行一个 Docker 节点的 rm 命令一样容易。这是从集群中删除一个受影响的节点,而 Docker 将去处理剩下的事情,即,重新均衡负载,并且确保其它的主机已经知道,而不会去与受影响的节点通讯。

正如我们看到的那样,感谢最小权限的编排器,甚至是,如果攻击者在主机上持续活动,它们将被从剩余的网络上切断。主机的证书 —— 它的身份标识 —— 被列入黑名单,因此,管理者也不能有效访问它。

结论

使用 Swarm 模式的 Docker 企业版,在缺省情况下确保了编排器的所有关键区域的安全:

  • 加入集群。阻止恶意节点加入到集群。
  • 把主机分组为安全区域。阻止攻击者的横向移动。
  • 安排任务。任务将仅被委派到允许的节点。
  • 分配资源。恶意节点不能 “盗取” 其它的负载或者资源。
  • 存储机密。从不明文保存并且从不写入到工人节点的磁盘上。
  • 与工人节点的通讯。使用相互认证的 TLS 加密。

因为 Swarm 模式的持续改进,Docker 团队正在努力将最小权限原则进一步推进。我们正在处理的一个任务是:如果一个管理者被攻陷了,怎么去保证剩下的节点的安全?路线图已经有了,其中一些功能已经可以使用,比如,白名单功能,仅允许特定的 Docker 镜像,阻止管理者随意运行负载。这是通过 Docker 可信内容来实现的。


via: https://blog.docker.com/2017/10/least-privilege-container-orchestration/

作者:Diogo Mónica 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

容器支持者认为未来属于容器化操作系统,而其他人或许有不同看法。

自从 Linus Torvalds 在 1991 年发布 Linux 以来,Linux 已历经漫长的岁月。它已经成为企业级领域的主流操作系统。同时,我们看到桌面级领域出现了很多改进和调整,但在过去的 25 年来,主流 Linux 发行版的模式很大程度上没有变化。基于软件包管理的传统模式依然统治着桌面级和服务器级市场。

但随着 Google 发布了基于 Linux 的 Chrome OS,情况出现了微妙的转变,Chrome OS 采用镜像模式。Core OS (目前归属于 Red Hat) 受 Google 启发推出了一款操作系统 Container Linux,主要面向企业级用户。

Container Linux 改变了操作系统更新的方式,也改变了应用分发和更新的方式。这会是 Linux 发行版的未来吗?这是否会取代基于软件包的传统发行版模式呢?

三种模式

SLE (SUSE Linux Enterprise) 的产品管理总监 Matthias Eckermann 认为目前存在 3 种模式,而不是 2 种。Eckermann 提到:“除了传统模式(RHEL/SLE)和镜像模式(RedHat 的 Atomic Host),还存在第三种模型:事务模式。SUSE CaaS 平台 及 SUSE MicroOS 就采用这种模式。”

差异有哪些

Linux 用户对传统模式非常熟悉,它由独立的软件包和共享库组成。这种模式有独特的优势,让应用开发者无需将共享库捆绑在应用中。由于库不会多次引入,使得系统简洁和轻便。这也让用户无需下载很多软件包,节省了带宽。发行版对软件包全权负责,通过推送系统级别的更新,可以轻松地解决安全隐患。

RHEL (Red Hat Enterprise Linux)的产品管理总监 Ron Pacheco 表示,“传统的打包方式继续为我们提供精心构建和优化操作系统的机会,以便支持需要经过时间考验的任务关键型工作负载。”

但传统模式也有一些弊端。应用开发者受限使用发行版包含的库,使其无法从发行版不支持的新软件中获益。这也可能导致不同版本之间相互冲突。最终,传统模式给管理员增加了挑战,使其难以让软件包一直处于最新版本状态。

镜像模式

镜像模式应运而生。Eckermann 表示,“镜像模式解决了传统模式遇到的问题,它在每次迭代更新时替换整个操作系统,而不是单个的软件包”。

Pacheco 表示,“当我们用镜像作为操作系统的代名词进行讨论时,我们真正关心的是可编程式的开发和部署以及更好的集成式生命周期管理”,基于 RHEL 搭建的 OpenShift 被他用作示例。

Pacheco 认为基于镜像的操作系统是一种延续,从手工打造并部署镜像,到可大规模管理的高度自动化基础设施;无论客户使用哪种类型,都需要运行同样的应用。他说,“你肯定不希望使用一个完全不同的部署模式,这需要重做很多工作”。

镜像模式用新的库和软件包替代来整个操作系统,但也面临一系列问题。在镜像模式中,需要重建镜像才能适应特殊环境的需求。例如,用户有特殊需求,需要安装特定硬件的驱动或安装底层监控功能,镜像模式无法满足,需要重新设计功能以实现细粒度操作。

事务模式

第三种模式采用事务更新,基于传统的软件包更新,但将全部的软件包视为一个镜像,就像镜像那样在一次操作中更新全部软件包。

Eckermann 表示,“由于安装或回滚时操作对象是打包在一起的单一软件包,用户在需要时能够做相应的调整,这就是差别所在。结合传统模式和镜像模式的优点,避免两种模式的缺点,事务模式给用户提供了额外的灵活性。”

Pacheco 表示,将精心构造的工作负载部署成镜像的做法越来越成为主流,因为这种部署方式具有一致性和可靠性,而且可以弹性部署。“这正是我们用户目前的做法,部署环境包括在预置设备或公有/私有云上创建并部署的虚拟机,或在传统的裸机上。”

Pacheco 建议我们将这几种模式视为操作系统角色的进化和扩展,而不是仅仅“使用场景的比较和对比”。

原子化更新的问世

Google 的 Chrome OS 和 Core OS 为我们普及了事务更新的概念,该模型也被 Red Hat 和 SUSE 采用。

Eckermann 表示,“我们必须认识到,用于容器主机的操作系统已经不再是关注点 —— 至少不是管理员的关注点。RedHat Atomic 主机和 SUSE CaaS 平台都解决了该问题,实现方式在用户看来很相似。”

SUSE CaaS 平台、Red Hat Atomic Host和 Container Linux (前身是 Core OS)提供的 不可变基础设施 Immutable infrastructure 推广了事务更新的使用。Red Hat 高级技术产品经理 Ben Breard 表示,“在事务模式中,主机总是会变更到已确认正确的新状态,这让我们更有信心执行更新,进而实现更快速的功能流、安全优势以及易于采用的操作模式。”

这些新型操作系统使用 Linux 容器将应用与底层系统隔离,解除了传统模式中基础设施更新的诸多限制。

Breard 补充道,“当编排层可以智能处理更新、部署,甚至最终实现无缝操作时,我们才会真正意识到该模式的威力和好处”。

展望未来

Linux 的未来会是什么样子?不同的人会给出不同的回答。容器支持者认为未来属于容器化的操作系统,但依然拥有庞大市场的 Linux 供应商显然不这么认为。

当被问到原子化发行版是否会在很久以后将替换传统发行版时,Eckermann 表示,“如果我回答肯定的,那么表示我顺应潮流;如果回答是否定的,意味着我还是站在传统阵营。然而,我的回答是否定的,即 atomic 发行版在很久以后也不会替换传统发行版,传统负载和容器化负载将在数据中心、私有云以及公有云环境中共存。”

Pacheco 认为,从 Linux 的部署增长情况来看,一般情况下很难想象一种模式替换另一种模式。与其将多种模式视为相互竞争的关系,不如将原子化发行版视为操作系统进化和部署的一部分。

此外,在一些使用案例中,我们需要同时使用多种 Linux 发行版。Eckermann 表示,“想一想银行和保险公司中大量的 PL/1 和 Cobol 系统。再想一想内存数据库和核心数据总线系统。”

这些应用大多数无法进行容器化。就我们目前来看,容器化不是解决所有问题的万金油。总是会同时存在多种不同的技术。

Eckermann 相信,随着时间的推移,大量新的开发和部署将采用容器化,但仍然有不错的理由,促使我们在企业级环境中保留传统的部署方式和应用。

Pacheco 认为,“用户需要经历业务、设计和文化的转型,才能最大化基于容器的部署带来的优势。好消息是业界已经认识到并开始大规模转变,就像历史上大型机转变成 UNIX,UNIX 转变成 x86,x86 转变成虚拟化那样”。

结论

很明显,未来容器化负载的使用量会持续增长,也就意味着原子化发行版的需求量持续增长。与此同时,仍会有不少工作负载运行在传统发行版中。重要的是,这两类用户都在新模式上大规模投入,以便市场改变时可以做相应的策略改变。从外部观察者的视角来看,未来属于事务/原子化模式。我们已经见证了数据中心的发展,我们花了很长时间完成了从每个服务器一个应用到“函数即服务”模型的转变。Linux 发行版进入原子化时代的日子也不会太远了。


via: https://www.linux.com/blog/2018/4/containerization-atomic-distributions-and-future-linux

作者:SWAPNIL BHARTIYA 选题:lujun9972 译者:pinewall 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Project Atomic 通过他们在 Open Container Initiative(OCI)上的努力创造了一个名为 Buildah 的伟大工具。Buildah 能帮助创建、构建和更新,它支持 Docker 容器镜像以及 OCI 兼容镜像。

Buildah 处理构建容器镜像时无需安装完整的容器运行时或守护进程。这对建立容器的持续集成和持续交付管道尤其有用。

Buildah 使容器的文件系统可以直接供构建主机使用。这意味着构建工具在主机上可用就行,而不需要在容器镜像中可用,从而使构建更快速,镜像更小,更安全。Buildah 有 CentOS、Fedora 和 Debian 的软件包。

安装 Buildah

从 Fedora 26 开始 Buildah 可以使用 dnf 进行安装。

$ sudo dnf install buildah -y

buildah 的当前版本为 0.16,可以通过以下命令显示。

$ buildah --version

基本命令

构建容器镜像的第一步是获取基础镜像,这是通过 Dockerfile 中的 FROM 语句完成的。Buildah 以类似的方式处理这个。

$ sudo buildah from fedora

该命令将拉取 Fedora 的基础镜像并存储在主机上。通过执行以下操作可以检查主机上可用的镜像。

$ sudo buildah images
IMAGE ID IMAGE NAME CREATED AT SIZE
9110ae7f579f docker.io/library/fedora:latest Mar 7, 2018 20:51 234.7 MB

在拉取基础镜像后,有一个该镜像的运行容器实例,这是一个“工作容器”。

以下命令显示正在运行的容器。

$ sudo buildah containers
CONTAINER ID BUILDER IMAGE ID IMAGE NAME
CONTAINER NAME
6112db586ab9 * 9110ae7f579f docker.io/library/fedora:latest fedora-working-container

Buildah 还提供了一个非常有用的命令来停止和删除当前正在运行的所有容器。

$ sudo buildah rm --all

完整的命令列表可以使用 --help 选项。

$ buildah --help

构建一个 Apache Web 服务器容器镜像

让我们看看如何使用 Buildah 在 Fedora 基础镜像上安装 Apache Web 服务器,然后复制一个可供服务的自定义 index.html

首先让我们创建自定义的 index.html

$ echo "Hello Fedora Magazine !!!" > index.html

然后在正在运行的容器中安装 httpd 包。

$ sudo buildah from fedora
$ sudo buildah run fedora-working-container dnf install httpd -y

让我们将 index.html 复制到 /var/www/html/

$ sudo buildah copy fedora-working-container index.html /var/www/html/index.html

然后配置容器入口点以启动 httpd。

$ sudo buildah config --entrypoint "/usr/sbin/httpd -DFOREGROUND" fedora-working-container

现在为了使“工作容器”可用,commit 命令将容器保存到镜像。

$ sudo buildah commit fedora-working-container hello-fedora-magazine

hello-fedora-magazine 镜像现在可用,并且可以推送到仓库以供使用。

$ sudo buildah images
IMAGE ID IMAGE NAME CREATED
AT SIZE
9110ae7f579f docker.io/library/fedora:latest
Mar 7, 2018 22:51 234.7 MB
49bd5ec5be71 docker.io/library/hello-fedora-magazine:latest
Apr 27, 2018 11:01 427.7 MB

通过运行以下步骤,还可以使用 Buildah 来测试此镜像。

$ sudo buildah from --name=hello-magazine docker.io/library/hello-fedora-magazine
$ sudo buildah run hello-magazine

访问 http://localhost 将显示 “Hello Fedora Magazine !!!”


via: https://fedoramagazine.org/daemon-less-container-management-buildah/

作者:Ashutosh Sudhakar Bhakare 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

最近几年,开源项目 Docker (已更名为Moby) 在容器普及化方面建树颇多。然而,它的功能特性不断集中到一个单一、庞大的系统,该系统由具有 root 权限运行的守护进程 dockerd 管控,这引发了人们的焦虑。对这些焦虑的阐述,具有代表性的是 Red Hat 公司的容器团队负责人 Dan Walsh 在 KubeCon + CloudNativecon 会议中的演讲。Walsh 讲述了他的容器团队目前的工作方向,即使用一系列更小、可协同工作的组件替代 Docker。他的战斗口号是“拒绝臃肿的守护进程”,理由是与公认的 Unix 哲学相违背。

Docker 模块化实践

就像我们在早期文献中看到的那样,容器的基础操作不复杂:你首先拉取一个容器镜像,利用该镜像创建一个容器,最后启动这个容器。除此之外,你要懂得如何构建镜像并推送至镜像仓库。大多数人在上述这些步骤中使用 Docker,但其实 Docker 并不是唯一的选择,目前的可替换选择是 rkt。rkt 引发了一系列标准的创建,包括运行时标准 CRI,镜像标准 OCI 及网络标准 CNI 等。遵守这些标准的后端,如 CRI-O 和 Docker,可以与 Kubernetes 为代表的管理软件协同工作。

这些标准促使 Red Hat 公司开发了一系列实现了部分标准的“核心应用”供 Kubernetes 使用,例如 CRI-O 运行时。但 Kubernetes 提供的功能不足以满足 Red Hat 公司的 OpenShift 项目所需。开发者可能需要构建容器并推送至镜像仓库,实现这些操作需要额外的一整套方案。

事实上,目前市面上已有多种构建容器的工具。来自 Sysdig 公司的 Michael Ducy 在分会场中回顾了 Docker 本身之外的 8 种镜像构建工具,而这也很可能不是全部。Ducy 将理想的构建工具定义如下:可以用可重现的方式创建最小化镜像。最小化镜像并不包含操作系统,只包含应用本身及其依赖。Ducy 认为 Distroless, SmithSource-to-Image 都是很好的工具,可用于构建最小化镜像。Ducy 将最小化镜像称为“微容器”。

可重现镜像 reproducible container 是指构建多次结果保持不变的镜像。为达到这个目标,Ducy 表示应该使用“宣告式”而不是“命令式”的方式。考虑到 Ducy 来自 Chef 配置管理工具领域,你应该能理解他的意思。Ducy 给出了符合标准的几个不错的实现,包括 Ansible 容器Habitatnixos-容器Simth 等,但你需要了解这些项目对应的编程语言。Ducy 额外指出 Habitat 构建的容器自带管理功能,如果你已经使用了 systemd、 Docker 或 Kubernetes 等外部管理工具,Habitat 的管理功能可能是冗余的。除此之外,我们还要提到从 Docker 和 Buildah 项目诞生的新项目 BuildKit, 它是 Red Hat 公司 Atomic 工程的一个组件。

使用 Buildah 构建容器

 title=

Buildah 名称显然来自于 Walsh 风趣的 波士顿口音; 该工具的品牌宣传中充满了波士顿风格,例如 logo 使用了波士顿梗犬(如图所示)。该项目的实现思路与 Ducy 不同:为了构建容器,与其被迫使用宣告式配置管理的方案,不如构建一些简单工具,结合你最喜欢的配置管理工具使用。这样你可以如愿的使用命令行,例如使用 cp 命令代替 Docker 的自定义指令 COPY 。除此之外,你可以使用如下工具为容器提供内容:1) 配置管理工具,例如Ansible 或 Puppet;2) 操作系统相关或编程语言相关的安装工具,例如 APT 和 pip; 3) 其它系统。下面展示了基于通用 shell 命令的容器构建场景,其中只需要使用 make 命令即可为容器安装可执行文件。

# 拉取基础镜像, 类似 Dockerfile 中的 FROM 命令
buildah from redhat

# 挂载基础镜像, 在其基础上工作
crt=$(buildah mount)
ap foo $crt
make install DESTDIR=$crt

# 下一步,生成快照
buildah commit

有趣的是,基于这个思路,你可以复用主机环境中的构建工具,无需在镜像中安装这些依赖,故可以构建非常微小的镜像。通常情况下,构建容器镜像时需要在容器中安装目标应用的构建依赖。例如,从源码构建需要容器中有编译器工具链,这是因为构建并不在主机环境进行。大量的容器也包含了 psbash 这样的 Unix 命令,对微容器而言其实是多余的。开发者经常忘记或无法从构建好的容器中移除一些依赖,增加了不必要的开销和攻击面。

Buildah 的模块化方案能够以非 root 方式进行部分构建;但mount 命令仍然需要 CAP_SYS_ADMIN,有一个 工单 试图解决该问题。但 Buildah 与 Docker 都有同样的限制,即无法在容器内构建容器。对于 Docker,你需要使用“特权”模式运行容器,一些特殊的环境很难满足这个条件,例如 GitLab 持续集成;即使满足该条件,配置也特别繁琐

手动提交的步骤可以对创建容器快照的时间节点进行细粒度控制。Dockerfile 每一行都会创建一个新的快照;相比而言,Buildah 的提交检查点都是事先选择好的,这可以减少不必要的快照并节省磁盘空间。这也有利于隔离私钥或密码等敏感信息,避免其出现在公共镜像中。

Docker 构建的镜像是非标准的、仅供其自身使用;相比而言,Buildah 提供多种输出格式,其中包括符合 OCI 标准的镜像。为向后兼容,Buildah 提供了一个“使用 Dockerfile 构建”的命令,即 buildah bud, 它可以解析标准的 Dockerfile。Buildah 提供 enter 命令直接查看镜像内部信息,run 命令启动一个容器。实现这些功能仅使用了 runc 在内的标准工具,无需在后台运行一个“臃肿的守护进程”。

Ducy 对 Buildah 表示质疑,认为采用非宣告性不利于可重现性。如果允许使用 shell 命令,可能产生很多预想不到的情况;例如,一个 shell 脚本下载了任意的可执行程序,但后续无法追溯文件的来源。shell 命令的执行受环境变量影响,执行结果可能大相径庭。与基于 shell 的工具相比,Puppet 或 Chef 这样的配置管理系统在理论上更加可靠,因为它们的设计初衷就是收敛于最终配置;事实上,可以通过配置管理系统调用 shell 命令。但 Walsh 对此提出反驳,认为已有的配置管理工具可以在 Buildah 的基础上工作,用户可以选择是否使用配置管理;这样更加符合“机制与策略分离”的经典 Unix 哲学。

目前 Buildah 处于测试阶段,Red Hat 公司正努力将其集成到 OpenShift。我写这篇文章时已经测试过 Buildah,它缺少一些文档,但基本可以稳定运行。尽管在错误处理方面仍有待提高,但它确实是一款值得你关注的容器工具。

替换其它 Docker 命令行

Walsh 在其演讲中还简单介绍了 Red hat 公司 正在开发的另一个暂时叫做 libpod 的项目。项目名称来源于 Kubernetes 中的 “pod”, 在 Kubernetes 中 “pod” 用于分组主机内的容器,分享名字空间等。

Libpod 提供 kpod 命令,用于直接检查和操作容器存储。Walsh 分析了该命令发挥作用的场景,例如 dockerd 停止响应或 Kubernetes 集群崩溃。基本上,kpod 独立地再次实现了 docker 命令行工具。kpod ps 返回运行中的容器列表,kpod images 返回镜像列表。事实上,命令转换速查手册 中给出了每一条 Docker 命令对应的 kpod 命令。

这种模块化实现的一个好处是,当你使用 kpod run 运行容器时,容器直接作为当前 shell 而不是 dockerd 的子进程启动。理论上,可以直接使用 systemd 启动容器,这样可以消除 dockerd 引入的冗余。这让由套接字激活的容器成为可能,但暂时基于 Docker 实现该特性并不容易即使借助 Kubernetes 也是如此。但我在测试过程中发现,使用 kpod 启动的容器有一些基础功能性缺失,具体而言是网络功能(!),相关实现在活跃开发过程中。

我们最后提到的命令是 push。虽然上述命令已经足以满足本地使用容器的需求,但没有提到远程仓库,借助远程仓库开发者可以活跃地进行应用打包协作。仓库也是持续部署框架的核心组件。skopeo 项目用于填补这个空白,它是另一个 Atomic 成员项目,按其 README 文件描述,“包含容器镜像及镜像库的多种操作”。该项目的设计初衷是,在不用类似 docker pull 那样实际去下载可能体积庞大的镜像的前提下,检查容器镜像的内容。Docker 拒绝加入 检查功能,建议通过一个额外的工具实现该功能,这促成了 Skopeo 项目。除了 pullpush,Skopeo 现在还可以完成很多其它操作,例如在,不产生本地副本的情况下将镜像在不同的仓库中复制和转换。由于部分功能比较基础,可供其它项目使用,目前很大一部分 Skopeo 代码位于一个叫做 containers/image 的基础库。Pivotal、 Google 的 container-diffkpod pushbuildah push 都使用了该库。

kpod 与 Kubernetes 并没有紧密的联系,故未来可能会更换名称(事实上,在本文刊发过程中,已经更名为 podman),毕竟 Red Hat 法务部门还没有明确其名称。该团队希望实现更多 pod 级别的命令,这样可以对多个容器进行操作,有点类似于 docker compose 实现的功能。但在这方面,Kompose 是更好的工具,可以通过 复合 YAML 文件 在 Kubernetes 集群中运行容器。按计划,我们不会实现类似于 [swarm] 的 Docker 命令,这部分功能最好由 Kubernetes 本身完成。

目前看来,已经持续数年的 Docker 模块化努力终将硕果累累。但目前 kpod 处于快速迭代过程中,不太适合用于生产环境,不过那些工具的与众不同的设计理念让人很感兴趣,而且其中大部分的工具已经可以用于开发环境。目前只能通过编译源码的方式安装 libpod,但最终会提供各个发行版的二进制包。

本文最初发表Linux Weekly News

via: https://anarc.at/blog/2017-12-20-docker-without-docker/

作者:Anarcat 译者:pinewall 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Docker 是一种所谓容器化的操作系统级的虚拟化软件。

基于 Linux 内核的 cgroup 和 namespace 等资源隔离特性,Docker 可以在单个 Linux 实例中运行多个独立的容器。

通过将应用依赖和相关库打包进容器,Docker 使得应用可以在容器中安全隔离地运行。

Dry 是什么

Dry 是一个管理并监控 Docker 容器和镜像的命令行工具。

Dry 可以给出容器相关的信息,包括对应镜像、容器名称、网络、容器中运行的命令及容器状态;如果运行在 Docker Swarm 中,工具还会给出 Swarm 集群的各种状态信息。

Dry 可以连接至本地或远程的 Docker 守护进程。如果连接本地 Docker,Docker 主机显示为 unix:///var/run/docker.sock

如果连接远程 Docker,Docker 主机显示为 tcp://IP Address:Port Numbertcp://Host Name:Port Number

Dry 可以提供类似 docker ps 的指标输出,但输出比 docker ps 内容详实、富有色彩。

相比 Docker,Dry 还可以手动添加一个额外的名称列,用于降低记忆难度。

推荐阅读:

如何在 Linux 中安装 Dry

在 Linux 中,可以通过一个简单的 shell 脚本安装最新版本的 Dry 工具。Dry 不依赖外部库。对于绝大多数的 Docker 命令,Dry 提供类似样式的命令。

$ curl -sSf https://moncho.github.io/dry/dryup.sh | sudo sh
 % Total % Received % Xferd Average Speed Time Time Time Current
 Dload Upload Total Spent Left Speed
100 10 100 10 0 0 35 0 --:--:-- --:--:-- --:--:-- 35
dryup: downloading dry binary
######################################################################## 100.0%
dryup: Moving dry binary to its destination
dryup: dry binary was copied to /usr/local/bin, now you should 'sudo chmod 755 /usr/local/bin/dry'

使用如下命令将文件权限变更为 755

$ sudo chmod 755 /usr/local/bin/dry

对于使用 Arch Linux 的用户,可以使用 PackerYaourt 包管理器,从 AUR 源安装该工具。

$ yaourt -S dry-bin
或者
$ packer -S dry-bin

如果希望在 Docker 容器中运行 dry,可以运行如下命令。前提条件是已确认在操作系统中安装了 Docker。

推荐阅读:

$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock moncho/dry

如何启动并运行 Dry

在控制台运行 dry 命令即可启动该工具,其默认输出如下:

$ dry

如何使用 Dry 监控 Docker

你可以在 dry 的界面中按下 m 键打开监控模式。

如何使用 Dry 管理容器

在选中的容器上单击回车键,即可管理容器。Dry 提供如下操作:查看日志,查看、杀死、删除容器,停止、启动、重启容器,查看容器状态及镜像历史记录等。

如何监控容器资源利用率

用户可以使用 Stats+Top 选项查看指定容器的资源利用率。

该操作需要在容器管理界面完成(在上一步的基础上,点击 Stats+Top 选项)。另外,也可以按下 s 打开容器资源利用率界面。

如何查看容器、镜像及本地卷的磁盘使用情况

可以使用 F8 键查看容器、镜像及本地卷的磁盘使用情况。

该界面明确地给出容器、镜像和卷的总数,哪些处于使用状态,以及整体磁盘使用情况、可回收空间大小的详细信息。

如何查看已下载的镜像

按下 2 键即可列出全部的已下载镜像。

如何查看网络列表

按下 3 键即可查看全部网络及网关。

如何查看全部 Docker 容器

按下 F2 键即可列出列出全部容器,包括运行中和已关闭的容器。

Dry 快捷键

查看帮助页面或 dry GitHub 即可查看全部快捷键。


via: https://www.2daygeek.com/dry-an-interactive-cli-manager-for-docker-containers/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:pinewall 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

概述

Google 的 k8s 在 2017 年已经从容器编排领域的竞争中取得主导地位,从 Docker 之前的一度排挤到最终完全拥抱 k8s,显然 k8s 已经成了目前业界的标准。

但是到目前为止能提供 k8s 完全托管服务的云服务商少之又少,即便是目前在云提供商有统治力的 AWS 也没有完全提供 k8s 托管服务,仅仅提供有限的定制服务,在这一方面并不成熟。

然而 Google 的 k8s 托管服务,即 GKE,却将 k8s 托管服务做到了极致(至少目前看来),不仅提供了全套的 k8s 托管服务,更引人注目的是 Google 已然将 Autoscaler 和 k8s 集成,实现了 k8s 节点的自动伸缩机制,能根据 pod 的需求自动化添加或删除节点,当现有节点无法承载新的服务时会自动添加节点来满足需求,当现有节点足够空闲时会启用调节机制自动化收缩节点,从某种意义上来说这几乎做到了无服务器的理念。

然而这也许只是冰山一角,更多强大的功能还需要进一步探索,本文只是一个入门指南,主要指导能快速开始上手基于 Google Cloud Platform 的 GKE 服务(k8s 托管服务)。

GKE 入门指南

接下来我们一步步指引如何使用 GKE 来部署服务,前提是对 k8s 有所了解,能简单使用 kubectl 命令。

1. 安装并配置 Google Cloud SDK

Google Cloud SDK 是 访问 GCP(Google Cloud Platform)平台各种资源的命令行工具集,类似 aws 的 aws 命令行工具。

安装和配置就不多说了,点击下面链接选择相应操作系统版本的 tar 包下载,然后解压,在 PATH 环境变量中添加 google-cloud-sdk/bin 即可:

https://cloud.google.com/sdk/?hl=zh-cn

2. 初始化 Google Cloud SDK

初始化 Google Cloud SDK 是将 gcloud 命令和 Google 账号绑定起来并设置一些其他的默认值,比如区域,代理,账号,项目(Google 账号中新建的项目)之类的。

在执行 gcloud init 初始化之前得先给 gcloud 配置 HTTP 代理(GFW 你懂得),具体配置见我之前这篇文章。然后执行 gcloud init 完成初始化,直接根据向导来即可。

3. 到 Google Cloud Platform 控制台建一个 k8s 集群,记住名称

4. 安装 gcloud kubectl 组件

gcloud components install kubectl 

5. 获取群集的身份验证凭据

创建群集后,您需要获取身份验证凭据以与群集进行交互。要为集群进行身份验证,请运行以下命令:

gcloud container clusters get-credentials <上一步创建的集群名称> 

6. 接下来部署一个简单的 hello-server 服务到 GKE

kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080

相关链接

附录

gloud 常用命令

gcloud auth login --no-launch-browser # gcloud 登录认证
gcloud config set compute/zone [COMPUTE_ZONE] # 设置默认区域
gcloud components list # 列出可安装组件
gcloud components install [组件名称] # 安装组件
gcloud components update  # 更新所有已安装组件
gcloud components remove [组件名称] # 卸载已安装组件

设置 gcloud http 代理

gcloud config set proxy/type http
gcloud config set proxy/address 127.0.0.1
gcloud config set proxy/port 1087

设置集群 docker 私服认证

kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

注意:设置 docker 私服后,要在 GKE 部署 k8s 服务,必须得在 k8s 资源文件(yaml 格式)中的 container
同一级指定 imagePullSecrets 键,要不然仍然无法拉取配置的私服的镜像,示例资源文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets:
  - name: regcred

查看集群 docker 私服配置

kubectl get secret regcred --output=yaml      #base64 格式 显示
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d # base64