Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terraform and Updates

Being able to capture infrastructure in a single Terraform file has obvious benefits. However, I am not clear in my mind how - once, for example, a virtual machine has been created - subsequent updates are handled.

So, to provide a specific scenario. Suppose that using Terraform we set up an Azure vm with SQL Server 2014. Then, after a month we decide that we should like to update that vm with the latest service pack for SQL Server 2014 that has just been released.

Is the recommended practice that we update the Terraform configuration file and re-apply it?

like image 801
David Brower Avatar asked Aug 30 '16 08:08

David Brower


People also ask

What is Terraform update?

The terraform refresh command reads the current settings from all managed remote objects and updates the Terraform state to match. Warning: This command is deprecated, because its default behavior is unsafe if you have misconfigured credentials for any of your providers.

What is the latest Terraform version?

Terraform v0. 14 is a major release and so it includes some small changes in behavior that you may need to consider when upgrading. This guide is intended to help with that process. The goal of this guide is to cover the most common upgrade concerns and issues that would benefit from more explanation and background.


2 Answers

I have to disagree with the other two responses. Terraform can handle infrastructure updates just fine. The key thing to understand, however, is that Terraform largely follows an immutable infrastructure paradigm, which means that to "update" a resource, you delete the old resource and create a new one to replace it. This is much like functional programming, where variables are immutable, and to "update" something, you actually create a new variable.

The typical pattern with Terraform is to use it to deploy a server image, such as an Virtual Machine (VM) Image (e.g. an Amazon Machine Image (AMI)) or a Container Image (e.g. a Docker Image). When you want to "update" something, you create a new version of your image, deploy that onto a new server, and undeploy the old server.

Here's an example of how that works:

Imagine that you're building a Ruby on Rails app. You get the app working in dev and it's time to deploy to prod. The first step is to package the app as an AMI. You could do this using a tool like Packer. Now you have an AMI with id ami-1234.

Here is a Terraform template you could use to deploy this AMI on a server (an EC2 Instance) in AWS with an Elastic IP Address attached to it:

resource "aws_instance" "example" {
  ami = "ami-1234"
  instance_type = "t2.micro"
}

resource "aws_eip" "example" {
  instance = "${aws_instance.example.id}"
}

When you run terraform apply, Terraform deploys the server, attaches an IP address to it, and now when users visit that IP, they will see v1 of your Rails app.

Some time later, you update your Rails app and want to deploy the new version, v2. To do that, you build a new AMI (i.e. you run Packer again) to get an ami with ID "ami-5678". You update your Terraform templates accordingly:

resource "aws_instance" "example" {
  ami = "ami-5678"
  instance_type = "t2.micro"
}

When you run terraform apply, Terraform undeploys the old server (which it can find because Terraform records the state of your infrastructure), deploys a new server with the new AMI, and now users will see v2 of your code at that same IP.

Of course, there is one problem here: in between the time when Terraform undeploys v1 and when it deploys v2, your users would see downtime. To work around that, you could use Terraform's create_before_destroy lifecycle setting:

resource "aws_instance" "example" {
  ami = "ami-5678"
  instance_type = "t2.micro"

  lifecycle {
    create_before_destroy = true
  }
}

With create_before_destroy set to true, Terraform will create the replacement server first, switch the IP to it, and then remove the old server. This allows you to do zero-downtime deployment with immutable infrastructure (note: zero-downtime deployment works better with a load balancer that can do health checks than a simple IP address, especially if your server takes a long time to boot).

For more information on this, check out the book Terraform: Up & Running. The code samples for the book include an example of a zero-downtime deployment with a cluster of servers and a load balancer: https://github.com/brikis98/terraform-up-and-running-code

like image 71
Yevgeniy Brikman Avatar answered Nov 10 '22 22:11

Yevgeniy Brikman


Terraform is an infrastructure provision tool, th configuration/deployment tools will be:

  • chef
  • saltstack
  • ansible
  • etc.,

As I am working with chef, so basically, I provision the server instance by terraform, then terraform (terraform provisioner) handles the control to chef for system configuration and deployment.

For the moment, terraform cannot delete the node/client in chef server, so after you terraform destroy, you need remove them by yourself.

like image 44
perigee Avatar answered Nov 10 '22 23:11

perigee