Hosted Redash와 작별하여 ECS(Fargate)에서 Redash(v10) 구축
개시하다
이 글은 FOLIO Advent Calendar 2021 16일째 되는 글이다.
올해 HostedRedash 서비스 종료가 방송되었다.Hosted Redash를 영입하고 싶은 분들은 대책 옮기느라 바쁘시죠?
FOLIO 역시 호스테드 레즈를 활용해 9월 AWS ECS(Fargate)의 자비 운용으로 변경했다.
호스티드 레지스의 서비스가 끝난 뒤 보낸 편지가 커뮤니티에 제대로 작용하지 못해 마음이 아팠지만, 하나의 사례로 한 일의 기록을 전달했으면 좋겠다는 생각에 이 기사를 썼다.
화두로 참고할 사례가 많지만, 사례의 내용을 테라포름으로 낮추기가 힘들다는 점에 초점을 맞췄다.참고가 됐으면 좋겠어요.
해본 일
중간부재 구축
테라form의 구조 샘플을 함께 게재했습니다.
RDS
다음은 모두 최소한의 규격이고 매개 변수도 최소한의 것만 넣기 때문에 여러분의 상황에 따라 변경해 달라고 말씀드릴 수 있습니다.
rds.tf
module "db" {
# see: https://github.com/terraform-aws-modules/terraform-aws-rds
source = "terraform-aws-modules/rds/aws"
version = "~> 3.0"
identifier = "<your-redash-rds>"
engine = "postgres"
# redash公式は9系を利用しているが、さすがに古すぎるので無視して一旦12で構築する
engine_version = "12.6"
family = "postgres12"
major_engine_version = "12"
instance_class = "db.t3.micro"
allocated_storage = 5
storage_encrypted = true
allow_major_version_upgrade = true
auto_minor_version_upgrade = true
apply_immediately = true
username = "root"
password = random_password.rds_root_password.result
port = 5432
vpc_security_group_ids = ["<your-security-group_id>"]
maintenance_window = "sat:19:00-sat:19:30"
backup_window = "18:30-19:00"
backup_retention_period = 7
# Enhanced Monitoring - see example for details on how to create the role
# by yourself, in case you don't want to create it automatically
monitoring_interval = "30"
monitoring_role_name = "your-redash-rds-MonitoringRole"
create_monitoring_role = true
kms_key_id = aws_kms_key.db_encryption_key.arn
enabled_cloudwatch_logs_exports = ["postgresql"]
# DB subnet group
subnet_ids = ["<your-subnet-a>", "<your-subnet-c>"]
# Database Deletion Protection
deletion_protection = true
parameters = [
{
name = "autovacuum"
value = 1
},
{
name = "client_encoding"
value = "utf8"
}
]
}
resource "random_password" "rds_root_password" {
length = 30
override_special = "!$%&*()-_=+[]{}<>:"
}
resource "aws_kms_key" "db_encryption_key" {
description = "kms key for database encryption"
enable_key_rotation = true
}
resource "aws_kms_alias" "db_encryption_key" {
name = "alias/kms-redash-db-encryption-key"
target_key_id = aws_kms_key.db_encryption_key.key_id
}
실례가 만들어지면 임의의 페달 등에서 만들어진 루트 서버로 RDS에 연결하고, 레드 캐시를 만드는 사용자를 사용한다.login_rds.sh
psql -h <your-host>.<your-region>.rds.amazonaws.com -U root -p 5432
물론 정말 노력한다면 이 과정도 IaC화할 수 있지만 이번에는 포기하고 수동으로 집행했다.create_redash_role.sql
CREATE USER redash WITH PASSWORD '<your-awesome-strong-password>' CREATEDB;
CREATE DATABASE redash;
GRANT ALL ON ALL TABLES IN SCHEMA public TO redash;
redis
별다른 일을 하지 않고 최소한의 규격으로 구축하다.
redis.tf
resource "aws_elasticache_cluster" "redis" {
cluster_id = "redash-redis"
engine = "redis"
node_type = "cache.t2.micro"
num_cache_nodes = 1
# 公式がredis3系なのでそれに合わせる
# see: https://github.com/getredash/redash/blob/0f41f2572060600301a31ac3654dff09395f5ab4/docker-compose.yml#L48
parameter_group_name = "default.redis3.2"
engine_version = "3.2.10"
port = 6379
maintenance_window = "sat:19:00-sat:20:00"
subnet_group_name = aws_elasticache_subnet_group.redis.name
security_group_ids = ["<your-security-group-id>"]
}
resource "aws_elasticache_subnet_group" "redis" {
name = "redash-redis-subnet"
description = "redis subnet group for redash redis"
subnet_ids = ["<your-subnet-a>", "<your-subnet-c>"]
}
rds와 Redis를 방문할 때의 URL은 Redash 주체를 구축할 때 사용하기 때문에 파라미터 저장소에 등록하고 일어나세요.ECS
전체 구성 모방참고 문장 구축.
집단은 하나만 만들었고 서비스 정의 정의는 두 개를 정의했다. 작업 정의 정의 정의 정의는 최초로 수동으로 한 번 이동하는
create_db
명령의 세 가지를 포함한다.클러스터 정의 샘플
ecs_cluster.tf
resource "aws_ecs_cluster" "redash_ecs_cluster" {
name = "redash-ecs-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
capacity_providers = [
"FARGATE",
"FARGATE_SPOT"
]
}
서비스 정의 샘플
Redash 서버를 위한 서비스와 Redash worker를 위한 서비스는 부하에 따라 worker를 규모화하려는 상황에 따라 서비스를 분할합니다.그러나 워크맨이 사용하는 서비스는 뒤에 기술한 ALB 접근 설정을 제외하고는 내용이 거의 같다. 여기에는 서버가 사용하는 서비스만 예시한다.
또 레다스는 웹 서버와worker 사이에는 용기 간의 통신이 필요 없습니다로, 서비스 분할 시 서비스 할인 등을 설정할 필요가 없다.
또 레드쉬의 컨테이너가 일어서는 데 시간이 걸리는 경우가 있어 건강검진 시간을 600초로 늘렸다는 내용도 댓글에 실렸다.
ecs_service.tf
# ECSサービス
resource "aws_ecs_service" "redash_server_service" {
name = "redash-server"
cluster = aws_ecs_cluster.redash_ecs_cluster.id
# 後述
task_definition = aws_ecs_task_definition.redash_server.arn
desired_count = 1
deployment_maximum_percent = 200
deployment_minimum_healthy_percent = 100
# デフォルトの設定のままだと立ち上がる前にヘルスチェックが走ってしまうので、ヘルスチェックを始めるまで10分待つ
# see: https://discuss.redash.io/t/aws-fargate-redash-server-alb/6152
health_check_grace_period_seconds = 600
deployment_circuit_breaker {
enable = true
rollback = true
}
network_configuration {
subnets = ["<your-subnet-a>", "<your-subnet-c>"]
security_groups = ["<your-security-group-id>"]
assign_public_ip = false
}
capacity_provider_strategy {
capacity_provider = "FARGATE"
base = 2
weight = 1
}
capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
base = 0
weight = 0
}
enable_execute_command = true
# ALBからアクセスさせるための設定
load_balancer {
target_group_arn = "<your-alb-target-group-arn>"
container_name = "redash_server"
container_port = 5000
}
작업 정의 샘플
이것은 서비스 정의와 관련된 작업 정의의 견본입니다.CPU와 메모리는 최소한이지만 환경에 따라 축소하는 것이 좋다고 생각합니다.
container_definition.tf
# 初回のみ手動で一度だけ実行するコマンドなのでサービスには紐付け不要
resource "aws_ecs_task_definition" "create_db" {
family = "redash_create_db"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
task_role_arn = "<your-task-role-arn>"
execution_role_arn = "<your-task-execusion-role-arn>"
cpu = 1024
memory = 2048
container_definitions = file("container_definition/create_db.json")
}
# redash server用のサービスに紐付けるコンテナ定義
resource "aws_ecs_task_definition" "redash_server" {
family = "redash_server"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
task_role_arn = "<your-task-role-arn>"
execution_role_arn = "<your-task-execusion-role-arn>"
cpu = 1024
memory = 2048
container_definitions = file("container_definition/redash_server.json")
}
# redash worker用のサービスに紐付けるコンテナ定義
resource "aws_ecs_task_definition" "redash_worker" {
family = "redash_worker"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
task_role_arn = "<your-task-role-arn>"
execution_role_arn = "<your-task-execusion-role-arn>"
cpu = 1024
memory = 2048
container_definitions = file("container_definition/redash_worker.json")
}
다음 작업 정의container데피니션 샘플도 거기다 놔둬.적절하게
name
및 command
를 교체하십시오.워크맨worker
,schedullerscheduler
,createdb 명령을 실행하려면 create_db
로 바꾸십시오.그리고 다른 사람이 만든 조회참고 문장를 편집할 수 있습니다. 필요없는query런너참고 문장를 삭감하고 있습니다.
container_definition/redash_worker.json
[
{
"name": "redash_server",
"image": "redash/redash:10.0.0.b50363",
"cpu": 0,
"stopTimeout": 60,
"memoryReservation": null,
"environment": [
{
"name": "REDASH_HOST",
"value": "<your-host>"
},
{
"name": "PYTHONUNBUFFERED",
"value": "0"
},
{
"name": "REDASH_LOG_LEVEL",
"value": "INFO"
},
{
"name": "REDASH_FEATURE_SHOW_PERMISSIONS_CONTROL",
"value": "true"
},
{
"name": "REDASH_DISABLED_QUERY_RUNNERS",
"value": "redash.query_runner.graphite,redash.query_runner.mongodb,redash.query_runner.couchbase,redash.query_runner.url"
}
],
"secrets": [
{
"name": "REDASH_DATABASE_URL",
"valueFrom": "<your-redah-rds-url>"
},
{
"name": "REDASH_REDIS_URL",
"valueFrom": "<your-redah-redis-url>"
}
],
"command": [
"server"
],
"logConfiguration": {
"logDriver": "awslogs",
"secretOptions": null,
"options": {
"awslogs-group": "<your-log-group>",
"awslogs-region": "<your-region>",
"awslogs-stream-prefix": "<your-prefix>"
}
},
"entryPoint": null,
"portMappings": [
{
"hostPort": 5000,
"protocol": "tcp",
"containerPort": 5000
}
],
"dockerLabels": null
}
]
ALB+Route53+ACM
https를 통해 제작된 ECS에서 실행되는 Redash 환경에 접근할 수 있도록 ALB+Route 53+ACM의 스택을 준비합니다.
루트 53에서 도메인을 취득하고 ACM으로 인증서를 만들어 거기에 ALB를 추가한 청취자, ECS 항목에 추가된 타겟팀을 추가했다.
이렇게 하면 건강검진을 통해 브라우저에서redash에 안전하게 접근할 수 있다.
건강검진은
/ping
에서 시행하죠.alb.tf
resource "aws_lb" "redash" {
name = "redash-lb"
internal = false
load_balancer_type = "application"
security_groups = [<"your-alb-sg-id">]
subnets = var.subnet_ids
}
resource "aws_lb_target_group" "redash" {
name = "redash-target"
port = 5000
protocol = "HTTP"
target_type = "ip"
vpc_id = <your-vpc-id>
health_check {
# health check用の /ping でhealth checkを行う
# see: https://discuss.redash.io/t/aws-fargate-redash-server-alb/6152/6
path = "/ping"
interval = 300
timeout = 120
}
}
resource "aws_lb_listener" "forward" {
load_balancer_arn = aws_lb.redash.arn
port = "443"
protocol = "HTTPS"
certificate_arn = aws_acm_certificate.redash.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.redash.arn
}
}
resource "aws_acm_certificate" "redash" {
domain_name = "redash.exapmle.com"
subject_alternative_names = [
"*.redash.exapmle.com"
]
validation_method = "DNS"
tags = {
Name = "<your-redash-dns-name>"
}
}
Redash 내부 데이터 전송
이전 호스트 버전의 Redash에서 이전한 경우 dump 이전 환경의 RDS 데이터를 고려하여 INSERT를 새 환경의 DB로 옮길 수 있지만 Hosted Redash는 RDS에 직접 접근할 수 없기 때문에 변환 스크립트를 써야 한다.
왕도는 redash-migrate 방법을 사용했지만 이번에는 Hosted Redash가 이전에 사용했던 자전Redash(참고로 그때는 EC2를 사용했는데...) 데이터를 Hosted Redash로 옮기는 스크립트가 있어서 회수하고 사용했습니다.하지만 0을 바탕으로 하면 레드스-migrate로 둥글다고 생각해요.
기타, 상세한 주변 자원 제작 및 준비
업무 수준의 이동
그러면 필요한 자원 준비가 끝난 후 자신의 환경의redash를 이용하여 업무 수준의 이전을 시작할 수 있다.Redash는 사내 각 팀에 의해 다양한 용도로 사용되고 있으며, 이전할 때 다음과 같은 절차를 취하여 각 단계에서 발생하는 문의에 대응하는 동시에 이전하였다.
총결산
무사히 Hosted Redash에 Redash(v10)를 구축해 Hosted Redash와 작별했다.
FOLIO가 2020년부터 이전운용(EC2) 레드ash에서 Hosted Redash로 옮긴 뒤 올해 9월 Hosted Redash가 철수해 이전운용(ECS)으로 이동하기 시작했는데, 이 짧은 시간 안에 지난번을 포함해 두 번의 레드ash 이전이 이뤄질 줄은 몰랐다는 게 실감이지만 다양한 지식을 정리하는 좋은 경험이 됐다.Hosted Redash의 서비스가 끝났기 때문에 이 글을 직접 쓰는 사람은 드물겠지만, 앞으로 Redash를 새롭게 시작하는 분들에게 참고가 될 수 있다면 좋겠다.
Reference
이 문제에 관하여(Hosted Redash와 작별하여 ECS(Fargate)에서 Redash(v10) 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/paulxll/articles/5acfafd0921f0b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)