Setting Up Grafana and Prometheus on MacBook Pro (Intel Version) via Docker and Kubernetes
This guide will walk you through setting up Grafana and Prometheus on a MacBook Pro (Intel version) using Docker Desktop’s Kubernetes service. You’ll learn how to monitor your system metrics and set up persistent data storage for Grafana and Prometheus.
Prerequisites
- MacBook Pro 2019 (Intel version)
- Docker Desktop installed with Kubernetes enabled
- Basic knowledge of Kubernetes and command-line operations
- tmux (optional but recommended for managing multiple terminal sessions)
- stern (for log monitoring)
- yq (for YAML processing)
Pre-Steps for All Methods
1. Start Docker Desktop and Kubernetes Service
Ensure Docker Desktop is running and Kubernetes is enabled:
kubectl get nodes
Expected output:
NAME STATUS ROLES AGE VERSION docker-desktop Ready control-plane 3h28m v1.30.2
Check for any existing pods:
kubectl get pods
Expected output:
No resources found in default namespace.
2. Create Necessary Directories
Set up your working directories:
mkdir -p ~/tmp/mac-k8s-monitoring
cd ~/tmp/mac-k8s-monitoring
3. Set Up Node Exporter
In a separate terminal, download and run the Node Exporter to gather system metrics:
Download Node Exporter
For Intel Macs:
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.darwin-amd64.tar.gz
tar xf node_exporter-1.8.2.darwin-amd64.tar.gz
For ARM MACs (M series): Download the darwin-arm64 version. This would be the only difference in the steps as long as the other prereqs work.
Run Node Exporter
./node_exporter-1.8.2.darwin-amd64/node_exporter
You should see output similar to:
ts=2024-10-27T02:30:14.522Z caller=tls_config.go:313 level=info msg="Listening on" address=[::]:9100 ts=2024-10-27T02:30:14.522Z caller=tls_config.go:316 level=info msg="TLS is disabled." http2=false address=[::]:9100
4. Obtain Your Mac’s IP Address
You’ll need your Mac’s IP address for configuration:
ifconfig | grep inet
Look for the IP address under your main network interface. For example:
inet 192.168.86.222 netmask 0xffffff00 broadcast 192.168.86.255
This IP (192.168.86.222
in this example) will be used later in the configuration files.
Method 1: Non-Persistent Method
This method sets up Grafana and Prometheus without persistent storage, suitable for testing purposes.
1. Create the Kubernetes Manifest
Create a file named grafana-prometheus.yml
and replace your Mac’s IP Address in place of mine (192.168.86.222
):
cat > grafana-prometheus.yml << 'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
---
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'host-metrics'
static_configs:
- targets: ['YOUR_MAC_IP:9100'] # Replace with your Mac's IP address
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus:latest
args:
- "--config.file=/etc/prometheus/prometheus.yml"
ports:
- containerPort: 9090
volumeMounts:
- name: config-volume
mountPath: /etc/prometheus/
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: config-volume
configMap:
name: prometheus-config
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:latest
ports:
- containerPort: 3000
env:
- name: GF_SECURITY_ADMIN_PASSWORD
value: "foobar"
---
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 30001
protocol: TCP
selector:
app: prometheus
---
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: monitoring
spec:
type: NodePort
ports:
- port: 3000
targetPort: 3000
nodePort: 30002
protocol: TCP
selector:
app: grafana
EOF
2. Apply the Kubernetes Manifest
Deploy Grafana and Prometheus:
kubectl apply -f grafana-prometheus.yml
3. Monitor Deployment Status
Check the status of the pods and services:
kubectl get all -n monitoring
Expected output:
NAME READY STATUS RESTARTS AGE pod/grafana-xxxxxxxxx-xxxxx 1/1 Running 0 XXm pod/prometheus-xxxxxxxxx-xxxxx 1/1 Running 0 XXm NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/grafana NodePort 10.xxx.xxx.xxx <none> 3000:30002/TCP XXm service/prometheus NodePort 10.xxx.xxx.xxx <none> 9090:30001/TCP XXm
4. Access Grafana and Prometheus
Grafana
Open your browser and navigate to http://localhost:30002/.
- Login Credentials:
- Username:
admin
- Password:
foobar
- Username:
You’ll be prompted to change the password upon first login.
Prometheus
Open your browser and navigate to http://localhost:30001/.
To check the targets, go to http://localhost:30001/targets. You should see all targets as “Up”.
5. Monitor Logs with Stern (Optional)
Install stern if you haven’t already:
brew install stern
Use stern to monitor logs:
stern -n monitoring .
You can filter logs for specific components:
stern -n monitoring prom
stern -n monitoring graf
6. Adjusting Configurations
If you need to update configurations (e.g., the IP address):
- Edit
grafana-prometheus.yml
. - Reapply the manifest:
kubectl apply -f grafana-prometheus.yml
- Restart Prometheus to load new configurations:
kubectl get pod -n monitoring # get your PROMETHEUS_POD_NAME kubectl exec <pod/PROMETHEUS_POD_NAME> -n monitoring -- kill -1 1
Or use the one-liner to find the pod name automatically:
# naive with kubectl, grep and awk kubectl exec `kubectl get pods -n monitoring | grep prometheus | awk '{print $1}'` -n monitoring -- kill -1 1 # precise with only kubectl kubectl exec $(kubectl get pods -n monitoring -l app=prometheus -o jsonpath="{.items[0].metadata.name}") -n monitoring -- kill -1 1
7. Set Up Grafana Dashboard
Import Dashboard
- In Grafana, click on Dashboards > Import.
- Enter dashboard ID
1860
(Node Exporter Full). - Select your Prometheus data source.
- Click Import.
Note: Explore all of grafana public dashboards online. The numerical ID of the dashboard is the only requirement.
Method 2: Persistent Data for Prometheus and Grafana
This method sets up persistent storage for Grafana and Prometheus, ensuring data and configurations are retained across restarts.
1. Clean Up Previous Deployments
If you have previous deployments:
kubectl delete ns monitoring
Optionally, remove old storage directories:
rm -rf ~/tmp/k8s-mon/grafana-storage ~/tmp/k8s-mon/prometheus-storage
2. Create Persistent Storage Directories
Set up directories for persistent storage:
mkdir -p ~/tmp/k8s-mon/grafana-storage
mkdir -p ~/tmp/k8s-mon/prometheus-storage
Note: Keep these directories outside of synced folders (like Dropbox) to avoid file locking issues. While the documented locations should be fine, be cautious if choosing alternative directory locations.
3. Create the Kubernetes Manifest with HostPath Volumes
Create a file named grafana-prometheus-hostpath.yml
:
cat > grafana-prometheus-hostpath.yml << 'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
---
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'host-metrics'
static_configs:
- targets: ['YOUR_MAC_IP:9100'] # Replace with your Mac's IP address
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus:latest
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus" # Directory within the container for data storage
ports:
- containerPort: 9090
volumeMounts:
- name: config-volume
mountPath: /etc/prometheus/
- name: prometheus-storage # Persistent storage mount
mountPath: /prometheus
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: config-volume
configMap:
name: prometheus-config
- name: prometheus-storage
hostPath:
path: /Users/USERNAME/tmp/k8s-mon/prometheus-storage # Replace USERNAME with your actual username
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
---
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 30001
protocol: TCP
selector:
app: prometheus
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:latest
ports:
- containerPort: 3000
env:
- name: GF_SECURITY_ADMIN_PASSWORD
value: "foobar" # Set a secure password for production
volumeMounts:
- name: grafana-storage
mountPath: /var/lib/grafana # Grafana data will be stored here
volumes:
- name: grafana-storage
hostPath:
path: /Users/USERNAME/tmp/k8s-mon/grafana-storage # Replace USERNAME with your actual username
---
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: monitoring
spec:
type: NodePort
ports:
- port: 3000
targetPort: 3000
nodePort: 30002
protocol: TCP
selector:
app: grafana
EOF
Important:
- Replace
YOUR_MAC_IP
with your actual Mac IP address. - Replace
USERNAME
with your actual macOS username in thehostPath
entries.
4. Apply the Kubernetes Manifest
Deploy Grafana and Prometheus with persistent storage:
kubectl apply -f grafana-prometheus-hostpath.yml
5. Configure Grafana’s Prometheus Data Source via REST API
Copy & paste the subshell below into your terminal to configure the data source:
(
# Variables
PROMETHEUS_URL=http://prometheus.monitoring.svc.cluster.local:9090/
GRAFANA_URL=http://localhost:30002
GRAFANA_USERNAME=admin
GRAFANA_PASSWORD=foobar
# Create a Prometheus data source in Grafana
curl -XPOST -u $GRAFANA_USERNAME:$GRAFANA_PASSWORD
-H 'Content-Type: application/json'
-H 'Accept: application/json'
$GRAFANA_URL/api/datasources
-d "{"name": "prometheus", "type": "prometheus", "url": "$PROMETHEUS_URL", "access": "proxy", "basicAuth": false}"
echo
)
6. Verify Data Source Creation
Check if the data source has been created by inspecting Grafana’s SQLite database:
sqlite3 ~/tmp/k8s-mon/grafana-storage/grafana.db 'select * from data_source;'
Expected output:
1|1|2|prometheus|prometheus|proxy|http://prometheus.monitoring.svc.cluster.local:9090/||||0|||1|{"httpMethod":"POST"}|2024-10-27 03:23:03|2024-10-27 03:23:24|0|{}|0|ce23k4ra97mrkb|0|
7. Set Up Grafana Dashboard
Import Dashboard
- In Grafana, click on Dashboards > Import.
- Enter dashboard ID
1860
(Node Exporter Full). - Select the
prometheus
data source. - Click Import.
Note: Explore all of grafana public dashboards online. The numerical ID of the dashboard is the only requirement.
Testing Deletion and Recreation
To ensure that persistent storage is working, you can delete and recreate the namespace:
kubectl delete ns monitoring
kubectl apply -f grafana-prometheus-hostpath.yml
Your dashboards and data sources should persist across redeployments due to the persistent volumes.
Tips and Additional Notes
Monitoring Logs with Stern
Install stern
for log monitoring:
brew install stern
Use stern
to monitor logs:
stern -n monitoring .
Using tmux
for Session Management
tmux
can help you manage multiple terminal sessions efficiently. You can have separate panes for:
- Running
stern
for log monitoring - Running
node_exporter
- Editing YAML files
- Executing bash commands (
kubectl
, etc.)
For more information on running tmux, check out my TMUX cheatsheet article.
Checking YAML Files with yq
Before applying Kubernetes manifests, validate and view them with yq
:
brew install yq
yq grafana-prometheus-hostpath.yml
This command outputs syntax-highlighted YAML and can help catch any syntax errors.
Conclusion
By following this guide, you’ve successfully set up Grafana and Prometheus on your MacBook Pro (Intel version) using Docker Desktop and Kubernetes. You now have a monitoring stack capable of collecting and visualizing system metrics with persistent data storage.
Feel free to explore more dashboards and customize your monitoring setup according to your needs. Happy monitoring!