기본 세팅은 마치고 Observability 관련하여 시작할 것이다.

EKS에서 로깅은 애플리케이션과 Node도 있지만 각종 컴포넌트가 있는 Control Plane 로깅도 필요하다.

이 글에서는 Control Plane 로깅, 컨테이너 로깅, Fluent Bit 구성에 대한 내용을 말할 것이다.

Control Plane 로깅

Untitled

eks 클러스터에 들어가서 관찰성 탭을 보면 control plane 로깅이 다 꺼져있다.

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

이 명령어로 모든 로깅을 다 켰다. 그럼 클러스터 업데이트 중이라고 뜨고 잠시 후에 모든 로깅이 켜진다.

Untitled 1

Cloud Watch에 들어가면 /aws/eks/myeks/cluster 라는 로그 그룹이 생성되고 아래와 같은 로그 스트림도 생성된다.

Untitled 2

Amazon EKS 컨트롤 플레인 로깅 - Amazon EKS

Untitled 3

각 스트림에 들어가서 error 를 필터링해서 로그를 확인할 수도 있다!

awscli로도 확인할 수 있는데 로그가 너무 길어 불편했다. grep으로 필터링하면 좀 낫긴한거 같기도 하다…

Untitled 4

Logs Insights에서 쿼리를 실행하여 내가 원하는 값을 추출해 낼 수도 있다.

예를 들어 authenticator로 시작하는 로그스트림을 뽑아냈다.

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

Untitled 5

또는 error 레벨에 해당되는 로그만 뽑아내 볼 수 있다.

fields @timestamp, @message
| filter @logStream ~= "authenticator"
| filter @message like /level=error/ 
| sort @timestamp desc

Untitled 6

이건 사용해 보면서 쿼리를 좀 알아야 잘 사용할 수 있을 것 같다.

마무리로 control plane 로깅은 비활성화하고 로그 그룹도 삭제한다.

eksctl utils **update-cluster-logging** --cluster $CLUSTER_NAME --region $AWS_DEFAULT_REGION **--disable-types all** --approve
aws logs **delete-log-group** --log-group-name /aws/eks/$CLUSTER_NAME/cluster

컨테이너 로깅

컨테이너를 로깅하기 위해 nginx를 설치하였다.

(지금 클러스터에 external dns랑 alb controller를 설치해 놔서 자동으로 ALB와 Route53에 생성된다.)

Untitled 7

Untitled 8

컨테이너 로그는 표준 출력 STDOUT과 표준 에러 STDERR로 보내는 것을 권고한다.

그래서 kubectl logs 명령어를 입력하여 표준 입력 STDIN 으로 보내면 즉각적으로 로그를 볼 수 있다.

View container logs

logs 옵션에는 여러 가지가 있는데 나는 아래 세 가지가 가장 유용하다고 생각한다.

-f는 로그를 실시간으로 볼 수 있게 해 준다. tail은 지정한 라인 수만큼 보여주고 since는 최근 시간을 보여 준다.

Untitled 9

kubectl logs를 사용하면 아래와 같이 터미널에 출력된다.

Untitled 10

직접 컨테이너에 들어 가서 확인하면 각각 STDOUT과 STDERR의 파일 위치도 확인 가능하다. 이 도커이미지는 심볼릭 링크를 걸어놨다..!

Untitled 11

파드가 종료되고 나면 더 이상의 로그는 확인할 수 없다. 그래서 로그를 보존하기 위해 pvc를 붙여서 따로 저장해 둘 수 있다. 또는 로깅 아키텍처를 고려해야 한다.

로깅 아키텍처

Untitled 12

기본적으로 컨테이너가 재시작하는 경우, kubelet은 종료된 컨테이너 하나를 로그와 함께 유지한다. 그러나 파드가 노드에서 축출되면 로그도 같이 축출된다.

사용자가 kubectl logs를 실행하면 → kubelet이 해당 요청을 받고 → 로그 파일에서 직접 읽는다 → kubelet이 로그 내용을 사용자에게 반환한다

이 때 kubelet 설정 파일에서 kubelet 파라미터인 containerLogMaxSize와 containerLogMaxFiles의 기본 값인 10Mi와 5개까지 반환할 수 있다. 각 노드에서 journalctl -u kubelet로 확인 가능하다

Untitled 13

kubelet은 항상 컨테이너 런타임으로 하여금 /var/log/pods 아래에 로그를 기록하도록 지시한다.

Untitled 14

[ec2-user@ip-192-168-3-228 default_nginx-6c65c594db-9rp89_c57dbf7f-a360-46d8-b9d3-2b4942d561ec]$ ls
nginx  preserve-logs-symlinks

ns_nginx파드_블라블라 디렉토리로 들어가면 nginxpreserve-logs-symlinks 디렉토리가 있다. preserve-logs-symlinkskubectl logs -p 했을 때 보여지는 로그 파일이다. (이전 인스턴스에 대한 로그를 검색할 수 있어서 트러블슈팅에 유용하다)

Untitled 15

nginx 디렉토리로 들어가면 현재 찍히는 로그 파일을 확인할 수 있다.

Fluent Bit 데몬셋 구성

또는 로그 에이전트를 데몬셋 형식 또는 애플리케이션의 사이드카 형식으로 구현해서 로그를 수집할 수 있다

여기서는 fluent bit을 데몬셋으로 구성하여 각 애플리케이션에 대한 logging을 수집하고 cloudwatch에 전달할 것이다.

우선 네임스페이스 먼저 생성한다

kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cloudwatch-namespace.yaml

그 다음은 cm을 생성할 건데 ClusterName과 RegionName은 각 사용자에 맞게 정의한다.

ClusterName=myeks
RegionName=ap-northeast-2
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
kubectl create configmap fluent-bit-cluster-info \
--from-literal=cluster.name=${ClusterName} \
--from-literal=http.server=${FluentBitHttpServer} \
--from-literal=http.port=${FluentBitHttpPort} \
--from-literal=read.head=${FluentBitReadFromHead} \
--from-literal=read.tail=${FluentBitReadFromTail} \
--from-literal=logs.region=${RegionName} -n amazon-cloudwatch

생성하고 나서 확인해 보면 위에서 넣어준 값이 잘 들어가 있는 것을 확인할 수 있다.

Untitled 16

  • fluent-bit-cluster-info

    Untitled 17

  • fluent-bit-config 라는 컨피그맵은 각 노드에서 어떤 로그(INPUT_Path)를 어느 로그 그룹(OUTPUT_log_group_name)에 보낼건지 정의되어 있다.

    1. /aws/containerinsights/Cluster_Name/application : /var/log/containers/*.log, /var/log/containers/fluent-bit*, /var/log/containers/cloudwatch-agent*
    2. /aws/containerinsights/Cluster_Name/host : /var/log/dmesg, /var/log/messages, /var/log/secure
    3. /aws/containerinsights/Cluster_Name/dataplane : /var/log/journal, /var/log/containers/aws-node*, /var/log/containers/kube-proxy*

    Untitled 18

    Untitled 19

이제 Fluent Bit 데몬셋을 생성한다.

kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/fluent-bit/fluent-bit.yaml

Untitled 20

이제 fluent bit 구성은 끝났다.

aws cloudwatch로 넘어가 로그 그룹을 확인해 보면 아래와 같이 생성된 것을 볼 수 있다.

Untitled 21

애플리케이션에 대한 로그를 보기 위해 /aws/containerinsights/myeks/application 에 들어가서 해당하는 로그스트림을 눌러 보면 로그 확인이 가능하다.

Untitled 22

Fluent Bit를 DaemonSet로 설정하여 CloudWatch Logs에 로그 전송 - Amazon CloudWatch

Categories:

Updated:

Leave a comment