How to Monitor External Services with Prometheus from Kubernetes
Monitoring external systems—like bare-metal servers, APIs, or other cloud services—from within Kubernetes can help unify your observability pipeline. With Prometheus Operator, you don’t need to deploy a second Prometheus instance. Instead, you can expose external targets using Kubernetes-native manifests: Service, Endpoints, and ServiceMonitor.
In this guide, we’ll walk through:
- Monitoring a VM with Node Exporter
 - Monitoring a remote NGINX server
 - Scraping a custom REST API
 - Tips on TLS and firewalling external exporters
 
How to Monitor External Services with Prometheus from Kubernetes
Why Monitor External Services from Kubernetes
Monitoring external systems—like bare-metal servers, APIs, or other cloud services—from within Kubernetes can help unify your observability pipeline. With Prometheus Operator, you don’t need to deploy a second Prometheus instance. Instead, you can expose external targets using Kubernetes-native manifests: Service, Endpoints, and ServiceMonitor.
Prometheus Operator simplifies Prometheus management in Kubernetes by automating tasks like configuration, scaling, and high availability. By leveraging these Kubernetes resources, you can monitor external services seamlessly within your existing Kubernetes cluster, reducing operational complexity and costs.
- A 
Servicewithout a selector. - A 
Endpointsresource pointing to real IPs. - A 
ServiceMonitorthat ties it all together. 
Example 1: Monitor a VM with Node Exporter
Step 1: Install Node Exporter on the VM
Install Node Exporter using the latest release:
wget https://github.com/prometheus/node_exporter/releases/latest/download/node_exporter-*.tar.gz
tar xvfz node_exporter-*.tar.gz
sudo mv node_exporter-*/node_exporter /usr/local/bin/
sudo useradd -rs /bin/false node_exporter
Enable and start the service with systemd:
sudo tee /etc/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl start node_exporter && sudo systemctl enable node_exporter
Ensure port 9100 is open:
sudo firewall-cmd --add-port=9100/tcp --permanent && sudo firewall-cmd --reload
Step 2: Create the Kubernetes Resources
Service (no selector):
apiVersion: v1
kind: Service
metadata:
  name: node-vm-metrics
  namespace: monitoring
  labels:
    app: node-vm
spec:
  ports:
    - name: metrics
      port: 9100
      targetPort: 9100
Endpoints:
apiVersion: v1
kind: Endpoints
metadata:
  name: node-vm-metrics
  namespace: monitoring
subsets:
  - addresses:
      - ip: 192.168.1.100
    ports:
      - name: metrics
        port: 9100
ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: node-vm
  namespace: monitoring
  labels:
    release: prometheus
spec:
  selector:
    matchLabels:
      app: node-vm
  namespaceSelector:
    matchNames:
      - monitoring
  endpoints:
    - port: metrics
      interval: 10s
Example 2: Monitor an NGINX Instance with Exporter
Let’s say you’ve installed the official nginx-prometheus-exporter on a bare-metal host.
The NGINX exporter runs on :9113 and scrapes metrics from http://localhost/status.
Step 1: Install NGINX Prometheus Exporter
Install the NGINX Prometheus Exporter on your bare-metal server using the latest release:
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/latest/download/nginx-prometheus-exporter-*.tar.gz
tar xvfz nginx-prometheus-exporter-*.tar.gz
sudo mv nginx-prometheus-exporter-* /usr/local/bin/nginx-prometheus-exporter
Enable and start the service with systemd:
sudo tee /etc/systemd/system/nginx-prometheus-exporter.service <<EOF
[Unit]
Description=NGINX Prometheus Exporter
After=network.target
[Service]
ExecStart=/usr/local/bin/nginx-prometheus-exporter \
  --nginx.status.addr=localhost:8080 \
  --web.listen-address=0.0.0.0:9113
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl start nginx-prometheus-exporter && sudo systemctl enable nginx-prometheus-exporter
Ensure port 9113 is open:
sudo firewall-cmd --add-port=9113/tcp --permanent && sudo firewall-cmd --reload
Step 2: Create the Kubernetes Resources
Endpoints:
apiVersion: v1
kind: Endpoints
metadata:
  name: nginx-ext
  namespace: monitoring
subsets:
  - addresses:
      - ip: 10.20.0.5
    ports:
      - name: metrics
        port: 9113
Service:
apiVersion: v1
kind: Service
metadata:
  name: nginx-ext
  namespace: monitoring
  labels:
    app: nginx-ext
spec:
  ports:
    - name: metrics
      port: 9113
ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: nginx-ext
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: nginx-ext
  namespaceSelector:
    matchNames:
      - monitoring
  endpoints:
    - port: metrics
      path: /metrics
      interval: 15s
Example 3: Scraping a Custom REST API
Some internal apps may expose custom metrics under /metrics in Prometheus format.
As long as the app binds to a known IP and port, and outputs valid Prometheus text format, the pattern is the same.
apiVersion: v1
kind: Endpoints
metadata:
  name: custom-api-metrics
  namespace: monitoring
subsets:
  - addresses:
      - ip: 172.16.100.5
    ports:
      - name: http
        port: 9200
---
apiVersion: v1
kind: Service
metadata:
  name: custom-api-metrics
  namespace: monitoring
  labels:
    app: custom-api
spec:
  ports:
    - name: http
      port: 9200
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: custom-api
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: custom-api
  namespaceSelector:
    matchNames:
      - monitoring
  endpoints:
    - port: http
      path: /metrics
      interval: 10s
Security Tips: TLS, Network, and Relabeling
- Restrict access: Use firewall rules or VPNs to restrict which IPs can scrape metrics.
 - TLS endpoints: If your external exporter supports HTTPS, set 
scheme: httpsin the ServiceMonitor and configure certificates as needed. - Relabeling: Add 
metricRelabelingsorrelabelingsif you want to clean up labels or add context (e.g., VM name, region, etc.). 
Example:
relabelings:
  - sourceLabels: [__address__]
    targetLabel: instance
    regex: "(.*):.*"
    replacement: "$1"
    action: replace
Final Thoughts
Prometheus inside Kubernetes can scrape far more than just in-cluster Pods. Whether you’re monitoring VMs, physical servers, IoT nodes, or APIs, this approach lets you manage external targets with the same tooling and alerting infrastructure you already rely on.
This model scales beautifully—and keeps your observability stack clean, unified, and Kubernetes-native.