fix: Fix kubeconfig for editor.

This commit is contained in:
Laur IVAN 2026-02-11 14:59:27 +01:00
parent b06be19c5a
commit b68634a624
34 changed files with 1319 additions and 3 deletions

View File

@ -6,10 +6,10 @@
"files.trimTrailingWhitespace": true,
"sops.defaults.ageKeyFile": "age.key",
"vs-kubernetes": {
"vs-kubernetes.kubeconfig": "./kubeconfig",
"vs-kubernetes.kubeconfig": "/home/laur/dev/ai/ops/homelab/kubeconfig",
"vs-kubernetes.knownKubeconfigs": [
"./kubeconfig"
]
"/home/laur/dev/ai/ops/homelab/kubeconfig"
]
},
"yaml.schemaStore.enable": true,
"yaml.schemas": {

View File

@ -0,0 +1 @@
# TODO: Fix this via homelab-u3p: Install homepage dashboard [dashboard, deployment, homepage]

View File

@ -0,0 +1 @@
# TODO: see implementation of external secrets

View File

@ -0,0 +1,130 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/refs/heads/main/helmrelease-helm-v2.json
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: &app publish-k8s-schemas
spec:
interval: 1h
chartRef:
kind: OCIRepository
name: app-template
values:
controllers:
*app :
type: cronjob
cronjob:
backoffLimit: 0
concurrencyPolicy: 'Replace'
failedJobsHistory: 1
schedule: '0 */4 * * *'
successfulJobsHistory: 0
initContainers:
generate-schemas:
image:
repository: ghcr.io/bjw-s-labs/k8s-crd-extractor
tag: 2025.12.22@sha256:176cc556053abba6fda83eeb398531cd33c3092553cab8a49a736f68972c057b
command: [/usr/bin/catatonit, --, sh]
args:
- -c
- /app/crd-extractor.sh && exec sh /config/map/generate-index.sh
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: { drop: [ALL] }
containers:
app:
image:
repository: ghcr.io/bjw-s-labs/wrangler
tag: 4.63.0@sha256:1e9dc1c872a6e9cc84ccfc50704c7a2fdfec1f8c8e28672dd7c083a008e4bf39
envFrom:
- secretRef:
name: *app
args:
- pages
- deploy
- /data/crdSchemas
- --project-name
- kubernetes-schemas
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
memory: 1Gi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: { drop: [ALL] }
defaultPodOptions:
restartPolicy: OnFailure
securityContext:
runAsGroup: 65534
runAsNonRoot: true
runAsUser: 65534
persistence:
tmpfs:
type: emptyDir
advancedMounts:
*app :
generate-schemas:
- path: /config/.datree
subPath: data
- path: /tmp
subPath: tmp
app:
- path: /config
subPath: config
- path: /data
subPath: data
config:
type: configMap
name: *app
advancedMounts:
*app :
generate-schemas:
- path: /config/map
readOnly: true
serviceAccount:
*app : {}
rbac:
roles:
*app :
type: ClusterRole
rules:
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
- customresourcedefinitions/status
verbs:
- get
- list
- watch
- apiGroups:
- apiregistration.k8s.io
resources:
- apiservices
- apiservices/status
verbs:
- get
- list
- watch
bindings:
*app :
type: ClusterRoleBinding
roleRef:
identifier: *app
subjects:
- identifier: *app

View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
cd /config/.datree/crdSchemas/
echo "creating index"
# Count stats
group_count=$(find . -maxdepth 1 -type d | wc -l)
group_count=$((group_count - 1))
schema_count=$(find . -name "*.json" | wc -l)
updated=$(date -u +"%Y-%m-%d")
echo "groups: $group_count - schemas: $schema_count"
# Generate schema cards HTML
schemas_html=""
for dir in */; do
dir_name="${dir%/}"
file_count=$(find "$dir" -maxdepth 1 -name "*.json" | wc -l)
files_html=""
for file in "$dir"*.json; do
if [ -f "$file" ]; then
filename=$(basename "$file")
files_html="${files_html}<a href=\"${file}\" class=\"file-link\">${filename}</a>"
fi
done
schemas_html="${schemas_html}<div class=\"group-card\"><div class=\"group-header\"><span class=\"group-name\">${dir_name}</span><span class=\"group-count\">${file_count}</span><svg class=\"chevron\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\"><path d=\"M4.427 5.427l3.396 3.396a.25.25 0 00.354 0l3.396-3.396A.25.25 0 0011.396 5H4.604a.25.25 0 00-.177.427z\"/></svg></div><div class=\"group-files\">${files_html}</div></div>"
done
# Copy template and inject data
cp /config/map/index.html index.html
sed -i "s|<!-- SCHEMAS_PLACEHOLDER -->|${schemas_html}|g" index.html
sed -i "s|<div class=\"stat-value\" id=\"group-count\">-</div>|<div class=\"stat-value\" id=\"group-count\">${group_count}</div>|g" index.html
sed -i "s|<div class=\"stat-value\" id=\"schema-count\">-</div>|<div class=\"stat-value\" id=\"schema-count\">${schema_count}</div>|g" index.html
sed -i "s|<div class=\"stat-value\" id=\"last-updated\">-</div>|<div class=\"stat-value\" id=\"last-updated\">${updated}</div>|g" index.html
echo "index created"

View File

@ -0,0 +1,391 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kubernetes Schemas | tholinka.dev</title>
<link rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>☸️</text></svg>">
<style>
:root {
--bg-primary: #0d1117;
--bg-secondary: #161b22;
--bg-tertiary: #21262d;
--text-primary: #fff;
--text-secondary: #eee;
--text-muted: #999;
--accent: #58a6ff;
--accent-hover: #79c0ff;
--border: #30363d;
--success: #3fb950;
--gradient-start: #58a6ff;
--gradient-end: #a371f7;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
header {
text-align: center;
padding: 3rem 0;
border-bottom: 1px solid var(--border);
margin-bottom: 2rem;
}
.logo {
max-width: 5rem;
max-height: 5rem;
}
h1 {
font-size: 2.5rem;
font-weight: 600;
background: linear-gradient(135deg, var(--gradient-start), var(--gradient-end));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.5rem;
}
.subtitle {
color: var(--text-secondary);
font-size: 1.1rem;
}
.usage-card {
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 2rem;
}
.usage-card h2 {
font-size: 1rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 1rem;
}
.code-block {
background: var(--bg-tertiary);
border-radius: 8px;
padding: 1rem 1.25rem;
font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
font-size: 0.9rem;
overflow-x: auto;
position: relative;
}
.code-block code {
color: var(--text-primary);
}
.code-block .comment {
color: var(--text-muted);
}
.code-block .string {
color: var(--success);
}
.search-container {
margin-bottom: 2rem;
}
.search-input {
width: 100%;
padding: 0.875rem 1.25rem;
font-size: 1rem;
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 8px;
color: var(--text-primary);
transition: border-color 0.2s, box-shadow 0.2s;
}
.search-input:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.15);
}
.search-input::placeholder {
color: var(--text-muted);
}
.stats {
display: flex;
gap: 2rem;
margin-bottom: 2rem;
flex-wrap: wrap;
}
.stat {
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 8px;
padding: 1rem 1.5rem;
flex: 1;
min-width: 150px;
}
.stat-value {
font-size: 2rem;
font-weight: 600;
color: var(--accent);
}
.stat-label {
color: var(--text-secondary);
font-size: 0.875rem;
}
.schemas-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 1rem;
}
.group-card {
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
transition: border-color 0.2s, transform 0.2s;
}
.group-card:hover {
border-color: var(--accent);
transform: translateY(-2px);
}
.group-header {
padding: 1rem 1.25rem;
background: var(--bg-tertiary);
border-bottom: 1px solid var(--border);
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.group-name {
font-weight: 600;
font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
font-size: 0.9rem;
color: var(--accent);
}
.group-count {
background: var(--bg-primary);
padding: 0.25rem 0.75rem;
border-radius: 999px;
font-size: 0.8rem;
color: var(--text-secondary);
}
.group-files {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.group-card.open .group-files {
max-height: 500px;
overflow-y: auto;
}
.file-link {
display: block;
padding: 0.625rem 1.25rem;
color: var(--text-primary);
text-decoration: none;
font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
font-size: 0.85rem;
border-bottom: 1px solid var(--border);
transition: background 0.15s;
}
.file-link:last-child {
border-bottom: none;
}
.file-link:hover {
background: var(--bg-tertiary);
color: var(--accent);
}
.chevron {
transition: transform 0.2s;
}
.group-card.open .chevron {
transform: rotate(180deg);
}
footer {
margin-top: 3rem;
padding-top: 2rem;
border-top: 1px solid var(--border);
text-align: center;
color: var(--text-secondary);
font-size: 0.875rem;
}
footer a {
color: var(--accent);
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
.hidden {
display: none !important;
}
@media (max-width: 768px) {
.container {
padding: 1rem;
}
header {
padding: 2rem 0;
}
h1 {
font-size: 1.75rem;
}
.schemas-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<svg class="logo" width="800px" height="800px" viewBox="0 -10.44 722.846 722.846"
xmlns="http://www.w3.org/2000/svg">
<path
d="M358.986 10.06a46.725 46.342 0 00-17.906 4.531L96.736 131.341a46.725 46.342 0 00-25.28 31.438l-60.282 262.25a46.725 46.342 0 006.344 35.531 46.725 46.342 0 002.656 3.688l169.125 210.28a46.725 46.342 0 0036.531 17.438l271.219-.062a46.725 46.342 0 0036.531-17.406l169.063-210.313a46.725 46.342 0 009.03-39.219L651.3 162.716a46.725 46.342 0 00-25.281-31.437L381.643 14.59a46.725 46.342 0 00-22.657-4.53z"
fill="#326ce5" />
<path
d="M361.408 99.307c-8.077.001-14.626 7.276-14.625 16.25 0 .138.028.27.03.406-.011 1.22-.07 2.689-.03 3.75.192 5.176 1.32 9.138 2 13.907 1.23 10.206 2.26 18.667 1.625 26.531-.62 2.965-2.803 5.677-4.75 7.562l-.344 6.188a190.337 190.337 0 00-26.438 4.062c-37.974 8.623-70.67 28.184-95.562 54.594a245.167 245.167 0 01-5.281-3.75c-2.612.353-5.25 1.159-8.688-.844-6.545-4.405-12.506-10.486-19.719-17.812-3.305-3.504-5.698-6.841-9.625-10.219-.891-.767-2.252-1.804-3.25-2.594-3.07-2.447-6.69-3.724-10.187-3.843-4.496-.154-8.824 1.604-11.656 5.156-5.036 6.315-3.424 15.968 3.593 21.562.071.057.147.101.219.157.964.781 2.145 1.783 3.031 2.437 4.167 3.077 7.973 4.652 12.125 7.094 8.747 5.402 15.999 9.88 21.75 15.281 2.246 2.394 2.639 6.613 2.938 8.438l4.687 4.187c-25.093 37.764-36.707 84.41-29.843 131.938l-6.125 1.781c-1.615 2.085-3.896 5.365-6.282 6.344-7.525 2.37-15.994 3.24-26.218 4.312-4.8.4-8.943.161-14.032 1.125-1.12.212-2.68.619-3.906.906l-.125.032c-.067.015-.155.048-.219.062-8.62 2.083-14.157 10.006-12.375 17.813 1.783 7.808 10.203 12.556 18.875 10.687.063-.014.154-.017.219-.031.098-.022.184-.07.281-.094 1.21-.265 2.724-.56 3.782-.843 5.003-1.34 8.626-3.308 13.125-5.032 9.676-3.47 17.691-6.37 25.5-7.5 3.26-.255 6.697 2.012 8.406 2.969l6.375-1.094c14.67 45.483 45.414 82.245 84.344 105.313l-2.657 6.375c.958 2.475 2.014 5.824 1.3 8.27-2.838 7.36-7.7 15.13-13.237 23.792-2.681 4.002-5.425 7.108-7.844 11.688-.579 1.096-1.316 2.78-1.875 3.937-3.759 8.043-1.002 17.305 6.219 20.782 7.266 3.497 16.284-.192 20.187-8.25.006-.012.026-.02.031-.032.004-.009-.004-.022 0-.03.556-1.143 1.344-2.645 1.813-3.72 2.072-4.747 2.762-8.815 4.219-13.406 3.87-9.72 5.995-19.919 11.322-26.274 1.459-1.74 3.837-2.41 6.303-3.07l3.312-6c33.938 13.027 71.927 16.523 109.875 7.907a189.77 189.77 0 0025.094-7.563c.93 1.651 2.661 4.826 3.125 5.625 2.506.815 5.24 1.236 7.469 4.531 3.985 6.81 6.71 14.865 10.031 24.594 1.457 4.591 2.178 8.66 4.25 13.406.472 1.082 1.256 2.605 1.812 3.75 3.895 8.085 12.943 11.787 20.22 8.282 7.219-3.478 9.979-12.74 6.218-20.782-.559-1.158-1.327-2.841-1.906-3.937-2.42-4.58-5.163-7.655-7.844-11.656-5.537-8.662-10.13-15.858-12.969-23.22-1.187-3.796.2-6.157 1.125-8.624-.554-.635-1.739-4.22-2.437-5.906 40.457-23.889 70.298-62.022 84.312-106.063 1.893.298 5.182.88 6.25 1.094 2.2-1.45 4.222-3.344 8.188-3.031 7.808 1.129 15.823 4.03 25.5 7.5 4.498 1.723 8.121 3.723 13.125 5.062 1.057.283 2.572.547 3.781.813.097.023.183.071.281.093.066.015.156.017.219.032 8.672 1.866 17.094-2.88 18.875-10.688 1.78-7.807-3.754-15.732-12.375-17.812-1.254-.286-3.032-.77-4.25-1-5.09-.964-9.231-.727-14.031-1.125-10.225-1.072-18.694-1.943-26.219-4.313-3.068-1.19-5.251-4.841-6.313-6.344l-5.906-1.718c3.062-22.155 2.237-45.212-3.062-68.282-5.349-23.284-14.8-44.58-27.407-63.343 1.515-1.378 4.377-3.911 5.188-4.657.237-2.624.033-5.375 2.75-8.281 5.751-5.4 13.003-9.879 21.75-15.281 4.152-2.443 7.99-4.017 12.156-7.094.942-.696 2.23-1.798 3.219-2.594 7.015-5.596 8.63-15.248 3.594-21.562-5.037-6.314-14.797-6.91-21.813-1.313-.998.791-2.353 1.823-3.25 2.594-3.926 3.378-6.351 6.714-9.656 10.219-7.213 7.326-13.174 13.438-19.719 17.844-2.836 1.65-6.99 1.08-8.875.968l-5.562 3.969c-31.72-33.26-74.905-54.525-121.406-58.656-.13-1.949-.3-5.471-.344-6.532-1.904-1.821-4.204-3.376-4.781-7.312-.637-7.864.426-16.325 1.656-26.531.679-4.769 1.807-8.73 2-13.907.044-1.176-.027-2.884-.031-4.156-.001-8.974-6.548-16.25-14.625-16.25zm-18.313 113.438l-4.344 76.718-.312.157c-.292 6.863-5.94 12.343-12.875 12.343-2.841 0-5.463-.912-7.594-2.468l-.125.062-62.906-44.594c19.333-19.01 44.063-33.06 72.562-39.53a154.125 154.125 0 0115.594-2.688zm36.656 0c33.274 4.092 64.045 19.159 87.625 42.25l-62.5 44.312-.218-.093c-5.548 4.051-13.364 3.046-17.688-2.375a12.807 12.807 0 01-2.812-7.47l-.063-.03zM232.126 283.62l57.438 51.375-.063.312c5.185 4.507 5.95 12.328 1.625 17.75a12.892 12.892 0 01-6.687 4.406l-.063.25-73.625 21.25c-3.747-34.265 4.329-67.573 21.375-95.343zm258.157.03c8.534 13.833 14.996 29.283 18.843 46.032 3.801 16.548 4.755 33.067 3.188 49.031l-74-21.312-.063-.313c-6.626-1.81-10.699-8.551-9.156-15.312a12.786 12.786 0 014.094-6.844l-.031-.156 57.125-51.125zm-140.657 55.313h23.532l14.625 18.282-5.25 22.812-21.125 10.156-21.188-10.187-5.25-22.813zm75.438 62.563c1-.05 1.995.04 2.969.219l.125-.157 76.156 12.875c-11.146 31.314-32.473 58.44-60.969 76.594l-29.562-71.406.093-.125c-2.715-6.31.002-13.71 6.25-16.719 1.6-.77 3.271-1.197 4.938-1.281zm-127.906.312c5.811.082 11.024 4.116 12.375 10.032.632 2.77.324 5.513-.72 7.937l.22.281-29.25 70.688c-27.348-17.549-49.13-43.824-60.782-76.063l75.5-12.812.125.156c.845-.155 1.701-.23 2.532-.219zm63.78 30.97a12.764 12.764 0 016.032 1.28c2.56 1.233 4.537 3.174 5.781 5.5h.282l37.218 67.25a154.256 154.256 0 01-14.875 4.157c-28.464 6.463-56.838 4.504-82.53-4.25l37.124-67.125h.063a12.91 12.91 0 0110.906-6.813z"
style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;marker:none;-inkscape-font-specification:Sans"
font-weight="400" color="#000000" fill="#ffffff" stroke="#ffffff" stroke-width=".25"
overflow="visible" font-family="Sans" />
</svg>
<h1>Kubernetes Schemas</h1>
<p class="subtitle">CRD JSON schemas from the tholinka.dev cluster</p>
</header>
<div class="usage-card">
<h2>Usage</h2>
<div class="code-block">
<code><span class="comment"># yaml-language-server: </span><span class="string">$schema=https://schemas.tholinka.dev/{group}/{kind}_{version}.json</span></code>
</div>
</div>
<div class="search-container">
<input type="text" class="search-input" id="search"
placeholder="Search schemas... (e.g., helmrelease, certificate, gateway)">
</div>
<div class="stats">
<div class="stat">
<div class="stat-value" id="group-count">-</div>
<div class="stat-label">API Groups</div>
</div>
<div class="stat">
<div class="stat-value" id="schema-count">-</div>
<div class="stat-label">Schemas</div>
</div>
<div class="stat">
<div class="stat-value" id="last-updated">-</div>
<div class="stat-label">Last Updated</div>
</div>
</div>
<div class="schemas-grid" id="schemas-grid">
<!-- SCHEMAS_PLACEHOLDER -->
</div>
<footer>
<p>
Generated by <a href="https://github.com/datreeio/CRDs-catalog" target="_blank">crd-extractor</a>
Hosted on <a href="https://pages.cloudflare.com" target="_blank">Cloudflare Pages</a>
<a href="https://github.com/tholinka/home-ops" target="_blank">Source</a>
</p>
</footer>
</div>
<script>
// Search functionality
const searchInput = document.getElementById('search');
const grid = document.getElementById('schemas-grid');
searchInput.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase();
const cards = grid.querySelectorAll('.group-card');
cards.forEach(card => {
const groupName = card.querySelector('.group-name').textContent.toLowerCase();
const files = card.querySelectorAll('.file-link');
let hasMatch = groupName.includes(query);
files.forEach(file => {
const fileName = file.textContent.toLowerCase();
if (fileName.includes(query)) {
hasMatch = true;
file.classList.remove('hidden');
} else if (query) {
file.classList.add('hidden');
} else {
file.classList.remove('hidden');
}
});
if (hasMatch) {
card.classList.remove('hidden');
if (query) card.classList.add('open');
} else {
card.classList.add('hidden');
}
});
});
// Toggle group expansion
grid.addEventListener('click', (e) => {
const header = e.target.closest('.group-header');
if (header) {
header.closest('.group-card').classList.toggle('open');
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,20 @@
---
# yaml-language-server: $schema=https://schemas.tholinka.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: publish-k8s-schemas
namespace: &namespace self-hosted
spec:
interval: 1h
path: ./kubernetes/apps/self-hosted/publish-k8s-schemas/app
postBuild:
substituteFrom:
- name: cluster-secrets
kind: Secret
prune: true
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: *namespace

View File

@ -0,0 +1,24 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: grafana-instance
spec:
path: ./kubernetes/apps/monitoring-system/grafana/instance
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: monitoring-system
interval: 10m
prune: true
wait: true
dependsOn:
#? wait for the 1password-connect secret store to be ready
- name: 1password-connect
namespace: security-system
- name: grafana-operator
- name: envoy-gateway
namespace: network-system
- name: openebs
namespace: storage-system

View File

@ -0,0 +1,21 @@
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: grafana-admin-password-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: onepassword
kind: ClusterSecretStore
target:
name: grafana-admin-password-secret
creationPolicy: Owner
data:
- secretKey: GF_SECURITY_ADMIN_PASSWORD
remoteRef:
key: Grafana Admin
property: password

View File

@ -0,0 +1,34 @@
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
name: prometheus
spec:
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasource:
type: prometheus
name: prometheus
access: proxy
isDefault: true
url: http://prometheus-operated:9090
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
name: alertmanager
spec:
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasource:
type: alertmanager
name: alertmanager
access: proxy
jsonData:
implementation: prometheus
url: http://alertmanager-operated:9093

View File

@ -0,0 +1,75 @@
---
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
name: grafana
labels:
grafana.internal/instance: grafana
spec:
config:
analytics:
check_for_updates: "false"
check_for_plugin_updates: "false"
feedback_links_enabled: "false"
reporting_enabled: "false"
server:
enable_gzip: "true"
root_url: https://grafana.admin.mirceanton.com
auth: {disable_login_form: "false"}
auth.anonymous: {enabled: "true"}
metrics: {enabled: "true"}
news: {news_feed_enabled: "false"}
plugins: {plugin_admin_enabled: "false"}
security: {angular_support_enabled: "true"}
deployment:
spec:
strategy:
type: Recreate
template:
spec:
containers:
- name: grafana
env:
- name: GF_SECURITY_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: grafana-admin-password-secret
key: GF_SECURITY_ADMIN_PASSWORD
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: {drop: ["ALL"]}
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
volumes:
- name: grafana-data
persistentVolumeClaim:
claimName: grafana-pvc
httpRoute:
spec:
hostnames: ["grafana.admin.mirceanton.com"]
parentRefs:
- name: envoy-admin
namespace: network-system
rules:
- backendRefs:
- name: grafana-service
port: 3000
persistentVolumeClaim:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
storageClassName: openebs-hostpath
disableDefaultSecurityContext: All

View File

@ -0,0 +1,9 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
#- ./admin.externalsecret.yaml
- ./data-sources.yaml
- ./grafana.yaml
- ./service-monitor.yaml

View File

@ -0,0 +1,19 @@
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: grafana
spec:
jobLabel: grafana
endpoints:
- port: grafana
path: /metrics
honorLabels: true
namespaceSelector:
matchNames: ["monitoring-system"]
selector:
matchLabels:
grafana.internal/instance: grafana

View File

@ -0,0 +1,7 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: []
#- ./operator.ks.yaml
#- ./instance.ks.yaml

View File

@ -0,0 +1,15 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: grafana-operator
spec:
path: ./kubernetes/apps/monitoring-system/grafana/operator
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: monitoring-system
interval: 10m
prune: true
wait: true

View File

@ -0,0 +1,16 @@
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: grafana-operator
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
configMapRef:
name: grafana-operator-dashboard
key: grafana-operator.json

View File

@ -0,0 +1,27 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: grafana-operator
spec:
interval: 10m
chartRef:
kind: OCIRepository
name: grafana-operator
values:
replicas: 1
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
memory: 64Mi
serviceMonitor: {enabled: true}
dashboard: {enabled: true}
maxConcurrentReconciles: 4
logging:
level: info
encoder: json

View File

@ -0,0 +1,13 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: grafana-operator
spec:
interval: 15m
url: oci://ghcr.io/grafana/helm-charts/grafana-operator
ref: {tag: 5.21.4}
layerSelector:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy

View File

@ -0,0 +1,20 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: &app headlamp
spec:
commonMetadata:
labels:
app.kubernetes.io/name: *app
path: ./kubernetes/apps/observability/headlamp/app
prune: true
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
interval: 1h
retryInterval: 2m
timeout: 5m
# TODO: Add OAuth integration.

View File

@ -0,0 +1,21 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
labels:
app.kubernetes.io/instance: headlamp
app.kubernetes.io/name: headlamp
app.kubernetes.io/part-of: headlamp
name: headlamp
spec:
hostnames:
- headlamp.kantai.xyz
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: envoy-internal
namespace: network
rules:
- backendRefs:
- name: headlamp
port: 80

View File

@ -0,0 +1,19 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: headlamp
spec:
interval: 1h
layerSelector:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy
ref:
tag: 0.40.0
url: oci://ghcr.io/home-operations/charts-mirror/headlamp
verify:
provider: cosign
matchOIDCIdentity:
- issuer: ^https://token.actions.githubusercontent.com$
subject: ^https://github.com/home-operations/charts-mirror.*$

View File

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./app.ks.yaml

View File

@ -0,0 +1,20 @@
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: kube-prometheus-stack
spec:
path: ./kubernetes/apps/monitoring-system/kube-prometheus-stack/app
sourceRef:
kind: GitRepository
name: flux-system
namespace: flux-system
targetNamespace: monitoring-system
interval: 10m
prune: true
wait: true
dependsOn:
- name: openebs
namespace: storage-system
- name: envoy-gateway
namespace: network-system

View File

@ -0,0 +1,143 @@
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-api-server
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/15761/revisions/20/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-coredns
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/15762/revisions/22/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-global
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/15757/revisions/43/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-namespaces
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/15758/revisions/44/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-nodes
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/15759/revisions/40/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-pods
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/15760/revisions/37/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: kubernetes-volumes
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/11454/revisions/14/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: node-exporter-full
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/1860/revisions/42/download
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: prometheus
spec:
allowCrossNamespaceImport: true
instanceSelector:
matchLabels:
grafana.internal/instance: grafana
datasources:
- datasourceName: prometheus
inputName: DS_PROMETHEUS
url: https://grafana.com/api/dashboards/19105/revisions/8/download

View File

@ -0,0 +1,208 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: kube-prometheus-stack
spec:
interval: 10m
chartRef:
kind: OCIRepository
name: kube-prometheus-stack
values:
crds: {enabled: true}
cleanPrometheusOperatorObjectNames: true
# ==========================================================================
# Alertmanager
# ==========================================================================
alertmanager:
enabled: true
route:
main:
enabled: true
hostnames: ["alertmanager.admin.mirceanton.com"]
parentRefs:
- name: envoy-admin
namespace: network-system
alertmanagerSpec:
# alertmanagerConfiguration: {name: alertmanager}
# =======================================
# App Settings
# =======================================
externalUrl: "https://alertmanager.admin.mirceanton.com"
logFormat: json
logLevel: info
# =======================================
# Resources
# =======================================
replicas: 1
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
memory: 128Mi
storage:
volumeClaimTemplate:
spec:
storageClassName: openebs-hostpath
resources:
requests:
storage: 1Gi
# ==========================================================================
# Prometheus Operator
# ==========================================================================
prometheusOperator:
enabled: true
# =======================================
# App Settings
# =======================================
logFormat: json
logLevel: info
# =======================================
# Resources
# =======================================
resources:
requests:
cpu: 20m
memory: 64Mi
limits:
memory: 128Mi
# ==========================================================================
# Prometheus
# ==========================================================================
prometheus:
enabled: true
route:
main:
enabled: true
hostnames: ["prometheus.admin.mirceanton.com"]
parentRefs:
- name: envoy-admin
namespace: network-system
prometheusSpec:
# =======================================
# App Settings
# =======================================
externalUrl: "https://prometheus.admin.mirceanton.com"
enableAdminAPI: true
retention: 14d
retentionSize: 50GB
logLevel: info
logFormat: json
# =======================================
#? Replace default Prometheus image with prompp and
#? override 'unsupported Prometheus version' error
# =======================================
version: v2.55.1
image:
registry: mirror.gcr.io
repository: prompp/prompp
tag: 0.7.4
# =======================================
# Security
# =======================================
securityContext:
runAsNonRoot: true
runAsUser: 64535
runAsGroup: 64535
fsGroup: 64535
# =======================================
#? Disable prometheus resource to be created with selectors based on
#? values in the helm deployment if a nil or {} value is provided
# =======================================
podMonitorSelectorNilUsesHelmValues: false
probeSelectorNilUsesHelmValues: false
ruleSelectorNilUsesHelmValues: false
scrapeConfigSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
# =======================================
# Resources
# =======================================
replicas: 1
shards: 1
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
memory: 1Gi
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: openebs-hostpath
resources:
requests:
storage: 50Gi
# ==========================================================================
# Grafana
# ==========================================================================
grafana:
enabled: false
forceDeployDashboards: true
operator:
dashboardsConfigMapRefEnabled: true
folder: monitoring-system
matchLabels:
grafana.internal/instance: grafana
# ==========================================================================
# Exporters
# ==========================================================================
coreDns: {enabled: true}
kubelet: {enabled: true}
kubeApiServer: {enabled: true}
kubeControllerManager: {enabled: true}
kubeScheduler: {enabled: true}
kubeProxy: {enabled: true}
kubeEtcd:
enabled: true
service:
selector:
component: kube-apiserver
nodeExporter: {enabled: true}
prometheus-node-exporter:
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
memory: 64Mi
kubeStateMetrics: {enabled: true}
kube-state-metrics:
resources:
requests:
cpu: 20m
memory: 64Mi
limits:
memory: 128Mi
# ==========================================================================
# Additional Settings
# ==========================================================================
additionalPrometheusRulesMap:
oom-rules:
groups:
- name: oom
rules:
- alert: OomKilled
annotations:
summary: Container {{ $labels.container }} in pod {{ $labels.namespace }}/{{ $labels.pod }} has been OOMKilled {{ $value }} times in the last 10 minutes.
expr: (kube_pod_container_status_restarts_total - kube_pod_container_status_restarts_total offset 10m >= 1) and ignoring (reason) min_over_time(kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}[10m]) == 1
labels:
severity: critical

View File

@ -0,0 +1,13 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: kube-prometheus-stack
spec:
interval: 15m
url: oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack
ref: {tag: 81.5.0}
layerSelector:
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
operation: copy

View File

@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./app.ks.yaml

View File

@ -0,0 +1,9 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: monitoring-system
resources:
- ./namespace.yaml
#- ./grafana
#- ./kube-prometheus-stack

View File

@ -0,0 +1,7 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: _
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled

View File

@ -0,0 +1,4 @@
# External secrets should be implemented.
# Most popular is 1password, but it's paid
# https://github.com/tholinka/home-ops implements secrets via bitwarden (which is free)