Я пытаюсь создать образ докера, который содержит все необходимые плагины/поставщики, необходимые для нескольких исходных репозиториев, чтобы при запуске автоматизированного terraform validate
ему не приходилось загружать гигабайты избыточных данных.
Однако я понимаю, что это создает проблему обслуживания, поскольку кто-то может обновить версию плагина, и ее необходимо будет загрузить, поскольку образ докера не будет ее содержать.
Вопрос
Ниже приведены соответствующие файлы:
.terraformrc
plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
disable_checkpoint = true
provider_installation {
filesystem_mirror {
path = "$HOME/.terraform/providers"
}
direct {
}
}
tflint
(не относится к этому вопросу, но отображается в Dockerfile ниже)
plugin "aws" {
enabled = true
version = "0.21.1"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
plugin "azurerm" {
enabled = true
version = "0.20.0"
source = "github.com/terraform-linters/tflint-ruleset-azurerm"
}
Dockerfile
FROM ghcr.io/terraform-linters/tflint-bundle AS base
LABEL name=tflint
RUN adduser -h /home/jenkins -s /bin/sh -u 1000 -D jenkins
RUN apk fix && apk --no-cache --update add git terraform openssh
ADD .terraformrc /home/jenkins/.terraformrc
RUN mkdir -p /home/jenkins/.terraform.d/plugin-cache/registry.terraform.io
ADD .tflint.hcl /home/jenkins/.tflint.hcl
WORKDIR /home/jenkins
RUN tflint --init
FROM base AS build
ARG SSH_PRIVATE_KEY
RUN mkdir /root/.ssh && \
echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_ed25519 && \
chmod 400 /root/.ssh/id_ed25519 && \
touch /root/.ssh/known_hosts && \
ssh-keyscan mygitrepo >> /root/.ssh/known_hosts
RUN git clone git@mygitrepo:wrai/tools/g.git
RUN git clone git@mygitrepo:myproject/a.git && \
git clone git@mygitrepo:myproject/b.git && \
git clone git@mygitrepo:myproject/c.git && \
git clone git@mygitrepo:myproject/d.git && \
git clone git@mygitrepo:myproject/e.git && \
git clone git@mygitrepo:myproject/f.git
RUN ls -1d */ | xargs -I {} find {} -name '*.tf' | xargs -n 1 dirname | sort -u | \
xargs -I {} -n 1 -P 20 terraform -chdir = {} providers mirror /home/jenkins/.terraform.d
RUN chown -R jenkins:jenkins /home/jenkins
USER jenkins
FROM base AS a
COPY --from=build /home/jenkins/a/ /home/jenkins/a
RUN cd /home/jenkins/a && terraform init
FROM base AS b
COPY --from=build /home/jenkins/b/ /home/jenkins/b
RUN cd /home/jenkins/b && terraform init
FROM base AS c
COPY --from=build /home/jenkins/c/ /home/jenkins/c
RUN cd /home/jenkins/c && terraform init
FROM base AS azure_infrastructure
COPY --from=build /home/jenkins/d/ /home/jenkins/d
RUN cd /home/jenkins/d && terraform init
FROM base AS aws_infrastructure
COPY --from=build /home/jenkins/e/ /home/jenkins/e
RUN cd /home/jenkins/e && terraform init
Это проще всего сделать с помощью настройки каталога кеша плагинов в CLI. Это заменяет старое использование аргумента -plugin-dir=PATH
для команды init
. Вы также можете установить зеркало файловой системы в каждом terraform
блоке в конфигурации корневого модуля, но это будет обременительно для вашего варианта использования. В вашей ситуации вы уже настраиваете это в своем .terraformrc
, но filesystem_mirror
path
конфликтует с plugin_cache_dir
. Вы хотели бы разрешить этот конфликт или, возможно, полностью удалить зеркальный блок.
Поскольку этот параметр фиксируется в файле конфигурации CLI в Dockerfile
, он будет автоматически использоваться в будущих командах.
Это поведение команды init
по умолчанию, поэтому с вашей стороны не требуется никаких дополнительных действий.
Примечание:
Пользователь jenkins
обычно является /sbin/nologin
для оболочки и /var/lib/jenkins
для домашнего каталога. Если целью этого образа Docker является агент сборки Jenkins, возможно, вы захотите, чтобы пользовательская конфигурация jenkins
была больше согласована со стандартом.
TL;DR:
required_providers
terraform init
оттуда...
Я наткнулся на этот вопрос, когда пытался понять то же самое.
Сначала я попытался использовать подразумеваемое зеркало файловой системы, запустив terraform providers mirror /usr/local/share/terraform/plugins
в каталоге, содержащем только один файл terraform, содержащий блок required_providers
. Это работает нормально, пока вы используете только те версии провайдеров, которые вы зеркалировали.
Однако невозможно использовать версию провайдера, отличную от той, которую вы отразили, потому что:
Terraform просканирует все зеркальные каталоги файловой системы, чтобы увидеть, какие провайдеры там размещены, и автоматически исключит всех этих провайдеров из подразумеваемой прямой блокировки.
Я обнаружил, что лучше использовать каталог кеша плагинов. EDIT: вы можете предварительно загрузить плагины, установив TF_PLUGIN_CACHE_DIR в какой-либо каталог, а затем запустив terraform init
в каталоге, который только объявляет required_providers
.
Ранее переработанный материал ниже:
Оставалось только одно препятствие: terraform providers mirror
загружает провайдеров в упакованном макете:
Упакованный макет: HOSTNAME/NAMESPACE/TYPE/terraform-provider-TYPE_VERSION_TARGET.zip — это zip-файл дистрибутива, полученный из исходного реестра провайдера.
в то время как Terraform ожидает, что каталог кеша плагинов будет использовать распакованный макет:
Распакованный макет: HOSTNAME/NAMESPACE/TYPE/VERSION/TARGET — это каталог, содержащий результат распаковки zip-файла дистрибутива провайдера.
Итак, я преобразовал упакованный макет в распакованный с помощью find и parallel:
find path/to/plugin-dir -name index.json -exec rm {} +`
find path/to/plugin-dir -name '*.json' | parallel --will-cite 'mkdir -p {//}/{/.}/linux_amd64; unzip {//}/*.zip -d {//}/{/.}/linux_amd64; rm {}; rm {//}/*.zip'
Мне нравится ваш сверхинженерный подход :) Я действительно кое-чему научился
Спасибо за детали Дженкинса - у вас есть ссылка, которую я могу проверить, чтобы понять стандарт? Потому что, да, это для агента. Кэш плагинов — это правильный баланс между сложностью проектирования и уменьшенной избыточностью. Спасибо