top of page

AWS EKS 로그 관리...다들 하고 계시죠?

AWS EKS 로그 관리...다들 하고 계시죠? - AWS EKS에서 효과적인 로그 관리 Fluent Bit으로 시작하기

AWS EKS 로그 관리...다들 하고 계시죠? - AWS EKS에서 효과적인 로그관리 Fluent Bit으로 시작하기

Written by Minhyeok Cha


예전에 공부하려고 작성한 노트들을 정리하다 EKS 관련된 글을 발견했습니다. 완전 주니어때 정리한 거라 제가 이해하고 작성한 건지도 모르겠더라고요. 그래서 다시 복습도 할 겸, 블로그 소재로 삼을 겸 하나 들고 왔습니다.


간단한 아키텍처로 먼저 소개하겠습니다.

아키텍처

nginx이미지는 그냥 로그 테스트용으로 넣었습니다. 사실 이게 없으면 아키텍처가 너무 심심해 보여서 억지로 끼워 넣은 거라고 봐도 무방합니다.


이제 Fluent-bit이라는 새 친구를 통해 로그 가져다가 OpenSearch로 보내는 과정을 살펴보려고 합니다.



 

Fluent-bit이란?

본격적으로 시작하기 전에 Fluent-bit가 무엇을 하는 친구인지 알아보겠습니다.

Fluentd는 사실 많이 들었던 EFK (Elasticsearch, Fluentd, Kibana)에서 F를 담당하는 친구입니다. 이 친구는 EFK의 하나인 만큼 많은 곳에서 신뢰를 얻는 오픈소스 로그 수집기입니다.

그리고 오늘 사용할 Fluent Bit는 최대한 가볍게 사용하기 위해 만들어졌습니다.


Fluentd와 Fluent-bit의 차이점


Fluentd

Fluent Bit

리소스 사용

많은 리소스를 사용합니다. (일반적으로 수십 MB의 메모리)

매우 경량화되어 있어 메모리 사용량이 적습니다.(보통 수 MB)

기능성

플러그인과 확장 기능을 제공하여 복잡한 로그 처리 시나리오를 지원합니다.

기본적인 로그 수집 및 전송 기능에 초점을 맞춥니다.

구성 복잡성

더 복잡한 구성이 가능하며, 고급 기능을 위해서는 더 많은 설정이 필요할 수 있습니다.

비교적 간단한 구성으로 시작할 수 있습니다.

💡 Fluent Bit이 더 가볍고 사용이 용이하다고 합니다.


데모 시작

1. EKS 클러스터 생성, Opensearch 도메인 생성

💡 이 부분(EKS, 도메인 생성)은 주요 내용이 아니라 패스하겠습니다.

2. OIDC 생성

# eksctl로 만드는 방법
eksctl utils associate-iam-oidc-provider \
	--cluster eks \
	--approve
콘솔에서 OIDC 생성하기
콘솔로 생성하시려면 사진을 참고하세요. 공급자 URL은 EKS cluster에 들어가면 있습니다.

IAM 역할에 연결할 정책 생성

fluent-bit-policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "es:ESHttp*"
            ],
            "Resource": "arn:aws:es:${AWS_REGION}:${ACCOUNT_ID}:domain/${ES_DOMAIN_NAME}",
            "Effect": "Allow"
        }
    ]
}

위에서 만든 OIDC와 정책을 가지고 iamserviceaccount 생성

kubectl create namespace log

eksctl create iamserviceaccount \
    --name fluent-bit \
    --namespace log \
    --cluster eks-logging \
    --attach-policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/fluent-bit-policy" \
    --approve \
    --override-existing-serviceaccounts
💡 콘솔로 가서 생성된 역할 및 적용된 정책, Opensearch 도메인 등이 잘 적용되었는지 확인합니다.

3. OpenSearch 액세스 권한 부여

사전에 생성된 혹은 기존에 있는 오픈서치 ID와 PW를 변수로 넣고 다음 명령어를 사용합니다.

 curl -sS -u " ${ES_DOMAIN_USER} : ${ES_DOMAIN_PASSWORD} " \ 
    -X PATCH \ "https://{opensearchendpoint}/_opendistro/_security/api/rolesmapping/all_access?pretty" \ 
    -H 'Content-Type: application/json' \ 
    -d '[ 
            { 
                "op": "add", "path": "/backend_roles", "value": ["'iamsa:role:arn'"] 
            } 
        ]'

4. Fluent Bit 설치

Fluent Bit은 쿠버네티스 기준으로 config 설정과 데몬셋을 배포해 주면, 완료입니다.


먼저 cluster role을 만들고 service account와 바인딩 작업을 해주는 파일을 하나 작성합니다.

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: fluent-bit-read
rules:
- apiGroups: [""]
  resources:
  - namespaces
  - pods
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: fluent-bit-read
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: fluent-bit-read
subjects:
- kind: ServiceAccount
  name: fluent-bit
  namespace: log

ConfigMap입니다.

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: fluent-bit-config
  namespace: logging
  labels:
    k8s-app: fluent-bit
data:
  fluent-bit.conf: |
    [SERVICE]
        Flush         1
        Log_Level     info
        Daemon        off
        Parsers_File  parsers.conf
        HTTP_Server   On
        HTTP_Listen   0.0.0.0
        HTTP_Port     2020

    @INCLUDE input-kubernetes.conf
    @INCLUDE filter-kubernetes.conf
    @INCLUDE output-elasticsearch.conf

  input-kubernetes.conf: |
    [INPUT]
        Name              tail
        Tag               kube.*
        Path              /var/log/nginx/access.log
        Parser            docker
        DB                /var/log/flb_kube.db
        Mem_Buf_Limit     50MB
        Skip_Long_Lines   On
        Refresh_Interval  10

  filter-kubernetes.conf: |
    [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
        Kube_Tag_Prefix     kube.var.log.containers.
        Merge_Log           On
        Merge_Log_Key       log_processed
        K8S-Logging.Parser  On
        K8S-Logging.Exclude Off

  output-elasticsearch.conf: |
  output-opensearch.conf: |
    [OUTPUT]
        Name            es
        Match           *
        Host            "오픈서치 도메인"
        Port            443
        TLS             On
        AWS_Auth        On
        AWS_Region      ap-northeast-2
        Index           "오픈서치에 들어갈 인덱스"
        Replace_Dots    On
        Suppress_Type_Name On

제가 config 부분에서 애를 먹었는데, output에서 "Suppress_Type_Name"을 켜야 합니다. 처음에 설치 후 로그를 쏴보니 Fluent Bit에서 OpenSearch로 보낼 수 없다는 오류만 나와서 역할 바인딩 이슈의 문제인 줄 알았습니다.

삽질하여 찾아본 결과, Fluent Bit의 설정이 최신 OpenSearch 버전과 호환되지 않아 그런 거더라고요. 따라서 위와 같이 configmap 설정을 하여 로그 전송에 성공하였습니다.


parser.conf 파일도 공식 링크에 잘 작성되어 있으며, 저희는 테스트를 nginx로 진행할 예정이라 다음과 같이 사용했습니다.

parsers.conf: |
		[PARSER]
		    Name   nginx
		    Format regex
		    Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")
		    Time_Key time
		    Time_Format %d/%b/%Y:%H:%M:%S %z

    [PARSER]
        Name   json
        Format json
        Time_Key time
        Time_Format %d/%b/%Y:%H:%M:%S %z

    [PARSER]
        Name        docker
        Format      json
        Time_Key    time
        Time_Format %Y-%m-%dT%H:%M:%S.%L
        Time_Keep   On

Deamonset 입니다.

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluent-bit
  namespace: log
  labels:
    k8s-app: fluent-bit-logging
    version: v1
    kubernetes.io/cluster-service: "true"

spec:
  selector:
    matchLabels:
      k8s-app: fluent-bit-logging
  template:
    metadata:
      labels:
        k8s-app: fluent-bit-logging
        version: v1
        kubernetes.io/cluster-service: "true"
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "2020"
        prometheus.io/path: /api/v1/metrics/prometheus
    spec:
      containers:
      - name: fluent-bit
        image: amazon/aws-for-fluent-bit:2.5.0
        imagePullPolicy: Always
        ports:
          - containerPort: 2020
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: fluent-bit-config
          mountPath: /fluent-bit/etc/
      terminationGracePeriodSeconds: 10
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: fluent-bit-config
        configMap:
          name: fluent-bit-config
      serviceAccountName: fluent-bit
 

남은 부분은 제가 저번에 작성한 데이터 파이프라인 구축 중 logstash와 비슷한 맥락의 파일입니다.

정확한 설명 참고는 공식 문서를 읽어보면 좋을 것 같습니다.

Kubernetes | Fluent Bit: Official Manual
Configuring Parser | Fluent Bit: Official Manual

5. 테스트 이미지 배포 및 Fluent Bit 로그 확인

# 데모 nginx pod 만들기
 kubectl run nginx --image=nginx -n default 

# nginx에 10개의 HTTP GET 요청을 하는 루프 
for i in {1..10}; do
  kubectl exec -it nginx -n default -- curl -s http://{파드 IP 조회해서 기입} | grep -q . && echo "Request $i: Success" || echo "Request $i: Failure"
done

# nginx pod 로그 확인
kubectl logs nginx -n default

# fluent bit 로그 적재 및 전달 확인
kubectl logs (fluent bit pod name) -n log


Opensearch 도메인 접속 및 로그 확인

Opensearch에서는 패턴을 만들어야 대시보드에서 로그를 간편하게 볼 수 있습니다.

OpenSearch에서 index pattern 만들기
OpenSearch 대시보드에서 로그 보기
OpenSearch 대시보드에서 로그 보기: nginx에 쏜 로그가 전달된 것을 확인할 수 있습니다.
💡 nginx에 쏜 로그가 전달된 것을 확인할 수 있습니다.


마무리

Fluent Bit이 컨테이너에서 주로 쓰는 로그 수집기로 유명해 AWS OpenSearch와 EKS 클러스터를 통합하는 데모 세션을 EKS 복습 겸 진행해 보았습니다.

EKS는 manifest 파일로 운용되는 느낌이 강해서 다시 보니 yaml 파일만 잔뜩 있어 읽기가 귀찮네요.

그래서 더 쉬운 방법이 없나 찾아봤는데, 요즘엔 이런 것도 있더라고요.

eks-charts/stable/aws-for-fluent-bit at master ・ aws/eks-charts

이 글을 보시는 분들은 helm 사용법을 찾아보시면 좋을 것 같습니다.


그리고 개인적으로 궁금했던 Logstach가 컨테이너에 못 쓰는 이유를 찾아봤습니다. 사이즈가 무거운 것도 있지만 핵심 기능 중 하나인 영구 큐 같은 기능이 스테이트리스 컨테이너 환경에서 사용이 힘들다고 하네요.


이번에 컨테이너 로그 구축을 하며 느낀 점은, 뭐든 하기 전에 공식 문서를 먼저 읽는 게 좋다는 것입니다. 파일 하나하나 읽어가면서 오랜만에 삽질도 하고 눈도 아팠네요. 여러분들은 이점을 참고하셔서 눈 아프지 마시길 바랍니다.

조회수 19회댓글 0개

Comments


bottom of page