-
-
Notifications
You must be signed in to change notification settings - Fork 997
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stacks #3313
Comments
Considering that Terraform is also working on a similar abstraction called "stacks", perhaps another name is better suited as it might get confusing? That being said, you are unlikely to both use Terraform stacks and Terragrunt stacks. |
On the one hand... I agree that a name overlapping with an underlying tf feature would be confusing. On the other... If we deliver first that becomes their problem. They had a blog post last year in November about it and talked about it at hashiconf. If they haven't pushed this in a year it probably lost traction. |
@odgrim my understanding is that the feature is in private preview, as mentioned in many of their releases. See https://github.com/hashicorp/terraform/releases/tag/v1.10.0-alpha20240807 as an example. So I still think it's on their roadmap, just seems slow to get to public preview. |
Thanks for the feedback on the RFC, @hugorut! I've received feedback in multiple forums, so I'll try to give one big consolidated response here. The NameIt is very sensible to find some confusion around multiple tools leveraging the same name in different contexts. We feel like the name "stack" has salience in the community, and evokes the abstraction we're looking to encapsulate here. We've also been using the term "stack" in this context for a very long time internally. This RFC formalizes it externally, and adds tooling for dynamically generating them. This is an RFC, however, so if there are other names that folks feel would be more appropriate, make your suggestions heard! Does Terragrunt Need a Dedicated
|
It seems the proposed Stack concept is designed to help with breaking up monolithic configuration repositories. Could Stacks also be another chance to help shrink or reduce the number of |
Great RFC, thank you! I understand this will take a lot to make it happen, but I hope this gets real traction soon!
|
Similar to those proposals, it does aim to reduce boilerplate in Terragrunt usage by reducing the number of files that have to exist in a repository, yes. It does not aim to address those issues, though. There are many potential ways to address Terragrunt code duplication. Hopefully, this is a very convenient way to address those problems without introducing surprising or difficult to maintain behavior. @chkp-sergeyl |
Per feedback in multiple forums, a practical example has been requested, so I've created the following: If you would like to have a chance to try out using Terragrunt in a context where Stacks are useful, and see what Some initial feedback has already been collected in the form of some issues created on the repository. If you have any more feedback on the walkthrough, feel free to create an issue or submit a pull request there. As always general feedback on the RFC is encouraged here. |
👍🏼 👌🏼 I root for this, it boosts many DRY use cases for IaC |
So, aside from Terraform, both CloudFormation/CDK and Pulumi use "stacks" to refer to separately deployable projects. It's always bugged me that Terraform doesn't have a term for this. It's a project when it comes to code, corresponds to a statefile, but there's nothing to call it, and no concept of this level as a reusable, distributable component. It bugs me even more that Terraform are using the term to mean a collection of multiple deployable things, but still not something that is reusable and distributable. I tend to use the term "stack" closer to CF and Pulumi (in books and talks and things), and would vote for using it consistently! I've started using the term "Infrastructure Product" to refer to a higher level component, e.g. a collection of stacks. Is the Terragrunt stack a collection of multiple deployable things, or a single deployable thing? How does it related to services (as in this article? Is it reusable and distributable? |
I largely think the term "stacks" is confusing also. I've long equated terraform state to a "stack" to follow the terminology from CloudFormation. When you deploy a CloudFormation template, you create a CloudFormation stack. You can deploy the template many times to create many separate stacks. When you deploy a Terraform module, you create a Terraform state. You can deploy the module many times to create many separate states. A CloudFormation template is like a Terraform module, and a CloudFormation stack is like a Terraform state. Other than the terminology, the idea is very intriguing. |
To address both points: @kief You can read a more detailed breakdown of what this might look like in practice here: @lorengordon A Stack in Terragrunt terminology differs from a Unit in that it's a set of related pieces of infrastructure, each with their own state that pass messages between each other via |
Maybe... I know, to continue the CloudFormation analogy, this would be a StackSet... :D |
For the folks that have been following along: I've introduced a new chapter to the walkthrough I shared earlier detailing how a user would go about adopting Stacks for a use-case involving real AWS infrastructure: Please share any feedback you have here, especially if you think elements of the design in this RFC might make it easier/harder to adopt Stacks for infrastructure you are provisioning today. |
Per feedback I've received externally, I'm including a note that, at a future date, something like the following will be made available for Stacks to be used more conveniently: # terragrunt.stack.hcl
unit "foo" {
source = "../units/foo"
path = "services/foo"
inputs = {
name = "your-name"
}
} # .terragrunt-stack/services/foo/terragrunt.hcl
inputs = {
name = unit.inputs.name
} And similarly, a mechanism like the following will be available for recursive stacks: # terragrunt.stack.hcl
stack "foo" {
source = "../stacks/foo"
path = "services/foo"
inputs = {
name = "your-name"
}
} # .terragrunt-stack/services/foo/terragrunt.stack.hcl
unit "bar" {
source = ".../../units/bar"
path = "sub-service/bar"
inputs = {
name = stack.inputs.name
}
} The behavior we land on will be documented as something to be delivered in a future release, after Stacks are made available. |
With that, we've received enough feedback to officially accept the RFC for Stacks! 🎉 I'll mark the RFC as accepted, and we'll start scheduling the work to make Stacks available. |
👏🏼 I will happily be a test user for this. Any public way to know about ongoing development for Stacks feature? |
@diegoaguilar , I'm happy to hear the enthusiasm! Of course, all ongoing work for Stacks will be public, as this is an open source project. The official blog post announcement announcing the release of Stacks for folks that aren't following GitHub will be the point in which we'll close this issue as completed, with a link to that blog post for more information. In the meantime, I've added a new label for issues As we get closer to the announcement, we'll also have an issue template like this created for Stacks so that folks can report issues related to stacks with the label automatically applied. Following this issue will be the best way to get those updates as time goes on, as anything that references |
I wonder what Terragrunt's value-adds will be now that Terraform and OpenTofu are both trying to address the DRY problem natively. We're using Terragrunt right now and the changes in 1.0 look promising, but I feel a lot of uncertainty due to the velocity at which all these projects are moving. It probably goes without saying, but for us the ideal is an intuitive workflow that can grow with us without having to juggle. |
Hey @EdanBrooke ! We've been talking about the best way to communicate the changes that are happening to Terragrunt, and the overall IaC landscape. Your feedback is really appreciated, and welcome! If I could give a quick, personal answer to this feedback, the main value-add that Terragrunt provides today is that of an IaC orchestrator, not just as a tool to make OpenTofu/Terraform more DRY. You might have noticed that all of the features described in the road to 1.0 blog post centered around this value proposition of IaC orchestration. I personally look at it like the difference between containers and Kubernetes. Sure, Docker might make it more convenient to spin up containers in a reliable way, with dynamic configurations so that each container can do more, but Kubernetes is solving the problem of orchestrating those containers at a higher level, so that you can do more than you could with just Docker. Similarly, OpenTofu is really good at getting infrastructure represented in one state to different infrastructure represented in another state, but if you want to segment that infrastructure into multiple state files to limit blast radius, have updates to those units of infrastructure coordinated correctly, and dynamically, Terragrunt is a really good tool for making that feasible. What we're trying to deliver with Stacks is very explicitly an experience that won't force you to change everything you are currently doing with Terragrunt, but rather an experience that lets you opt-in to the parts you like, for the infrastructure you're ready to change and no new If you have the time, and you haven't done it yet, I recommend going through this walkthrough and seeing how and why Stacks was designed as it was in this proposal. |
Something I've asked @denis256 to evaluate is a modification to the Stacks design to introduce a new optional attribute for unit {
source = "../units/foo"
path = "foo"
hidden = false
}
stack {
source = "../stacks/bar"
path = "bar"
hidden = false
} The thought behind this is to make it so that users can optionally decide not to generate units and stacks within the hidden This might make it easier for folks to have a "soft" adoption of Stacks, as existing implicit stacks (a directory with a bunch of units) won't be placed into It didn't seem like a heavy lift, so we're asking for feedback on that as an adjustment to the RFC, and we'll look to add that capability after the first pass of implementation is complete. I've also added it as part of the agenda for tomorrow's Office Hours, so please attend if you would like to share your feedback live! |
Hey guys, is there any rough time estimates for when stacks will be available? |
Hey @nuryupin-kr , Yup! We're shooting for Q1 2025. We'll be cutting publicly available pre-releases, etc as we make progress, so you'll be able to give feedback as we make progress. This is one of our two top priorities for Q1, including the CLI redesign. Of course, if feedback makes us feel like we need more time to flesh things out or stabilize things, it might take longer. We're more interested in incremental progress and getting it right than getting it done quickly. |
We just published a blog post providing a deep dive on stacks! https://blog.gruntwork.io/the-road-to-terragrunt-1-0-stacks-cd97f11ef565 Share your feedback if it gives you any new insights as to how it will work. There's also a special feature Dynamic Stacks that we're committing to above and beyond the contents of this RFC to give users even more tools in their tool belt for managing stacks. |
Published alpha release with support of https://github.com/gruntwork-io/terragrunt/releases/tag/v0.71.2-alpha2024122001 |
Pardon me if I am redundant or off topic. I tried to read what I could find but found no explicit answer about the deletion (removing a unit in a stack file). If it behaves exactly like a run-all in the IMHO the more consistent approach would be to remove resources deployed in a unit that is no longer present in a stack file, but in order to achieve that you might need to introduce a stack state. Is it something planned down the line ? |
Hey @FuNK3Y , Great question! The short answer is yes! The state that we're going to be using for automatically tracking changes is going to be git, and the mechanism is something I'll be publishing an RFC for after this RFC and #3445 are done. As you pointed out, it's a larger feature than just supporting stacks, so it's easier to discuss it once stacks are available and the CLI redesign is complete (so that we don't have to adjust the names of flags we introduce right after introducing them). |
I just wanted to comment that I have spent good 2 hours diving into all of the discussion, links, examples and walkthroughs and I must say ... I am psyched for the stacks! As a long time terragrunt user that manages a multi account and env setup on top of AWS, the amount of terragrunt.hcl files I have currently is enormous. Stacks look like a great orchestration abstraction that given some though on the initial design will make bootstrapping new infrastructure way easier and pleasant (especially thinking here about provisioning a new environment that consists of multiple small terraform modules that are glued together via inputs / dependency blocks) - one no longer has to built terraform modules that wrap another terraform modules to limit the amount of terragrunt.hcl files. Big shoutout to @yhakbar for providing this walkthrough https://github.com/yhakbar/terragrunt-3313-stacks-walkthrough/tree/main as for me it cleared up any misconceptions and shown the real power of stacks. |
Summary
To reduce code repetition and make it easier to manage Terragrunt codebases, this proposal introduces a layer of abstraction above
terragrunt.hcl
files called Stacks. Stacks are defined using files namedterragrunt.stack.hcl
.Users will interact with Stacks using commands prefixed with
terragrunt stack
, which will allow them to create, manage, and destroy Stacks.Motivation
Many users using Terragrunt experience repetition with
terragrunt.hcl
files in their repositories.One reason for this might be that, while Terragrunt configurations provide an abstraction for DRY (Don't Repeat Yourself) OpenTofu/Terraform modules, the ability to abstract the Terragrunt configuration itself is somewhat limited.
Users typically use a collection of
terragrunt.hcl
files, each of which are relevant to managing an OpenTofu/Terraform module for a single state file. Repeatedly provisioning the same module across multiple environments, or multiple times within the same environment currently necessitates replication of the sameterragrunt.hcl
file for each instantiation of that module.Users have experienced complications with synchronizing updates across multiple
terragrunt.hcl
files, and have expressed a desire for a more streamlined way to synchronize updates across multipleterragrunt.hcl
files.In addition, Terragrunt code re-use has been largely limited to Terragrunt configurations found on local filesystems. Expanding tooling so that Terragrunt configurations can be shared across repositories would be beneficial, both for the scalability of Terragrunt codebases, and to expand the ways in which Gruntwork customers can leverage configurations maintained by Gruntwork.
Proposal
Introduce a new
terragrunt.stack.hcl
configuration file that can be used by Terragrunt to manage a Stack.terragrunt.stack.hcl
The
terragrunt.stack.hcl
file will have configurations that entirely focus on generating a stack ofterragrunt.hcl
files. Theseterragrunt.hcl
files will use the same syntax as current Terragrunt configurations, and use existing tooling to integrate into the stack.An example
terragrunt.stack.hcl
file might look like this:In this example, the
terragrunt.stack.hcl
file defines three Units:service
,db
, andapi
. Each Unit is the path to a directory containing aterragrunt.hcl
file, using go-getter to load the configurations locally or from a remote source.Quick Detour on "Units"
The term "Unit" is language that we haven't standardized externally, but is something that we've been using internally at Gruntwork. It's a way to refer to a single instantiation of an OpenTofu/Terraform module, and we believe the best way to do that is with a
terragrunt.hcl
file. Whenever you see reference to "Unit", you can mentally replace that with aterragrunt.hcl
file. It's a unit of infrastructure, with its own state, potentially integrated into a larger system.We have yet to standardize this term throughout Terragrunt tooling and documentation, but we believe it's a useful concept to introduce in this proposal.
If you have feedback on this terminology, please let share it!
terragrunt.stack.hcl
Configuration ContinuedThose
unit
configuration blocks are used to instantiate Terragrunt Units. The two things that are required for a Unit to be instantiated are:source
attribute (Required): The way in which Terragrunt is going to fetch the relevant directory containing theterragrunt.hcl
file.path
attribute (Optional): The path to the directory where the unit is going to be generated. If not provided, the default path determined by the source will be used. More on this will be discussed later.The
locals
block is one that most Terragrunt users are familiar with. It's a way to define reusable variables throughout a Terragrunt stack.terragrunt stack
CommandsIn tandem with introducing a new configuration file, Terragrunt will also have a new set of commands that will allow users to interact with Stacks. These commands will be prefixed with
terragrunt stack
.terragrunt stack generate
: This command will generate the stack of Units, using the configurations in theterragrunt.stack.hcl
file.What this will do is create a
.terragrunt-stack
directory next to theterragrunt.stack.hcl
file, and populate it with content from the Units defined in theterragrunt.stack.hcl
file.The paths to the units in the
.terragrunt-stack
directory will be determined by thepath
attribute in theunit
configuration blocks. If thepath
attribute is not provided, a default path will be determined based on parsing thesource
attribute.e.g.
Would generate the file structure:
terragrunt stack run *
: Similar to therun-all
command, thestack run
command allows users to run commands across all Units recursively discovered in a directory with therun
command. A significant difference to therun-all
command is that thestack run
command will run those commands within the context of the.terragrunt-stack
directory. The suffix*
is a wildcard that is forwarded to the underlying wrapped binary that Terragrunt is orchestrating (OpenTofu/Terraform), just like it does withrun-all
.e.g.
Would run
terraform plan
in each of the Units in the.terragrunt-stack
directory. If the.terragrunt-stack
directory does not exist, thestack run
command will generate it first.To ensure that users have full control over this process, the
stack run
command will have a--terragrunt-generate-stack=false
flag that will prevent the.terragrunt-stack
directory from being generated. The verbosity of this flag is not ideal, but it is in-line with the verbosity of other Terragrunt flags. This is something to revisit in the future.terragrunt stack output
: In order to be able to interact with the Units within a stack outside of it, thestack output
command will be introduced. This command will take the outputs of the Units in the Stack and stitch them together into a single output. This will allow users to interact with the stack as a single unit, rather than having to interact with each Unit individually.e.g.
This will allow users to access the outputs of the Units in the Stack, without having to navigate to each Unit individually.
How
terragrunt.hcl
Files Are ImpactedOne of the main goals of this proposal is to make it so that users can take the exact same
terragrunt.hcl
files they are using today, and use them as part of a Stack. To that end, users should not expect any special syntax used interragrunt.hcl
files used in a Stack.Units are already frequently written with relative paths for their
dependency
blocks to reference each other.e.g.
A unit with that
dependency
block would expect to find a folder nameddb
sibling to it in the directory structure. Stacks take advantage of that, allowing them to be generated dynamically using thepath
attribute in theunit
configuration blocks, and the relative paths in thedependency
blocks will work within the context of the.terragrunt-stack
directory.In addition, users frequently use the path from a
terragrunt.hcl
file at the root of the repository or the.git
directory to determine where state files are stored for individual units.In the context of a Stack, the path simply includes the
.terragrunt-stack
directory with no changes to how the path is currently calculated.e.g.
Given the following file structure:
Replacing the contents of
dir
with:Will result in the following file structure once a
terragrunt stack
command is run:The
service
anddb
units will be generated in the.terragrunt-stack
directory, and thedependency
block in theservice
unit will be able to reference thedb
unit using the same relative path../db
.The implication to existing
terragrunt.hcl
files is that they cannot necessarily be easily refactored into Stacks with the initial release due to the need to move state, but it should be trivial to generate new instances of the same Units in a new Stack.In the future, additional tooling can be explored to help users migrate to Stacks from existing Terragrunt configurations.
How Stacks Use Shared Configurations
A common pattern seen with modern Terragrunt configurations is that they frequently rely on shared configurations via the
include
configuration block. Users may be familiar with canonical_envcommon
directories, that are designed for this in the Gruntwork library. This can be a useful pattern, and one that doesn't have to be abandoned when adopting Stacks.One benefit of this design, however, is that all Units have a natural alternate location to store shared configurations that they rely on: the
terragrunt.stack.hcl
file. Units can leverage existing functions like read_terragrunt_config to read configurations from theterragrunt.stack.hcl
file.e.g.
There may be benefits to introducing new functionality that makes it easier to share configurations across Units in a Stack in the future, but the initial release will not need include anything besides what Terragrunt can do today.
Nesting Stacks
To mitigate the risk of Stacks becoming too large, or repeated, Stacks are designed to be nestable.
e.g.
In this example, the
services
stack will be generated at.terragrunt-stack/services
, and thedb
unit will be generated at.terragrunt-stack/db
. Once theservices
stack is generated, Terragrunt will recursively generate a stack using the contents of the.terragrunt-stack/services/terragrunt.stack.hcl
file until it fully generates the stack.Any
terragrunt stack run *
commands will run on the top-level stack, picking up all the nested stacks as part of the process.Technical Details
To support the introduction of Stacks, the following have to be achieved:
A new configuration file will be accepted by Terragrunt:
terragrunt.stack.hcl
The
terragrunt.stack.hcl
will follow the spec outlined in this proposal. It will supportlocals
andunit
blocks.A new command will be introduced:
terragrunt stack
The
terragrunt stack
command will follow the spec outlined in this proposal. It will support the following subcommands:terragrunt stack generate
terragrunt stack output
terragrunt stack run *
Considerations:
.gitignore
a new directory:.terragrunt-stack
(though they could technically take a vendored approach and commit it).terragrunt.hcl
configurations that are invalid in potentially non-obvious ways (they may use paths in theirterragrunt.stack.hcl
file that don't align with theconfig_path
value independency
blocks ofterragrunt.hcl
files).Press Release
Introducing Terragrunt Stacks!
Stacks are a way to drastically reduce the repetition in Terragrunt codebases by leveraging a new configuration file:
terragrunt.stack.hcl
.With the introduction of Stacks, users can now consolidate large numbers of
terragrunt.hcl
files into a singleterragrunt.stack.hcl
file.Stacks are a powerful new feature, and are the largest change to how users write Terragrunt configurations to date.
To get started, try out the new
terragrunt stack
command, which allows you to create, manage, and destroy Stacks:Drawbacks
Potentially Too Much Abstraction
The largest potential drawback to introducing Stacks is that it is yet another layer of abstraction to how users manage their infrastructure.
Terragrunt is already a fairly complex tool, and adding Stacks on top of it may make it more difficult for users to understand how their infrastructure is being managed.
The ways in which this design attempts to mitigate this drawback include:
Stacks are Optional: Users can continue to use Terragrunt as they always have, and only introduce Stacks where they need to scale their Terragrunt codebase.
Stacks are Explicit: Stacks are defined in a separate file, and are not a hidden feature in Terragrunt configurations. This makes it clear when a user is working with a Stack, and when they are not.
Stacks are Simple: The design of Stacks is intentionally simple, with only a few added configurations and commands introduced in this initial proposal.
Stacks are Familiar: All of the work Stacks do to interact with infrastructure is mediated by
terragrunt.hcl
files. Users can runterragrunt stack generate
, and see a.terragrunt-stack
directory that operates exactly like a current Terragrunt codebase without Stacks.This behavior falls in line with how the
.terragrunt-cache
directory was designed, allowing users to runtofu
/terraform
commands within the directory to achieve the same end result, dropping down a layer of abstraction.Performance
Users leveraging remote Units as part of their stacks will deal with the performance penalty of fetching those Units from a remote source before running any infrastructure updates.
It's probably not a huge penalty to deal with, but users can always vendor their
.terragrunt-stack
directories and remove the performance penalty entirely.Alternatives
_envcommon
The alternative that most Terragrunt users use today is to leverage a directory of shared configurations located in a directory named something like
_envcommon
.This directory usually contains a collection of files that use Terragrunt HCL configurations. These files are then included in multiple other
terragrunt.hcl
files via include configuration blocks using thepath
attribute.This approach is effective at reducing repetition in Terragrunt codebases, and has some advantages over the proposed solution:
terragrunt.hcl
files directly relates to the number of Units in the codebase. This can make it easier to initiate individual state updates, as there is always a singleterragrunt.hcl
file that can be run.However, this approach also has some drawbacks:
terragrunt.hcl
files can be difficult, as there is no built-in way to ensure that allterragrunt.hcl
files referencing the same_envcommon
file are updated._envcommon
directory is not independently versioned, and changes to the_envcommon
directory can result in updates with large blast radii.Larger OpenTofu/Terraform Modules
Another alternative is to put more logic into OpenTofu/Terraform modules themselves, and use a single
terragrunt.hcl
file to manage the larger module.This approach is also effective at reducing repetition in Terragrunt codebases, and allows users to put more of the logic for managing infrastructure in
.tf
files if they would prefer that.The drawbacks to this approach are largely the reason that using Terragrunt is advantageous:
run_cmd
,before_hook
,after_hook
,error_hook
can't be used to perform additional logic that is not supported by OpenTofu/Terraform.terragrunt.hcl
file.Migration Strategy
Users that aren't currently using stacks will have to do some work in order to migrate their existing Terragrunt codebases to use Stacks if they want to take advantage of them.
Creating
terragrunt.stack.hcl
FilesTaking a collection of
terragrunt.hcl
files, and consolidating them into a singleterragrunt.stack.hcl
file is the first step in migrating to StacksUsers will want to consider where they want their
terragrunt.hcl
files to live (either in the same repo, as part of a monorepo, or in a different, dedicated repository).Then, they'll want to decide which Units they want to consolidate into a Stack, and write
terragrunt.stack.hcl
files to reference those Units.Migrating State
Users will need to consider how they want to migrate their state files to work with Stacks.
For a gradual adoption of Stacks, users should prioritize using Stacks for net new infrastructure, then consider migrating existing infrastructure to Stacks.
Considerations to take into account when migrating state files include, but is not limited to:
To migrate state files, users will want to follow these steps:
Unresolved Questions
How does the community feel about introducing Stacks as a feature in Terragrunt?
This will be a significant change to what users see in Terragrunt codebases, and will require that they be comfortable with the new abstraction.
Are there alternate abstractions Gruntwork should prefer to this?
What is the minimum required feature set of Stacks to make them useful?
There is a lot more planned for Stacks than what is presented in this proposal. One goal here is to present the minimum feature set that will make Stacks useful to users, and to receive feedback from the community.
Is there anything missing from this proposal that immediately jumps to mind as a requirement to make Stacks useful?
How does the community feel about the design of Stacks?
Does this seem like a natural abstraction that fits well within the existing Terragrunt ecosystem? Are there any changes that should be made to the design work better?
How does the community feel about the terminology used here?
Do the terms "Stack" and "Unit" make sense in the context of Terragrunt? Are there any other terms that might be more appropriate?
How does this proposal fit into the lifecycle of a Terragrunt Unit?
Careful consideration goes into making sure that Terragrunt has good tooling so that configuration can be introduced into codebases in a sensible and convenient manner, that it is easy to create, update, manage, use, and remove.
Stacks are viewed as a natural extension of this lifecycle, where Units can be refactored into Stacks when they need to be reused repeatedly.
Does this proposal fit well into that lifecycle?
References
Proof of Concept Pull Request
No response
Support Level
Customer Name
No response
The text was updated successfully, but these errors were encountered: