Gom3rye

AWS- 로그 관리와 운영 본문

현대 오토에버 클라우드 스쿨

AWS- 로그 관리와 운영

Gom3rye 2025. 8. 6. 18:31
728x90
반응형

로그 관리와 운영

로그 관리 프로그램

  • ELK Stack
    • Elastic Search: 데이터 저장 및 검색
    • Log Stash: 데이터 수집 및 변환
    • Kibana: 시각화

최근에는 Log Stash 대신에 Fluentd를 사용하기도 해서 EFK 하기도 한다.

Kibana 대신에 태블로 같은 프로그램을 이용해서 별도로 시각화하기도 한다.

  • EKS에서의 로그 관리와 운영
    • 수집: Fluentd 컨테이너를 데몬셋으로 동작시키고 파드의 로그를 CloudWatch Logs에 저장
    • 저장: CloudWatch의 Logs에 저장
    • 모니터링: 메트릭 디렉토리를 설정하고 CloudWatch 사용자 메트릭을 생성해서 그 메트릭의 경보를 생성
    • 시각화: CloudWatch의 Logs Insights를 사용하여 대상 로그를 분석하고 CloudWatch의 대시보드로 시각화
  • 애플리케이션 로그의 저장
    • 기존 서버에 애플리케이션을 배포하는 경우 애플리케이션이 출력하는 로그를 배포된 서버의 특징 디렉토리에 로그 파일로 출력해서 저장하도록 설정하느 ㄴ경우가 많다.
    • 쿠버네티스와 같은 컨테이너 방식으로 배포하는 경우는 여러 개의 레플리카를 가지고 있기 때문에 어떤 호스트에서 동작 중인지 알 수 없으며 재시작 등을 하게 되면 호스트가 변경될 가능성이 있기 때문에 기존 방법으로 로그를 저장하면 안된다.
    • 쿠버네티스에서는 애플리케이션 로그 출력을 표준 출력으로 구성하는 것을 권장한다.
    • 로그는 kubectl logs <파드이름>의 형태로 출력하던가 kubectl logs -l 레이블을 지정해서 특정 레이블에 있는 모든 파드의 로그를 확인하는 것이 가능하다.
  • 로그 수집
    • AWS에서는 애플리케이션이 출력하는 로그를 수집하는 구조로 CloudWatch Logs 라는 서비스를 제공하는데 EC2에 CloudWatch 에이전트를 설치하고 수집 대상 로그 파일을 설정하면 AWS 로그 저장 공간으로 전송이 가능하다.
    • 로그 수집하는 컨테이너를 데몬셋으로 동작시켜서 각각이 표준 출력한 로그를 확인하고 CloudWatch Logs로 수집 관리
    • 데이터 노드의 IAM에 CloudWatchAgentServerPolicy 정책을 연결
      • 데이터 노드 중 하나의 인스턴스를 선택
      • 상세보기 페이지에서 IAM 역할을 선택
      • 권한 탭에서 권한 추가를 눌러서 정책 연결을 선택하고 정책을 연결
    • 데몬셋을 위한 네임스페이스를 생성
      • 리소스 파일을 생성(cloudwatch-namespace.yaml)
      apiVersion: v1
      kind: Namespace
      metadata:
        name: amazon-cloudwatch
        labels:
          name: amazon-cloudwatch
          
      # 리소스 생성
      kubectl apply -f cloudwatch-namespace.yaml
      
    • fluentd 컨테이너를 데몬셋으로 동작
      • 클러스터 이름과 저장할 region을 설정할 configmap을 생성
      • kubectl create configmap cluster-info --from-literal=cluster.name=eks-work-cluster --from-literal=logs.region=ap-northeast-2 -n amazon-cloudwatch
    • github에서 fluentd 샘플 매니페스트를 다운로드 받아서 데몬셋으로 fluentd 컨테이너를 실행
    • CloudWatch Logs에 로그 그룹이 생성
      • /aws/containerinsights/eks-work-cluster/application
      • /aws/containerinsights/eks-work-cluster/host
      • /aws/containerinsights/eks-work-cluster/dataplane
    • 로그 저장
      • CloudWatch Logs에 전송된 로그는 기본적으로 기간 제한 없이 저장되며 저장되는 로그 용량에 따라 과금이 발생하므로 용도에 맞게 저장 기간을 설정해 사용하는 것이 일반적이다.
  • 로그 모니터링
    • CloudWatch 경보를 사용한 통지

AutoScaling

  • 시스템 부하 상황에 따라 자동으로 리소스를 유연하게 조장하는 것
  • 쿠버네티스에도 오토스케일링 기능이 존재한다.
  • Cluster AutoScaler를 이용한 데이터 플레인 오토스케일링
    • EC2의 오토스케일링과 유사한데 데이터 플레인 인스턴스 오토스케일링
    • Cluster AutoScaler를 이용한 발견적 AutoScaling
      • Cluster AutoScaler의 스케일링 트리거 기준은 파드에 설정된 리소스 요청에 따라 판단
      • 파드를 배포할 때 요청한 CPU 리소스와 메모리 크기에 여유가 없으면 그 파드는 pending 상태가 된다.
      • Cluster AutoScaler는 이 상황을 감지하고 요청된 파드가 동작할 수 있도록 노드를 추가한다.
      • 파드가 pending 상태 일 때 노드가 추가됩니다.
  • Cluster AutoScaler를 이용한 데이터 플레인 오토스케일링 설정
    • 인스턴스에 AutoScalingFullAccess 정책을 연결
    • 설정을 위해서 AutoScaling 그룹 이름 확인: eks-eks-work-nodegroup-8ecc3e3d-f332-14da-2a79-ce20ebf6e200
    • 리소스 생성
      • cluster-autoscaler.yaml 파일의 2:5 부분 뒤에 autoscaling 그룹 이름을 수정
    • 확인
      • kubectl logs -f deployment/cluster-autoscaler -n kube-system
    • 파드의 개수를 늘려서 확인
  • Cluster AutoScaler 사용 시 주의할 점
    • Cluster AutoScaler는 requets 값으로 스케일링을 판단

파드를 배치할 때만 스케일링 할 지 판단

파드가 배치가 되면 노드의 스케쥴링은 실행되지 않음

실제 부하가 적지만 파드의 requests 값이 큰 경우 파드가 스케쥴링 되지 않고 스케일링 되어 버리므로 주의

request 값은 낮지만 limits 설정이 없거나 limits 가 아주 높은 값으로 설정된 경우 requests 자체에는 리소스에 여유가 있는데 이 경우 배포가 되면 노드에 과부하가 걸리는 Over Commit 상태가 될 수 있음

  • AWS 오토스케일링을 이용한 예방적 오토스케일링
    • 이전에 했던 방식은 파드를 배포할 때 문제가 발생하면 오토스케일링을 수행
    • 어떤 임계값을 넘으면 노드를 추가하는 것이 운영 측면에서 효율적
    • 컨테이너를 사용하는 이유 중 하나가 빠른 배포인데 노드 추가를 기다려야 한다면 컨테이너의 장점을 제대로 활용하지 못하는 것
  • Horizontal Pod Autoscaler를 이용한 파드 오토스케일링
    • HPA는 노드와 마찬가지로 파드 리소스 사용률에 맞춰 파드의 스케일 아웃, 스케일 인 기능을 구현
    • 서비스의 문제 발생을 막는 차원에서 설정
    • 파드의 리소스 사용 현황을 모니터링하고 임곗값을 넘을 경우 스케일 아웃 수행
    • 메트릭 서버 배포
      • HPA로 파드 수를 조절하려면 클러스터 내부에서 파드 리소스 사용 현황을 파악해야 합니다.
      • 공식 문서를 제공: components.yaml
    • HPA를 위한 yaml 파일을 생성
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      name: backend-app
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: backend-app
      minReplicas: 2
      maxReplicas: 5
      targetCPUUtilizationPercentage: 50
    
    • backend-app 이라는 Deployment는 CPU 사용량이 50퍼센트가 넘으면 파드의 개수를 2-5개로 늘려주는 설정
    • 리소스 생성
    • 과부하 테스트는 busybox 이미지를 이용하면 편리(최소 버전의 리눅스)
      • kubectl run -i --tty load-generator --image=busybox --rm -- sh

무한 반복해서 파드에 트래픽을 요청: 서비스 디스커버리를 이용하면 클러스터 내부의 통신이므로 EKS에서 통신 비용을 지불하지 않지만 LoasBalancer의 DNS를 이용하면 외부 통신이 되서 비용이 청구됩니다.

while true; do wget -q -O- http://backend-app-service.eks-work.svc.cluster.local:80/health; done

노드의 개수를 늘리는 것

파드의 개수를 늘리는 것: hpa (대부분의 일반적인 서비스들은 파드의 개수를 늘리므로 hpa.yaml 파일을 작성하는 방법은 꼭 알아두기)

보안

클러스터 보안

  • 인증 (Authentication): 일종의 로그인
    • EKS에서는 IAM을 이용한 인증, 인가 기능을 제공한다.
    • AWS CLI를 이용한 인증
    • AWS CLI의 aws eks update-kubeconfig 클러스터이름 명령을 사용하면 kubectl을 자동으로 설정할 수 있다.
    • 토큰을 이용해서 자동으로 인증
  • 인가 (Authentication): 권한
    • kubectl로 접속한 요청이 정상적으로 인증된 후에는 요청한 조작이 허가를 받은 것인지 아닌지를 점검한다.
    • 쿠버네티스는 Role-Based Access Control(RBAC) 라는 기능을 이용해서 인가를 구현한다.
    • Role과 RoleBinding이라는 쿠버네티스 오브젝트를 사용하여 설정한다.
    • Role은 어떤 조작을 허용할 것인가 하는 권한의 집합 같은 것을 정의하고 RoleBinding은 어떤 사용자에게 어떤 롤을 부여할 것인지를 정의한다.
    • EKS는 aws-auth이라는 이름의 configmap 안에 AWS CLI 인증 정보로 설정한 IAM 사용자, IAM 역할의 Amazon 리소스 이름(ARN), 쿠버네티스 오브젝트로 그룹을 연결해놓고 롤바인딩으로 그 그룹과 롤을 연결시키는 것으로 구현한다.
  • 리소스 접속이 제한된 사용자를 생성
    • 권한에 관련된 yaml 파일을 작성한 후 리소스 생성
    apiVersion: v1
    kind: Namespace
    metadata:
      name: rbac-test-ns
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: rbac-test-role
    rules:
    - apiGroups: ["extensions", "apps", ""]
      resources: ["pods", "pods/log", "deployments", "replicasets", "services"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: rbac-test-role-binding
      namespace: rbac-test-ns
    roleRef:
      kind: ClusterRole
      name: rbac-test-role
      apiGroup: rbac.authorization.k8s.io
    subjects:
    - kind: Group
      name: rbac-test-group
      apiGroup: rbac.authorization.k8s.io
    
    • AWS의 IAM에서 사용자를 생성하고 ARN을 복사
      • rbacTest
      • arn:aws:iam::208060188195:user/rbacTest
      • accesskey: AKIATA4K2QYRTKHT6ISP
      • secretkey: ~~~~
    • 사용자에게 eksctl에서의 권한 연결: 설정 완료
      • eksctl create iamidentitymapping --region ap-northeast-2 --cluster eks-work-cluster --username rbacTest --group rbac-test-group --arn arn:aws:iam::208060188195:user/rbacTest
    • aws-configure 명령으로 새로 생성된 사용자로 aws-cli를 설정
    • kubectl config use-context eks-work 로 네임 스페이스 변경
    • kubectl get pods 명령으로 파드를 조회
      • rbacTest는 rbac-test-ns 네임스페이스에 대한 권한만을 부여했기 때문에 접근 불가
      • Error from server (Forbidden): pods is forbidden: User "rbacTest" cannot list resource "pods" in API group "" in the namespace "eks-work" 라는 메시지를 출력
    • eks가 아니라면 eksctl create iamidentitymapping --region ap-northeast-2 --cluster eks-work-cluster --username rbacTest --group rbac-test-group --arn arn:aws:iam::208060188195:user/rbacTest
      • 명령은 수행할 필요가 없음

노드 보안

파드에 부여되는 호스트 권한 제어

  • 쿠버네티스 클러스터에서는 데이터 플레인 노드 위에서 파드가 동작하고 실행된다.
  • 클러스터를 관리하면서 어떤 파드든 무조건 생성되야 하는 건 아니다.
  • 보안이 고려되지 않은 클러스터에서는 어떤 행동이든 가능하다.
  • 쿠버네티스에서는 파드에 부여할 권한을 관리하는 Pod Security Policy 라는 기능을 소유하고 있다.
  • EKS에서도 1.19 버전에서 부터 지원
  • 확인: kubectl get psp
    • kubernetes 1.25 버전에서 제거됨
    • 1.25 이상에서 kubectl label namespace 네임스페이스이름 보안레벨설정

파드 보안

  • 컨테이너 라이프사이클에 맞춘 보안 대책의 필요성
    • 파드는 컨테이너
    • 컨테이너 자체에 필요한 보안은 쿠버네티스의 것이 아님
    • 필요에 따라 자체적으로 마련
    • 컨테이너 이미지 취약성
      • 컨테이너는 애플리케이션 실행에 필요한 각종 미들웨어나 프레임워크를 설치한 상태에서 이미지를 만들어두고 필요할 때 동작시킵니다.
      • 도커 파일을 작성하여 명확하게 관리한다 하더라도 컨테이너 내부의 소프트웨어 버전 등을 의식하면 관리하기는 어려움
      • 애플리케이션 배포 파이프라인에 포함시켜 컨테이너 이미지를 생성할 때 자동으로 확인하게 해서 취약한 컨테이너가 배포되는 것을 방지
      • 이미지를 만들기 전에 정적 코드 분석 등을 파이프라인에 포함시킴
    • 동작 감시(런타임 보호)
      • 컨테이너가 동작 중인 경우 동작 감시로 실제 컨테이너에 문제되는 동작이 있는지 확인
      • 사용하지 않는 bash 명령이나 이미 아는 피싱 사이트 등에 많은 트래픽이 발생하는지 등을 감시하고 있다가 의심스러운 동작이 발생할 경우 관리자에게 통지하는 방식을 사용
      • 슬랙같은 툴을 이용해서 메시지를 전송한다.
    • 자체적으로 구현하기는 난이도가 높아서 솔루션을 사용하는 것이 일반적
      • 컨테이너 이미지 스캔용으로는 trivy 나 microscanner 등을 이용
      • 동작 감시는 falco 등을 활용
      • sysdig 난 aqua 같은 소프트웨어를 이용

네트워크 보안

  • EndPoint IP 주소 제한
    • 기본적으로 EKS 클러스터 EndPoint는 인터넷에 공개됨
      • IAM 인증으로 로그인을 하기 때문에 EndPoint가 공개되도 크게 문제가 되지는 않음
    • EKS에서는 EndPoint의 IP 주소 제한 기능이 있으며 AWS 관리 콘솔에서 설정 가능
  • kubectl 명령을 VPC 내부로 제한하는 Private EndPoint도 제공
  • 네트워크 정책을 사용한 클러스터 내부 통신 제어
    • 여러 서비스가 있을 때 특정 서비스는 다른 특정 서비스에 요청을 할 수 없도록 설정하는 것이 가능
    • EKS에서 사용을 할 때는 Calico 라는 쿠버네티스 네트워크 정책 엔진을 설치해야 합니다.
    https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/calico.html
    • 모든 통신 차단하는 정책 (network-policy-all-deny.yaml)
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny
    spec:
      podSelector:
        matchLabels: {}
    
    • 서비스B에서 http 요청만 허가하는 정책: Service A에 적용(network-policy-http-from-serviceB2ServiceA.yaml)
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: network-policy-for-servicea
    spec:
      podSelector:
        matchLabels:
          app: ServiceA
      policyTypes:
      - Ingress
      Ingress:
      - from:
        - podSelector:
          matchLabels:
            app: ServiceB
        ports:
        - protocol: TCP
          port: 80
    

Manifest 관리 와 지속적 통합/지속적 전달

GitOps 와 GitOps를 구현하기 위한 도구 등장

  • 모든 설정을 코드로 관리할 수 있다면 애플리케이션 과 마찬가지고 배포도 지속적 통합 과 지속적 전달이 가능
  • 이러한 생각은 위브웍스 사가 GitOps 라는 프로세스를 만든 것 부터 시작
    • 쿠버네티스의 매니페스트도 리포지토리로 관리하고 pull 요청 기반의 운영으로 배포하는 것
    • 리포지토리의 매니페스트 파일 이 외에는 업데이트 인정하지 않는 구조를 도입함으로써 클러스터 관리를 통제
      • Application 개발자 -> git push -> git code(개발) -> CI(build/test/push) -> 컨테이너 레지스트리 -> Config Update(Manifest) -> Git Code(운영) -> Deploy Operator -> Kubernetes Cluster
      • 운영을 위한 Git Code를 운영 담당자가 직접 push 할 수 있습니다.
    • GitOps 라는 개념이 만들어지면서 쿠버네티스에 설정 정보 적용을 자동화해주는 도구가 등장
      • Weave Cloud: GitOps 라는 개념을 도입한 위브웍스에서 제공하는 CD 서비스
      • Spinnaker: 넷플릭스가 만든 CD 서비스
      • Scafold: 구글이 개발한 CD 도구
      • Argo CD
      • Concurce CI

AWS 의 CodePipeline을 이용해서 GitOps 구현 가능

  • CodePipeline은 AWS에서 제공하는 CICD 서비스
  • 기본 개념
    • 개발자가 git push를 수행하면 Code Commit 이 변경을 감지하고 파이프라인 동작시키고 Code Build 가 빌드를 수행하고 ECR에 이미지를 Push하고 Docker Build가 이미지 push가 완료되면 EKS에게 docker pull을 수행해서 파드를 다시 생성하도록 합니다.

kustomize

  • 쿠버네티스 매니페스트는 선언적 상태를 정의하기 때문에 동적으로 값을 변경하는 문법이 존재하지 않음
  • kustomize는 kubectl의 서브 명령어인데 처음에는 독립적으로 존재했는데 1.14 버전 이후에 서브 명령어로 추가됨
  • kubectl kustomize 명령을 사용하면 여러 개의 매니페스트나 환경에 의존적인 설정 값을 함께 합쳐서 매니페스트 하나로 만들어 줍니다.
  • 변경 내용이 있는지 확인하고자 하는 경우 kubectl kustomize 디렉토리이름

AWS의 기타 서비스

람다

=>서버리스 서비스

=>요청을 할 때 마다 코드를 실행시켜서 작업을 수행

=>요청마다 비용을 지불(서버 유지 비용이 없음)

=>트리거를 연결해서 특정 이벤트가 발생했을 때 함수를 실행시키고 그 결과를 다른 곳에 전송하거나 메시지로 보낼 수 있습니다.

AI

=>SageMaker: 머신 러닝 모델, 머신러닝 모델에 대한 인프라 설정 과 프로비저닝을 하지 않아도 됨

=>bedlock: 완전 관리형 생성형 AI 플랫폼

728x90
반응형