본문 바로가기

DevOps

kube-audit-rest로 EKS Control plane 로깅 비용 절감하기

반응형

1. 개요

https://sendbird.com/blog/aws-eks-migration-optimizations

7 AWS EKS Optimizations When Migrating From EC2-ASG

Learn how Sendbird migrated from EC2-based Auto Scaling Groups to Amazon EKS and implemented 7 key optimizations.

sendbird.com

 
sendbird 블로그 글을 보고 힌트를 얻어 작업하게 되었습니다.
 
https://github.com/RichardoC/kube-audit-rest

GitHub - RichardoC/kube-audit-rest: Kubernetes audit logging, when you don't control the control plane

Kubernetes audit logging, when you don't control the control plane - RichardoC/kube-audit-rest

github.com

 
- EKS에서는 Control palne 로깅을 활성화할 수 있다. 필자의 회사 경우 월 400만원 가량의 EKS Control Plane 로깅 비용이 발생하고 있었다.
- 근데 사실 Audit log를 자주 들여다보지도 않는다.
- 그리고 Cloudwatch logs가 굉장히 불편하다.
- 따라서 이를 비용도 줄이면서 사용성도 높이는 방법을 고민하고 있던 와중 Sendbird에서 kube-audit-rest 라는 것을 통해 해결했다고 하여서, 적용했습니다.
 
 

2. 구성 방법에 대하여

원리 및 적용하는 방법을 알아보자.
 
ValidatingWebhookConfiguration을 통해 Kubernetes API 서버가 모든 생성(Create) 또는 변경(mutate/modify) 요청을 감지하여 Webhook(kube-audit-rest)으로 전송하도록 구성한다.
 
Kube audit rest pod는 Webhook을 통해 요청이 들어오면 각 요청을 JSON 형식으로 디스크에 한 줄씩 기록한다.
 
이를 Log 수집 데몬(여기서는 Vector.deev를 사용한다. 물론 다른 것 써도 된다)이 Sidecar 컨테이너로 떠서 File log를 수집하고 적절한 Destination으로 전송한다. (필자의 경우 Grafana Loki를 활용했다.)
 

2.1. Certificate, Issuer, ValidatingWebhookConfiguration

 
Webhook 서버를 Kubernetes에서 운영할 때는 보안상 HTTPS 통신을 사용해야 하며, Kubernetes API 서버가 webhook 서버의 TLS 인증서를 검증할 수 있어야 한다.

이를 위해 cert-manager와 함께 아래의 리소스를 활용하여, 자동으로 신뢰할 수 있는 인증서(Certificate)를 생성하고, 이를 Webhook에 자동으로 연결(CA 삽입)하는 설정이 필요하다.
 
Issuer : 인증서를 서명할 주체

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: kube-audit-rest-selfsigned
spec:
  selfSigned: {}

 
- Issuer는 cert-manager가 TLS 인증서를 생성할 때 사용할 서명자(issuer)임
- 여기서는 외부 CA가 아니라 self-signed 방식을 사용하고 있어, 내부용 Webhook 서버에서 활용하게 된다.
- 이 Issuer는 Certificate 객체에서 참조된다.
 
 
Certificate – TLS 인증서 생성 정의

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: kube-audit-rest-certificate
spec:
  secretName: kube-audit-rest-secret
  dnsNames:
    - kube-audit-rest.kube-audit-rest.svc
    - kube-audit-rest.kube-audit-rest.svc.cluster.local
  issuerRef:
    name: kube-audit-rest-selfsigned
    kind: Issuer

 
- 실제로 TLS 인증서 + 개인키를 발급해주는 객체
- 발급된 인증서는 secretName에 명시된 Secret (kube-audit-rest-secret)에 저장된다.
- webhook 서버에 접근할 때 사용하는 주소 (kube-audit-rest.kube-audit-rest.svc 등)를 명시해야 인증서 검증이 통과되기 때문에 명시해준다.
 
 
ValidatingWebhookConfiguration – 요청 가로채는 Webhook 정의
 

kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
metadata:
  name: kube-audit-rest
  labels:
    app: kube-audit-rest
  annotations:
    cert-manager.io/inject-ca-from: kube-audit-rest/kube-audit-rest-certificate
webhooks:
  - name: kube-audit-rest.kube-audit-rest.svc.cluster.local
    failurePolicy: Ignore
    timeoutSeconds: 5 # default : 10초
    sideEffects: None
    # Exclude 네임스페이스 명시
    namespaceSelector:
      matchExpressions:
        - key: kubernetes.io/metadata.name
          operator: NotIn
          values: ["argocd", "istio-system", ...]
    # kube-audit-rest 서비스의 주소를 명시해줍니다.
    clientConfig:
      service:
        name: kube-audit-rest
        namespace: kube-audit-rest
        path: "/log-request"
    # 모니터링할 API 목록을 명시해줍니다.
    rules:
      - operations: [ "CREATE", "UPDATE", "DELETE" ]
        apiGroups: ["*"]
        apiVersions: ["*"]
        resources: ["*/*"]
        scope: "*"
      - operations: [ "CONNECT" ]
        apiGroups: ["*"]
        apiVersions: ["*"]
        resources: ["pods/exec", "pods/portforward", "pods/proxy", "pods/attach"]
        scope: "*"
    admissionReviewVersions: ["v1"]

 
- annotation : cert-manager에게 Webhook에 필요한 CA 인증서를 자동으로 삽입하라고 지시하는 부분
- Certificate로 발급된 인증서의 루트 CA(self-signed)를 이 Webhook 설정에 자동으로 포함시키게 된다.
- Kubernetes API 서버는 이 CA를 통해 webhook 서버의 TLS 인증서를 검증하게 된다.
- namespaceSelector, rules는 본인 환경에 맞게 적절하게 설정하면 된다.
 
 
 

2.2. Vector

Deployment 라던가 Service 등의 설정은 다루지 않겠다.
 
Vector 설정에 대해 간단히 설명해보겠다.
 
Vector.dev는 로그 수집 데몬으로 Sidecar container로 붙어서 특정 파일 로그를 읽고 이를 처리한 다음에 적절한 목적지로 전송하는 역할을 수행한다.
 
당연히 kube-audit-rest Deployment 내 Sidecar container로 Vector를 붙여야 하고 적절한 vector config가 적용된 ConfigMap 혹은 volume을 마운트해줘야 할 것이다.
 
 
audit log를 /tmp 경로로부터 읽어야 할 것이기 때문에 source 설정을 해야 한다.

sources:
  audit-files:
    type: file
    include:
      - /tmp/*

 
 
그리고 필자의 경우 transforms 단계에서 REDACTED 설정과 불필요한 필드는 모두 drop 하는 설정을 진행했다.
 
그리고 유용한 필드들을 미리 Loki label로 인덱싱할 수 있도록 하는 설정도 진행했다.
 
[1] REDACT : vector remap transform을 활용했다.
https://vector.dev/docs/reference/vrl/

Vector Remap Language (VRL)

A domain-specific language for modifying your observability data

vector.dev

 
 
[2] drop : filter transform을 활용하여 drop 했다.
https://vector.dev/docs/reference/configuration/transforms/filter/

Filter transform

Filter events based on a set of conditions

vector.dev

 
 
(참고 : ValidatingWebhooks 에서는 Namespace 단위로 Exclude 하여 애초에 보내지 않도록 하였고, Vector에서는 ValidatingWebhook에서 필터링할 수 없는 것들에 대해 좀 더 상세하게 Drop 하였다.)
 
 
[3] error handling : Loki label로 활용할 field 들이 혹시나 없을 경우 unknown으로 미리 채워넣는다.
if 조건절 활용
 
[4] Loki로 전송
그 이후에는 Loki sink를 활용하여 보내게 된다.
https://vector.dev/docs/reference/configuration/sinks/loki/
 


 
여기까지 kube-audit-rest를 활용하여 eks control plane 비용을 절감하는 방법에 대해 알아보았다.
 
ValidatingWebhook에 대한 이해, Cert-manager를 통해 Certificate를 발급받는 것에 대한 이해, Vector 혹은 fluentBit을 통해 Log를 처리하는 방법에 대한 이해만 있다면 손쉽게 적용할 수 있을 것이다.
 
사용 후기
 
- 적용 방법이 간단하다.
- EKS 컨트롤 플레인으로 발생되는 비용을 거의 90% 가량 절감할 수 있다. 멀티 클러스터 환경일 경우 그 효과가 더욱 나타난다.
- Grafana Loki를 활용하기 때문에 Cloudwatch logs보다 오히려 더 활용도가 높아진다.

반응형