Как импортировать ручные изменения в удаленное состояние Terraform

Я новичок в terraform - я создал удаленное tfstate в s3, и теперь в мою инфраструктуру AWS внесены некоторые ручные изменения. Мне нужно импортировать эти ручные изменения в tfstate.

Я использовал команду импорта для некоторых ресурсов, но для некоторых ресурсов, таких как политика IAM и т. Д., Такой команды импорта нет.

Также некоторые ресурсы, такие как БД, изменены с добавлением новых параметров, и мне также нужно их импортировать. Когда я пытаюсь импортировать эти изменения, он говорит:

Error importing: 1 error(s) occurred:

* Can't import aws_security_group.Q8SgProdAdminSshInt, would collide
  with an existing resource.

Please remove or rename this resource before continuing.

Любая помощь будет оценена по достоинству. Спасибо.


person Grin like a Cheshire cat    schedule 13.05.2017    source источник


Ответы (2)


Прежде чем напрямую ответить на этот вопрос, я думаю, что вам поможет контекст:

За кулисами Terraform поддерживает файл состояния, который содержит сопоставление ресурсов в вашей конфигурации с объектами в базовом API поставщика. Когда вы создаете новый объект с помощью Terraform, идентификатор созданного объекта автоматически сохраняется в состоянии, чтобы будущие команды могли найти указанный объект для операций чтения, обновления и удаления.

terraform import - это другой способ создания записи в файле состояния. Вместо того, чтобы создавать новый объект и записывать его идентификатор, пользователь предоставляет идентификатор в командной строке. Terraform читает объект с этим идентификатором и добавляет результат в файл состояния, после чего он становится неотличимым по состоянию от ресурса, который Terraform создал сам.

Итак, с учетом всего сказанного, давайте рассмотрим ваши вопросы один за другим.


Импорт ресурсов, которые не поддерживают terraform import

Поскольку для импорта каждого ресурса требуется небольшой объем кода проверки и выборки данных, в настоящее время не все ресурсы поддерживаются для импорта.

Учитывая то, что мы знаем о том, что terraform import делает из вышеизложенного, теоретически можно пропустить проверку Terraform предоставленного идентификатора и вместо этого вручную добавить ресурс в состояние. Это сложная операция, и ее следует выполнять осторожно, чтобы не повредить состояние.

Сначала извлеките состояние в локальный файл, который вы будете использовать для своей локальной работы:

terraform state pull >manual-import.tfstate

В результате будет создан файл manual-import.tfstate, который можно будет открыть в текстовом редакторе. Он использует синтаксис JSON, поэтому, хотя его внутренняя структура не задокументирована как стабильный формат, мы можем тщательно редактировать его, пока мы остаемся совместимыми с ожидаемой структурой.

Проще всего найти существующий ресурс в том же модуле, в котором вы хотите его импортировать, дублировать и редактировать. Предположим, у нас есть такой объект resources:

"resources": {
    "null_resource.foo": {
        "type": "null_resource",
        "depends_on": [],
        "primary": {
            "id": "5897853859325638329",
            "attributes": {
                "id": "5897853859325638329"
            },
            "meta": {},
            "tainted": false
        },
        "deposed": [],
        "provider": ""
    }
},

Каждый атрибут в этом объекте resources соответствует ресурсу в вашей конфигурации. Имя атрибута - это тип и имя ресурса. В этом случае тип ресурса - null_resource, а имя атрибута - foo. В вашем случае вы можете увидеть здесь что-то вроде aws_instance.server.

Атрибуты id для многих ресурсов (но не для всех!) - это главное, что необходимо заполнить. Таким образом, мы можем продублировать эту структуру для гипотетической политики IAM:

"resources": {
    "null_resource.foo": {
        "type": "null_resource",
        "depends_on": [],
        "primary": {
            "id": "5897853859325638329",
            "attributes": {
                "id": "5897853859325638329"
            },
            "meta": {},
            "tainted": false
        },
        "deposed": [],
        "provider": ""
    },
    "aws_iam_policy.example": {
        "type": "aws_iam_policy",
        "depends_on": [],
        "primary": {
            "id": "?????",
            "attributes": {
                "id": "?????"
            },
            "meta": {},
            "tainted": false
        },
        "deposed": [],
        "provider": ""
    }
},

На этом этапе задача состоит в том, чтобы выяснить, какой идентификатор требуется для этого ресурса. Единственный надежный способ узнать об этом - прочтите код, который говорит мне, что этот ресурс ожидает, что идентификатор будет полным ARN политики.

Обладая этими знаниями, мы заменяем две последовательности ????? в приведенном выше примере на ARN политики, которую мы хотим импортировать.

После внесения изменений в состояние вручную необходимо обновить номер serial на верхнем уровне файла. Terraform ожидает, что любое новое изменение будет иметь более высокий серийный номер, поэтому мы можем увеличить этот номер.

После завершения обновлений мы должны загрузить обновленный файл состояния обратно в Terraform:

terraform state push manual-import.tfstate

Наконец, мы можем попросить Terraform обновить состояние, чтобы убедиться, что оно работает:

terraform refresh

Опять же, это довольно рискованный процесс, поскольку файл состояния - это запись Terraform о его отношениях с базовой системой, и его может быть трудно восстановить, если содержимое этого файла потеряно. Часто проще просто заменить ресурс, чем прилагать все усилия, если только он уже не играет критически важную роль в вашей инфраструктуре и нет доступной стратегии постепенной миграции.

Импорты сталкиваются с существующими ресурсами

Сообщение об ошибке, указанное в вашем вопросе, говорит о конфликте импорта с существующим ресурсом:

Error importing: 1 error(s) occurred:

* Can't import aws_security_group.Q8SgProdAdminSshInt, would collide with an existing resource.

Please remove or rename this resource before continuing.

Смысл этого сообщения в том, что когда Terraform попытался записать новый ресурс в файл состояния, он обнаружил, что запись ресурса уже присутствует для имени aws_security_group.Q8SgProdAdminSshInt. Это говорит о том, что либо она уже импортирована, либо новая группа безопасности уже создана самим Terraform.

Вы можете проверить атрибуты существующего ресурса в состоянии:

terraform state show aws_security_group.Q8SgProdAdminSshInt

Сравните полученные данные с группой безопасности, которую вы пытались импортировать. Если идентификаторы совпадают, то делать нечего, поскольку ресурс уже импортирован.

Если идентификаторы не совпадают, вам нужно выяснить, какой из двух объектов вы хотите сохранить. Если вы хотите сохранить тот, который уже есть в Terraform, вы можете вручную удалить тот, который вы пытались импортировать.

Если вы хотите сохранить тот, который вы пытались импортировать, вы можете удалить ненужный из состояния Terraform, чтобы освободить место для успешного импорта:

terraform state rm aws_security_group.Q8SgProdAdminSshInt

Обратите внимание, что это просто заставляет Terraform «забыть» ресурс; он по-прежнему будет существовать в EC2, и его нужно будет удалить вручную через консоль, инструменты командной строки или API. Обязательно запишите его id перед удалением, чтобы убедиться, что вы можете найти его и очистить.

person Martin Atkins    schedule 15.05.2017
comment
Одно примечание к этому заключается в том, что по какой-то причине версия terraform для Windows помещает некоторый непечатаемый символ ascii в извлечение файла состояния, поэтому мне пришлось переместить всю свою терраформу в окно linux и внести там изменения. - person Aaron; 02.07.2018

Для ресурсов вы должны использовать функцию импорта или вручную добавить состояние терраформирования, например, блок ..

или если есть какие-либо изменения в конфигурации, такие как вы упомянули конфигурации дБ .. если ресурс дБ управляется удаленным состоянием terraform .. terraform refresh поможет вам ..

person Shubham Bansal    schedule 13.05.2017
comment
Мне удалось внести изменения в базу данных. Вы знаете, как я могу импортировать aws_vpc_dhcp_options_association? Не могли бы вы объяснить состояние терраформирования, такое как блок, как это можно сделать? - person Grin like a Cheshire cat; 13.05.2017
comment
Также обновление terraform будет соответствовать моему удаленному состоянию, хотя мое удаленное состояние не обновляется только с внесенными вручную изменениями. - person Grin like a Cheshire cat; 13.05.2017
comment
Terraform ведет себя по-разному в разных случаях ... если вы хотите, чтобы конкретная опция dhcp установила обходной путь ... стоит обновить удаленное состояние vpc ... он пометит текущую опцию dhcp как установленную по умолчанию .. - person Shubham Bansal; 13.05.2017