DevOps
AWS MSK PART2 — MSK 클러스터를 구축해볼까요?
Fang여기어때
2022년 8월 29일
원문에서 보기 ↗
안녕하세요. 여기어때 서비스개발팀에서 백엔드 개발을 담당하고 있는 팡입니다😀
서비스개발팀은 여기어때 앱의 전시 데이터와 상품 데이터를 노출하고, 노출을 위한 각 도메인의 데이터를 동기화하는 서비스를 개발하고 운영하며, 여기어때 서비스 제일 앞단에서의 트래픽을 분산처리 하는 업무를 담당하고 있습니다. “2년차 개발자와 함께하는 서비스개발팀 탐방기”에 대한 상세한 설명이 있으니 많은 관심 부탁드립니다.
MSK PART1 — MSK 도입 여정 글 재미있게 보셨나요?
이번 포스팅에서는 MSK 클러스터를 직접 생성하고 MSK 클러스터와 통신해서 제어할 수 있는 관리 노드를 설정하는 부분에 대해 설명하겠습니다. 그리고 Kafka Producer & Consumer 테스트, 성능 테스트에 대해서도 살펴보겠습니다.
AWS MSK PART 1 — MSK 도입 여정
AWS MSK PART 2 — 클러스터를 구축해볼까요? 👈
AWS MSK PART 3 — 모니터링을 구축해볼까요?
AWS MSK PART 4 — 운영은 어떻게 하고 있나요?
MSK 클러스터 생성
AWS Console에서 MSK 클러스터 생성 방법은 2가지가 있습니다.
Quick create(빠른 생성)
- MSK를 빠르게 생성해서 테스트하고 싶은 경우에만 사용하면 좋은 방법입니다.
- VPC, 서브넷은 기본값을 사용하며 보안 및 가용성, 관련 부분은 상세한 설정이 불가능합니다.
Custom create(맞춤 생성)
- 보안, 가용성 및 사용자가 원하는 모든 설정이 가능합니다.
Quick create(빠른 생성)를 통해 MSK를 생성하는 절차입니다.
STEP 1. 클러스터 이름을 입력합니다.
STEP 2. Apache Kafka version을 선택합니다. (2.6.2 버전을 권장)
STEP 3. Broker type을 선택합니다.
STEP 4. EBS(Elastic Block Store) 스토리지 볼륨 크기를 입력합니다.
STEP 5. 클러스터 설정을 확인합니다.
- 설정된 정보를 확인하고, 클러스터가 생성된 이후에는 VPC, Subnet, Zone, 클러스터 내 암호화, 저장 데이터 암호화는 설정을 변경할 수 없습니다.
STEP 6. create cluster를 클릭하여 클러스터를 생성합니다.
STEP 7. 일반적으로 클러스터 생성 시 15분 정도 소요된다고 나오지만 약 30분 정도 소요됩니다.

Custom create(맞춤 생성)을 통해 MSK를 생성하는 절차입니다.
STEP 1. Cluster Setting
Cluster 생성 방법은 Custom create을 선택합니다.
Cluster name
- MSK 클러스터에 이름을 설정합니다.
- 클러스터를 생성한 후에는 변경할 수 없습니다.
- 최대 64자까지 가능합니다.
Apache Kafka version
- 2.6.2를 권장합니다.
- 최신 버전은 3.2.0까지 선택할 수 있습니다.
- https://docs.aws.amazon.com/msk/latest/developerguide/supported-kafka-versions.html
Brokers
- MSK 클러스터의 성능은 브로커의 수와 브로커 유형(인스턴스 타입)에 따라 다릅니다.
- Broker type을 선택합니다. (kafka.t3.small)
- Number of zones에서 AZ의 개수는 3개를 추천하지만, 개발 환경에서는 최소 구성을 위해 2로 설정하였습니다. → 실제 상용 환경에서는 AZ를 3으로 설정해주세요. 클러스터가 생성된 후에는 AZ 개수를 변경할 수 없습니다.
- Number of brokers per zone은 AZ 당 배포되는 브로커의 개수를 1로 설정합니다. MSK 클러스터에서 총 2개의 브로커가 생성됩니다. (AZ에 1개씩)
- Storage는 브로커당 EBS 스토리지 볼륨 10GiB로 설정합니다. (최소 1Gib, 최대: 16364GiB) 클러스터가 생성된 후에는 스토리지를 줄이는 것은 불가능하고, 스토리지 확장만 가능합니다. 저렴한 비용으로 사용하려면 초기에 EBS를 작게 설정하고, 디스크를 확장해서 사용하는 것을 추천합니다. 브로커 EBS 스토리지를 자동 확장하도록 Auto Scaling 구성이 가능합니다.
- Configuration에서 Cluster Configuration은 MSK default configuration으로 설정합니다. Custom Configuration 적용이 필요하다면 MSK Custom Configuration을 참고해주세요.

STEP 2. Networking
- MSK 브로커를 배포할 VPC, Zone, Subnet을 설정합니다.
- VPC는 MSK 브로커를 배포할 VPC를 지정합니다. 클러스터를 생성한 후에는 변경 불가합니다.
- Zone은 Step 1에서 Zone을 2개로 설정해서 First zone, Second zone 설정만 가능합니다.
- Public access에서 기본적으로 브로커는 클러스터의 VPC 내부에서만 접근할 수 있습니다.
- Security groups in Amazon EC2는 클러스터의 ENI에 할당할 보안 그룹을 선택합니다.

Step 3. Security
- Access control methods는 MSK가 클라이언트를 인증하고 작업을 허용하거나 거부하는데 사용할 방법을 설정합니다. 클러스터에는 하나 이상의 방법을 선택 가능하며, 선택한 방법에 따라 선택할 수 있는 암호화 옵션을 결정합니다.
- Unauthenticated access는 클라이언트에 대한 인증이 필요하지 않으며 모든 작업이 허용됩니다.
- SASL/SCRAM authentication을 선택하면 SCRAM은 SASL 프레임워크를 사용하여 사용자 이름 및 암호 인증 방법을 제공합니다. Amazon MSK는 AWS Secrets Manager를 사용하여 SASL/SCRAM을 활성화할 수 있습니다.
- Encryption에서 Between clients and brokers 암호화를 체크하면 TLS encryption과 IAM, SASL/SCRAM에서 TLS 암호화를 사용합니다.
- Plaintext를 체크하면 SASL/SCRAM 또는 IAM 액세스 제어 방법에서는 Plaintext로 트래픽 전송이 불가능합니다.
- 클러스터 내에서는 TLS 암호화를 사용하게 됩니다.
- Encrypt data at rest (저장 데이터 암호화)에서 MSK는 AWS KMS(Key Management System) 키를 사용하여 저장 데이터를 암호화합니다. Use AWS managed key를 체크하면 Amazon MSK에서 사용자를 대신하여 생성, 관리 및 사용하는 계정의 KMS 키를 사용합니다.

Step 4. Monitoring and tags
개발 환경에서 최대한 테스트하기 위해 여러가지 모니터링 옵션을 사용하였습니다.
- Amazon CloudWatch metrics for this cluster에서는 모니터링 수준을 선택할 수 있습니다. Enhanced partition-level monitoring은 향상된 브로커 수준 모니터링 및 주제 수준 모니터링이 포함되며 추가 비용으로 이용할 수 있습니다.
- Open monitoring with Prometheus에서 Enable open monitoring with Prometheus 체크합니다. Prometheus는 시계열 메트릭 데이터를 위한 오픈 소스 모니터링 시스템으로서 활성화를 하면 JMX Exporter, Node Exporter를 사용하여 메트릭을 노출할 수 있습니다. Prometheus 모니터링은 무료로 제공되지만 데이터 전송에는 요금이 부과됩니다.
- Prometheus exporters에서 JMS Exporter 체크하면 Apache Kafka JMX 메트릭을 노출합니다. Node Exporter 체크하면 CPU 및 디스크 메트릭을 노출합니다.
- Broker log delivery에서 MSK에 문제가 있는 경우 AWS에 문의하려면 로그 저장이 필요합니다. 비용이 많이 들지 않으므로 CloudWatch Logs 또는 S3에 로그를 저장합니다. CloudWatch Log에 저장하려면 Deliver to Amazon CloudWatch Logs를 체크하고 CloudWatch Log group을 생성하고 선택해주세요.

MSK 클러스터 생성 확인
AWS 가이드 문서에서는 MSK 클러스터 생성에 15분 정도 시간이 소요된다고 나와 있지만 실제로는 약 30분 정도 소요되었습니다. 잠시 커피 한 잔 드시고 오셔서 확인해보면 짜잔~ MSK 클러스터가 생성되었습니다.
생성된 MSK 클러스터에서 View client Information 정보를 클릭해보겠습니다.

Bootstrap server들의 인증 타입별로 private endpoint 정보, Zookeeper 노드에 대한 endpoint 정보를 확인할 수 있습니다.

클라이언트 머신 생성 및 테스트
클라이언트 머신 생성이란 MSK 클러스터와 통신해서 제어할 수 있는 관리 노드인 EC를 생성하고 설정하는 과정입니다.
클라이언트가 MSK 클러스터에 쉽게 연결할 수 있도록 MSK 클러스터와 연결에 VPC에 EC2를 생성합니다. AWS에 사용 경험이 있다고 가정하고 EC2를 생성하는 과정은 생략하도록 하겠습니다.
EC2에 Apache Kafka 클라이언트 라이브러리 및 도구를 설치합니다.
https://gist.github.com/jhhwang4195/9888e257d5044f1eb37e78dfa49371e9#file-msk_client-sh
카프카 토픽(MSKTutorialTopic) 생성에서는 비용을 최소로 사용하기 위해 AZ 2개에 각각 브로커가 1개로 생성되어 총 브로커 수는 2개이므로 replication-factor는 2로 설정하였습니다.
ZookeeperConnectString은 클러스터가 생성된 이후 확인한 Zookeeper endpoint 정보를 입력하시면 됩니다.
Kafka Producer & Consumer 테스트
이제 생성된 토픽(MSKTutorialTopic)에 데이터를 생성하고 소비하는 과정을 kafka에서 제공하는 스크립트를 통해 확인해보도록 해보겠습니다.
Apache kafka가 설치된 디렉토리로 이동하여 client.properties 파일을 생성하고 내용을 입력합니다.
security.protocol=PLAINTEXT
토픽에 프로듀싱하기 위해서는 kafka-console-producer.sh 스크립트를 사용해서 확인할 수 있습니다.
./kafka-console-producer.sh --broker-list BootstrapBrokerString --producer.config client.properties --topic MSKTutorialTopic
전송하기 위한 메시지를 입력하고 Enter를 입력합니다. 메시지 입력 및 Enter를 입력할 때마다 메시지가 전송됩니다.
새로운 터미널을 사용하여 EC2(클라이언트 머신)에 ssh로 접속하고 kafka가 설치된 디렉토리로 이동합니다.
./kafka-console-consumer.sh --bootstrap-server BootstrapBrokerString --consumer.config client.properties --topic MSKTutorialTopic --from-beginning
실제로 테스트했던 명령과 결과를 참고하시면 좀 더 이해가 쉬울 것 같습니다.
https://gist.github.com/jhhwang4195/fd8c6222020161f407e5cfbbe7e2749b
MSK 성능 테스트
최소 사양으로 구성한 MSK 클러스터에서 성능 테스트를 진행해볼까요?
Apache Kafka를 설치하면 기본적으로 성능을 측정할 수 있는 스크립트를 제공해줍니다. 아래 스크립트를 사용하여 성능을 테스트해보겠습니다.
- kafka-producer-perf-test.sh
- kafka-consumer-perf-test.sh
MSK 클러스터 사양 및 성능 테스트 조건
- t3.small (2core, 2GB RAM)
- t 시리즈 인스턴스는 CPU 사용량을 버스트할 수 있는 기능으로 인해 정확한 성능은 측정할 수 없습니다.
성능 테스트를 진행하면서 사용했던 명령어 및 결과입니다.

https://gist.github.com/jhhwang4195/b0d7e9927db3af63e5bcce1b1ffbe7fb#file-msk_performance_test-sh
성능 테스트에 관한 결과를 분석해볼까요?
브로커 인스턴스 타입에 따라 throughput이 제한되어 있어서 레코드 크기에 따라 차이가 있는 것을 볼 수 있습니다. 프로듀서 결과를 보면 record-size 1,000인 경우 초당 약 70,000개의 레코드가 처리되는 것을 확인할 수 있습니다. 컨슈머 결과를 보면 record-size 1,000인 경우 초당 약 100,000개의 레코드가 처리되는 것을 확인할 수 있었습니다. record-size가 10,000인 경우에도 약 5천 개의 레코드를 처리할 수 있는 것으로 확인하였고, 개발 환경에서 사용하는 데 큰 무리는 없을 것 같습니다.
SASL/SCRAM 인증 설정
MSK 클러스터를 생성할 때 보안 설정 옵션에 대해 다시 살펴볼까요?

보안 및 운영을 고려하면 인증은 중요한 사항이며 다양한 팀에서 수많은 개발자가 사용하다 보면 보안은 더욱 중요해지게 됩니다.
실제로 개발에서는 Plaintext를 사용하지 않고 MSK에 대한 사용자 이름 및 암호 인증은 SASL/SCRAM(Simple Authentication and Security Layer/Salted Challenge Response Mechanism)를 사용하였습니다. MSK는 AWS Secrets Manager를 사용하여 SASL/SCRAM을 활성화가 가능하며 클러스터를 생성한 후 secrets를 연결할 수 있습니다. 또한 SASL/SCRAM 인증을 설정하면 클라이언트와 브로커 사이에는 데이터 전송 시 TLS 암호화를 사용합니다. Secret Manager에는 사용자 자격 증명을 저장해야 하며 Secret Name은 AmazonMSK_ 접두어로 시작되어야 합니다.

MSK에서는 Secrets Manager로부터 secrets를 연결할 수가 있습니다. 실제로 연결되면 AWS Console → MSK 클러스터 선택 → Properties → Security settings에서 확인할 수 있습니다.

MSK를 구축하면서 제일 어려웠던 부분이 SASL/SCRAM 인증이었습니다. SASL/SCRAM 인증을 사용하면 MSK 설정하는 절차가 복잡해지고, 운영 및 관리에 복잡해집니다. 개발자들도 개발 시 SASL/SCRAM 인증이 필요하며, 다음 파트에서 살펴볼 모니터링에서도 인증 때문에 수많은 이슈가 발생하였습니다. SASL/SCRAM 문서에 설명이 있지만 텍스트로만 설명되어 있어서 어려웠습니다. 잘 안되는 경우 실수로 빠뜨린 절차가 없는지 꼼꼼하게 확인이 필요합니다.
Producer & Consumer 샘플 코드
Producer, Consumer는 Java 8로 진행했으며 라이브러리는 Apache Kafka Client 2.6.2 Library를 사용해서 진행하였습니다. 앞에서 말씀드린 것처럼 실제로 개발에서는 Kafka 인증은 Plaintext를 사용하지 않고, SASL/SCRAM 방식의 인증을 사용하고 있습니다. 실제로 업무를 진행하면서 개발자들에게 제일 문의가 많았던 부분은 SASL/SCRAM 인증이었습니다. 소스 코드에서 SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG의 kafka.client.truststore.jks 파일 생성은 여기를 참고해주세요.
Gradle 설정 (build.gradle)
https://gist.github.com/jhhwang4195/fe06da1c9199c9b18d6021bcc4c113ac#file-build-gradle
Kafka Producer
https://gist.github.com/jhhwang4195/78910d9bef2feb39100774804bb7a757#file-kafka_producer-java
Kafka Consumer
https://gist.github.com/jhhwang4195/267b5a6ef46e587372d5cdb701bbdddb#file-kafka_consumer-java
마치며
이번 글에서는 MSK 클러스터를 생성하는 과정에 대해서 살펴보았습니다.
MSK 클러스터 생성 후에는 클러스터 이름, 클러스터의 AZ개수, VPC는 변경할 수가 없으므로 주의해서 생성하셔야 합니다. 또한 클러스터가 생성된 후에는 스토리지를 줄이는 것은 불가능하며 스토리지 확장만 가능합니다. 비용을 저렴하게 사용하려면 초기에 EBS를 작게 설정하고, 디스크를 확장해서 사용하는 것이 좋습니다.
MSK 클러스터와 통신해서 제어할 수 있는 관리 노드인 EC2를 생성하여 설정하는 과정을 살펴보았고, Kafka를 설치하면 제공되는 스크립트를 사용하여 토픽 생성, Producer, Consumer를 테스트해보았습니다. MSK 클러스터 생성 시 비용을 최소화하기 위해 브로커 유형은 t3.small을 사용하고, AZ는 2개, AZ마다 브로커는 1개로 설정하였습니다. (한 달에 약 85.35 USD 비용이 발생합니다) 최소 사양으로 구성한 MSK 클러스터에서 성능 테스트를 진행한 결과에 대해서도 살펴보았습니다.
마지막으로 자바를 이용하여 Producer, Consumer 코드도 간단하게 살펴보았습니다.
AWS MSK PART 3 — 모니터링을 구축해볼까요? 에서는 모니터링에 대해서 살펴보도록 하겠습니다.
여기어때 서비스를 발전시키고 함께 성장하고 싶으신 개발자분들 많은 지원 부탁드릴게요!
끝까지 읽어주셔서 감사합니다.