分类 容器与云 下的文章

这份可下载的指南充满了有用的教程,让 SRE 和系统管理员使用 Kubernetes 获得便利。

 title=

Kubernetes 是容器编排的事实标准,在基础设施管理和应用开发方面已经迅速发展成为容器环境的主导。作为一个拥有庞大的爱好者和专业人士社区的开源平台,以及作为云原生计算基金会的一部分,Kubernetes 不仅成为一个强大而令人印象深刻的编排系统本身,而且它还促进了一个庞大的相关工具和服务的生态系统,使其更容易使用,并通过更强大和复杂的组件扩展其功能。

在这本新的电子书《给 SRE 和系统管理员的 Kubernetes 指导》中,Jess Cherry(Ben Finkel 也有贡献)涵盖了一系列用于管理和整合 Kubernetes 的工具和服务。Cherry 和 Finkel 提供了一些有用的 入门 指南,包括 Kubernetes 和一些工具。他们甚至还分享了面试问题,以帮助读者为在这个快速增长的大规模生态系统中工作做好准备。

了解 Kubernetes

如果你刚开始接触 Kubernetes 和容器,Ben Finkel 的 《Kubernetes 入门》文如其题,也是一篇对你需要了解的相关概念的出色介绍。它也是一本轻量级的快速入门指南,用于设置和使用单节点集群进行测试。没有什么比亲身体验技术并直接进入学习更好的方法了。什么是 吊舱 Pod ? 如何在集群上部署一个应用程序? Ben 一一为你做了介绍。

与集群交互的主要方式是 kubectl 命令,这是一种 CLI 工具,它提供了一种与管理集群本身的 API 服务器交互的适合方式。例如,你可以使用 kubectl get 来列出上述的吊舱和部署,但正如你对 Kubernetes 这样复杂的东西所期望的那样,它的 CLI 界面有很强的功能和灵活性。Jess Cherry 的《9 个系统管理员需要知道的 kubectl 命令》速查表是一个很好的介绍,是使用 kubectl 的入门好方法。

同样,Cherry 的《给初学者的 Kubernetes 命令空间》也很好地解释了什么是命名空间以及它们在 Kubernetes 中的使用方式。

简化 Kubernetes 的工作

在一个复杂的系统中工作是很困难的,尤其是使用像 kubectl 这样强大而极简的 CLI 工具。幸运的是,在围绕 Kubernetes 的生态系统中,有许多工具可用于简化事情,使扩展服务和集群管理更容易。

可用于在 Kubernetes 上部署和维护应用和服务的 kubectl 命令主要使用的是 YAML 和 JSON。然而,一旦你开始管理更多应用,用 YAML 的大型仓库这样做会变得既重复又乏味。一个好的解决方案是采用一个模板化的系统来处理你的部署。Helm 就是这样一个工具,被称为 “Kubernetes 的包管理器”,Helm 提供了一种方便的方式来打包和共享应用。Cherry 写了很多关于 Helm 的有用文章:创建有效的 《Helm 海图》和有用的《Helm 命令》。

kubectl 也为你提供了很多关于集群本身的信息:上面运行的是什么,以及正在发生的事件。这些信息可以通过 kubectl 来查看和交互,但有时有一个更直观的 GUI 来进行交互是有帮助的。K9s 符合这两个世界的要求。虽然它仍然是一个终端应用,但它提供了视觉反馈和一种与集群交互的方式,而不需要长长的 kubectl 命令。Cherry 也写了一份很好的《k9s 使用入门》的指南。

建立在 Kubernetes 的强大和灵活性之上的扩展

幸运的是,尽管 Kubernetes 是复杂而强大的,但它惊人的灵活并且开源。它专注于其核心优势:容器编排,并允许围绕它的爱好者和专业人士的社区扩展其能力,以承担不同类型的工作负载。其中一个例子是 Knative,在 Kubernetes 之上提供组件,它为无服务器和事件驱动的服务提供工具,并利用 Kubernetes 的编排能力在容器中运行最小化的微服务。事实证明,这样做非常高效,既能提供在容器中开发小型、易于测试和维护的应用的好处,又能提供仅在需要时运行这些应用的成本优势,可以在特定事件中被触发,但在其他时候处于休眠。

在这本电子书中,Cherry 介绍了 Knative 和它的事件系统,以及为什么值得自己研究使用 Knative。

有一个完整的世界可以探索

通过 Jess Cherry 和 Ben Finkel 的这本新的电子书,可以开始了解 Kubernetes 和围绕它的生态系统。除了上述主题外,还有一些关于有用的 Kubernetes 扩展和第三方工具的文章。


via: https://opensource.com/article/21/6/kubernetes-ebook

作者:Chris Collins 选题:lujun9972 译者:geekpi 校对:wxy

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

开发和实施云原生(容器优先)软件的检查清单。

 title=

许多年来,单体应用是实现业务需求的标准企业架构。但是,当云基础设施开始以规模和速度为业务加速,这种情况就发生了重大变化。应用架构也发生了转变,以适应云原生应用和 微服务无服务器 以及事件驱动的服务,这些服务运行在跨混合云和多云平台的不可变的基础设施上。

云原生与 Kubernetes 的联系

根据 云原生计算基金会 (CNCF) 的说法:

“云原生技术使企业能够在现代动态环境中建立和运行可扩展的应用,如公共云、私有云和混合云。容器、服务网格、微服务、不可变的基础设施和声明式 API 就是这种方法的典范。”

“这些技术使松散耦合的系统具有弹性、可管理和可观察性。与强大的自动化相结合,它们使工程师能够以最小的工作量频繁地、可预测地进行重要的改变。”

Kubernetes 这样的容器编排平台允许 DevOps 团队建立不可变的基础设施,以开发、部署和管理应用服务。现在,快速迭代的速度与业务需求相一致。构建容器以在 Kubernetes 中运行的开发人员需要一个有效的地方来完成。

云原生软件的要求

创建云原生应用架构需要哪些能力,开发人员将从中获得哪些好处?

虽然构建和架构云原生应用的方法有很多,但以下是一些需要考虑的部分:

  • 运行时: 它们更多是以容器优先或/和 Kubernetes 原生语言编写的,这意味着运行时会如 Java、Node.js、Go、Python 和 Ruby。
  • 安全: 在多云或混合云应用环境中部署和维护应用时,安全是最重要的,应该是环境的一部分。
  • 可观察性: 使用 Prometheus、Grafana 和 Kiali 等工具,这些工具可以通过提供实时指标和有关应用在云中的使用和行为的更多信息来增强可观察性。
  • 效率: 专注于极小的内存占用、更小的构件大小和快速启动时间,使应用可跨混合/多云平台移植。
  • 互操作性: 将云原生应用与能够满足上述要求的开源技术相结合,包括 Infinispan、MicroProfile、Hibernate、Kafka、Jaeger、Prometheus 等,以构建标准运行时架构。
  • DevOps/DevSecOps: 这些方法论是为持续部署到生产而设计的,与最小可行产品 (MVP) 一致,并将安全作为工具的一部分。

让云原生具体化

云原生似乎是一个抽象的术语,但回顾一下定义并像开发人员一样思考可以使其更加具体。为了使云原生应用获得成功,它们需要包括一长串定义明确的组成清单。

你是如何规划云原生应用的设计的?在评论中分享你的想法。


via: https://opensource.com/article/20/1/cloud-native-software

作者:Daniel Oh 选题:lujun9972 译者:geekpi 校对:wxy

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

有很多令人信服的理由来用 Pulp 来托管你自己的容器注册中心。下面是其中的一些。

 title=

Linux 容器极大地简化了软件发布。将一个应用程序与它运行所需的一切打包的能力有助于提高环境的稳定性和可重复性。

虽然有许多公共注册中心可以上传、管理和分发容器镜像,但有许多令人信服的论据支持托管自己的容器注册中心。让我们来看看为什么自我托管是有意义的,以及 Pulp,一个自由开源项目,如何帮助你在企业内部环境中管理和分发容器。

为什么要托管你自己的容器注册中心

你可以考虑托管自己的容器注册中心,原因有很多:

  • 体积:一些容器镜像是相当大的。如果你有多个团队下载同一个镜像,这可能需要大量的时间,并给你的网络和预算带来压力。
  • 带宽:如果你在一个带宽有限的地区工作,或在一个出于安全原因限制访问互联网的组织中工作,你需要一个可靠的方法来管理你工作的容器。
  • 金钱:服务条款可以改变。外部容器注册中心能引入或增加速率限制阈值,这可能会对你的操作造成极大的限制。
  • 稳定性:托管在外部资源上的容器镜像可能会因为一些原因消失几天。小到你所依赖的更新容器镜像,可能会导致你想要避免的重大更改。
  • 隐私:你可能也想开发和分发容器,但你不想在公共的第三方注册中心托管。

使用 Pulp 进行自我托管

使用 Pulp,你可以避免这些问题并完全控制你的容器。

1、避免速率限制

在 Pulp 中创建容器镜像的本地缓存,可以让你组织中的每个人都能拉取到 Pulp 上托管的容器镜像,而不是从外部注册中心拉取。这意味着你可以避免速率限制,只有当你需要新的东西时才从外部注册中心进行同步。当你确实需要从外部注册中心同步容器时,Pulp 首先检查内容是否已经存在,然后再从远程注册中心启动同步。如果你受到注册中心的速率限制,你就只镜像你需要的内容,然后用 Pulp 在整个组织中分发它。

2、整理你的容器

使用 Pulp,你可以创建一个仓库,然后从任何与 Docker Registry HTTP API V2 兼容的注册中心镜像和同步容器。这包括 Docker、Google Container registry、Quay.io 等,也包括另一个 Pulp 服务器。对于你结合来自不同注册中心的镜像容器的方式,没有任何限制或约束。你可以自由地混合来自不同来源的容器。这允许你整理一套公共和私人容器,以满足你的确切要求。

3、无风险的实验

在 Pulp 中,每当你对仓库进行修改时,就会创建一个新的不可变的版本。你可以创建多个版本的仓库,例如,development、test、stage 和 production,并在它们之间推送容器。你可以自由地将容器镜像的最新更新从外部注册中心同步到 Pulp,然后让最新的变化在开发或其他环境中可用。你可以对你认为必要的仓库进行任何修改,并促进容器内容被测试团队或其他环境使用。如果出了问题,你可以回滚到早期版本。

4、只同步你需要的内容

如果你想使用 Pulp 来创建一个容器子集的本地缓存,而不是一个完整的容器注册中心,你可以从一个远程源过滤选择容器。使用 Pulp,有多种内容同步选项,以便你只存储你需要的内容,或配置你的部署,按需缓存内容。

5、在断线和空气隔离的环境中工作

如果你在一个断线或受限制的环境中工作,你可以从一个连接的 Pulp 实例中同步更新到你断连的 Pulp。目前,有计划为 Pulp 实现一个原生的空气隔离功能,以促进完全断线的工作流程。同时,作为一种变通方法,你可以使用 Skopeo 等工具来下载你需要的容器镜像,然后将它们推送到你断线的 Pulp 容器注册中心。

还有更多!

通过 Pulp,你还可以从容器文件中构建容器,将私有容器推送到仓库,并在整个组织中分发这些容器。我们将在未来的文章中对这个工作流程进行介绍。

如何开始

如果你对自我托管你的容器注册中心感兴趣,你现在就可以 安装 Pulp。随着 Pulp Ansible 安装程序的加入,安装过程已经被大量自动化和简化了。

Pulp 有一个基于插件的架构。当你安装 Pulp 时,选择容器插件和其他任何你想管理的内容插件类型。如果你想测试一下 Pulp,你今天就可以评估 Pulp 的容器化版本。

如果你有任何问题或意见,请随时在 Freenode IRC 的 #pulp 频道与我们联系,我们也很乐意在我们的邮件列表 [email protected] 中接受问题。


via: https://opensource.com/article/21/5/container-management-pulp

作者:Melanie Corr 选题:lujun9972 译者:geekpi 校对:wxy

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

在复杂的 IT 基础设施中,有许多重复性任务。成功运行这些任务并不容易。运行失败大多数是人为错误引发。在 Ansible 帮助下,你可以通过远程主机来执行所有任务,这些远程主机按照 行动手册 playbook 执行,行动手册可以根据需要重复使用多次。在本文中,你将学习如何在 Fedora Linux 上安装、配置 Ansible,以及如何使用它来管理、配置 Podman 容器。

Ansible

Ansible 是一个由红帽赞助的开源基础设施自动化工具。它可以处理大型基础设施带来的所有问题,例如安装和更新软件包、备份、确保特定服务持续运行等等。你用 YAML 写的行动手册来做这些事。Ansible 行动手册可以反复使用,使系统管理员的工作不那么复杂。行动手册减少了重复任务,并且可以轻松修改。但是我们有很多像 Ansible 一样的自动化工具,为什么要用它呢?与其他一些配置管理工具不同,Ansible 是无代理的:你不必在受管节点上安装任何东西。

Podman

Podman 是一个开源的容器引擎,用于开发、管理和运行容器镜像。但什么是容器呢?每当你创建任何新应用程序并将其部署在物理服务器、云服务器或虚拟机上时,你面临的最常见问题是可移植性和兼容性。这就是容器出现的原因。容器在操作系统级别上进行虚拟化,因此它们只包含所需的库和应用程序服务。容器的好处包括:

  • 便携性
  • 隔离性
  • 扩展性
  • 轻量级
  • 快速启动
  • 更小的磁盘和内存需求

简而言之:当你为任何应用程序构建容器镜像时,所有必需的依赖项都被打包到容器中。你现在可以在任何主机操作系统上运行该容器,没有任何可移植性和兼容性问题。

Podman 的关键亮点在于它没有守护程序,因此不需要 root 权限来运行容器。你可以借助 Dockerfile 构建容器镜像,或者从 Docker Hub、fedoraproject.orgQuay 上拉取镜像。

为什么用 Ansible 配置 Podman?

Ansible 提供了一种轻松多次运行重复任务的方法。它还为云提供商(如 AWS、GCP 和 Azure)、容器管理工具(如 Docker 和 Podman)与数据库管理提供了大量模块。Ansible 还有一个社区(Ansible Galaxy),在这里你可以找到大量 Ansible 角色 Roles ,它们由来自世界各地的贡献者创建。因为这些,Ansible 成为了 DevOps 工程师和系统管理员手中的好工具。

借助 DevOps,应用程序的开发步伐很快。开发的应用不局限于任意操作系统,这点至关重要。这就是 Podman 出现的地方。

安装 Ansible

首先,安装 Ansible:

$ sudo dnf install ansible -y

配置 Ansible

Ansible 需要在受管节点上运行 ssh,所以首先生成一个 密钥对 Key Pair

$ ssh-keygen

生成密钥后,将密钥复制到受管节点。

输入 yes,然后输入受管节点的密码。现在可以远程访问受管主机。

为了能够访问受管节点,你需要将所有主机名或 IP 地址存储在清单文件中。默认情况下,这是在 ~/etc/ansible/hosts

这是 库存 inventory 文件的样子。方括号用于将组分配给某些特定的节点。

[group1]
green.example.com
blue.example.com
[group2]
192.168.100.11
192.168.100.10

检查所有受管节点是否可以到达。

$ ansible all -m ping

你可以看到如下输出:

[mahesh@fedora new] $ ansible all -m ping
fedora.example.com I SUCCESS {
    "ansibe_facts": {
       "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[mahesh@fedora new] $

现在创建你的第一个 行动手册 playbook ,它将在受管节点上安装 Podman。首先用 .yml 拓展名创建一个任意名称的文件。

$ vim name_of_playbook.yml

行动手册应该如下所示。第一个字段是行动手册的名称。主机字段(hosts)用于提及清单中提到的主机名或组名。become: yes 表示升级权限,以及任务(tasks)包含所要执行的任务,这里的名称(name)指定任务(tasks)名称,yum 是安装软件包的模块,下面在名称字段(name)指定软件包名称,在状态字段(state)指定安装或删除软件包。

---
 - name: First playbook
   hosts: fedora.example.com
   become: yes
   tasks:
     - name: Installing podman.
       yum:
         name: podman
         state: present

检查文件中是否有语法错误:

$ ansible-playbook filename --syntax-check

现在运行行动手册:

$ ansible-playbook filename

你可以看到如下输出:

[mahesh@fedora new] $ ansible-playbook podman_installation.yml
PLAY [First playbook] *************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
0k: [fedora.example.com]

TASK [Installing podman] ************************************************************************************************
changed: [fedora.example.com]

PLAY RECAP *************************************************************************************************
fedora.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
[mahesh@fedora new] $

现在创建一个新的行动手册,从 Docker Hub 中拉取一个镜像。你将使用 podman_image 模块从 Docker Hub 中提取版本号为 2-alpine 的 httpd 镜像。

---
 - name: Playbook for podman.
    hosts: fedora.example.com
    tasks:
     - name: Pull httpd:2-alpine image from dockerhub.
       podman_image:
         name: docker.io/httpd
         tag: 2-alpine

现在检查已拉取的镜像:

[mahesh@fedora new] $ podman images
REPOSITORY                           TAG                  IMAGE ID           CREATED             SIZE
docker.io/library/httpd       2-alpine         fa848876521a    11 days ago        57 MB

[mahesh@fedora new] $

创建一个新的行动手册来运行 httpd 镜像。更多信息请查看 podman\_container 模块文档。

---
 - name: Playbook for podman.
   hosts: fedora.example.com
   tasks:
     - name: Running httpd image.
       containers.podman.podman_container:
         name: my-first-container
         image:  docker.io/httpd:2-alpine
         state: started

检查容器运行状态。

[mahesh@fedora new] $ podman ps
CONTAINER ID        IMAGE    COMMAND   CREATED      STATUS         PORTS         NAMES
45d966eOe207     docker.io/library/httpd:2-alpine    httpd-foreground    13 seconds ago    Up 13 seconds ago       my-first-container

[mahesh@fedora new] $

现在停止已运行的容器,改变状态,由 started 变为 absent

- name: Stopping httpd container.
  containers.podman.podman_container:
    name: my-first-container
    image: docker.io/httpd:2-alpine
    state: absent

当你执行 podman ps 命令时,你看不到任何运行的容器。

[mahesh@fedora new] $ podman ps
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

[mahesh@fedora new] $

podman_container 可以做很多事情,例如重新创建容器、重新启动容器、检查容器是否正在运行等等。有关执行这些操作的信息,请参考 文档


via: https://fedoramagazine.org/using-ansible-to-configure-podman-containers/

作者:mahesh1b 选题:lujun9972 译者:DCOLIVERSUN 校对:wxy

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

开始探索 kubectl、容器、吊舱等,接着下载我们的免费的速查表,这样你就可以随时掌握关键的命令了。

 title=

云计算主要是在 Kubernetes 上运行,Kubernetes 主要是在 Linux 上运行,而 Linux 在有熟练的系统管理员控制时运行得最好。无论你认为自己是云计算架构师还是只是一个保守的系统管理员,现代互联网都需要了解如何在容器中创建应用和服务,按需扩展,按需扩展以及如何明智地进行监视和管理。

进入勇敢的容器世界的第一步是学习 Kubernetes 和它的基本命令:kubectl

安装 kubectl

kubectl 命令允许你在 Kubernetes 集群上运行命令。你使用 kubectl 来部署应用、查看日志、检查和管理集群资源,并在出现问题时进行故障排除。kubectl(以及整个 Kubernetes)的典型“问题”是,要对集群运行命令,你首先需要一个集群。然而,有一些简单的解决方案。

首先,你可以创建自己的 Kubernetes 集群,只需买三块树莓派板和相关外围设备(主要是电源)。当你获得了硬件,阅读 Chris Collins 的 使用树莓派构建 Kubernetes 集群,你就会拥有自己的安装有 kubectl 的集群。

另一种获得集群的方法是使用 Minikube,这是一个 Kubernetes 的实践环境。在所有建立和运行集群的方法中,这是最简单的。

还有更多的选择;例如,你可以参加一个关于 Kubernetes 的课程,以获得一个运行集群的实验室,或者你可以在云上购买时间。只要你有一个 Kubernetes 环境来练习,如何获得集群并不重要。

当你你能访问一个集群,你就可以开始探索 kubectl 命令。

了解吊舱和容器

容器是一个轻量级的、部分的 Linux 系统,专门用于运行一个应用或服务。容器受到 内核命名空间 的限制,这使它能够访问其主机(运行容器的计算机)上的重要系统组件,同时防止它向其主机发送数据。容器以容器镜像(或简称 镜像)的形式保存,并由称为 ContainerfileDockerfile 的文本文件定义。

吊舱 Pod 是容器的正式集合,也是管理员扩展、监控和维护任何数量的容器的一种简单方法。

这些一起就像 Kubernetes 的“应用程序”。创建或获取容器镜像是你在云上运行服务的方式。

运行一个吊舱

容器镜像的两个可靠的仓库是 Docker Hub 和 Quay。你可以在仓库中搜索可用的镜像列表。通常有由项目提供的大型项目的官方镜像,也有专门的、定制的或特殊项目的社区镜像。最简单和最小的镜像之一是 BusyBox 容器,它提供了一个最小的 shell 环境和一些常用命令。

无论你是从仓库中拉取镜像,还是自己编写镜像定义并从 Git 仓库中拉取到集群中,其工作流程都是一样的。当你想在 Kubernetes 中启动一个吊舱时:

  1. Docker HubQuay 上找到一个你想使用的镜像
  2. 拉取镜像
  3. 创建一个吊舱
  4. 部署吊舱

以 BusyBox 容器为例子,你可以用一条命令完成最后三个步骤:

$ kubectl create deployment my-busybox --image=busybox

等待 kubectl 完成这个过程,最后你就有了一个正在运行的 BusyBox 实例。这个吊舱并没有暴露给其他人。它只是在后台安静地在你的集群上运行。

要看你的集群上有哪些吊舱在运行:

$ kubectl get pods --all-namespaces

你也可以获得关于吊舱部署的信息:

$ kubectl describe deployment my-busybox

与吊舱互动

容器通常包含使其自动化的配置文件。例如,将 Nginx httpd 服务器作为容器安装,应该不需要你的互动。你开始运行容器,它就会工作。对于你添加到吊舱中的第一个容器和之后的每个容器都是如此。

Kubernetes 模型的优点之一是,你可以根据需要扩展你的服务。如果你的网络服务被意外的流量淹没,你可以在你的云中启动一个相同的容器(使用 scaleautoscale 子命令),使你的服务处理传入请求的能力增加一倍。

即便如此,有时还是很高兴看到一些证明吊舱正在按预期运行的证据,或者能够对似乎无法正常运行的某些问题进行故障排除。为此,你可以在一个容器中运行任意的命令:

$ kubectl exec my-busybox -- echo "hello cloud"

另外,你可以在你的容器中打开一个 shell,用管道将你的标准输入输入到其中,并将其输出到终端的标准输出:

$ kubectl exec --stdin --tty my-busybox -- /bin/sh

暴露服务

默认情况下,吊舱在创建时不会暴露给外界,这样你就有时间在上线前进行测试和验证。假设你想把 Nginx Web 服务器作为一个吊舱安装和部署在你的集群上,并使其可以访问。与任何服务一样,你必须将你的吊舱指向服务器上的一个端口。kubectl 子命令 expose 可以为你做到这点:

$ kubectl create deployment \
  my-nginx --image=nginx
$ kubectl expose deployment \
  my-nginx --type=LoadBalancer --port=8080

只要你的集群可以从互联网上访问,你就可以通过打开浏览器并导航到你的公共 IP 地址来测试你的新 Web 服务器的可访问性。

不仅仅是吊舱

Kubernetes 提供了很多东西,而不仅仅是存储普通服务的镜像。除了作为一个 容器编排 系统,它还是一个云开发的平台。你可以编写和部署应用,管理和监控性能和流量,实施智能负载平衡策略等。

Kubernetes 是一个强大的系统,它已经迅速成为各种云的基础,最主要的是 开放混合云。今天就开始学习 Kubernetes 吧。随着你对 Kubernetes 的进一步了解,你会需要一些关于其主要概念和一般语法的快速提醒,所以 下载我们的 Kubernetes 速查表 并将它放在身边。


via: https://opensource.com/article/21/5/kubernetes-cheat-sheet

作者:Seth Kenlon 选题:lujun9972 译者:geekpi 校对:wxy

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

使用容器工作是很多用户和开发者的日常任务。容器开发者经常需要频繁地(重新)构建容器镜像。如果你开发容器,你有想过减小镜像的大小吗?较小的镜像有一些好处。在下载的时候所需要的带宽更少,而且在云环境中运行的时候也可以节省开销。而且在 Fedora CoreOSIoT 以及Silverblue 上使用较小的容器镜像可以提升整体系统性能,因为这些操作系统严重依赖于容器工作流。这篇文章将会提供一些减小容器镜像大小的技巧。

工具

以下例子所用到的主机操作系统是 Fedora Linux 33。例子使用 Podman 3.1.0 和Buildah 1.2.0。Podman 和 Buildah 已经预装在大多数 Fedora Linux 变种中。如果你没有安装 Podman 和 Buildah,可以用下边的命令安装:

$ sudo dnf install -y podman buildah

任务

从一个基础的例子开始。构建一个满足以下需求的 web 容器:

  • 容器必须基于 Fedora Linux
  • 使用 Apache httpd web 服务器
  • 包含一个定制的网站
  • 容器应该比较小

下边的步骤也适用于比较复杂的镜像。

设置

首先,创建一个工程目录。这个目录将会包含你的网站和容器文件:

$ mkdir smallerContainer
$ cd smallerContainer
$ mkdir files
$ touch files/index.html

制作一个简单的登录页面。对于这个演示,你可以将下面的 HTML 复制到 index.html 文件中。

<!doctype html>

<html lang="de">
<head>
  <title>Container Page</title>
</head>

<body>
  <header>
    <h1>Container Page</h1>
  </header>
  <main>
    <h2>Fedora</h2>
    <ul>
      <li><a href="https://getfedora.org">Fedora Project</a></li>
      <li><a href="https://docs.fedoraproject.org/">Fedora Documentation</a></li>
      <li><a href="https://fedoramagazine.org">Fedora Magazine</a></li>
      <li><a href="https://communityblog.fedoraproject.org/">Fedora Community Blog</a></li>
    </ul>
    <h2>Podman</h2>
    <ul>
      <li><a href="https://podman.io">Podman</a></li>
      <li><a href="https://docs.podman.io/">Podman Documentation</a></li>
      <li><a href="https://github.com/containers/podman">Podman Code</a></li>
      <li><a href="https://podman.io/blogs/">Podman Blog</a></li>
    </ul>
    <h2>Buildah</h2>
    <ul>
      <li><a href="https://buildah.io">Buildah</a></li>
      <li><a href="https://github.com/containers/buildah">Buildah Code</a></li>
      <li><a href="https://buildah.io/blogs/">Buildah Blog</a></li>
    </ul>
    <h2>Skopeo</h2>
    <ul>
      <li><a href="https://github.com/containers/skopeo">skopeo Code</a></li>
    </ul>
    <h2>CRI-O</h2>
    <ul>
      <li><a href="https://cri-o.io/">CRI-O</a></li>
      <li><a href="https://github.com/cri-o/cri-o">CRI-O Code</a></li>
      <li><a href="https://medium.com/cri-o">CRI-O Blog</a></li>
    </ul>
  </main>
</body>

</html>

此时你可以选择在浏览器中测试上面的 index.html 文件:

$ firefox files/index.html

最后,创建一个容器文件。这个文件可以命名为 Dockerfile 或者 Containerfile

$ touch Containerfile

现在你应该有了一个工程目录,并且该目录中的文件系统布局如下:

smallerContainer/
|- files/
|    |- index.html
|
|- Containerfile

构建

现在构建镜像。下边的每个阶段都会添加一层改进来帮助减小镜像的大小。你最终会得到一系列镜像,但只有一个 Containerfile

阶段 0:一个基本的容器镜像

你的新镜像将会非常简单,它只包含强制性步骤。在 Containerfile 中添加以下内容:

# 使用 Fedora 33 作为基镜像
FROM registry.fedoraproject.org/fedora:33

# 安装 httpd
RUN dnf install -y httpd

# 复制这个网站
COPY files/* /var/www/html/

# 设置端口为 80/tcp
EXPOSE 80

# 启动 httpd
CMD ["httpd", "-DFOREGROUND"]

在上边的文件中有一些注释来解释每一行内容都是在做什么。更详细的步骤:

  1. FROM registry.fedoraproject.org/fedora:33 的基础上创建一个构建容器
  2. 运行命令: dnf install -y httpd
  3. 将与 Containerfile 有关的文件拷贝到容器中
  4. 设置 EXPOSE 80 来说明哪个端口是可以自动设置的
  5. 设置一个 CMD 指令来说明如果从这个镜像创建一个容器应该运行什么

运行下边的命令从工程目录创建一个新的镜像:

$ podman image build -f Containerfile -t localhost/web-base

使用一下命令来查看你的镜像的属性。注意你的镜像的大小(467 MB)。

$ podman image ls
REPOSITORY                         TAG     IMAGE ID      CREATED        SIZE
localhost/web-base                 latest  ac8c5ed73bb5  5 minutes ago  467 MB
registry.fedoraproject.org/fedora  33      9f2a56037643  3 months ago   182 MB

以上这个例子中展示的镜像在现在占用了467 MB的空间。剩下的阶段将会显著地减小镜像的大小。但是首先要验证镜像是否能够按照预期工作。

输入以下命令来启动容器:

$ podman container run -d --name web-base -P localhost/web-base

输入以下命令可以列出你的容器:

$ podman container ls
CONTAINER ID  IMAGE               COMMAND               CREATED        STATUS            PORTS                  NAMES
d24063487f9f  localhost/web-base  httpd -DFOREGROUN...  2 seconds ago  Up 3 seconds ago  0.0.0.0:46191->80/tcp  web-base

以上展示的容器正在运行,它正在监听的端口是 46191 。从运行在主机操作系统上的 web 浏览器转到 localhost:46191 应该呈现你的 web 页面:

$ firefox localhost:46191

阶段 1:清除缓存并将残余的内容从容器中删除

为了优化容器镜像的大小,第一步应该总是执行“清理”。这将保证安装和打包所残余的内容都被删掉。这个过程到底需要什么取决于你的容器。对于以上的例子,只需要编辑 Containerfile 让它包含以下几行。

[...]
# Install httpd
RUN dnf install -y httpd && \
    dnf clean all -y
[...]

构建修改后的 Containerfile 来显著地减小镜像(这个例子中是 237 MB)。

$ podman image build -f Containerfile -t localhost/web-clean
$ podman image ls
REPOSITORY            TAG     IMAGE ID      CREATED        SIZE
localhost/web-clean   latest  f0f62aece028  6 seconds ago  237 MB

阶段 2:删除文档和不需要的依赖包

许多包在安装时会被建议拉下来,包含一些弱依赖和文档。这些在容器中通常是不需要的,可以删除。 dnf 命令有选项可以表明它不需要包含弱依赖或文档。

再次编辑 Containerfile ,并在 dnf install 行中添加删除文档和弱依赖的选项:

[...]
# Install httpd
RUN dnf install -y httpd --nodocs --setopt install_weak_deps=False && \
    dnf clean all -y
[...]

构建经过以上修改后的 Containerfile 可以得到一个更小的镜像(231 MB)。

$ podman image build -f Containerfile -t localhost/web-docs
$ podman image ls
REPOSITORY            TAG     IMAGE ID      CREATED        SIZE
localhost/web-docs    latest  8a76820cec2f  8 seconds ago  231 MB

阶段 3:使用更小的容器基镜像

前面的阶段结合起来,使得示例镜像的大小减少了一半。但是仍然还有一些途径来进一步减小镜像的大小。这个基镜像 registry.fedoraproject.org/fedora:33 是通用的。它提供了一组软件包,许多人希望这些软件包预先安装在他们的 Fedora Linux 容器中。但是,通用的 Fedora Linux 基镜像中提供的包通常必须要的更多。Fedora 项目也为那些希望只从基本包开始,然后只添加所需内容来实现较小总镜像大小的用户提供了一个 fedora-minimal 镜像。

使用 podman image search 来查找 fedora-minimal 镜像,如下所示:

$ podman image search fedora-minimal
INDEX               NAME   DESCRIPTION   STARS   OFFICIAL   AUTOMATED
fedoraproject.org   registry.fedoraproject.org/fedora-minimal         0

fedora-minimal 基镜像不包含 DNF,而是倾向于使用不需要 Python 的较小的 microDNF。当 registry.fedoraproject.org/fedora:33registry.fedoraproject.org/fedora-minimal:33 替换后,需要用 microdnf 命令来替换 dnf

# 使用 Fedora minimal 33 作为基镜像
FROM registry.fedoraproject.org/fedora-minimal:33

# 安装 httpd
RUN microdnf install -y httpd --nodocs --setopt install_weak_deps=0 && \
    microdnf clean all -y
[...]

使用 fedora-minimal 重新构建后的镜像大小如下所示 (169 MB):

$ podman image build -f Containerfile -t localhost/web-docs
$ podman image ls
REPOSITORY             TAG     IMAGE ID      CREATED        SIZE
localhost/web-minimal  latest  e1603bbb1097  7 minutes ago  169 MB

最开始的镜像大小是 467 MB。结合以上每个阶段所提到的方法,进行重新构建之后可以得到最终大小为 169 MB 的镜像。最终的 镜像大小比最开始的 镜像小了 182 MB!

从零开始构建容器

前边的内容使用一个容器文件和 Podman 来构建一个新的镜像。还有最后一个方法要展示——使用 Buildah 来从头构建一个容器。Podman 使用与 Buildah 相同的库来构建容器。但是 Buildah 被认为是一个纯构建工具。Podman 被设计来是为了代替 Docker 的。

使用 Buildah 从头构建的容器是空的——它里边什么都 没有 。所有的东西都需要安装或者从容器外复制。幸运地是,使用 Buildah 相当简单。下边是一个从头开始构建镜像的小的 Bash 脚本。除了运行这个脚本,你也可以在终端逐条地运行脚本中的命令,来更好的理解每一步都是做什么的。

#!/usr/bin/env bash
set -o errexit

# 创建一个容器
CONTAINER=$(buildah from scratch)

# 挂载容器文件系统
MOUNTPOINT=$(buildah mount $CONTAINER)

# 安装一个基本的文件系统和最小的包以及 nginx
dnf install -y --installroot $MOUNTPOINT  --releasever 33 glibc-minimal-langpack httpd --nodocs --setopt install_weak_deps=False

dnf clean all -y --installroot $MOUNTPOINT --releasever 33

# 清除
buildah unmount $CONTAINER

# 复制网站
buildah copy $CONTAINER 'files/*' '/var/www/html/'

# 设置端口为 80/tcp
buildah config --port 80 $CONTAINER

# 启动 httpd
buildah config --cmd "httpd -DFOREGROUND" $CONTAINER

# 将容器保存为一个镜像
buildah commit --squash $CONTAINER web-scratch

或者,可以通过将上面的脚本传递给 Buildah 来构建镜像。注意不需要 root 权限。

$ buildah unshare bash web-scratch.sh
$ podman image ls
REPOSITORY             TAG     IMAGE ID      CREATED        SIZE
localhost/web-scratch  latest  acca45fc9118  9 seconds ago  155 MB

最后的镜像只有 155 MB!而且 攻击面 也减少了。甚至在最后的镜像中都没有安装 DNF(或者 microDNF)。

结论

构建一个比较小的容器镜像有许多优点。减少所需要的带宽、磁盘占用以及攻击面,都会得到更好的镜像。只用很少的更改来减小镜像的大小很简单。许多更改都可以在不改变结果镜像的功能下完成。

只保存所需的二进制文件和配置文件来构建非常小的镜像也是可能的。


via: https://fedoramagazine.org/build-smaller-containers/

作者:Daniel Schier 选题:lujun9972 译者:ShuyRoy 校对:wxy

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