kaas

command module
v0.0.0-...-77e3877 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2020 License: Unlicense Imports: 15 Imported by: 0

README

KaaS 🧀

Ephemeral Kubernetes as a Service using Typhoon K8s on Digital Ocean

The purpose of this repository is to provision development clusters in a really simple and fast way. Result of this twitter thread.

Example request for a development cluster:

key=$(base64 < key.asc)
json="{\"version\":\"v1.18.1\",\"pubkey\":\"$key\"}"

curl --header "Content-Type: application/json" \
  --request POST \
  --data "$json" \
  https://k8stfw.com/cluster

Note: key.asc is your gpg public key, please see the test folder for an example.

It relies on Simple Typhoon K8s to provision clusters using Kubernetes batch jobs.

Current configuration:

region: nyc3
minutes: 120

In order to run your own KaaS, one must install the appropriate yamls from the k8s folder and provide the Kubernetes config file (including the do_token) from his manager cluster to the KaaS server (in this case, running on Google App Engine).

KaaS is a simple http request handler:

func main() {

	http.HandleFunc("/cluster", kaas)

	http.HandleFunc("/favicon.ico", faviconHandler)

	fs := http.FileServer(http.Dir("./static"))
	http.Handle("/", fs)

	log.Printf("Starting kaas 🧀\n")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}

}

It checks the currently supported version by Typhoon K8s:

func checkversions() (SupportedVersions, error) {
	client := github.NewClient(nil)

	taglist, _, err := client.Repositories.ListTags(context.Background(), "poseidon", "typhoon", nil)
	if err != nil {
		return SupportedVersions{}, err
	}
	var supported SupportedVersions
	for _, tag := range taglist {
		supported.Versions = append(supported.Versions, tag.GetName())
	}
	if err != nil {
		return SupportedVersions{}, err
	}
	return supported, nil
}

If it receives a POST request with a valid version, it returns the url where the encrypted kubeconfig file will be hosted and triggers createcluster():

if stringInSlice(cluster.Version, supported.Versions) {
    id, err := uuid.NewUUID()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    cluster.ID = id.String()
    cluster.Minutes = "120"
    cluster.Region = "nyc3"
    cluster.Cfg = "https://storage.googleapis.com/" + cluster.ID + "/cluster-config.gpg"

    err = createcluster(cluster)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    js, err := json.Marshal(cluster.Cfg)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    _, err = w.Write(js)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

} else {
    fmt.Fprintf(w, "Unsupported version")
}

createcluster() creates a Kubernetes job using Simple Typhoon K8s:

job := &batchv1.Job{
    ObjectMeta: metav1.ObjectMeta{
        Name: cluster.ID,
    },
    Spec: batchv1.JobSpec{
        Template: apiv1.PodTemplateSpec{
            Spec: apiv1.PodSpec{
                Containers: []apiv1.Container{
                    {
                        Name:  "terraform",
                        Image: "danacr/stk:latest",
                        Env: []apiv1.EnvVar{
                            apiv1.EnvVar{
                                Name:  "TF_VAR_cluster_id",
                                Value: cluster.ID},
                            apiv1.EnvVar{
                                Name:  "TF_VAR_cluster_region",
                                Value: cluster.Region},
                            apiv1.EnvVar{
                                Name:  "HOW_LONG",
                                Value: cluster.Minutes},
                            apiv1.EnvVar{
                                Name:  "CLUSTER_VERSION",
                                Value: cluster.Version},
                            apiv1.EnvVar{
                                Name:  "pubkey",
                                Value: cluster.PubKey},
                        },
                        VolumeMounts: []apiv1.VolumeMount{
                            apiv1.VolumeMount{
                                Name:      "do-token",
                                MountPath: "/home/terraform/config/do_token",
                                SubPath:   "do_token",
                            },
                            apiv1.VolumeMount{
                                Name:      "service-account",
                                MountPath: "/home/terraform/config/service-account-key.json",
                                SubPath:   "service-account-key.json",
                            },
                        },
                    },
                },
                RestartPolicy: apiv1.RestartPolicyNever,
                Volumes: []apiv1.Volume{
                    apiv1.Volume{
                        Name: "do-token",
                        VolumeSource: apiv1.VolumeSource{
                            Secret: &apiv1.SecretVolumeSource{
                                SecretName: "do-token",
                                Items: []apiv1.KeyToPath{
                                    apiv1.KeyToPath{
                                        Key:  "do_token",
                                        Path: "do_token",
                                    },
                                },
                            },
                        },
                    },
                    apiv1.Volume{
                        Name: "service-account",
                        VolumeSource: apiv1.VolumeSource{
                            Secret: &apiv1.SecretVolumeSource{
                                SecretName: "service-account",
                                Items: []apiv1.KeyToPath{
                                    apiv1.KeyToPath{
                                        Key:  "service-account-key.json",
                                        Path: "service-account-key.json",
                                    },
                                },
                            },
                        },
                    },
                },
            },
        },
    },
}

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL