본문 바로가기
  • lakescript
스터디 이야기/AWS EKS

[AEWS] 4-1. Amazon EKS - Observability(EKS Logging)

by lakescript 2024. 3. 25.

사전 준비

더보기

 

위와 같이 사전 준비가 필요합니다.

저번 글에서 설명했듯이, EKS를 배포하기 위한 VPC를 생성하고, Public Subnet, Private Subnet을 생성합니다. 그 후 EKS Cluster에 접근하기 위한 bastion EC2를 미리 생성합니다.
추가로, 지난번 실습 때 진행했었던 ExternalDNS와 AWS LB Controller, EBS csi driver 설치, gp3 스토리지 클래스 생성까지 해주셔야합니다.

 

EKS Control Plane Logging

 
 
 
Amazon EKS는 관리형 서비스로 AWS에서 관리하는 Contol Plane과 사용자가 관리하는 Data Plane이 있습니다. Data Plane일 경우 다양한 모니터링 시스템을 적용하여 logging을 할 수 있는 반면, Control Plane은 AWS에서 관리하기 때문에 사용자가 직접 Logging하기 쉽지 않은데요. 특별한 옵션 설정으로 Logging이 가능합니다.
 

설정 방법

AWS Managed Console

 
AWS Managed Console에 접근하여 EKS메뉴 > 관찰성 탭으로 이동합니다. 그러면 위의 사진과 같이 API 서버, Authenticator, 스케줄러, 감시, 컨트롤러 관리자가 모두 off로 설정되어 있는 것을 확인하실 수 있습니다.

 
 
모두 Logging을 하기 위해 오른쪽 상단에 있는 로깅 관리 버튼을 클릭하고 각각 On으로 설정하고 저장합니다. 설정되기 까지 짧은 시간이 소요되는데, 새로고침 하게 되면 제어플레인 로깅 부분에서 모든 리소스의 Logging이 On으로 설정된 것을 확인하실 수 있습니다.
 
 

AWS CLI

aws eks update-cluster-config --region $AWS_DEFAULT_REGION --name $CLUSTER_NAME \
    --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'

 
위의 명령어로 로그 그룹을 생성합니다.

 
로그 그룹을 출력해보면 정상적으로 CloudWatch에 해당 로그 그룹이 생성된 것을 확인하실 수 있습니다.

 
그 후 CloudWatch에 접근해서 kube 필터로 로그 스트림을 살펴보면 정상적으로 로그를 수집중임을 확인하실 수 있습니다.
 

로그 확인 for cli

로그가 정상적으로 수집되는지 확인해보도록 하겠습니다.

aws logs tail /aws/eks/$CLUSTER_NAME/cluster --log-stream-name-prefix kube-controller-manager --follow

 
위의 명령어를 통해 kube-controller-manager의 log를 확인하겠습니다.
 

kubectl scale deployment -n kube-system coredns --replicas=1

현재 기본적으로 2개 배포되어있는 coredns 파드의 수를 1개로 줄여보겠습니다.
 

 
그럼 위의 사진 처럼 kube-controller-manager의 log가 정상적으로 쌓이는 것을 보실 수 있습니다!
 
 

로그 확인 for Log Insights

cli 외에 Console에서 확인하실 수 있는데, Cloudwatch 메뉴에 접근하여 로그 > Log Insights 탭에서 가능합니다.
 
Log Insights는 Cloudwatch에서 수집되고 있는 로그 그룹의 로그 스트림들을 SQL문으로 세부적으로 필터링하여 조회할 수 있게 해줍니다. 여기서는 몇가지 유용한 SQL문을 살펴보겠습니다.

EC2 Instance가 NodeNotReady 상태인 로그 검색

fields @timestamp, @message
| filter @message like /NodeNotReady/
| sort @timestamp desc

 

kube-apiserver-audit 로그에서 userAgent 정렬해서 아래 4개 필드 정보 검색

fields userAgent, requestURI, @timestamp, @message
| filter @logStream ~= "kube-apiserver-audit"
| stats count(userAgent) as count by userAgent
| sort count desc

 

각 Object들의 log 확인

kube-scheduler

fields @timestamp, @message
| filter @logStream ~= "kube-scheduler"
| sort @timestamp desc

 
authenticator

fields @timestamp, @message
| filter @logStream ~= "authenticator"
| sort @timestamp desc

 
kube-controller-manager
 

fields @timestamp, @message
| filter @logStream ~= "kube-controller-manager"
| sort @timestamp desc

 
이 처럼 각 @logStream에 수집하고 있는 로그스트림 이름을 명시하면 확인하실 수 있습니다.
 
또한 Log Insight는 CLI로도 확인 가능합니다.

aws logs get-query-results --query-id $(aws logs start-query \
--log-group-name '/aws/eks/myeks/cluster' \
--start-time `date -d "-1 hours" +%s` \
--end-time `date +%s` \
--query-string 'fields @timestamp, @message | filter @logStream ~= "kube-scheduler" | sort @timestamp desc' \
| jq --raw-output '.queryId')

 
 

EKS Data Plane Logging

 
 

Pod(Container) Logging

Pod의 로그는 주로 컨테이너의 표준 출력(stdout)표준 에러(stderr) 스트림을 통해 생성됩니다 특히, Kubernetes 클러스터에서는 각 노드의 kubelet이 컨테이너의 표준 출력과 표준 에러를 자동으로 캡처하여 해당 노드의 파일 시스템에 저장합니다. 이 파일들은 일반적으로 /var/log/containers/ 디렉토리에 위치하고, Pod 이름, 네임스페이스, 컨테이너 이름, Kubernetes 클러스터 내의 다른 식별 정보등 다양한 정보를 포함하는 파일 이름으로 저장됩니다.
 

Log를 표준 출력(STDOUT)와 표준 에러(STDERR)로 설정하는 이유

모든 컨테이너 애플리케이션이 stdout과 stderr를 사용하면, 로그 수집 및 관리 절차를 표준화할 수 있습니다. 이를 통해 다양한 애플리케이션에서 수집되는 로그를 통합적으로 처리할 수 있습니다. 또한, 쿠버네티스와 같은 컨테이너 오케스트레이션 시스템과 로그 수집 도구( Fluentd, Logstash등)가 stdout과 stderr에서 로그를 자동으로 캡처하고, 로그를 쉽게 수집, 검색, 분석할 수 있도록 중앙 집중식 로깅 시스템으로 전송합니다. 
 
 

Pod Logging 실습

실습을 통해 NGINX Pod를 배포해보고 직접 Log들을 확인해보겠습니다.
 

파라미터 파일 생성

service:
  type: NodePort
  
networkPolicy:
  enabled: false

ingress:
  enabled: true
  ingressClassName: alb
  hostname: nginx.$MyDomain
  pathType: Prefix
  path: /
  annotations: 
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
    alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
    alb.ingress.kubernetes.io/success-codes: 200-399
    alb.ingress.kubernetes.io/load-balancer-name: $CLUSTER_NAME-ingress-alb
    alb.ingress.kubernetes.io/group.name: study
    alb.ingress.kubernetes.io/ssl-redirect: '443'

 
위의 파일 명세는 alb를 배포하기 위한 설정 파일입니다. 여기서 특별한 점은 certificate-arn을 설정해줘야 하는데 아래의 명령어로 실행한 결과를 넣어주시면 됩니다.
 

certificate-arn 확인

CERT_ARN=$(aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text)

 
 

NGINX 웹서버 배포

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install nginx bitnami/nginx --version 15.14.0 -f nginx-values.yaml

 
 

NGINX 배포 확인

kubectl get ingress,deploy,svc,ep nginx

 

kubectl get targetgroupbindings

 
 
그 후 nginx URL로 접속하면 아래와 같이 정상적으로 접근하시는 것을 확인하실 수 있습니다!

 
 
 

Pod (Container) Log 확인

kubectl logs deploy/nginx -f

 
kubectl logs 명령어를 통해 위에서 배포한 nginx pod의 로그를 확인해보겠습니다.

 
 
해당 로그는 nginx container의 로그를 확인한 것이기에 아래의 명령어로 container log를 확인하면 같은 결과를 볼 수 있습니다.

kubectl logs $POD-NAME -c nginx

 
 

Container Insights metrics in Amazon CloudWatch & Fluent Bit

자! 그럼 stdout으로 Pod의 Log를 확인할 수 있고 CloudWatch를 통해 Cluster의 Log를 모니터링 할 수 있으니 Pod의 Log를 CloudWatch를 통해 모니터링 해보겠습니다.
 
 

 
위의 아키텍처를 보면 데몬셋으로 CloudWatch Agent와 Fluent-bit 컨테이너를 띄우게 됩니다. CloudWatch Agent 컨테이너는 metric data를 수집하고, Fluent-bit는 Pod들의 log를 수집하는 형태입니다. 여기서 주의하실 점은 log용 pod가 띄어지는 것이 아니라, side-car container 형태로 로그를 수집할 대상이 되는 Pod에 떠서 실시간으로 로그를 수집한다는 점입니다.
 
즉, 위의 아키텍처를 3가지의 단계로 정리해보겠습니다.

[수집]
플루언트비트 Fluent Bit 컨테이너를 데몬셋으로 동작시키고, 아래 3가지 종류의 로그를 CloudWatch Logs 에 전송
1. /aws/containerinsights/Cluster_Name/application : 로그 소스(All log files in /var/log/containers), 각 컨테이너/파드 로그
2. /aws/containerinsights/Cluster_Name/host : 로그 소스(Logs from /var/log/dmesg, /var/log/secure, and /var/log/messages), 노드(호스트) 로그
3. /aws/containerinsights/Cluster_Name/dataplane : 로그 소스(/var/log/journal for kubelet.service, kubeproxy.service, and docker.service), 쿠버네티스 데이터플레인 로그
[저장]
CloudWatch Logs 에 로그를 저장, 로그 그룹 별 로그 보존 기간 설정 가능
[시각화]
CloudWatch 의 Logs Insights 를 사용하여 대상 로그를 분석하고, CloudWatch 의 대시보드로 시각화한다

 
위에 명시된 것처럼 로그를 수집할 때에 경로가 각각 다릅니다.
 

application 로그 소스

모든 log 파일들이 /var/log/containers에서 수집되며 심볼릭 링크로 인해 /var/log/pods/<컨테이너>를 통해 각 컨테이너/파드의  로그를 수집합니다.
 

host 로그 소스

/var/log/dmesg, /var/log/secure, /var/log/messages에서 노드(호스트) 로그가 수집됩니다.
 

dataplane 로그 소스

/var/log/journal 안에 kubelet.service, kubeproxy.service, and docker.service등 쿠버네티스 데이터플레인 로그가 수집됩니다.
 
 
 

CloudWatch Container observability 설치

aws eks create-addon --cluster-name $CLUSTER_NAME --addon-name amazon-cloudwatch-observability

 
위의 명령어를 통해 addon으로 amazon-cloudwatch-observability를 설치합니다.
 

CloudWatch Container observability 설치 확인 

aws eks list-addons --cluster-name myeks --output table

 
addon이 정상적으로 설치된 것을 확인하고 아래의 명령어들로 k8s resource가 생성되었는지 확인합니다.

kubectl get-all -n amazon-cloudwatch
kubectl get ds,pod,cm,sa,amazoncloudwatchagent -n amazon-cloudwatch
kubectl describe clusterrole cloudwatch-agent-role amazon-cloudwatch-observability-manager-role    # 클러스터롤 확인
kubectl describe clusterrolebindings cloudwatch-agent-role-binding amazon-cloudwatch-observability-manager-rolebinding  # 클러스터롤 바인딩 확인
kubectl -n amazon-cloudwatch logs -l app.kubernetes.io/component=amazon-cloudwatch-agent -f # 파드 로그 확인
kubectl -n amazon-cloudwatch logs -l k8s-app=fluent-bit -f    # 파드 로그 확인

 
 

Fluent bit 설정 

해당 addon을 설치하면 fluent-bit도 동시에 설치가 됩니다. 하지만 어떠한 설정을 통해 log를 수집하는지 살펴보는 것이 필요합니다.

kubectl describe cm fluent-bit-config -n amazon-cloudwatch

 
위의 명령어를 통해 fluent-bit에 설정된 log 수집 설정 파일을 확인하실 수 있습니다.
설정에는 application-log.conf , dataplane-log.conf , fluent-bit.conf , host-log.conf , parsers.conf로 구성되어 있으며 각각 INPUT/FILTER/OUTPUT 필터가 적용되어 있습니다.
 
대표적으로 application-log.conf 를 보도록 하겠습니다.

 

INPUT
파일, 네트워크, 표준 I/O등 다양한 소스로부터 데이터를 수집하는 역할을 합니다. 
FILTER
수집된 데이터의 구조를 변경하거나, 특정 필드를 추가, 삭제하는 등 데이터를 변형하는 역할을 합니다.
OUTPUT
처리된 데이터를 파일 시스템, 데이터 베이스, 로그 시스템, 모니터링 시스템등 다양한 대상으로 전송하는 역할을 합니다. 

 

CloudWatch 확인 - log

AWS Managed Console에서 CloudWatch 메뉴에 접근하여 로그 그룹을 확인해보면 아래와 같이 4개의 로그 그룹이 생성되어 로그스트림이 수집되는 것을 확인하실 수 있습니다.

 

 

CloudWatch 확인 - Metric

아래와 같이 cloudwatch agent를 통해 수집된 metric 데이터는 인사이트 > container insights에서 확인하실 수 있습니다.

 
 
 
 
 
 


Reference

- https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/eks-observe.html
- https://docs.docker.com/config/containers/logging/