Skip to content

Instantly share code, notes, and snippets.

@lukehoban
Created May 19, 2023 06:42
Show Gist options
  • Save lukehoban/4ee81b57e9813870bdb3459e96bbdc34 to your computer and use it in GitHub Desktop.
Save lukehoban/4ee81b57e9813870bdb3459e96bbdc34 to your computer and use it in GitHub Desktop.
Pulumi Self-Hosted Cloud - Simple Kubernetes Deployment
import * as pulumi from "@pulumi/pulumi";
import * as k8s from "@pulumi/kubernetes";
import * as command from "@pulumi/command";
class ServiceDeployment extends pulumi.ComponentResource {
internalEndpoint: pulumi.Output<string>;
externalEndpoint?: pulumi.Output<string>;
service: k8s.core.v1.Service;
constructor(name: string, args: { name: string, image: string, replicas?: number, env?: Record<string, pulumi.Input<string>>, ports?: { port: number }[], loadBalancer?: boolean, volumes?: { name: string, mountPath: string, secret: k8s.core.v1.Secret }[] }, opts?: pulumi.ComponentResourceOptions) {
super("selfhosted:ServiceDeployment", name, {}, opts);
const labels = { app: args.name };
const deployment = new k8s.apps.v1.Deployment(name, {
spec: {
selector: { matchLabels: labels },
replicas: args.replicas ?? 1,
template: {
metadata: { labels: labels },
spec: {
containers: [{
name: name,
image: args.image,
env: args.env ? Object.keys(args.env).map(k => ({ name: k, value: args.env![k] })) : undefined,
volumeMounts: args.volumes ? args.volumes.map(v => ({ name: v.name, mountPath: v.mountPath, subPath: v.name })) : undefined,
}],
volumes: args.volumes ? args.volumes.map(v => ({ name: v.name, secret: { secretName: v.secret.metadata.name } })) : undefined,
}
}
}
});
this.service = new k8s.core.v1.Service(name, {
spec: {
ports: args.ports,
selector: labels,
type: args.loadBalancer ? "LoadBalancer" : undefined,
},
});
this.internalEndpoint = pulumi.interpolate`http://${this.service.metadata.name}:${this.service.spec.ports[0].port}`;
if (args.loadBalancer) {
this.externalEndpoint = pulumi.interpolate`http://${this.service.status.loadBalancer.ingress[0].hostname}:${this.service.spec.ports[0].port}`;
}
}
}
const config = new pulumi.Config();
const licenseKey = config.requireSecret("licenseKey");
const mysql = new ServiceDeployment("mysql", {
name: "mysql",
image: "mysql:8.0",
env: {
MYSQL_DATABASE: "pulumi",
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
},
ports: [{ port: 3306 }],
});
const migrations = new k8s.batch.v1.Job("migrations", {
spec: {
template: {
spec: {
containers: [{
name: "migrations",
image: "pulumi/migrations:latest",
env: [
{ name: "PULUMI_DATABASE_ENDPOINT", value: pulumi.interpolate`${mysql.service.metadata.name}:3306`, },
{ name: "PULUMI_DATABASE_PING_ENDPOINT", value: mysql.service.metadata.name, }
],
}],
restartPolicy: "Never",
},
},
},
});
const randomness = new command.local.Command("localKeys", {
create: "head -c 32 /dev/random | base64",
});
const localKeysSecret = new k8s.core.v1.Secret("localKeys", {
metadata: { name: "localkeys" },
data: { "localkeys": randomness.stdout },
})
const api = new ServiceDeployment("api", {
name: "api",
image: "pulumi/service:latest",
env: {
PULUMI_LICENSE_KEY: licenseKey,
PULUMI_ENTERPRISE: "true",
PULUMI_DATABASE_NAME: "pulumi",
PULUMI_API_DOMAIN: "localhost:8080",
PULUMI_CONSOLE_DOMAIN: "localhost:3000",
PULUMI_DATABASE_ENDPOINT: pulumi.interpolate`${mysql.service.metadata.name}:3306`,
PULUMI_LOCAL_OBJECTS: "/pulumi/checkpoints",
PULUMI_POLICY_PACK_LOCAL_HTTP_OBJECTS: "/pulumi/policypacks",
PULUMI_LOCAL_KEYS: "/pulumi/localkeys",
},
ports: [{ port: 8080 }],
loadBalancer: true,
volumes: [{ name: "localkeys", mountPath: "/pulumi/localkeys", secret: localKeysSecret }],
});
const console = new ServiceDeployment("console", {
name: "console",
image: "pulumi/console:latest",
env: {
PULUMI_API: api.externalEndpoint!,
PULUMI_API_INTERNAL_ENDPOINT: api.internalEndpoint,
CONSOLE_DOMAIN: "http://localhost:3000",
HOMEPAGE_DOMAIN: "http://localhost:3000",
},
ports: [{ port: 3000 }],
loadBalancer: true,
});
export const apiEndpoint = api.externalEndpoint!;
export const appEndpoint = console.externalEndpoint!;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment