BLOG
중앙 집중식 로깅은 Kubernetes 클러스터를 대규모로 실행 및 관리하는 도구 구성 요소입니다. 개발자는 애플리케이션 디버깅 및 모니터링을 위해 로그에 액세스해야 하고, 운영팀은 애플리케이션 모니터링을 위해 액세스해야 하며, 보안을 위해서는 모니터링에 액세스해야 합니다. 이 팀들 모두 로그 처리 및 저장에 대한 요구 사항이 다릅니다. 오늘 블로그 게시물에서는 Amazon CloudWatch와 결합한 AWS용 Fluent Bit를 사용하여 로그를 중앙 집중화하는 솔루션을 보여드리겠습니다.
AWS용 Fluent Bit는 Fluent Bit를 기반으로 하는 컨테이너이며 다양한 출력 대상에 대한 로그 필터, 파서 및 라우터로 설계되었습니다. Fluent Bit용 AWS는 Amazon CloudWatch, Amazon Kinesis Data Firehose 및 Amazon Kinesis Data Streams와 같은 AWS 서비스에 대한 지원을 추가합니다.
솔루션을 살펴보기 전에 Fluent Bit가 로그를 처리하여 출력 대상으로 보내는 방법을 살펴보겠습니다. 로그는 먼저 입력을 통해 수집됩니다. Kubernetes의 입력은 Docker가 해당 호스트의 컨테이너 stdout 및 stderr에서 생성한 컨테이너 로그 파일입니다. 이 입력은 Docker 로그 형식을 처리하고 로그 항목에서 시간이 올바르게 설정되었는지 확인합니다.
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
DB /var/log/flb_kube.db
Parser docker
Docker_Mode On
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
다음으로 Fluent Bit 필터 세트로 로그를 필터링합니다. 이 솔루션은 Kubernetes 필터를 활용하여 로그 저장소 솔루션에서 쉽게 쿼리할 수 있도록 포드 레이블 및 주석으로 로그 항목을 보강합니다.
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc.cluster.local:443
Merge_Log On
Merge_Log_Key data
K8S-Logging.Parser On
K8S-Logging.Exclude On
기본적으로 Kubernetes 필터는 로그 데이터가 JSON 형식인 것으로 가정하고 해당 데이터를 구문 분석하려고 시도합니다. 예를 들어, 로그 항목이 JSON에서 문자열로 직렬화된 경우 로그 항목에서 구조화된 데이터를 사용할 수 있어야 합니다. 예를 들어 다음과 같은 로그 항목이 있는 경우 백엔드 시스템에서 구조화된 데이터를 사용할 수 있습니다. 플러그인은 또한 애플리케이션의 원래 항목을 유지합니다.
입력:
“{ \”message\”: \”A new user signed up!\”, \”service\”: \”user-service\”, \”metadata\”: { \”source\”: \”mobile\” } }”
산출:
{
“data”: {
“message”: “A new user signed up!”,
“service”: “user-service”,
“metadata”: {
“source”: “mobile”
}
},
“log”: “{ \”message\”: \”A new user signed up!\”, \”service\”: \”user-service\”, \”metadata\”: { \”source\”: \“mobile\” } }”
}
파서는 NGINX 또는 Apache와 같은 사용자 정의 파서를 사용하도록 사용자 정의할 수 있습니다. Kubernetes Pod에 주석을 추가하면 기본 JSON 파서를 재정의할 수 있습니다. 이제 다양한 로그 형식을 문자열 형식에서 구조화된 형식으로 구문 분석하고 역 직렬화 할 수 있습니다.
annotations:
fluentbit.io/parser: nginx
Kubernetes Filter는 Kubernetes 메타 데이터로 데이터를 보강합니다. Kubernetes API Server를 호출하고 해당 포드에 대한 정보를 쿼리합니다. Kubernetes라는 로그 항목에 추가 키가 추가됩니다.
kubernetes: {
annotations: {
“kubernetes.io/psp”: “eks.privileged”
},
container_hash: “<some hash>”,
container_name: “myapp”,
docker_id: “<some id>”,
host: “ip-10-1-128-166.us-east-2.compute.internal”,
labels: {
app: “myapp”,
“pod-template-hash”: “<some hash>”
},
namespace_name: “default”,
pod_id: “198f7dd2-2270-11ea-be47-0a5d932f5920”,
pod_name: “myapp-5468c5d4d7-n2swr”
}
이제 메타 데이터로 로그를 구문 분석하고 강화한 결과를 출력 대상으로 보냅니다. 다른 사용 사례에 대해 여러 개의 출력이 나오는 것이 일반적입니다. 예를 들어 개발자가 로그에 액세스하고 장기 저장을 위해 S3로 내보낼 수 있도록 모든 로그를 Amazon CloudWatch로 전송하려고 할 수 있습니다. 일부 개발팀들은 ELK(Elasticsearch, Logstash, Kibana) 스택을 사용할 수 있습니다. ELK의 경우 Kinesis Data Firehose 플러그인을 활용하여 Amazon Elasticsearch 및 S3에 로그를 스트리밍 할 수 있습니다. 이 툴 세트는 일반적으로 개발자가 S3를 통해 장기 감사 요구 사항을 유지하면서 디버깅을 위해 실시간 스트림 로그를 작성하는 데 사용됩니다. 로그를 여러 출력으로 나누는 방법에 대한 자세한 내용은 Fluent Bit 스트림에 대한 블로그 게시물을 참고해 주시기 바랍니다. 본 예제는 단순하게 유지하고 Amazon CloudWatch Logs만 사용하겠습니다.
먼저 CloudWatch Logs의 출력을 구성해야 합니다. Fluent Bit를 구성하여 로그를 특정 로그 그룹으로 보내고 해당 그룹이 없는 경우 해당 그룹을 만듭니다.
[OUTPUT]
Name cloudwatch
Match **
region us-east-2
log_group_name fluentbit-cloudwatch
log_stream_prefix fluentbit-
auto_create_group true
Fluent Bit 구성이 완료되었으므로 클러스터 및 DaemonSet을 배포해야 합니다. 먼저 eksctl을 사용하여 서비스 계정에 대한 IAM 역할이 활성화된 새 클러스터를 생성합니다. 이 작업을 수행하는 방법에 대한 자세한 내용은 eksctl 설명서를 참조하십시오. 클러스터를 설정할 때 적절한 “ALB Ingress Controller” 권한이 있는 “kube-system”네임 스페이스에 “alb-ingress-controller”라는 서비스 계정이 있고 “fluentbit-system”네임 스페이스에 “fluentbit”가 있는지 확인하십시오. Amazon CloudWatch Logs에 쓸 수 있는 권한이 있습니다. 이제 FluentBit 서비스 계정이 있는 EKS 클러스터가 생겼습니다.
helm repo add incubator http://storage.googleapis.com/kubernetes–charts–incubator
helm upgrade –i aws–alb incubator/aws–alb–ingress–controller \
—namespace kube–system \
—set clusterName=fluentbit–demo–cluster \
—set awsRegion=us–east–2 \
—set awsVpcID=<vpc id of cluster> \
—set image.tag=v1.1.5 \
—set rbac.create=true \
—set rbac.serviceAccountName=alb–ingress–controller
클러스터가 프로비저닝되면 DaemonSet을 배포합니다. 먼저 Fluent Bit 에이전트를 배포하는 데 사용되는 ClusterRole, ClusterRoleBinding, ConfigMap 및 DaemonSet을 정의하는 fluentbit.yml 파일을 만듭니다.
—
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: fluentbit
rules:
– apiGroups: [“”]
resources:
– namespaces
– pods
verbs: [“get”, “list”, “watch”]
—
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: fluentbit
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: fluentbit
subjects:
– kind: ServiceAccount
name: fluentbit
namespace: fluentbit–system
—
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentbit–config
namespace: fluentbit–system
labels:
app.kubernetes.io/name: fluentbit
data:
fluent-bit.conf: |
[SERVICE]
Parsers_File /fluent-bit/parsers/parsers.conf
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
DB /var/log/flb_kube.db
Parser docker
Docker_Mode On
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc.cluster.local:443
Merge_Log On
Merge_Log_Key data
K8S–Logging.Parser On
K8S–Logging.Exclude On
[OUTPUT]
Name cloudwatch
Match **
region us–east–2
log_group_name fluentbit–cloudwatch
log_stream_prefix fluentbit–
auto_create_group true
—
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentbit
namespace: fluentbit–system
labels:
app.kubernetes.io/name: fluentbit
spec:
selector:
matchLabels:
name: fluentbit
template:
metadata:
labels:
name: fluentbit
spec:
serviceAccountName: fluentbit
containers:
– name: aws–for–fluent–bit
imagePullPolicy: Always
image: amazon/aws–for–fluent–bit:latest
volumeMounts:
– name: varlog
mountPath: /var/log
– name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
– name: fluentbit–config
mountPath: /fluent–bit/etc/
resources:
limits:
memory: 500Mi
requests:
cpu: 500m
memory: 100Mi
volumes:
– name: varlog
hostPath:
path: /var/log
– name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
– name: fluentbit–config
configMap:
name: fluentbit–config
배포가 완료되면 CoreDNS 및 AWS Node 컨테이너와 같은 시스템 컨테이너에 대해 Amazon CloudWatch Log Group으로 로그가 스트리밍 되는 것을 볼 수 있습니다. 이것이 애플리케이션에 어떻게 사용될 수 있는지 보여주기 위해 NGINX 컨테이너를 배포하고 커스텀 Fluent Bit 파서를 지정합니다. 아래는 데모 애플리케이션에 사용되는 demo.yml 파일입니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
annotations:
fluentbit.io/parser: nginx
spec:
containers:
– name: nginx
image: nginx:1.17–alpine
ports:
– containerPort: 80
—
apiVersion: v1
kind: Service
metadata:
name: nginx–service
spec:
type: NodePort
selector:
app: nginx
ports:
– protocol: TCP
port: 80
targetPort: 80
—
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx–ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet–facing
spec:
rules:
– http:
paths:
– path: /*
backend:
serviceName: nginx–service
servicePort: 80
클러스터에 배포되면 ALB가 구성될 때까지 기다립니다. 다음 명령을 실행하여 ALB 엔드 포인트를 얻을 수 있습니다.
❯ kubectl get ingress/nginx–ingress
NAME HOSTS ADDRESS PORTS AGE
nginx–ingress * 3d6aa6b1–default–nginxingr–29e9–1180704856.us–east–2.elb.amazonaws.com 80 3h3m
그런 다음 hey 와 같은 HTTP 요청을 시뮬레이션하여 애플리케이션의 로드를 시뮬레이션하고 로그를 생성하세요.
hey –n 30 –c 1 http://3d6aa6b1–default–nginxingr–29e9–1180704856.us–east–2.elb.amazonaws.com/
이제 로그에 다음과 유사한 항목이 표시됩니다.
{
“data”:{
“agent”:“hey/0.0.1”,
“code”:“200”,
“host”:“-“,
“method”:“GET”,
“path”:“/”,
“referer”:“-“,
“remote”:“10.1.128.166”,
“size”:“612”,
“user”:“-“
},
“kubernetes”:{
“annotations”:{
“fluentbit.io/parser”:“nginx”,
“kubernetes.io/psp”:“eks.privileged”
},
“container_hash”:“0e61b143db3110f3b8ae29a67f107d5536b71a7c1f10afb14d4228711fc65a13”,
“container_name”:“nginx”,
“docker_id”:“b90a89309ac90fff2972822c66f11736933000c5aa6376dff0c11a441fa427ee”,
“host”:“ip-10-1-128-166.us-east-2.compute.internal”,
“labels”:{
“app”:“nginx”,
“pod-template-hash”:“5468c5d4d7”
},
“namespace_name”:“default”,
“pod_id”:“198f7dd2-2270-11ea-be47-0a5d932f5920”,
“pod_name”:“nginx-5468c5d4d7-n2swr”
},
“log”:“10.1.128.166 – – [19/Dec/2019:17:41:12 +0000] \”GET / HTTP/1.1\” 200 612 \”-\” \”hey/0.0.1\” \”52.95.4.2\”\n”,
“stream”:“stdout”,
“time”:“2019-12-19T17:41:12.70630778Z”
}
AWS용 Fluent Bit DaemonSet은 이제 애플리케이션에서 로그를 스트리밍하여 Kubernetes 메타 데이터를 추가하고 로그를 구문 분석한 다음 모니터링 및 경고를 위해 Amazon CloudWatch로 보냅니다.
참고: AWS Fargate에서 컨테이너를 실행하는 경우 Fargate는 데몬 셋을 지원하지 않으므로 포드마다 별도의 사이드카 컨테이너를 실행해야 합니다.
결론적으로, 이 아키텍처는 모니터링 및 분석할 수 있는 구조화된 방식으로 Amazon CloudWatch, Amazon Kinesis Data Firehose, Amazon Kinesis Data Streams 및 기타 여러 백엔드로 로그를 스트리밍하도록 구성할 수 있습니다. 이를 통해 관리자는 조직 내 필요한 그룹에 액세스 할 수 있습니다.
원문 URL: https://aws.amazon.com/ko/blogs/containers/kubernetes-logging-powered-by-aws-for-fluent-bit/
** 메가존 클라우드 TechBlog는 AWS BLOG 영문 게재 글 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 개제하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달드리도록 하겠습니다.