From 1e565dc4a5f3e4dd7082849874753e3c82ee4e7f Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Fri, 18 Jan 2019 09:40:59 +0100 Subject: [PATCH] cluster: start implementing metallb --- cluster/kube/cluster.jsonnet | 3 + cluster/kube/lib/metallb.libsonnet | 110 +++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 cluster/kube/lib/metallb.libsonnet diff --git a/cluster/kube/cluster.jsonnet b/cluster/kube/cluster.jsonnet index 4eb9eee2..c79a8279 100644 --- a/cluster/kube/cluster.jsonnet +++ b/cluster/kube/cluster.jsonnet @@ -4,6 +4,7 @@ local kube = import "../../kube/kube.libsonnet"; local coredns = import "lib/coredns.libsonnet"; local metrics = import "lib/metrics.libsonnet"; local calico = import "lib/calico.libsonnet"; +local metallb = import "lib/metallb.libsonnet"; local Cluster(fqdn) = { local cluster = self, @@ -48,6 +49,8 @@ local Cluster(fqdn) = { dns: coredns.Environment {}, // Metrics Server metrics: metrics.Environment {}, + // Metal Load Balancer + metallb: metallb.Environment {}, }; diff --git a/cluster/kube/lib/metallb.libsonnet b/cluster/kube/lib/metallb.libsonnet new file mode 100644 index 00000000..a00163b9 --- /dev/null +++ b/cluster/kube/lib/metallb.libsonnet @@ -0,0 +1,110 @@ +# Deploy MetalLB + +local kube = import "../../../kube/kube.libsonnet"; + +local bindServiceAccountClusterRole(sa, cr) = kube.ClusterRoleBinding(cr.metadata.name) { + roleRef: { + apiGroup: "rbac.authorization.k8s.io", + kind: "ClusterRole", + name: cr.metadata.name, + }, + subjects: [ + { + kind: "ServiceAccount", + name: sa.metadata.name, + namespace: sa.metadata.namespace, + }, + ], +}; + +{ + Environment: { + local env = self, + local cfg = env.cfg, + cfg:: { + namespace: "metallb-system", + namespaceCreate: true, + }, + + ns: if cfg.namespaceCreate then kube.Namespace(cfg.namespace), + + saController: kube.ServiceAccount("controller") { + metadata+: { + namespace: cfg.namespace, + }, + }, + + saSpeaker: kube.ServiceAccount("speaker") { + metadata+: { + namespace: cfg.namespace, + }, + }, + + crController: kube.ClusterRole("%s:controller" % cfg.namespace) { + rules: [ + { + apiGroups: [""], + resources: ["services"], + verbs: ["get", "list", "watch", "update"], + }, + { + apiGroups: [""], + resources: ["services/status"], + verbs: ["update"], + }, + { + apiGroups: [""], + resources: ["events"], + verbs: ["create", "patch"], + }, + ], + }, + + crbController: bindServiceAccountClusterRole(env.saController, env.crController), + + crSpeaker: kube.ClusterRole("%s:speaker" % cfg.namespace) { + rules: [ + { + apiGroups: [""], + resources: ["services", "endpoints", "nodes"], + verbs: ["get", "list", "watch"], + }, + ], + }, + + crbSpeaker: bindServiceAccountClusterRole(env.saSpeaker, env.crSpeaker), + + roleWatcher: kube.Role("config-watcher") { + metadata+: { + namespace: cfg.namespace, + }, + rules: [ + { + apiGroups: [""], + resources: ["configmaps"], + verbs: ["get", "list", "watch"], + }, + { + apiGroups: [""], + resources: ["events"], + verbs: ["create"], + }, + ], + }, + + rbWatcher: kube.RoleBinding("config-watcher") { + metadata+: { + namespace: cfg.namespace, + }, + subjects: [ + { kind: "ServiceAccount", name: env.saController.metadata.name }, + { kind: "ServiceAccount", name: env.saSpeaker.metadata.name }, + ], + roleRef: { + apiGroup: "rbac.authorization.k8s.io", + kind: "Role", + name: env.roleWatcher.metadata.name, + }, + }, + }, +}