-
Notifications
You must be signed in to change notification settings - Fork 58
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
Example of deploying the operator with Flux source controller #339
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2c11c2a
Draft of Flux+Pulumi example
squaremo 0911824
Assume CRD is installed rather than attempting to
squaremo 615d2c1
Describe how to use Flux source example
squaremo 9b97e25
Always create the Stack CRD given the version
squaremo 0e106ad
Include webhook receiver in app stack
squaremo ab2b0e5
Supply an example of deploying ngrok
squaremo e7fbab7
Explain webhooks and tunneling in the README
squaremo 5c5705b
Bail if there's no access token
squaremo a6742c7
Mention Flux example in changelog
squaremo c0ce680
Make stack name for object a config item
squaremo 20bd15b
Bump default versions to 1.10.0
squaremo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
name: flux-and-pulumi | ||
runtime: nodejs | ||
description: Deploy Pulumi and Flux together |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
# Example of using the Pulumi Kubernetes operator with Flux | ||
|
||
The Pulumi operator can use [Flux sources][] for getting Pulumi programs. This example shows how to | ||
set the operator, and Flux source controller, up; and, how to create a `GitRepository` (a Flux | ||
source) and a `Stack` object that points to it. | ||
|
||
## Running the installation program | ||
|
||
The project in this directory will: | ||
|
||
- install the Flux source CRDs and controller | ||
- install the Pulumi operator and its CRD(s) | ||
- give the Pulumi operator permissions to see Flux source objects | ||
|
||
You'll need to install the program dependencies: | ||
|
||
```console | ||
flux-source$ npm install | ||
``` | ||
|
||
Now you can run the stack with the Pulumi command-line: | ||
|
||
```console | ||
flux-source$ pulumi up | ||
``` | ||
|
||
## Running the example app Stack | ||
|
||
You will need to install the dependencies for the program: | ||
|
||
```console | ||
app$ npm install | ||
``` | ||
|
||
For the project in `app/`, you'll need a Pulumi access token. You can create one in the [Pulumi | ||
service][] under "Access tokens". Assign it to the environment variable | ||
`PULUMI_ACCESS_TOKEN`. | ||
|
||
You will also need to supply a git repository URL. You can use my example: | ||
`https://github.com/squaremo/pko-dev`, but you won't be able to install webhooks there, so it might | ||
pay to fork that or create your own. (If you do create your own, you will likely want to change the | ||
`dir` in the Stack spec, which gives the subdirectory of the repo where your Pulumi code is). | ||
|
||
To run the program: | ||
|
||
```console | ||
app$ pulumi config set git-url https://github.com/squaremo/pko-dev | ||
app$ pulumi config set stack-name $(pulumi whoami)/app/dev | ||
app$ pulumi up | ||
``` | ||
|
||
This creates a `GitRepository` object in the cluster, which you can examine: | ||
|
||
```console | ||
app$ kubectl get gitrepository | ||
``` | ||
|
||
and a `Stack` object, pointing at the `GitRepository` object, which will run the program and create | ||
a deployment. You watch the stack object until it has completed: | ||
|
||
```console | ||
app$ kubectl get stack -w | ||
``` | ||
|
||
You should see the state become `succeeded` in a minute or so. The result of the stack is a | ||
deployment: | ||
|
||
```console | ||
app$ kubectl get deployment | ||
``` | ||
|
||
You can also look in the [Pulumi service][] to see what it creates. | ||
|
||
## Webhooks | ||
|
||
The program in `app/` also creates a webhook receiver, so you can get notifications from GitHub when | ||
there are new commits pushed. You will need to expose the webhook service to the internet for this | ||
to work: either use the guide in | ||
https://fluxcd.io/flux/guides/webhook-receivers/#expose-the-webhook-receiver, or use something like | ||
ngrok to tunnel the webhook into a private cluster. If you use the Flux guide, be aware that the | ||
webhook receiver here is in `default` namespace, rather than `flux-system`. There's a working | ||
example for ngrok in `ngrok/`. | ||
|
||
### Using ngrok to tunnel webhooks | ||
|
||
The directory `ngrok/` has a program that will run ngrok in such a way as to make the webhooks | ||
work. It doesn't need any configuration; just: | ||
|
||
```console | ||
ngrok$ pulumi up | ||
``` | ||
|
||
To see the public hostname that it's set up, access the ngrok console: | ||
|
||
```console | ||
ngrok$ NGROK_SERVICE=$(pulumi stack output service) | ||
ngrok$ kubectl port-forward service/$NGROK_SERVICE 4040:80 | ||
``` | ||
|
||
The ngrok console will then be reachable on http://localhost:4040/. | ||
|
||
Bear in mind that the tunnel hostname will change every time this restarts, so it's only really | ||
useful for (shortlived) demos. | ||
|
||
## Installing development versions | ||
|
||
You can use the install program to run a locally-built image, with the following steps. | ||
|
||
* install the CRD over the top of that installed by the stack | ||
|
||
```console | ||
pulumi-kubernetes-operator$ make install-crds | ||
``` | ||
|
||
* build a development version of the image: | ||
|
||
```console | ||
pulumi-kubernetes-operator$ make build-image IMAGE_NAME=pulumi/pulumi-kubernetes-operator | ||
``` | ||
|
||
(`IMAGE_NAME` means it won't name the image after `$(whoami)`) | ||
|
||
> If you're using `kind` to run a local Kubernetes cluster, you will need to side-load the image: | ||
> | ||
> ```console | ||
> kind load docker-image pulumi/pulumi-kubernetes-operator:$(git rev-parse --short HEAD) | ||
> ``` | ||
* use that image's tag as the `operator-version` configuration item when running the stack: | ||
```console | ||
pulumi-kubernetes-operator/examples/flux-source$ pulumi up -c operator-version=$(git rev-parse --short HEAD) | ||
``` | ||
[Flux source]: https://fluxcd.io/flux/components/source/api/ | ||
[Pulumi service]: https://app.pulumi.com/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/bin/ | ||
/node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
config: | ||
app:git-url: https://github.com/squaremo/pko-dev |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
name: app | ||
description: Application stack for Flux+Pulumi | ||
runtime: nodejs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import * as pulumi from "@pulumi/pulumi"; | ||
import * as k8s from "@pulumi/kubernetes"; | ||
import * as random from "@pulumi/random"; | ||
|
||
const config = new pulumi.Config(); | ||
export const gitURL = config.require('git-url'); | ||
export const stackName = config.require('stack-name'); | ||
|
||
// A git repository source for our Pulumi program | ||
const gitRepo = new k8s.apiextensions.CustomResource("pko-dev", { | ||
apiVersion: 'source.toolkit.fluxcd.io/v1beta2', | ||
kind: 'GitRepository', | ||
metadata: { | ||
'namespace': 'default', | ||
}, | ||
spec: { | ||
interval: '5m0s', | ||
url: gitURL, | ||
ref: { branch: 'main' }, | ||
}, | ||
}); | ||
|
||
const pulumiToken = process.env['PULUMI_ACCESS_TOKEN']; | ||
if (!pulumiToken) { | ||
throw new Error('This stack needs a Pulumi access token in the environment variable PULUMI_ACCESS_TOKEN') | ||
} | ||
|
||
// A secret with the Pulumi access token, taken from the environment. | ||
const tokenSecret = new k8s.core.v1.Secret("pulumi-token", { | ||
stringData: { | ||
'PULUMI_ACCESS_TOKEN': pulumiToken, | ||
}, | ||
squaremo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
|
||
const stack = new k8s.apiextensions.CustomResource("basic", { | ||
apiVersion: 'pulumi.com/v1', | ||
kind: 'Stack', | ||
metadata: { | ||
'namespace': 'default', | ||
}, | ||
spec: { | ||
stack: stackName, | ||
envRefs: { | ||
'PULUMI_ACCESS_TOKEN': { | ||
'type': 'Secret', | ||
'secret': { | ||
key: 'PULUMI_ACCESS_TOKEN', | ||
name: tokenSecret.metadata.name, | ||
}, | ||
}, | ||
}, | ||
fluxSource: { | ||
sourceRef: { | ||
apiVersion: gitRepo.apiVersion, | ||
kind: gitRepo.kind, | ||
name: gitRepo.metadata.name, | ||
}, | ||
dir: 'basic', | ||
}, | ||
refresh: true, | ||
}, | ||
}); | ||
|
||
// Using webhooks: this follows the guide at https://fluxcd.io/flux/guides/webhook-receivers/. | ||
|
||
// This program will go as far as creating the receiver in the cluster. You will need to | ||
|
||
// - expose that to the internet, either by creating an Ingress or LoadBalancer (explained in the | ||
// Flux documentation linked above), or using something like ngrok | ||
// (https://hub.docker.com/r/ngrok/ngrok). | ||
// | ||
// - install the webhook in the GitHub repository you're syncing from. | ||
|
||
// GitHub webhooks need a shared secret. | ||
|
||
export const token = pulumi.secret(new random.RandomString("webhook-token", { | ||
length: 40, | ||
special: false, | ||
}).result); | ||
|
||
const webhookSecret = new k8s.core.v1.Secret("webhook-token", { | ||
metadata: { | ||
namespace: 'default', | ||
}, | ||
stringData: { token }, | ||
}); | ||
|
||
const receiver = new k8s.apiextensions.CustomResource("app-hook", { | ||
apiVersion: 'notification.toolkit.fluxcd.io/v1beta1', | ||
kind: 'Receiver', | ||
metadata: { | ||
namespace: 'default', | ||
}, | ||
spec: { | ||
type: 'github', | ||
events: ["ping", "push"], | ||
secretRef: { | ||
name: webhookSecret.metadata.name, | ||
}, | ||
resources: [{ | ||
kind: 'GitRepository', | ||
name: gitRepo.metadata.name, | ||
}], | ||
}, | ||
}); | ||
|
||
export const readme = pulumi.unsecret(pulumi.interpolate ` | ||
The GitRepository, Stack and webhook receiver are set up. Get the webhook path with | ||
kubectl get receiver/${receiver.metadata.name} | ||
The token output has the secret for using as a webhook secret. Install the webhook at | ||
${gitURL}/settings/hooks, using the public host you've set up, the path from the receiver status, | ||
and the token. | ||
`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "app", | ||
"main": "index.ts", | ||
"devDependencies": { | ||
"@types/node": "^14" | ||
}, | ||
"dependencies": { | ||
"@pulumi/kubernetes": "^3.0.0", | ||
"@pulumi/kubernetesx": "^0.1.5", | ||
"@pulumi/pulumi": "^3.0.0", | ||
"@pulumi/random": "^4.8.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"compilerOptions": { | ||
"strict": true, | ||
"outDir": "bin", | ||
"target": "es2016", | ||
"module": "commonjs", | ||
"moduleResolution": "node", | ||
"sourceMap": true, | ||
"experimentalDecorators": true, | ||
"pretty": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"noImplicitReturns": true, | ||
"forceConsistentCasingInFileNames": true | ||
}, | ||
"files": [ | ||
"index.ts" | ||
] | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth showing off any of the value add here? (Features we get via Flux that aren’t available directly?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, somewhere. This example is a "how to", to show people how to get it working at all, and (secondarily) for them to adapt to their needs. Putting fancy stuff in would obscure that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would cool to do more examples that show off e.g.,