基於Loki打造雲原生分散式日誌系統
簡介
Grafana Loki是一個水平可擴充套件,高可用性,多租戶的日誌聚合系統,包含了日誌收集,儲存,視覺化以及報警等功能。
與其他日誌系統不同,Loki的構想是僅對日誌建立標籤索引,而使原始日誌訊息保持未索引狀態。這意味著Loki的運營成本更低,並且效率更高。
Loki特別適合儲存Kubernetes Pod日誌。諸如Pod標籤之類的元資料會自動被抓取並建立索引。
與EFK對比
EFK(Elasticsearch,Fluentd,Kibana)技術棧用於收集,視覺化和查詢來自各種來源的日誌。 Elasticsearch中的資料作為非結構化JSON物件儲存在磁碟上。每個物件的鍵和每個鍵的內容都被索引。然後可以使用JSON物件或定義為Lucene的查詢語言來查詢資料。
相比之下,Loki在單二進位制模式下可以將資料儲存在磁碟上,但是在水平可伸縮模式下,資料儲存在雲端儲存系統(例如S3,GCS或Cassandra)中。日誌以純文字格式儲存,並帶有一組標籤名稱和值,其中僅對標籤對進行索引。這種折衷使得它比全索引更具備成本優勢,並且允許開發人員從其應用程式積極地進行日誌記錄。使用LogQL查詢Loki中的日誌。但是,由於這種設計的折衷,基於內容(即日誌行中的文字)進行過濾的LogQL查詢需要載入搜尋視窗中與查詢中定義的標籤匹配的所有塊。
此外,我們知道metrcis和alert只能揭示預定義的問題,未知的問題還得從Log裡邊查詢。日誌和 metric 分在兩個系統,這增加了排查問題的難度。我們的日誌和metrcis系統需要建立聯絡,而靈感來源於prometheus的loki,恰好解決了這個問題。
Loki架構
Loki大體架構如下:
接下來我們介紹一些核心元件:
Distributor
—— Distributor 服務負責處理客戶端的寫入流。這是日誌資料寫入路徑中的第一站。Distributor收到一組流後,將驗證每個流的正確性並確保其在配置的租戶(或全域性)限制之內。然後,將有效塊拆分為多個批次,並並行傳送到多個ingester。
Distributor 使用一致性雜湊和可配置的複製因子,以確定ingester服務的哪些例項應接收給定的流。流是與租戶和唯一標籤集關聯的一組日誌。使用租戶ID和標籤集對流進行雜湊,然後使用雜湊查詢將流傳送到的例項。
Ingester
—— Ingester服務負責在寫入路徑上將日誌資料寫入到長期儲存後端(DynamoDB,S3,Cassandra等),並在讀取路徑上返回日誌資料以進行記憶體中查詢。
Ingester包含一個生命週期器,該生命週期器管理雜湊環中ingester的生命週期。每個ingester狀態為以下狀態中的一種:
PENDING
,
JOINING
,
ACTIVE
,
LEAVING
或
UNHEALTHY
。
Query frontend
—— Query frontend是一項可選服務,可提供查詢器的API終結點,並可用於加速讀取路徑。當Query frontend就位時,應將傳入的查詢請求定向到Query frontend,而不是Querier。為了執行實際查詢,叢集中仍將需要Querier服務。
Query frontend在內部執行一些查詢調整,並將查詢儲存在內部佇列中。在此設定中,Queriers充當工作人員,將工作從佇列中拉出,執行,然後將其返回到Query frontend進行聚合。Queriers需要配置Query frontend地址(透過-querier。frontend-address CLI標誌),以允許Queriers連線到Query frontend。
Query frontend是無狀態的。但是,由於內部佇列的工作原理,建議執行一些Query frontend副本以充分利用公平排程的好處。在大多數情況下,兩個副本就足夠了。
Querier
——Querier 使用 LogQL 查詢語言處理查詢,同時從ingester和長期儲存中獲取日誌。
Querier將查詢所有記憶體中的記憶體資料,然後回退到針對後端儲存執行相同的查詢。由於副本因素,Querier可能會收到重複的資料。為解決此問題,Querier在內部對具有相同納秒級時間戳,標籤集和日誌訊息的資料進行重複資料刪除。
Chunk Store
—— Chunk Store是Loki的長期資料儲存,旨在支援互動式查詢和持續寫入,而無需後臺維護任務。它包括:
塊的索引。該索引可以透過以下方式支援:
Amazon DynamoDB
Google Bigtable
Apache Cassandra
塊資料本身的鍵值(KV)儲存,可以是:
Amazon DynamoDB
Google Bigtable
Apache Cassandra
Amazon S3
Google Cloud Storage
當然還可以包括做日誌報警的ruler元件以及負責在其時間段開始之前建立週期表,並在其資料時間範圍超出保留期限時將其刪除的table-manager。
部署
Loki微服務部署模式,涉及元件比較多,我們生產環境使用k8s部署,當然涉及到敏感資訊已經去掉。
Chuck 儲存選擇的是s3,index儲存選擇的是Cassandra。
1:建立s3 桶,然後將aksk新增到下面的配置檔案中。Cassandra 叢集搭建我們這裡不再講述。
2:部署loki的配置檔案,
apiVersion: v1
data:
config。yaml: |
chunk_store_config:
chunk_cache_config:
memcached:
batch_size: 100
parallelism: 100
memcached_client:
consistent_hash: true
host: memcached。loki。svc。cluster。local
service: memcached-client
max_look_back_period: 0
write_dedupe_cache_config:
memcached:
batch_size: 100
parallelism: 100
memcached_client:
consistent_hash: true
host: memcached-index-writes。loki。svc。cluster。local
service: memcached-client
auth_enabled: false
distributor:
ring:
kvstore:
store: memberlist
frontend:
compress_responses: true
log_queries_longer_than: 5s
max_outstanding_per_tenant: 200
frontend_worker:
frontend_address: query-frontend。loki。svc。cluster。local:9095
grpc_client_config:
max_send_msg_size: 1。048576e+08
parallelism: 2
ingester:
chunk_block_size: 262144
chunk_idle_period: 15m
lifecycler:
heartbeat_period: 5s
interface_names:
- eth0
join_after: 30s
num_tokens: 512
ring:
kvstore:
store: memberlist
replication_factor: 3
max_transfer_retries: 0
ingester_client:
grpc_client_config:
max_recv_msg_size: 6。7108864e+07
remote_timeout: 1s
limits_config:
enforce_metric_name: false
ingestion_burst_size_mb: 20
ingestion_rate_mb: 10
ingestion_rate_strategy: global
max_cache_freshness_per_query: 10m
max_global_streams_per_user: 10000
max_query_length: 12000h
max_query_parallelism: 16
max_streams_per_user: 0
reject_old_samples: true
reject_old_samples_max_age: 168h
querier:
query_ingesters_within: 2h
query_range:
align_queries_with_step: true
cache_results: true
max_retries: 5
results_cache:
cache:
memcached_client:
consistent_hash: true
host: memcached-frontend。loki。svc。cluster。local
max_idle_conns: 16
service: memcached-client
timeout: 500ms
update_interval: 1m
split_queries_by_interval: 30m
ruler: {}
schema_config:
configs:
- from: “2020-05-15”
index:
period: 168h
prefix: cassandra_table
object_store: s3
schema: v11
store: cassandra
server:
graceful_shutdown_timeout: 5s
grpc_server_max_concurrent_streams: 1000
grpc_server_max_recv_msg_size: 1。048576e+08
grpc_server_max_send_msg_size: 1。048576e+08
http_listen_port: 3100
http_server_idle_timeout: 120s
http_server_write_timeout: 1m
storage_config:
cassandra:
username: loki-superuser
password: xxx
addresses: loki-dc1-all-pods-service。cass-operator。svc。cluster。local
auth: true
keyspace: lokiindex
aws:
bucketnames: xx
endpoint: s3。amazonaws。com
region: ap-southeast-1
access_key_id: xx
secret_access_key: xx
s3forcepathstyle: false
index_queries_cache_config:
memcached:
batch_size: 100
parallelism: 100
memcached_client:
consistent_hash: true
host: memcached-index-queries。loki。svc。cluster。local
service: memcached-client
memberlist:
abort_if_cluster_join_fails: false
bind_port: 7946
join_members:
- loki-gossip-ring。loki。svc。cluster。local:7946
max_join_backoff: 1m
max_join_retries: 10
min_join_backoff: 1s
table_manager:
creation_grace_period: 3h
poll_interval: 10m
retention_deletes_enabled: true
retention_period: 168h
kind: ConfigMap
metadata:
name: loki
namespace: loki
——-
apiVersion: v1
data:
overrides。yaml: |
overrides: {}
kind: ConfigMap
metadata:
name: overrides
namespace: loki
2:部署依賴的4個memcached:
memcached-frontend。yaml如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: memcached-frontend
name: memcached-frontend
namespace: loki
spec:
replicas: 3
selector:
matchLabels:
app: memcached-frontend
serviceName: memcached-frontend
template:
metadata:
annotations:
prometheus。io/scrape: “true”
prometheus。io/port: “9150”
labels:
app: memcached-frontend
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: memcached-frontend
topologyKey: kubernetes。io/hostname
containers:
- args:
- -m 1024
- -I 5m
- -c 1024
- -v
image: memcached:1。5。17-alpine
imagePullPolicy: IfNotPresent
name: memcached
ports:
- containerPort: 11211
name: client
resources:
limits:
cpu: “3”
memory: 1536Mi
requests:
cpu: 500m
memory: 1329Mi
- args:
- ——memcached。address=localhost:11211
- ——web。listen-address=0。0。0。0:9150
image: prom/memcached-exporter:v0。6。0
imagePullPolicy: IfNotPresent
name: exporter
ports:
- containerPort: 9150
name: http-metrics
updateStrategy:
type: RollingUpdate
——-
apiVersion: v1
kind: Service
metadata:
labels:
app: memcached-frontend
name: memcached-frontend
namespace: loki
spec:
ports:
- name: memcached-client
port: 11211
targetPort: 11211
selector:
app: memcached-frontend
memcached-index-queries。yaml 如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: memcached-index-queries
name: memcached-index-queries
namespace: loki
spec:
replicas: 3
selector:
matchLabels:
app: memcached-index-queries
serviceName: memcached-index-queries
template:
metadata:
annotations:
prometheus。io/scrape: “true”
prometheus。io/port: “9150”
labels:
app: memcached-index-queries
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: memcached-index-queries
topologyKey: kubernetes。io/hostname
containers:
- args:
- -m 1024
- -I 5m
- -c 1024
- -v
image: memcached:1。5。17-alpine
imagePullPolicy: IfNotPresent
name: memcached
ports:
- containerPort: 11211
name: client
resources:
limits:
cpu: “3”
memory: 1536Mi
requests:
cpu: 500m
memory: 1329Mi
- args:
- ——memcached。address=localhost:11211
- ——web。listen-address=0。0。0。0:9150
image: prom/memcached-exporter:v0。6。0
imagePullPolicy: IfNotPresent
name: exporter
ports:
- containerPort: 9150
name: http-metrics
updateStrategy:
type: RollingUpdate
——-
apiVersion: v1
kind: Service
metadata:
labels:
app: memcached-index-queries
name: memcached-index-queries
namespace: loki
spec:
clusterIP: None
ports:
- name: memcached-client
port: 11211
targetPort: 11211
selector:
app: memcached-index-queries
memcached-index-writes。yaml 如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: memcached-index-writes
name: memcached-index-writes
namespace: loki
spec:
replicas: 3
selector:
matchLabels:
app: memcached-index-writes
serviceName: memcached-index-writes
template:
metadata:
annotations:
prometheus。io/scrape: “true”
prometheus。io/port: “9150”
labels:
app: memcached-index-writes
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: memcached-index-writes
topologyKey: kubernetes。io/hostname
containers:
- args:
- -m 1024
- -I 1m
- -c 1024
- -v
image: memcached:1。5。17-alpine
imagePullPolicy: IfNotPresent
name: memcached
ports:
- containerPort: 11211
name: client
resources:
limits:
cpu: “3”
memory: 1536Mi
requests:
cpu: 500m
memory: 1329Mi
- args:
- ——memcached。address=localhost:11211
- ——web。listen-address=0。0。0。0:9150
image: prom/memcached-exporter:v0。6。0
imagePullPolicy: IfNotPresent
name: exporter
ports:
- containerPort: 9150
name: http-metrics
updateStrategy:
type: RollingUpdate
——-
apiVersion: v1
kind: Service
metadata:
labels:
app: memcached-index-writes
name: memcached-index-writes
namespace: loki
spec:
clusterIP: None
ports:
- name: memcached-client
port: 11211
targetPort: 11211
selector:
app: memcached-index-writes
memcached。yaml 如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: memcached
name: memcached
namespace: loki
spec:
replicas: 3
selector:
matchLabels:
app: memcached
serviceName: memcached
template:
metadata:
annotations:
prometheus。io/scrape: “true”
prometheus。io/port: “9150”
labels:
app: memcached
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: memcached
topologyKey: kubernetes。io/hostname
containers:
- args:
- -m 4096
- -I 2m
- -c 1024
- -v
image: memcached:1。5。17-alpine
imagePullPolicy: IfNotPresent
name: memcached
ports:
- containerPort: 11211
name: client
resources:
limits:
cpu: “3”
memory: 6Gi
requests:
cpu: 500m
memory: 5016Mi
- args:
- ——memcached。address=localhost:11211
- ——web。listen-address=0。0。0。0:9150
image: prom/memcached-exporter:v0。6。0
imagePullPolicy: IfNotPresent
name: exporter
ports:
- containerPort: 9150
name: http-metrics
updateStrategy:
type: RollingUpdate
——-
apiVersion: v1
kind: Service
metadata:
labels:
app: memcached
name: memcached
namespace: loki
spec:
clusterIP: None
ports:
- name: memcached-client
port: 11211
targetPort: 11211
selector:
app: memcached
對於這4個memcached 的作用,大家可以結合loki的配置檔案和架構圖查閱。
4:在Loki中,ring是由tokens分成較小段的空間。每個段都屬於單個“ ingester”,用於對多個ingester的系列/日誌進行分片。除tokens外,每個例項還具有其ID,地址和定期更新的最新心跳時間戳。這允許其他元件(distributors 和 queriers)發現哪些inester是可用的和有效的。
支援consul ,etcd,memberlist(gossip) 等實現。 我們為了減少不必要的依賴,選擇了memberlist。
所以需要部署一個service:
gossip_ring。yaml 如下:
apiVersion: v1
kind: Service
metadata:
labels:
name: loki-gossip-ring
name: loki-gossip-ring
namespace: loki
spec:
ports:
- name: gossip-ring
port: 7946
targetPort: 7946
protocol: TCP
selector:
gossip_ring_member: ‘true’
5:部署distributor
apiVersion: apps/v1
kind: Deployment
metadata:
name: distributor
namespace: loki
labels:
app: distributor
spec:
minReadySeconds: 10
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: distributor
template:
metadata:
annotations:
prometheus。io/path: /metrics
prometheus。io/port: “3100”
prometheus。io/scrape: “true”
labels:
app: distributor
gossip_ring_member: ‘true’
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: distributor
topologyKey: kubernetes。io/hostname
containers:
- args:
- -config。file=/etc/loki/config/config。yaml
- -limits。per-user-override-config=/etc/loki/overrides/overrides。yaml
- -target=distributor
image: grafana/loki:1。6。1
imagePullPolicy: IfNotPresent
name: distributor
ports:
- containerPort: 3100
name: http-metrics
- containerPort: 9095
name: grpc
- containerPort: 7946
name: gossip-ring
readinessProbe:
httpGet:
path: /ready
port: 3100
initialDelaySeconds: 15
timeoutSeconds: 1
resources:
limits:
cpu: “1”
memory: 1Gi
requests:
cpu: 500m
memory: 500Mi
volumeMounts:
- mountPath: /etc/loki/config
name: loki
- mountPath: /etc/loki/overrides
name: overrides
volumes:
- configMap:
name: loki
name: loki
- configMap:
name: overrides
name: overrides
——-
apiVersion: v1
kind: Service
metadata:
labels:
name: distributor
name: distributor
namespace: loki
spec:
ports:
- name: distributor-http-metrics
port: 3100
targetPort: 3100
- name: distributor-grpc
port: 9095
targetPort: 9095
selector:
app: distributor
6:部署ingester
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ingester
namespace: loki
labels:
app: ingester
spec:
updateStrategy:
type: RollingUpdate
replicas: 3
serviceName: ingester
selector:
matchLabels:
app: ingester
strategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
template:
metadata:
annotations:
prometheus。io/path: /metrics
prometheus。io/port: “3100”
prometheus。io/scrape: “true”
labels:
name: ingester
gossip_ring_member: ‘true’
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
securityContext:
fsGroup: 10001
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: ingester
topologyKey: kubernetes。io/hostname
containers:
- args:
- -config。file=/etc/loki/config/config。yaml
- -limits。per-user-override-config=/etc/loki/overrides/overrides。yaml
- -target=ingester
image: grafana/loki:1。6。1
imagePullPolicy: IfNotPresent
name: ingester
ports:
- containerPort: 3100
name: http-metrics
- containerPort: 9095
name: grpc
- containerPort: 7946
name: gossip-ring
readinessProbe:
httpGet:
path: /ready
port: 3100
initialDelaySeconds: 15
timeoutSeconds: 1
resources:
limits:
cpu: “2”
memory: 10Gi
requests:
cpu: “1”
memory: 5Gi
volumeMounts:
- mountPath: /etc/loki/config
name: loki
- mountPath: /etc/loki/overrides
name: overrides
- mountPath: /data
name: ingester-data
terminationGracePeriodSeconds: 4800
volumes:
- configMap:
name: loki
name: loki
- configMap:
name: overrides
name: overrides
volumeClaimTemplates:
- metadata:
labels:
app: querier
name: ingester-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: gp2
——-
apiVersion: v1
kind: Service
metadata:
labels:
name: ingester
name: ingester
namespace: loki
spec:
ports:
- name: ingester-http-metrics
port: 3100
targetPort: 3100
- name: ingester-grpc
port: 9095
targetPort: 9095
selector:
app: ingester
7:部署query-frontend
apiVersion: apps/v1
kind: Deployment
metadata:
name: query-frontend
namespace: loki
labels:
app: query-frontend
spec:
minReadySeconds: 10
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
name: query-frontend
template:
metadata:
annotations:
prometheus。io/path: /metrics
prometheus。io/port: “3100”
prometheus。io/scrape: “true”
labels:
app: query-frontend
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: query-frontend
topologyKey: kubernetes。io/hostname
containers:
- args:
- -config。file=/etc/loki/config/config。yaml
- -limits。per-user-override-config=/etc/loki/overrides/overrides。yaml
- -log。level=debug
- -target=query-frontend
image: grafana/loki:master-92ace83
imagePullPolicy: IfNotPresent
name: query-frontend
ports:
- containerPort: 3100
name: http-metrics
- containerPort: 9095
name: grpc
readinessProbe:
httpGet:
path: /ready
port: 3100
initialDelaySeconds: 15
timeoutSeconds: 1
resources:
limits:
memory: 1200Mi
requests:
cpu: “2”
memory: 600Mi
volumeMounts:
- mountPath: /etc/loki/config
name: loki
- mountPath: /etc/loki/overrides
name: overrides
volumes:
- configMap:
name: loki
name: loki
- configMap:
name: overrides
name: overrides
——-
apiVersion: v1
kind: Service
metadata:
labels:
name: query-frontend
name: query-frontend
namespace: loki
spec:
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: query-frontend-http-metrics
port: 3100
targetPort: 3100
- name: query-frontend-grpc
port: 9095
targetPort: 9095
selector:
app: query-frontend
8:部署querier
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
name: querier
name: querier
namespace: loki
spec:
updateStrategy:
type: RollingUpdate
replicas: 3
serviceName: querier
selector:
matchLabels:
app: querier
template:
metadata:
annotations:
prometheus。io/path: /metrics
prometheus。io/port: “3100”
prometheus。io/scrape: “true”
labels:
app: querier
gossip_ring_member: ‘true’
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
securityContext:
fsGroup: 10001
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: querier
topologyKey: kubernetes。io/hostname
containers:
- args:
- -config。file=/etc/loki/config/config。yaml
- -limits。per-user-override-config=/etc/loki/overrides/overrides。yaml
- -target=querier
image: grafana/loki:1。6。1
imagePullPolicy: IfNotPresent
name: querier
ports:
- containerPort: 3100
name: http-metrics
- containerPort: 9095
name: grpc
- containerPort: 7946
name: gossip-ring
readinessProbe:
httpGet:
path: /ready
port: 3100
initialDelaySeconds: 15
timeoutSeconds: 1
resources:
requests:
cpu: “4”
memory: 2Gi
volumeMounts:
- mountPath: /etc/loki/config
name: loki
- mountPath: /etc/loki/overrides
name: overrides
- mountPath: /data
name: querier-data
volumes:
- configMap:
name: loki
name: loki
- configMap:
name: overrides
name: overrides
volumeClaimTemplates:
- metadata:
labels:
app: querier
name: querier-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: gp2
——-
apiVersion: v1
kind: Service
metadata:
labels:
name: querier
name: querier
namespace: loki
spec:
ports:
- name: querier-http-metrics
port: 3100
targetPort: 3100
- name: querier-grpc
port: 9095
targetPort: 9095
selector:
app: querier
9:部署table manager
apiVersion: apps/v1
kind: Deployment
metadata:
name: table-manager
namespace: loki
labels:
app: table-manager
spec:
minReadySeconds: 10
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: table-manager
template:
metadata:
annotations:
prometheus。io/path: /metrics
prometheus。io/port: “3100”
prometheus。io/scrape: “true”
labels:
app: table-manager
spec:
nodeSelector:
group: loki
tolerations:
- effect: NoExecute
key: app
operator: Exists
containers:
- args:
- -bigtable。backoff-on-ratelimits=true
- -bigtable。grpc-client-rate-limit=5
- -bigtable。grpc-client-rate-limit-burst=5
- -bigtable。table-cache。enabled=true
- -config。file=/etc/loki/config/config。yaml
- -limits。per-user-override-config=/etc/loki/overrides/overrides。yaml
- -target=table-manager
image: grafana/loki:1。6。1
imagePullPolicy: IfNotPresent
name: table-manager
ports:
- containerPort: 3100
name: http-metrics
- containerPort: 9095
name: grpc
readinessProbe:
httpGet:
path: /ready
port: 3100
initialDelaySeconds: 15
timeoutSeconds: 1
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- mountPath: /etc/loki/config
name: loki
volumes:
- configMap:
name: loki
name: loki
——-
apiVersion: v1
kind: Service
metadata:
labels:
app: table-manager
name: table-manager
namespace: loki
spec:
ports:
- name: table-manager-grpc
port: 9095
targetPort: 9095
selector:
app: table-manager
部署完成之後,可以檢視所有pod執行狀態:
kubectl get pods -n loki
NAME READY STATUS RESTARTS AGE
distributor-84747955fb-hhtzl 1/1 Running 0 8d
distributor-84747955fb-pq9wn 1/1 Running 0 8d
distributor-84747955fb-w66hp 1/1 Running 0 8d
ingester-0 1/1 Running 0 8d
ingester-1 1/1 Running 0 8d
ingester-2 1/1 Running 0 8d
memcached-0 2/2 Running 0 3d2h
memcached-1 2/2 Running 0 3d2h
memcached-2 2/2 Running 0 3d2h
memcached-frontend-0 2/2 Running 0 3d2h
memcached-frontend-1 2/2 Running 0 3d2h
memcached-frontend-2 2/2 Running 0 3d2h
memcached-index-queries-0 2/2 Running 0 3d2h
memcached-index-queries-1 2/2 Running 0 3d2h
memcached-index-queries-2 2/2 Running 0 3d2h
memcached-index-writes-0 2/2 Running 0 3d3h
memcached-index-writes-1 2/2 Running 0 3d3h
memcached-index-writes-2 2/2 Running 0 3d3h
querier-0 1/1 Running 0 3d3h
querier-1 1/1 Running 0 3d3h
querier-2 1/1 Running 0 3d3h
query-frontend-6c8ffc8667-qj5zq 1/1 Running 0 8d
table-manager-c4fdf6475-zjzqg 1/1 Running 0 8d
至此,部署工作完成。至於promtail外掛,本文不作介紹,目前支援loki資料來源的外掛比較多,比如fluent bit 等。
視覺化
Grafana已經透過Explore元件支援對loki直接查詢。
透過標籤組合來實現查詢。
總結
如果對全文索引不是強需求,那麼loki是k8s 日誌系統的一個比較好的選擇。