Terraform παγίδες

Terraform παγίδες
Ας επισημάνουμε μερικές παγίδες, συμπεριλαμβανομένων εκείνων που σχετίζονται με τους βρόχους, τις δηλώσεις if και τις τεχνικές ανάπτυξης, καθώς και γενικότερα ζητήματα που επηρεάζουν το Terraform γενικά:

  • οι παράμετροι count και for_each έχουν περιορισμούς.
  • περιορισμός μηδενικών εγκαταστάσεων διακοπής λειτουργίας·
  • Ακόμα και ένα καλό σχέδιο μπορεί να αποτύχει.
  • Η ανακατασκευή μπορεί να έχει τις παγίδες της.
  • η αναβαλλόμενη συνοχή είναι συνεπής... με την αναβολή.

Οι παράμετροι count και for_each έχουν περιορισμούς

Τα παραδείγματα σε αυτό το κεφάλαιο χρησιμοποιούν εκτενώς την παράμετρο count και την έκφραση for_each σε βρόχους και λογική υπό όρους. Έχουν καλή απόδοση, αλλά έχουν δύο σημαντικούς περιορισμούς που πρέπει να γνωρίζετε.

  • Το Count και το for_each δεν μπορούν να αναφέρουν καμία μεταβλητή εξόδου πόρων.
  • Το count και το for_each δεν μπορούν να χρησιμοποιηθούν στη διαμόρφωση της μονάδας.

Το count και το for_each δεν μπορούν να αναφέρουν καμία μεταβλητή εξόδου πόρων

Φανταστείτε ότι πρέπει να αναπτύξετε πολλούς διακομιστές EC2 και για κάποιο λόγο δεν θέλετε να χρησιμοποιήσετε το ASG. Ο κωδικός σας θα μπορούσε να είναι έτσι:

resource "aws_instance" "example_1" {
   count             = 3
   ami                = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

Ας τα δούμε ένα προς ένα.

Δεδομένου ότι η παράμετρος count έχει οριστεί σε μια στατική τιμή, αυτός ο κώδικας θα λειτουργεί χωρίς προβλήματα: όταν εκτελείτε την εντολή εφαρμογής, θα δημιουργήσει τρεις διακομιστές EC2. Τι θα γινόταν όμως αν θέλετε να αναπτύξετε έναν διακομιστή σε κάθε Ζώνη Διαθεσιμότητας (AZ) στην τρέχουσα περιοχή σας AWS; Μπορείτε να βάλετε τον κώδικά σας να φορτώσει μια λίστα ζωνών από την πηγή δεδομένων aws_availability_zones και, στη συνέχεια, να πραγματοποιήσετε βρόχο μέσα από κάθε μία και να δημιουργήσετε έναν διακομιστή EC2 σε αυτόν χρησιμοποιώντας την παράμετρο count και την πρόσβαση σε ευρετήριο πίνακα:

resource "aws_instance" "example_2" {
   count                   = length(data.aws_availability_zones.all.names)
   availability_zone   = data.aws_availability_zones.all.names[count.index]
   ami                     = "ami-0c55b159cbfafe1f0"
   instance_type       = "t2.micro"
}

data "aws_availability_zones" "all" {}

Αυτός ο κωδικός θα λειτουργεί επίσης καλά, καθώς η παράμετρος count μπορεί να παραπέμπει σε πηγές δεδομένων χωρίς προβλήματα. Τι συμβαίνει όμως εάν ο αριθμός των διακομιστών που πρέπει να δημιουργήσετε εξαρτάται από την έξοδο κάποιου πόρου; Για να αποδειχθεί αυτό, ο ευκολότερος τρόπος είναι να χρησιμοποιήσετε τον πόρο random_integer, ο οποίος, όπως υποδηλώνει το όνομα, επιστρέφει έναν τυχαίο ακέραιο:

resource "random_integer" "num_instances" {
  min = 1
  max = 3
}

Αυτός ο κώδικας δημιουργεί έναν τυχαίο αριθμό μεταξύ 1 και 3. Ας δούμε τι θα συμβεί αν προσπαθήσουμε να χρησιμοποιήσουμε την έξοδο αυτού του πόρου στην παράμετρο count του πόρου aws_instance:

resource "aws_instance" "example_3" {
   count             = random_integer.num_instances.result
   ami                = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

Εάν εκτελέσετε σχέδιο terraform σε αυτόν τον κώδικα, θα λάβετε το ακόλουθο σφάλμα:

Error: Invalid count argument

   on main.tf line 30, in resource "aws_instance" "example_3":
   30: count = random_integer.num_instances.result

The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.

Το Terraform απαιτεί να υπολογίζονται τα count και for_each κατά τη φάση σχεδιασμού, πριν δημιουργηθούν ή τροποποιηθούν οποιοιδήποτε πόροι. Αυτό σημαίνει ότι το count και το for_each μπορούν να αναφέρονται σε κυριολεκτικά, μεταβλητές, πηγές δεδομένων, ακόμη και λίστες πόρων (εφόσον το μήκος τους μπορεί να προσδιοριστεί κατά τον χρόνο προγραμματισμού), αλλά όχι σε υπολογισμένες μεταβλητές εξόδου πόρων.

Το count και το for_each δεν μπορούν να χρησιμοποιηθούν στη διαμόρφωση της μονάδας

Κάποια μέρα μπορεί να μπείτε στον πειρασμό να προσθέσετε μια παράμετρο μέτρησης στη διαμόρφωση της μονάδας σας:

module "count_example" {
     source = "../../../../modules/services/webserver-cluster"

     count = 3

     cluster_name = "terraform-up-and-running-example"
     server_port = 8080
     instance_type = "t2.micro"
}

Αυτός ο κώδικας επιχειρεί να χρησιμοποιήσει την καταμέτρηση μέσα σε μια λειτουργική μονάδα για να δημιουργήσει τρία αντίγραφα του πόρου του συμπλέγματος διακομιστή ιστού. Εναλλακτικά, μπορεί να θέλετε να κάνετε τη σύνδεση μιας λειτουργικής μονάδας προαιρετική βάσει κάποιας συνθήκης Boolean ορίζοντας την παράμετρο μέτρησής της σε 0. Αυτό μπορεί να μοιάζει με λογικό κώδικα, αλλά θα λάβετε αυτό το σφάλμα κατά την εκτέλεση του σχεδίου terraform:

Error: Reserved argument name in module block

   on main.tf line 13, in module "count_example":
   13: count = 3

The name "count" is reserved for use in a future version of Terraform.

Δυστυχώς, από το Terraform 0.12.6, η χρήση count ή for_each σε έναν πόρο λειτουργικής μονάδας δεν υποστηρίζεται. Σύμφωνα με τις σημειώσεις έκδοσης Terraform 0.12 (http://bit.ly/3257bv4), η HashiCorp σχεδιάζει να προσθέσει αυτήν τη δυνατότητα στο μέλλον, επομένως, ανάλογα με το πότε θα διαβάσετε αυτό το βιβλίο, μπορεί να είναι ήδη διαθέσιμο. Για να μάθετε σίγουρα, διαβάστε το αρχείο αλλαγής Terraform εδώ.

Περιορισμοί μηδενικών αναπτύξεων χρόνου διακοπής λειτουργίας

Η χρήση του μπλοκ create_before_destroy σε συνδυασμό με το ASG είναι μια εξαιρετική λύση για τη δημιουργία αναπτύξεων μηδενικού χρόνου διακοπής λειτουργίας, εκτός από μία προειδοποίηση: οι κανόνες αυτόματης κλιμάκωσης δεν υποστηρίζονται. Ή για να είμαστε πιο ακριβείς, αυτό επαναφέρει το μέγεθος ASG στο ελάχιστο μέγεθος σε κάθε ανάπτυξη, κάτι που θα μπορούσε να είναι πρόβλημα εάν χρησιμοποιούσατε κανόνες αυτόματης κλιμάκωσης για να αυξήσετε τον αριθμό των διακομιστών που εκτελούνται.

Για παράδειγμα, η λειτουργική μονάδα webserver-cluster περιέχει ένα ζεύγος πόρων aws_autoscaling_schedule, που στις 9 π.μ. αυξάνει τον αριθμό των διακομιστών στο σύμπλεγμα από δύο σε δέκα. Εάν αναπτύξετε, για παράδειγμα, στις 11 π.μ., το νέο ASG θα εκκινήσει με δύο μόνο διακομιστές αντί για δέκα και θα παραμείνει έτσι μέχρι τις 9 π.μ. της επόμενης ημέρας.

Αυτός ο περιορισμός μπορεί να παρακαμφθεί με διάφορους τρόπους.

  • Αλλάξτε την παράμετρο επανάληψης στο aws_autoscaling_schedule από 0 9 * * * ("τρέξτε στις 9 π.μ.") σε κάτι σαν 0-59 9-17 * * * ("τρέξτε κάθε λεπτό από τις 9 π.μ. έως τις 5 μ.μ."). Εάν το ASG έχει ήδη δέκα διακομιστές, η εκτέλεση αυτού του κανόνα αυτόματης κλιμάκωσης δεν θα αλλάξει τίποτα, αυτό που θέλουμε. Αλλά εάν το ASG έχει μόλις πρόσφατα αναπτυχθεί, αυτός ο κανόνας θα εξασφαλίσει ότι σε ένα λεπτό το πολύ ο αριθμός των διακομιστών του θα φτάσει τους δέκα. Αυτή δεν είναι μια εντελώς κομψή προσέγγιση και τα μεγάλα άλματα από δέκα σε δύο διακομιστές και πίσω μπορούν επίσης να προκαλέσουν προβλήματα στους χρήστες.
  • Δημιουργήστε ένα προσαρμοσμένο σενάριο που χρησιμοποιεί το API AWS για να προσδιορίσει τον αριθμό των ενεργών διακομιστών στο ASG, καλέστε το χρησιμοποιώντας μια εξωτερική πηγή δεδομένων (δείτε "Εξωτερική πηγή δεδομένων" στη σελίδα 249) και ορίστε την παράμετρο επιθυμητής_χωρητικότητας του ASG στην τιμή που επιστρέφεται από το σενάριο. Με αυτόν τον τρόπο, κάθε νέο στιγμιότυπο ASG θα λειτουργεί πάντα με την ίδια χωρητικότητα με τον υπάρχοντα κώδικα Terraform και καθιστά πιο δύσκολη τη διατήρησή του.

Φυσικά, η Terraform θα είχε ιδανικά ενσωματωμένη υποστήριξη για αναπτύξεις μηδενικού χρόνου διακοπής λειτουργίας, αλλά από τον Μάιο του 2019, η ομάδα της HashiCorp δεν είχε σχέδια να προσθέσει αυτήν τη λειτουργία (λεπτομέρειες - εδώ).

Το σωστό σχέδιο μπορεί να εφαρμοστεί ανεπιτυχώς

Μερικές φορές η εντολή σχεδίου παράγει ένα απόλυτα σωστό σχέδιο ανάπτυξης, αλλά η εντολή εφαρμογής επιστρέφει ένα σφάλμα. Δοκιμάστε, για παράδειγμα, να προσθέσετε τον πόρο aws_iam_user με το ίδιο όνομα που χρησιμοποιήσατε για τον χρήστη IAM που δημιουργήσατε νωρίτερα στο Κεφάλαιο 2:

resource "aws_iam_user" "existing_user" {
   # Подставьте сюда имя уже существующего пользователя IAM,
   # чтобы попрактиковаться в использовании команды terraform import
   name = "yevgeniy.brikman"
}

Τώρα, εάν εκτελέσετε την εντολή σχεδίου, το Terraform θα παράγει ένα φαινομενικά λογικό σχέδιο ανάπτυξης:

Terraform will perform the following actions:

   # aws_iam_user.existing_user will be created
   + resource "aws_iam_user" "existing_user" {
         + arn                  = (known after apply)
         + force_destroy   = false
         + id                    = (known after apply)
         + name               = "yevgeniy.brikman"
         + path                 = "/"
         + unique_id         = (known after apply)
      }

Plan: 1 to add, 0 to change, 0 to destroy.

Εάν εκτελέσετε την εντολή εφαρμογής θα λάβετε το ακόλουθο σφάλμα:

Error: Error creating IAM User yevgeniy.brikman: EntityAlreadyExists:
User with name yevgeniy.brikman already exists.

   on main.tf line 10, in resource "aws_iam_user" "existing_user":
   10: resource "aws_iam_user" "existing_user" {

Το πρόβλημα, φυσικά, είναι ότι υπάρχει ήδη ένας χρήστης IAM με αυτό το όνομα. Και αυτό μπορεί να συμβεί όχι μόνο σε χρήστες IAM, αλλά σε σχεδόν οποιονδήποτε πόρο. Είναι πιθανό κάποιος να δημιούργησε αυτόν τον πόρο με μη αυτόματο τρόπο ή χρησιμοποιώντας τη γραμμή εντολών, αλλά σε κάθε περίπτωση, η αντιστοίχιση αναγνωριστικών οδηγεί σε διενέξεις. Υπάρχουν πολλές παραλλαγές αυτού του σφάλματος που συχνά αιφνιδιάζουν τους νεοφερμένους στο Terraform.

Το βασικό σημείο είναι ότι η εντολή terraform plan λαμβάνει υπόψη μόνο εκείνους τους πόρους που καθορίζονται στο αρχείο κατάστασης Terraform. Εάν οι πόροι δημιουργηθούν με κάποιον άλλο τρόπο (για παράδειγμα, με μη αυτόματο τρόπο κάνοντας κλικ στην κονσόλα AWS), δεν θα καταλήξουν στο αρχείο κατάστασης και επομένως η Terraform δεν θα τους λάβει υπόψη κατά την εκτέλεση της εντολής σχεδίου. Ως αποτέλεσμα, ένα σχέδιο που φαίνεται σωστό με την πρώτη ματιά θα αποδειχθεί ανεπιτυχές.

Υπάρχουν δύο διδάγματα που πρέπει να αντληθούν από αυτό.

  • Εάν έχετε ήδη ξεκινήσει να εργάζεστε με την Terraform, μην χρησιμοποιήσετε τίποτα άλλο. Εάν η διαχείριση μέρους της υποδομής σας γίνεται με χρήση Terraform, δεν μπορείτε πλέον να την τροποποιήσετε με μη αυτόματο τρόπο. Διαφορετικά, όχι μόνο κινδυνεύετε με περίεργα σφάλματα Terraform, αλλά αναιρείτε επίσης πολλά από τα οφέλη του IaC, καθώς ο κώδικας δεν θα είναι πλέον ακριβής αναπαράσταση της υποδομής σας.
  • Εάν έχετε ήδη κάποια υποδομή, χρησιμοποιήστε την εντολή εισαγωγής. Εάν αρχίζετε να χρησιμοποιείτε το Terraform με υπάρχουσα υποδομή, μπορείτε να το προσθέσετε στο αρχείο κατάστασης χρησιμοποιώντας την εντολή εισαγωγής terraform. Με αυτόν τον τρόπο η Terraform θα γνωρίζει ποια υποδομή πρέπει να διαχειριστεί. Η εντολή εισαγωγής παίρνει δύο ορίσματα. Το πρώτο είναι η διεύθυνση του πόρου στα αρχεία διαμόρφωσής σας. Η σύνταξη εδώ είναι η ίδια όπως για τους συνδέσμους πόρων: _. (όπως aws_iam_user.existing_user). Το δεύτερο όρισμα είναι το αναγνωριστικό του πόρου που θα εισαχθεί. Ας υποθέσουμε ότι το αναγνωριστικό πόρου aws_iam_user είναι το όνομα χρήστη (για παράδειγμα, yevgeniy.brikman) και το αναγνωριστικό πόρου aws_instance είναι το αναγνωριστικό διακομιστή EC2 (όπως i-190e22e5). Ο τρόπος εισαγωγής ενός πόρου συνήθως υποδεικνύεται στην τεκμηρίωση στο κάτω μέρος της σελίδας του.

    Παρακάτω είναι μια εντολή εισαγωγής που συγχρονίζει τον πόρο aws_iam_user που προσθέσατε στη διαμόρφωση Terraform μαζί με τον χρήστη IAM στο Κεφάλαιο 2 (αντικαθιστώντας το όνομά σας με yevgeniy.brikman, φυσικά):

    $ terraform import aws_iam_user.existing_user yevgeniy.brikman

    Η Terraform θα καλέσει το API AWS για να βρει τον χρήστη IAM και να δημιουργήσει μια συσχέτιση αρχείου κατάστασης μεταξύ αυτού και του πόρου aws_iam_user.existing_user στη διαμόρφωση Terraform. Από εδώ και στο εξής, όταν εκτελείτε την εντολή plan, το Terraform θα γνωρίζει ότι ο χρήστης IAM υπάρχει ήδη και δεν θα προσπαθήσει να τον δημιουργήσει ξανά.

    Αξίζει να σημειωθεί ότι εάν διαθέτετε ήδη πολλούς πόρους που θέλετε να εισαγάγετε στο Terraform, η μη αυτόματη εγγραφή του κώδικα και η εισαγωγή του καθενός τη φορά μπορεί να είναι μια ταλαιπωρία. Αξίζει λοιπόν να αναζητήσετε ένα εργαλείο όπως το Terraforming (http://terraforming.dtan4.net/), το οποίο μπορεί να εισάγει αυτόματα κώδικα και κατάσταση από τον λογαριασμό σας AWS.

    Το Refactoring μπορεί να έχει τις παγίδες του

    Αναπαράσταση είναι μια κοινή πρακτική στον προγραμματισμό όπου αλλάζετε την εσωτερική δομή του κώδικα ενώ αφήνετε αμετάβλητη την εξωτερική συμπεριφορά. Αυτό γίνεται για να γίνει ο κώδικας σαφέστερος, καθαρότερος και ευκολότερος στη συντήρηση. Το Refactoring είναι μια απαραίτητη τεχνική που πρέπει να χρησιμοποιείται τακτικά. Αλλά όταν πρόκειται για το Terraform ή οποιοδήποτε άλλο εργαλείο IaC, πρέπει να είστε εξαιρετικά προσεκτικοί σχετικά με το τι εννοείτε με τον όρο «εξωτερική συμπεριφορά» ενός κομματιού κώδικα, διαφορετικά θα προκύψουν απροσδόκητα προβλήματα.

    Για παράδειγμα, ένας κοινός τύπος αναδιαμόρφωσης είναι η αντικατάσταση των ονομάτων μεταβλητών ή συναρτήσεων με πιο κατανοητά. Πολλά IDE έχουν ενσωματωμένη υποστήριξη για ανακατασκευή και μπορούν να μετονομάσουν αυτόματα μεταβλητές και συναρτήσεις σε όλο το έργο. Στις γλώσσες προγραμματισμού γενικής χρήσης, αυτή είναι μια ασήμαντη διαδικασία που μπορεί να μην σκεφτείτε, αλλά στο Terraform πρέπει να είστε εξαιρετικά προσεκτικοί με αυτό, διαφορετικά μπορεί να αντιμετωπίσετε διακοπές λειτουργίας.

    Για παράδειγμα, η λειτουργική μονάδα webserver-cluster έχει μια μεταβλητή εισόδου cluster_name:

    variable "cluster_name" {
       description = "The name to use for all the cluster resources"
       type          = string
    }

    Φανταστείτε ότι ξεκινήσατε να χρησιμοποιείτε αυτήν την ενότητα για να αναπτύξετε μια microservice που ονομάζεται foo. Αργότερα, θέλετε να μετονομάσετε την υπηρεσία σας σε μπαρ. Αυτή η αλλαγή μπορεί να φαίνεται ασήμαντη, αλλά στην πραγματικότητα μπορεί να προκαλέσει διακοπές στην υπηρεσία.

    Το γεγονός είναι ότι η λειτουργική μονάδα webserver-cluster χρησιμοποιεί τη μεταβλητή cluster_name σε έναν αριθμό πόρων, συμπεριλαμβανομένης της παραμέτρου ονόματος δύο ομάδων ασφαλείας και του ALB:

    resource "aws_lb" "example" {
       name                    = var.cluster_name
       load_balancer_type = "application"
       subnets = data.aws_subnet_ids.default.ids
       security_groups      = [aws_security_group.alb.id]
    }

    Εάν αλλάξετε την παράμετρο ονόματος σε έναν πόρο, το Terraform θα διαγράψει την παλιά έκδοση αυτού του πόρου και θα δημιουργήσει μια νέα στη θέση του. Αλλά εάν αυτός ο πόρος είναι ALB, μεταξύ της διαγραφής του και της λήψης μιας νέας έκδοσης, δεν θα έχετε έναν μηχανισμό για να ανακατευθύνετε την κυκλοφορία στον διακομιστή ιστού σας. Ομοίως, εάν διαγραφεί μια ομάδα ασφαλείας, οι διακομιστές σας θα αρχίσουν να απορρίπτουν οποιαδήποτε κίνηση δικτύου μέχρι να δημιουργηθεί μια νέα ομάδα.

    Ένας άλλος τύπος ανακατασκευής που μπορεί να σας ενδιαφέρει είναι η αλλαγή του Terraform ID. Ας πάρουμε τον πόρο aws_security_group στη λειτουργική μονάδα webserver-cluster ως παράδειγμα:

    resource "aws_security_group" "instance" {
      # (...)
    }

    Το αναγνωριστικό αυτού του πόρου ονομάζεται παράδειγμα. Φανταστείτε ότι κατά την ανακατασκευή αποφασίσατε να το αλλάξετε σε ένα πιο κατανοητό (κατά τη γνώμη σας) όνομα cluster_instance:

    resource "aws_security_group" "cluster_instance" {
       # (...)
    }

    Τι θα γίνει τελικά; Αυτό είναι σωστό: μια αναστάτωση.

    Η Terraform συσχετίζει κάθε αναγνωριστικό πόρου με το αναγνωριστικό παρόχου cloud. Για παράδειγμα, το iam_user συσχετίζεται με το αναγνωριστικό χρήστη AWS IAM και το aws_instance σχετίζεται με το αναγνωριστικό διακομιστή AWS EC2. Εάν αλλάξετε το αναγνωριστικό πόρου (π. Εάν εφαρμόσετε αυτές τις αλλαγές, το Terraform θα διαγράψει την παλιά ομάδα ασφαλείας και θα δημιουργήσει μια νέα, ενώ οι διακομιστές σας θα αρχίσουν να απορρίπτουν οποιαδήποτε κίνηση δικτύου.

    Εδώ είναι τέσσερα βασικά μαθήματα που πρέπει να αφαιρέσετε από αυτή τη συζήτηση.

    • Να χρησιμοποιείτε πάντα την εντολή σχεδίου. Μπορεί να αποκαλύψει όλα αυτά τα εμπόδια. Ελέγξτε προσεκτικά τα αποτελέσματά του και δώστε προσοχή σε περιπτώσεις όπου η Terraform σχεδιάζει να διαγράψει πόρους που πιθανότατα δεν θα πρέπει να διαγραφούν.
    • Δημιουργήστε πριν διαγράψετε. Εάν θέλετε να αντικαταστήσετε έναν πόρο, σκεφτείτε προσεκτικά εάν πρέπει να δημιουργήσετε έναν αντικαταστάτη πριν διαγράψετε το πρωτότυπο. Εάν η απάντηση είναι ναι, το create_before_destroy μπορεί να βοηθήσει. Το ίδιο αποτέλεσμα μπορεί να επιτευχθεί με μη αυτόματο τρόπο εκτελώντας δύο βήματα: πρώτα προσθέστε έναν νέο πόρο στη διαμόρφωση και εκτελέστε την εντολή εφαρμογής και, στη συνέχεια, αφαιρέστε τον παλιό πόρο από τη διαμόρφωση και χρησιμοποιήστε ξανά την εντολή εφαρμογής.
    • Η αλλαγή των αναγνωριστικών απαιτεί αλλαγή κατάστασης. Εάν θέλετε να αλλάξετε το αναγνωριστικό που σχετίζεται με έναν πόρο (για παράδειγμα, μετονομάστε το aws_security_group από παράδειγμα σε cluster_instance) χωρίς να διαγράψετε τον πόρο και να δημιουργήσετε μια νέα έκδοσή του, πρέπει να ενημερώσετε το αρχείο κατάστασης Terraform ανάλογα. Ποτέ μην το κάνετε αυτό με μη αυτόματο τρόπο - χρησιμοποιήστε την εντολή terraform state. Όταν μετονομάζετε αναγνωριστικά, θα πρέπει να εκτελέσετε την εντολή terraform state mv, η οποία έχει την ακόλουθη σύνταξη:
      terraform state mv <ORIGINAL_REFERENCE> <NEW_REFERENCE>

      Το ORIGINAL_REFERENCE είναι μια έκφραση που αναφέρεται στον πόρο στην τρέχουσα μορφή του και το NEW_REFERENCE είναι το σημείο όπου θέλετε να τον μετακινήσετε. Για παράδειγμα, όταν μετονομάζετε την ομάδα aws_security_group από παράδειγμα σε cluster_instance, πρέπει να εκτελέσετε την ακόλουθη εντολή:

      $ terraform state mv 
         aws_security_group.instance 
         aws_security_group.cluster_instance

      Αυτό λέει στο Terraform ότι η κατάσταση που είχε συσχετιστεί προηγουμένως με το aws_security_group.instance θα πρέπει τώρα να συσχετιστεί με το aws_security_group.cluster_instance. Εάν μετά τη μετονομασία και την εκτέλεση αυτής της εντολής το terraform plan δεν εμφανίσει αλλαγές, τότε τα κάνατε όλα σωστά.

    • Ορισμένες ρυθμίσεις δεν μπορούν να αλλάξουν. Οι παράμετροι πολλών πόρων είναι αμετάβλητες. Εάν προσπαθήσετε να τους αλλάξετε, το Terraform θα διαγράψει τον παλιό πόρο και θα δημιουργήσει έναν νέο στη θέση του. Κάθε σελίδα πόρου συνήθως υποδεικνύει τι συμβαίνει όταν αλλάζετε μια συγκεκριμένη ρύθμιση, επομένως φροντίστε να ελέγξετε την τεκμηρίωση. Χρησιμοποιείτε πάντα την εντολή σχεδίου και σκεφτείτε να χρησιμοποιήσετε τη στρατηγική create_before_destroy.

    Η αναβαλλόμενη συνέπεια είναι συνεπής... με την αναβολή

    Ορισμένα API παρόχων cloud, όπως το AWS, είναι ασύγχρονα και έχουν καθυστερημένη συνέπεια. Ασύγχρονη σημαίνει ότι η διεπαφή μπορεί να επιστρέψει αμέσως μια απάντηση χωρίς να περιμένει να ολοκληρωθεί η ζητούμενη ενέργεια. Η καθυστερημένη συνέπεια σημαίνει ότι οι αλλαγές μπορεί να χρειαστούν χρόνο για να διαδοθούν σε όλο το σύστημα. Ενώ συμβαίνει αυτό, οι απαντήσεις σας μπορεί να είναι ασυνεπείς και να εξαρτώνται από το ποια αντίγραφο της πηγής δεδομένων ανταποκρίνεται στις κλήσεις API σας.

    Φανταστείτε, για παράδειγμα, ότι πραγματοποιείτε μια κλήση API στο AWS ζητώντας του να δημιουργήσει έναν διακομιστή EC2. Το API θα επιστρέψει μια "επιτυχημένη" απάντηση (201 Δημιουργήθηκε) σχεδόν αμέσως, χωρίς να περιμένει τη δημιουργία του ίδιου του διακομιστή. Εάν προσπαθήσετε να συνδεθείτε σε αυτό αμέσως, είναι σχεδόν βέβαιο ότι θα αποτύχει επειδή σε εκείνο το σημείο το AWS εξακολουθεί να προετοιμάζει τους πόρους ή, εναλλακτικά, ο διακομιστής δεν έχει ακόμη εκκινήσει. Επιπλέον, εάν πραγματοποιήσετε άλλη κλήση για να λάβετε πληροφορίες σχετικά με αυτόν τον διακομιστή, ενδέχεται να λάβετε ένα σφάλμα (404 δεν βρέθηκε). Το θέμα είναι ότι οι πληροφορίες σχετικά με αυτόν τον διακομιστή EC2 ενδέχεται να εξακολουθούν να διαδίδονται σε όλο το AWS προτού γίνει διαθέσιμο παντού, θα πρέπει να περιμένετε μερικά δευτερόλεπτα.

    Κάθε φορά που χρησιμοποιείτε ένα ασύγχρονο API με χαλαρή συνέπεια, πρέπει περιοδικά να επαναλαμβάνετε το αίτημά σας μέχρι να ολοκληρωθεί η ενέργεια και να διαδοθεί μέσω του συστήματος. Δυστυχώς, το AWS SDK δεν παρέχει καλά εργαλεία για αυτό και το έργο Terraform υπέφερε από πολλά σφάλματα όπως το 6813 (https://github.com/hashicorp/terraform/issues/6813):

    $ terraform apply
    aws_subnet.private-persistence.2: InvalidSubnetID.NotFound:
    The subnet ID 'subnet-xxxxxxx' does not exist

    Με άλλα λόγια, δημιουργείτε έναν πόρο (όπως ένα υποδίκτυο) και στη συνέχεια προσπαθείτε να λάβετε κάποιες πληροφορίες σχετικά με αυτόν (όπως το αναγνωριστικό του υποδικτύου που δημιουργήθηκε πρόσφατα) και η Terraform δεν μπορεί να τον βρει. Τα περισσότερα από αυτά τα σφάλματα (συμπεριλαμβανομένου του 6813) έχουν διορθωθεί, αλλά εξακολουθούν να εμφανίζονται κατά καιρούς, ειδικά όταν η Terraform προσθέτει υποστήριξη για έναν νέο τύπο πόρου. Αυτό είναι ενοχλητικό, αλλά στις περισσότερες περιπτώσεις δεν προκαλεί κανένα κακό. Όταν εκτελείτε ξανά την εφαρμογή terraform, όλα θα πρέπει να λειτουργούν, καθώς μέχρι αυτή τη στιγμή οι πληροφορίες θα έχουν ήδη εξαπλωθεί σε όλο το σύστημα.

    Αυτό το απόσπασμα παρουσιάζεται από το βιβλίο του Evgeniy Brikman "Terraform: υποδομή σε επίπεδο κώδικα".

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο