cluster: deploy calico and metrics service
diff --git a/cluster/kube/lib/metrics.libsonnet b/cluster/kube/lib/metrics.libsonnet
new file mode 100644
index 0000000..e11f5ef
--- /dev/null
+++ b/cluster/kube/lib/metrics.libsonnet
@@ -0,0 +1,142 @@
+# Deploy a per-cluster Metrics Server setup.
+
+local kube = import "../../../kube/kube.libsonnet";
+
+{
+    Environment: {
+        local env = self,
+        local cfg = env.cfg,
+        cfg:: {
+            image: "k8s.gcr.io/metrics-server-amd64:v0.3.1",
+            namespace: "kube-system",
+        },
+
+        sa: kube.ServiceAccount("metrics-server") {
+            metadata+: {
+                namespace: cfg.namespace,
+            },
+        },
+
+        # Cluster Role and Binding for the metrics server to allow reading node state.
+        crServer: kube.ClusterRole("system:metrics-server") {
+            rules: [
+                {
+                    apiGroups: [""],
+                    resources: ["pods", "nodes", "nodes/stats"],
+                    verbs: ["get", "list", "watch"]
+                },
+            ],
+        },
+        crbServer: kube.ClusterRoleBinding("system:metrics-server") {
+            roleRef: {
+                apiGroup: "rbac.authorization.k8s.io",
+                kind: "ClusterRole",
+                name: env.crServer.metadata.name,
+            },
+            subjects: [
+                {
+                    kind: "ServiceAccount",
+                    name: env.sa.metadata.name,
+                    namespace: env.sa.metadata.namespace,
+                },
+            ],
+        },
+
+        # Let the metrics server act as an auth delegator.
+        crbAuthDelegator: kube.ClusterRoleBinding("metrics-server:system:auth-delegator") {
+            roleRef: {
+                apiGroup: "rbac.authorization.k8s.io",
+                kind: "ClusterRole",
+                name: "system:auth-delegator",
+            },
+            subjects: [
+                {
+                    kind: "ServiceAccount",
+                    name: env.sa.metadata.name,
+                    namespace: env.sa.metadata.namespace,
+                },
+            ],
+        },
+
+        # Let the metrics server access the apiserver extensions configmap.
+        rbAPIExtensionsMap: kube.RoleBinding("metrics-server-auth-reader") {
+            metadata+: {
+                namespace: cfg.namespace,
+            },
+            roleRef: {
+                apiGroup: "rbac.authorization.k8s.io",
+                kind: "Role",
+                name: "extension-apiserver-authentication-reader",
+            },
+            subjects: [
+                {
+                    kind: "ServiceAccount",
+                    name: env.sa.metadata.name,
+                    namespace: env.sa.metadata.namespace,
+                },
+            ],
+        },
+
+
+        deployment: kube.Deployment("metrics-server") {
+            metadata+: {
+                namespace: cfg.namespace,
+                labels+: {
+                    "k8s-app": "metrics-server",
+                },
+            },
+            spec+: {
+                template+: {
+                    spec+: {
+                        serviceAccountName: env.sa.metadata.name,
+                        volumes_: {
+                            tmp: {
+                                emptyDir: {},
+                            },
+                        },
+                        containers_: {
+                            coredns: kube.Container("metrics-server") {
+                                local container = self,
+
+                                image: cfg.image,
+                                imagePullPolicy: "IfNotPresent",
+                                # TODO(q3k): define resource limits
+                                ports_: {
+                                    https: {
+                                        containerPort: 443,
+                                        protocol: "TCP",
+                                    },
+                                },
+                                volumeMounts_: {
+                                    tmp: {
+                                        mountPath: "/tmp",
+                                    },
+                                },
+                            },
+                        },
+                    },
+                },
+            },
+        },
+        svc: kube.Service("metrics-server") {
+            local svc = self,
+            metadata+: {
+                namespace: cfg.namespace,
+            },
+            target_pod: env.deployment.spec.template,
+        },
+        api: kube._Object("apiregistration.k8s.io/v1beta1", "APIService", "v1beta1.metrics.k8s.io") {
+            spec+: {
+                service: {
+                    name: env.svc.metadata.name,
+                    namespace: env.svc.metadata.namespace,
+                },
+                group: "metrics.k8s.io",
+                version: "v1beta1",
+                insecureSkipTLSVerify: true,
+                groupPriorityMinimum: 100,
+                versionPriority: 100,
+            },
+        },
+    },
+}