Development/Python

How to automatically stop Aurora MySQL RDS Clusters

gepp 2023. 2. 16. 17:58

 

아래 가이드대로 설정해도 aurora mysql RDS 이용시 제대로 작동하지 않아, 

( RDS를 7일 이상 Stop 할때 가이드: https://aws.amazon.com/premiumsupport/knowledge-center/rds-stop-seven-days/?nc1=h_ls )

RDS 옵션 확인시 인스턴스는 stop옵션이 존재하지 않고 클러스터에 있는 것을 확인하여 - 해당 샘플 코드에서

인스턴스를 클러스터로 할 수 있도록 변경하였다.

참고 문서는 아래 API 문서를 참고하였고 실제 api 호출시 나오는 로그의 항목 필드를 확인해서 필터링할 수 있는지 봐서

코드를 변경하였다.

Python boto3 API 문서: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances

RDS는 7일마다 자동시작되므로 cron(00 00 ? * 5 *) Event 트리거를 추가하였고, 시간과 분은 직접 stop한 시각으로부터 +RDS 시작에 걸리는 시간(분) 뒤로 적절히 정하였다.

 

아래 에러코드 발생시에는 DB 인스턴스에 추가한 태그 (여기서는 autostop=yes) 를 삭제하고, 

DB 클러스터를 선택하여 RDS 클러스터 태그로 추가한다.

Cannot stop instance blahblah.
An error occurred (InvalidParameterCombination) when calling the StopDBInstance operation: aurora-mysql DB instances are not eligible for stopping and starting.
Cannot stop instance portal-rds-1.

 

아래는 변경된 코드이며 클러스터를 중단한다. 

성공시 아래 로그가 발생한다.

 

  • Log
Stopping cluster: my-cluster-name
  • code in Python
import boto3
rds = boto3.client('rds')

def lambda_handler(event, context):

    #Stop DB clusters
    dbi = rds.describe_db_instances()
    print (dbi)
    dbs = rds.describe_db_clusters()
    print (dbs)
    
    for db in dbs['DBClusters']:
        #Check if DB instance is not already stopped
        if (db['Status'] == 'available'):
            try:
                GetTags=rds.list_tags_for_resource(ResourceName=db['DBClusterArn'])['TagList']
                for tags in GetTags:
                #if tag "autostop=yes" is set for cluster, stop it
                    if(tags['Key'] == 'autostop' and tags['Value'] == 'yes'):
                        result = rds.stop_db_cluster(DBClusterIdentifier=db['DBClusterIdentifier'])
                        print ("Stopping cluster: {0}.".format(db['DBClusterIdentifier']))
            except Exception as e:
                print ("Cannot stop rds {0}.".format(db['DBClusterIdentifier']))
                print(e)
                
if __name__ == "__main__":
    lambda_handler(None, None)