Gom3rye
AWS- 로그 관리와 운영 본문
로그 관리와 운영
로그 관리 프로그램
- 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 관리 콘솔에서 설정 가능
- 기본적으로 EKS 클러스터 EndPoint는 인터넷에 공개됨
- kubectl 명령을 VPC 내부로 제한하는 Private EndPoint도 제공
- 네트워크 정책을 사용한 클러스터 내부 통신 제어
- 여러 서비스가 있을 때 특정 서비스는 다른 특정 서비스에 요청을 할 수 없도록 설정하는 것이 가능
- EKS에서 사용을 할 때는 Calico 라는 쿠버네티스 네트워크 정책 엔진을 설치해야 합니다.
- 모든 통신 차단하는 정책 (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 플랫폼
'현대 오토에버 클라우드 스쿨' 카테고리의 다른 글
| 작심 큰일 챌린지 - 초콜릿 괴도 코코 (Sweet) (파이썬) (3) | 2025.08.07 |
|---|---|
| 작심 큰일 챌린지 - 컵라면 (파이썬) (3) | 2025.08.06 |
| 작심 큰일 챌린지 - 냅색 문제 (파이썬) (3) | 2025.08.05 |
| AWS- EKS 이어서 (1) | 2025.08.05 |
| 리눅스 마스터 2급 1차 시험 족보 (5) | 2025.08.05 |