AWS 서비스중 chatops라는 유용한 서비스가 있습니다.
비용이 무료 라는 큰 장점을 가지며, Slack 등 메신저와 통합되어 작동하면서 AWS 리소스들을 편리하게 관리할 수 있는 서비스입니다.
해당 서비스를 이용하여 AWS EKS 서비스 배포를 자동화하는 문서 입니다.
저는 해당 서비스를 사용해서 EKS를 배포하는것 이외에 특정 Iam 계정의 Access Key를 active 혹은 deactive 하는 작업을 자동화시켜서 사용중입니다.
해당 서비스와 Lambda , SNS 등을 잘 조합해서 사용한다면 Slack이나 Teams와 같은 메신저 채팅으로 간단하게 AWS 환경을 모니터링, 문제 해결, 작동할 수 있습니다.
EKS 배포 CloudFormation Template이 필요합니다.
AWS 서비스중 사용할 대상 서비스는 다음과 같습니다.
1. IAM
2. Secret Manager
3. Lambda
4. chatops
작업의 순서는 다음과 같습니다
0. aws chatops와 Slack 연동
1. IAM 작업
- Lambda Policy, Role 생성
2. secret manager 생성
3. Lambda Function 생성
먼저 Slack 메세지를 받을 AWS ChatOps 서비스를 생성합니다.
웹에 접속한뒤 새 클라이언트 구성 버튼을 클릭합니다.
클라이언트 종류로는 Amazon Chime, Teams, Slack이 있는데 해당 문서에서는 Slack으로 진행합니다.
Slack에 로그인되어 있다면, WoakrSpace 엑세스 권한 요청 페이지로 리다이렉트됩니다.
이때 허용을 클릭하면 됩니다.
이후 새 채널 구성 버튼을 클릭합니다.
구성 이름을 선택한 후, AWS에게 보내는 명령어가 민감정보를 포함할 수 있기 때문에 프라이빗을 선택합니다.
채널 ID는 Slack에서 chatOps에게 명령어를 보낼 채널을 우클릭 -> 채널 세부정보 보기 -> 최 하단 채널 ID : ..... 의 채널 ID를 복사해서 붙여넣기 합니다.
ChatOps가 가질 권한을 부여합니다.
ChatOps에게 Lambda를 트리거할 권한만 부여하면 되기 때문에, AWSLambda_FullAccess 정책을 가진 Role을 생성합니다.
신뢰 관계는 다음과 같습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "chatbot.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
권한 부여 이후 채널을 생성합니다.
민감정보를 잘 관리하기 위해서 Secret Manager를 생성합니다.
json 형태로 Lambda가 Access Key, Secret Key, pem key Name 을 갖게끔 구성합니다.
이름은 jinseong-key 로 등록합니다.
{
"access_key": "...",
"secret_key": "...",
"key_name": "..."
}
먼저 Policy부터 생성합니다.
Lambda Function이 접근할 서비스들에 대해 허용하는 정책을 생성합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"ssm:GetParameters",
"ec2:Describe*",
"ec2:ModifySubnetAttribute",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateSecurityGroup",
"ec2:CreateSubnet",
"ec2:AttachInternetGateway",
"ec2:CreateInternetGateway",
"ec2:CreateVpc",
"ec2:ModifyVpcAttribute",
"ec2:CreateRouteTable",
"ec2:CreateRoute",
"ec2:AssociateRouteTable",
"ec2:CreateKeyPair",
"ec2:RunInstances",
"ec2:CreateTags",
"eks:CreateCluster",
"eks:DeleteCluster",
"eks:DescribeCluster",
"eks:ListClusters",
"eks:CreateNodegroup",
"eks:DeleteNodegroup",
"eks:DescribeNodegroup",
"eks:ListNodegroups",
"iam:CreateRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy",
"iam:CreatePolicy",
"iam:DeletePolicy",
"iam:DeleteRole",
"iam:DetachRolePolicy",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"cloudformation:*"
],
"Resource": [
"arn:{jinseong-key-arn-value}",
"*"
]
}
]
}
이후 해당 Policy를 가지는 Role을 생성해 줍니다.
aws chatops가 트리거할 Lambda 함수를 생성합니다.
python 3.12 버전으로 생성하였으며, EKS create Template은 EKS Study에서 사용중인 oneclick 배포 Template을 사용합니다.
aws chatops로 넘어오는 명령어 중 , --payload
값으로 json을 넘길 수 있습니다. 이 값은 event parameter
로 넘어오게 되는데, lambda code에서 이것을 받아서 사용할 수 있습니다.
해당 문서에서는 EKS Cluster에 접근을 허용할 ip 대역을 --payload
로 받아옵니다.
또한 boto3 를 사용하여 aws secret manager와 cloudformation에 접근합니다.
import json
import boto3
import os
from botocore.vendored import requests
from botocore.exceptions import ClientError
def lambda_handler(event, context):
formation_client = boto3.client('cloudformation')
secret_client = boto3.client('secretsmanager')
# secret manager 파싱
get_secret_value_response = secret_client.get_secret_value(SecretId='jinseong-key')
secret = get_secret_value_response['SecretString']
# JSON 문자열 파싱
secret_dict = json.loads(secret)
key_name = secret_dict["key_name"]
access_key = secret_dict["access_key"]
secret_key = secret_dict["secret_key"]
# payload json 값 파싱
sg_cidr = event['sg_cidr']
formation_client.create_stack(
StackName = 'myeks',
# EKS Template URL
TemplateURL = 'https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick.yaml',
Parameters = [
{
'ParameterKey': 'KeyName',
'ParameterValue': key_name
},
{
'ParameterKey': 'MyIamUserAccessKeyID',
'ParameterValue': access_key
},
{
'ParameterKey': 'MyIamUserSecretAccessKey',
'ParameterValue': secret_key
},
{
'ParameterKey': 'SgIngressSshCidr',
'ParameterValue': sg_cidr
}
]
)
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('EKS Create Success!')
}
aws chatOps와 연결한 Slack 채널에서 아래 명령어를 기입합니다.
@aws lambda invoke --function-name eks-oneclick-deploy --payload '{"sg_cidr":"{my-ip-cidr}/32"}' --region ap-northeast-2
eks-oneclick-deploy 라는 이름의 lambda 함수를 트리거하고, region은 ap-northeast-2 , event 파라미터로 보낼 payload 값은 sg_cidr key정보에 value 로 담습니다.
명령어를 전송하면 스레드로 해당 command를 수행할것인지 한번 더 물어보는데, @aws Run
댓글을 남기면 command를 수행하고 대상 Lambda Function을 트리거합니다.
CloudFormation 을 확인하면, 스택들이 생성되는것을 확인할 수 있습니다.