TL; DR
Два решения:
- Создание двух отдельных модулей с помощью Terraform
Используйте интерполяции и зависимость_ между кодом, который создает ваш кластер Kubernetes, и ресурсами kubernetes:
resource "kubernetes_service" "example" {
metadata {
name = "my-service"
}
depends_on = ["aws_vpc.kubernetes"]
}
resource "aws_vpc" "kubernetes" {
...
}
При уничтожении ресурсов
Вы столкнулись с проблемой жизненного цикла зависимости
PS: я не знаю код, который вы использовали для создания / подготовки вашего кластера Kubernetes, но я думаю, что это выглядит так
- Написать код для кластера Kubernetes (создает VPC)
- Применить
- Написать код для обеспечения Kubernetes (создайте Сервис, который создает ELB)
- Применить это
- Попробуйте все уничтожить => Ошибка
То, что происходит, заключается в том, что, создав службу LoadBalancer , Kubernetes предоставит ELB на AWS. Но Terraform этого не знает, и нет никакой связи между созданным ELB и любыми другими ресурсами, управляемыми Terraform.
Поэтому, когда terraform пытается уничтожить ресурсы в коде, он попытается уничтожить VPC. Но этого не может быть, потому что внутри этого VPC есть ELB, о котором терраформ не знает.
Первым делом нужно убедиться, что Terraform «депровизирует» кластер Kubernetes, а затем уничтожить сам кластер.
Два решения здесь:
Используйте разные модули, чтобы не было жизненного цикла зависимостей. Например, первый модуль может быть k8s-infra
, а другой - k8s-resources
. Первый управляет всем скелетом Кубернетеса и применяется первым / уничтожает последним. Второй управляет тем, что находится внутри кластера и применяется последним / первым уничтожается.
Используйте параметр depends_on
для явной записи жизненного цикла зависимости
При создании ресурсов
Вы также можете столкнуться с проблемой зависимости, когда terraform apply
не может создать ресурсы, даже если ничего еще не применено. Я приведу другой пример с postgres
- Написать код для создания сервера RDS PostgreSQL
- Примените его с помощью Terraform
- Введите код, в том же модуле , чтобы предоставить этот экземпляр RDS провайдеру postgres terraform
- Примените его с помощью Terraform
- Уничтожить все
- Попробуйте применить все => ОШИБКА
Путем небольшой отладки Terraform я узнал, что все провайдеры инициализируются с самого начала plan
/ apply
, поэтому, если один из них имеет недопустимую конфигурацию (неправильные ключи API / недостижимая конечная точка), Terraform завершится ошибкой.
Решением здесь является использование целевого параметра команды plan
/ apply
.
Terraform будет инициализировать только тех поставщиков, которые связаны с применяемыми ресурсами.
- Примените код RDS у провайдера AWS:
terraform apply -target=aws_db_instance
- Применить все
terraform apply
. Поскольку экземпляр RDS уже доступен, поставщик PostgreSQL также может инициировать себя