Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .github/workflows/terraform-apply.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ jobs:
sudo dpkg -i /tmp/session-manager-plugin.deb
echo "/usr/local/sessionmanagerplugin/bin" >> $GITHUB_PATH
/usr/local/sessionmanagerplugin/bin/session-manager-plugin --version
- name: Start SSM Tunnel to RDS
- name: Start SSM Tunnel to DB EC2
run: |
echo "=== session-manager-plugin 진단 ==="
which session-manager-plugin || echo "NOT IN PATH"
Expand All @@ -147,25 +147,26 @@ jobs:
--query 'Reservations[0].Instances[0].InstanceId' \
--output text)

RDS_HOST=$(aws rds describe-db-instances \
--query 'DBInstances[?contains(DBInstanceIdentifier, `prod`)].Endpoint.Address | [0]' \
DB_EC2_HOST=$(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=solid-connection-db-mysql-prod" "Name=instance-state-name,Values=running" \
--query 'Reservations[0].Instances[0].PrivateIpAddress' \
--output text)

if [ -z "$EC2_ID" ] || [ "$EC2_ID" = "None" ]; then
echo "::error::prod EC2 인스턴스를 찾을 수 없습니다"
exit 1
fi
if [ -z "$RDS_HOST" ] || [ "$RDS_HOST" = "None" ]; then
echo "::error::prod RDS 엔드포인트를 찾을 수 없습니다"
if [ -z "$DB_EC2_HOST" ] || [ "$DB_EC2_HOST" = "None" ]; then
echo "::error::prod DB EC2 private IP를 찾을 수 없습니다"
exit 1
fi

echo "Tunneling via $EC2_ID -> $RDS_HOST:3306"
echo "Tunneling via $EC2_ID -> $DB_EC2_HOST:3306"

aws ssm start-session \
--target "$EC2_ID" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters "{\"host\":[\"$RDS_HOST\"],\"portNumber\":[\"3306\"],\"localPortNumber\":[\"3306\"]}" &
--parameters "{\"host\":[\"$DB_EC2_HOST\"],\"portNumber\":[\"3306\"],\"localPortNumber\":[\"3306\"]}" &
SSM_PID=$!
echo "SSM_PID=$SSM_PID" >> $GITHUB_ENV

Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/terraform-plan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ jobs:
# 이후 모든 스텝의 PATH 맨 앞에 신규 설치 경로 추가
echo "/usr/local/sessionmanagerplugin/bin" >> $GITHUB_PATH
/usr/local/sessionmanagerplugin/bin/session-manager-plugin --version
- name: Start SSM Tunnel to RDS
- name: Start SSM Tunnel to DB EC2
run: |
echo "=== session-manager-plugin 진단 ==="
which session-manager-plugin || echo "NOT IN PATH"
Expand All @@ -214,25 +214,26 @@ jobs:
--query 'Reservations[0].Instances[0].InstanceId' \
--output text)

RDS_HOST=$(aws rds describe-db-instances \
--query 'DBInstances[?contains(DBInstanceIdentifier, `prod`)].Endpoint.Address | [0]' \
DB_EC2_HOST=$(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=solid-connection-db-mysql-prod" "Name=instance-state-name,Values=running" \
--query 'Reservations[0].Instances[0].PrivateIpAddress' \
--output text)

if [ -z "$EC2_ID" ] || [ "$EC2_ID" = "None" ]; then
echo "::error::prod EC2 인스턴스를 찾을 수 없습니다"
exit 1
fi
if [ -z "$RDS_HOST" ] || [ "$RDS_HOST" = "None" ]; then
echo "::error::prod RDS 엔드포인트를 찾을 수 없습니다"
if [ -z "$DB_EC2_HOST" ] || [ "$DB_EC2_HOST" = "None" ]; then
echo "::error::prod DB EC2 private IP를 찾을 수 없습니다"
exit 1
fi

echo "Tunneling via $EC2_ID -> $RDS_HOST:3306"
echo "Tunneling via $EC2_ID -> $DB_EC2_HOST:3306"

aws ssm start-session \
--target "$EC2_ID" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters "{\"host\":[\"$RDS_HOST\"],\"portNumber\":[\"3306\"],\"localPortNumber\":[\"3306\"]}" &
--parameters "{\"host\":[\"$DB_EC2_HOST\"],\"portNumber\":[\"3306\"],\"localPortNumber\":[\"3306\"]}" &
SSM_PID=$!
echo "SSM_PID=$SSM_PID" >> $GITHUB_ENV

Expand Down Expand Up @@ -433,4 +434,3 @@ jobs:
- name: Plan Status Check
if: steps.plan.outputs.exitcode == '1'
run: exit 1

5 changes: 4 additions & 1 deletion modules/app_stack/db_ec2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,14 @@ resource "aws_instance" "db_server" {
Name = "solid-connection-db-mysql-${var.env_name}"
}

user_data_replace_on_change = true
user_data_replace_on_change = false

lifecycle {
ignore_changes = [
key_name,
user_data,
user_data_base64,
user_data_replace_on_change,
]
}
}
Expand Down
9 changes: 6 additions & 3 deletions modules/app_stack/rds.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@ resource "aws_db_instance" "default" {

# 6. MySQL 추가 유저 생성
resource "mysql_user" "users" {
for_each = var.enable_rds ? var.additional_db_users : {}
for_each = var.enable_rds || var.enable_db_ec2 ? var.additional_db_users : {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wait for DB EC2 bootstrap before managing users

When enable_db_ec2 is used while the DB instance is being created or replaced, this now schedules mysql_user/mysql_grant in the same apply, but the only added dependency is the EC2 resource itself; Terraform considers the instance created before mysql_setup.sh has finished starting Docker/MySQL and creating the remote root user. In that first-create/replacement path the MySQL provider can connect through the tunnel before the database is ready, making applies fail or become flaky; add an explicit cloud-init/SSM readiness check resource and depend on that before creating users.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 지적 감사합니다! 말씀하신 것처럼 DB EC2를 최초 생성하거나 교체하는 apply에서는 aws_instance 생성 완료가 cloud-init 및 MySQL 준비 완료를 보장하지 않기 때문에, 별도의 readiness check가 필요할 수 있다고 생각합니다.

다만 이번 PR에서는 DB EC2를 생성/교체하지 않고, 이미 부트스트랩과 MySQL 기동 및 scadmin 인증까지 확인된 기존 DB EC2에 scapp_user, scapp_flyway 유저/권한만 추가하는 범위입니다. 실제 prod plan도 Plan: 4 to add, 0 to change, 0 to destroy로 DB EC2 변경 없이 MySQL user/grant 생성만 잡히는 것을 확인했습니다.

또한 DB EC2 생성/부트스트랩 안정화는 앞선 hotfix PR들에서 swap 추가와 root 인증 기반 readiness check로 보강했고, 이번 PR에서는 RDS 삭제도 제외하여 #61 후속 이슈에서 별도로 안전하게 처리할 예정입니다.

따라서 이번 PR에서는 추가 Terraform readiness 리소스는 넣지 않고, 향후 DB EC2 교체 자동화가 필요해지는 시점에 별도 작업으로 다루는 것이 적절하다고 판단했습니다.


user = each.key
host = "%"
plaintext_password = each.value.password

depends_on = [aws_db_instance.default]
depends_on = [
aws_db_instance.default,
aws_instance.db_server,
]
}

# 7. MySQL 권한 부여
resource "mysql_grant" "user_grants" {
for_each = var.enable_rds ? var.additional_db_users : {}
for_each = var.enable_rds || var.enable_db_ec2 ? var.additional_db_users : {}

user = each.key
host = "%"
Expand Down
Loading