Build centralized logging with ELK Stack, Loki, or CloudWatch Logs.
You are a logging infrastructure expert. Help me set up log aggregation.
## Logging Needs
Log sources: ${{SOURCES}}
Volume: ${{VOLUME}}
Retention: ${{RETENTION}}
Search needs: ${{SEARCH}}
## Please Configure:
1. **Fluent Bit Configuration**
```ini
# fluent-bit.conf
[SERVICE]
Flush 1
Log_Level info
Parsers_File parsers.conf
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
Mem_Buf_Limit 5MB
Skip_Long_Lines On
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
K8S-Logging.Parser On
[FILTER]
Name modify
Match *
Add cluster production
[OUTPUT]
Name es
Match *
Host elasticsearch
Port 9200
Index logs-%Y.%m.%d
Type _doc
Logstash_Format On
```
2. **Elasticsearch Setup**
```yaml
# elasticsearch.yaml (Kubernetes)
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: logs
spec:
version: 8.11.0
nodeSets:
- name: default
count: 3
config:
node.store.allow_mmap: false
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
# Index Lifecycle Policy
PUT _ilm/policy/logs-policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "1d"
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": { "number_of_shards": 1 },
"forcemerge": { "max_num_segments": 1 }
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
```
3. **Grafana Loki Setup**
```yaml
# loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
ingester:
lifecycler:
ring:
kvstore:
store: inmemory
replication_factor: 1
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /loki/boltdb-shipper-active
cache_location: /loki/boltdb-shipper-cache
shared_store: filesystem
filesystem:
directory: /loki/chunks
limits_config:
enforce_metric_name: false
reject_old_samples: true
reject_old_samples_max_age: 168h
```
4. **Promtail Agent**
```yaml
# promtail-config.yaml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
pipeline_stages:
- cri: {}
- json:
expressions:
level: level
msg: message
- labels:
level:
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
target_label: app
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
```
5. **CloudWatch Logs**
```yaml
# Fluent Bit to CloudWatch
[OUTPUT]
Name cloudwatch_logs
Match *
region us-east-1
log_group_name /ecs/myapp
log_stream_prefix from-fluent-bit-
auto_create_group true
```
6. **Log Parsing**
```ini
# parsers.conf
[PARSER]
Name json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%LZ
[PARSER]
Name nginx
Format regex
Regex ^(?<remote>[^ ]*) - (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^"]*)" "(?<agent>[^"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
```
7. **Kibana Visualization**
```json
// Saved search
{
"query": {
"bool": {
"must": [
{ "match": { "kubernetes.namespace": "production" } },
{ "range": { "level": { "gte": "error" } } }
],
"filter": [
{ "range": { "@timestamp": { "gte": "now-1h" } } }
]
}
}
}
```
8. **Alerting**
```yaml
# Elasticsearch Watcher
PUT _watcher/watch/error-alert
{
"trigger": {
"schedule": { "interval": "5m" }
},
"input": {
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"bool": {
"must": [
{ "match": { "level": "error" } },
{ "range": { "@timestamp": { "gte": "now-5m" } } }
]
}
}
}
}
}
},
"condition": {
"compare": { "ctx.payload.hits.total": { "gt": 10 } }
},
"actions": {
"notify_slack": {
"webhook": {
"url": "https://hooks.slack.com/services/xxx"
}
}
}
}
```Or press ⌘C to copy
Replace these placeholders with your own content before using the prompt.
[{SOURCES][{VOLUME][{RETENTION][{SEARCH]{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "1d"
}{
"min_age": "7d",
"actions": {
"shrink": { "number_of_shards": 1 }{ "max_num_segments": 1 }{
"min_age": "30d",
"actions": {
"delete": {}{
"query": {
"bool": {
"must": [
{ "match": { "kubernetes.namespace": "production" }{ "range": { "level": { "gte": "error" }{ "range": { "@timestamp": { "gte": "now-1h" }{
"trigger": {
"schedule": { "interval": "5m" }{
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"bool": {
"must": [
{ "match": { "level": "error" }{ "range": { "@timestamp": { "gte": "now-5m" }{
"compare": { "ctx.payload.hits.total": { "gt": 10 }{
"notify_slack": {
"webhook": {
"url": "https://hooks.slack.com/services/xxx"
}[SERVICE][INPUT][FILTER][OUTPUT][PARSER]