Skip to content

Commit 139185b

Browse files
Documentation for Stacks (#275)
Adds docs for our new major feature vertical. This is definitely still WIP but covers all the main workflows for now.
1 parent 941b23a commit 139185b

File tree

11 files changed

+357
-1
lines changed

11 files changed

+357
-1
lines changed

pages/deployments/stacks.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
title: Stacks
3+
description: How to manage Infrastructure as Code at Scale Using Plural
4+
---

pages/stacks/customize-runners.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
title: Customize Stack Runners
3+
description: Configure runner pods to enable workload identity or EKS IRSA
4+
---
5+
6+
All stacks are run in a dedicated pod to support seamless scalability and enhance security. That said, you'll likely need to customize the definitions of those pods for a few usecases:
7+
8+
* Needing to add wiring to meet your existing OPA policy constraints around things like custom labels or `securityContext`
9+
* Needing to configure the pod with service accounts preconfigured for IRSA, GKE workload identity or similar secure cloud credential issuance systems
10+
* Needing to use your own base image
11+
12+
The process is simple and can be done per-stack or globally
13+
14+
## Configure the base image of your stack
15+
16+
All the stack runner images we provide are open source and available at https://github.com/pluralsh/deployment-operator. You're free to extend them and add any additional tools you want in the environment. Once that extended image is baked and published, you can reconfigure your stack CRD with:
17+
18+
19+
```yaml
20+
apiVersion: deployments.plural.sh/v1alpha1
21+
kind: InfrastructureStack
22+
metadata:
23+
name: gke-demo
24+
namespace: stacks
25+
spec:
26+
name: gke-demo
27+
type: TERRAFORM
28+
...
29+
configuration:
30+
image: your.registry/stack-harness
31+
tag: your-tag
32+
```
33+
34+
## Configure Runner for a single stack
35+
36+
The `jobSpec` field with a stack spec can configure that stacks runner, like so:
37+
38+
```yaml
39+
apiVersion: deployments.plural.sh/v1alpha1
40+
kind: InfrastructureStack
41+
metadata:
42+
name: gke-demo
43+
namespace: stacks
44+
spec:
45+
name: gke-demo
46+
type: TERRAFORM
47+
approval: true
48+
detach: false
49+
manageState: true
50+
51+
configuration:
52+
version: 1.8.2
53+
repositoryRef:
54+
name: fleet
55+
namespace: fleets
56+
clusterRef:
57+
name: mgmt
58+
namespace: infra
59+
workdir: gke-cluster
60+
git:
61+
ref: main
62+
folder: terraform
63+
# add a service account and label
64+
jobSpec:
65+
serviceAccount: stacks
66+
labels:
67+
deployment.plural.sh/needed-label: "finally-set"
68+
```
69+
70+
The expectation being that the service account was preconfigured for IRSA like so:
71+
72+
```yaml
73+
apiVersion: v1
74+
kind: ServiceAccount
75+
metadata:
76+
name: stacks
77+
namespace: plrl-deploy-operator
78+
annotations:
79+
eks.amazonaws.com/role-arn: arn:aws:iam::{your-account-id}:role/plrl-stacks
80+
```
81+
82+
This will add a service account and labels to the pod, but you can configure more information up to a full k8s JobTemplateSpec object. We encourage referencing our [CRD docs](/deployments/operator/api) if you want to learn all the knobs available.
83+
84+
## Configure Runner Pods Globally
85+
86+
You can also configure runners globally here:
87+
88+
```yaml
89+
apiVersion: deployments.plural.sh/v1alpha1
90+
kind: DeploymentSettings
91+
metadata:
92+
name: global
93+
spec:
94+
stacks:
95+
jobSpec:
96+
serviceAccount: stacks
97+
labels:
98+
deployment.plural.sh/needed-label: "finally-set"
99+
```
100+
101+
Configuration at the stack-level will always take priority, and global configuration is used as the next fallback before finally our hardcoded defaults.

pages/stacks/local-execution.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: Local Execution
3+
description: Executing IaC from Plural Stacks Locally
4+
---
5+
6+
One of the crucial aspects of Infrastructure as Code is you always have local execution as a break-glass measure if your control plane is broken. We make sure that principle is preserved in all cases. There are really two cases here to consider:
7+
8+
* You're using a self-managed state store, like s3. In this case, as long as you can replicate cloud creds locally, you can use your IaC outside of Plural at any time if you wish.
9+
* You're using Plural to manage your state.
10+
11+
## Run locally with Plural Managed State
12+
13+
Plural's terraform state backend ultimately works by using the `http` remote backend and writing an `_override.tf` file to the local folder to wire in that backend. You can invoke that logic from the cli with:
14+
15+
```sh
16+
plural cd stacks gen-backend
17+
```
18+
19+
This will write the same file locally, and a `terraform init` will initialize terraform against that http backend.
20+
21+
{% callout severity="warning" %}
22+
This file will potentially contain secret information, so you should be careful not to commit it to Git
23+
{% /callout %}

pages/stacks/manual-runs.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
title: Manual Runs
3+
description: Repair errors or one-off tasks in the stack environment
4+
---
5+
6+
Infrastructure as Code is great, but definitely will occasionally flake. Anything from drift in infrastructure or a terraform lock going awry can cause annoying breakages. Manual runs are meant to solve for this. There are two main modes of a manual run:
7+
8+
* One-off script supplied by the user in-UI
9+
* Pre-configured runs for common repair workflows, like running `terraform force-unlock {lock-id}` which can enhance self-serviceability of the process
10+
11+
## Launching a Manual Run
12+
13+
To launch a manual run, simply click the `Create manual run` button in the stacks UI
14+
15+
![](/assets/stacks/manual-run.png)
16+
17+
This will provide a simple wizard which can guide you through the workflow. This will trigger a run with the expected commands, within the same environment as a standard stack run.
18+
19+
## Create a Custom Run
20+
21+
You can create a pre-baked manual run via the `CustomRun` CRD, like so:
22+
23+
```yaml
24+
apiVersion: deployments.plural.sh/v1alpha1
25+
kind: CustomStackRun
26+
metadata:
27+
name: force-unlock
28+
spec:
29+
name: force-unlock
30+
documentation: "force release a terraform lock if present"
31+
commands:
32+
- cmd: terraform
33+
args: [init]
34+
- cmd: terraform
35+
args:
36+
- force-unlock
37+
- '-force'
38+
- "{{ context.lockId }}"
39+
configuration:
40+
- name: lockId
41+
type: STRING
42+
documentation: the lock id to release
43+
```
44+
45+
This creates a wizard-based manual run for the `terraform force-unlock` command, which can save your engineers a tedious look through the docs. It's also incredibly useful if you have customized your runner with additional scripts that might be used for ad-hoc operations.

pages/stacks/overview.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
title: Plural Stacks
3+
description: API-Driven Infrastructure As Code CD
4+
---
5+
6+
The goal of Plural Stacks is to provide a scalable framework to manage infrastructure as code like Terraform, Ansible and Pulumi with a kubernetes-friendly, api-driven approach. The core workflow is as follows:
7+
8+
* Declaratively define a stack with a type (terraform, ansible, etc), a location in a git repository to source code from, and a cluster on which it will execute
9+
* On each commit to the tracked git repository, a run is created which the Plural deployment operator will detect and execute on the targeted cluster
10+
- this allows users to fine grain permissions and network location of IaC runs where both are necessary to configure.
11+
* Plural will carefully execute the run for you, and besides basic information like communicating stdout to the UI, we will also gather and present useful information like inputs/outputs, terraform state diagrams and more
12+
* On PRs to the tracked repository, a "plan" run is also executed and comments posted on the relevant PR where possible.
13+
14+
To get a better idea of the full power of the experience, feel free to take a look at this demo video (at 2x speed if you want to save some time):
15+
16+
{% embed url="https://youtu.be/06WXbvw6p3w" aspectRatio="16 / 9" /%}
17+
18+
# A Basic Stack
19+
20+
The most common way to instantiate a stack is via Kubernetes CRD. This gives a flexible, modular way of recreating infrastructure with Terraform and pairs nicely with our PR Automation tooling for full self-service around IaC.
21+
22+
Here's an example:
23+
24+
```yaml
25+
apiVersion: deployments.plural.sh/v1alpha1
26+
kind: InfrastructureStack
27+
metadata:
28+
name: gke-demo
29+
namespace: stacks
30+
spec:
31+
name: gke-demo
32+
type: TERRAFORM
33+
approval: true
34+
detach: false
35+
manageState: true
36+
37+
configuration:
38+
version: 1.8.2
39+
repositoryRef:
40+
name: fleet
41+
namespace: fleets
42+
clusterRef:
43+
name: mgmt
44+
namespace: infra
45+
workdir: gke-cluster
46+
git:
47+
ref: main
48+
folder: terraform
49+
files:
50+
- mountPath: /plural
51+
secretRef:
52+
name: gcp-creds
53+
environment:
54+
- name: GOOGLE_APPLICATION_CREDENTIALS
55+
value: /plural/creds.json
56+
- name: TF_VAR_cluster
57+
value: gke-demo
58+
- name: TF_VAR_tier
59+
value: dev
60+
- name: TF_VAR_fleet
61+
value: gke-dem
62+
```
63+
64+
The meaning of this yaml is pretty self-documenting, we are:
65+
66+
* creating a `TERRAFORM` stack, so it will execute the standard terraform workflow
67+
* we're using Plural as the state store, removing the need to configure S3 or other backends manually
68+
* `approval` will be required before `terraform apply` will trigger, ensuring a human verifies the plan first to reduce misconfiguration risk
69+
* we're sourcing manifests from the `fleet` repository (referencing a `GitRepository` crd)
70+
* we're executing on the `mgmt` cluster (referencing a `Cluster` crd)
71+
* and we're executing in the `terraform/gke-cluster` folder
72+
73+
You can also see you can bind files and environment variables into the environment, although it is still best practice to use IRSA, GKE workload identity or similar mechanisms for issuing cloud credentials.

pages/stacks/pr-workflow.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
title: Stack PR Workflow
3+
description: API-Driven Infrastructure As Code CD
4+
---
5+
6+
Plural Stacks have the ability to trigger dry runs on PR giving users clear information as to what infrastructure can change as a result. This will do two things:
7+
8+
* run a dry run that terminates at the equivalent of `terraform plan` for the relevant stack type
9+
* post informative messages back to the PR to surface relevant details in Git.
10+
11+
To trigger a PR run, you'll need to follow a few conventions:
12+
13+
* the branch can be named any name like `plrl/stacks/<stack-name>/.*`
14+
* You include text like `Plural Stack: <stack-name>` in the title or description of the PR
15+
16+
This will tie the PR to the stack and initiate the dry-run process.
17+
18+
## Dependencies
19+
20+
There are a few dependencies to getting these working:
21+
22+
* You need to configure a SCM connection to whatever source control provider you're using. We currently support Github and Gitlab, and are happy to support others on request as well.
23+
* You need to configure a webhook against that SCM as well.
24+
25+
Both can be done in the ui.
26+
27+
Finally, you need to configure your stacks to use a given SCM connection, that can be done globally with:
28+
29+
```yaml
30+
apiVersion: deployments.plural.sh/v1alpha1
31+
kind: ScmConnection
32+
metadata:
33+
name: github
34+
spec:
35+
name: <name-from-ui>
36+
type: GITHUB
37+
---
38+
apiVersion: deployments.plural.sh/v1alpha1
39+
kind: DeploymentSettings
40+
metadata:
41+
name: global
42+
spec:
43+
stacks:
44+
connectionRef:
45+
name: github
46+
```
273 KB
Loading

src/NavData.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,32 @@ const rootNavData: NavMenu = deepFreeze([
160160
},
161161
],
162162
},
163+
{
164+
href: '/stacks/',
165+
title: 'Iac Management with Stacks',
166+
sections: [
167+
{
168+
title: 'Overview',
169+
href: '/stacks/overview',
170+
},
171+
{
172+
title: 'Customizing Stack Runners',
173+
href: '/stacks/customize-runners',
174+
},
175+
{
176+
title: 'Pull Request Workflow',
177+
href: '/stacks/pr-workflow',
178+
},
179+
{
180+
title: 'Manual Runs',
181+
href: '/stacks/manual-runs',
182+
},
183+
{
184+
title: 'Executing IaC Locally',
185+
href: '/stacks/local-execution',
186+
},
187+
],
188+
},
163189
{
164190
href: '/deployments/services',
165191
title: 'Deployments',

src/generated/graphql.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2150,7 +2150,8 @@ export enum Provider {
21502150
Gcp = 'GCP',
21512151
Generic = 'GENERIC',
21522152
Kind = 'KIND',
2153-
Kubernetes = 'KUBERNETES'
2153+
Kubernetes = 'KUBERNETES',
2154+
Linode = 'LINODE'
21542155
}
21552156

21562157
export type PublicKey = {

0 commit comments

Comments
 (0)