blob: 1826b0c5d922424176b89cc6d978bc52dc1fa324 [file] [log] [blame]
Sergiusz Bazanskidbfa9882020-06-06 01:21:45 +02001# Common cluster configuration.
2# This defines what Kubernetes resources are required to turn a bare k8s
3# deployment into a fully working cluster.
4# These assume that you're running on bare metal, and using the corresponding
5# NixOS deployment that we do.
6
7local kube = import "../../kube/kube.libsonnet";
8local policies = import "../../kube/policies.libsonnet";
9
10local calico = import "lib/calico.libsonnet";
11local certmanager = import "lib/cert-manager.libsonnet";
12local coredns = import "lib/coredns.libsonnet";
13local metallb = import "lib/metallb.libsonnet";
14local metrics = import "lib/metrics.libsonnet";
15local nginx = import "lib/nginx.libsonnet";
16local prodvider = import "lib/prodvider.libsonnet";
17local rook = import "lib/rook.libsonnet";
18local pki = import "lib/pki.libsonnet";
19
20{
21 Cluster(short, realm):: {
22 local cluster = self,
23 local cfg = cluster.cfg,
24
25 short:: short,
26 realm:: realm,
27 fqdn:: "%s.%s" % [cluster.short, cluster.realm],
28
29 cfg:: {
30 // Storage class used for internal services (like registry). This must
31 // be set to a valid storage class. This can either be a cloud provider class
32 // (when running on GKE &co) or a storage class created using rook.
33 storageClassNameRedundant: error "storageClassNameRedundant must be set",
34 },
35
36 // These are required to let the API Server contact kubelets.
37 crAPIServerToKubelet: kube.ClusterRole("system:kube-apiserver-to-kubelet") {
38 metadata+: {
39 annotations+: {
40 "rbac.authorization.kubernetes.io/autoupdate": "true",
41 },
42 labels+: {
43 "kubernetes.io/bootstrapping": "rbac-defaults",
44 },
45 },
46 rules: [
47 {
48 apiGroups: [""],
49 resources: ["nodes/%s" % r for r in [ "proxy", "stats", "log", "spec", "metrics" ]],
50 verbs: ["*"],
51 },
52 ],
53 },
54 crbAPIServer: kube.ClusterRoleBinding("system:kube-apiserver") {
55 roleRef: {
56 apiGroup: "rbac.authorization.k8s.io",
57 kind: "ClusterRole",
58 name: cluster.crAPIServerToKubelet.metadata.name,
59 },
60 subjects: [
61 {
62 apiGroup: "rbac.authorization.k8s.io",
63 kind: "User",
64 # A cluster API Server authenticates with a certificate whose CN is == to the FQDN of the cluster.
65 name: cluster.fqdn,
66 },
67 ],
68 },
69
70 // This ClusterRole is bound to all humans that log in via prodaccess/prodvider/SSO.
71 // It should allow viewing of non-sensitive data for debugability and openness.
72 crViewer: kube.ClusterRole("system:viewer") {
73 rules: [
74 {
75 apiGroups: [""],
76 resources: [
77 "nodes",
78 "namespaces",
79 "pods",
80 "configmaps",
81 "services",
82 ],
83 verbs: ["list"],
84 },
85 {
86 apiGroups: ["metrics.k8s.io"],
87 resources: [
88 "nodes",
89 "pods",
90 ],
91 verbs: ["list"],
92 },
93 {
94 apiGroups: ["apps"],
95 resources: [
96 "statefulsets",
97 ],
98 verbs: ["list"],
99 },
100 {
101 apiGroups: ["extensions"],
102 resources: [
103 "deployments",
104 "ingresses",
105 ],
106 verbs: ["list"],
107 }
108 ],
109 },
110 // This ClusterRole is applied (scoped to personal namespace) to all humans.
111 crFullInNamespace: kube.ClusterRole("system:admin-namespace") {
112 rules: [
113 {
114 apiGroups: ["", "extensions", "apps"],
115 resources: ["*"],
116 verbs: ["*"],
117 },
118 {
119 apiGroups: ["batch"],
120 resources: ["jobs", "cronjobs"],
121 verbs: ["*"],
122 },
Serge Bazanskif40c9242021-02-07 19:23:43 +0000123 {
124 apiGroups: ["networking.k8s.io"],
125 resources: ["ingresses"],
126 verbs: ["*"],
127 },
Sergiusz Bazanskidbfa9882020-06-06 01:21:45 +0200128 ],
129 },
130 // This ClusterRoleBindings allows root access to cluster admins.
131 crbAdmins: kube.ClusterRoleBinding("system:admins") {
132 roleRef: {
133 apiGroup: "rbac.authorization.k8s.io",
134 kind: "ClusterRole",
135 name: "cluster-admin",
136 },
137 subjects: [
138 {
139 apiGroup: "rbac.authorization.k8s.io",
140 kind: "User",
141 name: user + "@hackerspace.pl",
142 } for user in [
143 "q3k",
144 "implr",
145 "informatic",
146 ]
147 ],
148 },
149
150 podSecurityPolicies: policies.Cluster {},
151
152 allowInsecureNamespaces: [
153 policies.AllowNamespaceInsecure("kube-system"),
154 policies.AllowNamespaceInsecure("metallb-system"),
155 ],
156
157 // Allow all service accounts (thus all controllers) to create secure pods.
158 crbAllowServiceAccountsSecure: kube.ClusterRoleBinding("policy:allow-all-secure") {
159 roleRef_: cluster.podSecurityPolicies.secureRole,
160 subjects: [
161 {
162 kind: "Group",
163 apiGroup: "rbac.authorization.k8s.io",
164 name: "system:serviceaccounts",
165 }
166 ],
167 },
168
169 // Calico network fabric
170 calico: calico.Environment {},
171
172 // CoreDNS for this cluster.
173 dns: coredns.Environment {
174 cfg+: {
175 cluster_domains: [
176 "cluster.local",
177 cluster.fqdn,
178 ],
179 },
180 },
181
182 // Metrics Server
183 metrics: metrics.Environment {},
184
185 // Metal Load Balancer
186 metallb: metallb.Environment {},
187
188 // Main nginx Ingress Controller
189 nginx: nginx.Environment {},
190
191 // Cert-manager (Let's Encrypt, CA, ...)
192 certmanager: certmanager.Environment {},
193
194 issuer: kube.ClusterIssuer("letsencrypt-prod") {
195 spec: {
196 acme: {
197 server: "https://acme-v02.api.letsencrypt.org/directory",
198 email: "bofh@hackerspace.pl",
199 privateKeySecretRef: {
200 name: "letsencrypt-prod"
201 },
202 http01: {},
203 },
204 },
205 },
206
207 // Rook Ceph storage operator.
208 rook: rook.Operator {
209 operator+: {
210 spec+: {
211 replicas: 1,
212 },
213 },
214 },
215
216 // TLS PKI machinery (compatibility with mirko)
217 pki: pki.Environment(cluster.short, cluster.realm),
218
219 // Prodvider
220 prodvider: prodvider.Environment {
221 cfg+: {
222 apiEndpoint: "kubernetes.default.svc.%s" % [cluster.fqdn],
223 },
224 },
225 },
226}