개요
- 내가 이걸 다하나?
- 손이 너무 많이 간다... (고도화 전략 - %로 주기)
- MYSQL Version Upgrade (5.7 -> 8.0)
- 역시 손이 너무 많이간다 ... (고도화 전략 - Terraform 활용하기)
내가 이걸 다하나?
현재 회사에서 근무한지는 어언 11개월이 넘어가고
Devops 파트에서 팀리드가 된지는 6개월이 넘어가는 시점
나는, 우리는 DB를 어떻게 관리했고 앞으로는 어떻게 관리할건지 얘기해보겠다.
사실 DB는 각 회사에 DBA분이 다 하시는건지 알았다. (예전회사는 그랬으니... <- 바보같은 생각)
History가 굉장히 많지만, Database 에 대한 권한제어는 DevOps 파트에서 관리한다.
초반에는 아래와 같은 이유로 굉장히 손이 많이 갔었다.
- 신규입사자 및 퇴사자 계정 추가 및 제거
- 유저별 권한 추가 및 제어
- 인덱스 별 쿼리 제어 및 DML 쿼리의 대한 검증
신규입사자 및 퇴사자 계정 추가 및 제거
## 유저생성
create user <username>@'%' identified by '<password>';
## 유저삭제
DROP user '<username>'@'%';
뭐 어떻게 보면 별거는 아니다.
신규입사자가 오면 유저를 생성하고, 퇴사자는 유저를 Drop 하면 된다.
뭐 금방금방 처리할수는 있지만, 갑자기 바쁠때 처리할라고하면 굉장히 은근 귀찮다.
해당 관련해서 다른 팀원들이 유저를 제거하기 위해 아래와같은 쿼리를 사용했다.
## mysql.user 에서 유저삭제?
DELETE FROM mysql.user WHERE user = <username>;
근데, 이렇게 하면 유저는 삭제되지만 부여된 권한이 삭제가 되지 않는다.
즉... 제대로 삭제가 안된다
유저별 권한 추가 및 제어
## 권한 추가
GRANT SELECT ON `prd_database`.table TO '<username>'@'%';
## 이거 꼭 해줘야 함
flush privileges;
## 해당 유저에 권한 보기
SHOW GRANTS FOR <username>;
유저별 권한은 팀마다 챕터마다 사용하는 DB.Table 추가해주면 된다.
사실 이것도 크게 어렵진 않다. 하지만 물론 이것도 하다보면 손이 꽤 많이간다.
테이블이 없어지거나, 관리가 안된다면... 은근 빡세다
인덱스 별 쿼리 제어 및 DML 쿼리의 대한 검증
이건 크게 관리포인트라기 보다는...
우리회사 특이점 인지는 몰라도, 인덱스 및 쿼리검증은 Devops가 한다 (이게맞나? 싶지만 그것에 대한 의문은 하지않는다 -> 그게프로니까)
보통 인덱스 같은 경우, 아래와 같은 프로세스를 사용해서 진행한다
- RDS에 스냅샷 생성 (index-test)
- 생성된 스냅샷 DB에 인덱스 진행
- 인덱스 시간 및 process 점유 파악
- 금방끝나거나 가벼운작업이라면 진행하지만, 시간이 꽤 걸리는 작업이라면 공지하고 18시~19시 이후에 진행
쿼리에 대한검증도 보통... 위와같이 진행할 수 있다.
가끔 한방쿼리를 사용하는 사람도 있어서...
손이 너무 많이 간다 (고도화전략 - % 로 주기)
회사마다 다르겠지만 현재 우리회사의 DB.Table 숫자는 아래와 같았다.
- Database : 40 + a
- Table : 100 + a
이렇다보니.. 각 유저별 DB.Table 권한을 세세하게 주기가 너무어려웠다.
어떻게 하면 편하게 줄 수 있을까 해서... 편법이 떠올랐다.
## prd_database 구성된 테이블에 SELECT 권한 전체주기
GRANT SELECT ON `prd_database`.* TO '<username>'@'%';
flush privileges;
## prd로 시작하는 전테 데이터베이스.Table에 SELECT 권한 전체주기
GRANT SELECT ON `prd%`.* TO '<username>'@'%';
flush privileges;
이야... 이렇게 하니까 편하긴한데 문제는 여러가지가 발생하였다.
DB가 안돼요
가끔 Data Engineer 분이 본인 쿼리가 안된다고 한다.
근데 또 DB IDE를 껐다 키면 또 됐다가 안됐다가 오락가락 한다.
그 이유를 보니 권한 구성을 살펴보니 아래와 같았다.
그냥 내가 봤을때는 개판이었다.
빨간줄로 슥슥 그었지만, %와 raw 하게 권한을 준것이 짬뽕이되어, 뭔가 꼬이는게 아닐까 하는생각이 들었고,
%로 구성된 권한을 제외하니까 다시는 해당 이슈가 발생하지 않았다....
보안상 이슈
일단 결론적으로 말하면 % 형태로 권한을 부여하는것은 솔직히 좋지 않다.
특히 보안상... 왜냐하면 {prefix}% 시작하는 모든 DB.Table에 대해서는 부여된 권한을 사용할 수 있기 때문이다.
그럼 어떻게 해야할까...
어떻게 하면 보안상으로 훌륭하고, 우리팀의 손을 덜수 있을까?
MYSQL Version Upgrade (5.7 -> 8.0)
업무를 하다보니... 올때가 왔다.
대충 요약하면 MYSQL 5.7 버전이 이제 지원을 종료 하니 8.0 으로 버전을 올려라 이런 얘기다
( 종료는 아니고 표준지원이 종료되니 -> 5.7을 사용할거면 돈을 더 내라... )
별다른 대책이 없다.
그래서 공지하고 기존 5.7 -> 8.0 으로 DB를 업그레이드 했다 (Blue/Green 방법 활용)
관련해서는 추후에 글을 한번 써볼예정임 -> 다사다난했음
역시 손이 너무 많이 간다 ( 고도화전략 - Terraform 활용하기 )
8.0 으로 버전을 올리면서 MYSQL에 내가 몰랐던 기능이 하나 추가되었다.
이 전까진 유저에 대해서 권한을 주고 뺐다 보니까, 굉장히 불편했다.
그런데 Role이 추가된다니... 나름 신세계
AWS 를 주로사용하는 나로서는 RBAC 같은 기능을 나름 잘 사용했기 때문에 회사에 한번 적용해보기로 하였다.
Role 관련 쿼리
## Role 생성
CREATE ROLE 'role_name';
## Role 권한 부여
GRANT SELECT, INSERT, UPDATE ON database_name.* TO 'role_name';
## 유저에 관련 Role 부여
GRANT 'role_name' TO 'user_name'@'host';
## Role 삭제
DROP ROLE 'role_name';
## Role에 대한 권한 확인
SHOW GRANTS FOR 'role_name';
오우... 유저에 권한을 부여하고 하는것보다 더 간단하다고 생각했다.
Role을 사용하면 팀으로 공통된 역할을 부여하는것이 가능할거라고 생각했다.
적용 Architecture
위 구성을 보면 설명은 아래와 같다.
- ADMIN_ROLE은 말 그대로 DB 전체적인 권한
- DATA_ROLE은 DB 에 DML / DDL 권한 및 DBA 수준의 역할을 부여
- *_TEAM_ROLE은 팀마다 관리하는 DB.Table 별 DML 권한 부여
- *_TEAM_READONLY_ROLE은 팀마다 관리하는 DB.Table 별 SELECT 권한 부여
이렇듯 Role 자체를 미리 만들어두면 유저별로 권한을 부여해주는 귀찮은 짓은 안해도 된다.
그럼? Role 관리는 어떻게 할까?
테라폼을 활용하자 (MYSQL Provider)
이 회사에 테라폼 마스터인 내가 있으니... 어떤것도 무섭지 않지
Role 자체에 대한 정의를 미리 만들어놓고 users.tf에다가 해당 값을 매핑시킨다면 크게 어려운것은 없었다
## provider.tf
terraform {
required_providers {
mysql = {
source = "petoju/mysql"
}
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
}
}
variable "HOST" {
}
variable "DB_USER" {
}
variable "DB_PASSWORD" {
}
provider "mysql" {
endpoint = "${var.HOST}:3306"
username = var.DB_USER
password = var.DB_PASSWORD
}
provider "aws" {
profile = ########
region = "ap-northeast-2"
}
terraform {
backend "s3" {
bucket = "shared-state"
key = "database/prd/prd-cluster/terraform.tfstate"
region = "ap-northeast-2"
profile = #######
}
}
## roles.tf
ROLES = {
ADMIN : {
"%" : "ADMIN"
},
"STANDARD" : {
"prod%" : "READ_ONLY",
"prd%" : "READ_ONLY"
},
"DBA" : {
"performance_schema" : "READ_ONLY"
},
"DATA" : {
"prod%" : "ALL_DATA",
"prd%" : "ALL_DATA"
},
}
// DML (CRUD)
TEAM_ROLES = {
"REFUND" : {
"refund.p" : "TEAM_DML",
"refund.pV2" : "TEAM_DML",
"refund.pLog" : "TEAM_DML",
"refund.history" : "TEAM_DML",
"refund.fail" : "TEAM_DML",
"refund.status" : "TEAM_DML"
},
"CARE" : {},
"OP" : {},
"CORE" : {},
"REFUND_READONLY" : {},
"CARE_READONLY" : {},
"OP_READONLY" : {},
"CORE_READONLY" : {},
}
users.yml
user:
display_name: user lee
email: user@company_workspace.kr
given_name: user
family_name: lee
group: developer
role:
shared:
- developer-service
dev:
- zent-sso
db:
prd-database:
- STANDARD ## Role
- REFUND ## Role
provider로 MYSQL을 정의하고
roles.tf에 관련된 Role을 정의한다
그리고 users.yml 을 정의 한후 yamldecode 메서드를 사용해서 기존 role과 매핑시켜주면 된다. (매핑하는 로직이 꽤 빡셀수 있음)
결과는 아래와 같다
유저자체가 가지는 권한에 대해서는 손쉽게 Role로써 부여가 가능하다.
또 이를 Terraform으로 한번더 추상화하니, 더 쉽게 관리가 가능해졌다.
'Architecture > 회고 및 경험' 카테고리의 다른 글
GPU 인스턴스 구성을 구성해보자 - 2 (0) | 2025.03.29 |
---|---|
GPU 인스턴스 구성을 구성해보자 - 1 (0) | 2025.03.24 |
Self Hosted -> CodeBuild (Gtihub Action) 로 넘어가기 (0) | 2025.03.16 |
Platform Engineer의 대한 나의 생각 (0) | 2025.02.16 |
Database Dump 방법 (0) | 2025.01.12 |