Add radar app

This commit is contained in:
dvirlabs 2026-02-11 10:08:05 +02:00
parent 73933b070c
commit 8ed7002240
15 changed files with 1007 additions and 15 deletions

21
argocd-apps/radar.yaml Normal file
View File

@ -0,0 +1,21 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: radar
namespace: argocd
spec:
project: infra
source:
repoURL: 'https://git.dvirlabs.com/dvirlabs/infra.git'
targetRevision: HEAD
path: charts/radar
helm:
valueFiles:
- ../../manifests/radar/values.yaml
destination:
server: https://kubernetes.default.svc
namespace: infra
syncPolicy:
automated:
prune: true
selfHeal: true

18
charts/radar/Chart.yaml Normal file
View File

@ -0,0 +1,18 @@
apiVersion: v2
appVersion: 0.9.1
description: Modern Kubernetes visibility — topology, traffic, and Helm management
home: https://github.com/skyhook-io/radar
keywords:
- kubernetes
- visualization
- monitoring
- kubectl
- dashboard
maintainers:
- email: support@skyhook.io
name: Skyhook Team
name: radar
sources:
- https://github.com/skyhook-io/radar
type: application
version: 0.9.1

182
charts/radar/README.md Normal file
View File

@ -0,0 +1,182 @@
# Radar Helm Chart
Deploy Radar to your Kubernetes cluster for web-based cluster visualization and management.
> **See also:** [In-Cluster Deployment Guide](../../../docs/in-cluster.md) for ingress and DNS setup.
## Prerequisites
- Kubernetes 1.21+
- Helm 3.0+
## Installation
### Quick Start
```bash
helm repo add skyhook https://skyhook-io.github.io/helm-charts
helm repo update skyhook
helm upgrade --install radar skyhook/radar -n radar --create-namespace
```
Access via port-forward:
```bash
kubectl port-forward svc/radar 9280:9280 -n radar
open http://localhost:9280
```
### With Ingress
```bash
helm upgrade --install radar skyhook/radar \
-n radar --create-namespace \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.hosts[0].host=radar.example.com \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix
```
### With TLS
```bash
helm upgrade --install radar skyhook/radar \
-n radar --create-namespace \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.hosts[0].host=radar.example.com \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix \
--set ingress.tls[0].secretName=radar-tls \
--set ingress.tls[0].hosts[0]=radar.example.com
```
## Configuration
| Parameter | Description | Default |
|-----------|-------------|---------|
| `replicaCount` | Number of replicas | `1` |
| `image.repository` | Image repository | `ghcr.io/skyhook-io/radar` |
| `image.tag` | Image tag | Chart appVersion |
| `service.type` | Service type | `ClusterIP` |
| `service.port` | Service port | `9280` |
| `ingress.enabled` | Enable ingress | `false` |
| `ingress.className` | Ingress class name | `""` |
| `timeline.storage` | Timeline storage (memory/sqlite) | `memory` |
| `persistence.enabled` | Enable PVC for SQLite | `false` |
| `traffic.prometheusUrl` | Manual Prometheus/VictoriaMetrics URL (skips auto-discovery) | `""` |
| `resources.limits.memory` | Memory limit | `512Mi` |
| `resources.requests.memory` | Memory request | `128Mi` |
See `values.yaml` for all configuration options.
## RBAC
The chart creates a ClusterRole with read-only access to common Kubernetes resources.
### Default Permissions (Core K8s Resources)
Always granted (required for basic functionality):
| API Group | Resources |
|-----------|-----------|
| Core (`""`) | pods, services, configmaps, events, namespaces, nodes, pvcs, serviceaccounts, endpoints |
| `apps` | deployments, daemonsets, statefulsets, replicasets |
| `networking.k8s.io` | ingresses, networkpolicies |
| `batch` | jobs, cronjobs |
| `autoscaling` | horizontalpodautoscalers |
| `apiextensions.k8s.io` | customresourcedefinitions (for CRD discovery) |
### Privileged Permissions (Opt-in)
Disabled by default for security:
| Feature | Value | Description |
|---------|-------|-------------|
| Secrets | `rbac.secrets: true` | View secrets in resource list |
| Terminal | `rbac.podExec: true` | Shell access to pods |
| Port Forward | `rbac.portForward: true` | Port forwarding to pods |
| Logs | `rbac.podLogs: true` | View pod logs (**enabled by default**) |
### CRD Access
Radar discovers CRDs in your cluster. All common CRD groups are enabled by default. Granting RBAC for CRDs that don't exist has no effect.
**Wildcard option:** Grant read access to ALL CRDs with one setting:
```bash
--set rbac.crdGroups.all=true
```
This overrides individual settings below. Simpler but broader — some orgs may not allow this.
| Option | API Groups |
|--------|------------|
| `argo` | `argoproj.io` |
| `awx` | `awx.ansible.com` |
| `certManager` | `cert-manager.io` |
| `cloudnativePg` | `cloudnative-pg.io` |
| `crossplane` | `crossplane.io`, `pkg.crossplane.io` |
| `descheduler` | `descheduler.alpha.kubernetes.io` |
| `envoyGateway` | `gateway.envoyproxy.io` |
| `externalDns` | `externaldns.k8s.io` |
| `externalSecrets` | `external-secrets.io` |
| `flux` | `*.toolkit.fluxcd.io` |
| `gatewayApi` | `gateway.networking.k8s.io` |
| `gcpMonitoring` | `monitoring.googleapis.com` |
| `grafana` | `monitoring.grafana.com`, `tempo.grafana.com`, `loki.grafana.com` |
| `istio` | `networking.istio.io`, `security.istio.io` |
| `karpenter` | `karpenter.sh`, `karpenter.k8s.aws` |
| `keda` | `keda.sh` |
| `knative` | `serving.knative.dev`, `eventing.knative.dev` |
| `kubeshark` | `kubeshark.io` |
| `kured` | `kured.io` |
| `kyverno` | `kyverno.io`, `wgpolicyk8s.io`, `reports.kyverno.io` |
| `mariadb` | `mariadb.mmontes.io` |
| `nginx` | `nginx.org` |
| `openshift` | `observability.openshift.io` |
| `opentelemetry` | `opentelemetry.io` |
| `prometheus` | `monitoring.coreos.com` |
| `reflector` | `reflector.v1.k8s.emberstack.com` |
| `reloader` | `reloader.stakater.com` |
| `sealedSecrets` | `sealed-secrets.bitnami.com` |
| `strimzi` | `strimzi.io`, `kafka.strimzi.io` |
| `tekton` | `tekton.dev` |
| `traefik` | `traefik.io`, `traefik.containo.us` |
| `velero` | `velero.io` |
**Disable groups:** `--set rbac.crdGroups.istio=false`
**Add unlisted CRDs:**
```yaml
rbac:
additionalCrdGroups:
- mycompany.io
```
### Troubleshooting: "Failed to list resource" Warnings
If you see these warnings, Radar discovered a CRD but doesn't have RBAC access. This is **not an error** — add the API group to `additionalCrdGroups` if you need it.
### Advanced: Custom Rules
For fine-grained control, use `additionalRules` to add arbitrary RBAC rules:
```yaml
rbac:
additionalRules:
- apiGroups: ["custom.example.com"]
resources: ["myresources"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["delete"] # Dangerous - use with caution
```
### Capability Detection
Radar uses its ServiceAccount permissions to access the Kubernetes API. The UI automatically detects which features are available based on RBAC and hides unavailable features (e.g., the terminal button won't appear if `podExec` is disabled).
## Uninstalling
```bash
helm uninstall radar -n radar
kubectl delete namespace radar
```

View File

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "radar.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "radar.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "radar.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "radar.labels" -}}
helm.sh/chart: {{ include "radar.chart" . }}
{{ include "radar.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "radar.selectorLabels" -}}
app.kubernetes.io/name: {{ include "radar.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "radar.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "radar.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,297 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "radar.fullname" . }}
labels:
{{- include "radar.labels" . | nindent 4 }}
rules:
# Core resources (read-only)
- apiGroups: [""]
resources:
- pods
- services
- configmaps
- events
- namespaces
- nodes
- persistentvolumeclaims
- serviceaccounts
- endpoints
verbs: ["get", "list", "watch"]
{{- if .Values.rbac.helm }}
# Helm write operations require broad permissions because charts can create
# any Kubernetes resource type. Read access for common resources is granted
# by other rules in this ClusterRole. Secrets read access is auto-enabled below.
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "update", "patch", "delete"]
{{- end }}
{{- if or .Values.rbac.secrets .Values.rbac.helm }}
# Secrets access - required for Helm release storage (rbac.helm)
# or for showing secrets in the resource browser (rbac.secrets)
- apiGroups: [""]
resources:
- secrets
verbs: ["get", "list", "watch"]
{{- end }}
# Workload resources (read-only)
- apiGroups: ["apps"]
resources:
- deployments
- daemonsets
- statefulsets
- replicasets
verbs: ["get", "list", "watch"]
# Networking resources (read-only)
- apiGroups: ["networking.k8s.io"]
resources:
- ingresses
- networkpolicies
verbs: ["get", "list", "watch"]
# Batch resources (read-only)
- apiGroups: ["batch"]
resources:
- jobs
- cronjobs
verbs: ["get", "list", "watch"]
# Autoscaling resources (read-only)
- apiGroups: ["autoscaling"]
resources:
- horizontalpodautoscalers
verbs: ["get", "list", "watch"]
# Authorization (required for capability detection via SelfSubjectAccessReview)
- apiGroups: ["authorization.k8s.io"]
resources:
- selfsubjectaccessreviews
verbs: ["create"]
{{- if .Values.rbac.podLogs }}
# Pod logs (opt-in - enables log viewer)
- apiGroups: [""]
resources:
- pods/log
verbs: ["get"]
{{- end }}
{{- if .Values.rbac.podExec }}
# Pod exec (opt-in - enables terminal feature)
- apiGroups: [""]
resources:
- pods/exec
verbs: ["create"]
{{- end }}
{{- if .Values.rbac.portForward }}
# Port forwarding (opt-in - enables port forward feature)
- apiGroups: [""]
resources:
- pods/portforward
verbs: ["create"]
{{- end }}
{{- if .Values.rbac.traffic }}
# Traffic visibility (Hubble/Cilium) - scoped to only the TLS cert secret
- apiGroups: [""]
resources:
- secrets
resourceNames:
- hubble-relay-client-certs
verbs: ["get"]
{{- end }}
# CRD discovery
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs: ["get", "list", "watch"]
# CRD access
{{- if .Values.rbac.crdGroups.all }}
# Wildcard access to all CRDs (rbac.crdGroups.all=true)
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- else }}
# Per-group CRD access
{{- if .Values.rbac.crdGroups.argo }}
- apiGroups: ["argoproj.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.awx }}
- apiGroups: ["awx.ansible.com"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.certManager }}
- apiGroups: ["cert-manager.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.cloudnativePg }}
- apiGroups: ["cloudnative-pg.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.crossplane }}
- apiGroups: ["crossplane.io", "pkg.crossplane.io", "apiextensions.crossplane.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.descheduler }}
- apiGroups: ["descheduler.alpha.kubernetes.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.envoyGateway }}
- apiGroups: ["gateway.envoyproxy.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.externalDns }}
- apiGroups: ["externaldns.k8s.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.externalSecrets }}
- apiGroups: ["external-secrets.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.flux }}
- apiGroups: ["source.toolkit.fluxcd.io", "kustomize.toolkit.fluxcd.io", "helm.toolkit.fluxcd.io", "notification.toolkit.fluxcd.io", "image.toolkit.fluxcd.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.gatewayApi }}
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.gcpMonitoring }}
- apiGroups: ["monitoring.googleapis.com"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.grafana }}
- apiGroups: ["monitoring.grafana.com", "tempo.grafana.com", "loki.grafana.com", "grafana.integreatly.org"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.istio }}
- apiGroups: ["networking.istio.io", "security.istio.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.karpenter }}
- apiGroups: ["karpenter.sh", "karpenter.k8s.aws"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.keda }}
- apiGroups: ["keda.sh"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.knative }}
- apiGroups: ["serving.knative.dev", "eventing.knative.dev"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.kubeshark }}
- apiGroups: ["kubeshark.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.kured }}
- apiGroups: ["kured.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.kyverno }}
- apiGroups: ["kyverno.io", "wgpolicyk8s.io", "reports.kyverno.io", "openreports.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.mariadb }}
- apiGroups: ["mariadb.mmontes.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.nginx }}
- apiGroups: ["nginx.org"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.openshift }}
- apiGroups: ["observability.openshift.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.opentelemetry }}
- apiGroups: ["opentelemetry.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.prometheus }}
- apiGroups: ["monitoring.coreos.com"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.reflector }}
- apiGroups: ["reflector.v1.k8s.emberstack.com"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.reloader }}
- apiGroups: ["reloader.stakater.com"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.sealedSecrets }}
- apiGroups: ["sealed-secrets.bitnami.com"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.strimzi }}
- apiGroups: ["strimzi.io", "kafka.strimzi.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.tekton }}
- apiGroups: ["tekton.dev"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.traefik }}
- apiGroups: ["traefik.io", "traefik.containo.us"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- if .Values.rbac.crdGroups.velero }}
- apiGroups: ["velero.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- end }}
{{- with .Values.rbac.additionalCrdGroups }}
# Additional CRD groups from additionalCrdGroups
- apiGroups:
{{- toYaml . | nindent 6 }}
resources: ["*"]
verbs: ["get", "list", "watch"]
{{- end }}
{{- with .Values.rbac.additionalRules }}
{{- toYaml . | nindent 2 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,16 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "radar.fullname" . }}
labels:
{{- include "radar.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "radar.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ include "radar.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,107 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "radar.fullname" . }}
labels:
{{- include "radar.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "radar.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "radar.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "radar.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- --port={{ .Values.service.port }}
- --no-browser
- --timeline-storage={{ .Values.timeline.storage }}
{{- if eq .Values.timeline.storage "sqlite" }}
- --timeline-db={{ .Values.timeline.dbPath }}
{{- end }}
- --history-limit={{ .Values.timeline.historyLimit }}
{{- if .Values.traffic.prometheusUrl }}
- --prometheus-url={{ .Values.traffic.prometheusUrl }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
env:
- name: HELM_CACHE_HOME
value: "/tmp/helm/cache"
- name: HELM_CONFIG_HOME
value: "/tmp/helm/config"
- name: HELM_DATA_HOME
value: "/tmp/helm/data"
{{- with .Values.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.probes.liveness.enabled }}
livenessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
{{- end }}
{{- if .Values.probes.readiness.enabled }}
readinessProbe:
httpGet:
path: /api/health
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: tmp
mountPath: /tmp
{{- if and .Values.persistence.enabled (eq .Values.timeline.storage "sqlite") }}
- name: data
mountPath: /data
{{- end }}
volumes:
- name: tmp
emptyDir: {}
{{- if and .Values.persistence.enabled (eq .Values.timeline.storage "sqlite") }}
- name: data
persistentVolumeClaim:
claimName: {{ include "radar.fullname" . }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,43 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "radar.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "radar.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if and .Values.persistence.enabled (eq .Values.timeline.storage "sqlite") -}}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "radar.fullname" . }}
labels:
{{- include "radar.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.persistence.accessMode }}
{{- if .Values.persistence.storageClassName }}
storageClassName: {{ .Values.persistence.storageClassName | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size }}
{{- end }}

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "radar.fullname" . }}
labels:
{{- include "radar.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "radar.selectorLabels" . | nindent 4 }}

View File

@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "radar.serviceAccountName" . }}
labels:
{{- include "radar.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

198
charts/radar/values.yaml Normal file
View File

@ -0,0 +1,198 @@
# Default values for radar.
replicaCount: 1
image:
repository: ghcr.io/skyhook-io/radar
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# RBAC configuration
rbac:
# Create ClusterRole and ClusterRoleBinding
create: true
# Additional rules to add to the ClusterRole
additionalRules: []
# Privileged permissions (disabled by default for security)
# Enable these based on features you need:
# Allow Helm write operations (install, upgrade, rollback, uninstall, apply values)
# Requires broad permissions - grants create/update/patch/delete on all resource types,
# since Helm charts can create any kind of Kubernetes resource.
# Automatically enables secrets read access (needed for Helm release storage).
helm: false
# Allow reading secrets (shows secrets in resource list)
secrets: false
# Allow pod exec (enables terminal feature)
podExec: false
# Allow pod logs (enables log viewer)
# This is relatively safe - only reads logs, no write access
podLogs: true
# Allow port forwarding (enables port forward feature)
portForward: false
# Traffic visibility (Hubble/Cilium integration)
# Grants read access ONLY to hubble-relay-client-certs secret for TLS auth
traffic: true
# CRD access - all common groups enabled by default
# Granting RBAC for CRDs that don't exist has no effect.
crdGroups:
# Set to true to grant read access to ALL CRDs (overrides individual settings below)
# Simpler but broader permissions - some orgs may not allow this
all: false
argo: true # argoproj.io
awx: true # awx.ansible.com
certManager: true # cert-manager.io
cloudnativePg: true # cloudnative-pg.io
crossplane: true # crossplane.io, pkg.crossplane.io
descheduler: true # descheduler.alpha.kubernetes.io
envoyGateway: true # gateway.envoyproxy.io
externalDns: true # externaldns.k8s.io
externalSecrets: true # external-secrets.io
flux: true # *.toolkit.fluxcd.io
gatewayApi: true # gateway.networking.k8s.io
gcpMonitoring: true # monitoring.googleapis.com
grafana: true # monitoring.grafana.com, tempo/loki/grafana.integreatly.org
istio: true # networking.istio.io, security.istio.io
karpenter: true # karpenter.sh, karpenter.k8s.aws
keda: true # keda.sh
knative: true # serving.knative.dev, eventing.knative.dev
kubeshark: true # kubeshark.io
kured: true # kured.io
kyverno: true # kyverno.io, wgpolicyk8s.io, reports.kyverno.io
mariadb: true # mariadb.mmontes.io
nginx: true # nginx.org
openshift: true # observability.openshift.io
opentelemetry: true # opentelemetry.io
prometheus: true # monitoring.coreos.com
reflector: true # reflector.v1.k8s.emberstack.com
reloader: true # reloader.stakater.com
sealedSecrets: true # sealed-secrets.bitnami.com
strimzi: true # strimzi.io, kafka.strimzi.io
tekton: true # tekton.dev
traefik: true # traefik.io, traefik.containo.us
velero: true # velero.io
# Additional CRD API groups for custom/unlisted CRDs
# Example: ["mycompany.io", "custom.example.com"]
additionalCrdGroups: []
podAnnotations: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
capabilities:
drop:
- ALL
service:
type: ClusterIP
port: 9280
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: radar.example.com
paths:
- path: /
pathType: Prefix
tls: []
# - secretName: radar-tls
# hosts:
# - radar.example.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# Timeline storage configuration
timeline:
# Storage backend: "memory" or "sqlite"
storage: memory
# Path to SQLite database (only used when storage is "sqlite")
# Note: Requires a PVC when using sqlite
dbPath: /data/timeline.db
# Maximum number of events to retain
historyLimit: 10000
# Traffic source configuration
traffic:
# Manual Prometheus/VictoriaMetrics URL (bypasses auto-discovery)
# Use this when auto-discovery doesn't find your metrics service.
# Examples:
# http://prometheus-server.monitoring:80
# http://vmsingle.victoria-metrics:8428
# http://vmselect.victoria-metrics:8481/select/0/prometheus
prometheusUrl: ""
# Persistence for SQLite timeline storage
# Required when timeline.storage is "sqlite" (readOnlyRootFilesystem prevents local writes)
persistence:
enabled: false
# storageClassName: ""
accessMode: ReadWriteOnce
size: 1Gi
nodeSelector: {}
tolerations: []
affinity: {}
# Additional environment variables
env: []
# - name: DEBUG
# value: "true"
# Liveness and readiness probes
probes:
liveness:
enabled: true
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readiness:
enabled: true
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3

View File

@ -1,15 +0,0 @@
enabled: true
app: nachmani-bot
uptime_kuma:
enabled: true
url: https://nachmani-bot.dvirlabs.com
tag: infra
# targets:
# - <exporter-host>:<port>
# scheme: http
# external_check:
# url: https://nachmani-bot.dvirlabs.com
# expected_codes:
# '502': critical
# '404': warning
# '1033': critical

View File

@ -0,0 +1,2 @@
enabled: true
hostname: radar.dvirlabs.com

View File

@ -0,0 +1,17 @@
replicaCount: 1
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
hosts:
- host: radar.dvirlabs.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: tls-radar-ingress
hosts:
- radar.dvirlabs.com