Skip to content

Commit

Permalink
Add a Jenkins on Kubernetes example
Browse files Browse the repository at this point in the history
  • Loading branch information
swgillespie committed Jun 1, 2018
1 parent 176ce60 commit 76871f6
Show file tree
Hide file tree
Showing 6 changed files with 315 additions and 0 deletions.
3 changes: 3 additions & 0 deletions kubernetes-ts-jenkins/.gitignore
@@ -0,0 +1,3 @@
/bin/
/node_modules/
/.pulumi/
3 changes: 3 additions & 0 deletions kubernetes-ts-jenkins/Pulumi.yaml
@@ -0,0 +1,3 @@
name: kubernetes-ts-jenkins
description: Jenkins deployment on Kubernetes
runtime: nodejs
15 changes: 15 additions & 0 deletions kubernetes-ts-jenkins/index.ts
@@ -0,0 +1,15 @@
import * as pulumi from "@pulumi/pulumi";
import * as jenkins from "./jenkins";

const config = new pulumi.Config("jenkins");
const instance = new jenkins.Instance("jenkins", {
name: "jenkins",
credentials: {
username: config.require("username"),
password: config.require("password"),
},
resources: {
memory: "512Mi",
cpu: "100m",
}
});
254 changes: 254 additions & 0 deletions kubernetes-ts-jenkins/jenkins.ts
@@ -0,0 +1,254 @@
import * as pulumi from "@pulumi/pulumi";
import * as k8s from "@pulumi/kubernetes";
import * as input from "@pulumi/kubernetes/types/input";
import { extensions } from "@pulumi/kubernetes";

function createDeploymentArgs(args: JenkinsArgs): input.extensions.v1beta1.Deployment {
const image = args.image || {
registry: "docker.io",
repository: "bitnami/jenkins",
tag: "2.107.3",
pullPolicy: "IfNotPresent",
};

// This object is a projection of the Kubernetes object model into the Pulumi object model.
// Its structure is derived from the Deployment object in the Kubernetes API.
return {
metadata: {
name: args.name,
},
spec: {
replicas: 1,
template: {
metadata: {
labels: {
app: args.name,
},
},
spec: {
volumes: [
{
name: "jenkins-data",
persistentVolumeClaim: {
claimName: args.name,
}
},
],
containers: [
{
name: args.name,
image: `${image.registry}/${image.repository}:${image.tag}`,
imagePullPolicy: image.pullPolicy,
env: [
{
name: "JENKINS_USERNAME",
value: args.credentials.username,
},
{
name: "JENKINS_PASSWORD",
valueFrom: {
secretKeyRef: {
name: args.name,
key: "jenkins-password",
},
},
},
],
ports: [
{
name: "http",
containerPort: 8080,
},
{
name: "https",
containerPort: 8443,
},
],
livenessProbe: {
httpGet: {
path: "/",
port: "http",
},
initialDelaySeconds: 180,
timeoutSeconds: 5,
failureThreshold: 6,
},
readinessProbe: {
httpGet: {
path: "/",
port: "http",
},
initialDelaySeconds: 90,
timeoutSeconds: 5,
periodSeconds: 6,
},
volumeMounts: [
{
name: "jenkins-data",
mountPath: "/bitnami/jenkins",
}
],
resources: {
requests: {
memory: args.resources.memory,
cpu: args.resources.cpu,
},
},
} // container
] // containers
} // spec
} // template
} // spec
} // deployment
}

/**
* ComponentResource for a Jenkins instance running in a Kubernetes cluster.
*/
export class Instance extends pulumi.ComponentResource {
constructor(name: string, args: JenkinsArgs, opts?: pulumi.ResourceOptions) {
super("jenkins:jenkins:Instance", name, args, opts);

// The Secret will contain the root password for this instance.
const secret = new k8s.core.v1.Secret(`${args.name}-secret`, {
metadata: {
name: args.name,
},
type: "Opaque",
data: {
"jenkins-password": Buffer.from(args.credentials.password).toString("base64"),
},
}, { parent: this });

// The PVC provides persistant storage for Jenkins state.
const pvc = new k8s.core.v1.PersistentVolumeClaim(`${args.name}-pvc`, {
metadata: {
name: args.name,
annotations: {
"volume.beta.kubernetes.io/storage-class": "standard"
},
},
spec: {
accessModes: ["ReadWriteOnce"],
resources: {
requests: {
storage: "8Gi",
},
},
},
}, { parent: this });

// The Deployment describes the desired state for our Jenkins setup.
const deploymentArgs = createDeploymentArgs(args);
const deployment = new k8s.extensions.v1beta1.Deployment(`${args.name}-deploy`, deploymentArgs, { parent: this });

// The Service exposes Jenkins to the external internet by providing load-balanced ingress for HTTP and HTTPS.
const service = new k8s.core.v1.Service(`${args.name}-service`, {
metadata: {
name: args.name,
},
spec: {
type: "LoadBalancer",
ports: [
{
name: "http",
port: 80,
targetPort: "http",
},
{
name: "https",
port: 443,
targetPort: "https",
}
],
selector: {
app: args.name,
}
}
}, { parent: this });

// This component resource has no outputs.
this.registerOutputs({});
}
}

/**
* Arguments for Jenkins instances.
*/
export interface JenkinsArgs {
/**
* The name of the instance. All Kubernetes objects will be tagged with this name
* in their metadata.
*/
readonly name: string,

/**
* Credentials for accessing the created Jenkins instance.
*/
readonly credentials: JenkinsCredentials,

/**
* The Docker image to use to launch this instance of Jenkins.
*/
readonly image?: JenkinsImage,

/**
* Resource requests for this instance.
*/
readonly resources: JenkinsResources,
}

/**
* Credentials to access the newly-created Jenkins instance.
*/
export interface JenkinsCredentials {
/**
* Username for the root user.
*/
readonly username: string,

/**
* Password for the root user.
*/
readonly password: string,
}

/**
* The image to use when launching Jenkins.
*/
export interface JenkinsImage {
/**
* The registry from which to draw Docker images.
*/
readonly registry: string,

/**
* The Docker repository name for the target image.
*/
readonly repository: string,

/**
* The Docker image tag for the target image.
*/
readonly tag: string,

/**
* Pull policy for this image.
*/
readonly pullPolicy: string,
}

/**
* Resource requests for this Jenkins instance.
*/
export interface JenkinsResources {
/**
* Requested memory.
*/
readonly memory: string;

/**
* Requested CPU.
*/
readonly cpu: string;
}
16 changes: 16 additions & 0 deletions kubernetes-ts-jenkins/package.json
@@ -0,0 +1,16 @@
{
"name": "kubernetes-ts-jenkins",
"main": "bin/index.js",
"typings": "bin/index.d.ts",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"typescript": "^2.7.2",
"@types/node": "latest"
},
"dependencies": {
"@pulumi/pulumi": "^0.12.2",
"@pulumi/kubernetes": "^0.13.0"
}
}
24 changes: 24 additions & 0 deletions kubernetes-ts-jenkins/tsconfig.json
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es6",
"lib": [
"es6"
],
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"stripInternal": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true
},
"files": [
"index.ts"
]
}

0 comments on commit 76871f6

Please sign in to comment.