blob: 09c3b333659f545e05ed91d16a9ae283effd9e9a [file] [log] [blame]
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +01001# Top level cluster configuration.
2
3local kube = import "../../kube/kube.libsonnet";
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +02004local policies = import "../../kube/policies.libsonnet";
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +02005
Sergiusz Bazanskiaf3be422019-01-17 18:57:19 +01006local calico = import "lib/calico.libsonnet";
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +02007local certmanager = import "lib/cert-manager.libsonnet";
8local cockroachdb = import "lib/cockroachdb.libsonnet";
9local coredns = import "lib/coredns.libsonnet";
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +010010local metallb = import "lib/metallb.libsonnet";
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +020011local metrics = import "lib/metrics.libsonnet";
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +020012local nginx = import "lib/nginx.libsonnet";
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020013local prodvider = import "lib/prodvider.libsonnet";
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020014local registry = import "lib/registry.libsonnet";
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020015local rook = import "lib/rook.libsonnet";
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +010016
17local Cluster(fqdn) = {
18 local cluster = self,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +020019 local cfg = cluster.cfg,
20
21 cfg:: {
22 // Storage class used for internal services (like registry). This must
23 // be set to a valid storage class. This can either be a cloud provider class
24 // (when running on GKE &co) or a storage class created using rook.
25 storageClassNameRedundant: error "storageClassNameRedundant must be set",
26 },
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +010027
28 // These are required to let the API Server contact kubelets.
29 crAPIServerToKubelet: kube.ClusterRole("system:kube-apiserver-to-kubelet") {
30 metadata+: {
31 annotations+: {
32 "rbac.authorization.kubernetes.io/autoupdate": "true",
33 },
34 labels+: {
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020035 "kubernetes.io/bootstrapping": "rbac-defaults",
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +010036 },
37 },
38 rules: [
39 {
40 apiGroups: [""],
41 resources: ["nodes/%s" % r for r in [ "proxy", "stats", "log", "spec", "metrics" ]],
42 verbs: ["*"],
43 },
44 ],
45 },
Sergiusz Bazanski5bebbeb2019-01-13 22:08:05 +010046 crbAPIServer: kube.ClusterRoleBinding("system:kube-apiserver") {
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +010047 roleRef: {
48 apiGroup: "rbac.authorization.k8s.io",
49 kind: "ClusterRole",
50 name: cluster.crAPIServerToKubelet.metadata.name,
51 },
52 subjects: [
53 {
54 apiGroup: "rbac.authorization.k8s.io",
55 kind: "User",
56 # A cluster API Server authenticates with a certificate whose CN is == to the FQDN of the cluster.
57 name: fqdn,
58 },
59 ],
Sergiusz Bazanski49b9a132019-01-14 00:02:59 +010060 },
61
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020062 // This ClusteRole is bound to all humans that log in via prodaccess/prodvider/SSO.
63 // It should allow viewing of non-sensitive data for debugability and openness.
64 crViewer: kube.ClusterRole("system:viewer") {
65 rules: [
66 {
67 apiGroups: [""],
68 resources: [
69 "nodes",
70 "namespaces",
71 "pods",
72 "configmaps",
73 "services",
74 ],
75 verbs: ["list"],
76 },
77 {
78 apiGroups: ["metrics.k8s.io"],
79 resources: [
80 "nodes",
81 "pods",
82 ],
83 verbs: ["list"],
84 },
85 {
86 apiGroups: ["apps"],
87 resources: [
88 "statefulsets",
89 ],
90 verbs: ["list"],
91 },
92 {
93 apiGroups: ["extensions"],
94 resources: [
95 "deployments",
96 "ingresses",
97 ],
98 verbs: ["list"],
99 }
100 ],
101 },
102 // This ClusterRole is applied (scoped to personal namespace) to all humans.
103 crFullInNamespace: kube.ClusterRole("system:admin-namespace") {
104 rules: [
105 {
106 apiGroups: ["*"],
107 resources: ["*"],
108 verbs: ["*"],
109 },
110 ],
111 },
112 // This ClusterRoleBindings allows root access to cluster admins.
113 crbAdmins: kube.ClusterRoleBinding("system:admins") {
114 roleRef: {
115 apiGroup: "rbac.authorization.k8s.io",
116 kind: "ClusterRole",
117 name: "cluster-admin",
118 },
119 subjects: [
120 {
121 apiGroup: "rbac.authorization.k8s.io",
122 kind: "User",
123 name: user + "@hackerspace.pl",
124 } for user in [
125 "q3k",
126 "implr",
127 "informatic",
128 ]
129 ],
130 },
131
132 podSecurityPolicies: policies.Cluster {},
133
134 allowInsecureNamespaces: [
135 policies.AllowNamespaceInsecure("kube-system"),
136 # TODO(q3k): fix this?
137 policies.AllowNamespaceInsecure("ceph-waw2"),
Sergiusz Bazanski5f3a5e02019-09-25 02:51:51 +0200138 policies.AllowNamespaceInsecure("matrix"),
139 policies.AllowNamespaceInsecure("registry"),
140 policies.AllowNamespaceInsecure("internet"),
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +0200141 ],
142
143 // Allow all service accounts (thus all controllers) to create secure pods.
144 crbAllowServiceAccountsSecure: kube.ClusterRoleBinding("policy:allow-all-secure") {
145 roleRef_: cluster.podSecurityPolicies.secureRole,
146 subjects: [
147 {
148 kind: "Group",
149 apiGroup: "rbac.authorization.k8s.io",
150 name: "system:serviceaccounts",
151 }
152 ],
153 },
154
Sergiusz Bazanskiaf3be422019-01-17 18:57:19 +0100155 // Calico network fabric
156 calico: calico.Environment {},
Sergiusz Bazanski49b9a132019-01-14 00:02:59 +0100157 // CoreDNS for this cluster.
Sergiusz Bazanskiaf3be422019-01-17 18:57:19 +0100158 dns: coredns.Environment {},
159 // Metrics Server
160 metrics: metrics.Environment {},
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +0100161 // Metal Load Balancer
Sergiusz Bazanski14cbacb2019-04-01 18:00:44 +0200162 metallb: metallb.Environment {
163 cfg+: {
164 addressPools: [
165 { name: "public-v4-1", protocol: "layer2", addresses: ["185.236.240.50-185.236.240.63"] },
166 ],
167 },
168 },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200169 // Main nginx Ingress Controller
170 nginx: nginx.Environment {},
Piotr Dobrowolski79ddbc52019-04-02 13:20:15 +0200171 certmanager: certmanager.Environment {},
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200172 issuer: certmanager.ClusterIssuer("letsencrypt-prod") {
173 spec: {
174 acme: {
175 server: "https://acme-v02.api.letsencrypt.org/directory",
176 email: "bofh@hackerspace.pl",
177 privateKeySecretRef: {
178 name: "letsencrypt-prod"
179 },
180 http01: {},
181 },
182 },
183 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200184
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200185 // Rook Ceph storage
Sergiusz Bazanskic3b0f762019-06-20 16:42:19 +0200186 rook: rook.Operator {
187 operator+: {
188 spec+: {
189 // TODO(q3k): Bring up the operator again when stability gets fixed
190 // See: https://github.com/rook/rook/issues/3059#issuecomment-492378873
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200191 replicas: 1,
Sergiusz Bazanskic3b0f762019-06-20 16:42:19 +0200192 },
193 },
194 },
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200195
196 // Docker registry
197 registry: registry.Environment {
198 cfg+: {
199 domain: "registry.%s" % [fqdn],
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200200 storageClassName: cfg.storageClassNameParanoid,
201 objectStorageName: "waw-hdd-redundant-2-object",
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200202 },
203 },
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +0200204
205 // Prodvider
206 prodvider: prodvider.Environment {},
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +0100207};
208
Sergiusz Bazanski49b9a132019-01-14 00:02:59 +0100209
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +0100210{
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200211 k0: {
212 local k0 = self,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200213 cluster: Cluster("k0.hswaw.net") {
214 cfg+: {
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200215 storageClassNameParanoid: k0.ceph.blockParanoid.name,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200216 },
217 },
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200218 cockroach: {
Sergiusz Bazanskid5338922019-08-09 14:13:50 +0200219 waw2: cockroachdb.Cluster("crdb-waw1") {
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200220 cfg+: {
221 topology: [
Sergiusz Bazanski184678b2019-06-22 02:07:41 +0200222 { name: "bc01n01", node: "bc01n01.hswaw.net" },
223 { name: "bc01n02", node: "bc01n02.hswaw.net" },
224 { name: "bc01n03", node: "bc01n03.hswaw.net" },
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200225 ],
Sergiusz Bazanskid5338922019-08-09 14:13:50 +0200226 hostPath: "/var/db/crdb-waw1",
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200227 },
228 },
Sergiusz Bazanski1fad2e52019-08-01 20:16:27 +0200229 clients: {
230 cccampix: k0.cockroach.waw2.Client("cccampix"),
231 cccampixDev: k0.cockroach.waw2.Client("cccampix-dev"),
232 },
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200233 },
234 ceph: {
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200235 // waw1 cluster - dead as of 2019/08/06, data corruption
236 // waw2 cluster
237 waw2: rook.Cluster(k0.cluster.rook, "ceph-waw2") {
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200238 spec: {
239 mon: {
240 count: 3,
241 allowMultiplePerNode: false,
242 },
243 storage: {
244 useAllNodes: false,
245 useAllDevices: false,
246 config: {
247 databaseSizeMB: "1024",
248 journalSizeMB: "1024",
249 },
250 nodes: [
251 {
252 name: "bc01n01.hswaw.net",
253 location: "rack=dcr01 chassis=bc01 host=bc01n01",
254 devices: [ { name: "sda" } ],
255 },
256 {
257 name: "bc01n02.hswaw.net",
258 location: "rack=dcr01 chassis=bc01 host=bc01n02",
259 devices: [ { name: "sda" } ],
260 },
261 {
262 name: "bc01n03.hswaw.net",
263 location: "rack=dcr01 chassis=bc01 host=bc01n03",
264 devices: [ { name: "sda" } ],
265 },
266 ],
267 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200268 benji:: {
269 metadataStorageClass: "waw-hdd-paranoid-2",
270 encryptionPassword: std.split((importstr "../secrets/plain/k0-benji-encryption-password"), '\n')[0],
271 pools: [
272 "waw-hdd-redundant-2",
273 "waw-hdd-redundant-2-metadata",
274 "waw-hdd-paranoid-2",
275 "waw-hdd-yolo-2",
276 ],
277 s3Configuration: {
278 awsAccessKeyId: "RPYZIROFXNLQVU2WJ4R3",
279 awsSecretAccessKey: std.split((importstr "../secrets/plain/k0-benji-secret-access-key"), '\n')[0],
280 bucketName: "benji-k0-backups",
281 endpointUrl: "https://s3.eu-central-1.wasabisys.com/",
282 },
283 }
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200284 },
285 },
286 // redundant block storage
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200287 blockRedundant: rook.ECBlockPool(k0.ceph.waw2, "waw-hdd-redundant-2") {
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200288 spec: {
289 failureDomain: "host",
290 erasureCoded: {
291 dataChunks: 2,
292 codingChunks: 1,
293 },
294 },
295 },
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200296 // paranoid block storage (3 replicas)
297 blockParanoid: rook.ReplicatedBlockPool(k0.ceph.waw2, "waw-hdd-paranoid-2") {
298 spec: {
299 failureDomain: "host",
300 replicated: {
301 size: 3,
302 },
303 },
304 },
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200305 // yolo block storage (no replicas!)
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200306 blockYolo: rook.ReplicatedBlockPool(k0.ceph.waw2, "waw-hdd-yolo-2") {
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200307 spec: {
308 failureDomain: "host",
309 replicated: {
310 size: 1,
311 },
312 },
313 },
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200314 objectRedundant: rook.S3ObjectStore(k0.ceph.waw2, "waw-hdd-redundant-2-object") {
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200315 spec: {
316 metadataPool: {
317 failureDomain: "host",
318 replicated: { size: 3 },
319 },
320 dataPool: {
321 failureDomain: "host",
322 erasureCoded: {
323 dataChunks: 2,
324 codingChunks: 1,
325 },
326 },
327 },
328 },
329 },
Sergiusz Bazanski9496d992019-09-02 16:32:40 +0200330
331 # Used for owncloud.hackerspace.pl, which for now lices on boston-packets.hackerspace.pl.
332 nextcloud: kube._Object("ceph.rook.io/v1", "CephObjectStoreUser", "nextcloud") {
333 metadata+: {
334 namespace: "ceph-waw2",
335 },
336 spec: {
337 store: "waw-hdd-redundant-2-object",
338 displayName: "nextcloud",
339 },
340 },
Sergiusz Bazanskic7258f42019-06-21 00:24:09 +0200341 },
Sergiusz Bazanski4d9e72c2019-01-13 22:06:33 +0100342}