blob: 5a8bf302ea5ffec69cbdebfa7e7b2462440beaa6 [file] [log] [blame]
Radek Pietruszewskif5844312023-10-27 22:41:18 +02001local kube = import "../../../kube/hscloud.libsonnet";
Serge Bazanski363bf4f2020-08-24 21:00:56 +02002
3{
4 // Global sets up a global tier instance of the hscloud monitoring infrastructure.
5 //
6 // This currently consists of Victoria Metrics, to which the agent tier sends metrics data via
7 // the prometheus remote_write protocol.
8 // Victoria Metrics is here used as a long-term storage solution. However, right now, it
9 // just keeps data locally on disk. In the future, S3 snapshots/backups should be introduced.
10 Global(name):: {
11 local global = self,
12 local cfg = global.cfg,
13
14 cfg:: {
15 name: name,
16 namespace: "monitoring-global-%s" % [cfg.name],
17
18 images: {
19 victoria: "victoriametrics/victoria-metrics:v1.40.0",
20 vmauth: "victoriametrics/vmauth:v1.40.0",
Serge Bazanski4f7caf82020-10-10 17:58:09 +020021 grafana: "grafana/grafana:7.2.1",
Serge Bazanski363bf4f2020-08-24 21:00:56 +020022 },
23
24 hosts: {
25 // DNS hostname that this global tier will use. Ingress will run under it.
26 globalAPI: error "hosts.globalAPI must be set",
Serge Bazanski4f7caf82020-10-10 17:58:09 +020027 globalDashboard: error "hosts.globalDashboard must be set",
Serge Bazanski363bf4f2020-08-24 21:00:56 +020028 },
29
30 storageClasses: {
31 // Storage class used for main data retention.
32 victoria: error "storageClasses.victoria must be set",
33 },
34
Serge Bazanski4f7caf82020-10-10 17:58:09 +020035 oauth: {
36 clientId: error "oauth.clientId must be set",
37 clientSecret: error "oauth.clientSecret must be set",
38 },
39
Serge Bazanski363bf4f2020-08-24 21:00:56 +020040 // A list of agents that will push metrics to this instance.
41 // List of:
42 // {
43 // username: the username that the agent will authenticate with
44 // password: the password that the agent will authenticate with
45 // }
46 agents: [],
47 },
48
49 // Generated URLs that agents should use to ship metrics over. Both require HTTP basic
50 // auth, configured via cfg.agents.
Serge Bazanski4f7caf82020-10-10 17:58:09 +020051 // The internal URL that should be used for agents colocated in the same Kubernetes cluster.
Serge Bazanski363bf4f2020-08-24 21:00:56 +020052 internalIngestURL:: "http://%s/api/v1/write" % [global.victoria.serviceAPI.host_colon_port],
Serge Bazanski4f7caf82020-10-10 17:58:09 +020053 // The internal URL that should be used for readers colocated in the same Kubernetes cluster.
54 internalReadURL:: "http://%s/" % [global.victoria.serviceAPI.host_colon_port],
55 // The global URL that should be used for agents sending data over the internet.
Serge Bazanski363bf4f2020-08-24 21:00:56 +020056 globalIngestURL:: "https://%s/api/v1/write" % [cfg.hosts.globalAPI],
Serge Bazanski4f7caf82020-10-10 17:58:09 +020057 // The global URL that should be used for readers over the internet.
58 globalReadURL:: "https://%s" % [cfg.hosts.globalAPI],
Serge Bazanski363bf4f2020-08-24 21:00:56 +020059
60 namespace: kube.Namespace(cfg.namespace),
61 local ns = global.namespace,
62
63 victoria: {
64 local victoria = self,
65
66 pvc: ns.Contain(kube.PersistentVolumeClaim("victoria-data")) {
radex36964dc2023-11-24 11:19:46 +010067 storage:: "64Gi",
68 storageClass:: cfg.storageClasses.victoria,
Serge Bazanski363bf4f2020-08-24 21:00:56 +020069 },
70
71 authSecret: ns.Contain(kube.Secret("vmauth")) {
72 data+: {
73 "config.yaml": std.base64(std.manifestJson({
74 users: [
75 {
76 username: a.username,
77 password: a.password,
78 url_prefix: "http://localhost:8428",
79 }
Serge Bazanski4f7caf82020-10-10 17:58:09 +020080 for a in (cfg.agents + [cfg.loopbackGrafanaUser])
Serge Bazanski363bf4f2020-08-24 21:00:56 +020081 ],
82 }) + "\n")
83 },
84 },
85
86 deploy: ns.Contain(kube.Deployment("victoria")) {
87 spec+: {
88 template+: {
89 spec+: {
90 containers_: {
91 default: kube.Container("default") {
92 image: cfg.images.victoria,
93 volumeMounts_: {
94 data: { mountPath: "/victoria-metrics-data", },
95 },
96 },
97 vmauth: kube.Container("vmauth") {
98 image: cfg.images.vmauth,
99 command: [
100 "/vmauth-prod",
101 "-auth.config", "/mnt/secret/config.yaml",
102 ],
103 volumeMounts_: {
104 secret: { mountPath: "/mnt/secret", },
105 },
106 ports_: {
107 api: { containerPort: 8427 }
108 },
109 }
110 },
111 volumes_: {
112 data: kube.PersistentVolumeClaimVolume(victoria.pvc),
113 secret: kube.SecretVolume(victoria.authSecret),
114 },
115 },
116 },
117 },
118 },
119
120 serviceAPI: ns.Contain(kube.Service("victoria-api")) {
radex8b8f3872023-11-24 11:09:46 +0100121 target:: victoria.deploy,
Serge Bazanski363bf4f2020-08-24 21:00:56 +0200122 spec+: {
123 ports: [
124 { name: "api", port: 8427, targetPort: 8427, protocol: "TCP" },
125 ],
126 type: "ClusterIP",
127 },
128 },
129
Radek Pietruszewskif5844312023-10-27 22:41:18 +0200130 ingressAPI: ns.Contain(kube.SimpleIngress("victoria-api")) {
131 hosts:: [cfg.hosts.globalAPI],
132 target_service:: victoria.serviceAPI,
Serge Bazanski363bf4f2020-08-24 21:00:56 +0200133 },
134 },
Serge Bazanski4f7caf82020-10-10 17:58:09 +0200135
136 grafana: {
137 local grafana = self,
138
139 // grafana.ini, serialized to secret.
140 ini:: {
141 sections: {
142 "auth": {
143 "disable_login_form": true,
144 "oauth_auto_login": true,
145 },
146 "security": {
147 # We do not disable basic auth, as we want to use builtin
148 # users as API users (eg for config reload), but we want
149 # to disable the default admin:admin user.
150 "disable_initial_admin_creation": true,
151 },
152 "auth.generic_oauth": {
153 enabled: true,
154 client_id: cfg.oauth.clientId,
155 client_secret: cfg.oauth.clientSecret,
Serge Bazanskicc2ff792021-01-30 17:26:47 +0100156 auth_url: "https://sso.hackerspace.pl/oauth/authorize",
157 token_url: "https://sso.hackerspace.pl/oauth/token",
158 api_url: "https://sso.hackerspace.pl/api/1/userinfo",
Serge Bazanski4f7caf82020-10-10 17:58:09 +0200159 scopes: "openid",
160 email_attribute_path: "email",
161 allow_sign_up: true,
162 role_attribute_path: "contains(groups, 'grafana-admin')",
163 },
164 "server": {
165 domain: cfg.hosts.globalDashboard,
166 root_url: "https://%s/" % [ cfg.hosts.globalDashboard ],
167 },
168 },
169 },
170
171 datasources:: {
172 apiVersion: 1,
173 datasources: [
174 {
175 name: "victoria-global",
176 type: "prometheus",
177 uid: "victoria-global",
178 isDefault: true,
179 url: global.internalReadURL,
180 basicAuth: true,
181 basicAuthUser: cfg.loopbackGrafanaUser.username,
182 secureJsonData: {
183 basicAuthPassword: cfg.loopbackGrafanaUser.password,
184 },
185 },
186 ],
187 },
188
189 config: ns.Contain(kube.Secret("grafana-config")) {
190 data+: {
191 "grafana.ini": std.base64(std.manifestIni(grafana.ini)),
192 "datasources.yaml": std.base64(std.manifestYamlDoc(grafana.datasources)),
193 },
194 },
195
196 pvc: ns.Contain(kube.PersistentVolumeClaim("grafana-data")) {
radex36964dc2023-11-24 11:19:46 +0100197 storage:: "8Gi",
198 storageClass:: cfg.storageClasses.grafana,
Serge Bazanski4f7caf82020-10-10 17:58:09 +0200199 },
200
201 deploy: ns.Contain(kube.Deployment("grafana")) {
202 spec+: {
203 template+: {
204 spec+: {
205 containers_: {
206 default: kube.Container("default") {
207 image: cfg.images.grafana,
208 ports_: {
209 public: { containerPort: 3000 },
210 },
211 env_: {
212 GF_PATHS_CONFIG: "/etc/hscloud-config/grafana.ini",
213 GF_PATHS_PROVISIONING: "/etc/hscloud-config/provisioning",
214 GF_PATHS_DATA: "/var/lib/grafana",
215 },
216 volumeMounts_: {
217 config: { mountPath: "/etc/hscloud-config", },
218 data: { mountPath: "/var/lib/grafana", },
219 },
220 resources: {
221 requests: { cpu: "100m", memory: "256M", },
222 limits: { cpu: "200m", memory: "512M", },
223 },
224 },
225 },
226 volumes_: {
227 data: kube.PersistentVolumeClaimVolume(grafana.pvc),
228 config: kube.SecretVolume(grafana.config) {
229 secret+: {
230 items: [
231 { key: "grafana.ini", path: "grafana.ini", },
232 { key: "datasources.yaml", path: "provisioning/datasources/datasources.yaml", },
233 ],
234 },
235 },
236 },
237 },
238 },
239 },
240 },
241
242 service: ns.Contain(kube.Service("grafana-public")) {
radex8b8f3872023-11-24 11:09:46 +0100243 target:: grafana.deploy,
Serge Bazanski4f7caf82020-10-10 17:58:09 +0200244 spec+: {
245 ports: [
246 { name: "public", port: 3000, targetPort: 3000, protocol: "TCP" },
247 ],
248 },
249 },
250
Radek Pietruszewskif5844312023-10-27 22:41:18 +0200251 ingress: ns.Contain(kube.SimpleIngress("grafana-public")) {
252 hosts:: [cfg.hosts.globalDashboard],
253 target_service:: grafana.service,
Serge Bazanski4f7caf82020-10-10 17:58:09 +0200254 },
255 },
Serge Bazanski363bf4f2020-08-24 21:00:56 +0200256 }
257}