Skip to content

one-year-gap/log-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

50 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Kafka Connect & MSK ์—ฐ๋™ ์šด์˜ ๊ฐ€์ด๋“œ

์ด ๋ฌธ์„œ๋Š” **์‹ค์ œ AWS ์ธํ”„๋ผ(MSK + ECS Fargate)**์—์„œ log-server๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ(docker-compose.local.yml)๊ณผ์˜ ์ฐจ์ด์ , ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ฃผ์ž… ๋ฐฉ๋ฒ•, Kafka Connect ๋ฐฐํฌ ์ ˆ์ฐจ๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


์ „์ฒด ์•„ํ‚คํ…์ฒ˜

API Server (ECS)
  โ””โ”€ KafkaProducer (key=member_id)
        โ”‚
        โ–ผ
  MSK (kafka.t3.small ร— 2, Multi-AZ)
  โ”œโ”€โ”€ client-event-logs (ํŒŒํ‹ฐ์…˜ 3, replication 2)
  โ””โ”€โ”€ error-logs / DLQ   (ํŒŒํ‹ฐ์…˜ 1, replication 2)
        โ”‚
        โ”œโ”€ Speed Layer (ECS Fargate 0.5vCPU)
        โ”‚    โ””โ”€ SpeedLayerConsumer (Spring Boot)
        โ”‚         โ”œโ”€ click_product_detail๋งŒ ํ•„ํ„ฐ๋ง (RecordFilterStrategy)
        โ”‚         โ”œโ”€ product_view_history UPSERT (PostgreSQL)
        โ”‚         โ””โ”€ ํŒŒ์‹ฑ ์‹คํŒจ โ†’ error-logs DLQ
        โ”‚
        โ””โ”€ Batch Layer (ECS Fargate 0.25vCPU)
             โ””โ”€ Kafka Connect Worker
                  โ””โ”€ S3 Sink โ†’ s3://<bucket>/events/raw/dt=.../hour=.../

1. MSK ์„ค์ •

1-1. MSK ํด๋Ÿฌ์Šคํ„ฐ ์ŠคํŽ™

ํ•ญ๋ชฉ ๊ฐ’ ๋น„๊ณ 
๋ธŒ๋กœ์ปค ํƒ€์ž… kafka.t3.small ์ผ 30๋งŒ ๊ฑด(3.5 TPS) ์ถฉ๋ถ„
๋ธŒ๋กœ์ปค ์ˆ˜ 2 (Multi-AZ) MSK ์ตœ์†Œ ๊ตฌ์„ฑ
Kafka ๋ฒ„์ „ 3.6.x MSK ์ง€์› ์ตœ์‹  ์•ˆ์ • ๋ฒ„์ „
์Šคํ† ๋ฆฌ์ง€ EBS 100GB (๋ธŒ๋กœ์ปค๋‹น) 1์ผ ๋ณด์กด ๊ธฐ์ค€ ์ถฉ๋ถ„
์ธ์ฆ ๋ฐฉ์‹ PLAINTEXT ๋™์ผ VPC ๋‚ด๋ถ€ ํ†ต์‹ 
ํ† ํ”ฝ ์ž๋™ ์ƒ์„ฑ ๋น„ํ™œ์„ฑํ™” ๋ช…์‹œ์  ์ƒ์„ฑ ๊ฐ•์ œ

1-2. MSK ํ† ํ”ฝ ์ƒ์„ฑ (์ตœ์ดˆ 1ํšŒ)

# MSK ๋ถ€ํŠธ์ŠคํŠธ๋žฉ ์ฃผ์†Œ ํ™•์ธ
MSK_BS=$(aws kafka get-bootstrap-brokers \
  --cluster-arn <MSK_CLUSTER_ARN> \
  --query 'BootstrapBrokerString' --output text)

# click ๋กœ๊ทธ ํ† ํ”ฝ
kafka-topics.sh --bootstrap-server $MSK_BS \
  --create --if-not-exists \
  --topic client-event-logs \
  --partitions 3 \
  --replication-factor 2 \
  --config retention.ms=86400000

# DLQ ํ† ํ”ฝ
kafka-topics.sh --bootstrap-server $MSK_BS \
  --create --if-not-exists \
  --topic error-logs \
  --partitions 1 \
  --replication-factor 2

1-3. Security Group ์„ค์ •

MSK Security Group ์ธ๋ฐ”์šด๋“œ:
  - Port 9092 (PLAINTEXT)
  - Source: Speed Layer ECS Task SG
  - Source: Kafka Connect ECS Task SG
  - Source: API Server ECS Task SG

Speed Layer ECS Task SG ์•„์›ƒ๋ฐ”์šด๋“œ:
  - MSK SG โ†’ 9092
  - PostgreSQL RDS SG โ†’ 5432

Kafka Connect ECS Task SG ์•„์›ƒ๋ฐ”์šด๋“œ:
  - MSK SG โ†’ 9092
  - S3 โ†’ VPC Endpoint ๋˜๋Š” NAT Gateway
  - CloudWatch Logs โ†’ VPC Endpoint ๋˜๋Š” NAT Gateway

2. Speed Layer (Spring Boot Consumer) โ€” MSK ์—ฐ๋™

2-1. ๋กœ์ปฌ vs MSK ๋‹ฌ๋ผ์ง€๋Š” ์ 

ํ•ญ๋ชฉ ๋กœ์ปฌ (docker-compose.local.yml) MSK ์šด์˜
KAFKA_BOOTSTRAP_SERVERS localhost:9092 b-1.xxx.kafka.ap-northeast-2.amazonaws.com:9092,b-2.xxx...:9092
DB_URL jdbc:postgresql://localhost:5435/holliverse jdbc:postgresql://<RDS_ENDPOINT>:5432/<DB_NAME>
์ธํ”„๋ผ ์‹คํ–‰ docker-compose.local.yml AWS MSK + RDS
Spring Boot ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์Œ ์—†์Œ (ํ™˜๊ฒฝ๋ณ€์ˆ˜๋งŒ ๊ต์ฒด)

2-2. ECS Task Definition ํ™˜๊ฒฝ๋ณ€์ˆ˜

ECS Task Definition์˜ environment ๋˜๋Š” AWS Secrets Manager/Parameter Store์— ๋‹ค์Œ์„ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค.

[
  { "name": "KAFKA_BOOTSTRAP_SERVERS",     "value": "b-1.xxx.kafka.ap-northeast-2.amazonaws.com:9092,b-2.xxx.kafka.ap-northeast-2.amazonaws.com:9092" },
  { "name": "KAFKA_TOPIC_CLIENT_EVENTS",   "value": "client-event-logs" },
  { "name": "KAFKA_TOPIC_ERROR",           "value": "error-logs" },
  { "name": "KAFKA_GROUP_SPEED",           "value": "speed-layer-group" },
  { "name": "KAFKA_MAX_POLL_RECORDS",      "value": "1" },
  { "name": "KAFKA_DLQ_ACKS",             "value": "all" },
  { "name": "KAFKA_DLQ_RETRIES",          "value": "3" },
  { "name": "DB_URL",                      "value": "jdbc:postgresql://<RDS_ENDPOINT>:5432/<DB_NAME>" },
  { "name": "DB_USERNAME",                 "value": "<DB_USERNAME>" },
  { "name": "DB_PASSWORD",                 "value": "<DB_PASSWORD>" },
  { "name": "JPA_DDL_AUTO",               "value": "validate" }
]

๋ณด์•ˆ: DB_PASSWORD ๋“ฑ ๋ฏผ๊ฐ ๊ฐ’์€ valueFrom์œผ๋กœ AWS Secrets Manager ARN์„ ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ์‹์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

2-3. application.yaml ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋งคํ•‘ ์š”์•ฝ

# application.yaml (์ฝ”๋“œ ๊ธฐ์ค€ โ€” ์šด์˜ ์‹œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๋ฎ์–ด์”€)
spring:
  datasource:
    url: ${DB_URL:jdbc:postgresql://localhost:5435/holliverse}
    username: ${DB_USERNAME:postgres}
    password: ${DB_PASSWORD:postgres}
  jpa:
    hibernate:
      ddl-auto: ${JPA_DDL_AUTO:validate}

app:
  kafka:
    bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
    topics:
      client-events: ${KAFKA_TOPIC_CLIENT_EVENTS:client-event-logs}
      error: ${KAFKA_TOPIC_ERROR:error-logs}
    groups:
      speed: ${KAFKA_GROUP_SPEED:speed-layer-group}
    listener:
      max-poll-records: ${KAFKA_MAX_POLL_RECORDS:1}
      ack-mode: RECORD
    producer:
      dlq-acks: ${KAFKA_DLQ_ACKS:all}
      dlq-retries: ${KAFKA_DLQ_RETRIES:3}

2-4. ECS Fargate ํƒœ์Šคํฌ ์ŠคํŽ™

ํ•ญ๋ชฉ ๊ฐ’
Launch type Fargate
vCPU 0.5
Memory 1 GB
์ดˆ๊ธฐ ํƒœ์Šคํฌ ์ˆ˜ 1 (์ตœ๋Œ€ 3, ํŒŒํ‹ฐ์…˜ ์ˆ˜ ๊ธฐ์ค€)
Consumer Group speed-layer-group
๋„คํŠธ์›Œํฌ VPC Private Subnet

3. Batch Layer (Kafka Connect S3 Sink) โ€” MSK ์—ฐ๋™

3-1. ECS Fargate ํƒœ์Šคํฌ ์ŠคํŽ™

ํ•ญ๋ชฉ ๊ฐ’
์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ confluentinc/cp-kafka-connect:7.7.1 (S3 Sink ํ”Œ๋Ÿฌ๊ทธ์ธ ํฌํ•จ)
vCPU 0.25
Memory 0.5 GB
ํƒœ์Šคํฌ ์ˆ˜ 1 (๊ณ ์ •)
Consumer Group s3-sink-group (Connect ๋‚ด๋ถ€ ์ž๋™ ๊ด€๋ฆฌ)

3-2. IAM Task Role ์ตœ์†Œ ๊ถŒํ•œ

ECS Task Role์— ๋‹ค์Œ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค.

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::<bucket>",
        "arn:aws:s3:::<bucket>/events/raw/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:*:*:/aws/ecs/*"
    }
  ]
}

3-3. Kafka Connect Worker ํ™˜๊ฒฝ๋ณ€์ˆ˜ (ECS Task Definition)

[
  { "name": "CONNECT_BOOTSTRAP_SERVERS",            "value": "b-1.xxx.kafka.ap-northeast-2.amazonaws.com:9092,b-2.xxx.kafka.ap-northeast-2.amazonaws.com:9092" },
  { "name": "CONNECT_REST_PORT",                    "value": "8083" },
  { "name": "CONNECT_GROUP_ID",                     "value": "kafka-connect-s3-group" },
  { "name": "CONNECT_CONFIG_STORAGE_TOPIC",         "value": "connect-configs" },
  { "name": "CONNECT_OFFSET_STORAGE_TOPIC",         "value": "connect-offsets" },
  { "name": "CONNECT_STATUS_STORAGE_TOPIC",         "value": "connect-status" },
  { "name": "CONNECT_KEY_CONVERTER",                "value": "org.apache.kafka.connect.storage.StringConverter" },
  { "name": "CONNECT_VALUE_CONVERTER",              "value": "org.apache.kafka.connect.storage.StringConverter" },
  { "name": "CONNECT_PLUGIN_PATH",                  "value": "/usr/share/java,/usr/share/confluent-hub-components" },
  { "name": "AWS_REGION",                           "value": "ap-northeast-2" }
]

Connect ๋‚ด๋ถ€ ํ† ํ”ฝ(connect-configs, connect-offsets, connect-status)๋„ MSK์— ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
์šด์˜ ์•ˆ์ •์„ฑ์„ ์œ„ํ•ด ์‚ฌ์ „์— replication-factor=2๋กœ ์ˆ˜๋™ ์ƒ์„ฑ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

3-4. ์ปค๋„ฅํ„ฐ ์„ค์ • ํŒŒ์ผ

JSONL.gz ํฌ๋งท (์ตœ์ข… ํ›„๋ณด) โ€” s3-sink-connector-jsonl.gz.json

{
  "name": "s3-sink-client-event-logs-jsonl",
  "config": {
    "connector.class": "io.confluent.connect.s3.S3SinkConnector",
    "tasks.max": "1",
    "topics": "client-event-logs",

    "s3.region": "${AWS_REGION}",
    "s3.bucket.name": "${S3_BUCKET_NAME}",
    "s3.part.size": "5242880",

    "flush.size": "500",
    "rotate.interval.ms": "300000",

    "storage.class": "io.confluent.connect.s3.storage.S3Storage",
    "format.class": "io.confluent.connect.s3.format.json.JsonFormat",
    "compression.type": "gzip",

    "partitioner.class": "io.confluent.connect.storage.partitioner.TimeBasedPartitioner",
    "timestamp.extractor": "RecordField",
    "timestamp.field": "timestamp",
    "path.format": "'events/raw/dt='YYYY-MM-dd'/hour='HH",
    "partition.duration.ms": "3600000",
    "locale": "ko_KR",
    "timezone": "UTC"
  }
}

Parquet ํฌ๋งท (Athena ์ตœ์ ํ™”, ์‹คํ—˜์šฉ) โ€” s3-sink-connector-parquet.json

{
  "name": "s3-sink-client-event-logs-parquet",
  "config": {
    "connector.class": "io.confluent.connect.s3.S3SinkConnector",
    "tasks.max": "1",
    "topics": "client-event-logs",

    "s3.region": "${AWS_REGION}",
    "s3.bucket.name": "${S3_BUCKET_NAME}",
    "s3.part.size": "5242880",

    "flush.size": "500",
    "rotate.interval.ms": "300000",

    "storage.class": "io.confluent.connect.s3.storage.S3Storage",
    "format.class": "io.confluent.connect.s3.format.parquet.ParquetFormat",
    "parquet.codec": "snappy",

    "partitioner.class": "io.confluent.connect.storage.partitioner.TimeBasedPartitioner",
    "timestamp.extractor": "RecordField",
    "timestamp.field": "timestamp",
    "path.format": "'events/raw/dt='YYYY-MM-dd'/hour='HH",
    "partition.duration.ms": "3600000",
    "locale": "ko_KR",
    "timezone": "UTC"
  }
}

์ฃผ์š” ์„ค์ • ์˜๋„

์„ค์ • ๊ฐ’ ์˜๋„
flush.size 500 500๊ฑด ์Œ“์ด๋ฉด S3์— ํ”Œ๋Ÿฌ์‹œ
rotate.interval.ms 300000 (5๋ถ„) 500๊ฑด ๋ฏธ๋งŒ์ด์–ด๋„ 5๋ถ„๋งˆ๋‹ค ๊ฐ•์ œ ํ”Œ๋Ÿฌ์‹œ
timestamp.field timestamp ์ด๋ฒคํŠธ ์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ dt/hour ํŒŒํ‹ฐ์…˜ ๊ณ„์‚ฐ
partition.duration.ms 3600000 (1์‹œ๊ฐ„) 1์‹œ๊ฐ„ ๋‹จ์œ„ ํŒŒํ‹ฐ์…˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ
path.format events/raw/dt=YYYY-MM-dd/hour=HH Athena/ETL ํŒŒํ‹ฐ์…˜ ํ‘œ์ค€ ๊ทœ์น™

3-5. ์ปค๋„ฅํ„ฐ ๋ฐฐํฌ ์ ˆ์ฐจ

1) Connect Worker๊ฐ€ ๊ธฐ๋™๋˜๋ฉด REST API๋กœ ์ปค๋„ฅํ„ฐ ๋“ฑ๋ก

export S3_BUCKET_NAME=holliverse-logs
export AWS_REGION=ap-northeast-2
export CONNECT_HOST=<connect-task-private-ip>  # ECS Task IP ๋˜๋Š” ALB

# JSONL.gz ์ปค๋„ฅํ„ฐ ๋“ฑ๋ก
envsubst < kafka-connect/s3-sink-connector-jsonl.gz.json \
  | curl -s -X POST http://$CONNECT_HOST:8083/connectors \
    -H "Content-Type: application/json" \
    -d @-

2) ์ปค๋„ฅํ„ฐ ์ƒํƒœ ํ™•์ธ

# ๋“ฑ๋ก๋œ ์ปค๋„ฅํ„ฐ ๋ชฉ๋ก
curl http://$CONNECT_HOST:8083/connectors

# ํŠน์ • ์ปค๋„ฅํ„ฐ ์ƒํƒœ (RUNNING ํ™•์ธ)
curl http://$CONNECT_HOST:8083/connectors/s3-sink-client-event-logs-jsonl/status

# ์ปค๋„ฅํ„ฐ ์‚ญ์ œ (์žฌ๋“ฑ๋ก ์‹œ)
curl -X DELETE http://$CONNECT_HOST:8083/connectors/s3-sink-client-event-logs-jsonl

3) S3 ์ ์žฌ ํ™•์ธ

aws s3 ls s3://holliverse-logs/events/raw/ --recursive | head -20
# ์˜ˆ์ƒ ๊ฒฝ๋กœ: events/raw/dt=2026-03-05/hour=12/part-00001.jsonl.gz

4. ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

MSK๋Š” VPC ๋‚ด๋ถ€์—์„œ๋งŒ ์ ‘์† ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ๋กœ์ปฌ์—์„œ๋Š” docker-compose.local.yml์˜ Kafka๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

4-1. ๋กœ์ปฌ ๊ธฐ๋™ ์ˆœ์„œ

# 1. Kafka + Kafka UI + PostgreSQL ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋™
docker compose -f docker-compose.local.yml up -d

# 2. ๊ธฐ๋™ ํ™•์ธ (์•ฝ 10์ดˆ ์†Œ์š”)
docker logs kafka --tail 20

# 3. ํ† ํ”ฝ ์ƒ์„ฑ
chmod +x scripts/create-topics.sh
./scripts/create-topics.sh --mode local

# 4. Spring Boot ์‹คํ–‰ (application.yaml ๊ธฐ๋ณธ๊ฐ’ = localhost)
./gradlew bootRun

4-2. ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ์ „์†ก

# click_product_detail โ€” product_view_history์— UPSERT๋จ
docker exec -i kafka kafka-console-producer \
  --bootstrap-server localhost:9092 \
  --topic client-event-logs <<'EOF'
{"event_id":1000000000001,"timestamp":"2026-03-05T12:00:00Z","event":"click","event_name":"click_product_detail","member_id":45,"event_properties":{"page_url":"https://api.holliverse.site/api/v1/customer/plans","product_id":10,"product_name":"5G ์š”๊ธˆ์ œ","product_type":"mobile","tags":["์˜์ƒOTT","์ธ๊ธฐ"]}}
EOF

# event_name์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ โ€” RecordFilterStrategy์—์„œ ํ๊ธฐ, DB ๋ฏธ์ ์žฌ
docker exec -i kafka kafka-console-producer \
  --bootstrap-server localhost:9092 \
  --topic client-event-logs <<'EOF'
{"event_id":1000000000002,"timestamp":"2026-03-05T12:01:00Z","event":"click","event_name":"page_view","member_id":45,"event_properties":{"product_id":99,"product_name":"๋ฌด์‹œ๋Œ€์ƒ","product_type":"etc","tags":[]}}
EOF

# event_id ํƒ€์ž… ์˜ค๋ฅ˜ (String) โ€” ์—ญ์ง๋ ฌํ™” ์‹คํŒจ โ†’ error-logs DLQ๋กœ ์ „์†ก
docker exec -i kafka kafka-console-producer \
  --bootstrap-server localhost:9092 \
  --topic client-event-logs <<'EOF'
{"event_id":"uuid-1234-5678","timestamp":"2026-03-05T12:02:00Z","event":"click","event_name":"click_product_detail","member_id":45,"event_properties":{"product_id":47,"product_name":"ํƒ€์ž…์˜ค๋ฅ˜","product_type":"mobile","tags":[]}}
EOF

4-3. PostgreSQL ์ ์žฌ ํ™•์ธ

# PostgreSQL ์ ‘์†
docker exec -it postgres psql -U loguser -d logdb

# ์ ์žฌ๋œ ๋ ˆ์ฝ”๋“œ ํ™•์ธ
SELECT member_id, product_id, product_name, product_type, tags, viewed_at, last_event_id
FROM product_view_history
ORDER BY viewed_at DESC;

# ์œ ์ €๋ณ„ ์ตœ๊ทผ ๋ณธ ์ƒํ’ˆ 3๊ฐœ ์กฐํšŒ (RAG ์„œ๋น™์šฉ ์ฟผ๋ฆฌ)
SELECT product_id, product_name, product_type, tags, viewed_at
FROM product_view_history
WHERE member_id = 45
ORDER BY viewed_at DESC
LIMIT 3;

4-4. DLQ(error-logs) ํ™•์ธ

docker exec -it kafka kafka-console-consumer \
  --bootstrap-server localhost:9092 \
  --topic error-logs \
  --from-beginning

5. ๋กœ์ปฌ vs MSK ๋น„๊ต ์š”์•ฝ

ํ•ญ๋ชฉ ๋กœ์ปฌ MSK ์šด์˜
KAFKA_BOOTSTRAP_SERVERS localhost:9092 b-1.xxx...:9092,b-2.xxx...:9092
DB_URL jdbc:postgresql://localhost:5435/holliverse jdbc:postgresql://<RDS_ENDPOINT>:5432/<DB>
Kafka ๊ธฐ๋™ docker-compose.local.yml AWS MSK ์ž๋™ ๊ด€๋ฆฌ
ํ† ํ”ฝ ์ƒ์„ฑ create-topics.sh --mode local create-topics.sh --mode msk
๋ชจ๋‹ˆํ„ฐ๋ง Kafka UI (localhost:8081) CloudWatch ์ž๋™ ์—ฐ๋™
Spring Boot ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์Œ ๋ณ€๊ฒฝ ์—†์Œ (ํ™˜๊ฒฝ๋ณ€์ˆ˜๋งŒ ๊ต์ฒด)
Kafka Connect ๋กœ์ปฌ ๋ฏธ์‚ฌ์šฉ (ํ…Œ์ŠคํŠธ ๋ถˆํ•„์š”) ECS Fargate Task

About

๐Ÿ‘จ๐Ÿผโ€๐Ÿš€HOLLIVESE LOG SERVER REPO๐Ÿ‘จ๐Ÿผโ€๐Ÿš€

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors