Cloudflare as Ingress

cloudfared is a tool we can use to connect our cluster securely to the outside world.

Cloudflare also gives us the option to use Quick Tunnels so we don't even have to setup a Cloudflare account at this stage.

Cloudflare will handle TLS termination for us, saving us some setup on our cluster.

Setting up the tunnel

Create a infra-as-code/cloudflare.ts and add the following

import * as kx from "@pulumi/kubernetesx"
import * as pulumi from "@pulumi/pulumi"

export function cloudflareTunnel(
    namespace: pulumi.Output<string>,
    url: string) {
    const cloudflaredPod = new kx.PodBuilder({
        containers: [{
            name: "cloudflare-tunnel",
            image: "cloudflare/cloudflared:latest",
            command: ["cloudflared", "tunnel", "--url", url],

    let deployName = pulumi.interpolate `${namespace}-cloudflare-tunnel`
    new kx.Deployment("cloudflare-tunnel", {
        metadata: {
            name: deployName,
            namespace: namespace
        spec: cloudflaredPod.asDeploymentSpec({ replicas: 1 })

Creating a service

We need to create a Kubernetes Service so that the Cloudflare tunnel can see out application.

Add the following to bottom of index.ts

new k8s.core.v1.Service("application", {
    metadata: {
        name: "application",
    spec: {
        ports: [
            { port: 3000, targetPort: 3000 }
        type: "ClusterIP",
        selector: {

cloudflareTunnel(, "http://application:3000")

At the top of index.ts import our cloudflareTunnel function.

import { cloudflareTunnel } from './cloudflare'

Getting our external URL

Cloudflare URL