Прежде чем напрямую ответить на этот вопрос, я думаю, что вам поможет контекст:
За кулисами 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