> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Deploying and Viewing Application Logs

> Deploy a small Kubernetes app that emits JSON logs to stdout and verify collection and viewing in Grafana Loki using kubectl and LogQL

This guide shows how to deploy a tiny example application to a Kubernetes cluster where logs are already collected and forwarded to Grafana Loki. You will:

* Retrieve Grafana credentials and (optionally) install Alloy.
* Deploy a simple app that writes structured JSON logs to stdout.
* Verify logs locally with `kubectl logs`.
* Confirm the logs are visible in Grafana Assistant (Grafana Loki) using a LogQL query.

Prerequisites:

* A running Kubernetes cluster with the logging stack (Loki + Grafana) already installed.
* `kubectl`, `helm`, and `base64` (or equivalent) available on your workstation.

## 1) Retrieve Grafana admin credentials and install Alloy

Inspect the Grafana secret in the `logging` namespace and decode the admin user and password:

```bash theme={null}
# Inspect secret data keys
kubectl get secret -n logging grafana -o jsonpath='{.data}'

# Retrieve and decode admin user and password
kubectl get secret -n logging grafana -o jsonpath='{.data.admin-user}' | base64 -d
kubectl get secret -n logging grafana -o jsonpath='{.data.admin-password}' | base64 -d
```

If Alloy is not already installed, install it via Helm (using your values file):

```bash theme={null}
helm install alloy grafana/alloy --values alloy-values.yaml -n logging
```

Example output from the Helm install and the pods in the `logging` namespace (condensed):

```bash theme={null}
# Helm install
NAME: alloy
LAST DEPLOYED: Wed Jul 29 15:02:50 2026
NAMESPACE: logging
STATUS: deployed

# Pods in the logging namespace (example)
kubectl get pods -n logging
NAME                            READY   STATUS    RESTARTS   AGE
alloy-15qrd                     1/2     Running   0          27s
grafana-667db46f55-5phkq        1/1     Running   0          17m
loki-0                          2/2     Running   0          11m
loki-canary-74kxn               1/1     Running   0          11m
loki-chunks-cache-0             2/2     Running   0          11m
loki-gateway-d896ddd77-lws4f    2/2     Running   0          11m
loki-results-cache-0            2/2     Running   0          11m
seaweedfs-filer-0               1/1     Running   0          39m
seaweedfs-master-0              1/1     Running   0          39m
seaweedfs-s3-6fd7b5c6f9-qrvxp   1/1     Running   0          39m
seaweedfs-volume-0              1/1     Running   0          39m
```

## 2) Deploy the example application

Create a Deployment named `api` that uses the `kodekloud/loki-demo` image and emits structured JSON logs to stdout.

app-deployment.yaml:

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: kodekloud/loki-demo
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
```

Apply the manifest and watch the pod start:

```bash theme={null}
kubectl apply -f app-deployment.yaml
kubectl get pods --watch
```

Example progress (condensed):

```bash theme={null}
deployment.apps/api created

# Watching pods
NAME                        READY   STATUS              RESTARTS   AGE
api-68b9dbd6b5-hxp22        0/1     ContainerCreating   0          6s
api-68b9dbd6b5-hxp22        1/1     Running             0          39s
```

## 3) Verify logs are emitted to stdout

Once the pod is Running, tail its logs to confirm the app emits structured JSON lines:

```bash theme={null}
kubectl logs api-68b9dbd6b5-hxp22 -f
```

Sample JSON log lines emitted by the app (streamed):

```json theme={null}
{"level":30,"time":1785337590529,"pid":1,"hostname":"api-68b9dbd6b5-hxp22","method":"GET","route":"/users","code":"500"}
{"level":30,"time":1785337591529,"pid":1,"hostname":"api-68b9dbd6b5-hxp22","method":"GET","route":"/cart","code":"200"}
{"level":40,"time":1785337592530,"pid":1,"hostname":"api-68b9dbd6b5-hxp22","method":"DELETE","route":"/users","code":"401"}
{"level":30,"time":1785337593531,"pid":1,"hostname":"api-68b9dbd6b5-hxp22","method":"PATCH","route":"/cart","code":"401"}
{"level":40,"time":1785337594532,"pid":1,"hostname":"api-68b9dbd6b5-hxp22","method":"POST","route":"/users","code":"201"}
...
```

The log collector performs automatic discovery of pod logs (stdout/stderr) and forwards them to Grafana Loki, so applications that write to standard output are collected without extra configuration.

## 4) Query the logs in Grafana (Explore view)

Open Grafana Assistant (Explore view) and run a Loki query that filters by the Deployment label we applied. For example:

```logql theme={null}
{app="api"} |= ""
```

This LogQL expression selects log streams with the `app="api"` label and returns all log lines. Running it should stream the same JSON lines you saw with `kubectl logs`, confirming the logs reached Grafana Loki.

Example formatted output in Grafana Assistant (condensed):

```text theme={null}
2026-07-29 18:07:35.593 UNK {
  "level": 30,
  "time": 1785337655592,
  "pid": 1,
  "hostname": "api-68b9dbd6b5-hxp22",
  "method": "DELETE",
  "route": "/cart",
  "code": "401"
}
2026-07-29 18:07:34.592 UNK {
  "level": 30,
  "time": 1785337654591,
  "pid": 1,
  "hostname": "api-68b9dbd6b5-hxp22",
  "method": "GET",
  "route": "/cart",
  "code": "200"
}
...
```

## Quick reference

| Task | Command / Query | Purpose |
| - | - | - |
| Inspect Grafana secret keys | `kubectl get secret -n logging grafana -o jsonpath='{.data}'` | Show encoded keys in the secret |
| Decode admin credentials | `kubectl get secret -n logging grafana -o jsonpath='{.data.admin-password}' \| base64 -d` | Print admin user/password |
| Install Alloy (Helm) | `helm install alloy grafana/alloy --values alloy-values.yaml -n logging` | Optional Alloy install for Grafana |
| Deploy example app | `kubectl apply -f app-deployment.yaml` | Create the `api` Deployment |
| Tail pod logs | `kubectl logs <pod-name> -f` | Verify logs are emitted to stdout |
| Loki query | `{app="api"} \|= ""` | Filter logs in Grafana by `app=api` |

## Summary

* Deploy the example app and verify it writes structured JSON logs to stdout using `kubectl logs`.
* The cluster log collector auto-discovers pod stdout/stderr and forwards those logs to Grafana Loki—no per-app config required for stdout logs.
* Use a Grafana (Explore) LogQL query such as `{app="api"} |= ""` to view application logs in Grafana Assistant.

## Links and references

* [Grafana Loki](https://learn.kodekloud.com/user/courses/grafana-loki)
* [Grafana Assistant](https://learn.kodekloud.com/user/courses/grafana-assistant)
* [Kubernetes Documentation](https://kubernetes.io/docs/)

> **[Watch Video](https://learn.kodekloud.com/user/courses/grafana-loki/module/595f27e5-031e-46ea-bffc-ee1a15f73837/lesson/12afcd37-2167-4d8b-959f-ca89e2ffc601)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.