-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Example of deploying the operator with Flux source controller (#339)
* Document Flux+Pulumi example This has two Pulumi projects: - the top directory (examples/flux-source) is for deploying the Pulumi Kubernetes operator along with the Flux source controller - the subdirectory app/ has an example a a Stack object refering to a Flux source. * Include webhook receiver in app stack - include Flux's notification-controller when installing Flux - create a webhook receiver object This parameterises the git URL used for the GitRepository source, so you must supply your own. (People won't be able to install webhooks in my repo!) * Supply an example of deploying ngrok You can use ngrok to tunnel webhooks through to a local or otherwise private cluster. This gives an example of deploying it which is enough to make the webhook in ../app work. * Mention Flux example in changelog Signed-off-by: Michael Bridgen <[email protected]>
- Loading branch information
Showing
13 changed files
with
615 additions
and
0 deletions.
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, | ||
}, | ||
}); | ||
|
||
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.