72 |
73 |
74 | Últimas senhas criadas
75 |
76 |
77 |
82 | {% include 'lista_senhas.html' %}
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/app/melange-giropops-senhas/templates/lista_senhas.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% for senha_gerada in senhas_geradas %}
4 | -
5 |
6 |
13 |
14 |
23 |
30 |
31 |
32 |
33 | {% endfor %}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "javascript"
5 |
6 | [[analyzers]]
7 | name = "python"
8 |
9 | [analyzers.meta]
10 | runtime_version = "3.x.x"
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.11-slim
2 |
3 | WORKDIR /app
4 |
5 | COPY requirements.txt .
6 | COPY app.py .
7 | COPY templates templates/
8 | COPY static static/
9 |
10 | RUN pip install --no-cache-dir -r requirements.txt
11 |
12 | EXPOSE 5000
13 |
14 | CMD ["flask", "run", "--host=0.0.0.0"]
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, render_template, request, jsonify
2 | import logging
3 | import os
4 | from prometheus_client import Counter, Histogram, Gauge, start_http_server, generate_latest
5 | import random
6 | import redis
7 | import socket
8 | import string
9 | import time
10 |
11 | app = Flask(__name__,
12 | template_folder='./templates',
13 | static_folder='./static')
14 |
15 | redis_host = os.environ.get('REDIS_HOST', 'redis-service')
16 | redis_port = 6379
17 | redis_password = ""
18 |
19 | senha_gerada_counter = Counter('senha_gerada', 'Contador de senhas geradas')
20 | senha_gerada_numeros_counter = Counter('senha_gerada_numeros', 'Contador de senhas geradas com números')
21 | senha_gerada_caracteres_especiais_counter = Counter('senha_gerada_caracteres_especiais', 'Contador de senhas geradas com caracteres especiais')
22 | senha_gerada_sem_caracteres_especiais_counter = Counter('senha_gerada_sem_caracteres_especiais', 'Contador de senhas geradas sem caracteres especiais')
23 | senha_gerada_sem_numeros_counter = Counter('senha_gerada_sem_numeros', 'Contador de senhas geradas sem números')
24 | redis_connection_error_counter = Counter('redis_connection_errors', 'Contador de erros de conexão com Redis')
25 | tempo_gerar_senha_histogram = Histogram('tempo_gerar_senha', 'Tempo para gerar uma senha')
26 | tempo_resposta_api_histogram = Histogram('tempo_resposta_api', 'Tempo de resposta da API')
27 | api_erro_counter = Counter('api_errors', 'Contador de erros de API', ['endpoint', 'status_code'])
28 | tamanho_fila_senhas_gauge = Gauge('tamanho_fila_senhas', 'Tamanho da fila de senhas no Redis')
29 |
30 | try:
31 | r = redis.StrictRedis(host=redis_host, port=redis_port, password=redis_password, decode_responses=True)
32 | r.ping()
33 | except redis.ConnectionError:
34 | logging.error("Erro ao conectar ao Redis")
35 | redis_connection_error_counter.inc()
36 | r = None
37 |
38 | def criar_senha(tamanho, incluir_numeros, incluir_caracteres_especiais):
39 | caracteres = string.ascii_letters
40 |
41 | if incluir_numeros:
42 | caracteres += string.digits
43 | senha_gerada_numeros_counter.inc()
44 |
45 | if incluir_caracteres_especiais:
46 | caracteres += string.punctuation
47 | senha_gerada_caracteres_especiais_counter.inc()
48 | else:
49 | senha_gerada_sem_caracteres_especiais_counter.inc()
50 |
51 | senha = ''.join(random.choices(caracteres, k=tamanho))
52 |
53 | if not any(char.isdigit() for char in senha):
54 | senha_gerada_sem_numeros_counter.inc()
55 |
56 | return senha
57 |
58 | @app.route('/', methods=['GET', 'POST'])
59 | def index():
60 | if request.method == 'POST':
61 | tamanho = int(request.form.get('tamanho', 8))
62 | incluir_numeros = request.form.get('incluir_numeros') == 'on'
63 | incluir_caracteres_especiais = request.form.get('incluir_caracteres_especiais') == 'on'
64 |
65 | #Medir time de gerar uma senha:
66 | start_time = time.time()
67 | senha = criar_senha(tamanho, incluir_numeros, incluir_caracteres_especiais)
68 | tempo_gerar_senha_histogram.observe(time.time() - start_time)
69 |
70 | if r:
71 | r.lpush("senhas", senha)
72 | senha_gerada_counter.inc()
73 |
74 | senhas = r.lrange("senhas", 0, 9) if r else []
75 | if senhas:
76 | senhas_geradas = [{"id": index + 1, "senha": senha} for index, senha in enumerate(senhas)]
77 | return render_template('index.html', senhas_geradas=senhas_geradas, senha=senhas_geradas[0]['senha'] or '' )
78 | return render_template('index.html')
79 |
80 |
81 | @app.route('/api/gerar-senha', methods=['POST'])
82 | @tempo_resposta_api_histogram.time()
83 | def gerar_senha_api():
84 | dados = request.get_json()
85 |
86 | tamanho = int(dados.get('tamanho', 8))
87 | incluir_numeros = dados.get('incluir_numeros', False)
88 | incluir_caracteres_especiais = dados.get('incluir_caracteres_especiais', False)
89 |
90 | start_time = time.time()
91 | try:
92 | senha = criar_senha(tamanho, incluir_numeros, incluir_caracteres_especiais)
93 | tempo_gerar_senha_histogram.observe(time.time() - start_time)
94 | if r:
95 | r.lpush("senhas", senha)
96 | senha_gerada_counter.inc()
97 | return jsonify({"senha": senha}), 200
98 | except Exception as e:
99 | api_erro_counter.labels(endpoint='/api/gerar-senha', status_code='500').inc()
100 | logging.error(f"Erro na API /api/gerar-senha: {str(e)}", exc_info=True)
101 | return jsonify({"error": "Erro ao gerar senha"}), 500
102 |
103 | @app.route('/api/senhas', methods=['GET'])
104 | @tempo_resposta_api_histogram.time()
105 | def listar_senhas():
106 | try:
107 | senhas = r.lrange("senhas", 0, 9) if r else []
108 | tamanho_fila_senhas_gauge.set(len(senhas))
109 |
110 | resposta = [{"id": index + 1, "senha": senha} for index, senha in enumerate(senhas)]
111 | return jsonify(resposta)
112 | except Exception as e:
113 | api_erro_counter.labels(endpoint='/api/senhas', status_code='500').inc()
114 | logging.error(f"Erro na API /api/senhas: {str(e)}", exc_info=True)
115 | return jsonify({"error": "Erro ao listar senhas"}), 500
116 |
117 | @app.route('/metrics')
118 | def metrics():
119 | return generate_latest()
120 |
121 | def start_prometheus_server(port):
122 | try:
123 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
124 | s.settimeout(1)
125 | if s.connect_ex(('0.0.0.0', port)) == 0:
126 | logging.error(f"Porta {port} já está em uso. Não será possível iniciar Prometheus.")
127 | return False
128 |
129 | start_http_server(port)
130 | return True
131 | except Exception as e:
132 | logging.error(f"Erro ao tentar iniciar Prometheus: {str(e)}", exc_info=True)
133 | return False
134 |
135 | if __name__ == '__main__':
136 | logging.basicConfig(filename='tmp/error.log', level=logging.DEBUG)
137 | port = 8089
138 | app.run(host='0.0.0.0', debug=False)
139 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==3.0.3
2 | redis==4.5.4
3 | prometheus-client==0.16.0
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/static/css/output.css:
--------------------------------------------------------------------------------
1 | /* styles.css */
2 |
3 | /* ! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com */
4 |
5 | /*
6 | 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
7 | 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
8 | */
9 |
10 | *,
11 | ::before,
12 | ::after {
13 | box-sizing: border-box;
14 | /* 1 */
15 | border-width: 0;
16 | /* 2 */
17 | border-style: solid;
18 | /* 2 */
19 | border-color: #e5e7eb;
20 | /* 2 */
21 | }
22 |
23 | ::before,
24 | ::after {
25 | --tw-content: '';
26 | }
27 |
28 | /*
29 | 1. Use a consistent sensible line-height in all browsers.
30 | 2. Prevent adjustments of font size after orientation changes in iOS.
31 | 3. Use a more readable tab size.
32 | 4. Use the user's configured `sans` font-family by default.
33 | 5. Use the user's configured `sans` font-feature-settings by default.
34 | */
35 |
36 | html {
37 | line-height: 1.5;
38 | /* 1 */
39 | -webkit-text-size-adjust: 100%;
40 | /* 2 */
41 | -moz-tab-size: 4;
42 | /* 3 */
43 | -o-tab-size: 4;
44 | tab-size: 4;
45 | /* 3 */
46 | font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
47 | /* 4 */
48 | font-feature-settings: normal;
49 | /* 5 */
50 | }
51 |
52 | /*
53 | 1. Remove the margin in all browsers.
54 | 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
55 | */
56 |
57 | body {
58 | margin: 0;
59 | /* 1 */
60 | line-height: inherit;
61 | /* 2 */
62 | }
63 |
64 | /*
65 | 1. Add the correct height in Firefox.
66 | 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
67 | 3. Ensure horizontal rules are visible by default.
68 | */
69 |
70 | hr {
71 | height: 0;
72 | /* 1 */
73 | color: inherit;
74 | /* 2 */
75 | border-top-width: 1px;
76 | /* 3 */
77 | }
78 |
79 | /*
80 | Add the correct text decoration in Chrome, Edge, and Safari.
81 | */
82 |
83 | abbr:where([title]) {
84 | -webkit-text-decoration: underline dotted;
85 | text-decoration: underline dotted;
86 | }
87 |
88 | /*
89 | Remove the default font size and weight for headings.
90 | */
91 |
92 | h1,
93 | h2,
94 | h3,
95 | h4,
96 | h5,
97 | h6 {
98 | font-size: inherit;
99 | font-weight: inherit;
100 | }
101 |
102 | /*
103 | Reset links to optimize for opt-in styling instead of opt-out.
104 | */
105 |
106 | a {
107 | color: inherit;
108 | text-decoration: inherit;
109 | }
110 |
111 | /*
112 | Add the correct font weight in Edge and Safari.
113 | */
114 |
115 | b,
116 | strong {
117 | font-weight: bolder;
118 | }
119 |
120 | /*
121 | 1. Use the user's configured `mono` font family by default.
122 | 2. Correct the odd `em` font sizing in all browsers.
123 | */
124 |
125 | code,
126 | kbd,
127 | samp,
128 | pre {
129 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
130 | /* 1 */
131 | font-size: 1em;
132 | /* 2 */
133 | }
134 |
135 | /*
136 | Add the correct font size in all browsers.
137 | */
138 |
139 | small {
140 | font-size: 80%;
141 | }
142 |
143 | /*
144 | Prevent `sub` and `sup` elements from affecting the line height in all browsers.
145 | */
146 |
147 | sub,
148 | sup {
149 | font-size: 75%;
150 | line-height: 0;
151 | position: relative;
152 | vertical-align: baseline;
153 | }
154 |
155 | sub {
156 | bottom: -0.25em;
157 | }
158 |
159 | sup {
160 | top: -0.5em;
161 | }
162 |
163 | /*
164 | 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
165 | 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
166 | 3. Remove gaps between table borders by default.
167 | */
168 |
169 | table {
170 | text-indent: 0;
171 | /* 1 */
172 | border-color: inherit;
173 | /* 2 */
174 | border-collapse: collapse;
175 | /* 3 */
176 | }
177 |
178 | /*
179 | 1. Change the font styles in all browsers.
180 | 2. Remove the margin in Firefox and Safari.
181 | 3. Remove default padding in all browsers.
182 | */
183 |
184 | button,
185 | input,
186 | optgroup,
187 | select,
188 | textarea {
189 | font-family: inherit;
190 | /* 1 */
191 | font-size: 100%;
192 | /* 1 */
193 | font-weight: inherit;
194 | /* 1 */
195 | line-height: inherit;
196 | /* 1 */
197 | color: inherit;
198 | /* 1 */
199 | margin: 0;
200 | /* 2 */
201 | padding: 0;
202 | /* 3 */
203 | }
204 |
205 | /*
206 | Remove the inheritance of text transform in Edge and Firefox.
207 | */
208 |
209 | button,
210 | select {
211 | text-transform: none;
212 | }
213 |
214 | /*
215 | 1. Correct the inability to style clickable types in iOS and Safari.
216 | 2. Remove default button styles.
217 | */
218 |
219 | button,
220 | [type='button'],
221 | [type='reset'],
222 | [type='submit'] {
223 | -webkit-appearance: button;
224 | /* 1 */
225 | background-color: transparent;
226 | /* 2 */
227 | background-image: none;
228 | /* 2 */
229 | }
230 |
231 | /*
232 | Use the modern Firefox focus style for all focusable elements.
233 | */
234 |
235 | :-moz-focusring {
236 | outline: auto;
237 | }
238 |
239 | /*
240 | Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
241 | */
242 |
243 | :-moz-ui-invalid {
244 | box-shadow: none;
245 | }
246 |
247 | /*
248 | Add the correct vertical alignment in Chrome and Firefox.
249 | */
250 |
251 | progress {
252 | vertical-align: baseline;
253 | }
254 |
255 | /*
256 | Correct the cursor style of increment and decrement buttons in Safari.
257 | */
258 |
259 | ::-webkit-inner-spin-button,
260 | ::-webkit-outer-spin-button {
261 | height: auto;
262 | }
263 |
264 | /*
265 | 1. Correct the odd appearance in Chrome and Safari.
266 | 2. Correct the outline style in Safari.
267 | */
268 |
269 | [type='search'] {
270 | -webkit-appearance: textfield;
271 | /* 1 */
272 | outline-offset: -2px;
273 | /* 2 */
274 | }
275 |
276 | /*
277 | Remove the inner padding in Chrome and Safari on macOS.
278 | */
279 |
280 | ::-webkit-search-decoration {
281 | -webkit-appearance: none;
282 | }
283 |
284 | /*
285 | 1. Correct the inability to style clickable types in iOS and Safari.
286 | 2. Change font properties to `inherit` in Safari.
287 | */
288 |
289 | ::-webkit-file-upload-button {
290 | -webkit-appearance: button;
291 | /* 1 */
292 | font: inherit;
293 | /* 2 */
294 | }
295 |
296 | /*
297 | Add the correct display in Chrome and Safari.
298 | */
299 |
300 | summary {
301 | display: list-item;
302 | }
303 |
304 | /*
305 | Removes the default spacing and border for appropriate elements.
306 | */
307 |
308 | blockquote,
309 | dl,
310 | dd,
311 | h1,
312 | h2,
313 | h3,
314 | h4,
315 | h5,
316 | h6,
317 | hr,
318 | figure,
319 | p,
320 | pre {
321 | margin: 0;
322 | }
323 |
324 | fieldset {
325 | margin: 0;
326 | padding: 0;
327 | }
328 |
329 | legend {
330 | padding: 0;
331 | }
332 |
333 | ol,
334 | ul,
335 | menu {
336 | list-style: none;
337 | margin: 0;
338 | padding: 0;
339 | }
340 |
341 | /*
342 | Prevent resizing textareas horizontally by default.
343 | */
344 |
345 | textarea {
346 | resize: vertical;
347 | }
348 |
349 | /*
350 | 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
351 | 2. Set the default placeholder color to the user's configured gray 400 color.
352 | */
353 |
354 | input::-moz-placeholder, textarea::-moz-placeholder {
355 | opacity: 1;
356 | /* 1 */
357 | color: #9ca3af;
358 | /* 2 */
359 | }
360 |
361 | input::placeholder,
362 | textarea::placeholder {
363 | opacity: 1;
364 | /* 1 */
365 | color: #9ca3af;
366 | /* 2 */
367 | }
368 |
369 | /*
370 | Set the default cursor for buttons.
371 | */
372 |
373 | button,
374 | [role="button"] {
375 | cursor: pointer;
376 | }
377 |
378 | /*
379 | Make sure disabled buttons don't get the pointer cursor.
380 | */
381 |
382 | :disabled {
383 | cursor: default;
384 | }
385 |
386 | /*
387 | 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
388 | 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
389 | This can trigger a poorly considered lint error in some tools but is included by design.
390 | */
391 |
392 | img,
393 | svg,
394 | video,
395 | canvas,
396 | audio,
397 | iframe,
398 | embed,
399 | object {
400 | display: block;
401 | /* 1 */
402 | vertical-align: middle;
403 | /* 2 */
404 | }
405 |
406 | /*
407 | Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
408 | */
409 |
410 | img,
411 | video {
412 | max-width: 100%;
413 | height: auto;
414 | }
415 |
416 | /* Make elements with the HTML hidden attribute stay hidden by default */
417 |
418 | [hidden] {
419 | display: none;
420 | }
421 |
422 | *, ::before, ::after {
423 | --tw-border-spacing-x: 0;
424 | --tw-border-spacing-y: 0;
425 | --tw-translate-x: 0;
426 | --tw-translate-y: 0;
427 | --tw-rotate: 0;
428 | --tw-skew-x: 0;
429 | --tw-skew-y: 0;
430 | --tw-scale-x: 1;
431 | --tw-scale-y: 1;
432 | --tw-pan-x: ;
433 | --tw-pan-y: ;
434 | --tw-pinch-zoom: ;
435 | --tw-scroll-snap-strictness: proximity;
436 | --tw-ordinal: ;
437 | --tw-slashed-zero: ;
438 | --tw-numeric-figure: ;
439 | --tw-numeric-spacing: ;
440 | --tw-numeric-fraction: ;
441 | --tw-ring-inset: ;
442 | --tw-ring-offset-width: 0px;
443 | --tw-ring-offset-color: #fff;
444 | --tw-ring-color: rgb(59 130 246 / 0.5);
445 | --tw-ring-offset-shadow: 0 0 #0000;
446 | --tw-ring-shadow: 0 0 #0000;
447 | --tw-shadow: 0 0 #0000;
448 | --tw-shadow-colored: 0 0 #0000;
449 | --tw-blur: ;
450 | --tw-brightness: ;
451 | --tw-contrast: ;
452 | --tw-grayscale: ;
453 | --tw-hue-rotate: ;
454 | --tw-invert: ;
455 | --tw-saturate: ;
456 | --tw-sepia: ;
457 | --tw-drop-shadow: ;
458 | --tw-backdrop-blur: ;
459 | --tw-backdrop-brightness: ;
460 | --tw-backdrop-contrast: ;
461 | --tw-backdrop-grayscale: ;
462 | --tw-backdrop-hue-rotate: ;
463 | --tw-backdrop-invert: ;
464 | --tw-backdrop-opacity: ;
465 | --tw-backdrop-saturate: ;
466 | --tw-backdrop-sepia: ;
467 | }
468 |
469 | ::backdrop {
470 | --tw-border-spacing-x: 0;
471 | --tw-border-spacing-y: 0;
472 | --tw-translate-x: 0;
473 | --tw-translate-y: 0;
474 | --tw-rotate: 0;
475 | --tw-skew-x: 0;
476 | --tw-skew-y: 0;
477 | --tw-scale-x: 1;
478 | --tw-scale-y: 1;
479 | --tw-pan-x: ;
480 | --tw-pan-y: ;
481 | --tw-pinch-zoom: ;
482 | --tw-scroll-snap-strictness: proximity;
483 | --tw-ordinal: ;
484 | --tw-slashed-zero: ;
485 | --tw-numeric-figure: ;
486 | --tw-numeric-spacing: ;
487 | --tw-numeric-fraction: ;
488 | --tw-ring-inset: ;
489 | --tw-ring-offset-width: 0px;
490 | --tw-ring-offset-color: #fff;
491 | --tw-ring-color: rgb(59 130 246 / 0.5);
492 | --tw-ring-offset-shadow: 0 0 #0000;
493 | --tw-ring-shadow: 0 0 #0000;
494 | --tw-shadow: 0 0 #0000;
495 | --tw-shadow-colored: 0 0 #0000;
496 | --tw-blur: ;
497 | --tw-brightness: ;
498 | --tw-contrast: ;
499 | --tw-grayscale: ;
500 | --tw-hue-rotate: ;
501 | --tw-invert: ;
502 | --tw-saturate: ;
503 | --tw-sepia: ;
504 | --tw-drop-shadow: ;
505 | --tw-backdrop-blur: ;
506 | --tw-backdrop-brightness: ;
507 | --tw-backdrop-contrast: ;
508 | --tw-backdrop-grayscale: ;
509 | --tw-backdrop-hue-rotate: ;
510 | --tw-backdrop-invert: ;
511 | --tw-backdrop-opacity: ;
512 | --tw-backdrop-saturate: ;
513 | --tw-backdrop-sepia: ;
514 | }
515 |
516 | .static {
517 | position: static;
518 | }
519 |
520 | .fixed {
521 | position: fixed;
522 | }
523 |
524 | .top-0 {
525 | top: 0px;
526 | }
527 |
528 | .z-10 {
529 | z-index: 10;
530 | }
531 |
532 | .my-14 {
533 | margin-top: 3.5rem;
534 | margin-bottom: 3.5rem;
535 | }
536 |
537 | .mb-4 {
538 | margin-bottom: 1rem;
539 | }
540 |
541 | .mb-6 {
542 | margin-bottom: 1.5rem;
543 | }
544 |
545 | .ml-2 {
546 | margin-left: 0.5rem;
547 | }
548 |
549 | .ml-4 {
550 | margin-left: 1rem;
551 | }
552 |
553 | .ml-auto {
554 | margin-left: auto;
555 | }
556 |
557 | .mr-10 {
558 | margin-right: 2.5rem;
559 | }
560 |
561 | .mr-16 {
562 | margin-right: 4rem;
563 | }
564 |
565 | .mr-2 {
566 | margin-right: 0.5rem;
567 | }
568 |
569 | .mr-4 {
570 | margin-right: 1rem;
571 | }
572 |
573 | .mr-8 {
574 | margin-right: 2rem;
575 | }
576 |
577 | .mr-auto {
578 | margin-right: auto;
579 | }
580 |
581 | .mt-10 {
582 | margin-top: 2.5rem;
583 | }
584 |
585 | .mt-12 {
586 | margin-top: 3rem;
587 | }
588 |
589 | .mt-4 {
590 | margin-top: 1rem;
591 | }
592 |
593 | .mt-40 {
594 | margin-top: 10rem;
595 | }
596 |
597 | .flex {
598 | display: flex;
599 | }
600 |
601 | .h-10 {
602 | height: 2.5rem;
603 | }
604 |
605 | .h-16 {
606 | height: 4rem;
607 | }
608 |
609 | .h-24 {
610 | height: 6rem;
611 | }
612 |
613 | .h-32 {
614 | height: 8rem;
615 | }
616 |
617 | .w-40 {
618 | width: 10rem;
619 | }
620 |
621 | .w-9 {
622 | width: 2.25rem;
623 | }
624 |
625 | .w-full {
626 | width: 100%;
627 | }
628 |
629 | .max-w-3xl {
630 | max-width: 48rem;
631 | }
632 |
633 | .max-w-4xl {
634 | max-width: 56rem;
635 | }
636 |
637 | .grow {
638 | flex-grow: 1;
639 | }
640 |
641 | .flex-col {
642 | flex-direction: column;
643 | }
644 |
645 | .items-center {
646 | align-items: center;
647 | }
648 |
649 | .justify-center {
650 | justify-content: center;
651 | }
652 |
653 | .justify-between {
654 | justify-content: space-between;
655 | }
656 |
657 | .justify-evenly {
658 | justify-content: space-evenly;
659 | }
660 |
661 | .self-start {
662 | align-self: flex-start;
663 | }
664 |
665 | .self-end {
666 | align-self: flex-end;
667 | }
668 |
669 | .whitespace-nowrap {
670 | white-space: nowrap;
671 | }
672 |
673 | .rounded {
674 | border-radius: 0.25rem;
675 | }
676 |
677 | .rounded-lg {
678 | border-radius: 0.5rem;
679 | }
680 |
681 | .rounded-t-lg {
682 | border-top-left-radius: 0.5rem;
683 | border-top-right-radius: 0.5rem;
684 | }
685 |
686 | .border {
687 | border-width: 1px;
688 | }
689 |
690 | .bg-emerald-200 {
691 | --tw-bg-opacity: 1;
692 | background-color: rgb(167 243 208 / var(--tw-bg-opacity));
693 | }
694 |
695 | .bg-emerald-700 {
696 | --tw-bg-opacity: 1;
697 | background-color: rgb(4 120 87 / var(--tw-bg-opacity));
698 | }
699 |
700 | .bg-green-700 {
701 | --tw-bg-opacity: 1;
702 | background-color: rgb(21 128 61 / var(--tw-bg-opacity));
703 | }
704 |
705 | .bg-slate-300 {
706 | --tw-bg-opacity: 1;
707 | background-color: rgb(203 213 225 / var(--tw-bg-opacity));
708 | }
709 |
710 | .bg-slate-50 {
711 | --tw-bg-opacity: 1;
712 | background-color: rgb(248 250 252 / var(--tw-bg-opacity));
713 | }
714 |
715 | .p-3 {
716 | padding: 0.75rem;
717 | }
718 |
719 | .px-10 {
720 | padding-left: 2.5rem;
721 | padding-right: 2.5rem;
722 | }
723 |
724 | .px-2 {
725 | padding-left: 0.5rem;
726 | padding-right: 0.5rem;
727 | }
728 |
729 | .px-3 {
730 | padding-left: 0.75rem;
731 | padding-right: 0.75rem;
732 | }
733 |
734 | .py-1 {
735 | padding-top: 0.25rem;
736 | padding-bottom: 0.25rem;
737 | }
738 |
739 | .pb-8 {
740 | padding-bottom: 2rem;
741 | }
742 |
743 | .text-center {
744 | text-align: center;
745 | }
746 |
747 | .font-emoji {
748 | font-family: Material Icons, sans-serif;
749 | }
750 |
751 | .text-2xl {
752 | font-size: 1.5rem;
753 | line-height: 2rem;
754 | }
755 |
756 | .text-4xl {
757 | font-size: 2.25rem;
758 | line-height: 2.5rem;
759 | }
760 |
761 | .text-lg {
762 | font-size: 1.125rem;
763 | line-height: 1.75rem;
764 | }
765 |
766 | .font-bold {
767 | font-weight: 700;
768 | }
769 |
770 | .tracking-wider {
771 | letter-spacing: 0.05em;
772 | }
773 |
774 | .text-emerald-600 {
775 | --tw-text-opacity: 1;
776 | color: rgb(5 150 105 / var(--tw-text-opacity));
777 | }
778 |
779 | .text-slate-50 {
780 | --tw-text-opacity: 1;
781 | color: rgb(248 250 252 / var(--tw-text-opacity));
782 | }
783 |
784 | .text-white {
785 | --tw-text-opacity: 1;
786 | color: rgb(255 255 255 / var(--tw-text-opacity));
787 | }
788 |
789 | .shadow {
790 | --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
791 | --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
792 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
793 | }
794 |
795 | .shadow-lg {
796 | --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
797 | --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
798 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
799 | }
800 |
801 | body {
802 | font-family: Ubuntu, sans-serif;
803 | background-color: #eeeeee;
804 | background-image: url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23aeb8af' fill-opacity='0.4'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4v2c-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
805 | }
806 |
807 | .hover\:bg-green-800:hover {
808 | --tw-bg-opacity: 1;
809 | background-color: rgb(22 101 52 / var(--tw-bg-opacity));
810 | }
811 |
812 | .hover\:bg-slate-400:hover {
813 | --tw-bg-opacity: 1;
814 | background-color: rgb(148 163 184 / var(--tw-bg-opacity));
815 | }
816 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/static/css/styles.css:
--------------------------------------------------------------------------------
1 | /* styles.css */
2 | @tailwind base;
3 | @tailwind components;
4 | @tailwind utilities;
5 |
6 | body {
7 | font-family: Ubuntu, sans-serif;
8 | background-color: #eeeeee;
9 | background-image: url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23aeb8af' fill-opacity='0.4'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4v2c-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
10 | }
11 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/static/js/main.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function showSenha() {
4 | const input = document.getElementById("senha");
5 | const senhaIcon = document.getElementById("senha-icon");
6 | if (input.attributes.type.nodeValue == "password") {
7 | input.setAttribute("type", "text");
8 | senhaIcon.innerText = "visibility_off";
9 | } else {
10 | input.setAttribute("type", "password");
11 | senhaIcon.innerText = "visibility";
12 | }
13 | }
14 | function showSenhaPorId(id) {
15 | console.log(id);
16 | const input = document.getElementById("senha-" + id);
17 | const senhaIcon = document.getElementById("senha-icon-" + id);
18 | if (input.attributes.type.nodeValue == "password") {
19 | input.setAttribute("type", "text");
20 | senhaIcon.innerText = "visibility_off";
21 | } else {
22 | input.setAttribute("type", "password");
23 | senhaIcon.innerText = "visibility";
24 | }
25 | }
26 | function copiarParaAreaDeTransferencia() {
27 | const senhaElemento = document.getElementById("senha");
28 | navigator.clipboard.writeText(senhaElemento.value).then(
29 | () => {
30 | alert("Senha copiada para a área de transferência!");
31 | },
32 | (err) => {
33 | alert("Não foi possível copiar a senha: " + err);
34 | }
35 | );
36 | }
37 |
38 | function copiarParaAreaDeTransferenciaPorId(id) {
39 | const senhaElemento = document.getElementById("senha-" + id);
40 | navigator.clipboard.writeText(senhaElemento.value).then(
41 | () => {
42 | alert("Senha copiada para a área de transferência!");
43 | },
44 | (err) => {
45 | alert("Não foi possível copiar a senha: " + err);
46 | }
47 | );
48 | }
49 |
50 | function toggleUsuarios() {
51 | const listaUsuariosContainer = document.getElementById(
52 | "lista-usuarios-container"
53 | );
54 | listaUsuariosContainer.classList.toggle("hidden");
55 | }
56 | function buscarUltimasSenhas() {
57 | navigation.reload();
58 | }
59 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/static/linuxtips-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/app/normal-giropops-senhas/static/linuxtips-logo.png
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./templates/*.html"],
4 | theme: {
5 | fontFamily: {
6 | emoji: ["Material Icons", "sans-serif"],
7 | },
8 | extend: {},
9 | },
10 | plugins: [],
11 | };
12 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Gerador de Senhas
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
25 |
26 |
27 |
28 |
29 |
30 |
Gerar senha
31 |
32 |
51 | {% if senha %}
52 |
53 |
Senha gerada:
54 |
56 |
57 |
61 |
65 |
66 | {% endif %}
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Últimas senhas criadas
75 |
76 |
77 |
82 | {% include 'lista_senhas.html' %}
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/app/normal-giropops-senhas/templates/lista_senhas.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% for senha_gerada in senhas_geradas %}
4 | -
5 |
6 |
13 |
14 |
23 |
30 |
31 |
32 |
33 | {% endfor %}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/docs/images/AWS-keys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/AWS-keys.png
--------------------------------------------------------------------------------
/docs/images/Arquitetura-Infra.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/Arquitetura-Infra.png
--------------------------------------------------------------------------------
/docs/images/acesso-giropops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/acesso-giropops.png
--------------------------------------------------------------------------------
/docs/images/bot-firing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/bot-firing.png
--------------------------------------------------------------------------------
/docs/images/bot-resolved.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/bot-resolved.png
--------------------------------------------------------------------------------
/docs/images/build-distroless.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/build-distroless.png
--------------------------------------------------------------------------------
/docs/images/build-melange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/build-melange.png
--------------------------------------------------------------------------------
/docs/images/build-normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/build-normal.png
--------------------------------------------------------------------------------
/docs/images/camadas-builddistroless.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/camadas-builddistroless.png
--------------------------------------------------------------------------------
/docs/images/camadas-buildmelange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/camadas-buildmelange.png
--------------------------------------------------------------------------------
/docs/images/camadas-buildnormal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/camadas-buildnormal.png
--------------------------------------------------------------------------------
/docs/images/crashloop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/crashloop.png
--------------------------------------------------------------------------------
/docs/images/estrutura-helm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/estrutura-helm.png
--------------------------------------------------------------------------------
/docs/images/false-signature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/false-signature.png
--------------------------------------------------------------------------------
/docs/images/get-top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/get-top.png
--------------------------------------------------------------------------------
/docs/images/giropops-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/giropops-image.png
--------------------------------------------------------------------------------
/docs/images/grafana-alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/grafana-alert.png
--------------------------------------------------------------------------------
/docs/images/grafana-giropops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/grafana-giropops.png
--------------------------------------------------------------------------------
/docs/images/grafana-temporesposta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/grafana-temporesposta.png
--------------------------------------------------------------------------------
/docs/images/harbor-configs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/harbor-configs.png
--------------------------------------------------------------------------------
/docs/images/helm-install-giropops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/helm-install-giropops.png
--------------------------------------------------------------------------------
/docs/images/imagem-ajustada.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/imagem-ajustada.png
--------------------------------------------------------------------------------
/docs/images/keda-scaledown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/keda-scaledown.png
--------------------------------------------------------------------------------
/docs/images/keda-working.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/keda-working.png
--------------------------------------------------------------------------------
/docs/images/kyverno-bloqueios.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/kyverno-bloqueios.png
--------------------------------------------------------------------------------
/docs/images/locust-charts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/locust-charts.png
--------------------------------------------------------------------------------
/docs/images/locust-grafana1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/locust-grafana1.png
--------------------------------------------------------------------------------
/docs/images/locust-grafana2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/locust-grafana2.png
--------------------------------------------------------------------------------
/docs/images/locust-statics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/locust-statics.png
--------------------------------------------------------------------------------
/docs/images/locust-test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/locust-test.png
--------------------------------------------------------------------------------
/docs/images/melange-keys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/melange-keys.png
--------------------------------------------------------------------------------
/docs/images/nginx-assinada.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/nginx-assinada.png
--------------------------------------------------------------------------------
/docs/images/prom-target.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/prom-target.png
--------------------------------------------------------------------------------
/docs/images/redis-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/redis-image.png
--------------------------------------------------------------------------------
/docs/images/scale-deployment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/scale-deployment.png
--------------------------------------------------------------------------------
/docs/images/scan-build-distroless.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/scan-build-distroless.png
--------------------------------------------------------------------------------
/docs/images/scan-build-melange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/scan-build-melange.png
--------------------------------------------------------------------------------
/docs/images/scan-build-normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/scan-build-normal.png
--------------------------------------------------------------------------------
/docs/images/set-env.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/docs/images/set-env.png
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | // Definindo apenas variáveis necessárias. Todo restante pode ser modificado diretamente neste arquivo
2 | variable "access_key" {}
3 | variable "secret_key" {}
4 | variable "k8s_subnet_cidr" {
5 | default = "172.31.112.0/20" // Altere esse valor para o correspondente com sua VPC
6 | }
7 | variable "k8s_subnet_cidr_2" {
8 | default = "172.31.128.0/20" // Altere esse valor para o correspondente com sua VPC
9 | }
10 |
11 | provider "aws" {
12 | region = "us-east-1"
13 | access_key = var.access_key
14 | secret_key = var.secret_key
15 | }
16 |
17 | terraform {
18 | backend "s3" {
19 | bucket = "fabiobartoli-k8s-pick-bucket" // Passe o nome do Bucket que você criou para armazenar o state
20 | key = "terraform/k8s-PICK-state"
21 | region = "us-east-1"
22 | }
23 | }
24 |
25 | module "k8s_provisioner" {
26 | source = "./modules/k8s_provisioner"
27 | ami = "ami-04b70fa74e45c3917" // Ubuntu Server 24.04 LTS (HVM), SSD Volume Type
28 | cp_instance_type = "t3a.small" // 2vCPU x 2Gib Memory
29 | instance_type = "t3a.small" // 2vCPU x 2Gib Memory
30 | volume_size = 64
31 | instance_count = 4 // Número de instâncias
32 | vpc_id = "vpc-096357cb7db323b17" // ID da sua VPC
33 | k8s_subnet_cidr = var.k8s_subnet_cidr
34 | k8s_subnet_cidr_2 = var.k8s_subnet_cidr_2
35 | k8s_subnet_az = "us-east-1a" // AZ para a subnet que será criada
36 | k8s_subnet_az_2 = "us-east-1b" // AZ para a subnet secundário para o Balancer
37 | AWS_ACCESS_KEY_ID = var.access_key
38 | AWS_SECRET_ACCESS_KEY = var.secret_key
39 | private_key = file("${path.module}/id_rsa")
40 | public_key = file("${path.module}/id_rsa.pub")
41 | security_group_rules = [
42 | // PORTAS NECESSÁRIAS PARA O K8S
43 | {
44 | protocol = "tcp"
45 | from_port = 6443
46 | to_port = 6443
47 | cidr_blocks = ["0.0.0.0/0"] //Acessar o Kubeconfig remotamente
48 | },
49 | {
50 | protocol = "tcp"
51 | from_port = 80
52 | to_port = 80
53 | cidr_blocks = ["0.0.0.0/0"] //Acessar o Kubeconfig remotamente
54 | },
55 | {
56 | protocol = "tcp"
57 | from_port = 443
58 | to_port = 443
59 | cidr_blocks = ["0.0.0.0/0"] //Acessar o Kubeconfig remotamente
60 | },
61 | {
62 | protocol = "tcp"
63 | from_port = 30443
64 | to_port = 30443
65 | cidr_blocks = ["0.0.0.0/0"] //Acessar o Nodeport
66 | },
67 | {
68 | protocol = "tcp"
69 | from_port = 22
70 | to_port = 22
71 | cidr_blocks = ["0.0.0.0/0"] //SSH para o Terraform poder usar
72 | },
73 | //LIBERA TODAS PORTAS PRA COMUNICAÇÃO ENTRE O CLUSTER
74 | {
75 | protocol = "-1"
76 | from_port = 0
77 | to_port = 0
78 | cidr_blocks = [var.k8s_subnet_cidr]
79 | }
80 | ]
81 | }
82 |
83 | output "control_plane_public_ip" {
84 | value = module.k8s_provisioner.control_plane_public_ip
85 | }
86 |
87 | output "worker_public_ips" {
88 | value = module.k8s_provisioner.worker_public_ips
89 | }
90 |
91 | output "k8s_alb_dns_name" {
92 | value = module.k8s_provisioner.k8s_alb_dns_name
93 | }
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/giropops-chart-0.1.0.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/manifests/helm/giropops-app/giropops-chart-0.1.0.tgz
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/helm-giropops-app/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: giropops-chart
3 | description: Helm chart para criar os Deployments, Services e ServiceAccounts do giropops
4 |
5 | version: 0.1.0
6 | appVersion: "1.0"
7 |
8 | maintainers:
9 | - name: Fabio Bartoli
10 | email: fabio.bartoli@outlook.com
11 |
12 | keywords:
13 | - ingress
14 | - giropops
15 | - redis
16 |
17 | sources:
18 | - https://github.com/FabioBartoli/LINUXtips-PICK/
19 |
20 | dependencies: []
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/helm-giropops-app/templates/deployment.yaml:
--------------------------------------------------------------------------------
1 | {{- range $deployment := .Values.deployments }}
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | name: {{ $deployment.name }}
6 | namespace: {{ $deployment.namespace }}
7 | labels:
8 | env: {{ if $.Values.env }}{{ $.Values.env }}{{ else }}dev{{ end }}
9 | {{- range $key, $value := $deployment.labels }}
10 | {{ $key }}: {{ $value }}
11 | {{- end }}
12 | spec:
13 | replicas: {{ $deployment.replicas }}
14 | selector:
15 | matchLabels:
16 | app: {{ $deployment.labels.app }}
17 | template:
18 | metadata:
19 | labels:
20 | env: {{ if $.Values.env }}{{ $.Values.env }}{{ else }}dev{{ end }}
21 | {{- range $key, $value := $deployment.labels }}
22 | {{ $key }}: {{ $value }}
23 | {{- end }}
24 | spec:
25 | serviceAccountName: {{ $deployment.serviceAccountName }}
26 | {{- if $deployment.imagePullSecrets }}
27 | imagePullSecrets:
28 | {{- range $secret := $deployment.imagePullSecrets }}
29 | - name: {{ $secret.name }}
30 | {{- end }}
31 | {{- end }}
32 | containers:
33 | {{- range $container := $deployment.containers }}
34 | - name: {{ $container.name }}
35 | image: {{ $container.image }}
36 | ports:
37 | {{- range $port := $container.ports }}
38 | - containerPort: {{ $port.containerPort }}
39 | {{- end }}
40 | env:
41 | {{- range $env := $container.env }}
42 | - name: {{ $env.name }}
43 | value: {{ $env.value }}
44 | {{- end }}
45 | resources:
46 | limits:
47 | memory: {{ $container.resources.limits.memory }}
48 | cpu: {{ $container.resources.limits.cpu }}
49 | requests:
50 | memory: {{ $container.resources.requests.memory }}
51 | cpu: {{ $container.resources.requests.cpu }}
52 | securityContext:
53 | allowPrivilegeEscalation: {{ $container.securityContext.allowPrivilegeEscalation }}
54 | runAsUser: {{ $container.securityContext.runAsUser }}
55 | runAsGroup: {{ $container.securityContext.runAsGroup }}
56 | capabilities:
57 | drop:
58 | {{- range $capability := $container.securityContext.capabilities.drop }}
59 | - {{ $capability }}
60 | {{- end }}
61 | {{- if $container.securityContext.capabilities.add }}
62 | add:
63 | {{- range $capability := $container.securityContext.capabilities.add }}
64 | - {{ $capability }}
65 | {{- end }}
66 | {{- end }}
67 | livenessProbe:
68 | {{- toYaml $container.livenessProbe | nindent 12 }}
69 | readinessProbe:
70 | {{- toYaml $container.readinessProbe | nindent 12 }}
71 | {{- if $container.command }}
72 | command:
73 | {{- range $cmd := $container.command }}
74 | - {{ $cmd | quote }}
75 | {{- end }}
76 | {{- end }}
77 | {{- end }}
78 | ---
79 | {{- end }}
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/helm-giropops-app/templates/service.yaml:
--------------------------------------------------------------------------------
1 | {{- range $service := .Values.services }}
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: {{ $service.name }}
6 | namespace: {{ $service.namespace | default "default" }}
7 | labels:
8 | app: {{ $service.selector.app }}
9 | spec:
10 | selector:
11 | app: {{ $service.selector.app }}
12 | ports:
13 | {{- range $port := $service.ports }}
14 | - protocol: {{ $port.protocol }}
15 | port: {{ $port.port }}
16 | targetPort: {{ $port.targetPort }}
17 | name: {{ $port.name | default "http" }}
18 | {{- end }}
19 | type: ClusterIP
20 | ---
21 | {{- end }}
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/helm-giropops-app/templates/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | {{- range $sa := .Values.serviceAccounts }}
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | name: {{ $sa.name }}
6 | namespace: {{ $sa.namespace | default "default" }}
7 | ---
8 | {{- end }}
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/helm-giropops-app/values.yaml:
--------------------------------------------------------------------------------
1 | deployments:
2 | - name: giropops-senhas
3 | namespace: giropops
4 | replicas: 2
5 | serviceAccountName: giropops-senhas-sa
6 | labels:
7 | app: giropops-senhas
8 | containers:
9 | - name: giropops-senhas
10 | image: harbor.fabiobartoli.com.br/pick2024/melange-giropops-senhas
11 | ports:
12 | - containerPort: 5000
13 | env:
14 | - name: REDIS_HOST
15 | value: redis-service
16 | resources:
17 | limits:
18 | memory: "256Mi"
19 | cpu: "500m"
20 | requests:
21 | memory: "128Mi"
22 | cpu: "250m"
23 | securityContext:
24 | allowPrivilegeEscalation: false
25 | runAsUser: 1000
26 | runAsGroup: 3000
27 | capabilities:
28 | drop:
29 | - ALL
30 | livenessProbe:
31 | httpGet:
32 | path: /
33 | port: 5000
34 | initialDelaySeconds: 10
35 | periodSeconds: 10
36 | timeoutSeconds: 5
37 | failureThreshold: 3
38 | readinessProbe:
39 | exec:
40 | command:
41 | - curl
42 | - -f
43 | - http://localhost:5000/
44 | initialDelaySeconds: 10
45 | periodSeconds: 10
46 | timeoutSeconds: 5
47 | failureThreshold: 3
48 | successThreshold: 1
49 | imagePullSecrets:
50 | - name: regcred
51 |
52 | - name: redis-deployment
53 | namespace: giropops
54 | replicas: 1
55 | serviceAccountName: redis-sa
56 | labels:
57 | app: redis
58 | containers:
59 | - name: redis
60 | image: harbor.fabiobartoli.com.br/pick2024/redis
61 | ports:
62 | - containerPort: 6379
63 | resources:
64 | limits:
65 | memory: "256Mi"
66 | cpu: "500m"
67 | requests:
68 | memory: "128Mi"
69 | cpu: "250m"
70 | securityContext:
71 | runAsUser: 1000
72 | runAsGroup: 3000
73 | allowPrivilegeEscalation: false
74 | capabilities:
75 | drop:
76 | - ALL
77 | add:
78 | - NET_BIND_SERVICE
79 | - CHOWN
80 | - SETUID
81 | - SETGID
82 | livenessProbe:
83 | tcpSocket:
84 | port: 6379
85 | initialDelaySeconds: 30
86 | timeoutSeconds: 5
87 | periodSeconds: 5
88 | failureThreshold: 5
89 | successThreshold: 1
90 | readinessProbe:
91 | exec:
92 | command:
93 | - redis-cli
94 | - ping
95 | initialDelaySeconds: 20
96 | timeoutSeconds: 5
97 | periodSeconds: 3
98 | command: ["redis-server", "--appendonly", "no"]
99 | imagePullSecrets:
100 | - name: regcred
101 |
102 | services:
103 | - name: giropops-senhas
104 | namespace: giropops
105 | selector:
106 | app: giropops-senhas
107 | ports:
108 | - protocol: TCP
109 | port: 5000
110 | targetPort: 5000
111 | name: tcp-app
112 |
113 | - name: redis-service
114 | namespace: giropops
115 | selector:
116 | app: redis
117 | ports:
118 | - protocol: TCP
119 | port: 6379
120 | targetPort: 6379
121 |
122 | serviceAccounts:
123 | - name: giropops-senhas-sa
124 | namespace: giropops
125 |
126 | - name: redis-sa
127 | namespace: giropops
--------------------------------------------------------------------------------
/manifests/helm/giropops-app/index.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | entries:
3 | giropops-chart:
4 | - apiVersion: v2
5 | appVersion: "1.0"
6 | created: "2024-08-26T21:07:08.194533872-03:00"
7 | description: Helm chart para criar os Deployments, Services e ServiceAccounts
8 | do giropops
9 | digest: 712e07ad91dae023aa2a6abc5e27067da237e11f7b723b1f803744418d237c40
10 | keywords:
11 | - ingress
12 | - giropops
13 | - redis
14 | maintainers:
15 | - email: fabio.bartoli@outlook.com
16 | name: Fabio Bartoli
17 | name: giropops-chart
18 | sources:
19 | - https://github.com/FabioBartoli/LINUXtips-PICK/
20 | urls:
21 | - https://fabiobartoli.github.io/LINUXtips-PICK/manifests/helm/giropops-app/giropops-chart-0.1.0.tgz
22 | version: 0.1.0
23 | generated: "2024-08-26T21:07:08.194152363-03:00"
24 |
--------------------------------------------------------------------------------
/manifests/helm/ingress/helm-pick-cluster-ingress/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: ingress-templates
3 | description: Helm chart reutilizável para configurar Ingresses no Kubernetes
4 |
5 | type: application
6 |
7 | version: 0.1.0
8 | appVersion: "1.0"
9 |
10 | maintainers:
11 | - name: Fabio Bartoli
12 | email: fabio.bartoli@outlook.com
13 |
14 | keywords:
15 | - ingress
16 | - nginx
17 | - kubernetes
18 | - helm
19 | - harbor
20 | - locust
21 | - kube-prometheus
22 |
23 | sources:
24 | - https://github.com/FabioBartoli/LINUXtips-PICK/
25 |
26 | dependencies: []
27 |
28 |
--------------------------------------------------------------------------------
/manifests/helm/ingress/helm-pick-cluster-ingress/templates/ingress.yaml:
--------------------------------------------------------------------------------
1 | {{- range $ingress := .Values.ingresses }}
2 | apiVersion: networking.k8s.io/v1
3 | kind: Ingress
4 | metadata:
5 | name: {{ $ingress.name }}
6 | namespace: {{ $ingress.namespace | default "default" }}
7 | annotations:
8 | {{- range $key, $value := $ingress.annotations }}
9 | {{ $key }}: "{{ $value }}"
10 | {{- end }}
11 | spec:
12 | ingressClassName: {{ $ingress.ingressClassName }}
13 | rules:
14 | - host: {{ $ingress.host }}
15 | http:
16 | paths:
17 | {{- range $path := $ingress.paths }}
18 | - path: {{ $path.path }}
19 | pathType: {{ $path.pathType }}
20 | backend:
21 | service:
22 | name: {{ $path.service.name }}
23 | port:
24 | number: {{ $path.service.port }}
25 | {{- end }}
26 | {{- if $ingress.tls }}
27 | tls:
28 | - hosts:
29 | {{- range $host := $ingress.tls.hosts }}
30 | - {{ $host }}
31 | {{- end }}
32 | secretName: {{ $ingress.tls.secretName }}
33 | {{- end }}
34 | ---
35 | {{- end }}
--------------------------------------------------------------------------------
/manifests/helm/ingress/helm-pick-cluster-ingress/values.yaml:
--------------------------------------------------------------------------------
1 | ingresses:
2 | - name: giropops-senhas
3 | namespace: giropops
4 | ingressClassName: nginx
5 | host: giropops-senhas.fabiobartoli.com.br
6 | annotations:
7 | nginx.ingress.kubernetes.io/rewrite-target: /
8 | paths:
9 | - path: /
10 | pathType: Prefix
11 | service:
12 | name: giropops-senhas
13 | port: 5000
14 |
15 | - name: grafana
16 | namespace: monitoring
17 | ingressClassName: nginx
18 | host: grafana.fabiobartoli.com.br
19 | annotations:
20 | nginx.ingress.kubernetes.io/rewrite-target: /
21 | paths:
22 | - path: /
23 | pathType: Prefix
24 | service:
25 | name: kube-prometheus-grafana
26 | port: 80
27 |
28 | - name: harbor-ingress
29 | namespace: harbor
30 | ingressClassName: nginx
31 | host: harbor.fabiobartoli.com.br
32 | annotations:
33 | ingress.kubernetes.io/proxy-body-size: "0"
34 | ingress.kubernetes.io/ssl-redirect: "true"
35 | nginx.ingress.kubernetes.io/proxy-body-size: "0"
36 | nginx.ingress.kubernetes.io/ssl-redirect: "true"
37 | paths:
38 | - path: /api/
39 | pathType: Prefix
40 | service:
41 | name: harbor-harbor-core
42 | port: 80
43 | - path: /service/
44 | pathType: Prefix
45 | service:
46 | name: harbor-harbor-core
47 | port: 80
48 | - path: /v2/
49 | pathType: Prefix
50 | service:
51 | name: harbor-harbor-core
52 | port: 80
53 | - path: /chartrepo/
54 | pathType: Prefix
55 | service:
56 | name: harbor-harbor-core
57 | port: 80
58 | - path: /c/
59 | pathType: Prefix
60 | service:
61 | name: harbor-harbor-core
62 | port: 80
63 | - path: /
64 | pathType: Prefix
65 | service:
66 | name: harbor-harbor-portal
67 | port: 80
68 |
69 | - name: locust-giropops
70 | namespace: locust
71 | ingressClassName: nginx
72 | host: locust.fabiobartoli.com.br
73 | annotations:
74 | nginx.ingress.kubernetes.io/rewrite-target: /
75 | paths:
76 | - path: /
77 | pathType: Prefix
78 | service:
79 | name: locust-giropops
80 | port: 8089
81 |
82 | - name: kube-prometheus
83 | namespace: monitoring
84 | ingressClassName: nginx
85 | host: prometheus.fabiobartoli.com.br
86 | annotations:
87 | nginx.ingress.kubernetes.io/rewrite-target: /
88 | paths:
89 | - path: /
90 | pathType: Prefix
91 | service:
92 | name: kube-prometheus-kube-prome-prometheus
93 | port: 9090
94 |
--------------------------------------------------------------------------------
/manifests/helm/ingress/index.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | entries:
3 | ingress-templates:
4 | - apiVersion: v2
5 | appVersion: "1.0"
6 | created: "2024-08-26T18:05:33.890213211-03:00"
7 | description: Helm chart reutilizável para configurar Ingresses no Kubernetes
8 | digest: 5620153968b1839823cd7a89d48bb5e6d6c782a68cc09f67dbd95179605f1a26
9 | keywords:
10 | - ingress
11 | - nginx
12 | - kubernetes
13 | - helm
14 | - harbor
15 | - locust
16 | - kube-prometheus
17 | maintainers:
18 | - email: fabio.bartoli@outlook.com
19 | name: Fabio Bartoli
20 | name: ingress-templates
21 | sources:
22 | - https://github.com/FabioBartoli/LINUXtips-PICK/
23 | type: application
24 | urls:
25 | - https://fabiobartoli.github.io/LINUXtips-PICK/manifests/helm/ingress/ingress-templates-0.1.0.tgz
26 | version: 0.1.0
27 | generated: "2024-08-26T18:05:33.889914709-03:00"
28 |
--------------------------------------------------------------------------------
/manifests/helm/ingress/ingress-templates-0.1.0.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FabioBartoli/LINUXtips-PICK/69b38d18f83e4e3fbd86e9ca07452a96b7e93de9/manifests/helm/ingress/ingress-templates-0.1.0.tgz
--------------------------------------------------------------------------------
/manifests/locust/locust-configmap.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | data:
3 | locustfile.py: |-
4 | from locust import HttpUser, task, between
5 |
6 | class Giropops(HttpUser):
7 | wait_time = between(1, 2)
8 |
9 | @task(1)
10 | def gerar_senha(self):
11 | self.client.post("/api/gerar-senha", json={"tamanho": 8, "incluir_numeros": True, "incluir_caracteres_especiais": True})
12 |
13 | @task(2)
14 | def listar_senha(self):
15 | self.client.get("/api/senhas")
16 | kind: ConfigMap
17 | metadata:
18 | name: locust-scripts
19 | namespace: locust
20 |
--------------------------------------------------------------------------------
/manifests/locust/locust-deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | labels:
5 | app: locust-giropops
6 | name: locust-giropops
7 | namespace: locust
8 | spec:
9 | replicas: 1
10 | selector:
11 | matchLabels:
12 | app: locust-giropops
13 | template:
14 | metadata:
15 | labels:
16 | app: locust-giropops
17 | spec:
18 | containers:
19 | - image: linuxtips/locust-giropops:1.0
20 | name: locust-giropops
21 | env:
22 | - name: LOCUST_LOCUSTFILE
23 | value: "/usr/src/app/scripts/locustfile.py"
24 | ports:
25 | - containerPort: 8089
26 | imagePullPolicy: Always
27 | volumeMounts:
28 | - name: locust-scripts
29 | mountPath: /usr/src/app/scripts
30 | securityContext:
31 | allowPrivilegeEscalation: false
32 | runAsUser: 1000
33 | runAsGroup: 3000
34 | volumes:
35 | - name: locust-scripts
36 | configMap:
37 | name: locust-scripts
38 | optional: true
39 |
--------------------------------------------------------------------------------
/manifests/locust/locust-service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: locust-giropops
5 | namespace: locust
6 | spec:
7 | selector:
8 | app: locust-giropops
9 | ports:
10 | - protocol: TCP
11 | port: 80
12 | targetPort: 8089
13 | type: ClusterIP
14 |
--------------------------------------------------------------------------------
/manifests/metrics-hpa/KEDA-scaledObjectRedis.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: keda.sh/v1alpha1
2 | kind: ScaledObject
3 | metadata:
4 | name: redis-scaledobject
5 | namespace: giropops
6 | spec:
7 | scaleTargetRef:
8 | kind: Deployment
9 | name: redis-deployment
10 | minReplicaCount: 1
11 | maxReplicaCount: 10
12 | cooldownPeriod: 60
13 | triggers:
14 | - type: prometheus
15 | metadata:
16 | serverAddress: http://kube-prometheus-kube-prome-prometheus.monitoring.svc.cluster.local:9090/
17 | metricName: giropops_senhas_replicas
18 | threshold: '3'
19 | query: |
20 | sum(kube_deployment_status_replicas{namespace="giropops",deployment="giropops-senhas"})
--------------------------------------------------------------------------------
/manifests/metrics-hpa/hpa-giropops.senhas.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: autoscaling/v2
2 | kind: HorizontalPodAutoscaler
3 | metadata:
4 | name: giropops-senhas-hpa
5 | namespace: giropops
6 | spec:
7 | scaleTargetRef:
8 | apiVersion: apps/v1
9 | kind: Deployment
10 | name: giropops-senhas
11 | minReplicas: 2
12 | maxReplicas: 10
13 | metrics:
14 | - type: Resource
15 | resource:
16 | name: cpu
17 | target:
18 | type: Utilization
19 | averageUtilization: 50
20 | - type: Resource
21 | resource:
22 | name: memory
23 | target:
24 | type: Utilization
25 | averageUtilization: 50
26 | behavior:
27 | scaleUp:
28 | stabilizationWindowSeconds: 5
29 | policies:
30 | - type: Percent
31 | value: 100
32 | periodSeconds: 10
33 | scaleDown:
34 | stabilizationWindowSeconds: 60
35 | policies:
36 | - type: Percent
37 | value: 100
38 | periodSeconds: 10
39 |
--------------------------------------------------------------------------------
/manifests/metrics-hpa/metrics-components.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | metadata:
4 | labels:
5 | k8s-app: metrics-server
6 | name: metrics-server
7 | namespace: kube-system
8 | ---
9 | apiVersion: rbac.authorization.k8s.io/v1
10 | kind: ClusterRole
11 | metadata:
12 | labels:
13 | k8s-app: metrics-server
14 | rbac.authorization.k8s.io/aggregate-to-admin: "true"
15 | rbac.authorization.k8s.io/aggregate-to-edit: "true"
16 | rbac.authorization.k8s.io/aggregate-to-view: "true"
17 | name: system:aggregated-metrics-reader
18 | rules:
19 | - apiGroups:
20 | - metrics.k8s.io
21 | resources:
22 | - pods
23 | - nodes
24 | verbs:
25 | - get
26 | - list
27 | - watch
28 | ---
29 | apiVersion: rbac.authorization.k8s.io/v1
30 | kind: ClusterRole
31 | metadata:
32 | labels:
33 | k8s-app: metrics-server
34 | name: system:metrics-server
35 | rules:
36 | - apiGroups:
37 | - ""
38 | resources:
39 | - nodes/metrics
40 | verbs:
41 | - get
42 | - apiGroups:
43 | - ""
44 | resources:
45 | - pods
46 | - nodes
47 | verbs:
48 | - get
49 | - list
50 | - watch
51 | ---
52 | apiVersion: rbac.authorization.k8s.io/v1
53 | kind: RoleBinding
54 | metadata:
55 | labels:
56 | k8s-app: metrics-server
57 | name: metrics-server-auth-reader
58 | namespace: kube-system
59 | roleRef:
60 | apiGroup: rbac.authorization.k8s.io
61 | kind: Role
62 | name: extension-apiserver-authentication-reader
63 | subjects:
64 | - kind: ServiceAccount
65 | name: metrics-server
66 | namespace: kube-system
67 | ---
68 | apiVersion: rbac.authorization.k8s.io/v1
69 | kind: ClusterRoleBinding
70 | metadata:
71 | labels:
72 | k8s-app: metrics-server
73 | name: metrics-server:system:auth-delegator
74 | roleRef:
75 | apiGroup: rbac.authorization.k8s.io
76 | kind: ClusterRole
77 | name: system:auth-delegator
78 | subjects:
79 | - kind: ServiceAccount
80 | name: metrics-server
81 | namespace: kube-system
82 | ---
83 | apiVersion: rbac.authorization.k8s.io/v1
84 | kind: ClusterRoleBinding
85 | metadata:
86 | labels:
87 | k8s-app: metrics-server
88 | name: system:metrics-server
89 | roleRef:
90 | apiGroup: rbac.authorization.k8s.io
91 | kind: ClusterRole
92 | name: system:metrics-server
93 | subjects:
94 | - kind: ServiceAccount
95 | name: metrics-server
96 | namespace: kube-system
97 | ---
98 | apiVersion: v1
99 | kind: Service
100 | metadata:
101 | labels:
102 | k8s-app: metrics-server
103 | name: metrics-server
104 | namespace: kube-system
105 | spec:
106 | ports:
107 | - name: https
108 | port: 443
109 | protocol: TCP
110 | targetPort: https
111 | selector:
112 | k8s-app: metrics-server
113 | ---
114 | apiVersion: apps/v1
115 | kind: Deployment
116 | metadata:
117 | labels:
118 | k8s-app: metrics-server
119 | name: metrics-server
120 | namespace: kube-system
121 | spec:
122 | selector:
123 | matchLabels:
124 | k8s-app: metrics-server
125 | strategy:
126 | rollingUpdate:
127 | maxUnavailable: 0
128 | template:
129 | metadata:
130 | labels:
131 | k8s-app: metrics-server
132 | spec:
133 | containers:
134 | - args:
135 | - --cert-dir=/tmp
136 | - --secure-port=10250
137 | - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
138 | - --kubelet-use-node-status-port
139 | - --metric-resolution=15s
140 | - --kubelet-insecure-tls
141 | image: registry.k8s.io/metrics-server/metrics-server:v0.7.1
142 | imagePullPolicy: IfNotPresent
143 | livenessProbe:
144 | failureThreshold: 3
145 | httpGet:
146 | path: /livez
147 | port: https
148 | scheme: HTTPS
149 | periodSeconds: 10
150 | name: metrics-server
151 | ports:
152 | - containerPort: 10250
153 | name: https
154 | protocol: TCP
155 | readinessProbe:
156 | failureThreshold: 3
157 | httpGet:
158 | path: /readyz
159 | port: https
160 | scheme: HTTPS
161 | initialDelaySeconds: 20
162 | periodSeconds: 10
163 | resources:
164 | requests:
165 | cpu: 100m
166 | memory: 200Mi
167 | securityContext:
168 | allowPrivilegeEscalation: false
169 | capabilities:
170 | drop:
171 | - ALL
172 | readOnlyRootFilesystem: true
173 | runAsNonRoot: true
174 | runAsUser: 1000
175 | seccompProfile:
176 | type: RuntimeDefault
177 | volumeMounts:
178 | - mountPath: /tmp
179 | name: tmp-dir
180 | nodeSelector:
181 | kubernetes.io/os: linux
182 | priorityClassName: system-cluster-critical
183 | serviceAccountName: metrics-server
184 | volumes:
185 | - emptyDir: {}
186 | name: tmp-dir
187 | ---
188 | apiVersion: apiregistration.k8s.io/v1
189 | kind: APIService
190 | metadata:
191 | labels:
192 | k8s-app: metrics-server
193 | name: v1beta1.metrics.k8s.io
194 | spec:
195 | group: metrics.k8s.io
196 | groupPriorityMinimum: 100
197 | insecureSkipTLSVerify: true
198 | service:
199 | name: metrics-server
200 | namespace: kube-system
201 | version: v1beta1
202 | versionPriority: 100
--------------------------------------------------------------------------------
/modules/k8s_provisioner/ingress-deploy.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | labels:
5 | app.kubernetes.io/instance: ingress-nginx
6 | app.kubernetes.io/name: ingress-nginx
7 | name: ingress-nginx
8 | ---
9 | apiVersion: v1
10 | automountServiceAccountToken: true
11 | kind: ServiceAccount
12 | metadata:
13 | labels:
14 | app.kubernetes.io/component: controller
15 | app.kubernetes.io/instance: ingress-nginx
16 | app.kubernetes.io/name: ingress-nginx
17 | app.kubernetes.io/part-of: ingress-nginx
18 | app.kubernetes.io/version: 1.11.2
19 | name: ingress-nginx
20 | namespace: ingress-nginx
21 | ---
22 | apiVersion: v1
23 | automountServiceAccountToken: true
24 | kind: ServiceAccount
25 | metadata:
26 | labels:
27 | app.kubernetes.io/component: admission-webhook
28 | app.kubernetes.io/instance: ingress-nginx
29 | app.kubernetes.io/name: ingress-nginx
30 | app.kubernetes.io/part-of: ingress-nginx
31 | app.kubernetes.io/version: 1.11.2
32 | name: ingress-nginx-admission
33 | namespace: ingress-nginx
34 | ---
35 | apiVersion: rbac.authorization.k8s.io/v1
36 | kind: Role
37 | metadata:
38 | labels:
39 | app.kubernetes.io/component: controller
40 | app.kubernetes.io/instance: ingress-nginx
41 | app.kubernetes.io/name: ingress-nginx
42 | app.kubernetes.io/part-of: ingress-nginx
43 | app.kubernetes.io/version: 1.11.2
44 | name: ingress-nginx
45 | namespace: ingress-nginx
46 | rules:
47 | - apiGroups:
48 | - ""
49 | resources:
50 | - namespaces
51 | verbs:
52 | - get
53 | - apiGroups:
54 | - ""
55 | resources:
56 | - configmaps
57 | - pods
58 | - secrets
59 | - endpoints
60 | verbs:
61 | - get
62 | - list
63 | - watch
64 | - apiGroups:
65 | - ""
66 | resources:
67 | - services
68 | verbs:
69 | - get
70 | - list
71 | - watch
72 | - apiGroups:
73 | - networking.k8s.io
74 | resources:
75 | - ingresses
76 | verbs:
77 | - get
78 | - list
79 | - watch
80 | - apiGroups:
81 | - networking.k8s.io
82 | resources:
83 | - ingresses/status
84 | verbs:
85 | - update
86 | - apiGroups:
87 | - networking.k8s.io
88 | resources:
89 | - ingressclasses
90 | verbs:
91 | - get
92 | - list
93 | - watch
94 | - apiGroups:
95 | - coordination.k8s.io
96 | resourceNames:
97 | - ingress-nginx-leader
98 | resources:
99 | - leases
100 | verbs:
101 | - get
102 | - update
103 | - apiGroups:
104 | - coordination.k8s.io
105 | resources:
106 | - leases
107 | verbs:
108 | - create
109 | - apiGroups:
110 | - ""
111 | resources:
112 | - events
113 | verbs:
114 | - create
115 | - patch
116 | - apiGroups:
117 | - discovery.k8s.io
118 | resources:
119 | - endpointslices
120 | verbs:
121 | - list
122 | - watch
123 | - get
124 | ---
125 | apiVersion: rbac.authorization.k8s.io/v1
126 | kind: Role
127 | metadata:
128 | labels:
129 | app.kubernetes.io/component: admission-webhook
130 | app.kubernetes.io/instance: ingress-nginx
131 | app.kubernetes.io/name: ingress-nginx
132 | app.kubernetes.io/part-of: ingress-nginx
133 | app.kubernetes.io/version: 1.11.2
134 | name: ingress-nginx-admission
135 | namespace: ingress-nginx
136 | rules:
137 | - apiGroups:
138 | - ""
139 | resources:
140 | - secrets
141 | verbs:
142 | - get
143 | - create
144 | ---
145 | apiVersion: rbac.authorization.k8s.io/v1
146 | kind: ClusterRole
147 | metadata:
148 | labels:
149 | app.kubernetes.io/instance: ingress-nginx
150 | app.kubernetes.io/name: ingress-nginx
151 | app.kubernetes.io/part-of: ingress-nginx
152 | app.kubernetes.io/version: 1.11.2
153 | name: ingress-nginx
154 | rules:
155 | - apiGroups:
156 | - ""
157 | resources:
158 | - configmaps
159 | - endpoints
160 | - nodes
161 | - pods
162 | - secrets
163 | - namespaces
164 | verbs:
165 | - list
166 | - watch
167 | - apiGroups:
168 | - coordination.k8s.io
169 | resources:
170 | - leases
171 | verbs:
172 | - list
173 | - watch
174 | - apiGroups:
175 | - ""
176 | resources:
177 | - nodes
178 | verbs:
179 | - get
180 | - apiGroups:
181 | - ""
182 | resources:
183 | - services
184 | verbs:
185 | - get
186 | - list
187 | - watch
188 | - apiGroups:
189 | - networking.k8s.io
190 | resources:
191 | - ingresses
192 | verbs:
193 | - get
194 | - list
195 | - watch
196 | - apiGroups:
197 | - ""
198 | resources:
199 | - events
200 | verbs:
201 | - create
202 | - patch
203 | - apiGroups:
204 | - networking.k8s.io
205 | resources:
206 | - ingresses/status
207 | verbs:
208 | - update
209 | - apiGroups:
210 | - networking.k8s.io
211 | resources:
212 | - ingressclasses
213 | verbs:
214 | - get
215 | - list
216 | - watch
217 | - apiGroups:
218 | - discovery.k8s.io
219 | resources:
220 | - endpointslices
221 | verbs:
222 | - list
223 | - watch
224 | - get
225 | ---
226 | apiVersion: rbac.authorization.k8s.io/v1
227 | kind: ClusterRole
228 | metadata:
229 | labels:
230 | app.kubernetes.io/component: admission-webhook
231 | app.kubernetes.io/instance: ingress-nginx
232 | app.kubernetes.io/name: ingress-nginx
233 | app.kubernetes.io/part-of: ingress-nginx
234 | app.kubernetes.io/version: 1.11.2
235 | name: ingress-nginx-admission
236 | rules:
237 | - apiGroups:
238 | - admissionregistration.k8s.io
239 | resources:
240 | - validatingwebhookconfigurations
241 | verbs:
242 | - get
243 | - update
244 | ---
245 | apiVersion: rbac.authorization.k8s.io/v1
246 | kind: RoleBinding
247 | metadata:
248 | labels:
249 | app.kubernetes.io/component: controller
250 | app.kubernetes.io/instance: ingress-nginx
251 | app.kubernetes.io/name: ingress-nginx
252 | app.kubernetes.io/part-of: ingress-nginx
253 | app.kubernetes.io/version: 1.11.2
254 | name: ingress-nginx
255 | namespace: ingress-nginx
256 | roleRef:
257 | apiGroup: rbac.authorization.k8s.io
258 | kind: Role
259 | name: ingress-nginx
260 | subjects:
261 | - kind: ServiceAccount
262 | name: ingress-nginx
263 | namespace: ingress-nginx
264 | ---
265 | apiVersion: rbac.authorization.k8s.io/v1
266 | kind: RoleBinding
267 | metadata:
268 | labels:
269 | app.kubernetes.io/component: admission-webhook
270 | app.kubernetes.io/instance: ingress-nginx
271 | app.kubernetes.io/name: ingress-nginx
272 | app.kubernetes.io/part-of: ingress-nginx
273 | app.kubernetes.io/version: 1.11.2
274 | name: ingress-nginx-admission
275 | namespace: ingress-nginx
276 | roleRef:
277 | apiGroup: rbac.authorization.k8s.io
278 | kind: Role
279 | name: ingress-nginx-admission
280 | subjects:
281 | - kind: ServiceAccount
282 | name: ingress-nginx-admission
283 | namespace: ingress-nginx
284 | ---
285 | apiVersion: rbac.authorization.k8s.io/v1
286 | kind: ClusterRoleBinding
287 | metadata:
288 | labels:
289 | app.kubernetes.io/instance: ingress-nginx
290 | app.kubernetes.io/name: ingress-nginx
291 | app.kubernetes.io/part-of: ingress-nginx
292 | app.kubernetes.io/version: 1.11.2
293 | name: ingress-nginx
294 | roleRef:
295 | apiGroup: rbac.authorization.k8s.io
296 | kind: ClusterRole
297 | name: ingress-nginx
298 | subjects:
299 | - kind: ServiceAccount
300 | name: ingress-nginx
301 | namespace: ingress-nginx
302 | ---
303 | apiVersion: rbac.authorization.k8s.io/v1
304 | kind: ClusterRoleBinding
305 | metadata:
306 | labels:
307 | app.kubernetes.io/component: admission-webhook
308 | app.kubernetes.io/instance: ingress-nginx
309 | app.kubernetes.io/name: ingress-nginx
310 | app.kubernetes.io/part-of: ingress-nginx
311 | app.kubernetes.io/version: 1.11.2
312 | name: ingress-nginx-admission
313 | roleRef:
314 | apiGroup: rbac.authorization.k8s.io
315 | kind: ClusterRole
316 | name: ingress-nginx-admission
317 | subjects:
318 | - kind: ServiceAccount
319 | name: ingress-nginx-admission
320 | namespace: ingress-nginx
321 | ---
322 | apiVersion: v1
323 | data:
324 | allow-snippet-annotations: "false"
325 | kind: ConfigMap
326 | metadata:
327 | labels:
328 | app.kubernetes.io/component: controller
329 | app.kubernetes.io/instance: ingress-nginx
330 | app.kubernetes.io/name: ingress-nginx
331 | app.kubernetes.io/part-of: ingress-nginx
332 | app.kubernetes.io/version: 1.11.2
333 | name: ingress-nginx-controller
334 | namespace: ingress-nginx
335 | ---
336 | apiVersion: v1
337 | kind: Service
338 | metadata:
339 | labels:
340 | app.kubernetes.io/component: controller
341 | app.kubernetes.io/instance: ingress-nginx
342 | app.kubernetes.io/name: ingress-nginx
343 | app.kubernetes.io/part-of: ingress-nginx
344 | app.kubernetes.io/version: 1.11.2
345 | name: ingress-nginx-controller
346 | namespace: ingress-nginx
347 | spec:
348 | ipFamilies:
349 | - IPv4
350 | ipFamilyPolicy: SingleStack
351 | ports:
352 | - appProtocol: http
353 | name: http
354 | port: 80
355 | protocol: TCP
356 | targetPort: http
357 | nodePort: 30080
358 | - appProtocol: https
359 | name: https
360 | port: 443
361 | protocol: TCP
362 | targetPort: https
363 | nodePort: 30443
364 | selector:
365 | app.kubernetes.io/component: controller
366 | app.kubernetes.io/instance: ingress-nginx
367 | app.kubernetes.io/name: ingress-nginx
368 | type: NodePort
369 | ---
370 | apiVersion: v1
371 | kind: Service
372 | metadata:
373 | labels:
374 | app.kubernetes.io/component: controller
375 | app.kubernetes.io/instance: ingress-nginx
376 | app.kubernetes.io/name: ingress-nginx
377 | app.kubernetes.io/part-of: ingress-nginx
378 | app.kubernetes.io/version: 1.11.2
379 | name: ingress-nginx-controller-admission
380 | namespace: ingress-nginx
381 | spec:
382 | ports:
383 | - appProtocol: https
384 | name: https-webhook
385 | port: 443
386 | targetPort: webhook
387 | selector:
388 | app.kubernetes.io/component: controller
389 | app.kubernetes.io/instance: ingress-nginx
390 | app.kubernetes.io/name: ingress-nginx
391 | type: ClusterIP
392 | ---
393 | apiVersion: apps/v1
394 | kind: Deployment
395 | metadata:
396 | labels:
397 | app.kubernetes.io/component: controller
398 | app.kubernetes.io/instance: ingress-nginx
399 | app.kubernetes.io/name: ingress-nginx
400 | app.kubernetes.io/part-of: ingress-nginx
401 | app.kubernetes.io/version: 1.11.2
402 | name: ingress-nginx-controller
403 | namespace: ingress-nginx
404 | spec:
405 | minReadySeconds: 0
406 | revisionHistoryLimit: 10
407 | selector:
408 | matchLabels:
409 | app.kubernetes.io/component: controller
410 | app.kubernetes.io/instance: ingress-nginx
411 | app.kubernetes.io/name: ingress-nginx
412 | strategy:
413 | rollingUpdate:
414 | maxUnavailable: 1
415 | type: RollingUpdate
416 | template:
417 | metadata:
418 | labels:
419 | app.kubernetes.io/component: controller
420 | app.kubernetes.io/instance: ingress-nginx
421 | app.kubernetes.io/name: ingress-nginx
422 | app.kubernetes.io/part-of: ingress-nginx
423 | app.kubernetes.io/version: 1.11.2
424 | spec:
425 | containers:
426 | - args:
427 | - /nginx-ingress-controller
428 | - --election-id=ingress-nginx-leader
429 | - --controller-class=k8s.io/ingress-nginx
430 | - --ingress-class=nginx
431 | - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
432 | - --validating-webhook=:8443
433 | - --validating-webhook-certificate=/usr/local/certificates/cert
434 | - --validating-webhook-key=/usr/local/certificates/key
435 | - --enable-metrics=false
436 | env:
437 | - name: POD_NAME
438 | valueFrom:
439 | fieldRef:
440 | fieldPath: metadata.name
441 | - name: POD_NAMESPACE
442 | valueFrom:
443 | fieldRef:
444 | fieldPath: metadata.namespace
445 | - name: LD_PRELOAD
446 | value: /usr/local/lib/libmimalloc.so
447 | image: registry.k8s.io/ingress-nginx/controller:v1.11.2@sha256:d5f8217feeac4887cb1ed21f27c2674e58be06bd8f5184cacea2a69abaf78dce
448 | imagePullPolicy: IfNotPresent
449 | lifecycle:
450 | preStop:
451 | exec:
452 | command:
453 | - /wait-shutdown
454 | livenessProbe:
455 | failureThreshold: 5
456 | httpGet:
457 | path: /healthz
458 | port: 10254
459 | scheme: HTTP
460 | initialDelaySeconds: 10
461 | periodSeconds: 10
462 | successThreshold: 1
463 | timeoutSeconds: 1
464 | name: controller
465 | ports:
466 | - containerPort: 80
467 | name: http
468 | protocol: TCP
469 | - containerPort: 443
470 | name: https
471 | protocol: TCP
472 | - containerPort: 8443
473 | name: webhook
474 | protocol: TCP
475 | readinessProbe:
476 | failureThreshold: 3
477 | httpGet:
478 | path: /healthz
479 | port: 10254
480 | scheme: HTTP
481 | initialDelaySeconds: 10
482 | periodSeconds: 10
483 | successThreshold: 1
484 | timeoutSeconds: 1
485 | resources:
486 | requests:
487 | cpu: 100m
488 | memory: 90Mi
489 | securityContext:
490 | allowPrivilegeEscalation: false
491 | capabilities:
492 | add:
493 | - NET_BIND_SERVICE
494 | drop:
495 | - ALL
496 | readOnlyRootFilesystem: false
497 | runAsNonRoot: true
498 | runAsUser: 101
499 | seccompProfile:
500 | type: RuntimeDefault
501 | volumeMounts:
502 | - mountPath: /usr/local/certificates/
503 | name: webhook-cert
504 | readOnly: true
505 | dnsPolicy: ClusterFirst
506 | nodeSelector:
507 | kubernetes.io/os: linux
508 | serviceAccountName: ingress-nginx
509 | terminationGracePeriodSeconds: 300
510 | volumes:
511 | - name: webhook-cert
512 | secret:
513 | secretName: ingress-nginx-admission
514 | ---
515 | apiVersion: batch/v1
516 | kind: Job
517 | metadata:
518 | labels:
519 | app.kubernetes.io/component: admission-webhook
520 | app.kubernetes.io/instance: ingress-nginx
521 | app.kubernetes.io/name: ingress-nginx
522 | app.kubernetes.io/part-of: ingress-nginx
523 | app.kubernetes.io/version: 1.11.2
524 | name: ingress-nginx-admission-create
525 | namespace: ingress-nginx
526 | spec:
527 | template:
528 | metadata:
529 | labels:
530 | app.kubernetes.io/component: admission-webhook
531 | app.kubernetes.io/instance: ingress-nginx
532 | app.kubernetes.io/name: ingress-nginx
533 | app.kubernetes.io/part-of: ingress-nginx
534 | app.kubernetes.io/version: 1.11.2
535 | name: ingress-nginx-admission-create
536 | spec:
537 | containers:
538 | - args:
539 | - create
540 | - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
541 | - --namespace=$(POD_NAMESPACE)
542 | - --secret-name=ingress-nginx-admission
543 | env:
544 | - name: POD_NAMESPACE
545 | valueFrom:
546 | fieldRef:
547 | fieldPath: metadata.namespace
548 | image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.3@sha256:a320a50cc91bd15fd2d6fa6de58bd98c1bd64b9a6f926ce23a600d87043455a3
549 | imagePullPolicy: IfNotPresent
550 | name: create
551 | securityContext:
552 | allowPrivilegeEscalation: false
553 | capabilities:
554 | drop:
555 | - ALL
556 | readOnlyRootFilesystem: true
557 | runAsNonRoot: true
558 | runAsUser: 65532
559 | seccompProfile:
560 | type: RuntimeDefault
561 | nodeSelector:
562 | kubernetes.io/os: linux
563 | restartPolicy: OnFailure
564 | serviceAccountName: ingress-nginx-admission
565 | ---
566 | apiVersion: batch/v1
567 | kind: Job
568 | metadata:
569 | labels:
570 | app.kubernetes.io/component: admission-webhook
571 | app.kubernetes.io/instance: ingress-nginx
572 | app.kubernetes.io/name: ingress-nginx
573 | app.kubernetes.io/part-of: ingress-nginx
574 | app.kubernetes.io/version: 1.11.2
575 | name: ingress-nginx-admission-patch
576 | namespace: ingress-nginx
577 | spec:
578 | template:
579 | metadata:
580 | labels:
581 | app.kubernetes.io/component: admission-webhook
582 | app.kubernetes.io/instance: ingress-nginx
583 | app.kubernetes.io/name: ingress-nginx
584 | app.kubernetes.io/part-of: ingress-nginx
585 | app.kubernetes.io/version: 1.11.2
586 | name: ingress-nginx-admission-patch
587 | spec:
588 | containers:
589 | - args:
590 | - patch
591 | - --webhook-name=ingress-nginx-admission
592 | - --namespace=$(POD_NAMESPACE)
593 | - --patch-mutating=false
594 | - --secret-name=ingress-nginx-admission
595 | - --patch-failure-policy=Fail
596 | env:
597 | - name: POD_NAMESPACE
598 | valueFrom:
599 | fieldRef:
600 | fieldPath: metadata.namespace
601 | image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.3@sha256:a320a50cc91bd15fd2d6fa6de58bd98c1bd64b9a6f926ce23a600d87043455a3
602 | imagePullPolicy: IfNotPresent
603 | name: patch
604 | securityContext:
605 | allowPrivilegeEscalation: false
606 | capabilities:
607 | drop:
608 | - ALL
609 | readOnlyRootFilesystem: true
610 | runAsNonRoot: true
611 | runAsUser: 65532
612 | seccompProfile:
613 | type: RuntimeDefault
614 | nodeSelector:
615 | kubernetes.io/os: linux
616 | restartPolicy: OnFailure
617 | serviceAccountName: ingress-nginx-admission
618 | ---
619 | apiVersion: networking.k8s.io/v1
620 | kind: IngressClass
621 | metadata:
622 | labels:
623 | app.kubernetes.io/component: controller
624 | app.kubernetes.io/instance: ingress-nginx
625 | app.kubernetes.io/name: ingress-nginx
626 | app.kubernetes.io/part-of: ingress-nginx
627 | app.kubernetes.io/version: 1.11.2
628 | name: nginx
629 | spec:
630 | controller: k8s.io/ingress-nginx
631 | ---
632 | apiVersion: admissionregistration.k8s.io/v1
633 | kind: ValidatingWebhookConfiguration
634 | metadata:
635 | labels:
636 | app.kubernetes.io/component: admission-webhook
637 | app.kubernetes.io/instance: ingress-nginx
638 | app.kubernetes.io/name: ingress-nginx
639 | app.kubernetes.io/part-of: ingress-nginx
640 | app.kubernetes.io/version: 1.11.2
641 | name: ingress-nginx-admission
642 | webhooks:
643 | - admissionReviewVersions:
644 | - v1
645 | clientConfig:
646 | service:
647 | name: ingress-nginx-controller-admission
648 | namespace: ingress-nginx
649 | path: /networking/v1/ingresses
650 | failurePolicy: Fail
651 | matchPolicy: Equivalent
652 | name: validate.nginx.ingress.kubernetes.io
653 | rules:
654 | - apiGroups:
655 | - networking.k8s.io
656 | apiVersions:
657 | - v1
658 | operations:
659 | - CREATE
660 | - UPDATE
661 | resources:
662 | - ingresses
663 | sideEffects: None
664 |
--------------------------------------------------------------------------------
/modules/k8s_provisioner/main.tf:
--------------------------------------------------------------------------------
1 | resource "aws_key_pair" "k8s_key" {
2 | key_name = var.key_name
3 | public_key = var.public_key
4 | }
5 |
6 | resource "aws_security_group" "this" {
7 | count = var.instance_count
8 |
9 | vpc_id = var.vpc_id
10 |
11 | dynamic "ingress" {
12 | for_each = var.security_group_rules
13 | content {
14 | from_port = ingress.value.from_port
15 | to_port = ingress.value.to_port
16 | protocol = ingress.value.protocol
17 | cidr_blocks = ingress.value.cidr_blocks
18 | }
19 | }
20 |
21 | dynamic "egress" {
22 | for_each = var.security_group_rules
23 | content {
24 | from_port = 0
25 | to_port = 0
26 | protocol = "-1"
27 | cidr_blocks = ["0.0.0.0/0"]
28 | }
29 | }
30 |
31 | tags = {
32 | Name = "PICK-K8S-SG-Instance-${count.index + 1}"
33 | }
34 | }
35 |
36 | resource "aws_subnet" "k8s_subnet" {
37 | vpc_id = var.vpc_id
38 | cidr_block = var.k8s_subnet_cidr
39 | availability_zone = var.k8s_subnet_az
40 |
41 | map_public_ip_on_launch = true
42 |
43 | tags = {
44 | Name = "PICK-K8S-Subnet"
45 | }
46 | }
47 |
48 | resource "aws_subnet" "k8s_subnet_2" {
49 | vpc_id = var.vpc_id
50 | cidr_block = var.k8s_subnet_cidr_2
51 | availability_zone = var.k8s_subnet_az_2
52 |
53 | map_public_ip_on_launch = true
54 |
55 | tags = {
56 | Name = "PICK-K8S-Subnet-2"
57 | }
58 | }
59 |
60 | resource "aws_instance" "control_plane" {
61 | ami = var.ami
62 | instance_type = var.cp_instance_type
63 | key_name = aws_key_pair.k8s_key.key_name
64 | subnet_id = aws_subnet.k8s_subnet.id
65 |
66 | root_block_device {
67 | volume_size = var.volume_size
68 | }
69 |
70 | vpc_security_group_ids = [aws_security_group.this[0].id]
71 |
72 | tags = {
73 | Name = "PICK-K8S-Control-Plane"
74 | }
75 |
76 | provisioner "remote-exec" {
77 | inline = [
78 | <<-EOF
79 | cat <
/dev/null
108 | sudo apt-get update && sudo apt-get install -y containerd.io
109 | sudo containerd config default | sudo tee /etc/containerd/config.toml
110 | sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
111 | sudo sed -i 's/^KUBELET_EXTRA_ARGS=.*/KUBELET_EXTRA_ARGS=--max-pods=110/' /etc/default/kubelet
112 | sudo systemctl restart containerd
113 | sudo systemctl enable --now kubelet
114 | sudo kubeadm init --pod-network-cidr=10.10.0.0/16 --apiserver-advertise-address=${aws_instance.control_plane.private_ip}
115 | mkdir -p $HOME/.kube
116 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
117 | sudo chown $(id -u):$(id -g) $HOME/.kube/config
118 | ################ INSTALAR AUTOCOMPLETE E ALIAS ######################
119 | kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
120 | echo 'alias k=kubectl' >>~/.bashrc
121 | echo 'complete -F __start_kubectl k' >>~/.bashrc
122 | #####################################################################
123 | JOIN_COMMAND=$(kubeadm token create --print-join-command)
124 | aws ssm put-parameter --name "k8s_join_command" --value "$JOIN_COMMAND" --type "SecureString" --overwrite
125 | KUBECONFIG_FILE=$(cat ~/.kube/config)
126 | aws ssm put-parameter --name "k8s_kubeconfig" --value "$KUBECONFIG_FILE" --type "SecureString" --tier Advanced --overwrite
127 | #WeaveNet
128 | kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
129 | EOF
130 | ]
131 |
132 | connection {
133 | type = "ssh"
134 | host = self.public_ip
135 | user = "ubuntu"
136 | private_key = var.private_key
137 | }
138 | }
139 | }
140 |
141 | resource "aws_lb" "k8s_alb" {
142 | name = "k8s-control-plane-alb"
143 | internal = false
144 | load_balancer_type = "application"
145 | security_groups = [aws_security_group.this[0].id]
146 | subnets = [aws_subnet.k8s_subnet.id, aws_subnet.k8s_subnet_2.id]
147 |
148 | enable_deletion_protection = false
149 | idle_timeout = 60
150 |
151 | tags = {
152 | Name = "PICK-K8S-Control-Plane-ALB"
153 | }
154 | }
155 |
156 | resource "aws_lb_target_group" "k8s_tg_https" {
157 | name = "k8s-control-plane-tg-https"
158 | port = 30443
159 | protocol = "HTTPS"
160 | vpc_id = var.vpc_id
161 | target_type = "instance"
162 |
163 | health_check {
164 | path = "/healthz"
165 | interval = 30
166 | timeout = 5
167 | healthy_threshold = 2
168 | unhealthy_threshold = 2
169 | matcher = "200"
170 | }
171 | }
172 |
173 | resource "aws_lb_target_group_attachment" "k8s_tg_attachment_https" {
174 | target_group_arn = aws_lb_target_group.k8s_tg_https.arn
175 | target_id = aws_instance.control_plane.id
176 | port = 30443
177 | }
178 |
179 | resource "aws_lb_listener" "k8s_listener_http" {
180 | load_balancer_arn = aws_lb.k8s_alb.arn
181 | port = 80
182 | protocol = "HTTP"
183 |
184 | default_action {
185 | type = "redirect"
186 |
187 | redirect {
188 | port = "443"
189 | protocol = "HTTPS"
190 | status_code = "HTTP_301"
191 | }
192 | }
193 | }
194 |
195 | resource "aws_lb_listener" "k8s_listener_https" {
196 | load_balancer_arn = aws_lb.k8s_alb.arn
197 | port = 443
198 | protocol = "HTTPS"
199 | ssl_policy = "ELBSecurityPolicy-2016-08"
200 | certificate_arn = "arn:aws:acm:us-east-1:381492273741:certificate/48066b99-9cc7-46f1-9e08-31aaeeb1a735"
201 |
202 | default_action {
203 | type = "forward"
204 | target_group_arn = aws_lb_target_group.k8s_tg_https.arn
205 | }
206 | }
207 |
208 | resource "aws_route53_record" "dns_records" {
209 | for_each = toset(var.dns_names)
210 | zone_id = "Z0250850H44ROGORV6C9"
211 | name = each.value
212 | type = "A"
213 |
214 | alias {
215 | name = aws_lb.k8s_alb.dns_name
216 | zone_id = aws_lb.k8s_alb.zone_id
217 | evaluate_target_health = true
218 | }
219 |
220 | lifecycle {
221 | create_before_destroy = true
222 | }
223 | }
224 |
225 | resource "aws_instance" "worker" {
226 | count = var.instance_count - 1
227 | ami = var.ami
228 | instance_type = var.instance_type
229 | key_name = aws_key_pair.k8s_key.key_name
230 | subnet_id = aws_subnet.k8s_subnet.id
231 |
232 | root_block_device {
233 | volume_size = var.volume_size
234 | }
235 |
236 | vpc_security_group_ids = [aws_security_group.this[count.index + 1].id]
237 |
238 | tags = {
239 | Name = "PICK-K8S-Worker-${count.index + 1}"
240 | }
241 |
242 | provisioner "remote-exec" {
243 | inline = [
244 | <<-EOF
245 | cat < /dev/null
274 | sudo apt-get update && sudo apt-get install -y containerd.io
275 | sudo containerd config default | sudo tee /etc/containerd/config.toml
276 | sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
277 | sudo systemctl restart containerd
278 | sudo systemctl enable --now kubelet
279 | ################ INSTALAR AUTOCOMPLETE E ALIAS ######################
280 | kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
281 | echo 'alias k=kubectl' >>~/.bashrc
282 | echo 'complete -F __start_kubectl k' >>~/.bashrc
283 | #####################################################################
284 | JOIN_COMMAND=$(aws ssm get-parameter --name "k8s_join_command" --query "Parameter.Value" --with-decryption --output text)
285 | sudo $JOIN_COMMAND
286 | ################# INSTALANDO AS FERRAMENTAS QUE IREI UTILIZAR #######################
287 | if [ "$(hostname)" = "PICK-worker-1" ]; then
288 | mkdir ~/.kube
289 | aws ssm get-parameter --name "k8s_kubeconfig" --query "Parameter.Value" --with-decryption --output text > ~/.kube/config
290 | sudo chmod 600 /home/ubuntu/.kube/config
291 | #Ingress Controller
292 | git clone https://github.com/FabioBartoli/LINUXtips-PICK.git
293 | kubectl apply --validate=false -f ./LINUXtips-PICK/modules/k8s_provisioner/ingress-deploy.yaml
294 | kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
295 | # Helm
296 | curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
297 | chmod 700 get_helm.sh
298 | ./get_helm.sh
299 | # Adicionando repos ao Helm
300 | helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
301 | helm repo add harbor https://helm.goharbor.io
302 | helm repo add kyverno https://kyverno.github.io/kyverno/
303 | helm repo add ingress https://fabiobartoli.github.io/LINUXtips-PICK/manifests/helm/ingress/
304 | helm repo add giropops-app https://fabiobartoli.github.io/LINUXtips-PICK/manifests/helm/giropops-app/
305 | helm repo add kedacore https://kedacore.github.io/charts
306 | helm repo update
307 | kubectl create ns harbor && kubectl create ns monitoring && kubectl create ns locust && kubectl create ns giropops
308 | fi
309 | EOF
310 | ]
311 | connection {
312 | type = "ssh"
313 | host = self.public_ip
314 | user = "ubuntu"
315 | private_key = var.private_key
316 | }
317 | }
318 | depends_on = [aws_instance.control_plane]
319 | }
320 |
--------------------------------------------------------------------------------
/modules/k8s_provisioner/output.tf:
--------------------------------------------------------------------------------
1 | output "control_plane_public_ip" {
2 | value = aws_instance.control_plane.public_ip
3 | }
4 |
5 | output "worker_public_ips" {
6 | value = aws_instance.worker[*].public_ip
7 | }
8 |
9 | output "k8s_alb_dns_name" {
10 | description = "DNS name of the Kubernetes control plane ALB"
11 | value = aws_lb.k8s_alb.dns_name
12 | }
--------------------------------------------------------------------------------
/modules/k8s_provisioner/variables.tf:
--------------------------------------------------------------------------------
1 | variable "ami" {}
2 | variable "cp_instance_type" {}
3 | variable "instance_type" {}
4 | variable "volume_size" {}
5 | variable "instance_count" {}
6 | variable "vpc_id" {}
7 | variable "k8s_subnet_cidr" {}
8 | variable "k8s_subnet_cidr_2" {}
9 | variable "k8s_subnet_az" {}
10 | variable "k8s_subnet_az_2" {}
11 | variable "AWS_ACCESS_KEY_ID" {}
12 | variable "AWS_SECRET_ACCESS_KEY" {}
13 | variable "private_key" {}
14 | variable "public_key" {}
15 | variable "security_group_rules" {
16 | type = list(object({
17 | protocol = string
18 | from_port = number
19 | to_port = number
20 | cidr_blocks = list(string)
21 | }))
22 | }
23 |
24 | variable "key_name" {
25 | description = "The name of the key pair to use for the instances"
26 | default = "k8s-key"
27 | }
28 |
29 | variable "dns_names" {
30 | type = list(string)
31 | default = [
32 | "giropops-senhas.fabiobartoli.com.br",
33 | "grafana.fabiobartoli.com.br",
34 | "harbor.fabiobartoli.com.br",
35 | "locust.fabiobartoli.com.br",
36 | "prometheus.fabiobartoli.com.br"
37 | ]
38 | }
--------------------------------------------------------------------------------
/monitoring/grafana-alert.json:
--------------------------------------------------------------------------------
1 | {
2 | "apiVersion": 1,
3 | "groups": [
4 | {
5 | "orgId": 1,
6 | "name": "Evaluation",
7 | "folder": "Giropops-Alerts",
8 | "interval": "1m",
9 | "rules": [
10 | {
11 | "uid": "ddw507ksjsfeoc",
12 | "title": "Giropops-Notify",
13 | "condition": "C",
14 | "data": [
15 | {
16 | "refId": "A",
17 | "relativeTimeRange": {
18 | "from": 600,
19 | "to": 0
20 | },
21 | "datasourceUid": "prometheus",
22 | "model": {
23 | "disableTextWrap": false,
24 | "editorMode": "builder",
25 | "expr": "kube_deployment_status_replicas{deployment=\"giropops-senhas\"}",
26 | "fullMetaSearch": false,
27 | "includeNullMetadata": true,
28 | "instant": true,
29 | "intervalMs": 1000,
30 | "legendFormat": "__auto",
31 | "maxDataPoints": 43200,
32 | "range": false,
33 | "refId": "A",
34 | "useBackend": false
35 | }
36 | },
37 | {
38 | "refId": "B",
39 | "relativeTimeRange": {
40 | "from": 600,
41 | "to": 0
42 | },
43 | "datasourceUid": "__expr__",
44 | "model": {
45 | "conditions": [
46 | {
47 | "evaluator": {
48 | "params": [],
49 | "type": "gt"
50 | },
51 | "operator": {
52 | "type": "and"
53 | },
54 | "query": {
55 | "params": [
56 | "B"
57 | ]
58 | },
59 | "reducer": {
60 | "params": [],
61 | "type": "last"
62 | },
63 | "type": "query"
64 | }
65 | ],
66 | "datasource": {
67 | "type": "__expr__",
68 | "uid": "__expr__"
69 | },
70 | "expression": "A",
71 | "intervalMs": 1000,
72 | "maxDataPoints": 43200,
73 | "reducer": "last",
74 | "refId": "B",
75 | "type": "reduce"
76 | }
77 | },
78 | {
79 | "refId": "C",
80 | "relativeTimeRange": {
81 | "from": 600,
82 | "to": 0
83 | },
84 | "datasourceUid": "__expr__",
85 | "model": {
86 | "conditions": [
87 | {
88 | "evaluator": {
89 | "params": [
90 | 6
91 | ],
92 | "type": "gt"
93 | },
94 | "operator": {
95 | "type": "and"
96 | },
97 | "query": {
98 | "params": [
99 | "C"
100 | ]
101 | },
102 | "reducer": {
103 | "params": [],
104 | "type": "last"
105 | },
106 | "type": "query"
107 | }
108 | ],
109 | "datasource": {
110 | "type": "__expr__",
111 | "uid": "__expr__"
112 | },
113 | "expression": "B",
114 | "intervalMs": 1000,
115 | "maxDataPoints": 43200,
116 | "refId": "C",
117 | "type": "threshold"
118 | }
119 | }
120 | ],
121 | "noDataState": "NoData",
122 | "execErrState": "Error",
123 | "for": "1m",
124 | "annotations": {
125 | "summary": "Atenção! Número de deployments do giropops-senhas está alto!! ⚠️ ⚠️ ⚠️"
126 | },
127 | "labels": {},
128 | "isPaused": false,
129 | "notification_settings": {
130 | "receiver": "Fabio Bartoli"
131 | }
132 | }
133 | ]
134 | }
135 | ]
136 | }
--------------------------------------------------------------------------------
/monitoring/prometheus-metrics.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: monitoring.coreos.com/v1
2 | kind: ServiceMonitor
3 | metadata:
4 | name: giropops-senhas-servicemonitor
5 | namespace: monitoring
6 | labels:
7 | release: kube-prometheus
8 | spec:
9 | selector:
10 | matchLabels:
11 | app: giropops-senhas
12 | endpoints:
13 | - port: tcp-app
14 | path: /metrics
15 | interval: 30s
16 | namespaceSelector:
17 | matchNames:
18 | - giropops
--------------------------------------------------------------------------------
/monitoring/proxy-prometheus.yaml:
--------------------------------------------------------------------------------
1 | # based on https://github.com/kubermatic/kubeone/issues/1215#issuecomment-992471229
2 | apiVersion: v1
3 | kind: ConfigMap
4 | metadata:
5 | name: metrics-proxy-config
6 | namespace: monitoring
7 | data:
8 | haproxy.cfg: |
9 | defaults
10 | mode http
11 | timeout connect 5000ms
12 | timeout client 5000ms
13 | timeout server 5000ms
14 | default-server maxconn 10
15 |
16 | frontend kube-controller-manager
17 | bind ${NODE_IP}:10257
18 | mode tcp
19 | default_backend kube-controller-manager
20 |
21 | backend kube-controller-manager
22 | mode tcp
23 | server kube-controller-manager 127.0.0.1:10257
24 |
25 | frontend kube-scheduler
26 | bind ${NODE_IP}:10259
27 | mode tcp
28 | default_backend kube-scheduler
29 |
30 | backend kube-scheduler
31 | mode tcp
32 | server kube-scheduler 127.0.0.1:10259
33 |
34 | frontend kube-proxy
35 | bind ${NODE_IP}:10249
36 | http-request deny if !{ path /metrics }
37 | default_backend kube-proxy
38 |
39 | backend kube-proxy
40 | server kube-proxy 127.0.0.1:10249
41 |
42 | frontend etcd
43 | bind ${NODE_IP}:2381
44 | http-request deny if !{ path /metrics }
45 | default_backend etcd
46 |
47 | backend etcd
48 | server etcd 127.0.0.1:2381
49 | ---
50 | apiVersion: apps/v1
51 | kind: DaemonSet
52 | metadata:
53 | name: metrics-proxy
54 | namespace: monitoring
55 | spec:
56 | selector:
57 | matchLabels:
58 | app: metrics-proxy
59 | template:
60 | metadata:
61 | labels:
62 | app: metrics-proxy
63 | spec:
64 | containers:
65 | - env:
66 | - name: NODE_IP
67 | valueFrom:
68 | fieldRef:
69 | apiVersion: v1
70 | fieldPath: status.hostIP
71 | image: docker.io/haproxy:2.5
72 | name: haproxy
73 | securityContext:
74 | allowPrivilegeEscalation: false
75 | runAsUser: 99 # 'haproxy' user
76 | volumeMounts:
77 | - mountPath: /usr/local/etc/haproxy
78 | name: config
79 | hostNetwork: true
80 | tolerations:
81 | - effect: NoSchedule
82 | key: node-role.kubernetes.io/master
83 | operator: Exists
84 | - effect: NoSchedule
85 | key: node-role.kubernetes.io/control-plane
86 | operator: Exists
87 | volumes:
88 | - configMap:
89 | name: metrics-proxy-config
90 | name: config
--------------------------------------------------------------------------------
/scripts/install-helms.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Instalando o Harbor
4 | kubectl config set-context --current --namespace=harbor
5 | helm install harbor harbor/harbor --set expose.type=clusterIP --set expose.tls.auto.commonName=fabiobartoli.com.br \
6 | --set persistence.enabled=false --set externalURL=https://harbor.fabiobartoli.com.br \
7 | --set fullnameOverride=harbor-harbor --set trivy.enabled=true --namespace harbor
8 | # Instalando o Kube-Prometheus
9 | kubectl config set-context --current --namespace=monitoring
10 | helm install kube-prometheus prometheus-community/kube-prometheus-stack
11 | # Ajustando a captura de logs do Kubeadm
12 | kubectl apply -f /home/ubuntu/LINUXtips-PICK/monitoring/proxy-prometheus.yaml
13 | # Instalando o Kyverno
14 | kubectl config set-context --current --namespace=default
15 | helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace
16 | # Criando Regras do Kyverno
17 | kubectl apply -f /home/ubuntu/LINUXtips-PICK/security/kyverno/
18 | # Instalando o Locust
19 | sudo mkdir -p /usr/src/app/scripts/
20 | kubectl apply -f /home/ubuntu/LINUXtips-PICK/manifests/locust/
21 | # Passando a Secret de Login do Docker
22 | kubectl apply -f /home/ubuntu/LINUXtips-PICK/security/kyverno/docker-cred.yaml -n giropops
23 | kubectl apply -f /home/ubuntu/LINUXtips-PICK/security/kyverno/docker-cred.yaml -n kyverno
24 | # Instalando os Paths do Ingress
25 | helm install ingress-controller ingress/ingress-templates
26 | # Instalando o Metrics Server
27 | kubectl apply -f /home/ubuntu/LINUXtips-PICK/manifests/metrics-hpa/metrics-components.yaml
28 | # Instalando o Keda
29 | helm install keda kedacore/keda --namespace keda --create-namespace
30 | #helm install giropops giropops-app/giropops-chart --set env=stg
31 | #kubectl apply -f /home/ubuntu/LINUXtips-PICK/monitoring/prometheus-metrics.yaml
32 | #kubectl apply -f /home/ubuntu/LINUXtips-PICK/manifests/metrics-hpa/hpa-giropops.senhas.yaml
33 | #kubectl apply -f /home/ubuntu/LINUXtips-PICK/manifests/metrics-hpa/KEDA-scaledObjectRedis.yaml
--------------------------------------------------------------------------------
/security/kyverno/allow-only-harbor-registry.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kyverno.io/v1
2 | kind: ClusterPolicy
3 | metadata:
4 | name: ensure-images-from-trusted-registry
5 | namespace: giropops
6 | spec:
7 | validationFailureAction: Enforce
8 | rules:
9 | - name: trusted-registry
10 | match:
11 | resources:
12 | kinds:
13 | - Pod
14 | exclude:
15 | resources:
16 | namespaces:
17 | - harbor
18 | - ingress-nginx
19 | - kube-system
20 | - kyverno
21 | - monitoring
22 | - locust
23 | - keda
24 | validate:
25 | message: "Utilize imagens do Registry Harbor!"
26 | pattern:
27 | spec:
28 | containers:
29 | - name: "*"
30 | image: "harbor.fabiobartoli.com.br/*"
--------------------------------------------------------------------------------
/security/kyverno/disallow-root-user.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kyverno.io/v1
2 | kind: ClusterPolicy
3 | metadata:
4 | name: disallow-root-containers
5 | spec:
6 | validationFailureAction: Enforce
7 | rules:
8 | - name: disallow-root-user
9 | match:
10 | resources:
11 | kinds:
12 | - Pod
13 | exclude:
14 | resources:
15 | namespaces:
16 | - harbor
17 | - ingress-nginx
18 | - kube-system
19 | - kyverno
20 | - monitoring
21 | - keda
22 | validate:
23 | message: "Nenhum container pode ser executado como root! Ajuste as permissões"
24 | pattern:
25 | spec:
26 | containers:
27 | - securityContext:
28 | runAsUser: "!0"
29 |
--------------------------------------------------------------------------------
/security/kyverno/disalow-default-ns.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kyverno.io/v1
2 | kind: ClusterPolicy
3 | metadata:
4 | name: disallow-default-namespace
5 | annotations:
6 | pod-policies.kyverno.io/autogen-controllers: none
7 | policies.kyverno.io/title: Disallow Default Namespace
8 | policies.kyverno.io/minversion: 1.6.0
9 | policies.kyverno.io/category: Multi-Tenancy
10 | policies.kyverno.io/severity: medium
11 | policies.kyverno.io/subject: Pod
12 | spec:
13 | validationFailureAction: Enforce
14 | failurePolicy: Fail
15 | background: true
16 | rules:
17 | - name: validate-namespace
18 | match:
19 | any:
20 | - resources:
21 | kinds:
22 | - Pod
23 | validate:
24 | message: "Não é possível utilizar o namespace default!"
25 | pattern:
26 | metadata:
27 | namespace: "!default"
28 | - name: validate-podcontroller-namespace
29 | match:
30 | any:
31 | - resources:
32 | kinds:
33 | - DaemonSet
34 | - Deployment
35 | - Job
36 | - StatefulSet
37 | validate:
38 | message: "Using 'default' namespace is not allowed for pod controllers."
39 | pattern:
40 | metadata:
41 | namespace: "!default"
--------------------------------------------------------------------------------
/security/kyverno/docker-cred.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | data:
3 | .dockerconfigjson: ewoJImF1dGhzIjogewoJCSJoYXJib3IuZmFiaW9iYXJ0b2xpLmNvbS5iciI6IHsKCQkJImF1dGgiOiAiWm1GaWFXOWlZWEowYjJ4cE9sSndUbVpLTkZGRVpGVjBTbEJoYjFkaGRVZzFNMHBGTW5reVEycHUiCgkJfQoJfQp9
4 | kind: Secret
5 | metadata:
6 | name: regcred
7 | type: kubernetes.io/dockerconfigjson
--------------------------------------------------------------------------------
/security/kyverno/harbor-signature.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kyverno.io/v1
2 | kind: ClusterPolicy
3 | metadata:
4 | name: require-harbor-signature
5 | spec:
6 | validationFailureAction: Enforce
7 | background: false
8 | webhookTimeoutSeconds: 30
9 | failurePolicy: Fail
10 | rules:
11 | - name: require-harbor-signature
12 | match:
13 | any:
14 | - resources:
15 | kinds:
16 | - Pod
17 | - Deployment
18 | exclude:
19 | resources:
20 | namespaces:
21 | - harbor
22 | - ingress-nginx
23 | - kube-system
24 | - kyverno
25 | - monitoring
26 | - keda
27 | verifyImages:
28 | - imageReferences:
29 | - "harbor.fabiobartoli.com.br*"
30 | imageRegistryCredentials:
31 | secrets:
32 | - regcred
33 | attestors:
34 | - count: 1
35 | entries:
36 | - keys:
37 | publicKeys: |-
38 | -----BEGIN PUBLIC KEY-----
39 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjNhvsucfj6vfWeCfqGcXuFq01ewa
40 | +QhEAYBVkwg1IADM2CYIatTiEJiQDSNIeIiB9NUwfTJken9wkAMq8M4YxQ==
41 | -----END PUBLIC KEY-----
42 | rekor:
43 | ignoreTlog: true
44 | url: https://rekor.sigstore.dev
--------------------------------------------------------------------------------
/security/kyverno/require-probes.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kyverno.io/v1
2 | kind: ClusterPolicy
3 | metadata:
4 | name: require-pod-probes
5 | annotations:
6 | pod-policies.kyverno.io/autogen-controllers: DaemonSet,Deployment,StatefulSet
7 | policies.kyverno.io/title: Require Pod Probes
8 | policies.kyverno.io/category: Best Practices, EKS Best Practices
9 | policies.kyverno.io/severity: medium
10 | policies.kyverno.io/subject: Pod
11 | spec:
12 | validationFailureAction: Enforce
13 | failurePolicy: Fail
14 | background: true
15 | rules:
16 | - name: validate-probes
17 | match:
18 | any:
19 | - resources:
20 | kinds:
21 | - Pod
22 | exclude:
23 | any:
24 | - resources:
25 | namespaces:
26 | - harbor
27 | - ingress-nginx
28 | - kube-system
29 | - kyverno
30 | - monitoring
31 | - locust
32 | - keda
33 | preconditions:
34 | all:
35 | - key: "{{request.operation || 'BACKGROUND'}}"
36 | operator: AnyIn
37 | value:
38 | - CREATE
39 | - UPDATE
40 | validate:
41 | message: "Você deve incluir as Probies para fazer deploy!"
42 | foreach:
43 | - list: request.object.spec.containers[]
44 | deny:
45 | conditions:
46 | all:
47 | - key: livenessProbe
48 | operator: AllNotIn
49 | value: "{{ element.keys(@)[] }}"
50 | - key: startupProbe
51 | operator: AllNotIn
52 | value: "{{ element.keys(@)[] }}"
53 | - key: readinessProbe
54 | operator: AllNotIn
55 | value: "{{ element.keys(@)[] }}"
--------------------------------------------------------------------------------
/security/kyverno/verify-sensitive-vars.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kyverno.io/v1
2 | kind: ClusterPolicy
3 | metadata:
4 | name: disallow-sensitive-env-vars
5 | spec:
6 | validationFailureAction: Enforce
7 | failurePolicy: Fail
8 | rules:
9 | - name: disallow-sensitive-env-vars
10 | match:
11 | any:
12 | - resources:
13 | kinds:
14 | - Pod
15 | exclude:
16 | resources:
17 | namespaces:
18 | - harbor
19 | - ingress-nginx
20 | - kube-system
21 | - kyverno
22 | - monitoring
23 | - keda
24 | validate:
25 | message: "Secrets não devem ser montadas como variáveis!"
26 | pattern:
27 | spec:
28 | containers:
29 | - name: "*"
30 | =(env):
31 | - =(valueFrom):
32 | X(secretKeyRef): "null"
33 | - name: secrets-not-from-envfrom
34 | match:
35 | any:
36 | - resources:
37 | kinds:
38 | - Pod
39 | exclude:
40 | resources:
41 | namespaces:
42 | - harbor
43 | - ingress-nginx
44 | - kube-system
45 | - kyverno
46 | - monitoring
47 | validate:
48 | message: "Secrets não devem ser montadas como variáveis!"
49 | pattern:
50 | spec:
51 | containers:
52 | - name: "*"
53 | =(envFrom):
54 | - X(secretRef): "null"
55 |
--------------------------------------------------------------------------------
/security/melange/apko.yaml:
--------------------------------------------------------------------------------
1 | contents:
2 | repositories:
3 | - https://dl-cdn.alpinelinux.org/alpine/edge/main
4 | - /work/packages
5 | packages:
6 | - alpine-baselayout
7 | - giropops-senhas
8 | - curl
9 | accounts:
10 | groups:
11 | - groupname: nonroot
12 | gid: 65532
13 | users:
14 | - username: nonroot
15 | uid: 65532
16 | gid: 65532
17 | run-as: 65532
18 | environment:
19 | FLASK_APP: "/usr/bin/giropops-senhas"
20 | entrypoint:
21 | command: /usr/bin/giropops-senhas
22 |
--------------------------------------------------------------------------------
/security/melange/melange.yaml:
--------------------------------------------------------------------------------
1 | package:
2 | name: giropops-senhas
3 | version: 0.1
4 | description: Password Generator by LinuxTips
5 | dependencies:
6 | runtime:
7 | - python3
8 |
9 | environment:
10 | contents:
11 | keyring:
12 | - ./melange.rsa.pub
13 | repositories:
14 | - https://dl-cdn.alpinelinux.org/alpine/edge/main
15 | - https://dl-cdn.alpinelinux.org/alpine/edge/community
16 | packages:
17 | - alpine-baselayout-data
18 | - ca-certificates-bundle
19 | - busybox
20 | - gcc
21 | - musl-dev
22 | - python3
23 | - python3-dev
24 | - py3-pip
25 | - py3-virtualenv
26 | pipeline:
27 | - name: Build Python application
28 | runs: |
29 | EXECDIR="${{targets.destdir}}/usr/bin"
30 | WEBAPPDIR="${{targets.destdir}}/usr/share/webapps/giropops-senhas"
31 | mkdir -p "${EXECDIR}" "${WEBAPPDIR}"
32 | echo "#!/usr/share/webapps/giropops-senhas/venv/bin/python3" > "${EXECDIR}/giropops-senhas"
33 | cat app.py >> "${EXECDIR}/giropops-senhas"
34 | chmod +x "${EXECDIR}/giropops-senhas"
35 | virtualenv "${WEBAPPDIR}/venv"
36 | cp -r templates/ static/ ${WEBAPPDIR}/
37 | sh -c "source '${WEBAPPDIR}/venv/bin/activate' && pip install -r requirements.txt"
--------------------------------------------------------------------------------