diff --git a/README.md b/README.md index 858f97b..d293ed0 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,10 @@ shellyctl prometheus --config=config.yaml ``` ### Prometheus Server +The `prometheus` sub-command facilitates running a [Prometheus](https://prometheus.io/) compatible metrics server. + +See [contrib/k8s](contrib/k8s) for instructions on running the prometheus server within a Kubernetes cluster. + ``` Host a prometheus metrics exporter for shelly devices diff --git a/contrib/k8s/README.md b/contrib/k8s/README.md new file mode 100644 index 0000000..a712b0d --- /dev/null +++ b/contrib/k8s/README.md @@ -0,0 +1,53 @@ +# Example Kubernetes Manifests + +This folder provides two example Kubernetes manifests: +* [shellyctl-prom-hostNetwork.yaml](shellyctl-prom-hostNetwork.yaml) - Configures a prometheus server with mDNS search enabled on all interfaces. To support mDNS discovery this pod MUST run with `hostNetwork: true` which enables additional network privileges. To avoid port-conficts during pod replacement, the server is run as a StatefulSet w/ 1 replica. +* [shellyctl-prom.yaml](shellyctl-prom.yaml) - Configures a prometheus server running within pod networking. This leverages a traditional Deployment model. Because no mDNS/BLEdiscovery is possible you MUST specify hosts in the config file or configure and MQTT server. + +## Updating configuration +Both variants leverage a config-map for configuring shellyctl flags. Shellyctl does NOT support live config reloading so you must restar or replace the pod to reload configuration. + +``` +# edit the config file. +kubectl edit -n shellyctl configmap shellyctl-prom + +# replace shellyctl pods to reload configuration +kubectl delete pod -n shellyctl --all +``` + +## Service Discovery +These examples use the `prometheus.io/scrape` and `prometheus.io/port` anotations for service discovery. Your prometheus service discovery may be configured differently. See: +* [Prometheus Service Discovery Configuration](https://prometheus.io/docs/prometheus/latest/configuration/configuration/) +* [PodMonitor/ServiceMonitor in Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md#deploying-a-sample-application) +* [Victoria Metrics Agent](https://docs.victoriametrics.com/vmagent/) + + +## shellyctl-prom-hostNetwork.yaml +``` +# Create a namespace, shellyctl. +kubectl create namespace shellyctl + +# Optionally add a password for authenticating with devices. This step may be skipped if you do not use auth. +kubectl create secret -n shellyctl generic shellyctl-auth --from-literal=SHELLYCTL_AUTH=password + +# Apply the manifest. +kubectl apply -f https://raw.githubusercontent.com/jcodybaker/shellyctl/main/contrib/k8s/shellyctl-prom-hostNetwork.yaml +``` + +## shellyctl-prom.yaml +``` +# Create a namespace, shellyctl. +kubectl create namespace shellyctl + +# Optionally add a password for authenticating with devices. This step may be skipped if you do not use auth. +kubectl create secret -n shellyctl generic shellyctl-auth --from-literal=SHELLYCTL_AUTH=password + +# Download the manifest for local editing. +curl -LfO https://raw.githubusercontent.com/jcodybaker/shellyctl/main/contrib/k8s/shellyctl-prom.yaml + +# Edit the `host` list in configmap. +editor shellyctl-prom.yaml + +# Apply the manifest. +kubectl apply -f shellyctl-prom.yaml +``` \ No newline at end of file diff --git a/contrib/k8s/shellyctl-prom.yaml b/contrib/k8s/shellyctl-prom.yaml new file mode 100644 index 0000000..e87bfb6 --- /dev/null +++ b/contrib/k8s/shellyctl-prom.yaml @@ -0,0 +1,86 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + kubernetes.io/metadata.name: shellyctl + name: shellyctl + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: shellyctl-prom + namespace: shellyctl +data: + shellyctl-prom.yaml: | + bind-port: 9090 + log-level: debug + host: + # Example host config with password. + - http://admin:password@127.0.0.1 + - http://127.0.0.1 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: shellyctl-prom + name: shellyctl-prom + namespace: shellyctl +spec: + replicas: 1 + selector: + matchLabels: + app: shellyctl-prom + template: + metadata: + labels: + app: shellyctl-prom + spec: + containers: + - command: + - /bin/shellyctl + - prometheus + env: + - name: SHELLYCTL_CONFIG + value: /run/shellyctl/shellyctl-prom.yaml + image: ghcr.io/jcodybaker/shellyctl:latest + imagePullPolicy: Always + name: shellyctl + ports: + - containerPort: 9090 + protocol: TCP + volumeMounts: + - mountPath: /run/shellyctl + name: config + dnsPolicy: ClusterFirst + restartPolicy: Always + terminationGracePeriodSeconds: 30 + volumes: + - configMap: + defaultMode: 420 + name: shellyctl-prom + name: config + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: shellyctl-prom + annotations: + prometheus.io/port: "9090" + prometheus.io/scrape: "true" + name: shellyctl-prom + namespace: shellyctl +spec: + ports: + - name: 9090-9090 + port: 9090 + protocol: TCP + targetPort: 9090 + selector: + app: shellyctl-prom + type: ClusterIP \ No newline at end of file diff --git a/pkg/discovery/discovery.go b/pkg/discovery/discovery.go index a7f074b..e776479 100644 --- a/pkg/discovery/discovery.go +++ b/pkg/discovery/discovery.go @@ -80,7 +80,7 @@ func (d *Discoverer) AddDeviceByAddress(ctx context.Context, addr string, opts . default: return nil, fmt.Errorf("unsupported URI scheme %q", u.Scheme) } - if u.Path == "" { + if u.Path == "" || u.Path == "/" { u.Path = "/rpc" } if u.Path != "/rpc" {