Add observability platform Ansible project

Deploys the Grafana stack (Prometheus/Alertmanager/Loki/Tempo/Grafana with
Alloy as collector) and the ELK stack (Filebeat/Logstash/Elasticsearch/
Kibana) via Docker Compose on a target host. External to the application
repo, pre-built by the mentor.
This commit is contained in:
Movses Aslanyan
2026-09-05 08:11:34 +03:30
parent eb99cdbb8c
commit bffc42c9d3
26 changed files with 1056 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

@@ -0,0 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#07111f"/><stop offset="1" stop-color="#111a2d"/></linearGradient>
<filter id="shadow"><feDropShadow dx="0" dy="10" stdDeviation="12" flood-opacity=".25"/></filter>
<marker id="blueArrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0 0L10 5L0 10Z" fill="#35b9ff"/></marker>
<marker id="orangeArrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0 0L10 5L0 10Z" fill="#ff9f43"/></marker>
<marker id="redArrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0 0L10 5L0 10Z" fill="#ff5f6d"/></marker>
<style>
text{font-family:Inter,Segoe UI,Arial,sans-serif;fill:#eaf2ff}.title{font-size:42px;font-weight:800}.sub{font-size:18px;fill:#9fb0c9}.layer{font-size:15px;font-weight:700;letter-spacing:2px;fill:#7185a3}.box{fill:#121f35;stroke:#314762;stroke-width:2;rx:18;filter:url(#shadow)}.boxtitle{font-size:23px;font-weight:750}.meta{font-size:15px;fill:#afbdd1}.pill{fill:#1d304d;stroke:#405a7a}.pilltext{font-size:14px;fill:#d7e6fb}.flow{fill:none;stroke:#35b9ff;stroke-width:4;marker-end:url(#blueArrow)}.query{fill:none;stroke:#ff9f43;stroke-width:4;stroke-dasharray:12 9;marker-start:url(#orangeArrow);marker-end:url(#orangeArrow)}.alert{fill:none;stroke:#ff5f6d;stroke-width:4;marker-end:url(#redArrow)}.label{font-size:14px;font-weight:650;paint-order:stroke;stroke:#0a1424;stroke-width:7px;stroke-linejoin:round}.stage{fill:#0b1728;stroke:#223651;stroke-width:1.5;rx:22}
</style>
</defs>
<rect width="1920" height="1080" fill="url(#bg)"/>
<text x="70" y="74" class="title">ELK + Grafana — Operational Data Flow</text>
<text x="70" y="108" class="sub">Collection → processing → indexed storage → search, dashboards and alert delivery</text>
<rect x="45" y="150" width="295" height="750" class="stage"/><text x="70" y="186" class="layer">DATA SOURCES</text>
<rect x="365" y="150" width="285" height="750" class="stage"/><text x="390" y="186" class="layer">COLLECTION</text>
<rect x="675" y="150" width="285" height="750" class="stage"/><text x="700" y="186" class="layer">PROCESSING</text>
<rect x="985" y="150" width="390" height="750" class="stage"/><text x="1010" y="186" class="layer">INDEXED STORAGE</text>
<rect x="1400" y="150" width="475" height="750" class="stage"/><text x="1425" y="186" class="layer">QUERY, VISUALIZE &amp; ALERT</text>
<g><rect x="70" y="235" width="245" height="130" class="box"/><circle cx="108" cy="277" r="22" fill="#4ea1ff"/><text x="101" y="285" font-size="24" font-weight="800">A</text><text x="145" y="278" class="boxtitle">Applications</text><text x="95" y="320" class="meta">JSON / text logs</text><text x="95" y="344" class="meta">trace_id in log context</text></g>
<g><rect x="70" y="430" width="245" height="130" class="box"/><circle cx="108" cy="472" r="22" fill="#6ad36a"/><text x="101" y="480" font-size="23" font-weight="800">S</text><text x="145" y="473" class="boxtitle">System logs</text><text x="95" y="515" class="meta">journald / syslog</text><text x="95" y="539" class="meta">auth and kernel events</text></g>
<g><rect x="70" y="625" width="245" height="130" class="box"/><circle cx="108" cy="667" r="22" fill="#9c7cff"/><text x="101" y="675" font-size="23" font-weight="800">C</text><text x="145" y="668" class="boxtitle">Containers</text><text x="95" y="710" class="meta">Docker JSON logs</text><text x="95" y="734" class="meta">Kubernetes log files</text></g>
<g><rect x="395" y="340" width="225" height="250" class="box" stroke="#36c5f0"/><circle cx="507" cy="405" r="38" fill="#16769a"/><text x="493" y="417" font-size="36" font-weight="850">F</text><text x="507" y="472" class="boxtitle" text-anchor="middle">Filebeat</text><text x="507" y="504" class="meta" text-anchor="middle">tail • multiline • metadata</text><rect x="430" y="530" width="155" height="34" rx="17" class="pill"/><text x="507" y="552" class="pilltext" text-anchor="middle">disk registry</text></g>
<g><rect x="705" y="340" width="225" height="250" class="box" stroke="#f5c142"/><circle cx="817" cy="405" r="38" fill="#876b10"/><text x="804" y="417" font-size="34" font-weight="850">L</text><text x="817" y="472" class="boxtitle" text-anchor="middle">Logstash</text><text x="817" y="504" class="meta" text-anchor="middle">parse • enrich • route</text><rect x="740" y="530" width="155" height="34" rx="17" class="pill"/><text x="817" y="552" class="pilltext" text-anchor="middle">persistent queue</text></g>
<g><rect x="1025" y="275" width="310" height="390" class="box" stroke="#31b8dc"/><text x="1180" y="325" class="boxtitle" text-anchor="middle">Elasticsearch cluster</text><circle cx="1110" cy="420" r="66" fill="#123c58" stroke="#43c5e8" stroke-width="4"/><circle cx="1248" cy="420" r="66" fill="#123c58" stroke="#43c5e8" stroke-width="4"/><circle cx="1179" cy="540" r="66" fill="#123c58" stroke="#43c5e8" stroke-width="4"/><text x="1110" y="413" font-size="20" text-anchor="middle" font-weight="750">data-1</text><text x="1110" y="440" class="meta" text-anchor="middle">primary</text><text x="1248" y="413" font-size="20" text-anchor="middle" font-weight="750">data-2</text><text x="1248" y="440" class="meta" text-anchor="middle">replica</text><text x="1179" y="533" font-size="20" text-anchor="middle" font-weight="750">data-3</text><text x="1179" y="560" class="meta" text-anchor="middle">replica</text><rect x="1080" y="610" width="200" height="34" rx="17" class="pill"/><text x="1180" y="632" class="pilltext" text-anchor="middle">data streams • ILM</text></g>
<g><rect x="1435" y="235" width="190" height="150" class="box" stroke="#e758a8"/><text x="1530" y="285" class="boxtitle" text-anchor="middle">Kibana</text><text x="1530" y="322" class="meta" text-anchor="middle">Discover / Lens</text><rect x="1470" y="340" width="120" height="30" rx="15" class="pill"/><text x="1530" y="361" class="pilltext" text-anchor="middle">TCP 5601</text></g>
<g><rect x="1660" y="235" width="190" height="150" class="box" stroke="#ff9830"/><text x="1755" y="285" class="boxtitle" text-anchor="middle">Grafana</text><text x="1755" y="322" class="meta" text-anchor="middle">Explore / dashboards</text><rect x="1695" y="340" width="120" height="30" rx="15" class="pill"/><text x="1755" y="361" class="pilltext" text-anchor="middle">TCP 3000</text></g>
<g><rect x="1495" y="625" width="295" height="150" class="box" stroke="#ff5f6d"/><text x="1642" y="675" class="boxtitle" text-anchor="middle">Notification channels</text><text x="1642" y="712" class="meta" text-anchor="middle">Slack • Email • PagerDuty</text><rect x="1560" y="730" width="165" height="30" rx="15" class="pill"/><text x="1642" y="751" class="pilltext" text-anchor="middle">webhook / SMTP</text></g>
<path d="M315 300 C355 300 355 385 395 385" class="flow"/><path d="M315 495 H395" class="flow"/><path d="M315 690 C355 690 355 545 395 545" class="flow"/>
<path d="M620 465 H705" class="flow"/><text x="662" y="442" class="label" text-anchor="middle">Beats/TCP</text><text x="662" y="462" class="label" text-anchor="middle">5044</text>
<path d="M930 465 H1025" class="flow"/><text x="977" y="425" class="label" text-anchor="middle">Bulk API</text><text x="977" y="445" class="label" text-anchor="middle">HTTP(S) 9200</text>
<path d="M1335 355 C1385 355 1385 310 1435 310" class="query"/><path d="M1335 500 C1450 500 1535 310 1660 310" class="query"/><text x="1393" y="482" class="label" text-anchor="middle">Search API :9200</text>
<path d="M1755 385 C1755 505 1680 545 1642 625" class="alert"/><path d="M1530 385 C1530 505 1580 550 1615 625" class="alert"/><text x="1720" y="555" class="label" text-anchor="middle">alert rules</text>
<rect x="70" y="945" width="1780" height="80" rx="18" fill="#0c1728" stroke="#263b58"/>
<line x1="110" y1="985" x2="180" y2="985" class="flow"/><text x="200" y="991" class="meta">ingest / write path</text><line x1="465" y1="985" x2="535" y2="985" class="query"/><text x="555" y="991" class="meta">query + response</text><line x1="830" y1="985" x2="900" y2="985" class="alert"/><text x="920" y="991" class="meta">alert delivery</text><text x="1270" y="991" class="meta">Production: enable TLS/RBAC, snapshots, ≥3 ES nodes and external secrets</text>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

@@ -0,0 +1,55 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">
<defs>
<linearGradient id="bg2" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#08101d"/><stop offset="1" stop-color="#171326"/></linearGradient>
<filter id="shadow2"><feDropShadow dx="0" dy="10" stdDeviation="12" flood-opacity=".25"/></filter>
<marker id="mBlue" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10Z" fill="#47b7ff"/></marker>
<marker id="mGreen" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10Z" fill="#55d187"/></marker>
<marker id="mPurple" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10Z" fill="#a987ff"/></marker>
<marker id="mOrange" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0 0L10 5L0 10Z" fill="#ff9a3d"/></marker>
<marker id="mRed" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto"><path d="M0 0L10 5L0 10Z" fill="#ff5f6d"/></marker>
<style>
text{font-family:Inter,Segoe UI,Arial,sans-serif;fill:#edf4ff}.title{font-size:42px;font-weight:800}.sub{font-size:18px;fill:#9fb0c9}.layer{font-size:15px;font-weight:700;letter-spacing:2px;fill:#7185a3}.stage{fill:#0c1626;stroke:#273a56;stroke-width:1.5;rx:22}.box{fill:#142138;stroke:#324967;stroke-width:2;rx:18;filter:url(#shadow2)}.boxtitle{font-size:23px;font-weight:750}.meta{font-size:15px;fill:#b2c0d3}.pill{fill:#1e304b;stroke:#3d5878}.pilltext{font-size:14px;fill:#d9e8fb}.metric{fill:none;stroke:#55d187;stroke-width:4;marker-end:url(#mGreen)}.log{fill:none;stroke:#47b7ff;stroke-width:4;marker-end:url(#mBlue)}.trace{fill:none;stroke:#a987ff;stroke-width:4;marker-end:url(#mPurple)}.query{fill:none;stroke:#ff9a3d;stroke-width:4;stroke-dasharray:12 9;marker-start:url(#mOrange);marker-end:url(#mOrange)}.alert{fill:none;stroke:#ff5f6d;stroke-width:4;marker-end:url(#mRed)}.label{font-size:14px;font-weight:650;paint-order:stroke;stroke:#0a1424;stroke-width:7px;stroke-linejoin:round}
</style>
</defs>
<rect width="1920" height="1080" fill="url(#bg2)"/>
<text x="70" y="74" class="title">Grafana Observability Stack — Operational Data Flow</text>
<text x="70" y="108" class="sub">Metrics (Prometheus) • logs (Loki) • traces (Tempo) • alert routing (Alertmanager) • unified exploration (Grafana)</text>
<rect x="45" y="150" width="300" height="750" class="stage"/><text x="70" y="186" class="layer">WORKLOADS &amp; HOSTS</text>
<rect x="370" y="150" width="300" height="750" class="stage"/><text x="395" y="186" class="layer">COLLECT &amp; EXPORT</text>
<rect x="695" y="150" width="390" height="750" class="stage"/><text x="720" y="186" class="layer">STORE &amp; QUERY</text>
<rect x="1110" y="150" width="295" height="750" class="stage"/><text x="1135" y="186" class="layer">ALERT PIPELINE</text>
<rect x="1430" y="150" width="445" height="750" class="stage"/><text x="1455" y="186" class="layer">EXPLORE &amp; CORRELATE</text>
<g><rect x="70" y="230" width="250" height="140" class="box"/><circle cx="110" cy="273" r="22" fill="#55d187"/><text x="102" y="281" font-size="22" font-weight="850">M</text><text x="148" y="275" class="boxtitle">App metrics</text><text x="95" y="318" class="meta">/metrics endpoint</text><text x="95" y="343" class="meta">Prometheus exposition</text></g>
<g><rect x="70" y="425" width="250" height="140" class="box"/><circle cx="110" cy="468" r="22" fill="#47b7ff"/><text x="103" y="476" font-size="22" font-weight="850">L</text><text x="148" y="470" class="boxtitle">Container logs</text><text x="95" y="513" class="meta">Docker socket / files</text><text x="95" y="538" class="meta">structured log records</text></g>
<g><rect x="70" y="620" width="250" height="140" class="box"/><circle cx="110" cy="663" r="22" fill="#a987ff"/><text x="103" y="671" font-size="22" font-weight="850">T</text><text x="148" y="665" class="boxtitle">Instrumented apps</text><text x="95" y="708" class="meta">OpenTelemetry SDK</text><text x="95" y="733" class="meta">spans + resource attrs</text></g>
<g><rect x="400" y="270" width="240" height="290" class="box" stroke="#ff9a3d"/><circle cx="520" cy="342" r="42" fill="#a95014"/><text x="501" y="355" font-size="34" font-weight="850">A</text><text x="520" y="415" class="boxtitle" text-anchor="middle">Grafana Alloy</text><text x="520" y="450" class="meta" text-anchor="middle">discover • label • batch</text><rect x="435" y="478" width="170" height="34" rx="17" class="pill"/><text x="520" y="500" class="pilltext" text-anchor="middle">OTLP 4317 / 4318</text><rect x="455" y="520" width="130" height="27" rx="14" class="pill"/><text x="520" y="539" class="pilltext" text-anchor="middle">UI 12345</text></g>
<g><rect x="400" y="635" width="240" height="150" class="box" stroke="#55d187"/><text x="520" y="685" class="boxtitle" text-anchor="middle">Node Exporter</text><text x="520" y="722" class="meta" text-anchor="middle">host CPU / RAM / disk</text><rect x="460" y="742" width="120" height="28" rx="14" class="pill"/><text x="520" y="762" class="pilltext" text-anchor="middle">TCP 9100</text></g>
<g><rect x="730" y="220" width="320" height="170" class="box" stroke="#55d187"/><text x="890" y="270" class="boxtitle" text-anchor="middle">Prometheus</text><text x="890" y="308" class="meta" text-anchor="middle">scrape • TSDB • PromQL • rules</text><rect x="812" y="335" width="156" height="30" rx="15" class="pill"/><text x="890" y="356" class="pilltext" text-anchor="middle">HTTP 9090</text></g>
<g><rect x="730" y="455" width="320" height="170" class="box" stroke="#47b7ff"/><text x="890" y="505" class="boxtitle" text-anchor="middle">Loki</text><text x="890" y="543" class="meta" text-anchor="middle">labels • chunks • LogQL</text><rect x="812" y="570" width="156" height="30" rx="15" class="pill"/><text x="890" y="591" class="pilltext" text-anchor="middle">HTTP 3100</text></g>
<g><rect x="730" y="690" width="320" height="170" class="box" stroke="#a987ff"/><text x="890" y="740" class="boxtitle" text-anchor="middle">Tempo</text><text x="890" y="778" class="meta" text-anchor="middle">trace blocks • TraceQL</text><rect x="785" y="805" width="210" height="30" rx="15" class="pill"/><text x="890" y="826" class="pilltext" text-anchor="middle">query 3200 • OTLP 4317</text></g>
<g><rect x="1145" y="300" width="225" height="200" class="box" stroke="#ff5f6d"/><text x="1257" y="355" class="boxtitle" text-anchor="middle">Alertmanager</text><text x="1257" y="393" class="meta" text-anchor="middle">group • dedupe • route</text><rect x="1182" y="420" width="150" height="30" rx="15" class="pill"/><text x="1257" y="441" class="pilltext" text-anchor="middle">HTTP 9093</text></g>
<g><rect x="1145" y="610" width="225" height="150" class="box" stroke="#ff5f6d"/><text x="1257" y="660" class="boxtitle" text-anchor="middle">Receivers</text><text x="1257" y="700" class="meta" text-anchor="middle">Slack • Email • PagerDuty</text><text x="1257" y="730" class="meta" text-anchor="middle">webhook / SMTP</text></g>
<g><rect x="1470" y="300" width="365" height="350" class="box" stroke="#ff9a3d"/><circle cx="1652" cy="388" r="50" fill="#ba5a14"/><text x="1631" y="404" font-size="42" font-weight="850">G</text><text x="1652" y="477" class="boxtitle" text-anchor="middle">Grafana</text><text x="1652" y="518" class="meta" text-anchor="middle">dashboards • Explore • correlations</text><rect x="1547" y="548" width="210" height="34" rx="17" class="pill"/><text x="1652" y="570" class="pilltext" text-anchor="middle">Metrics ↔ Logs ↔ Traces</text><rect x="1592" y="596" width="120" height="30" rx="15" class="pill"/><text x="1652" y="617" class="pilltext" text-anchor="middle">TCP 3000</text></g>
<path d="M320 300 C360 300 360 315 400 315" class="metric"/><text x="354" y="286" class="label" text-anchor="middle">scrape</text>
<path d="M320 495 H400" class="log"/><text x="360" y="480" class="label" text-anchor="middle">tail</text>
<path d="M320 690 C360 690 360 515 400 515" class="trace"/><text x="355" y="655" class="label" text-anchor="middle">OTLP</text>
<path d="M640 350 C680 350 690 305 730 305" class="metric"/><text x="684" y="292" class="label" text-anchor="middle">/metrics</text>
<path d="M640 485 C680 485 690 540 730 540" class="log"/><text x="685" y="513" class="label" text-anchor="middle">push API</text>
<path d="M640 520 C690 520 680 775 730 775" class="trace"/><text x="681" y="728" class="label" text-anchor="middle">OTLP/gRPC</text>
<path d="M640 710 C690 710 680 340 730 340" class="metric"/><text x="670" y="630" class="label" text-anchor="middle">scrape :9100</text>
<path d="M1050 305 H1145" class="alert"/><text x="1097" y="286" class="label" text-anchor="middle">firing alerts</text>
<path d="M1257 500 V610" class="alert"/><text x="1305" y="560" class="label">route</text>
<path d="M1050 305 C1210 210 1370 260 1470 365" class="query"/><path d="M1050 540 C1210 540 1340 470 1470 470" class="query"/><path d="M1050 775 C1220 775 1350 625 1470 575" class="query"/><text x="1300" y="452" class="label" text-anchor="middle">PromQL / LogQL / TraceQL</text>
<path d="M1050 760 C1090 720 1090 390 1050 350" class="metric"/><text x="1092" y="560" class="label" text-anchor="middle" transform="rotate(-90 1092 560)">span metrics + exemplars → remote_write</text>
<rect x="70" y="945" width="1780" height="80" rx="18" fill="#0c1728" stroke="#263b58"/>
<line x1="105" y1="982" x2="170" y2="982" class="metric"/><text x="190" y="988" class="meta">metrics</text><line x1="340" y1="982" x2="405" y2="982" class="log"/><text x="425" y="988" class="meta">logs</text><line x1="555" y1="982" x2="620" y2="982" class="trace"/><text x="640" y="988" class="meta">traces</text><line x1="780" y1="982" x2="845" y2="982" class="query"/><text x="865" y="988" class="meta">query + response</text><line x1="1080" y1="982" x2="1145" y2="982" class="alert"/><text x="1165" y="988" class="meta">alerts</text><text x="1390" y="988" class="meta">Correlation key: trace_id / exemplars</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB