This page provides an overview of how to use the Pulumi plugin for Spinnaker to run Pulumi apps. Pulumi doesn’t require any particular arrangement of stacks or workflow to work in a CI/CD system. So the steps described here can be altered to fit into any existing type of deployment setup.
Plugins are a recent addition to Spinnaker and as such require a more recent version to use plugins as well as the Pulumi plugin for Spinnaker, which this guide will show you how to use.
- Spinnaker v1.19.4+
- Halyard 1.34+
Additionally, your Spinnaker instance should have been deployed using the distributed installation method (i.e. Kubernetes). If you are using any other installation method, although the plugin shown in this document will not work, you may be able to apply similar concepts to your installation.
This guide assumes you are using the default Pulumi Service managed backend. The Spinnaker plugin referenced in this guide supports specifying alternate backend URLs. To sign-up for a new Pulumi account, head over to the Pulumi Console.
Pulumi Stack And Branch Mappings
Learn more about Stacks.
The sample pipeline (shown later) below acts on a hypothetical stack:
- Depending on your use-case, you may want to create the Pulumi Stack ahead of time.
- To create a new stack, you have a couple of options, you may create it in the Pulumi Console directly.
- Alternatively, you can also run
pulumi new [template]to create a template project.
The source code for the stack is in a repository in GitHub cloned from this example and uses
TypeScript as the language.
The example infrastructure code creates a Kubernetes
Deployment using the
nginx container image.
If you modify the sample app or wish to create the
Deployment resource in a different Kubernetes cluster, follow the setup guide for the Kubernetes provider
to ensure that Pulumi can access that Kubernetes cluster.
While the example shows you how to deploy a Kubernetes resource, there are many other cloud providers that Pulumi supports.
Note: The names used above are purely for demonstration purposes only. You may choose a naming convention that best suits your organization.
Pulumi Plugin For Spinnaker
The Pulumi plugin executes a pre-configured job as a Kubernetes batch job. The job runs whichever container image you choose to use for executing the Pulumi apps. The only requirement for the image that the batch job uses is that it should contain the Pulumi CLI, and any necessary language runtime tools, such as
By default, the plugin suggests using the
pulumi/pulumi container image available publicly on Docker Hub.
Alternatively, you can also try to use one of the other language-specific images that are available under the
pulumi org on Docker Hub.
If you would like to use a private image for the job you can do so, but ensure that your Spinnaker cluster has the right credentials to pull an image from a private registry. Contact your Spinnaker administrator if you are unsure whether you can use a public image.
The pre-configured job will also need to access your VCS to clone the repo into the container. See the next section about configuring secrets to learn how you can use private repos with the plugin.
To pass sensitive secrets to the Kubernetes batch job run by the plugin, you’ll need to define a Kubernetes Secret. The secret will need to be in the same namespace as the namespace used to run the pre-configured job. Sensitive secrets such as the Pulumi Access Token, the cloud provider credentials, or even your Git VCS credentials (eg. GitHub, Bitbucket, GitLab), should be defined as key/value pairs in the Secret resource.
If you are using the service backend, either the Pulumi-managed or the self-hosted one, you’ll need to get a Pulumi Access Token for the Pulumi account that you’ll use in your pipeline. Save the value of the token with the key
PULUMI_ACCESS_TOKEN in your Kubernetes Secret resource.
Here’s an example Secret resource applied to a Spinnaker installation.
Tip: If your Spinnaker Kubernetes cluster was created using Pulumi, then instead of writing this YAML, you could deploy the Secret resource using Pulumi too.
apiVersion: v1 kind: Secret metadata: # Remember the name of this secret. name: pulumi-secrets # The namespace of this Secret and the namespace used by the plugin should match. # Learn more about Plugin Configuration in the next section. namespace: spinnaker data: # Any key/value pairs defined here will be injected as environment variables # available to the container in which your Pulumi app will be run. PULUMI_ACCESS_TOKEN: <base64EncodedValue> AWS_ACCESS_KEY_ID: <base64EncodedValue> AWS_SECRET_ACCESS_KEY: <base64EncodedValue> ... ... # If your Pulumi app is stored in a private repo, you may specify the username/password # here and then use the corresponding "key" names as placeholders in the URL you specify # later in the Pipeline Stage. GIT_USERNAME: <base64EncodedValue> GIT_PAT: <base64EncodedValue>
To create this resource in your Spinnaker cluster, run:
kubectl apply -f secrets.yaml
As you can see above you can set any environment variables required for the specific providers you plan to use in your Pulumi app. Learn more about provider setup.
For private Git repos, you can save the Personal Access Token used to clone your repo into the batch job container. Then when you configure the Stage in your Spinnaker Pipeline you can reference the same key names in the URL you specify.
https://$(GIT_USERNAME):$(GIT_PAT)@github.com/owner/repo. The env vars will automatically resolve to the values as per your Secret resource inside the pre-configured job container.
Installing The Spinnaker Plugin
While using the Pulumi plugin is optional, doing so will help reduce the maintenance of the manual steps required to run Pulumi in Spinnaker.
Installing the plugin is comprised of two steps. First, you’ll need to add the relevant plugin repository to your Halyard configration using the
hal CLI. Then, you can add the plugin itself.
# Add the Pulumi plugins repository for Spinnaker hal plugins repository add pulumi --url https://raw.githubusercontent.com/pulumi/spinnaker-plugins-repository/master/repositories.json # Add the plugin itself hal plugins add Pulumi.PreConfiguredJobPlugin --enabled true --version 0.0.1 --extensions pulumi.PreConfiguredJobStage # Apply the updates hal deploy apply
Depending on your Spinnaker installation you might have to run the above commands using
Note Before you can access the newly-added plugin in the Deck UI, you must wait for the old
orca Pod to be replaced with a new one in your cluster. This can take anywhere from a minute to a few depending on the size of your cluster.
To check the state of the running pods you may run
kubectl -n spinnaker get pods. This will print the pods in the
Spinnaker namespace as well as the age of the pod.
There are two configuration opportunities available with the plugin:
At this time, updating global plugin configuration requires editing your Halyard configuration file manually.
The plugin offers the following global configuration options.
account- The account to be used to run the pre-configured job. Add Kubernetes accounts using the
hal config provider kubernetes addcommand.
credentials- The credentials to use to run the pre-configured job.
namespace- The namespace in which to run the pre-configured job. Secret resources must also exist in the same namespace.
To set the above configuration properties, open the
~/.hal/config file where your Halyard installation exists. This typically requires SSH’ing into a Pod if your Spinnaker installation is done using the distributed installation method. Scroll-down to the plugins section and find the
Pulumi.PreConfiguredJobPlugin section. Under
config:, configure the above properties as you desire.
Don’t forget to run
hal deploy applyafter modifying your
Navigate to your Spinnaker instance’s Deck UI, and in the Pipeline that you wish to run Pulumi, click the
Add Stage button at the appropriate Pipeline branch and find the
The Pulumi stage’s UI shows you tooltips to help you fill in the values of the various input properties.
Spinnaker Pipelines support pipeline expressions that allow you to dynamically fill in values of inputs.
The following steps assume that you have cloned this Kubernetes example into your own repo.
Creating a Pipeline in Spinnaker is easy and offers many integration options for your GitOps workflow. In the sample pipeline, however, we will show you how to add the Pulumi stage and create a Kubernetes resource.
- Create a new Pipeline and click the Add Stage button. This will allow you to pick from a list of available stages, including the Pulumi stage which you would have added above.
- Configure the inputs for the Pulumi stage accordingly.
- As previously mentioned in this guide, you can use pipeline expressions for your stage inputs.
- Note that we are setting the value of the Command input to
Add a Manual Judgement stage to the pipeline and then let’s add the Pulumi stage again, but this time we’ll set the Command input to
up instead of
In the end, your pipeline should look like this:
Go back to the main Pipelines view and click on the Start Manual Execution link next to your pipeline. Check the logs from Pulumi as the Pulumi stage runs. The logs update in near real-time.
Once the pipeline is complete, assuming you have not modified the example app, the
nginx container would have been deployed to the
Get the pod IP by running a
kubectl command and
curl-ing the IP to see the response:
kubectl get pods -o wide curl http://POD_IP
We showed you a simple example of how you can get started with using Pulumi in your Spinnaker instance.
- Check out detailed examples for Pulumi.
- Learn how to use the multitude of providers available with Pulumi.
- We hope that you find the plugin useful in running Pulumi in your Spinnaker instance. If you run into problems or would like to provide feedback, we encourage you to open an issue in this repo. The plugin is free and open-source.
- Lastly, whether you are looking to use Pulumi to deploy a Spinnaker installation on your favorite cloud and have questions about it, or you want to simply participate in the various conversations happening with our community of users, feel free to drop by our Community Slack.