{"id":576,"date":"2025-03-07T18:44:53","date_gmt":"2025-03-07T18:44:53","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=576"},"modified":"2025-03-07T18:44:53","modified_gmt":"2025-03-07T18:44:53","slug":"setup-grafana-loki","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=576","title":{"rendered":"How to Setup Grafana Loki on Kubernetes &amp; Query Logs"},"content":{"rendered":"<p>In this blog, we will look into a step-by-step guide to setup Grafana Loki on Kubernetes using <a href=\"https:\/\/devopscube.com\/create-helm-chart\/\" rel=\"noreferrer noopener\">Helm<\/a>.<\/p>\n<p>We will also look at setting up Alloy which is an agent for Loki to collect logs and setup Grafana for querying logs using Loki.<\/p>\n<p><a href=\"https:\/\/grafana.com\/docs\/loki\/latest\/?ref=devopscube.com\" rel=\"noreferrer noopener\">Grafana Loki<\/a> is an open-source log aggregation system that supports large-scale log management. It is a widely adopted tool for organizations <a href=\"https:\/\/devopscube.com\/what-is-observability\/\" rel=\"noreferrer noopener\">observability<\/a> stack.<\/p>\n<p>If you want to learn in detail about Grafana Loki&#8217;s architecture, read the detailed <a href=\"https:\/\/devopscube.com\/grafana-loki-architecture\/\" rel=\"noreferrer noopener\">Grafana Loki Architecture blog.<\/a><\/p>\n<p>Pods that will be deployed for Loki are listed below:<\/p>\n<ol>\n<li>Loki (sts) &#8211; The Loki pod contains all its components, like ingester, distributor, etc.<br \/>This pod is responsible for compressing the logs into chunks and storing them, whether it&#8217;s configured for the local filesystem or the external object storage.<\/li>\n<li>Loki-canary (daemonset): This is a health check pod for Loki. It sends dummy logs to check Loki&#8217;s performance, such as latency and success rates.<\/li>\n<li>Loki-chunks-cache (sts): This caches the log chunks that have been recently queried so that the same chunk can be queried faster next time.<\/li>\n<li>Loki-gateway (deployment): This is an Nginx Ingress pod that routes requests to the correct Loki components. It will be more helpful if you use it with Loki Micro Services.<\/li>\n<li>Loki-results (sts):  This caches the results from previous queries for faster query if the same query is used next time.<\/li>\n<\/ol>\n<h2 id=\"loki-workflow\">Loki Workflow<\/h2>\n<p>A workflow overview of Loki is shown in the diagram below.<\/p>\n<figure class=\"kg-card kg-image-card kg-card-hascaption\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/monolithic-loki.png\" class=\"kg-image\" alt=\"Loki Workflow\" loading=\"lazy\" width=\"1920\" height=\"1080\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/monolithic-loki.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/05\/monolithic-loki.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/05\/monolithic-loki.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/monolithic-loki.png 1920w\" sizes=\"auto, (min-width: 720px) 720px\"><figcaption><span style=\"white-space: pre-wrap;\">Click to View in HD<\/span><\/figcaption><\/figure>\n<p>Let me explain the diagram<\/p>\n<ol>\n<li>The diagram shows two types of workflow, one given in numbers and the other in letters. Let&#8217;s see about numbers first.<\/li>\n<li>It starts with <code>Grafana Alloy<\/code>, a Loki log-collecting agent that collects logs from the <code>\/var\/log\/pods<\/code> directory.<\/li>\n<li>The collected logs are sent to <code>Loki-gateway<\/code>, which routes them to the <code>Loki pod<\/code>.<\/li>\n<li>In this Loki setup, <code>log ingestion<\/code>, <code>compression<\/code>, and <code>storage<\/code> happen inside the same pod. Once it is done, it stores the compressed log chunks in the <code>PV<\/code>.<\/li>\n<li>The letter flow starts with a <code>user<\/code> query the logs through the <code>Grafana dashboard<\/code>.<\/li>\n<li><code>Grafana<\/code> Sends the query requests to the <code>Loki gateway<\/code> and it routes the request to the Loki pod.<\/li>\n<li>After getting the query request, the Loki pod sends back the correct logs based on the query.<\/li>\n<li>The query results are then stored in the <code>result cache<\/code>, and the recently accessed chunk info is cached in the <code>chunk cache<\/code>.<\/li>\n<li>And there is <code>canary<\/code>, which sends dummy logs to Loki pod to check its health.<\/li>\n<\/ol>\n<h2 id=\"setup-prerequisites\">Setup Prerequisites<\/h2>\n<p>The following are the prerequisites for this setup.<\/p>\n<ol>\n<li><a href=\"https:\/\/devopscube.com\/setup-kubernetes-cluster-kubeadm\/\" rel=\"noreferrer noopener\">Kubernetes Cluster<\/a><\/li>\n<li>Kubectl<\/li>\n<li><a href=\"https:\/\/devopscube.com\/install-configure-helm-kubernetes\/\" rel=\"noreferrer noopener\">Helm installed<\/a> in your system<\/li>\n<\/ol>\n<h2 id=\"steps-to-setup-grafana-loki-on-kubernetes\">Steps to Setup Grafana Loki on Kubernetes<\/h2>\n<p>If you are ready with the prerequisites, follow the steps below to set up Loki on Kubernetes using Helm.<\/p>\n<h3 id=\"step-1-add-grafana-repo\">Step 1: Add Grafana repo<\/h3>\n<p>Add a Grafana repo to your system to download the helm chart and set up Loki. Run the following command to add the repo<\/p>\n<pre><code class=\"language-language-bash\">helm repo add grafana https:\/\/grafana.github.io\/helm-charts<\/code><\/pre>\n<p>Once the repo is added, run the following command to update the repo to make sure the repo is up-to-date<\/p>\n<pre><code class=\"language-bash\">helm repo update<\/code><\/pre>\n<p>Now, list every repo with the word Loki using the command<\/p>\n<pre><code class=\"language-bash\">helm search repo loki<\/code><\/pre>\n<p>You will get the list of repos with the word <code>Loki<\/code> as shown below<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-16-6.png\" class=\"kg-image\" alt=\"list repos with word loki\" loading=\"lazy\" width=\"1197\" height=\"637\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-16-6.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-16-6.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-16-6.png 1197w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>From these repos, we are going to use the <code>grafana\/loki<\/code> Helm chart repo to deploy Loki.<\/p>\n<h3 id=\"step-2-customize-the-loki-helm-values-file\">Step 2: Customize the Loki Helm Values file<\/h3>\n<p>Before deploying, we need to update some configurations in the <a href=\"https:\/\/devopscube.com\/how-to-deploy-helm-charts-using-argo-cd\/\" rel=\"noreferrer noopener\">helm chart<\/a>.<\/p>\n<p>Use the below command to save the default values of the helm chart in a YAML file.<\/p>\n<pre><code class=\"language-python\">helm show values grafana\/loki &gt; loki.yaml<\/code><\/pre>\n<p>You can also use the custom values file that we created below.<\/p>\n<pre><code class=\"language-yml\">loki:\n  commonConfig:\n    replication_factor: 1\n  storage:\n    type: 'filesystem'\n    bucketNames:\n      chunks: chunks\n      ruler: ruler\n      admin: admin\n  schemaConfig:\n    configs:\n      - from: \"2024-04-01\"\n        store: tsdb\n        object_store: filesystem\n        schema: v13\n        index:\n          prefix: loki_index_\n          period: 24h\n  storage_config:\n    filesystem:\n      directory: \/tmp\/loki\/chunks\n  pattern_ingester:\n    enabled: true\n  limits_config:\n    allow_structured_metadata: true\n    volume_enabled: true\n  ruler:\n    enable_api: true\n  auth_enabled: false\n\nminio:\n  enabled: false\n      \ndeploymentMode: SingleBinary\n\nsingleBinary:\n  replicas: 1\n  persistence:\n    storageClass: gp2\n    accessModes:\n      - ReadWriteOnce\n    size: 20Gi\n\n  resources:\n    requests:\n      cpu: \"1\"\n      memory: \"2Gi\"\n    limits:\n      cpu: \"2\"\n      memory: \"4Gi\"\n\nsidecar:\n  image:\n    repository: kiwigrid\/k8s-sidecar\n    tag: 1.30.0\n  resources:\n    requests:\n      cpu: 50m\n      memory: 50Mi\n    limits:\n      cpu: 100m\n      memory: 100Mi\n\nbackend:\n  replicas: 0\nread:\n  replicas: 0\nwrite:\n  replicas: 0\n\nchunksCache:\n  allocatedMemory: 500<\/code><\/pre>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\u26a0\ufe0f<\/div>\n<div class=\"kg-callout-text\">In this custom values file, <b><strong style=\"white-space: pre-wrap;\">gp2<\/strong><\/b> is the StorageClass name used. Replace it with the StorageClass present in your cluster.<\/div>\n<\/div>\n<p>In this, we are using the pods <code>filesystem<\/code> as storage for logs, which is a temporary storage.<\/p>\n<p>For the production environment, configure external storage like <a href=\"https:\/\/devopscube.com\/configure-loki-s3\/\" rel=\"noreferrer\">AWS S3<\/a>, Azure Blob Storage, etc.<\/p>\n<pre><code>deploymentMode: SingleBinary\n\nsingleBinary:\n  replicas: 1\n  persistence:\n    storageClass: gp2\n    accessModes:\n      - ReadWriteOnce\n    size: 20Gi<\/code><\/pre>\n<blockquote><p><strong>Note:<\/strong> By specifying the deployment mode as <code>SingleBinary<\/code>, we are deploying Loki as <code>monolithic<\/code>.<\/p>\n<p>It is a single binary deployment, which means all its components, such as the ingester, distributor, etc, run as a single pod.<\/p><\/blockquote>\n<p>The persistence volume configuration is also set with <code>20GB<\/code> the storage, you can modify it as per your requirements.<\/p>\n<p>Then, we configured the resource limit and requested the Loki and sidecar containers.<\/p>\n<pre><code>chunksCache:\n  allocatedMemory: 1024<\/code><\/pre>\n<p>We have also set the allocatedMemory for chunksCache pod to <code>1GB<\/code>, by default it allocates <code>8GB<\/code> for the pod, and it results in the chunksCache pod in the pending state with the following error.<\/p>\n<pre><code>Warning  FailedScheduling  96s (x2 over 97s)  default-scheduler  0\/2 nodes are available: 2 Insufficient memory. preemption: 0\/2 nodes are available: 2 No preemption victims found for incoming pod.<\/code><\/pre>\n<p>If you have more resources on your cluster, you can remove the above chunksCache allocatedMemory block from the values file.<\/p>\n<p>Since Loki is deployed as a <code>StatefulSet<\/code>, the logs will be saved on the same persistent volume even if the Loki pod is deleted and deployed again.<\/p>\n<p>Following are the images used in this Helm chart.<\/p>\n<ol>\n<li>grafana\/loki<\/li>\n<li>nginxinc\/nginx-unprivileged<\/li>\n<li>grafana\/loki-canary<\/li>\n<li>grafana\/loki-helm-test<\/li>\n<li>memcached<\/li>\n<li>prom\/memcached-exporter<\/li>\n<li>kiwigrid\/k8s-sidecar<\/li>\n<\/ol>\n<blockquote><p>Note: Setting up Loki as <a href=\"https:\/\/grafana.com\/docs\/loki\/latest\/setup\/install\/helm\/install-microservices\/?ref=devopscube.com\">MicroService<\/a> or <a href=\"https:\/\/grafana.com\/docs\/loki\/latest\/setup\/install\/helm\/install-scalable\/?ref=devopscube.com\">Scalable<\/a> mode is not so different from setting up Monolithic Loki, you just have to change the deployment mode in values file and increase the replicas of each Loki components.<\/p><\/blockquote>\n<h3 id=\"step-3-deploy-loki\">Step 3: Deploy Loki<\/h3>\n<p>Once the values file is set, deploy the Loki Helm chart with the values file using the following command.<\/p>\n<pre><code>helm install loki grafana\/loki -n loki --create-namespace -f loki.yaml<\/code><\/pre>\n<p>This creates a namespace <code>loki<\/code> and deploys the pods.<\/p>\n<p>Once the above command completes running, run the following command to check if the Loki pods are deployed.<\/p>\n<pre><code>kubectl get po -n loki<\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-17-6.png\" class=\"kg-image\" alt=\"pods deployed for loki monolithic mode\" loading=\"lazy\" width=\"1680\" height=\"810\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-17-6.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-17-6.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-17-6.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-17-6.png 1680w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>If every pod is running, move on to the next step.<\/p>\n<h3 id=\"step4-customize-grafana-alloy-helm-values-file\">Step4: Customize Grafana Alloy Helm Values file<\/h3>\n<p>The next step is to deploy <code>Alloy<\/code>, which is a log collecting agent for Loki.<\/p>\n<p>Download the Alloy values file using the following command, if you need to make any changes.<\/p>\n<pre><code>helm show values grafana\/alloy &gt; alloy.yaml<\/code><\/pre>\n<p>You can also use our custom values file.<\/p>\n<pre><code>alloy:\n  configMap:\n    content: |-\n      logging {\n        level = \"debug\"\n        format = \"logfmt\"\n      }\n      discovery.kubernetes \"pods\" {\n        role = \"pod\"\n      }\n      discovery.relabel \"pods\" {\n        targets = discovery.kubernetes.pods.targets\n\n        rule {\n          source_labels = [\"__meta_kubernetes_namespace\"]\n          target_label = \"namespace\"\n          action = \"replace\"\n        }\n\n        rule {\n          source_labels = [\"__meta_kubernetes_pod_label_app_kubernetes_io_name\"]\n          target_label = \"app\"\n          action = \"replace\"\n        }\n\n        rule {\n          source_labels = [\"__meta_kubernetes_pod_container_name\"]\n          target_label = \"container\"\n          action = \"replace\"\n        }\n\n        rule {\n          source_labels = [\"__meta_kubernetes_pod_name\"]\n          target_label = \"pod\"\n          action = \"replace\"\n        }\n      }\n      loki.source.kubernetes \"pods\" {\n        targets    = discovery.relabel.pods.output\n        forward_to = [loki.process.process.receiver]\n      }\n      loki.process \"process\" {\n        forward_to = [loki.write.loki.receiver]\n\n        stage.drop {\n          older_than          = \"1h\"\n          drop_counter_reason = \"too old\"\n        }\n        stage.match { \n          selector = \"{instance=~\\\".*\\\"}\"\n          stage.json {\n            expressions = {\n              level = \"\\\"level\\\"\",\n            }\n          }\n          stage.labels {\n            values = { \n              level = \"level\",\n            }\n          }\n        }\n        stage.label_drop {\n          values = [ \"service_name\" ]\n        }\n      }\n      loki.write \"loki\" {\n        endpoint {\n          url = \"http:\/\/loki-gateway\/loki\/api\/v1\/push\"\n        }\n      }\n  mounts:\n    varlog: true\n    dockercontainers: true\n\n  resources:\n    limits:\n      cpu: 200m\n      memory: 128Mi\n    requests:\n      cpu: 100m\n      memory: 128Mi<\/code><\/pre>\n<p>We have added resource request and limit for alloy pods.<\/p>\n<pre><code>loki.write \"loki\" {\n  endpoint {\n    url = \"http:\/\/loki-gateway\/loki\/api\/v1\/push\"\n  }\n}<\/code><\/pre>\n<p>The above block specifies the loki gateway endpoint, where the logs must be sent.<\/p>\n<p>By default the URL will be <code>http:\/\/loki-gateway\/loki\/api\/v1\/push<\/code>.<\/p>\n<p>If you disabled Loki gateway, the URL will be changed, which will be Loki\u2019s service URL <code>http:\/\/loki:3100\/loki\/api\/v1\/push<\/code>.<\/p>\n<p>This URL will only work if both Loki and Alloy are deployed in the same namespace, if both are in different namespaces, the URL will be <code>http:\/\/loki.loki.svc.cluster.local:3100\/loki\/api\/v1\/push<\/code>.<\/p>\n<p>Following are the images used in this Helm chart.<\/p>\n<ol>\n<li>grafana\/alloy<\/li>\n<li>prometheus-operator\/prometheus-config-reloader<\/li>\n<\/ol>\n<h3 id=\"step-5-install-grafana-alloy\">Step 5: Install Grafana Alloy<\/h3>\n<p>Once the values file is set, deploy the <code>Alloy<\/code> application with the values file using the following command.<\/p>\n<pre><code>helm install grafana-alloy grafana\/alloy -n loki -f alloy.yaml<\/code><\/pre>\n<p>Run the following command to check if the alloy pods are deployed.<\/p>\n<pre><code>kubectl get po -n loki<\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-97.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1632\" height=\"810\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/05\/image-97.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/05\/image-97.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/05\/image-97.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/05\/image-97.png 1632w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>You can see the Alloy pods are deployed as <code>Daemonset<\/code>.<\/p>\n<h3 id=\"step-6-customize-grafana-helm-values-file\">Step 6: Customize Grafana Helm Values file<\/h3>\n<p>The next step is to deploy <code>Grafana<\/code>, which we will use to query Loki and visualize it.<\/p>\n<p>Download the Grafana values file using the following command, if you need to make any changes.<\/p>\n<p>You can also use our custom values file.<\/p>\n<pre><code>image:\n  repository: grafana\/grafana\n  tag: latest\n  pullPolicy: IfNotPresent\n\nresources:\n  requests:\n    cpu: 100m\n    memory: 128Mi\n  limits:\n    cpu: 500m\n    memory: 512Mi\n\ndatasources:\n  datasources.yaml:\n    apiVersion: 1\n    datasources:\n    - name: Loki\n      type: loki\n      url: http:\/\/loki-gateway.loki.svc.cluster.local\n      access: proxy\n      isDefault: false\n      editable: true\n\nservice:\n  type: NodePort\n  port: 80<\/code><\/pre>\n<p>You can see we have added Loki as a <code>datasource<\/code> for Grafana, so we don&#8217;t have to configure it manually after logging in to Grafana.<\/p>\n<p>Also set the Grafana service  <code>Nodeport<\/code> to access the UI using the <code>node IP and nodeport<\/code>.<\/p>\n<blockquote><p>Exposing service as NodePort is not recommended for production environment, user Load Balancers or Ingress to expose the application.<\/p><\/blockquote>\n<p>Following are the images used in this Helm chart.<\/p>\n<ol>\n<li>grafana\/grafana<\/li>\n<li>bats\/bats<\/li>\n<li>curlimages\/curl<\/li>\n<li>library\/busybox<\/li>\n<li>kiwigrid\/k8s-sidecar<\/li>\n<\/ol>\n<h3 id=\"step-7-install-grafana\">Step 7: Install Grafana<\/h3>\n<p>Once the values file is set, deploy <code>Grafana<\/code> with the values file using the following command.<\/p>\n<pre><code>helm install grafana grafana\/grafana -n grafana --create-namespace -f g.yaml<\/code><\/pre>\n<p>This command will create a <code>namespace grafana<\/code> if not present and deploy the <code>Grafana pod<\/code> in it.<\/p>\n<p>Run the following command to check if the Grafana pod is deployed.<\/p>\n<pre><code>kubectl get po -n grafana<\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-20-8.png\" class=\"kg-image\" alt=\"checking if grafana pod is up and running\" loading=\"lazy\" width=\"1510\" height=\"510\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-20-8.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-20-8.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-20-8.png 1510w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Since we have exposed the Grafana service as NodePort, we can access the Grafana dashboard using the node IP and node port assigned to your service.<\/p>\n<h3 id=\"step-8-log-in-to-grafana-ui\">Step 8: Log in to Grafana UI<\/h3>\n<p>Access your Grafana on the browser using the <code>node IP and node port<\/code>, you will get the following window.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-19-6.png\" class=\"kg-image\" alt=\"Login to Grafana using the username and password\" loading=\"lazy\" width=\"1722\" height=\"1070\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-19-6.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-19-6.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-19-6.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-19-6.png 1722w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Login to Grafana using the username and password. Your default username will be <code>admin<\/code> and to get the password run the following command<\/p>\n<pre><code>kubectl get secret --namespace grafana grafana -o jsonpath=\"{.data.admin-password}\" | base64 --decode ; echo<\/code><\/pre>\n<p>This command will show your password for Grafana. Use the password to log in to Grafana.<\/p>\n<p>Once you log in, you can see the home screen of Grafana, press the three lines at the top left corner, you can see the menu, then go to <code>Connections &gt; Data sources<\/code> as shown in the below image.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-51-2.png\" class=\"kg-image\" alt=\"Grafana UI\" loading=\"lazy\" width=\"616\" height=\"436\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-51-2.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-51-2.png 616w\"><\/figure>\n<p>In the <code>Data sources<\/code> you can see Loki has been configured as default.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-54-3.png\" class=\"kg-image\" alt=\"Add adding loki as data source on grafana\" loading=\"lazy\" width=\"1024\" height=\"471\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-54-3.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-54-3.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-54-3.png 1024w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now, check if you are getting logs.<\/p>\n<p>Go to <code>Explore<\/code> by pressing the <code>Explore<\/code> button.<\/p>\n<p>To query logs select a <code>Label<\/code><strong> <\/strong>and <code>Value<\/code>, Loki will collect every log in your Kubernetes cluster and label it according to container, <a href=\"https:\/\/devopscube.com\/kubernetes-pod\/\">pod<\/a>, namespace, and other objects of <a href=\"https:\/\/devopscube.com\/kubernetes-tutorials-beginners\/\" rel=\"noreferrer noopener\">Kubernetes<\/a>.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-56-5.png\" class=\"kg-image\" alt=\"Filtering the logs using loki\" loading=\"lazy\" width=\"2000\" height=\"1019\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-56-5.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-56-5.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-56-5.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-56-5.png 2198w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>After selecting a <code>Label<\/code> and <code>Value<\/code>, press the Live button at the top right corner to query logs.<\/p>\n<p>You can also set a time to query logs. For example, if you set the time to <code>5s<\/code> it queries logs every <code>5s<\/code>.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-58-3.png\" class=\"kg-image\" alt=\"Filtering the logs using loki\" loading=\"lazy\" width=\"2000\" height=\"1118\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-58-3.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-58-3.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-58-3.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-58-3.png 2000w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>After pressing the Live button, scroll down to view the logs from the <code>Label<\/code> and <code>Value<\/code> you select.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-59-4.png\" class=\"kg-image\" alt=\"Filtering the logs using loki\" loading=\"lazy\" width=\"1944\" height=\"1016\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-59-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-59-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-59-4.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-59-4.png 1944w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>I believe this helped you to set up the Loki on Kubernetes using Helm. We also learned how to query logs using Loki from the Grafana dashboard.<\/p>\n<p>You can use our <a href=\"https:\/\/devopscube.com\/configure-loki-s3\/\" rel=\"noreferrer\">Configure S3 for Loki<\/a> blog to add S3 as log storage for Loki.<\/p>\n<p>If you want more detailed information about Grafana setup, you can use our guide on <a href=\"https:\/\/devopscube.com\/setup-grafana-kubernetes\/\">setting up Grafana on Kubernetes.<\/a><\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/setup-grafana-loki\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Setup Grafana Loki on Kubernetes &amp;amp; Query Logs \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/setup-grafana-loki\/<\/p>\n","protected":false},"author":1,"featured_media":577,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-576","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/576","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=576"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/576\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/577"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}