{"id":1031,"date":"2026-06-26T14:04:17","date_gmt":"2026-06-26T14:04:17","guid":{"rendered":"https:\/\/www.devopsschool.com\/tutorials\/?p=1031"},"modified":"2026-06-26T14:04:19","modified_gmt":"2026-06-26T14:04:19","slug":"prometheus-step-by-step-guide-install-prometheus-on-kubernetes-using-helm-with-hostpath-pv-and-pvc","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/tutorials\/prometheus-step-by-step-guide-install-prometheus-on-kubernetes-using-helm-with-hostpath-pv-and-pvc\/","title":{"rendered":"Prometheus &#8211; Step-by-Step Guide: Install Prometheus on Kubernetes Using Helm with hostPath PV and PVC"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Prometheus is one of the most popular open-source monitoring systems for Kubernetes. It collects metrics from Kubernetes nodes, pods, services, and applications, and gives you a powerful query language called PromQL to analyze them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we will install Prometheus in a Kubernetes cluster using the <code>prometheus-community\/prometheus<\/code> Helm chart. We will also fix the common PVC pending issue by creating static <code>hostPath<\/code> PersistentVolumes manually.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide is useful for lab, demo, practice, and small Kubernetes clusters.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Architecture<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We will install the following Prometheus components:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Prometheus Server\nAlertmanager\nKube State Metrics\nNode Exporter\nPushgateway\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Prometheus Server will store data under:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/mnt\/prometheus-server\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Alertmanager will store data under:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/mnt\/alertmanager\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These directories will be created on the Kubernetes worker node using <code>hostPath<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Important Note About hostPath<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>hostPath<\/code> storage is node-specific.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That means data is stored directly on one Kubernetes node. If the pod moves to another node, the same data may not be available there.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For production, use a proper storage solution such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AWS EBS CSI Driver\nNFS\nLonghorn\nCeph\nOpenEBS\nCloud provider storage class\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For learning and testing, <code>hostPath<\/code> is fine.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 1: Check Kubernetes Nodes<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">First, check that your Kubernetes cluster is running.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get nodes\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME             STATUS   ROLES           AGE   VERSION\nip-172-31-5-107  Ready    control-plane   ...\nip-172-31-0-191  Ready    worker          ...\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, the Prometheus pod later runs on:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ip-172-31-0-191\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So the hostPath directories must be created on that node.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 2: Install Helm<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Check if Helm is already installed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If Helm is not installed, install it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsSL -o get_helm.sh https:\/\/raw.githubusercontent.com\/helm\/helm\/main\/scripts\/get-helm-4\nchmod 700 get_helm.sh\n.\/get_helm.sh\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify Helm:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm version\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 3: Add Prometheus Helm Repository<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Add the Prometheus Community Helm repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm repo add prometheus-community https:\/\/prometheus-community.github.io\/helm-charts\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Update Helm repositories:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm repo update\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm repo list\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 4: Install Prometheus Using Helm<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Install Prometheus in the <code>default<\/code> namespace:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm install my-prometheus prometheus-community\/prometheus --version 29.13.0\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check all pods:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You may initially see something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                                                    READY   STATUS    AGE\nmy-prometheus-alertmanager-0                            0\/1     Pending   ...\nmy-prometheus-server-67b68bd4c6-wv79t                   0\/2     Pending   ...\nmy-prometheus-kube-state-metrics-7c4457f7d6-j7c8f       1\/1     Running   ...\nmy-prometheus-prometheus-node-exporter-5gs22            1\/1     Running   ...\nmy-prometheus-prometheus-node-exporter-kzqz9            1\/1     Running   ...\nmy-prometheus-prometheus-pushgateway-78fc6d6f89-khpfd   1\/1     Running   ...\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If Prometheus Server and Alertmanager are pending, it is usually because their PVCs are waiting for storage.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 5: Check PVC Status<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pvc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                                   STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE\nmy-prometheus-server                   Pending                                      &lt;unset&gt;        6m\nstorage-my-prometheus-alertmanager-0   Pending                                      &lt;unset&gt;        6m\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means Kubernetes created PVCs, but there are no matching PVs available.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 6: Describe the Prometheus Pod<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Check the Prometheus Server pod:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl describe pod my-prometheus-server-67b68bd4c6-wv79t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You may see this error:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Warning  FailedScheduling  default-scheduler  0\/2 nodes are available: pod has unbound immediate PersistentVolumeClaims.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means Prometheus cannot start because its PVC is not bound.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 7: Create PersistentVolume for Prometheus Server<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Create a file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; prometheus-server-pv.yaml &lt;&lt;'EOF'\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: prometheus-server-pv\nspec:\n  capacity:\n    storage: 8Gi\n  accessModes:\n    - ReadWriteOnce\n  persistentVolumeReclaimPolicy: Retain\n  storageClassName: \"\"\n  claimRef:\n    namespace: default\n    name: my-prometheus-server\n  hostPath:\n    path: \/mnt\/prometheus-server\n    type: DirectoryOrCreate\nEOF\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Apply it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f prometheus-server-pv.yaml\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 8: Create PersistentVolume for Alertmanager<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Create another PV:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; alertmanager-pv.yaml &lt;&lt;'EOF'\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: alertmanager-pv\nspec:\n  capacity:\n    storage: 2Gi\n  accessModes:\n    - ReadWriteOnce\n  persistentVolumeReclaimPolicy: Retain\n  storageClassName: \"\"\n  claimRef:\n    namespace: default\n    name: storage-my-prometheus-alertmanager-0\n  hostPath:\n    path: \/mnt\/alertmanager\n    type: DirectoryOrCreate\nEOF\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Apply it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f alertmanager-pv.yaml\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 9: Verify PV and PVC Binding<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Check PVs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM\nprometheus-server-pv   8Gi        RWO            Retain           Bound    default\/my-prometheus-server\nalertmanager-pv        2Gi        RWO            Retain           Bound    default\/storage-my-prometheus-alertmanager-0\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check PVCs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pvc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                                   STATUS   VOLUME                 CAPACITY   ACCESS MODES\nmy-prometheus-server                   Bound    prometheus-server-pv   8Gi        RWO\nstorage-my-prometheus-alertmanager-0   Bound    alertmanager-pv        2Gi        RWO\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, the storage issue is fixed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 10: Create hostPath Directories on Worker Node<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now create the required directories on the node where Prometheus is scheduled.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, check where the pod is running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pod -o wide\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>my-prometheus-server-67b68bd4c6-wv79t   1\/2   Running   ip-172-31-0-191\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">SSH into that worker node:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh ubuntu@ip-172-31-0-191\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create directories:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/mnt\/prometheus-server\nsudo mkdir -p \/mnt\/alertmanager\nsudo mkdir -p \/mnt\/data\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set ownership:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chown -R 65534:65534 \/mnt\/prometheus-server\nsudo chown -R 65534:65534 \/mnt\/alertmanager\nsudo chown -R 65534:65534 \/mnt\/data\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set permissions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chmod -R 775 \/mnt\/prometheus-server\nsudo chmod -R 775 \/mnt\/alertmanager\nsudo chmod -R 775 \/mnt\/data\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Why <code>65534:65534<\/code>?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prometheus commonly runs as a non-root user inside the container. If the hostPath directory is owned by root and not writable, Prometheus may crash with a permission error.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 11: Check Prometheus Pods Again<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                                                    READY   STATUS    RESTARTS   AGE\nmy-prometheus-alertmanager-0                            1\/1     Running   0          13m\nmy-prometheus-kube-state-metrics-7c4457f7d6-j7c8f       1\/1     Running   0          13m\nmy-prometheus-prometheus-node-exporter-5gs22            1\/1     Running   0          13m\nmy-prometheus-prometheus-node-exporter-kzqz9            1\/1     Running   0          13m\nmy-prometheus-prometheus-pushgateway-78fc6d6f89-khpfd   1\/1     Running   0          13m\nmy-prometheus-server-67b68bd4c6-b7qn2                   2\/2     Running   0          49s\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means Prometheus is now successfully running.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 12: Troubleshoot CrashLoopBackOff<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If Prometheus Server shows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CrashLoopBackOff\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check the pod:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl describe pod my-prometheus-server-67b68bd4c6-wv79t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check logs of the correct container:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs my-prometheus-server-67b68bd4c6-wv79t -c prometheus-server\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the pod restarted already, check previous logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs my-prometheus-server-67b68bd4c6-wv79t -c prometheus-server --previous\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A common issue is permission denied on <code>\/data<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fix it on the worker node:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/mnt\/prometheus-server\nsudo chown -R 65534:65534 \/mnt\/prometheus-server\nsudo chmod -R 775 \/mnt\/prometheus-server\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then delete the pod so Kubernetes recreates it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete pod my-prometheus-server-67b68bd4c6-wv79t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 13: Access Prometheus Using Port Forward<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">You can expose Prometheus locally using <code>kubectl port-forward<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, check the Prometheus Server pod name:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example pod name:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>my-prometheus-server-67b68bd4c6-b7qn2\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run port-forward:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl --namespace default port-forward pod\/my-prometheus-server-67b68bd4c6-b7qn2 9090:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;localhost:9090\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 14: Access Prometheus from Anywhere Using 0.0.0.0<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you want Prometheus to be accessible using your server public IP, use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl --namespace default port-forward --address 0.0.0.0 pod\/my-prometheus-server-67b68bd4c6-b7qn2 9090:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;&lt;server-public-ip&gt;:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;13.XX.XX.XX:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you are running on AWS EC2, make sure port <code>9090<\/code> is allowed in the Security Group.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Allow inbound:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Type: Custom TCP\nPort: 9090\nSource: Your IP address\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For testing, you may use <code>0.0.0.0\/0<\/code>, but it is not recommended because Prometheus does not have authentication by default.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 15: Access Prometheus Using Service Port Forward<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of forwarding directly to a pod, it is better to forward to the service.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check services:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get svc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should see something like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>my-prometheus-server   ClusterIP   ...   80\/TCP\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Forward service port <code>80<\/code> to local port <code>9090<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl --namespace default port-forward --address 0.0.0.0 svc\/my-prometheus-server 9090:80\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now access:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;&lt;server-public-ip&gt;:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This method is better than pod port-forwarding because pod names change when pods restart.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 16: Verify Prometheus UI<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Open Prometheus in your browser:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;&lt;server-public-ip&gt;:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Go to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Status -&gt; Targets\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should see targets such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubernetes-apiservers\nkubernetes-nodes\nkubernetes-nodes-cadvisor\nkubernetes-service-endpoints\nprometheus\nnode-exporter\nkube-state-metrics\npushgateway\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Healthy targets should show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UP\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 17: Run Basic Prometheus Queries<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">In the Prometheus UI, go to the query box and try these queries.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check all up targets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>up\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Prometheus server health:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>prometheus_build_info\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Kubernetes node CPU metrics:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node_cpu_seconds_total\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check memory available:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node_memory_MemAvailable_bytes\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check filesystem size:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node_filesystem_size_bytes\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check pod metrics:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kube_pod_info\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check deployment replicas:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kube_deployment_status_replicas\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 18: Useful Kubernetes Verification Commands<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Check pods:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check pods with node details:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -o wide\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check services:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get svc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check PV:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check PVC:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pvc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Describe Prometheus Server pod:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl describe pod &lt;prometheus-server-pod-name&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Prometheus Server logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs &lt;prometheus-server-pod-name&gt; -c prometheus-server\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Config Reloader logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs &lt;prometheus-server-pod-name&gt; -c prometheus-server-configmap-reload\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Helm release:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm list\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check Helm status:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm status my-prometheus\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 19: Optional \u2014 Create Node Exporter Dashboard in Grafana<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Prometheus collects metrics, but for dashboards, you usually install Grafana.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can later install Grafana using Helm:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm repo add grafana https:\/\/grafana.github.io\/helm-charts\nhelm repo update\nhelm install my-grafana grafana\/grafana\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then connect Grafana to Prometheus using this URL inside Kubernetes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;my-prometheus-server.default.svc.cluster.local\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Step 20: Cleanup Commands<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to remove Prometheus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm uninstall my-prometheus\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Delete PVs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete pv prometheus-server-pv\nkubectl delete pv alertmanager-pv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Delete local data from worker node carefully:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo rm -rf \/mnt\/prometheus-server\nsudo rm -rf \/mnt\/alertmanager\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Only run the above commands if you really want to delete Prometheus data.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Common Issues and Fixes<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Issue 1: PVC Pending<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Error:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pod has unbound immediate PersistentVolumeClaims\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check PVC:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pvc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Fix:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create matching PVs for the PVCs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f prometheus-server-pv.yaml\nkubectl apply -f alertmanager-pv.yaml\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Issue 2: Prometheus Server CrashLoopBackOff<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs &lt;prometheus-server-pod-name&gt; -c prometheus-server\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Possible reason:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>permission denied\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Fix permissions on worker node:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chown -R 65534:65534 \/mnt\/prometheus-server\nsudo chmod -R 775 \/mnt\/prometheus-server\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restart pod:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete pod &lt;prometheus-server-pod-name&gt;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Issue 3: Port Forward Works Locally but Not from Browser<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl --namespace default port-forward --address 0.0.0.0 svc\/my-prometheus-server 9090:80\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;&lt;server-public-ip&gt;:9090\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Also check cloud firewall or AWS Security Group.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Issue 4: Wrong Container Logs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs my-prometheus-server-67b68bd4c6-wv79t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Kubernetes may show logs from the default container:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>prometheus-server-configmap-reload\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To check actual Prometheus logs, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl logs my-prometheus-server-67b68bd4c6-wv79t -c prometheus-server\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Final Working Commands Summary<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get nodes\n\ncurl -fsSL -o get_helm.sh https:\/\/raw.githubusercontent.com\/helm\/helm\/main\/scripts\/get-helm-4\nchmod 700 get_helm.sh\n.\/get_helm.sh\n\nhelm repo add prometheus-community https:\/\/prometheus-community.github.io\/helm-charts\nhelm repo update\n\nhelm install my-prometheus prometheus-community\/prometheus --version 29.13.0\n\nkubectl get pods\nkubectl get pvc\nkubectl get pv\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create Prometheus PV:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; prometheus-server-pv.yaml &lt;&lt;'EOF'\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: prometheus-server-pv\nspec:\n  capacity:\n    storage: 8Gi\n  accessModes:\n    - ReadWriteOnce\n  persistentVolumeReclaimPolicy: Retain\n  storageClassName: \"\"\n  claimRef:\n    namespace: default\n    name: my-prometheus-server\n  hostPath:\n    path: \/mnt\/prometheus-server\n    type: DirectoryOrCreate\nEOF\n\nkubectl apply -f prometheus-server-pv.yaml\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create Alertmanager PV:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; alertmanager-pv.yaml &lt;&lt;'EOF'\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: alertmanager-pv\nspec:\n  capacity:\n    storage: 2Gi\n  accessModes:\n    - ReadWriteOnce\n  persistentVolumeReclaimPolicy: Retain\n  storageClassName: \"\"\n  claimRef:\n    namespace: default\n    name: storage-my-prometheus-alertmanager-0\n  hostPath:\n    path: \/mnt\/alertmanager\n    type: DirectoryOrCreate\nEOF\n\nkubectl apply -f alertmanager-pv.yaml\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create directories on worker node:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/mnt\/prometheus-server \/mnt\/alertmanager \/mnt\/data\n\nsudo chown -R 65534:65534 \/mnt\/prometheus-server \/mnt\/alertmanager \/mnt\/data\nsudo chmod -R 775 \/mnt\/prometheus-server \/mnt\/alertmanager \/mnt\/data\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restart Prometheus pod if needed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete pod &lt;prometheus-server-pod-name&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods\nkubectl get pv,pvc\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expose Prometheus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl --namespace default port-forward --address 0.0.0.0 svc\/my-prometheus-server 9090:80\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Access:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;&lt;server-public-ip&gt;:9090\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we installed Prometheus on Kubernetes using Helm. We also fixed the most common storage issue where Prometheus pods remain pending because PVCs are not bound.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We manually created <code>hostPath<\/code> PersistentVolumes for Prometheus Server and Alertmanager, created the required host directories on the worker node, fixed permissions, verified all pods, and finally accessed Prometheus from the browser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This setup is good for learning and practice. For production, replace <code>hostPath<\/code> with a proper dynamic storage provisioner such as AWS EBS CSI Driver or another production-grade storage backend.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Prometheus is one of the most popular open-source monitoring systems for Kubernetes. It collects metrics from Kubernetes nodes, pods, services, and applications, and gives you a powerful&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1031","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1031","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/comments?post=1031"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1031\/revisions"}],"predecessor-version":[{"id":1032,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1031\/revisions\/1032"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/media?parent=1031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1031"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}