1. Đặt vấn đề

Tôi bắt đầu triển khai CSDL Postgresql lên Amazon Web Service (AWS). AWS cung cấp dịch vụ RDS để phục vụ rất nhiều loại database engine khác nhau, cấp độ sẵn sàng, bảo mật, mở rộng tải cực kỳ đa dạng.
Việc kết nối từ PgAdmin, DBeaver vào RDS Postgresql phức tạp hơn so với việc host một Postgresql trong một VPS bởi cơ chế bảo mật rất phức tạp của AWS…

Trong bài này, tôi ghi lại các bước để cấu hình dựng RDS Postgresql và EC2 Bastion Host dùng làm trung gian kết nối giữa client (PgAdmin, DBeaver ) và RDS Postgresql.

2. Một số khái niệm cần nắm trước khi nói chuyện tiếp

Khái niệmVai trò/Ý nghĩa đơn giản
TerraformCông cụ để “lập trình” hạ tầng (tạo server, mạng…)
RDSdịch vụ quản lý CSDL do Amazon Web Services (AWS)
EC2dịch vụ máy chủ ảo (server) của AWS
VPCMạng riêng ảo – khu đô thị của bạn trên cloud
SubnetPhân vùng trong VPC (public = công khai, private = nội bộ)
Internet GatewayCổng ra vào Internet của VPC
Security GroupTường lửa kiểm soát ai được vào/ra các máy chủ
IngressLuồng dữ liệu đi vào máy chủ
EgressLuồng dữ liệu đi ra từ máy chủ
Bastion HostMáy trung gian để truy cập các máy trong subnet riêng tư
SSH TunnelĐường hầm bảo mật để truy cập từ xa vào dịch vụ nội bộ

3. Các phương án

3.1 A: Đặt RDS Postgresql trong public subnet

Cách đơn giản nhất chỉ phù hợp cho thử nghiệm nhanh, không dùng cho production là đặt RDS Postgresql trong public subnet sau đó bật publicly_accessible = yes. Bạn có thể tăng cường thêm bảo mật ở phần security group của RDS chỉ cho phép một địa chỉ IP của chính bạn mới được phép truy cập.

Cách này không được AWS khuyến khích nhưng vẫn kết nối ok nhé.

3.2 B: Đặt RDS trong private subnet, và chỉ cho các EC2 cùng subnet truy cập

Phương án B bảo mật tốt hơn, AWS khuyến khích dùng cho môi trường production. Tuy nhiên cách này cần phải tạo thêm EC2 nằm ở public subnet làm trung gian kết nối.
Trong một dự án prototype tôi chỉ cần tạo một EC2 miễn phí, cấu hình thấp nhất kiêm nhiệm nhiều nhiệm vụ:

  • Làm Bastion Host
  • Cài đặt Nginx làm proxy
  • Chạy vài Golang app…

4. Bastion Host - SSH tunneling

Sau khi chọn xong phương án B Đặt RDS trong private subnet. Giờ hãy tiến hành viết các file terraform. Tôi phải thành thật nói với các bạn là tôi ra lệnh cho AI viết là chủ yếu. Chạy thử nghiệm vài lần mới đúng yêu cầu. Vậy AI là tác giả, còn tôi là người kể lại thôi nhé.

Mã nguồn dự án này ở đây: https://github.com/techmaster-vietnam/fluentoaws/tree/main/infra

graph TB
    subgraph VPC[VPC - var_project_name-vpc]
        subgraph PublicSubnet[Public Subnet - region_a]
            Bastion[Bastion Host
t2.micro] IGW[Internet Gateway] end subgraph PrivateSubnets[Private Subnets] PrivateA[Private Subnet A
region_a] PrivateB[Private Subnet B
region_b] PrivateC[Private Subnet C
region_c] RDS[RDS PostgreSQL] end subgraph SecurityGroups[Security Groups] BastionSG[Bastion SG
Ports: 22,80,443] RDSSG[RDS SG
Port: 5432] end end Internet((Internet)) %% Kết nối Internet <--> IGW IGW <--> PublicSubnet Bastion --> RDSSG RDSSG --> RDS IGW <--> Bastion %% Security Group Rules BastionSG --> Bastion RDSSG --> RDS %% Subnet Associations RDS -.-> PrivateA RDS -.-> PrivateB RDS -.-> PrivateC

Sau khi tạo xong các file Terraform. Kết quả sẽ in ra như thế này

1. Tạo SSH tunnel:
   - Host: 13.229.46.231
   - Port: 22
   - Username: ec2-user
   - Private key: Sử dụng key pair đã tạo

2. Cấu hình kết nối PostgreSQL:
   - Host: polylang-rds.cp0msqwwux96.ap-southeast-1.rds.amazonaws.com:5432
   - Port: 5432
   - Database: polylang
   - Username: root
   - Password: [Sử dụng mật khẩu RDS]

4.1 Kết nối bằng pgadmin

pg_admin connection 1
Cấu hình SSH Tunnel
pg_admin connection SSH Tunnel

4.2 Kết nối bằng DBeaver

DBeaver Connection 1
DBeaver Connection 1
SSH Tunnel
SSH Tunnel