I have in my dotfiles:
alias tfplan='terraform plan -out=.tfplan -refresh=false'
alias tffreshplan='terraform plan -out=.tfplan'
alias tfapply='terraform apply .tfplan; rm .tfplan'
That way I never accidentally `terraform apply` without creating a plan first. I also have it not refresh the state by default, which is mostly unnecessary and speeds up the planning significantly.https://github.com/hashicorp/terraform/blob/master/website/s...
https://github.com/hashicorp/terraform/issues/13276
I hope you all can work on improving the definitions, because many of them really are a chore compared to setting things up in the AWS dashboard, at the moment (security groups for example).
I always refresh when running the pre-apply plan, but while iterating I use that. Do you always run your `tffreshplan` command before applying?
From what I have seen so far though, there isn't really that much difference/benefit over CloudFormation. We currently have 95% of our resources in AWS with about 4% in Azure, and 1% in Google Cloud. It's great that Terraform is 'mulit-cloud' but it still seems like you have to write .tf's catered to each cloud, you can't just lift and shift to another cloud by copying and pasting a file?
People say the 'plan' feature is one of the advantages over CFN, but as far as I can tell, CFN now offers the same feature... it tells you what's going to change when you upload a new stack.
I sound like a CFN advocate now, but I genuinely don't have that much experience with it, and really do want to give Terraform a chance. Convince me?
Oh, and since CFN started supporing YAML it looks easier to write too
* Ability to separate data (variables/parameters) from configs.
* Easier to read (well at least pre-YAML CFN).
* Allows comments in the code.
* Version control changes (diffs) are easier to read.
* Multi-Cloud support. Works against AWS, Google Compute, Azure, Docker, more.
* Multi-provider in general: can provision resources across multiple different cloud providers at once.
* Can write modules in TF that can be reused in multiple different configs.
* Tracks state via a version-controllable data file.
* 'terraform plan' is essentially a no-op mode to see what changes would occur without actual running or making changes.
* Actively developed.It also makes it for when/if you want to switch or start supporting other providers - your tool is already agnostic, and you don't need to go from CloudFormation and port over - you're already there.
The beauty of Terraform is that you can orchestrate all of your infrastructure, not just the stuff in one stack. If you've got 95%/4%/1% in AWS/Azure/GCP, how do you manage/reference the non-AWS resources? Terraform gives you a unified way to reference and link cross-infrastructure resources.
We're not quite at the point where even the "comparable" cloud services across clouds are drop-in compatible with each other, so this is not going to be possible for a while for reasons not related to Terraform.
> I sound like a CFN advocate now, but I genuinely don't have that much experience with it, and really do want to give Terraform a chance. Convince me?
You could spend your time learning either a vendor-specific tool (CFN), or a vendor agnostic one (Terraform). Since Terraform can do a lot of what CFN does, it may make sense to spend your time learning Terraform instead.
Edit: not sure about CFN, but Terraform is open source: https://github.com/hashicorp/terraform
However, this isn't to say that Terraform is always better than CloudFormation. In fact, I'd prefer to use CloudFormation for A/B | Blue-Green deploys because it supports UpdatePolicy options for rotating newly configured images into an autoscaling group. The logic to do that in Terraform is really not trivial at all (there is no clean, straightforward way to do such deployments with Terraform). Furthermore, rollbacks are significantly more reliable in my experience using CloudFormation than Terraform. Rollbacks may be easier to orchestrate using Terraform than CloudFormation though due to easier reference to non-AWS resources.
My preferred style of AWS deployments and infrastructure-as-code layering is Terraform with broken out modules and generating smaller CloudFormation templates for individual application components that need to be deployed often. This seems like a worst-of-both-worlds option but I think keeping CloudFormation templates constrained to just ASG modifications avoids a lot of the problems.
I used the terraforming gem (either because "terraform import" didnt' exist at the time, or because I just didn't like the way it worked) to bring a lot of things under management by terraform.
That's not even enough for our Network ACLs.
How do you work around that?
For example, the last time I used it, a few months ago, it was not able to import almost any of our Google Cloud stuff, and I discovered that import support is only provided for some resources. There's a third-party tool called Terraforming, but it apparently only works with AWS.
I'm quite disheartened that the world is lagging this far behind. The only competitor I've found is Salt, and I found its orchestration support to be a bit of a mess. And just as with Terraform, the code is constantly lagging behind the providers.
The one provider I'd have expected to be on the forefront of orchestration is Google, and in a different multiverse their engineers are swarming around Terraform to make sure it has top-notch, official, first-class support, but alas, not in this one.
Are there any competitors that provide a smoother experience?
- google_bigquery_dataset
- google_bigquery_table
- google_compute_address
- google_compute_disk
- google_compute_global_address
- google_compute_route
- google_compute_network
- google_dns_managed_zone
- google_sql_user
- google_storage_bucket
, with more to come shortly!We only have one open issue around import, so if there are other resources you'd like to see imported feel free to file an issue: https://github.com/terraform-providers/terraform-provider-go... (just moved to a new repo a few days ago, and we're still in the process of getting existing issues moved over). A big factor in our prioritization of what to work on is based around issues filed (and thumbs ups on those issues), so that's a great way to get in touch with the team.
If you have any other questions around the Terraform+GCP experience, feel free to ask us in the #terraform channel in the GCP slack (https://gcp-slack.appspot.com/ if you aren't already there). Best of luck, and do reach out if you need anything!
My lasting fear is that even if it has 90% of the support, there will always be one thing, or one edge case or bug, that will become an annoying blocker. Using a tool like TF means becoming dependent on it to a large extent.
I know you can hack this together with modules, but it seems like environment/project organization would be easier if terraform just recursed subdirectories. Right? I've seen a couple of issues for it, but I don't believe I've seen a concrete reason why it's a no-go.
We adopted the ingress/egress stanza on security group resource approach.
If we ever wanted to change to the other approach (as described in the article), I don't think I would do state surgery by hand or even use "terraform state mv". I would:
1. change terraforming to generate .tf files and tfstates the way I want
2. remove the security groups from my config and my state
3. use terraforming to regenerate the .tf files and tfstateI wanted to apologize that this is super confusing. All the scenarios where this exists (there are many) are historical. We originally went with the "nested" approach and now prefer the "split" approach for good reasons shown to us by users. But we kept both for backwards compatibility reasons. We have no good mechanism to enforce a migration at the moment. There are a couple ways we can resolve this technically in the future. For now, we should probably make sure the docs are annotated in all situations of the limitations of nested vs. standalone. I'll mention this to the team!
If you can choose between a "con todo" description that lumps together resources and subresources, versus describing every single little thing separately and then attaching them together, always use attachments.
1) You remove it explicitly from your configuration; which should be the intended result - it's no longer a "part of your infrastructure"
2) You've change some attribute that requires your provider to replace the instance entirely - Trying to think of an example off hand... While not applicable anymore as AWS now supports applying/changing IAM roles to running instances now, had you done something like that in the past, that would've forced a resource replacement.
So far, it leaves me rather anxious - Packer and Vagrant appear to offer the bare minimum of usable functionality, with any advanced scenario bumping into (sometimes intentional) walls.
For example, it takes me 15-20 minutes to transfer a 50 MB file to a Windows VM being created by Packer. The GitHub issue, filed nearly 2 years ago, is closed with a comment that this is by design: https://github.com/hashicorp/packer/issues/2648#issuecomment...
Yet there is a PowerShell command that uses the same communication mechanism that can somehow do it in a matter of seconds. Of course, I cannot use this PowerShell command because Packer does not give me a variable with a machine's IP address because... it is improper somehow? https://github.com/hashicorp/packer/issues/4993
What the hell, Hashicorp...
I have a list of 10+ issues I have found so far and I am only starting to use these tools. From the activity in GitHub, they seem to be abandonware.
Maybe if I submitted PRs they might be accepted (then again, maybe not: https://github.com/hashicorp/packer/pulls) but I expect more from software than just accepting PRs - I expect its authors to actually develop it and to show an interest in improving it.
There is unfortunately nothing better out there. I admit, I am forced to use these products even though I do not find them satisfactory and the authors do not seem helpful.
If I had to start all over again with my current knowledge, I might perhaps just write my own scripting and skip Packer/Vagrant altogether. The value they offer with VM management comes with the downside of being left in the mud and having the system work against you when you try something nontrivial.
I am scared of what I will find when I touch Terraform. As I write this, I think I will first see whether I can just script it manually.
Don't have the apply be automatic after a review is approved; terraform apply's occasionally go sideways and need human intervention (remember: rollbacks are not automatic). A human should always kick off the apply and monitor state change activity.
And thanks for the suggestion. So far it's been on a someday maybe list, but if it really does help that much, maybe we'll bump it to someday maybe soon.
- Are you commenting with the output of show on the planfile to get human-readable version?
- Line by line commenting on comments?
- Do you have state-splits? Do you run plan on each individually for every PR?
Shameless plug, if anybody is looking for a guide on getting started with Terraform and Google Cloud Platform, I wrote a short blog post:
https://blog.elasticbyte.net/getting-started-with-terraform-...
I've run into another similar type issue now and I think that I'm going to have to do state surgery like you. I want to refactor some of my terraform resources into modules, but this changes the resource names. I can't see any way to do it without either standing up new infrastructure or modifying the state directly.
https://github.com/sevagh/goat
This way in Terraform I provision a group of volumes, a group of instances, and rely on `goat` to do the rest.
[0] https://www.terraform.io/docs/configuration/resources.html#c...
1) Update the launch configuration of your un-used ASG ( with the new AMI ID )
2) Apply terraform to deploy the new ASG
3) Make sure it's working ( your local app on your new instances )
4) Connect the ELB to your new ASG
5) Set the old ASG to 0 instances to drain the connections
https://robmorgan.id.au/posts/rolling-deploys-on-aws-using-t...
Is it possible to query information directly from a state file? Some interpolation would help. I ask this because I often refer to resource information from another project, and I don't see that modules are helpful.
I posted my work-around here [1] some days ago . The real code was not there because I haven't had permission for my company, but it's very short and easy to write by anyone.
Thanks for your reading.
[1] https://github.com/icy/oops/blob/master/terraform/problem_1_...
Disclaimer: ex-HashiCorp employee.
Handling package dependencies with Go is not straighforward. There are several ways of doing it, and none are native to Golang.
Additionally, Go doesn't support getting versions of packages by tag or branch.
This bit me hard when I tried to update Palantir's TFJSON utility (turns tfplan binaries into json) so I could do unit testing of my Terraform plans with rspec.
The utility depended on v0.7.4 of terraform, but Terraform maintains a plan format constant that defines which plans can be used by what versions. They changed the plan format between 0.7.4 and 0.9.8 without bumping that constant, so when I tried running tfjson against plans created by the latter version, I got a weird non-matching datatype error that took a while to figure out. (I eventually had to vimdiff the hex outputs of plans created by both versions to figure that out.)
Additionally, HashiCorp made a significant change to the way they handled providers between 0.9.8 and 0.10.0 that justified them to bump the plab format version AGAIN. The catch: 0.10.0 isn't released yet, despite that being the code in their master branch.
I figured that updating tfjson's vendored terraform library to 0.9.8 would solve it. I first did a go get to fetch the latest TF codebase and used gvt to vendor it. That's when I discovered that plans generated by 0.9.8 are no longer compatible. After discovering that go get can't fetch packages by tag (Hashicorp tags their release commita) because Google believes in stable HEADs, I had to find a tool that could support fetching packages by tags. Govendor did that, so I used that.
It takes FOREVER to fetch all of the subpackages used by terraform. I couldn't do it during a three hour flight. Rubygems has its problems, but fetching deps isn't one of them. And even when I thought I fetched the entire source tree at v0.9.8, I would still get errors about missing types or missing packages.
I'm hopeful that I'll eventually find a solution, but it's a dog compared to using Gemfile.lock.
backend "s3" {
region = "us-west-1"
bucket = "foo-tf-us-west-1"
key = "foobar.tfstate"
dynamodb_table = "tf-lock"
}
}https://www.terraform.io/docs/backends/types/s3.html#dynamod...
> Most outages are caused by human error and configuration changes, and applying Terraform changes is a terrifying mix of the two.
Terraform is a great tool nonetheless. Just like Heap, we have code reviews for the configuration itself, and a CI pipeline for validating it. This pipeline is quite superficial (`terraform validate` mostly does syntax checking), so we are too working on using centralized state to `terraform plan` for reviews.
Did you try to use `terraform state mv`? I've found that command useful (albeit for much less than thousands of resources).
An alternative to doing this was `terraform import` on all the volumes, then defining attachments, and hoping it all worked when you run `terraform plan`. I don't 100% remember now why we didn't do that.
::Sulks off dejectedly::