자습서: 개발을 위한 Apache Kafka 서비스 만들기 및 사용

Azure Container Apps를 사용하면 개발 및 프로덕션 등급 서비스에 연결하여 애플리케이션에 다양한 기능을 제공할 수 있습니다.

이 자습서에서는 개발 Apache Kafka 서비스를 만들고 사용하는 방법을 알아봅니다.

이 자습서에서는 Azure CLI 명령과 Bicep 템플릿 조각을 소개합니다. Bicep을 사용하는 경우 모든 조각을 단일 Bicep 파일에 추가하고 템플릿을 모두 한 번에 배포할 수 있습니다.

  • 서비스 및 컨테이너 앱을 배포하기 위한 Container Apps 환경 만들기
  • Apache Kafka 서비스 만들기
  • 개발 Apache Kafka 서비스를 사용하도록 명령줄 앱 설정
  • kafka-ui 앱을 배포하여 애플리케이션 데이터 보기
  • 일관되고 예측 가능한 템플릿 배포를 사용하여 모든 리소스를 배포하는 최종 bicep 템플릿을 컴파일합니다.
  • 모든 리소스의 하나의 명령 배포에 azd 템플릿 사용

필수 조건

참고 항목

단일 명령 배포의 경우 마지막 azd 템플릿 단계로 건너뜁니다.

설정

  1. 공통 값에 대한 변수를 정의합니다.

    RESOURCE_GROUP="kafka-dev"
    LOCATION="northcentralus"
    ENVIRONMENT="aca-env"
    KAFKA_SVC="kafka01"
    KAFKA_CLI_APP="kafka-cli-app"
    KAFKA_UI_APP="kafka-ui-app"
    
  2. Azure에 로그인합니다.

    az login
    
  3. CLI를 최신 버전으로 업그레이드합니다.

    az upgrade
    
  4. Bicep을 최신 버전으로 업그레이드합니다.

    az bicep upgrade
    
  5. containerapp 확장자를 추가합니다.

    az extension add --name containerapp --upgrade
    
  6. 필수 네임스페이스를 등록합니다.

    az provider register --namespace Microsoft.App
    
    az provider register --namespace Microsoft.OperationalInsights
    

컨테이너 앱 환경 만들기

  1. 리소스 그룹을 만듭니다.

    az group create \
        --name "$RESOURCE_GROUP" \
        --location "$LOCATION"
    
  2. 컨테이너 앱 환경을 만듭니다.

    az containerapp env create \
      --name "$ENVIRONMENT" \
      --resource-group "$RESOURCE_GROUP" \
      --location "$LOCATION"
    

Apache Kafka 서비스 만들기

  1. Apache Kafka 서비스를 만듭니다.

    ENVIRONMENT_ID=$(az containerapp env show \
      --name "$ENVIRONMENT" \
      --resource-group "$RESOURCE_GROUP" \
      --output tsv \
      --query id)
    
  2. 템플릿을 배포합니다.

        az containerapp add-on kafka create \
        --name "$KAFKA_SVC" \
        --resource-group "$RESOURCE_GROUP" \
        --environment "$ENVIRONMENT"
    
  3. Kafka 인스턴스에서 로그 출력 보기

    로그 메시지를 보려면 logs 명령을 사용합니다.

    az containerapp logs show \
        --name $KAFKA_SVC \
        --resource-group $RESOURCE_GROUP \
        --follow --tail 30
    

    컨테이너 앱 Kafka 서비스 로그의 스크린샷.

서비스를 테스트하기 위한 앱 만들기

앱을 만들 때 ./kafka-topics.sh, ./kafka-console-producer.shkafka-console-consumer.sh를 사용하여 Kafka 인스턴스에 연결하도록 설정합니다.

  1. Kafka 서비스에 바인딩되는 kafka-cli-app 앱을 만듭니다.

    az containerapp create \
        --name "$KAFKA_CLI_APP" \
        --image mcr.microsoft.com/k8se/services/kafka:3.4 \
        --bind "$KAFKA_SVC" \
        --environment "$ENVIRONMENT" \
        --resource-group "$RESOURCE_GROUP" \
        --min-replicas 1 \
        --max-replicas 1 \
        --command "/bin/sleep" "infinity"
    
  2. CLI exec 명령을 실행하여 테스트 앱에 연결합니다.

    az containerapp exec \
        --name $KAFKA_CLI_APP \
        --resource-group $RESOURCE_GROUP \
        --command /bin/bash
    

    테스트 앱에서 --bind 또는 serviceBinds를 사용하면 연결 정보가 애플리케이션 환경에 삽입됩니다. 테스트 컨테이너에 연결하면 env 명령을 사용하여 값을 검사할 수 있습니다.

    env | grep "^KAFKA_"
    
    KAFKA_SECURITYPROTOCOL=SASL_PLAINTEXT
    KAFKA_BOOTSTRAPSERVER=kafka01:9092
    KAFKA_HOME=/opt/kafka
    KAFKA_PROPERTIES_SASL_JAAS_CONFIG=org.apache.kafka.common.security.plain.PlainLoginModule required username="kafka-user" password="7dw..." user_kafka-user="7dw..." ;
    KAFKA_BOOTSTRAP_SERVERS=kafka01:9092
    KAFKA_SASLUSERNAME=kafka-user
    KAFKA_SASL_USER=kafka-user
    KAFKA_VERSION=3.4.0
    KAFKA_SECURITY_PROTOCOL=SASL_PLAINTEXT
    KAFKA_SASL_PASSWORD=7dw...
    KAFKA_SASLPASSWORD=7dw...
    KAFKA_SASL_MECHANISM=PLAIN
    KAFKA_SASLMECHANISM=PLAIN
    
  3. kafka-topics.sh를 사용하여 이벤트 토픽을 만듭니다.

    kafka.props 파일을 만듭니다.

    echo "security.protocol=$KAFKA_SECURITY_PROTOCOL" >> kafka.props && \
    echo "sasl.mechanism=$KAFKA_SASL_MECHANISM" >> kafka.props && \
    echo "sasl.jaas.config=$KAFKA_PROPERTIES_SASL_JAAS_CONFIG" >> kafka.props
    

    quickstart-events 이벤트 토픽을 만듭니다.

    /opt/kafka/bin/kafka-topics.sh \
        --create --topic quickstart-events \
        --bootstrap-server $KAFKA_BOOTSTRAP_SERVERS \
        --command-config kafka.props
    # Created topic quickstart-events.
    
    /opt/kafka/bin/kafka-topics.sh \
        --describe --topic quickstart-events \
        --bootstrap-server $KAFKA_BOOTSTRAP_SERVERS \
        --command-config kafka.props
    # Topic: quickstart-events	TopicId: lCkTKmvZSgSUCHozhhvz1Q	PartitionCount: 1	ReplicationFactor: 1	Configs: segment.bytes=1073741824
    # Topic: quickstart-events	Partition: 0	Leader: 1	Replicas: 1	Isr: 1
    
  4. kafka-console-producer.sh를 사용하여 토픽에 이벤트를 작성합니다.

    /opt/kafka/bin/kafka-console-producer.sh \
        --topic quickstart-events \
        --bootstrap-server $KAFKA_BOOTSTRAP_SERVERS \
        --producer.config kafka.props
    
    > this is my first event
    > this is my second event
    > this is my third event
    > CTRL-C
    

    참고 항목

    ./kafka-console-producer.sh 명령은 >를 사용하여 이벤트를 작성하라는 메시지를 표시합니다. 표시된 대로 일부 이벤트를 작성한 다음, CTRL-C를 눌러 종료합니다.

  5. kafka-console-consumer.sh를 사용하여 토픽에서 이벤트를 읽습니다.

    /opt/kafka/bin/kafka-console-consumer.sh \
         --topic quickstart-events \
        --bootstrap-server $KAFKA_BOOTSTRAP_SERVERS \
        --from-beginning \
        --consumer.config kafka.props
    
    # this is my first event
    # this is my second event
    # this is my third event
    

컨테이너 앱 kafka CLI 출력 로그의 스크린샷.

기존 앱과 함께 개발 서비스 사용

Apache Kafka를 사용하는 앱이 이미 있는 경우 연결 정보를 로드하는 방법을 변경할 수 있습니다.

먼저 다음 환경 변수를 만듭니다.

KAFKA_HOME=/opt/kafka
KAFKA_PROPERTIES_SASL_JAAS_CONFIG=org.apache.kafka.common.security.plain.PlainLoginModule required username="kafka-user" password="7dw..." user_kafka-user="7dw..." ;
KAFKA_BOOTSTRAP_SERVERS=kafka01:9092
KAFKA_SASL_USER=kafka-user
KAFKA_VERSION=3.4.0
KAFKA_SECURITY_PROTOCOL=SASL_PLAINTEXT
KAFKA_SASL_PASSWORD=7dw...
KAFKA_SASL_MECHANISM=PLAIN

CLI(또는 Bicep)를 사용하면 앱을 업데이트하여 개발 서비스를 사용하도록 --bind $KAFKA_SVC를 추가할 수 있습니다.

개발 서비스에 바인딩

kafka-ui를 배포하여 Kafka 인스턴스를 보고 관리합니다.

Bicep 또는 azd 예를 참조하세요.

Kafka 서비스에 연결하는 pgweb 컨테이너 앱의 스크린샷.

모든 리소스 배포

모든 리소스를 한 번에 배포하려면 다음 예를 사용합니다.

Bicep

다음 Bicep 템플릿에는 이 자습서의 모든 리소스가 포함되어 있습니다.

이 콘텐츠로 kafka-dev.bicep 파일을 만들 수 있습니다.

targetScope = 'resourceGroup'
param location string = resourceGroup().location
param appEnvironmentName string = 'aca-env'
param kafkaSvcName string = 'kafka01'
param kafkaCliAppName string = 'kafka-cli-app'
param kafkaUiAppName string = 'kafka-ui'

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: '${appEnvironmentName}-log-analytics'
  location: location
  properties: {
    sku: {
      name: 'PerGB2018'
    }
  }
}

resource appEnvironment 'Microsoft.App/managedEnvironments@2023-04-01-preview' = {
  name: appEnvironmentName
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalytics.properties.customerId
        sharedKey: logAnalytics.listKeys().primarySharedKey
      }
    }
  }
}

resource kafka 'Microsoft.App/containerApps@2023-04-01-preview' = {
  name: kafkaSvcName
  location: location
  properties: {
    environmentId: appEnvironment.id
    configuration: {
      service: {
          type: 'kafka'
      }
    }
  }
}

resource kafkaCli 'Microsoft.App/containerApps@2023-04-01-preview' = {
  name: kafkaCliAppName
  location: location
  properties: {
    environmentId: appEnvironment.id
    template: {
      serviceBinds: [
        {
          serviceId: kafka.id
        }
      ]
      containers: [
        {
          name: 'kafka-cli'
          image: 'mcr.microsoft.com/k8se/services/kafka:3.4'
          command: [ '/bin/sleep', 'infinity' ]
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 1
      }
    }
  }
}

resource kafkaUi 'Microsoft.App/containerApps@2023-04-01-preview' = {
  name: kafkaUiAppName
  location: location
  properties: {
    environmentId: appEnvironment.id
    configuration: {
      ingress: {
        external: true
        targetPort: 8080
      }
    }
    template: {
      serviceBinds: [
        {
          serviceId: kafka.id
          name: 'kafka'
        }
      ]
      containers: [
        {
          name: 'kafka-ui'
          image: 'docker.io/provectuslabs/kafka-ui:latest'
          command: [
            '/bin/sh'
          ]
          args: [
            '-c'
            '''export KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS="$KAFKA_BOOTSTRAP_SERVERS" && \
            export KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG="$KAFKA_PROPERTIES_SASL_JAAS_CONFIG" && \
            export KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM="$KAFKA_SASL_MECHANISM" && \
            export KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL="$KAFKA_SECURITY_PROTOCOL" && \
            java $JAVA_OPTS -jar kafka-ui-api.jar'''
          ]
          resources: {
            cpu: json('1.0')
            memory: '2.0Gi'
          }
        }
      ]
    }
  }
}

output kafkaUiUrl string = 'https://${kafkaUi.properties.configuration.ingress.fqdn}'

output kafkaCliExec string = 'az containerapp exec -n ${kafkaCli.name} -g ${resourceGroup().name} --command /bin/bash'

output kafkaLogs string = 'az containerapp logs show -n ${kafka.name} -g ${resourceGroup().name} --follow --tail 30'

Azure CLI를 사용하여 템플릿을 배포합니다.

RESOURCE_GROUP="kafka-dev"
LOCATION="northcentralus"

az group create \
    --name "$RESOURCE_GROUP" \
    --location "$LOCATION"

az deployment group create -g $RESOURCE_GROUP \
    --query 'properties.outputs.*.value' \
    --template-file kafka-dev.bicep

Azure 개발자 CLI

최종 템플릿은 GitHub에서 사용할 수 있습니다.

azd up을 사용하여 템플릿을 배포합니다.

git clone https://github.com/Azure-Samples/aca-dev-service-kafka-azd
cd aca-dev-service-kafka-azd
azd up

리소스 정리

완료되면 다음 명령을 실행하여 Container Apps 리소스가 포함된 리소스 그룹을 삭제합니다.

주의

다음 명령은 지정된 리소스 그룹과 그 안에 포함된 모든 리소스를 삭제합니다. 지정된 리소스 그룹에 이 자습서의 범위에 속하지 않는 리소스가 포함된 경우 해당 리소스도 삭제됩니다.

az group delete \
    --resource-group $RESOURCE_GROUP