介绍

在本文中,我们将考虑如何使用多阶段构建来创建 Docker 镜像。使用有关 Terraform 的图像。
实际上,我想了解如何将 Terraform 与 Kubernetes 一起使用,但我在创建镜像时遇到了困难,所以我决定把它放在一起。

文章摘要

Terraform 有一个现有的图像,所以使用它来节省时间。
https://hub.docker.com/r/hashicorp/terraform/

在本文中,我们将考虑您拥有现有资源(Kubernetes 资源、AWS)并开始使用 Terraform 的情况。在这种情况下,最好能够将现有资源导入 Terraform。所以,这次我决定接触 Terraformer。

如果你使用 Docker 的 Terraformer,你需要自己使用镜像。正如其他文章中介绍的那样,我们还将考虑如何在多阶段构建中减小图像大小。

文章的流程如下。

  • 将 Terraform 与 Docker 结合使用
  • 创建可以使用 Terraformer 的图像
    • 基本图像选择
    • 多阶段构建实践
  • 试试 Terraformer
    • AWS
    • Kubernetes(失败)

将 Terraformer 与 Docker 一起使用

首先,在 EC2 上安装 Docker。方法与目前为止的文章相同,所以我将省略细节。
我改变的一件事是我暂时用newgrp docker 更改了组,而没有再次登录。但是,由于变成了新的shell,所以我注意到sh文件的后续处理不会进行。

理论是它是一个家庭。嘘
#!/bin/bash -ex

cd $HOME

echo "install docker"
DOCKER_VERSION=20.10.13-2.amzn2 #yum list | grep docker
sudo yum install -y docker-$DOCKER_VERSION
sudo systemctl start docker
sudo systemctl enable docker
sudo gpasswd -a ec2-user docker
newgrp docker

创建可以使用 Terraformer 的图像

选择基础镜像

我将创建一个可以使用 Terraformer 的图像,但我想知道FROM 指定的基本图像应该是什么。运行 Terraform 和 Terraformer 的源文件是必需的,但除此之外,根据应用程序进行更改。在本文中,我们将关注图像大小,并考虑是否可以通过排除不必要的文件来使其尽可能小。考虑使用下图。

图片名称 尺寸 评论
地形 110MB 带有 Terraform 的图像
https://hub.docker.com/r/hashicorp/terraform/
高山 5.54MB 给人的印象是它通常被视为轻量级图像。
Distroless(静态) 2.36MB 这是比 Alpine 更轻的图像。
https://console.cloud.google.com/gcr/images/distroless/GLOBAL/static
CentOS7 204MB 作为参考,我检查了将以各种方式包含的 CentOS 的大小。
https://hub.docker.com/_/centos

从大小来看,Terraform 图像超过 100MB。即使缩小大小,也可能超过 100MB。 Alpine 和 Distroless 的大小差异大约是两倍大,但如果你看 100MB 的大小,可能差异很小。因此,最好也考虑包含的源文件中的差异。

多阶段构建

根据上面列出的图像创建一个 Terraformer 图像。我们还使用多阶段构建来创建仅包含我们需要的文件的图像。
多阶段构建允许您使用中间图像来构建源文件,与最终图像分开。这样可以更轻松地从生成的映像中排除仅在安装期间使用的文件或未使用的包。
请注意,会创建一些中间图像,因此可能需要磁盘空间。

基于 Terraform(CentOS7,通过 aws-cli)

现在让我们在 Terraform 镜像上安装 Terraformer 并创建镜像。要使用的图像的作用如下。

图片名称 角色 评论
hashcorp/terraform:0.13.7 运行 Terraform,Terraformer 从创建的图像运行 Terraform 和 Terraformer。
centos:centos7 安装 Terraformer Terraform 映像可能会留下垃圾或缺少安装工具,因此请使用 CentOS 映像。
亚马逊/aws-cli:2.7.21 AWS 配置和凭证设置 用于从 Terraformer 访问 AWS。我只是为 AWS 访问创建了一个文件,但我尝试使用 AWS CLI,以免犯任何小错误。

在做 Try & Error 时,最终的 Dockerfile 如下。

Dockerfile
#AWSの認証情報。ビルド時に指定して、Dockerfileには書かないようにしました。
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG AWS_DEFAULT_REGION
ARG AWS_DEFAULT_OUTPUT=json
#Terraform、Terraformerについて
ARG TERRAFORMER_VERSION=0.8.21
ARG PROVIDER=all
ARG TMPDIR=/tmp/terraformer
ARG HOME_DIR=/root
ARG PROVIDER_FILE=provider.tf

FROM centos:centos7 as builder
#https://github.com/GoogleCloudPlatform/terraformer#installation
ARG TERRAFORMER_VERSION
ARG PROVIDER
ARG TMPDIR
WORKDIR ${TMPDIR}
RUN curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/${TERRAFORMER_VERSION}/terraformer-${PROVIDER}-linux-amd64
RUN chmod +x terraformer-${PROVIDER}-linux-amd64

FROM amazon/aws-cli:2.7.21 as aws-config
#https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG AWS_DEFAULT_REGION
ARG AWS_DEFAULT_OUTPUT
RUN aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
RUN aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
RUN aws configure set region $AWS_DEFAULT_REGION
RUN aws configure set output $AWS_DEFAULT_OUTPUT

FROM hashicorp/terraform:0.13.7
#Terraformerがサポートしているバージョンを指定します。(https://github.com/GoogleCloudPlatform/terraformer#capabilities)
ARG PROVIDER
ARG TMPDIR
ARG HOME_DIR
ARG PROVIDER_FILE
WORKDIR $TMPDIR
#Terraformのプラグインをインストールするために/tmp/terraformerディレクトリを作成します。こうしないとエラーになりました。
WORKDIR $HOME_DIR
COPY --from=builder ${TMPDIR}/terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer
#必要な実行ファイルのみコピーして持ってきています。
COPY --from=builder /lib64/ld-linux-x86-64.so.2 /lib64/libpthread.so.0 /lib64/libc.so.6 /lib64/
#Terraformerの実行ファイルの依存ライブラリも持ってくる必要があります。
COPY --from=aws-config $HOME_DIR/.aws $HOME_DIR/.aws
#AWSの認証情報が入ったファイルをコピーして持ってきます。
COPY $PROVIDER_FILE $HOME_DIR/
RUN ["terraform","init"]
ENTRYPOINT [""]
#もともとterraformが実行されるようになっているので、上書きしました。
r 在 p lovi。 tf
provider "aws" { version = "4.25.0" }
provider "kubernetes" { version = "2.12.1" }

上面描述了我们在 Dockerfile 中所做的事情。其他注意事项如下。
・由于未知 Terraform 图像可以处理多远,所以尽可能避免RUN 以防止出错。
・Terraformer 的依赖库可以通过以下命令进行检查。仅使用错误语句很难理解,因此我必须小心。

[root@4dcc09333e27 terraformer]# ldd terraformer-all-linux-amd64
        linux-vdso.so.1 =>  (0x00007ffee23fc000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe0df421000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fe0df053000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe0df63d000)

现在让我们构建它。

[ec2-user@ip-10-0-0-203 ~]$ docker build \
-f $HOME/Terraform/Dockerfile . \
-t my_tfr:Terraform \
--build-arg AWS_ACCESS_KEY_ID="..." \
--build-arg AWS_SECRET_ACCESS_KEY="..." \
--build-arg AWS_DEFAULT_REGION=...
Sending build context to Docker daemon  32.77kB
Step 1/38 : ARG AWS_ACCESS_KEY_ID
・・・
Successfully built aaa1f443c6c4
Successfully tagged my_tfr:Terraform

检查 Terraform 和 Terraformer 是否可以执行。

[ec2-user@ip-10-0-0-203 ~]$ docker run my_tfr:Terraform terraform -version
Terraform v0.13.7
+ provider registry.terraform.io/hashicorp/aws v4.25.0
+ provider registry.terraform.io/hashicorp/kubernetes v2.12.1

Your version of Terraform is out of date! The latest version
is 1.2.7. You can update by downloading from https://www.terraform.io/downloads.html
[ec2-user@ip-10-0-0-203 ~]$ docker run my_tfr:Terraform terraformer -v
version v0.8.21

基于 Alpine(CentOS7,aws-cli,通过 Terraform)

接下来,让我们基于 Alpine 创建一个镜像。
基础与 Terraform 基础相同,但最终运行 Terraform 和 Terraformer 的是 Alpine 映像。 Terraform 图像用于带来 Terraform 可执行文件。

图片名称 角色 评论
hashcorp/terraform:0.13.7 为了节省安装 Terraform。 使用 Terraform 作为中间图像,仅将 Terraform 带入最终图像。
做cr。艾欧/伊布里/阿尔卑斯山:3.16.2 运行 Terraform,Terraformer
Dockerfile
(変数の定義 省略)

FROM centos:centos7 as builder
(Terraformerのインストール 省略)

FROM amazon/aws-cli:2.7.21 as aws-config
(AWS認証情報の設定 省略)

FROM hashicorp/terraform:0.13.7 as terraform
#中間イメージとして、Terraformを使い、インストールを省く。

FROM docker.io/library/alpine:3.16.2
ARG PROVIDER
ARG TMPDIR
ARG HOME_DIR
ARG PROVIDER_FILE
WORKDIR $TMPDIR
WORKDIR $HOME_DIR
COPY --from=builder ${TMPDIR}/terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer
COPY --from=builder /lib64/ld-linux-x86-64.so.2 /lib64/libpthread.so.0 /lib64/libc.so.6 /lib64/
COPY --from=aws-config $HOME_DIR/.aws $HOME_DIR/.aws
COPY --from=terraform /bin/terraform /bin/terraform
#↑ここだけ違う。Terraformの実行ファイルを持ってくる。
COPY $PROVIDER_FILE $HOME_DIR/
RUN ["terraform","init"]
ENTRYPOINT [""]

它可以与 Terraform 基础类似地构建。

基于 Distroless(CentOS7,aws-cli,通过 Terraform)

最后,使用 Distroless 映像。与 Alpine base 相比,只有 base image 不同。所有其他命令完全相同。
尤其是,

FROM docker.io/library/alpine:3.16.2

从,

FROM gcr.io/distroless/static:latest

只需将其重写为由于只执行最小命令,我认为即使更改基本映像也很难出错。
但是,有些命令无法在 Distroless 上执行。一个具体的例子是 sh。

[ec2-user@ip-10-0-0-203 ~]$ docker run my_tfr:Alpine sh -c id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
[ec2-user@ip-10-0-0-203 ~]$ docker run my_tfr:Distroless sh -c id
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "sh": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled

在 Distroless 镜像中使用 sh 的一种方法是使用带有调试标签的镜像。但请注意,执行的是/busybox/sh,而不是/bin/sh。在 CentOS 等上工作的 shell 有可能无法工作。

[ec2-user@ip-10-0-0-203 ~]$ docker run -it gcr.io/distroless/static:debug
/ # ps
PID   USER     TIME  COMMAND
    1 root      0:00 /busybox/sh
    6 root      0:00 ps

比较结果图像的大小

现在让我们比较各种方法创建的图像的大小。

[ec2-user@ip-10-0-0-203 ~]$ docker images | head -n 1; docker images | grep my_tfr
REPOSITORY                 TAG          IMAGE ID       CREATED          SIZE
my_tfr                     Distroless   0495e5802299   9 minutes ago    799MB
my_tfr                     Alpine       ca2316e1de8f   17 minutes ago   802MB
my_tfr                     Terraform    aaa1f443c6c4   33 minutes ago   822MB

安装了 Terraformer 后,Terraform 基础增加了 712MB。此外,与其他基础相比,它大约大 20MB。这个结果是否有用取决于应用程序,但我希望它可以作为一个标准。

尝试使用创建的 Terraformer 图像

让我们使用创建的图像为 AWS 创建一个 tf 文件。

[ec2-user@ip-10-0-0-75 ~]$ docker run -v $HOME/tf-src:/root/generated/ my_tfr:Distroless terraformer import aws -r=ec2_instance,vpc
2022/08/13 04:45:13 aws importing default region
2022/08/13 04:45:13 aws importing... ec2_instance
2022/08/13 04:45:15 aws done importing ec2_instance
2022/08/13 04:45:15 aws importing... vpc
2022/08/13 04:45:15 aws done importing vpc
・・・

让我们看一下创建的文件。

[ec2-user@ip-10-0-0-75 ~]$ cd tf-src/aws/ec2_instance/
[ec2-user@ip-10-0-0-75 ec2_instance]$ ls
instance.tf  outputs.tf  provider.tf  terraform.tfstate
[ec2-user@ip-10-0-0-75 ec2_instance]$ view instance.tf
・・・
resource "aws_instance" "<instance名>" {
  ami                         = "ami-02892a4ea9bfa2192"
  associate_public_ip_address = "true"
  availability_zone           = "ap-northeast-1a"

  capacity_reservation_specification {
    capacity_reservation_preference = "open"
  }

  cpu_core_count       = "2"
  cpu_threads_per_core = "1"

  credit_specification {
    cpu_credits = "standard"
  }

  disable_api_stop        = "false"
  disable_api_termination = "false"
  ebs_optimized           = "false"

  enclave_options {
    enabled = "false"
  }

  get_password_data                    = "false"
  hibernation                          = "false"
  instance_initiated_shutdown_behavior = "stop"
  instance_type                        = "t2.medium"
  ipv6_address_count                   = "0"
  key_name                             = "..."

  maintenance_options {
    auto_recovery = "default"
  }

  metadata_options {
    http_endpoint               = "enabled"
    http_put_response_hop_limit = "1"
    http_tokens                 = "optional"
    instance_metadata_tags      = "disabled"
  }

  monitoring = "false"

  private_dns_name_options {
    enable_resource_name_dns_a_record    = "false"
    enable_resource_name_dns_aaaa_record = "false"
    hostname_type                        = "ip-name"
  }

  private_ip = "10.0.0.75"

  root_block_device {
    delete_on_termination = "true"
    encrypted             = "false"
    volume_size           = "20"
    volume_type           = "gp2"
  }

  source_dest_check = "true"
  subnet_id         = "subnet-00b0aafb0a5599895"

  tags = {
    Author = "..."
    Name   = "..."
  }

  tags_all = {
    Author = "..."
    Name   = "..."
  }

  tenancy                = "default"
  vpc_security_group_ids = ["sg-0b7a74b0cbb945d6c"]
}
・・・

有一组 EC2 设置。我认为可以根据这个文件克隆 EC2。
接下来我想尝试将它与 Kubernetes 一起使用,但没有成功。

[ec2-user@ip-10-0-0-75 ~]$ docker run -v $HOME/tf-src:/root/generated/ my_tfr:Distroless terraformer import kubernetes list
[ec2-user@ip-10-0-0-75 ~]$ docker run -v $HOME/tf-src:/root/generated/ my_tfr:Distroless terraformer import kubernetes -r deployment
2022/08/13 05:03:42 kubernetes importing... deployment
2022/08/13 05:03:42 kubernetes error importing deployment, err: kubernetes: deployment not supported resource
2022/08/13 05:03:42 kubernetes Connecting....

我检查了原因,但它可能是版本差异问题。每个工具的相应版本可以在以下页面中找到。

Terraformer (0.13) 支持的 Terraform 版本已经有将近两年的历史了。我发现很难匹配。您最好使用其他工具,例如:

综上所述

我觉得 Docker 的多阶段构建很容易,因为它不受镜像差异的影响。
我想如果我能利用这个工具的优点,而不是仅仅把迄今为止手动执行的东西放在一个 Dockerfile 中,我就能做以前做不到的事情。
我会继续学习。


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308623645.html

相关文章:

  • 2022-01-22
  • 2021-09-30
  • 2022-12-23
  • 2021-12-11
  • 2022-12-23
  • 2021-09-22
  • 2022-12-23
猜你喜欢
  • 2021-05-28
  • 2022-12-23
  • 2021-10-22
  • 2022-02-16
  • 2022-12-23
  • 2022-12-23
  • 2022-02-03
相关资源
相似解决方案