Cómo actualizar a Terraform 0.12

Para comenzar con Terraform, utilicé la versión 0.11 de Terraform. Como han señalado algunos lectores, esta versión carece de algunas funciones importantes, por lo que en este artículo explicaré cómo actualizar Terraform a la versión 0.12 con más funciones.
Es posible que se sorprenda al saber que muchas personas todavía usan Terraform 0.11, incluidas las grandes organizaciones y los usuarios obstinados a quienes les gusta quedarse con la tecnología comprobada. La conversión de Terraform 0.11 a 0.12 puede ser muy compleja. Si desea aprovechar las funciones más recientes pero cree que no está listo para actualizar, este artículo debería ayudarlo a facilitar la conversión.
En este artículo, usaré el código de mi artículo "Primeros pasos" y el tfenv herramienta, que le permite utilizar diferentes versiones de Terraform en la misma máquina. También asumo que está familiarizado con dos versiones de Terraform (la que está usando y la que está migrando) y cómo usar el terraform
mando en general.
Se requieren cambios de código para la versión 12
Algunas cosas funcionan en la versión 0.11 de Terraform que no funcionan en la versión 0.12. Aquí hay un ejemplo de código que usé en mi artículo anterior:
resource "kubernetes_namespace" "1-minikube-namespace" {
metadata {
name = "my-first-terraform-namespace"
}
}
Como señaló un lector, este bloque de código no funciona en la versión 0.12 debido a cambios en la forma en que funciona la última versión de Terraform. Este es un ejemplo simple y se vuelve más complicado. Estos son algunos ejemplos de cuántas cosas pueden necesitar cambiar en un entorno de producción.
El nuevo Terraform necesita una sintaxis y una estructura ligeramente diferentes. Para comenzar, agregue un vars.tf
Archivo:
variable "namespace" {
type = "string"
default = "helloworld"
}variable "cluster" {
type = "string"
default = "minikube"
}
Luego, intercambie partes del main.tf
archivo para incrustar el nuevo vars.tf
Archivo. El proveedor de Kubernetes ahora se ve así:
provider "kubernetes" {
config_context_cluster = "${var.cluster}"
}
Aquí está el recurso de espacio de nombres revisado:
resource "kubernetes_namespace" "1-minikube-namespace" {
metadata {
name = "${var.namespace}"
}
}
Finalmente, el proveedor de Helm modificado:
provider "helm" {
kubernetes {
config_context_cluster = "${var.cluster}"
}
}
¡Atención! Estos pequeños cambios serán importantes al cambiar de versión.
Distribuir antes de la conversión
Antes de continuar, configure tfenv para usar la versión correcta de Terraform:
[email protected]:~/terraform_doc$ tfenv list
0.12.29
0.11.15-oci
[email protected]:~/terraform_doc$ tfenv use 0.11.15-oci
Switching default version to v0.11.15-oci
Switching completed
[email protected]:~/terraform_doc$ terraform --version
Terraform v0.11.15-oci
+ provider.helm v1.2.2
+ provider.kubernetes v1.11.2Your version of Terraform is out of date! The latest version
is 0.xx.y. You can update by downloading from www.terraform.io/downloads.html
Si (como yo) ha realizado otro trabajo con Terraform después de usar el código en mi artículo anterior de Terraform, debe volver a implementar todo. Configure el clúster de Minikube para esta implementación de Terraform iniciando un nuevo clúster limpio:
$ minikube delete
? Deleting "minikube" in kvm2 ...
? Removed all traces of the "minikube" cluster.
[email protected]:~/terraform_doc$ minikube start
? minikube v1.14.0 on Ubuntu 18.04
Después de configurar el clúster, puede implementar el código de Terraform modificado. Comience con el init
mando:
$ terraform initInitializing provider plugins...
The following providers do not have any version constraints in configuration,
so the latest version was installed.To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.helm: version = "~> 1.2"
* provider.kubernetes: version = "~> 1.11"Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your Infraestructura. All Terraform commands
should now work. [...]
Entonces, ejecuta tu plan:
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
helm_release.local: Refreshing state... (ID: buildachart)
kubernetes_namespace.1-minikube-namespace: Refreshing state... (ID: my-first-terraform-namespace) [...]
Terraform will perform the following actions:
+ helm_release.local
id: <computed>
atomic: "false"
chart: "./buildachart"
cleanup_on_fail: "false"
create_namespace: "false"
dependency_update: "false"
disable_crd_hooks: "false"
disable_openapi_validation: "false"
[...]
+ kubernetes_namespace.1-minikube-namespace
id: <computed>
metadata.#: "1"
[...]
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
Por último, aplica el Terraform:
$ terraform apply --auto-approve
helm_release.local: Refreshing state... (ID: buildachart)
kubernetes_namespace.1-minikube-namespace: Refreshing state... (ID: my-first-terraform-namespace)
kubernetes_namespace.1-minikube-namespace: Creating...
metadata.#: "" => "1"
metadata.0.generation: "" => "<computed>"
[...]
helm_release.local: Creating...
atomic: "" => "false"
chart: "" => "./buildachart"
cleanup_on_fail: "" => "false"
create_namespace: "" => "false"
[...]
version: "" => "0.1.0"
wait: "" => "true"
kubernetes_namespace.1-minikube-namespace: Creation complete after 1s (ID: helloworld)
helm_release.local: Still creating... (10s elapsed)
helm_release.local: Creation complete after 13s (ID: buildachart)
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Ahora tiene una copia de seguridad local del estado de Terraform:
$ ls -lrtdrwxr-xr-x 6 jess jess 4096 May 16 14:15 buildachart
-rw-r--r-- 1 jess jess 363 Oct 24 13:06 main.tf
-rw-rw-r-- 1 jess jess 132 Oct 24 13:17 vars.tf
-rw-rw-r-- 1 jess jess 3897 Oct 24 13:20 terraform.tfstate.backup
-rw-rw-r-- 1 jess jess 3821 Oct 24 13:21 terraform.tfstate
Convertir de Terraform 0.11 a 0.12
Una vez que todo se haya implementado con Terraform 0.11, debe completar el proceso de conversión sin dañar lo que tiene en su nuevo clúster de producción. Primero, cambie su versión de Terraform a 0.12 usando tfenv:
$ tfenv list
0.12.29
* 0.11.15-oci (set by /home/jess/.tfenv/version)
[email protected]:~/terraform_doc$ tfenv use 0.12.29
Switching default version to v0.12.29
Switching completed
[email protected]:~/terraform_doc$ terraform --version
Terraform v0.12.29
+ provider.helm v1.2.2
+ provider.kubernetes v1.11.2
Ahora que está en Terraform 0.12, está listo para convertir. Afortunadamente, Terraform tiene un comando incorporado para esto, como se muestra en este fragmento de la lista de comandos de Terraform:
All other commands:
0.12upgrade Rewrites pre-0.12 module source code for v0.12
Prueba el upgrade
comando para ver lo que se reescribirá, luego ingrese yes
actualizar:
$ terraform 0.12upgradeThis command will rewrite the configuration files in the given directory so
that they use the new syntax features from Terraform v0.12, and will identify
any constructs that may need to be adjusted for correct operation with
Terraform v0.12.
[...]
Would you like to upgrade the module in the current directory?
Only 'yes' will be accepted to confirm.
Enter a value: yes-----------------------------------------------------------------------------
Upgrade complete!
The configuration files were upgraded successfully. Use your version control
system to review the proposed changes, make any necessary adjustments, and
then commit.
Parece que ha ido bien. Es posible que haya reescrito algunas cosas, pero eso no tendrá en cuenta todo lo que debe editarse con los archivos de Terraform. Sin embargo, hace un gran trabajo al tomar notas dentro de los archivos. Estos son los cambios realizados en el vars.tf
Archivo:
variable "namespace" {
type = string
default = "helloworld"
}variable "cluster" {
type = string
default = "minikube"
}
El type
modificado para eliminar las comillas alrededor de la palabra string
(el precio en los archivos de Terraform ha cambiado con el tiempo). Entonces, mira el main.tf
Archivo:
provider "kubernetes" {
config_context_cluster = var.cluster
}# TF-UPGRADE-TODO: In Terraform v0.11 and earlier, it was possible to begin a
# resource name with a number, but it is no longer possible in Terraform v0.12.
#
# Rename the resource and run `terraform state mv` to apply the rename in the
# state. Detailed information on the `state move` command can be found in the
# documentation online: https://www.terraform.io/docs/commands/state/mv.html
resource "kubernetes_namespace" "1-minikube-namespace" {
metadata {
name = var.namespace
}
}provider "helm" {
kubernetes {
config_context_cluster = var.cluster
}
}resource "helm_release" "local" {
name = "buildachart"
chart = "./buildachart"
}
Aquí también las comillas han cambiado y las variables ya no están encerradas. ${}
caracteres. La sección más grande es una gran nota TODO que el comando de conversión colocó en el código para mostrar lo que debe cambiar en el nombre del recurso para que sea aceptable en la versión 0.12. Aún mejor, explica cómo solucionar esto y el comando que necesita ejecutar. Los otros grandes cambios son los nuevos versions.tf
archivo y un nuevo archivo de copia de seguridad:
$ ls -lrt
drwxr-xr-x 6 jess jess 4096 May 16 14:15 buildachart
-rw-rw-r-- 1 jess jess 3897 Oct 24 13:20 terraform.tfstate.backup
-rw-r--r-- 1 jess jess 46 Oct 24 13:28 versions.tf
-rw-rw-r-- 1 jess jess 140 Oct 24 13:55 vars.tf
-rw-r--r-- 1 jess jess 369 Oct 24 13:56 main.tf
-rw-rw-r-- 1 jess jess 3821 Oct 24 13:56 terraform.tfstate.1603562212.backup
-rw-rw-r-- 1 jess jess 3827 Oct 24 13:56 terraform.tfstate
Para actualizar su clúster de producción, comience con un nombre diferente que sea más adecuado para esta versión:
resource "kubernetes_namespace" "upgrade-minikube-namespace" {
metadata {
name = var.namespace
}
}
Lijado de cantos ásperos
Después de ese cambio, debe ejecutar el terraform state mv
comando (como se indica en la gran nota TODO). Pero primero corre state list
para ver con qué estás trabajando:
$ terraform state list
helm_release.local
Kubernetes_namespace.1-minikube-namespace
El espacio de nombres todavía está establecido en el estado as 1-minikube-namespace
, y este es el estado al que debe mudarse. Esto se puede hacer asegurándose de tener los nombres de recursos nuevos y antiguos, luego ejecutando el archivo terraform state mv
mando. Pero primero, debe volver a 0.11, usando tfenv para realizar estos cambios, porque esto se implementó usando Terraform 0.11 y 0.12 no reconoce los números al comienzo del nombre del recurso (como dice TODO). Deberá revertir todos los cambios de código realizados desde la actualización de Terraform, excepto el cambio de nombre del activo:
principal.tf
provider "kubernetes" {
config_context_cluster = "${var.cluster}"
}resource "kubernetes_namespace" "upgrade-minikube-namespace" {
metadata {
name = "${var.namespace}"
}
}provider "helm" {
kubernetes {
config_context_cluster = "${var.cluster}"
}
}
resource "helm_release" "local" {
name = "buildachart"
chart = "./buildachart"
}
Vars.tf
variable "namespace" {
type = "string"
default = "helloworld"
}variable "cluster" {
type = "string"
default = "minikube"
}
Una vez que se reviertan los cambios, revierta tfenv a la versión 0.11 y ejecute el archivo state mv
mando:
$ tfenv use 0.11.15-oci
Switching default version to v0.11.15-oci
Switching completed
[email protected]:~/terraform_doc$ terraform state mv 'kubernetes_namespace.1-minikube-namespace' 'kubernetes_namespace.upgrade-minikube-namespace'
Moved kubernetes_namespace.1-minikube-namespace to kubernetes_namespace.upgrade-minikube-namespace
Pasos finales
Cuando termine, restablezca tfenv a la versión 0.12, luego elimine el suyo versions.tf
archivo para asegurarse de que la conversión se haya completado. Si no elimina este archivo, recibirá un mensaje de error:
$ terraform 0.12upgrade
Error: Module already upgraded
on versions.tf line 3, in terraform:
3: required_version = ">= 0.12"The module in directory . has a version constraint that suggests it has
already been upgraded for v0.12. If this is incorrect, either remove this
constraint or override this heuristic with the -force argument. Upgrading a
module that was already upgraded may change the meaning of that module.
Elimina el archivo y ejecuta el comando:
$ terraform 0.12upgradeThis command will rewrite the configuration files in the given directory so
that they use the new syntax features from Terraform v0.12, and will identify
any constructs that may need to be adjusted for correct operation with
Terraform v0.12. [...]Would you like to upgrade the module in the current directory?
Enter a value: yes-----------------------------------------------------------------------------
Upgrade complete!
Probar la conversión con otra distribución
Pruebe su nueva conversión volviendo a ejecutar la suya init
, plan
, Y apply
comandos (he omitido partes de la salida en estos fragmentos):
$ terraform initInitializing the backend...
Initializing provider plugins...
[...]
Terraform has been successfully initialized!$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state Almacenamiento.
helm_release.local: Refreshing state... [id=buildachart]
kubernetes_namespace.upgrade-minikube-namespace: Refreshing state... [id=helloworld]------------------------------------------------------------------------
No changes. Infraestructura is up-to-date
$ terraform apply
helm_release.local: Refreshing state... [id=buildachart]
kubernetes_namespace.upgrade-minikube-namespace: Refreshing state... [id=helloworld]
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Como muestra esto, una vez que todo estuvo preconfigurado y el estado se movió y se volvió a aplicar durante la conversión, no se realizaron otros cambios porque la infraestructura está en su lugar.
Pensamientos finales
Las actualizaciones de código y aplicaciones son difíciles de realizar, especialmente en un entorno de producción en vivo. Esto es muy cierto cuando se convierte de Terraform 0.11 a 0.12. Lo hice a gran escala e implicó una planificación extensa durante dos semanas.
Si planea hacer esto en su entorno de producción, asegúrese de:
- Comience eliminando cualquier recurso o formulario con números antepuestos.
- Mover el estado antes de actualizar.
- Mantenga sus archivos de Terraform actualizados en un repositorio bifurcado por seguridad.
Espero que este artículo te ayude a avanzar más rápido y más fácilmente que yo.
Artículos de interés