Amazon CloudWatch Logs에서 Amazon EKS 제어 영역 로그를 검색하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2021년 11월 12일

Amazon Elastic Kubernetes Service(Amazon EKS) 문제를 해결하고 있으며 EKS 제어 영역에서 실행되는 구성 요소에서 로그를 수집해야 합니다.

간략한 설명

Amazon CloudWatch Logs에서 로그를 보려면 Amazon EKS 제어 영역 로깅을 활성화해야 합니다. EKS 제어 영역 로그는/aws/eks/cluster-name/cluster 로그 그룹에서 찾을 수 있습니다. 자세한 내용은 클러스터 제어 영역 로그 보기를 참조하십시오.

참고: cluster name을 클러스터 이름으로 바꿉니다.

CloudWatch Logs 인사이트를 사용하여 EKS 제어 영역 로그 데이터를 검색할 수 있습니다. 자세한 내용은 CloudWatch 인사이트를 사용한 로그 데이터 분석을 참조하십시오.

중요: 클러스터에서 제어 영역 로깅을 활성화한 후에만 CloudWatch Logs에서 로그 이벤트를 볼 수 있습니다. CloudWatch Logs 인사이트에서 쿼리를 실행할 시간 범위를 선택하기 전에 제어 영역 로깅을 활성화했는지 확인하십시오.

해결 방법

CloudWatch 인사이트 검색

1.    CloudWatch Logs 인사이트 콘솔을 엽니다.

2.    로그 그룹 메뉴에서 쿼리할cluster log group(클러스터 로그 그룹)을 선택합니다.

3.    Run query(쿼리 실행)을 선택하여 결과를 봅니다.

참고: 결과를 .csv 파일로 내보내거나 결과를 클립보드에 복사하려면 Export results(결과 내보내기)를 선택합니다. 샘플 쿼리를 변경하여 특정 사용 사례에 대한 데이터를 가져올 수 있습니다. 일반적인 EKS 사용 사례는 다음 샘플 쿼리를 참조하십시오.

일반적인 EKS 사용 사례에 대한 샘플 쿼리

클러스터 생성자를 찾으려면 kubernetes-admin 사용자에게 매핑된 IAM 엔터티를 검색하십시오.

쿼리:

fields @logStream, @timestamp, @message
| sort @timestamp desc
| filter @logStream like /authenticator/
| filter @message like "username=kubernetes-admin"
| limit 50

예제 출력:

@logStream, @timestamp @message
authenticator-71976 ca11bea5d3083393f7d32dab75b,2021-08-11-10:09:49.020,"time=""2021-08-11T10:09:43Z"" level=info msg=""access granted"" arn=""arn:aws:iam::12345678910:user/awscli"" client=""127.0.0.1:51326"" groups=""[system:masters]"" method=POST path=/authenticate sts=sts.eu-west-1.amazonaws.com uid=""heptio-authenticator-aws:12345678910:ABCDEFGHIJKLMNOP"" username=kubernetes-admin"

앞의 출력에서, IAM 사용자 arn:aws:iam::12345678910:user/awscli는 사용자 kubernetes-admin에 매핑됩니다.

특정 사용자가 수행한 요청을 찾으려면, kubernetes-admin 사용자가 수행한 작업을 검색합니다.

예제 쿼리:

fields @logStream, @timestamp, @message
| filter @logStream like /^kube-apiserver-audit/
| filter strcontains(user.username,"kubernetes-admin")
| sort @timestamp desc
| limit 50

예제 출력:

@logStream,@timestamp,@message
kube-apiserver-audit-71976ca11bea5d3083393f7d32dab75b,2021-08-11 09:29:13.095,"{...""requestURI"":""/api/v1/namespaces/kube-system/endpoints?limit=500";","string""verb"":""list"",""user"":{""username"":""kubernetes-admin"",""uid"":""heptio-authenticator-aws:12345678910:ABCDEFGHIJKLMNOP"",""groups"":[""system:masters"",""system:authenticated""],""extra"":{""accessKeyId"":[""ABCDEFGHIJKLMNOP""],""arn"":[""arn:aws:iam::12345678910:user/awscli""],""canonicalArn"":[""arn:aws:iam::12345678910:user/awscli""],""sessionName"":[""""]}},""sourceIPs"":[""12.34.56.78""],""userAgent"":""kubectl/v1.22.0 (darwin/amd64) kubernetes/c2b5237"",""objectRef"":{""resource"":""endpoints"",""namespace"":""kube-system"",""apiVersion"":""v1""}...}"

특정 userAgent가 수행한 API 호출을 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, userAgent, verb, requestURI, @message
| filter @logStream like /kube-apiserver-audit/
| filter userAgent like /kubectl\/v1.22.0/
| sort @timestamp desc
| filter verb like /(get)/

단축된 예제 출력:

@logStream,@timestamp,userAgent,verb,requestURI,@message
kube-apiserver-audit-71976ca11bea5d3083393f7d32dab75b,2021-08-11 14:06:47.068,kubectl/v1.22.0 (darwin/amd64) kubernetes/c2b5237,get,/apis/metrics.k8s.io/v1beta1?timeout=32s,"{""kind"":""Event"",""apiVersion"":""audit.k8s.io/v1"",""level"":""Metadata"",""auditID"":""863d9353-61a2-4255-a243-afaeb9183524"",""stage"":""ResponseComplete"",""requestURI"":""/apis/metrics.k8s.io/v1beta1?timeout=32s"",""verb"":""get"",""user"":{""username"":""kubernetes-admin"",""uid"":""heptio-authenticator-aws:12345678910:AIDAUQGC5HFOHXON7M22F"",""groups"":[""system:masters"",""system:authenticated""],""extra"":{""accessKeyId"":[""ABCDEFGHIJKLMNOP""],""arn"":[""arn:aws:iam::12345678910:user/awscli""],""canonicalArn"":[""arn:aws:iam::12345678910:user/awscli""],""sourceIPs"":[""12.34.56.78""],""userAgent"":""kubectl/v1.22.0 (darwin/amd64) kubernetes/c2b5237""...}"

aws-auth ConfigMap에 대한 변이된 변경 사항을 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, @message
| filter @logStream like /^kube-apiserver-audit/
| filter requestURI like /\/api\/v1\/namespaces\/kube-system\/configmaps/
| filter objectRef.name = "aws-auth"
| filter verb like /(create|delete|patch)/
| sort @timestamp desc
| limit 50

단축된 예제 출력:

@logStream,@timestamp,@message
kube-apiserver-audit-f01c77ed8078a670a2eb63af6f127163,2021-10-27 05:43:01.850,{""kind"":""Event"",""apiVersion"":""audit.k8s.io/v1"",""level"":""RequestResponse"",""auditID"":""8f9a5a16-f115-4bb8-912f-ee2b1d737ff1"",""stage"":""ResponseComplete"",""requestURI"":""/api/v1/namespaces/kube-system/configmaps/aws-auth?timeout=19s"",""verb"":""patch"",""responseStatus"": {""metadata"": {},""code"": 200 },""requestObject"": {""data"": { contents of aws-auth ConfigMap } },""requestReceivedTimestamp"":""2021-10-27T05:43:01.033516Z"",""stageTimestamp"":""2021-10-27T05:43:01.042364Z"" }

거부된 요청을 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, @message
| filter @logStream like /^authenticator/
| filter @message like "denied"
| sort @timestamp desc
| limit 50

예제 출력:

@logStream,@timestamp,@message
authenticator-8c0c570ea5676c62c44d98da6189a02b,2021-08-08 20:04:46.282,"time=""2021-08-08T20:04:44Z"" level=warning msg=""access denied"" client=""127.0.0.1:52856"" error=""sts getCallerIdentity failed: error from AWS (expected 200, got 403)"" method=POST path=/authenticate"

포드가 스케줄링된 노드를 찾으려면 kube-scheduler 로그를 쿼리합니다.

예제 쿼리:

fields @logStream, @timestamp, @message
| sort @timestamp desc
| filter @logStream like /kube-scheduler/
| filter @message like "aws-6799fc88d8-jqc2r"
| limit 50

예제 출력:

@logStream,@timestamp,@message
kube-scheduler-bb3ea89d63fd2b9735ba06b144377db6,2021-08-15 12:19:43.000,"I0915 12:19:43.933124       1 scheduler.go:604] ""Successfully bound pod to node"" pod=""kube-system/aws-6799fc88d8-jqc2r"" node=""ip-192-168-66-187.eu-west-1.compute.internal"" evaluatedNodes=3 feasibleNodes=2"

앞의 예제 출력에서 포드 aws-6799fc88d8-jqc2r은 노드 ip-192-168-66-187.eu-west-1.compute.internal에서 스케줄링되었습니다.

Kubernetes API 서버 요청에 대한 HTTP 5xx 서버 오류를 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, responseStatus.code, @message
| filter @logStream like /^kube-apiserver-audit/
| filter responseStatus.code >= 500
| limit 50

단축된 예제 출력:

@logStream,@timestamp,responseStatus.code,@message
kube-apiserver-audit-4d5145b53c40d10c276ad08fa36d1f11,2021-08-04 07:22:06.518,503,"...""requestURI"":""/apis/metrics.k8s.io/v1beta1?timeout=32s"",""verb"":""get"",""user"":{""username"":""system:serviceaccount:kube-system:resourcequota-controller"",""uid"":""36d9c3dd-f1fd-4cae-9266-900d64d6a754"",""groups"":[""system:serviceaccounts"",""system:serviceaccounts:kube-system"",""system:authenticated""]},""sourceIPs"":[""12.34.56.78""],""userAgent"":""kube-controller-manager/v1.21.2 (linux/amd64) kubernetes/d2965f0/system:serviceaccount:kube-system:resourcequota-controller"",""responseStatus"":{""metadata"":{},""code"":503},..."}}"

CronJob 활성화 문제를 해결하려면 cronjob-controller가 수행한 API 호출을 검색하십시오.

예제 쿼리:

fields @logStream, @timestamp, @message
| filter @logStream like /kube-apiserver-audit/
| filter user.username like "system:serviceaccount:kube-system:cronjob-controller"
| display @logStream, @timestamp, @message, objectRef.namespace, objectRef.name
| sort @timestamp desc
| limit 50

단축된 예제 출력:

{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "objectRef": { "resource": "cronjobs", "namespace": "default", "name": "hello", "apiGroup": "batch", "apiVersion": "v1" }, "responseObject": { "kind": "CronJob", "apiVersion": "batch/v1", "spec": { "schedule": "*/1 * * * *" }, "status": { "lastScheduleTime": "2021-08-09T07:19:00Z" } } }

위의 예시 출력에서 default 네임스페이스의 hello 작업은 1분마다 실행되며 2021-08-09T07:19:00Z에 마지막으로 스케줄링되었습니다.

replicaset-controller가 수행한 API 호출을 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, @message
| filter @logStream like /kube-apiserver-audit/
| filter user.username like "system:serviceaccount:kube-system:replicaset-controller"
| display @logStream, @timestamp, requestURI, verb, user.username
| sort @timestamp desc
| limit 50

예제 출력:

@logStream,@timestamp,requestURI,verb,user.username
kube-apiserver-audit-8c0c570ea5676c62c44d98da6189a02b,2021-08-10 17:13:53.281,/api/v1/namespaces/kube-system/pods,create,system:serviceaccount:kube-system:replicaset-controller
kube-apiserver-audit-4d5145b53c40d10c276ad08fa36d1f11,2021-08-04 0718:44.561,/apis/apps/v1/namespaces/kube-system/replicasets/coredns-6496b6c8b9/status,update,system:serviceaccount:kube-system:replicaset-controller

Kubernete 리소스에 대해 수행되는 작업을 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, @message
| filter @logStream like /^kube-apiserver-audit/
| filter verb == "delete" and requestURI like "/api/v1/namespaces/default/pods/my-app"
| sort @timestamp desc
| limit 10

앞의 예제 쿼리는 포드 my-appdefault 네임스페이스를 바탕으로 delete API 호출을 필터링합니다.

단축된 예제 출력:

@logStream,@timestamp,@message
kube-apiserver-audit-e7b3cb08c0296daf439493a6fc9aff8c,2021-08-11 14:09:47.813,"...""requestURI"":""/api/v1/namespaces/default/pods/my-app"",""verb"":""delete"",""user"":{""username""""kubernetes-admin"",""uid"":""heptio-authenticator-aws:12345678910:ABCDEFGHIJKLMNOP"",""groups"":[""system:masters"",""system:authenticated""],""extra"":{""accessKeyId"":[""ABCDEFGHIJKLMNOP""],""arn"":[""arn:aws:iam::12345678910:user/awscli""],""canonicalArn"":[""arn:aws:iam::12345678910:user/awscli""],""sessionName"":[""""]}},""sourceIPs"":[""12.34.56.78""],""userAgent"":""kubectl/v1.22.0 (darwin/amd64) kubernetes/c2b5237"",""objectRef"":{""resource"":""pods"",""namespace"":""default"",""name"":""my-app"",""apiVersion"":""v1""},""responseStatus"":{""metadata"":{},""code"":200},""requestObject"":{""kind"":""DeleteOptions"",""apiVersion"":""v1"",""propagationPolicy"":""Background""},
..."

Kubernetes API 서버에 대해 수행한 호출과 관련된 HTTP 응답 코드 카운트를 검색하려면 다음 예제 쿼리를 사용할 수 있습니다.

fields @logStream, @timestamp, @message
| filter @logStream like /^kube-apiserver-audit/
| stats count(*) as count by responseStatus.code
| sort count desc

예제 출력:

responseStatus.code,count
200,35066
201,525
403,125
404,116
101,2

kube-system 네임스페이스에서 DaemonSets/Addons에 수행한 변경 사항을 찾으려면 다음 예제 쿼리를 사용할 수 있습니다.

filter @logStream like /^kube-apiserver-audit/
| fields @logStream, @timestamp, @message
| filter verb like /(create|update|delete)/ and strcontains(requestURI,"/apis/apps/v1/namespaces/kube-system/daemonsets")
| sort @timestamp desc
| limit 50

예제 출력:

{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "RequestResponse", "auditID": "93e24148-0aa6-4166-8086-a689b0031612", "stage": "ResponseComplete", "requestURI": "/apis/apps/v1/namespaces/kube-system/daemonsets/aws-node?fieldManager=kubectl-set", "verb": "patch", "user": { "username": "kubernetes-admin", "groups": [ "system:masters", "system:authenticated" ] }, "userAgent": "kubectl/v1.22.2 (darwin/amd64) kubernetes/8b5a191", "objectRef": { "resource": "daemonsets", "namespace": "kube-system", "name": "aws-node", "apiGroup": "apps", "apiVersion": "v1" }, "requestObject": { "REDACTED": "REDACTED" }, "requestReceivedTimestamp": "2021-08-09T08:07:21.868376Z", "stageTimestamp": "2021-08-09T08:07:21.883489Z", "annotations": { "authorization.k8s.io/decision": "allow", "authorization.k8s.io/reason": "" } }

앞의 예제 출력에서, kubernetes-admin 사용자는 kubectl v1.22.2를 사용하여 aws-node DaemonSet을 패치했습니다.


이 문서가 도움이 되었나요?


결제 또는 기술 지원이 필요하세요?