Real time – aws aurora status monitoring

오늘은 Aurora DB 서버의 메타 정보를 실시간으로 모니터링 할 수 있는 작은 프로그램을 하나 공유해보고자 한다. 예전에 만들어둔 베타 버전이 있었는데, 코드를 조금 다듬어서 새롭게 만들었다. 사실 Aurora의 메타 정보를 실시간으로 볼 일이 그렇게 많지는 않지만, Aurora 버전 업그레이드를 한다던가, 스펙을 변경한다던가, 파라미터를 변경한다던가 할 때 Real time으로 확인이 필요한 경우도 있다.

그래서 가끔씩 찾아오는 작업에 용이하게 사용하자 라는 취지로 개발한 프로그램이다.

https://github.com/godtechwak/auroraStatusChecker.git

How to Use

사용 방법은 다음과 같다.

(1) 리포지토리 복제

$ git clone https://github.com/godtechwak/auroraStatusChecker.git

(2) 모듈 초기화 및 빌드

$ cd auroraStatusChecker
$ git mod init aurora_status_check
$ git mod tidy
$ go build ./main.go

(3) 프로그램 실행 및 DB (클러스터|인스턴스) 목록 다운로드

$ ./main 2000
================================
Aurora Version & Parameter Check
================================
Region(kr/jp/ca/uk):
kr
WorkType(cluster/instance):
cluster
Do you want to create the list file? (yes/no):
yes
List saved to file: ./db_cluster_list_kr.txt

(4) 프로그램 재실행

$ ./main 2000
================================
Aurora Version & Parameter Check
================================
Region(kr/jp/ca/uk):
kr
WorkType(cluster/instance):
cluster
Do you want to create the list file? (yes/no):
no

(5) Aurora 메타 정보 실시간 모니터링

────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ──────────────────────────────────
                             Time│                          Duration│                      Cluster Name│                           Version│                            Status│                      Param Status│
────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ──────────────────────────────────
                     16:42:41.851│                             4.50s│                prod-silver-karrot│           8.0.mysql_aurora.3.04.1│                         available│                           in-sync│
                     16:42:41.853│                             4.50s│                  prod-silver-gold│           8.0.mysql_aurora.3.04.0│                         available│                           in-sync│
                     16:42:41.855│                             4.51s│               prod-silver-message│           8.0.mysql_aurora.3.04.0│                         available│                    pending-reboot│
                     16:42:41.852│                             4.50s│               prod-silver-account│           8.0.mysql_aurora.3.04.0│                         available│                           in-sync│
                     16:42:41.854│                             4.50s│                 prod-silver-admin│           8.0.mysql_aurora.3.04.1│                         available│                           in-sync│
                     16:42:41.855│                             4.51s│              prod-silver-analysis│           8.0.mysql_aurora.3.04.0│                         available│                    pending-reboot│
                     16:42:41.855│                             4.51s│                  prod-silver-auth│           8.0.mysql_aurora.3.04.0│                         available│                           in-sync│
────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ────────────────────────────────── ──────────────────────────────────

4번까지 진행하면 화면이 클리어되면서 Aurora 메타 정보를 실시간으로 모니터링 할 수 있다. 그리고 출력된 내용은 클러스터와 인스턴스 파일에 각각 로깅된다.

프로그램을 수행할 때 2000이라는 숫자를 인자로 넘기는 이유는 api 호출 횟 수에 스로틀링이 발생하기 때문이다. 그래서 수행 간의 최소 1초라는 간격을 강제하였다.

How to Modify

기본 출력되는 메타 정보 이외에 사용자가 추가적으로 모니터링 했으면 하는 메타 정보가 있을 것이다. 이 경우에는 rds_util 디렉터리의 cluster.go 또는 instance.go 파일에서 Describe()GetHeaders() 함수를 수정해주면 된다.

(1) cluster.go 에서 DB 클러스터의 Cluster Parameter Group 메타 정보를 추가로 조회하려는 경우

func (c Cluster) Describe(svc *rds.RDS, name string) ([]string, error) {
	input := &rds.DescribeDBClustersInput{
		DBClusterIdentifier: aws.String(name),
	}

	result, err := svc.DescribeDBClusters(input)
	if err != nil {
		return nil, err
	}

	clusterInfo := result.DBClusters[0]
	clusterParam := result.DBClusters[0].DBClusterMembers[0]

	values := []*string{
		clusterInfo.DBClusterIdentifier,
		clusterInfo.EngineVersion,
		clusterInfo.Status,
		clusterParam.DBClusterParameterGroupStatus,
		clusterInfo.DBClusterParameterGroup, // 추가된 부분	
        }

	var resultValues []string
	for _, value := range values {
		if value != nil {
			resultValues = append(resultValues, *value)
		} else {
			resultValues = append(resultValues, "")
		}
	}

	return resultValues, nil
}

func (c Cluster) GetHeaders() []string {
	return []string{"Time", "Duration", "Cluster Name", "Version", "Status", "Param Status", "Cluster Parameter Group"}
}

(... 생략) ────────────────────────────────── ──────────────────────────────────
(... 생략)                      Param Status│           Cluster Parameter Group│
(... 생략) ────────────────────────────────── ──────────────────────────────────
(... 생략)                           in-sync│   prod-silver-karrot-cluster-my80│
(... 생략)                           in-sync│     prod-silver-gold-cluster-my80│
(... 생략)                    pending-reboot│  prod-silver-message-cluster-my80│
(... 생략)                           in-sync│  prod-silver-account-cluster-my80│
(... 생략)                           in-sync│    prod-silver-admin-cluster-my80│
(... 생략) ────────────────────────────────── ──────────────────────────────────

(2) instance.go 에서 DB 인스턴스의 Class 메타 정보를 조회하려는 경우

func (i Instance) Describe(svc *rds.RDS, name string) ([]string, error) {
	input := &rds.DescribeDBInstancesInput{
		DBInstanceIdentifier: aws.String(name),
	}

	result, err := svc.DescribeDBInstances(input)
	if err != nil {
		return nil, err
	}

	instanceInfo := result.DBInstances[0]
	instanceParam := result.DBInstances[0].DBParameterGroups[0]

	values := []*string{
		instanceInfo.DBInstanceIdentifier,
		instanceInfo.EngineVersion,
		instanceInfo.DBInstanceStatus,
		instanceParam.ParameterApplyStatus,
		instanceInfo.DBInstanceClass, // 추가된 부분
	}

	var resultValues []string
	for _, value := range values {
		if value != nil {
			resultValues = append(resultValues, *value)
		} else {
			resultValues = append(resultValues, "")
		}
	}

	return resultValues, nil
}

func (i Instance) GetHeaders() []string {
	return []string{"Time", "Duration", "Instance Name", "Version", "Status", "Param Status", "DB Instance Class"}
}
(생략 ...) ────────────────────────────────── ──────────────────────────────────
(생략 ...)                      Param Status│                 DB Instance Class│
(생략 ...) ────────────────────────────────── ──────────────────────────────────
(생략 ...)                           in-sync│                     db.t4g.medium│
(생략 ...)                           in-sync│                     db.t4g.medium│
(생략 ...)                    pending-reboot│                    db.r6g.2xlarge│
(생략 ...)                           in-sync│                    db.r6g.2xlarge│
(생략 ...) ────────────────────────────────── ──────────────────────────────────

만드는 내내 ROI가 안나오는 작업이라고 생각했는데 만들어놓으니 나름 편하다는 생각이 들기도 한다. 누구라도 가볍게 사용해보면 좋을 것 같다.

댓글 남기기