BlogTechTODAY'S PICKS EKS + Fluent bit + OpenSearch 구성을 통한 로그 수집 TECH by Sangmi Park 2024년 02월 08일 2024년 02월 08일 381 1-a. EFK (ElasticSearch + Fluented + Kibana)란? EFK란 ElasitcSearch + Fluentd bit + Kibana의 조합을 일컬음보통 지속적으로 유입되는 로그 데이터를 수신하고 이 데이터를 차트와 그래프로 시각화 하거나 분석할때 사용하는 솔루션2021년 9월, Elastic의 라이선스 변경으로 인해 AWS에서는 ElasticSearch에 대한 업데이트 제공을 중단함. 기존 ElasticSearch를 포크(Fork)하여 OpenSearch라는 오픈 소스 서비스를 개시하고,Elastic에서 함께 지원하던 시각화 도구인 Kibana는 OpenSearch Dashboard 라는 서비스로 지원 1-b. OpenSearch + Fluent bit + OpenSearch Dashboard Fluent bit : 데이터(로그)를 수집해서 Opensearch로 전달OpenSearch : Fluentd로부터 받은 데이터를 검색 및 집계하여 필요한 정보 획득OpenSearch Dashboard: Opensearch의 빠른 검색능력을 통해 데이터 시각화 및 모니터링 1-c. Fluentd / Fluent bit / LogStash 장단점 장점단점Fluentd– 다양한 데이터 소스에서 로그를 수집하고 대용량 데이터 처리를 지원하는 포괄적인 로그 수집기– 풍부한 플러그인과 커뮤니티 지원이 제공됨– 일부 환경에서 성능이 떨어질 수 있으며, 메모리 사용량이 크고 설정이 상대적으로 복잡함Fluent bit– 경량화 되어 자원 소모가 적고, 빠른 처리 속도 제공– 컨테이너 환경에 적합하고 메모리 효율성이 뛰어남– 로그 처리 파이프라인이 다른 컴포넌트와 비교했을 때,일부 기능이 제한적일 수 있음LogStash– 다양한 데이터 입력과 출력 플러그인 지원– ElasticSearch와의 연동이 강력하며, 데이터 처리 파이프라인 구축이 상대적으로 용이– 자원 소모가 크고, 처리량이 많은 시나리오에서성능에 제약이 있을 수 있음 2-a. 사전 준비사항 1) 로그를 생성할 애플리케이션 생성git clone https://github.com/GoogleCloudPlatform/microservices-demo.git cd microservice-demo 2) 애플리케이션 yaml 파일 클러스터에 적용kubectl apply -f ./microservice-demo/release/kubernetes-manifests.yaml 3) 배포 확인kubectl get pod -A -n logging 2-b. Elasticsearch(Amazon OpenSearch Service) 생성 https://docs.aws.amazon.com/ko_kr/opensearch-service/latest/developerguide/createupdatedomains.html 를 참고하여 Elasticsearch 생성 2-c. AWS IRSA (IAM Role for Service Account) 설정 Kubernetes Service Account와 AWS IAM 역할을 연결하여 AWS 리소스에 대한 접근 권한을 부여하는 접근제어 방식1) EKS OIDC Identity Providers 생성 IAM > Access Management > Identity Providers > Add Provider → 공급자 유형 : OpenID Connect → 공급자 URL EKS > Clusters > 클러스터 선택 > Overview > OpenID Connect provider URL → 대상 : sts.amazonaws.com 2) IAM Policy 생성 IAM > Access Management > Policies > Create policy{ "Version": "2012-10-17", "Statement": [ { "Action": [ "es:ESHttp*" ], "Resource": "${OPENSEARCH_ARN}", "Effect": "Allow" } ]}→ ${OPENSEARCH_ARN} : 생성한 OpenSearch의 ARN 정보로 교체 3) IAM Role 생성 IAM > Access Management > Policies > Create role→ 신뢰할 수 있는 엔터티 유형 : 사용자 지정 신뢰 정책{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "${IDENTITY_PROVIDER_ARN}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${IDENTITY_PROVIDER}:aud": "sts.amazonaws.com", "${IDENTITY_PROVIDER}:sub": "${SERVICE_ACCOUNT_NAME}", } } } ] } → ${IDENTITY_PROVIDER_ARN} : 위에서 확인한 EKS OpenID Connect provider ARN 값→ ${IDENTITY_PROVIDER}:aud : 위에서 확인한 EKS OpenID Connect provider→ ${IDENTITY_PROVIDER}:sub : 생성할 Service Account 이름 2-d. RBAC (Role-Based Access Control) 설정 Kubernetes Service Account에게 클러스터 수준의 리소스 접근을 제어할 권한 부여1) Service Account 생성apiVersion: v1 kind: ServiceAccount metadata: name: fluent-bit annotations: eks.amazonaws.com/role-arn: ${IAM_ROLE_ARN} namespace: logging 2) Cluster Role 생성apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluent-bit-read rules: - apiGroups: - "" resources: - namespaces - pods verbs: - get - list - watch 3) Cluster Role Binding 생성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: logging 2-e. Fluent-bit ConfigMap 생성 apiVersion: v1 kind: ConfigMap metadata: labels: k8s-app: fluent-bit name: fluent-bit-config namespace: logging 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-opensearch.conf input-kubernetes.conf: | [INPUT] Name tail Tag kube.* Path /var/log/containers/*.log Parser docker DB /var/log/flb_kube.db Mem_Buf_Limit 5MB 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 On output-opensearch.conf: | [OUTPUT] Name es Match * Host ${OPENSEARCH_ENDPOINT} Port 443 TLS On AWS_Auth On AWS_Region ${AWS_REGION} Index ${INDEX_NAME} Replace_Dots On Suppress_Type_Name On parsers.conf: | [PARSER] Name docker Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L Time_Keep On→ [INPUT] Path /var/log/containers/*.log : 수집할 로그가 위치한 경로→ [OUTPUT] Host ${OPENSEARCH_ENDPOINT} AWS_Region ${AWS_REGION} Index ${INDEX_NAME} : Daemonset 컨테이너의 환경 변수에서 설정데몬셋(DaemonSet)과 ${OPENSEARCH_ENDPOINT} 변수를 사용하여 각 노드가 자체의OpenSearch 인스턴스로 로그 데이터를 전송하도록 구성하면, 각 노드가 독립적으로 로그 데이터를 처리하므로써 장애상황이 발생하여도 다른 노드는 정상적으로 로그 데이터를 전송하고 처리할 수 있습니다. 이로 인해 단일 포인트 오브 실패를 피할 수 있으며, 클러스터의 안정성과 로그 데이터의 신뢰성을 향상시킬 수 있음 2-f. Fluent-bit Daemonset 생성 apiVersion: apps/v1 kind: DaemonSet metadata: labels: k8s-app: fluent-bit-logging kubernetes.io/cluster-service: "true" version: v1 name: fluent-bit namespace: logging spec: selector: matchLabels: k8s-app: fluent-bit-logging template: metadata: annotations: prometheus.io/path: /api/v1/metrics/prometheus prometheus.io/port: "2020" prometheus.io/scrape: "true" labels: k8s-app: fluent-bit-logging kubernetes.io/cluster-service: "true" version: v1 spec: containers: - env: - name: OPENSEARCH_ENDPOINT value: ${OPENSEARCH_ENDPOINT} - name: AWS_REGION value: ${AWS_REGION} - name: INDEX_NAME value: ${INDEX_NAME} name: fluent-bit image: amazon/aws-for-fluent-bit:2.28.0 imagePullPolicy: Always ports: - containerPort: 2020 volumeMounts: - mountPath: /var/log name: varlog - mountPath: /var/lib/docker/containers name: varlibdockercontainers readOnly: true - mountPath: /fluent-bit/etc/ name: fluent-bit-config serviceAccountName: fluent-bit terminationGracePeriodSeconds: 10 tolerations: - effect: NoSchedule key: node-role.kubernetes.io/master operator: Exists - effect: NoExecute operator: Exists - effect: NoSchedule operator: Exists volumes: - hostPath: path: /var/log name: varlog - hostPath: path: /var/lib/docker/containers name: varlibdockercontainers - configMap: name: fluent-bit-config name: fluent-bit-config→ ${OPENSEARCH_ENDPOINT} : OpenSearch endpoint url (https:// 포함 X)→ ${AWS_REGION}→ ${INDEX_NAME} : 수집된 로그 데이터를 OpenSearch로 전송하기 전 어떤 인덱스 이름에 해당 로그를 저장할 지 정의→ image: amazon/aws-for-fluent-bit:2.28.0→ serviceAccountName: fluent-bit : 위에서 생성한 IAM Role에 설정값으로 지정 3. OpenSearch 동작 확인 1) OpenSearch 접속 2) 인덱스 패턴 생성메뉴 > Management > Stack Management > Index Patterns > Create index patternStep 1 of 2 위에서 설정한 Index Name (eks-log)를 검색하면 일치하는 소스가 조회됨 로그데이터에 time이라는 필드에 이벤트 시간 정보가 포함되어있다면 OpenSearch에서 @timestamp 필드에 매핑하게 되어정확한 시간 순서로 이벤트를 확인할 수 있음 3) 로그 적재 확인 방금 읽은 인사이트를 실무에 직접 적용하고 싶으시다면?지금 바로 베스핀글로벌에 문의하세요. 베스핀글로벌 문의하기