티스토리 뷰

728x90
반응형

서론

Amazon CloudWatch는 마이크로서비스를 지원하는 Telemetry 서비스이다.

Telemetry 서비스는 애플리케이션을 모니터링하고, 시스템 전반의 성능 변경 사항에 대응하며, 리소스 사용률을 최적화할 수 있도록 Insight를 제공한다. 또한 로그, 메트릭, 이벤트 형태로 모니터링 및 운영 데이터를 수집하여 클라우드와 온프레미스 서버에서 실행되는 모든 리소스와 애플리케이션 및 서비스에 대한 통합 대시보드를 제공해주는 것이 주 역할이다.

AWS를 운영하는 운영자는 CloudWatch를 통해 서비스 이상 동작을 빠르게 감지하고, 경보를 설정하며, 로그와 지표를 시각화하며, 자동화된 작업을 수행하고, 문제를 해결하며, 통찰력을 확보하여 애플리케이션을 원활하게 실행하고 운영할 수 있다.


Amazon CloudWatch 구성

1) IAM 구성

2) CloudWatch Agent 설정

3) CloudWatch Agent 배포

4) CloudWatch EKS 모니터링

5) CloudWatch API GATEWAY 로그 기록


IAM 구성

1) EKS IAM 구성

EKS 모니터링을 위한 IAM을 다음과 같이 추가한다.

IAM > Role > EKS WORKER NODE ROLE (EKS-WORKERNODE-ROLE)

위와 같이 EKS WORKER NODE ROLE에 CloudWatchAgentServerPolicy를 추가한다.


CloudWatch Agent 설정

다음으로 CloudWatch Agent를 설정한다.

1) Namespace 생성

apiVersion: v1
kind: Namespace
metadata:
  name: amazon-cloudwatch
  labels:
    name: amazon-cloudwatch

다음과 같이 github를 통해 직접 배포하거나, 위와 같이 yaml 파일을 생성하여 배포할 수 있다.

[root@ip-192-168-114-198 ingress_test]# kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cloudwatch-namespace.yaml
namespace/amazon-cloudwatch created
[root@ip-192-168-114-198 ingress_test]#

2) ServiceAccount 생성

apiVersion: v1
kind: ServiceAccount
metadata:
  name: cloudwatch-agent
  namespace: amazon-cloudwatch

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: cloudwatch-agent-role
rules:
  - apiGroups: [""]
    resources: ["pods", "nodes", "endpoints"]
    verbs: ["list", "watch"]
  - apiGroups: ["apps"]
    resources: ["replicasets"]
    verbs: ["list", "watch"]
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["list", "watch"]
  - apiGroups: [""]
    resources: ["nodes/proxy"]
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["nodes/stats", "configmaps", "events"]
    verbs: ["create"]
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["cwagent-clusterleader"]
    verbs: ["get","update"]

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: cloudwatch-agent-role-binding
subjects:
  - kind: ServiceAccount
    name: cloudwatch-agent
    namespace: amazon-cloudwatch
roleRef:
  kind: ClusterRole
  name: cloudwatch-agent-role
  apiGroup: rbac.authorization.k8s.io

다음과 같이 github를 통해 직접 배포하거나, 위와 같이 yaml 파일을 생성하여 배포할 수 있다.

[root@ip-192-168-114-198 ingress_test]# kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cwagent/cwagent-serviceaccount.yaml
serviceaccount/cloudwatch-agent created
clusterrole.rbac.authorization.k8s.io/cloudwatch-agent-role created
clusterrolebinding.rbac.authorization.k8s.io/cloudwatch-agent-role-binding created
[root@ip-192-168-114-198 ingress_test]#

3) ConfigMap

ConfigMap은 다음을 통해 다운로드 후 아래와 같이 수정 후 반영한다.

[root@ip-192-168-114-198 cloudwatch]# curl -O https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cwagent/cwagent-configmap.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   521  100   521    0     0   1273      0 --:--:-- --:--:-- --:--:--  1270
[root@ip-192-168-114-198 cloudwatch]# 

수정 사항은 다음과 같다.

apiVersion: v1
data:
  # Configuration is in Json format. No matter what configure change you make,
  # please keep the Json blob valid.
  cwagentconfig.json: |
    {
      "logs": {
        "metrics_collected": {
          "kubernetes": {
            "cluster_name": "{{cluster_name}}",
            "metrics_collection_interval": 60
          }
        },
        "force_flush_interval": 5
      }
    }
kind: ConfigMap
metadata:
  name: cwagentconfig
  namespace: amazon-cloudwatch

- logs.metrics_collected.kubernetes.cluster_name : 생성한 EKS CLUSTER NAME으로 변경

- logs.metrics_collected.kubernetes.metrics_collection_interval : CloudWatch에서 수집한 Metics 수집 주기 (최소 15초)

[root@ip-192-168-114-198 cloudwatch]# kubectl apply -f cwagent-configmap.yaml
configmap/cwagentconfig created
[root@ip-192-168-114-198 cloudwatch]#

위와 같이 namespace, serviceaccount, configmap이 구성이 완료되면 이제 CloudWatch를 배포할 준비가 완료된 것이다.


CloudWatch Agent 배포

CloudWatch Agent는 각 WorkNode에 DaemonSet으로 배치된다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: cloudwatch-agent
  namespace: amazon-cloudwatch
spec:
  selector:
    matchLabels:
      name: cloudwatch-agent
  template:
    metadata:
      labels:
        name: cloudwatch-agent
    spec:
      containers:
        - name: cloudwatch-agent
          image: amazon/cloudwatch-agent:1.247346.0b249609
          #ports:
          #  - containerPort: 8125
          #    hostPort: 8125
          #    protocol: UDP
          resources:
            limits:
              cpu:  200m
              memory: 200Mi
            requests:
              cpu: 200m
              memory: 200Mi
          # Please don't change below envs
          env:
            - name: HOST_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: HOST_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: K8S_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: CI_VERSION
              value: "k8s/1.2.3"
          # Please don't change the mountPath
          volumeMounts:
            - name: cwagentconfig
              mountPath: /etc/cwagentconfig
            - name: rootfs
              mountPath: /rootfs
              readOnly: true
            - name: dockersock
              mountPath: /var/run/docker.sock
              readOnly: true
            - name: varlibdocker
              mountPath: /var/lib/docker
              readOnly: true
            - name: sys
              mountPath: /sys
              readOnly: true
            - name: devdisk
              mountPath: /dev/disk
              readOnly: true
      volumes:
        - name: cwagentconfig
          configMap:
            name: cwagentconfig
        - name: rootfs
          hostPath:
            path: /
        - name: dockersock
          hostPath:
            path: /var/run/docker.sock
        - name: varlibdocker
          hostPath:
            path: /var/lib/docker
        - name: sys
          hostPath:
            path: /sys
        - name: devdisk
          hostPath:
            path: /dev/disk/
      terminationGracePeriodSeconds: 60
      serviceAccountName: cloudwatch-agent

다음과 같이 github를 통해 직접 배포하거나, 위와 같이 yaml 파일을 생성하여 배포할 수 있다.

[root@ip-192-168-114-198 cloudwatch]# kubectl apply -f cwagent-daemonset.yaml
daemonset.apps/cloudwatch-agent created
[root@ip-192-168-114-198 cloudwatch]# 

정상적으로 배포되었는지 확인한다.

[root@ip-192-168-114-198 cloudwatch]# kubectl get daemonset -n amazon-cloudwatch
NAME               DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
cloudwatch-agent   2         2         2       2            2           <none>          103s
[root@ip-192-168-114-198 cloudwatch]# kubectl get pods -n amazon-cloudwatch
NAME                     READY   STATUS    RESTARTS   AGE
cloudwatch-agent-h54pj   1/1     Running   0          110s
cloudwatch-agent-pvzvh   1/1     Running   0          110s
[root@ip-192-168-114-198 cloudwatch]#

위와 같이 배포가 완료되면 EKS Worker Node는 Metrics를 CloudWatch로 전송한다.


CloudWatch EKS 모니터링

이제 CloudWatch 대시보드에 접속하여 각종 지표를 확인해 보도록 하자.

1) Resources

(CloudWatch > Container Insights > Resources)

Resources TAB에서는 각종 EKS 리소스가 표출된다.

NRSON-EKS-CLUSTER(EKS Cluster)는 물론 EKS를 구성하는 Object들이 리소스로 등록되어 있다.

Metrics는 앞서 CloudWatch에 구성한 ConfigMap에 설정한 Collection 주기에 따라 수집한다.

Resources 탭의 상단에는 리소스탭에 표출될 데이터의 기간을 설정할 수 있으며, 그 오른쪽에는 맵 보기와 목록 보기가 있다. 현재 상단에 보이는 화면이 목록 보기이며, 맵 보기를 누르면 다음과 같이 화면이 전환된다.

CLUSTER, NAMESPACE, SERVICE, POD 순으로 구조화된 맵을 볼 수 있다. 해당 맵의 특정 리소스를 선택하여도 모니터링 화면을 볼 수 있다.

2) 경보 생성

또한 경보 생성 상태를 확인할 수 있다. 경보는 시스템의 장애를 사전에 방지하기 위해 AWS SNS를 통해 알람을 보내 주는 서비스이다.

경보 생성 방법은 다음과 같다.

(CloudWatch > 경보 > 경보 생성)

먼저 지표및 조건을 지정한다. 위와 같이 다양한 조건을 정의할 수 있으며, 우리는 Worker Node가 사용하는 Memory 사용량을 기준으로 알람을 생성해 보도록 한다.

위와 같이 통계 주기와 임계치를 선택한 후 다음을 클릭한다.

작업 구성에서는 알림을 전송할 SNS 구성과 Auto Scaling 작업 구성 그리고 EC2 작업을 선택할 수 있으며, 우리는 SNS를 통래 알림을 전송하는 방법을 구성한다.

경보 생성이 완료되면 다음으로 SNS를 확인하고 Topic 확인을 진행해야 한다.

먼저 SNS 화면을 확인해 보자.

위와 같이 Amazon SNS의 Topic(주제)을 구독하고 있는 nara0617@gmail.com 사용자가 확인 대기 중인 상태이다.

구독하고 있는 메일에 로그인하여 메일을 확인해 보자.

You have chosen to subscribe to the topic:
arn:aws:sns:ap-northeast-2:xxxxxxx:NODE_MEMORY_CloudWatch_Alarms_Topic


To confirm this subscription, click or visit the link below (If this was in error no action is necessary):
Confirm subscription

Please do not reply directly to this email. If you wish to remove yourself from receiving all future SNS subscription confirmation requests please send an email to sns-opt-out

Confirm subscription을 선택하면 이제 해당 Topic을 구독하는 Subscriber가 된다.

완료되면 다시한번 SNS 주제를 확인해 보자.

위와 같이 확인됨 상태로 변경된 것을 확인할 수 있다.

경보가 생성되었으면, 이제 경보 조건에 따라 경보가 발생하는지 확인해 보도록 하자.

위와 같이 경보 메시지가 발생한 것을 CloudWatch 경보 화면에서 확인할 수 있다.

이는 앞선 리소스 화면과 연계되어 리소스 별 경보 발생 현황을 함께 확인할 수 있다.

위와 같이 경보가 NRON-EKS-CLUSTER 내에서 발생하였다고 알람이 표시되며, 하단의 경보 이름을 선택하면, 아래와 같이 경보가 발생한 이유를 확인할 수 있는 상세 정보 화면으로 전환된다.

임계치와 리소스의 사용량을 적절히 조합하여 운영 상황에서는 모니터링과 경보 알림을 함께 사용하는 것을 권고한다.

3) Performance monitoring

(CloudWatch > Container Insights > Performance monitoring)

Performance monitoring을 선택하면 상세 성능 모니터링 화면으로 이동할 수 있다.

위와 같이 각종 리소스를 선택하여 모니터링할 수 있으며, 아래와 같이 CPU, MEMORY, NETWORK, CLUSTER FAILED, DISK, NODE COUNT를 모니터링한다.


CloudWatch API Gateway 로그 기록

1) API Gateway IAM 추가

API Gateway를 모니터링하기 위해 다음과 같이 IAM > Role을 추가한다.

API Gateway를 추가하면 자동으로 추가되는 정책인 AmazonAPIGatewayPushToCloudWatchLogs를 포함하는 APIGATEWAY-CLOUDWATCH ROLE을 생성한다. 생성된 ROLE의 ARN을 복사한다.

2) API Gateway 구성 변경

생성한 ROLE을 API Gateway에 적용한다.

(API GATEWAY > API > NRSON-API-SERVICE > 설정 > CloudWatch 로그 역할 ARN)

앞서 복사한 ARN을 넣은 후 저장을 클릭한다.

다음으로 스테이지에서 상세히 로그 설정을 구성한다.

위와 같이 로그 수준은 INFO, CloudWatch 로그 활성화, 전체/요청 응답 데이터 로깅, CloudWatch 세부 지표 활성화를 선택하여 active 상태로 변경한 후 변경 사항을 저장한다.

3) CloudWatch 확인

(CloudWatch > 로그 > 로그 그룹)

로그 그룹을 확인해 보면 아래와 같이 Api-Gateway-Execution-Logs-~~/api 로그 그룹이 생성된 것을 확인할 수 있다. 선택하면 아래와 같이 상세 정보를 확인할 수 있다. 또한 하단의 로그 스트림을 통해 로그를 확인할 수 있다.


결론

물론  위에 예로 들은 EKS와 API Gateway 이외에도 우리는 CloudWatch를 통해 다양한 지표를 모니터링할 수 있다.

Cloud Dashboard 생성 기능을 통해 나만의 커스터마이징된 대시보드를 생성하여 다양한 지표와 로그를 모니터링할 수 있다.

지표로는 1200개가 넘는 지표를 그래프 등으로 표출할 수 있으며, 수집되는 로그 그룹을 통해 대시보드에서 함께 모니터링할 수 있게 지원한다.

마이크로서비스 아키텍처를 설계할 때 필수적인 시스템과 서브시스템으로 구분하여 컴포넌트를 설계하고 배치하게 된다. 이중 Telemetry 서비스를 Eco System으로 분류하는 경우가 종종 있다.

이는 잘못된 사고이다. Telemetry는 마이크로서비스의 복잡한 호출 흐름과 장애 추적을 위해 반드시 구성되어야 하는 필수 컴포넌트임을 명심해야 한다. CloudWatch는 Telemetry 서비스 3가지 구성 요소(모니터링, 로깅, 추적) 중 모니터링과 로깅을 함께 지원하는 AWS Managed Service이다. 이를 적절히 활용하여 오픈소스와의 연계 또는 또다른 AWS Managed Service를 적용하여 완벽한 Telemetry 서비스가 될 수 있도록 조합해 나가야 할 것이다.

728x90
반응형