DevOPS kubernetes

Giải pháp Logging trong Kubernetes với Fluentd

Như chúng ta đã biết, docker container trong k8s sẽ ghi logs băng phương thức stream sdtout và sdterr ( standard output và errer). Sau đó, Docker sẽ chuyển hướng những stream này đến logging driver, tiếp đến, k8s sẽ ghi ra file những Log này với định dạng Json. Đây là cách thức ghi logs thông thường trong Kubernetes.  
Tuy nhiên, việc này sẽ có một vài khuyết điểm. Những log này sẽ bị mất nếu các pod hoặc các node bị xóa đi. Lúc này chúng ta sẽ không có Logs để trace được vấn đề khi có sự cố xảy ra. Để giải quyết vấn đề này, chúng ta cần phải chuyển những logs này đi một nơi khác để lưu trữ.  K8s cho phép chúng ta dễ dàng thiết lập việc này thông qua Kubernetes API controller. Để vận chuyển logs sẽ có những cách thức sau:
    + thứ nhất, cài đặt sidecar chạy trực tiếp trong mỗi service.
    + thứ hai, cài agent trên mỗi node, từ đó lấy logs những service chạy trên node đó.
    + cuối cùng, đẩy logs trực tiếp từ trong service đến central log.

Sử dụng Sidecar containers
Với cách này, chúng ta có thể cài 1 hoặc nhiều sidecar bên trong apps. Sidecar này sẽ đảm nhiệm việc lấy logs sdtout/stderror từ trong. Việc này sẽ có những lợi ích sau:

  • Có thể lấy được những logs độc lập cho từng app. Điều này sẽ rất có ích nếu chúng ta có nhiều định dạng logs khác nhau, nhiều định dạng hỗn độn sẽ khó cho việc quản lý, thì đây là lựa chọn tốt.

  • Lấy được logs thực tế của apps mà không cần phải ghi ra stdout hoặc stderr.

Tuy nhiên, nó cũng sẽ có khuyết điểm:

  • Logs sẽ được ghi ra một file và sau đó mới stream chúng đến stdout, Việc này sẽ làm tăng dung lượng disk. 
  • Nếu như chúng ta có quá nhiều ứng dụng, thì cứ mỗi app bắt buộc phải cài 1 sidecar. Điều này quá thủ công và tốn thời gian.

Cài đặt Agent trên mỗi Node
Ưu điểm:
Các Agent khi được cài trên mỗi Node, chúng có thể truy cập được các Logs của các service chạy trên đó. Với cách này có thể sẽ khắc phục được 2 khuyết điểm của Sidecar đã đề cập phía trên. Cách đơn giản nhất để triển khai các agent này là sử dụng "Daemonset". với Daemonset này, nó sẽ đảm bảo là trên mỗi node đều sẽ có ít nhất 1 agent chạy trên đó, đồng thời nó sẽ định kỳ kiểm tra các trạng thái của Node. 

Khuyết Điểm:
Deamonset chỉ làm việc với stdout và stderror của app.

Deploying Fluentd để thu thập  Application Logs
Việc triển khai theo cách thức Node-level agent này được sử dụng phổ biến trong K8s. Vì chúng ta chỉ cần cài 1 agent trên mỗi node là có thể lấy được Logs của tất cả service chạy trên nó. Ở đây, chúng ta sẽ chọn Fluenttd agent bởi vì sự phố biến của nó, đồng thời nó hỗ trợ nhiều đầu ra như:  Elasticsearch, Splunnk, Kafka, RabbitMQ, Slack ….

Bước 1: Cấp quyền cho Fluentd

apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: fluentd
  namespace: kube-system
rules:
- apiGroups:
- ""
  resources:
  - pods
  - namespaces
  verbs:
  - get
  - list
  - watch

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: fluentd
roleRef:
  kind: ClusterRole
  name: fluentd
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: kube-system

Lưu lại file và thực thi:
kubectl create -f rbac.yml

Bước 2: Triển khai DaemonSet

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
    version: v1
    kubernetes.io/cluster-service: "true"
spec:
  template:
    metadata:
      labels:
        k8s-app: fluentd-logging
        version: v1
        kubernetes.io/cluster-service: "true"
    spec:
      serviceAccount: fluentd
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:elasticsearch
        env:
        - name:  FLUENT_ELASTICSEARCH_HOST
          value: "f505e785.qb0x.com"
        - name:  FLUENT_ELASTICSEARCH_PORT
          value: "30216"
        - name: FLUENT_ELASTICSEARCH_SCHEME
          value: "https"
        - name: FLUENT_UID
          value: "0"
        # X-Pack Authentication
        # =====================
        - name: FLUENT_ELASTICSEARCH_USER
          value: "abf54990f0a286dc5d76"
        - name: FLUENT_ELASTICSEARCH_PASSWORD
          value: "75c4bd6f7b"
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

Lưu ý:
+ fluent/fluentd-kubernetes-daemonset:elasticsearch :  images Fluentd
+ chúng ta nên cung cấp các biến môi trường để connect tới Cluster Elastcsearch.
+ Fluent cần quyền root để có thể đọc, ghi được file trong /var/log. Để tránh lỗi phân quyền, do đó chúng ta sẽ set biến môi trường FLUENT_UID = 0.
lưu file và tiến hành thực thi:
kubectl create -f fluentd-elasticsearch.yml
Kiểm tra xem trạng thái fluentd có kết nối thành công hay không, chúng ta sẽ thấy được output như sau:

2018–09–11 09:20:05 +0000 [info]: 
Connection opened to Elasticsearch cluster => {:host=>”f505e785.qb0x.com”, 
:port=>30216, :scheme=>”https”, :user=>”abf54990f0a286dc5d76", :password=>”obfuscated”}

Kiểm tra logs được thu thập từ Fluentd trên Dashboard Kibana:
Management -> Index Patterns -> Create New Index Pattern

Ở đây, chúng ta sẽ thấy logs của App và Log của hệ thống K8s, với các thông tin: namespace, Docker container ID, labels …
log:INFO: == Kubernetes addon reconcile completed at 2018-09-11T09:31:39+0000 == stream:stdout docker.container_id:9b596c9195003246af0f71406f05ab4d339601dadc213048202992739fe9267e kubernetes.container_name:kube-addon-manager kubernetes.namespace_name:kube-system kubernetes.pod_name:kube-addon-manager-minikube kubernetes.pod_id:f6d8ff9d-8a6e-11e8-9e55-0800270c281a kubernetes.labels.component:kube-addon-manager kubernetes.labels.version:v8.6

Tóm lại
Fluentd là một trong những cách tốt nhất cho giải pháp logging của K8s.  Trong bài hướng dẫn này, chúng tôi đã chứng minh cách mà Fluentd có thể dễ dàng để tập trung các logs từ nhiều application khác nhau và gửi chúng đến Elasticsearch hoặc bất kỳ ứng dụng đầu ra khác. Không giống như sidecar containers, bắt buộc phải cài đặt theo từng service, Node-level với Fluentd chỉ cần một agent chạy trên mỗi Node là đủ.

Người Viết:
LK

Add Comment

Click here to post a comment