feat(secrets): add sealed-secrets management and Grafana monitoring installation
This commit is contained in:
@@ -40,12 +40,25 @@ install_argocd() {
|
||||
install_cert_manager
|
||||
install_argocd
|
||||
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.15.1/deploy/static/provider/baremetal/deploy.yaml
|
||||
# Restore sealed-secrets key before ArgoCD syncs so existing SealedSecrets decrypt correctly.
|
||||
# Export from old cluster first: ./sealed-secrets-key.sh export sealed-secrets-key-backup.yaml
|
||||
echo "🔑 Restoring sealed-secrets key..."
|
||||
read -rp "Path to sealed-secrets key backup (leave blank to skip): " KEY_FILE
|
||||
if [[ -n "$KEY_FILE" ]]; then
|
||||
./sealed-secrets-key.sh import "$KEY_FILE"
|
||||
else
|
||||
echo "⚠️ Skipped. SealedSecrets will fail to decrypt until key is imported."
|
||||
fi
|
||||
|
||||
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
|
||||
sleep 5s
|
||||
|
||||
kubectl apply -f ../eu-central-1/root-apps-app.yaml
|
||||
|
||||
echo "📊 Installing Grafana monitoring..."
|
||||
./metrics-deployment-values.sh
|
||||
echo "✅ Grafana monitoring installed!"
|
||||
|
||||
clear
|
||||
|
||||
ARGO_PW=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 --decode)
|
||||
|
||||
Executable
+136
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
read -rsp "Grafana Cloud API token: " GF_TOKEN
|
||||
echo
|
||||
|
||||
helm repo add grafana https://grafana.github.io/helm-charts &&
|
||||
helm repo update &&
|
||||
helm upgrade --install --rollback-on-failure --timeout 300s grafana-k8s-monitoring grafana/k8s-monitoring \
|
||||
--version "^4" --namespace "monitoring" --create-namespace --values - <<EOF
|
||||
cluster:
|
||||
name: nowchess
|
||||
destinations:
|
||||
grafana-cloud-metrics:
|
||||
type: prometheus
|
||||
url: https://prometheus-prod-65-prod-eu-west-2.grafana.net/api/prom/push
|
||||
auth:
|
||||
type: basic
|
||||
username: "3192630"
|
||||
password: ${GF_TOKEN}
|
||||
grafana-cloud-logs:
|
||||
type: loki
|
||||
url: https://logs-prod-012.grafana.net/loki/api/v1/push
|
||||
auth:
|
||||
type: basic
|
||||
username: "1591990"
|
||||
password: ${GF_TOKEN}
|
||||
gc-otlp-endpoint:
|
||||
type: otlp
|
||||
url: https://otlp-gateway-prod-eu-west-2.grafana.net/otlp
|
||||
protocol: http
|
||||
auth:
|
||||
type: basic
|
||||
username: "1634203"
|
||||
password: ${GF_TOKEN}
|
||||
clusterMetrics:
|
||||
enabled: false
|
||||
collector: alloy-metrics
|
||||
hostMetrics:
|
||||
enabled: false
|
||||
collector: alloy-metrics
|
||||
linuxHosts:
|
||||
enabled: false
|
||||
windowsHosts:
|
||||
enabled: false
|
||||
clusterEvents:
|
||||
enabled: true
|
||||
collector: alloy-singleton
|
||||
namespaces:
|
||||
- nowchess
|
||||
- nowchess-staging
|
||||
podLogsViaLoki:
|
||||
enabled: true
|
||||
collector: alloy-logs
|
||||
namespaces:
|
||||
- nowchess
|
||||
- nowchess-staging
|
||||
extraDiscoveryRules: |
|
||||
rule {
|
||||
source_labels = ["__meta_kubernetes_pod_container_name"]
|
||||
regex = "nowchess-frontend"
|
||||
action = "drop"
|
||||
}
|
||||
applicationObservability:
|
||||
enabled: true
|
||||
collector: alloy-receiver
|
||||
receivers:
|
||||
otlp:
|
||||
grpc:
|
||||
enabled: true
|
||||
http:
|
||||
enabled: true
|
||||
annotationAutodiscovery:
|
||||
enabled: true
|
||||
collector: alloy-metrics
|
||||
bearerToken:
|
||||
enabled: false
|
||||
namespaces:
|
||||
- nowchess
|
||||
- nowchess-staging
|
||||
- redis
|
||||
metricsTuning:
|
||||
includeMetrics:
|
||||
- nowchess.*
|
||||
- http_server.*
|
||||
- grpc_server.*
|
||||
- grpc_client.*
|
||||
- redis_stream_length
|
||||
- worker_pool.*
|
||||
- process_cpu.*
|
||||
- process_uptime.*
|
||||
- jvm_memory.*
|
||||
- jvm_threads.*
|
||||
- jvm_gc.*
|
||||
extraMetricProcessingRules: |
|
||||
rule {
|
||||
action = "drop"
|
||||
source_labels = ["__name__"]
|
||||
regex = ".*_bucket"
|
||||
}
|
||||
rule {
|
||||
action = "labeldrop"
|
||||
regex = "(uri|url|exception|outcome|method|methodType|local_address|remote_address|target_addr|instance|pod)"
|
||||
}
|
||||
collectors:
|
||||
alloy-metrics:
|
||||
presets:
|
||||
- clustered
|
||||
- statefulset
|
||||
alloy-singleton:
|
||||
presets:
|
||||
- singleton
|
||||
alloy-logs:
|
||||
presets:
|
||||
- filesystem-log-reader
|
||||
- daemonset
|
||||
alloy-receiver:
|
||||
presets:
|
||||
- deployment
|
||||
collectorCommon:
|
||||
alloy:
|
||||
remoteConfig:
|
||||
enabled: true
|
||||
url: https://fleet-management-prod-011.grafana.net
|
||||
auth:
|
||||
type: basic
|
||||
username: "1634203"
|
||||
password: ${GF_TOKEN}
|
||||
telemetryServices:
|
||||
kube-state-metrics:
|
||||
deploy: false
|
||||
node-exporter:
|
||||
deploy: true
|
||||
windows-exporter:
|
||||
deploy: false
|
||||
EOF
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
NAMESPACE="kube-system"
|
||||
|
||||
usage() {
|
||||
echo "Manage sealed-secrets controller keys for cluster migration."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $0 export [output-file] Export active key(s) to YAML (default: sealed-secrets-key-backup.yaml)"
|
||||
echo " $0 import <input-file> Import key(s) to new cluster before first ArgoCD sync"
|
||||
echo ""
|
||||
echo "IMPORTANT: Never commit the backup file to Git. Store in Passwords.kdbx."
|
||||
exit 1
|
||||
}
|
||||
|
||||
export_key() {
|
||||
local out="${1:-sealed-secrets-key-backup.yaml}"
|
||||
|
||||
local keys
|
||||
keys=$(kubectl -n "$NAMESPACE" get secret \
|
||||
-l sealedsecrets.bitnami.com/sealed-secrets-key \
|
||||
-o name 2>/dev/null)
|
||||
|
||||
if [[ -z "$keys" ]]; then
|
||||
echo "Error: no sealed-secrets keys found in namespace $NAMESPACE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Strip runtime-only fields so the manifest is re-applicable
|
||||
kubectl -n "$NAMESPACE" get secret \
|
||||
-l sealedsecrets.bitnami.com/sealed-secrets-key \
|
||||
-o yaml \
|
||||
| kubectl neat \
|
||||
> "$out" 2>/dev/null \
|
||||
|| kubectl -n "$NAMESPACE" get secret \
|
||||
-l sealedsecrets.bitnami.com/sealed-secrets-key \
|
||||
-o yaml \
|
||||
| grep -v $'^\t' \
|
||||
| python3 -c "
|
||||
import sys, yaml
|
||||
docs = list(yaml.safe_load_all(sys.stdin))
|
||||
# Remove a List wrapper if present, emit individual documents
|
||||
if len(docs) == 1 and docs[0].get('kind') == 'List':
|
||||
docs = docs[0]['items']
|
||||
strip = {'resourceVersion', 'uid', 'selfLink', 'creationTimestamp',
|
||||
'generation', 'managedFields'}
|
||||
for d in docs:
|
||||
meta = d.get('metadata', {})
|
||||
for f in strip:
|
||||
meta.pop(f, None)
|
||||
d['metadata'] = meta
|
||||
print(yaml.dump_all(docs, default_flow_style=False))
|
||||
" > "$out"
|
||||
|
||||
local count
|
||||
count=$(echo "$keys" | wc -l | tr -d ' ')
|
||||
echo "Exported $count key(s) to: $out"
|
||||
echo ""
|
||||
echo "WARNING: Store this file securely (e.g. Passwords.kdbx). Never commit to Git."
|
||||
}
|
||||
|
||||
import_key() {
|
||||
local in="${1:?'import requires a file argument — run: $0 import <file>'}"
|
||||
|
||||
if [[ ! -f "$in" ]]; then
|
||||
echo "Error: file not found: $in" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Importing sealed-secrets key(s) from: $in"
|
||||
kubectl apply -f "$in"
|
||||
|
||||
echo ""
|
||||
echo "Key imported. If the sealed-secrets controller is already running, restart it:"
|
||||
echo " kubectl -n kube-system rollout restart deployment/sealed-secrets"
|
||||
echo ""
|
||||
echo "Apply this BEFORE ArgoCD syncs the secrets application."
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
export) export_key "${2:-}" ;;
|
||||
import) import_key "${2:-}" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user