토리맘의 한글라이즈 프로젝트 logo 토리맘의 한글라이즈 프로젝트

스프링 클라우드 데이터 플로우 공식 레퍼런스를 한글로 번역한 문서입니다.

전체 목차는 여기에 있습니다.


스프링 부트를 사용하면 툴이나 문서를 만들때 이용하는 애플리케이션의 설정 프로퍼티에 관한 메타데이터를 executable jar 안에 번들링할 수 있다. 이 섹션에선 애플리케이션 설정 메타데이터를 컨테이너 이미지의 레이블로 제공하는 방법을 포함해서, Data Flow와 함께 사용할 애플리케이션을 구성하고 빌드하는 방법에 대해 설명한다.

자체 애플리케이션을 만들 때는, spring-boot-configuration-processor 라이브러리를 사용하면 @ConfigurationProperties 어노테이션을 선언한 클래스로 애플리케이션 설정 메타데이터를 쉽게 생성할 수 있다. 이 라이브러리에는 자바 어노테이션 프로세서가 들어있다. 프로젝트를 컴파일하면 이 프로세서를 호출해서 설정 메타데이터 파일을 생성하며, 이 파일은 uber-jar 안에 META-INF/spring-configuration-metadata.json으로 저장된다.

설정 프로세서를 사용하려면 애플리케이션의 pom.xml에 아래 의존성을 추가해라:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

목차


Exposing Application Properties for Data Flow

스트림, 태스크 애플리케이션들은 부트 공통 애플리케이션 프로퍼티Data Flow에서 사용하는 공통 프로퍼티, 그리고 애플리케이션 의존성에 포함된 다른 프로퍼티들도 함께 제공하는 스프링 부트 애플리케이션이다. 일반 애플리케이션에선 이 전체 프로퍼티 셋을 모두 사용할 수 있다. 하지만 이 프로퍼티들을 Data Flow 툴에 전부 적용하기엔 사용성 문제가 있다. 그렇기 때문에 Data Flow UI와 쉘에서 애플리케이션 설정 기능을 제공할 땐, 별도 설정 프로퍼티 메타데이터를 사용해서 가장 관련성이 높은 프로퍼티들만 포함시킨다 (디폴트로). 이 메타데이터를 통해 사용 가능한 프로퍼티들을 나열해주고, 자동 완성을 처리해주고, 앞 단에서 유효성을 검사하는 등 맥락에 따라 프로퍼티 설정을 도와준다.

Data Flow Configuration Metadata

Data Flow와 가장 관련있는 애플리케이션 프로퍼티들을 정의하려면, 프로젝트 리소스 디렉토리에 META-INF/dataflow-configuration-metadata.properties라는 파일을 생성해라. 이 파일엔 아래 프로퍼티 중 최소 하나는 정의해야 한다:

예제들은 Spring Cloud Stream applications Git 레포지토리에서 많이 찾을 수 있다. 예를 들어 jdbc 싱크의 dataflow-configuration-metadata.properties 파일에는 다음과 같은 설정이 들어있다:

configuration-properties.classes=org.springframework.cloud.fn.consumer.jdbc.JdbcConsumerProperties
configuration-properties.names=\
spring.datasource.url,\
spring.datasource.driver-class-name,\
spring.datasource.username,\
spring.datasource.password,\
spring.datasource.schema,\
spring.datasource.data,\
spring.datasource.initialization-mode

여기서는 싱크에서 사용하는 전용 @ConfigurationProperties와 함께, JDBC 데이터소스 구성에 필요한 몇 가지 표준 spring.datasource 설정 프로퍼티를 노출하고 있다.

Packaging Configuration Metadata

설정 프로퍼티를 executable jar나 컨테이너 이미지로 패키징하는 일반적인 절차는 다음과 같다:

  1. 에서 설명했던 대로 pom.xml에 부트의 설정 프로세서를 추가한다.
  2. 에서 설명한 방법대로 노출하고 싶은 프로퍼티들을 지정한다.
  3. 필요하다면 여기에서 설명하는 방법대로 spring-cloud-app-starter-metadata-maven-plugin을 설정한다.

애플리케이션 메타데이터를 사용해 컨테이너 이미지에 레이블을 생성할 때는 별도로 다음과 같은 절차를 거친다:

  1. 여기에서 설명하는 방법대로 properties-maven-plugin을 설정하고 META-INF/spring-configuration-metadata-encoded.properties를 메이븐 프로퍼티로 로드한다. 이 단계에서 org.springframework.cloud.dataflow.spring.configuration.metadata.json 프로퍼티가 로드될 거다.
  2. 필요하다면 여기에서 설명하는 대로 jib-maven-plugin(또는 docker-maven-plugin) 설정을 확장한다.

Dedicated Metadata Artifacts

uber jar 안에 애플리케이션 메타데이터를 포함시키게 되면, 단순한 메타데이터 점검을 위해 매우 큰 uber jar를 다운받을 수도 있다. 이때 메타데이터가 필요한 Data Flow 작업을 호출하면 눈에 띄게 지연이 발생하기도 한다. 애플리케이션 메타데이터만 가지고 있는 jar를 별도로 생성하면 다음과 같은 면에서 더 좋다:

컨테이너 이미지를 사용하는 환경에선 (ex. 쿠버네티스), Data Flow는 이미지를 다운받을 필요 없이, 설정한 컨테이너 레지스트리에 REST API를 통해 접근해서 메타데이터를 질의한다. 메타데이터 전용 jar도 생성하기로 했다면, Data Flow에서도 이 jar를 사용할 거다.

Creating Metadata Artifacts

spring-cloud-app-starter-metadata-maven-plugin을 사용하면 애플리케이션에 필요한 모든 메타데이터 파일을 쉽게 준비할 수 있다. 메타데이터는 런타임 환경에 따라 별도 컴패니언companion 아티팩트 jar나, 애플리케이션의 컨테이너 이미지 내부에 설정 레이블로 패키징된다. 이 플러그인을 사용하려면 pom.xml에 아래 설정을 추가해라:

<plugin>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-dataflow-apps-metadata-plugin</artifactId>
   <version>1.0.2</version>
   <configuration>
      <storeFilteredMetadata>true</storeFilteredMetadata>
   </configuration>
   <executions>
      <execution>
         <id>aggregate-metadata</id>
         <phase>compile</phase>
         <goals>
            <goal>aggregate-metadata</goal>
         </goals>
      </execution>
   </executions>
</plugin>

이 플러그인은 반드시 spring-configuration-metadata.json 파일을 생성하는 spring-boot-configuration-processor와 함께 사용해야 한다. 둘 모두 설정했는지 다시 한 번 확인해봐라.

참고: 애플리케이션을 적절하게 설정해주면, 스프링 부트 (웬만하면 2.4.1+ 버전 권장) 메이븐 플러그인 build-image goal에서 사용하는 스프링 부트 전용 Cloud Native 빌드팩이 이 메타데이터를 자동으로 설정해준다.

Metadata Jar File

이 플러그인은 uber-jar로 패키징하는 애플리케이션일 때는 메타데이터가 들어있는 컴패니언companion 아티팩트를 생성한다. 구체적으로 말하면, 설정 프로퍼티 메타데이터를 가지고 있는 스프링 부트 JSON 파일과, 앞 섹션에서 설명했던 dataflow 설정 메타데이터 파일이 들어 있다. 아래 예시는 기본 log 싱크의 아티팩트 jar에 들어있는 파일들을 보여준다:

$ jar tvf log-sink-rabbit-3.0.0.BUILD-SNAPSHOT-metadata.jar
373848 META-INF/spring-configuration-metadata.json
   174 META-INF/dataflow-configuration-metadata.properties

spring-cloud-app-starter-metadata-maven-plugin은 바로 사용할 수 있는 애플리케이션 metadata.jar 아티팩트를 생성해준다. 애플리케이션의 pom.xml에 이 플러그인을 반드시 설정해야 한다.

Metadata Container Image Label

spring-cloud-app-starter-metadata-maven-plugin은 컨테이너 이미지로 패키징하는 애플리케이션일 때는, spring-configuration-metadata.json 파일의 내용과 Data Flow에 노출해준 프로퍼티들을 함께 컨테이너 이미지 안에 레이블로 복사한다. 설정 레이블의 키는 org.springframework.cloud.dataflow.spring.configuration.metadata.json을 사용한다. 컨테이너 이미지에 모든 설정 메타데이터가 포함돼 있으므로, 컴패니언companion 아티팩트는 따로 필요하지 않다.

이 플러그인은 컴파일 타임에 org.springframework.cloud.dataflow.spring.configuration.metadata.json이라는 프로퍼티를 딱 하나 가지고 있는 META-INF/spring-configuration-metadata-encoded.properties 파일을 생성한다. 프로퍼티 값에는 노출해준 설정 메타데이터 셋을 문자열로 담고있다. 다음은 전형적인 메타데이터 JSON 파일 예시다:

org.springframework.cloud.dataflow.spring.configuration.metadata.json={\n  \"groups\": [{\n    \"name\": \"log\",\n    \"type\": \"org.springframework.cloud.stream.app.log.sink.LogSinkProperties\",\n    \"sourceType\": \"org.springframework.cloud.stream.app.log.sink.LogSinkProperties\"\n  }],\n  \"properties\": [\n    {\n      \"name\": \"log.expression\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"A SpEL expression (against the incoming message) to evaluate as the logged message.\",\n      \"sourceType\": \"org.springframework.cloud.stream.app.log.sink.LogSinkProperties\",\n      \"defaultValue\": \"payload\"\n    },\n    {\n      \"name\": \"log.level\",\n      \"type\": \"org.springframework.integration.handler.LoggingHandler$Level\",\n      \"description\": \"The level at which to log messages.\",\n      \"sourceType\": \"org.springframework.cloud.stream.app.log.sink.LogSinkProperties\"\n    },\n    {\n      \"name\": \"log.name\",\n      \"type\": \"java.lang.String\",\n      \"description\": \"The name of the logger to use.\",\n      \"sourceType\": \"org.springframework.cloud.stream.app.log.sink.LogSinkProperties\"\n    }\n  ],\n  \"hints\": []\n}

Properties Maven Plugin

이 프로퍼티를 도커 레이블로 바꾸려면, 먼저 properties-maven-plugin을 사용해서 메이븐 프로퍼티로 로드해야 한다:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>properties-maven-plugin</artifactId>
    <version>1.0.0</version>
    <executions>
        <execution>
            <phase>process-classes</phase>
            <goals>
                <goal>read-project-properties</goal>
            </goals>
            <configuration>
                <files>
                    <file>${project.build.outputDirectory}/META-INF/spring-configuration-metadata-encoded.properties</file>
                </files>
            </configuration>
        </execution>
    </executions>
</plugin>

Container Maven Plugin

fabric8:docker-maven-plugin이나 jib 메이븐 플러그인을 사용해서 org.springframework.cloud.dataflow.spring.configuration.metadata.json 프로퍼티를 도커 레이블에 같은 이름으로 삽입해라:

Jib Maven plugin Fabric8 Maven plugin
<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>2.0.0</version>
    <configuration>
        <from>
            <image>springcloud/openjdk</image>
        </from>
        <to>
            <image>springcloudstream/${project.artifactId}</image>
            <tags>
                <tag>3.0.0.BUILD-SNAPSHOT</tag>
            </tags>
        </to>
        <container>
            <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
            <format>Docker</format>
            <labels>
                <org.springframework.cloud.dataflow.spring-configuration-metadata.json>
                    ${org.springframework.cloud.dataflow.spring.configuration.metadata.json}
                </org.springframework.cloud.dataflow.spring-configuration-metadata.json>
            </labels>
        </container>
    </configuration>
</plugin>

주의: docker-maven-plugin 버전은 최소 0.33.0 이상이 필요하다!

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.33.0</version>
    <configuration>
        <images>
            <image>
                <name>springcloudstream/${project.artifactId}:2.1.3.BUILD-SNAPSHOT</name>
                <build>
                    <from>springcloud/openjdk</from>
                    <volumes>
                        <volume>/tmp</volume>
                    </volumes>
                    <labels>
                        <org.springframework.cloud.dataflow.spring-configuration-metadata.json>
                          ${org.springframework.cloud.dataflow.spring.configuration.metadata.json}
                        </org.springframework.cloud.dataflow.spring-configuration-metadata.json>
                    </labels>
                    <entryPoint>
                        <exec>
                            <arg>java</arg>
                            <arg>-jar</arg>
                            <arg>/maven/log-sink-kafka.jar</arg>
                        </exec>
                    </entryPoint>
                    <assembly>
                        <descriptor>assembly.xml</descriptor>
                    </assembly>
                </build>
            </image>
        </images>
    </configuration>
</plugin>

Using Application Metadata

애플리케이션 설정 메타데이터를 만들었다면 (별도 컴패니언companion 아티팩트 혹은 애플리케이션 컨테이너 이미지에 설정 레이블로 임베딩), 몇 가지 설정을 추가해서 Data Flow가 메타데이터를 찾을 수 있는 위치를 알려줘야 할 수 있다.

Using Metadata Jar files

app register 명령어로 단일 앱을 등록할 때는, 다음과 같이 쉘의 --metadata-uri 옵션을 사용하면 된다:

dataflow:>app register --name log --type sink
    --uri maven://org.springframework.cloud.stream.app:log-sink:2.1.0.RELEASE
    --metadata-uri maven://org.springframework.cloud.stream.app:log-sink:jar:metadata:2.1.0.RELEASE

app import 명령어로 파일을 등록할 때는, 파일에 <type>.<name> 라인마다 별도로 <type>.<name>.metadata 라인도 적어줘야 한다. 엄밀히 말하면 선택 사항이긴 하지만 (메타데이터를 선언한 앱과 선언하지 않은 앱이 같이 있어도 잘 동작한다), 베스트 프랙티스는 모두 선언해주는 거다.

다음은 메타데이터 아티팩트를 메이븐 레포지토리로 호스팅하는 uber jar 앱의 예시다 (http://file://을 통해 가져올 때도 똑같이 작성해주면 된다).

source.http=maven://org.springframework.cloud.stream.app:log-sink:2.1.0.RELEASE
source.http.metadata=maven://org.springframework.cloud.stream.app:log-sink:jar:metadata:2.1.0.RELEASE

Using Metadata Container Image Labels

app register 명령어로 단일 도커 앱을 등록할 때는, Data Flow 서버가 자동으로 설정 레이블 org.springframework.cloud.dataflow.spring-configuration-metadata.json에서 메타데이터를 확인한다:

dataflow:>app register --name log --type sink --uri container:springcloudstream/log-sink-rabbit:2.1.13.RELEASE

필요한 설정은 사용하는 컨테이너 레지스트리 provider나 인스턴스에 따라 다르다.

시크릿을 볼륨으로 마운트해서 쓰는 private 컨테이너 레지스트리에선, 이 시크릿을 통해 레지스트리 설정을 자동으로 유추한다. spring.cloud.dataflow.container.registry-configurations 하위 프로퍼티로는 다음과 같이 다양한 컨테이너 레지스트리 설정을 명시할 수 있다:

Container Registry Support

기본적으로 Harbor, Arifactory/JFrog, Amazon ECR, Azure Container Registry와 같은 다양한 온클라우드on-cloud 및 온프레미스on-premise 컨테이너 레지스트리에 연결할 수 있으며, 자체 private 레지스트리를 호스팅할 수도 있다.

레지스트리마다 인증 스키마가 다를 수 있으므로, 이어지는 섹션에선 레지스트리별로 필요한 세부 설정 정보를 설명한다:

Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[default].registry-host=registry-1.docker.io
- spring.cloud.dataflow.container.registry-configurations[default].authorization-type=dockeroauth2
- spring.cloud.dataflow.container.registry-configurations[default].extra[registryAuthUri]=https://auth.docker.io/token?service=registry.docker.io&scope=repository:{repository}:pull&offline_token=1&client_id=shell
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          default:
            registry-host: registry-1.docker.io
            authorization-type: dockeroauth2
            extra:
              'registryAuthUri': 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:{repository}:pull&offline_token=1&client_id=shell'

이미지 이름에 레지스트리 호스트 프리픽스를 제공하지 않으면 이 레지스트리를 디폴트로 사용한다. public 도커허브 레포지토리에선 username과 password 인증이 필요하지 않지만, private 도커허브 레포지토리에는 credential이 필요하다.

Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[harbor].registry-host=demo.goharbor.io
- spring.cloud.dataflow.container.registry-configurations[harbor].authorization-type=dockeroauth2
- spring.cloud.dataflow.container.registry-configurations[harbor].user=admin
- spring.cloud.dataflow.container.registry-configurations[harbor].secret=Harbor12345
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          harbor:
            registry-host: demo.goharbor.io
            authorization-type: dockeroauth2
            user: admin
            secret: Harbor12345

Harbor 레지스트리 설정은 도커허브와 유사하게 OAuth2 토큰 인증을 사용하지만, registryAuthUri는 조금 달라진다. registryAuthUri는 이후 부트스트랩할 때 자동으로 리졸브되지만, 다음과 같이 재정의해도 된다:

Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[harbor].extra[registryAuthUri]=https://demo.goharbor.io/service/token?service=harbor-registry&scope=repository:{repository}:pull
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          harbor:
            extra:
              'registryAuthUri': https://demo.goharbor.io/service/token?service=harbor-registry&scope=repository:{repository}:pull
Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[myjfrog].registry-host=springsource-docker-private-local.jfrog.io
- spring.cloud.dataflow.container.registry-configurations[myjfrog].authorization-type=basicauth
- spring.cloud.dataflow.container.registry-configurations[myjfrog].user=[artifactory user]
- spring.cloud.dataflow.container.registry-configurations[myjfrog].secret=[artifactory encrypted password]
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          myjfrog:
            registry-host: springsource-docker-private-local.jfrog.io
            authorization-type: basicauth
            user: [artifactory user]
            secret: [artifactory encrypted password]

참고: JFrog에선 암호화된 Password를 생성해야 한다.

Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[myecr].registry-host=283191309520.dkr.ecr.us-west-1.amazonaws.com
- spring.cloud.dataflow.container.registry-configurations[myecr].authorization-type=awsecr
- spring.cloud.dataflow.container.registry-configurations[myecr].user=[your AWS accessKey]
- spring.cloud.dataflow.container.registry-configurations[myecr].secret=[your AWS secretKey]
- spring.cloud.dataflow.container.registry-configurations[myecr].extra[region]=us-west-1
- spring.cloud.dataflow.container.registry-configurations[myecr].extra[registryIds]=283191309520
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          myecr:
            registry-host: 283191309520.dkr.ecr.us-west-1.amazonaws.com
            authorization-type: awsecr
            user: [your AWS accessKey]
            secret: [your AWS secretKey]
            extra:
              region: us-west-1
              'registryIds': 283191309520

credential 외에도, 별도 프로퍼티로 레지스트리의 region을 제공해야 한다 (ex. .extra[region]=us-west-1). 필요하다면 .extra[registryIds] 프로퍼티는 여러 레지스트리 ID를 콤마로 구분해서 설정할 수 있다.

Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[myazurecr].registry-host=tzolovazureregistry.azurecr.io
- spring.cloud.dataflow.container.registry-configurations[myazurecr].authorization-type=basicauth
- spring.cloud.dataflow.container.registry-configurations[myazurecr].user=[your Azure registry username]
- spring.cloud.dataflow.container.registry-configurations[myazurecr].secret=[your Azure registry access password]
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          myazurecr:
            registry-host: tzolovazureregistry.azurecr.io
            authorization-type: basicauth
            user: [your Azure registry username]
            secret: [your Azure registry access password]

Customizations

프로퍼티를 사용해서 레지스트리 시크릿을 통해 가져온 설정을 재정의하거나 보강할 수 있다. 예를 들어, my-private-registry:5000에서 실행 중인 레지스트리에 액세스하기 위한 시크릿을 생성해뒀다면, 다음과 같이 이 레지스트리에 대한 SSL 검증을 비활성화할 수 있다:

Java properties Yaml
- spring.cloud.dataflow.container.registry-configurations[myregistry].registry-host=my-private-registry:5000
- spring.cloud.dataflow.container.registry-configurations[myregistry].disableSslVerification=true
spring:
  cloud:
    dataflow:
      container:
        registry-configurations:
          myregistry:
            registry-host: my-private-registry:5000
            disableSslVerification: true

자체 서명self-signed 인증서로 레지스트리를 테스트할 때 유용할 거다.

미리 프록시를 구성해뒀다면, 일부 레지스트리 설정을 리다이렉트할 수 있다. 예를 들어, my-proxy.test:8080에 설정해둔 프록시를 통해 my-private-registry:5000에서 실행 중인 레지스트리에 액세스한다면:

Java properties Yaml
- spring.cloud.dataflow.container.http-proxy.host=my-proxy.test
- spring.cloud.dataflow.container.http-proxy.port=8080
- spring.cloud.dataflow.container.registry-configurations[myregistrywithproxy].registry-host=my-proxy-registry:5000
- spring.cloud.dataflow.container.registry-configurations[myregistrywithproxy].use-http-proxy=true
spring:
  cloud:
    dataflow:
      container:
        httpProxy:
          host: my-proxy.test
          port: 8080
        registry-configurations:
          myregistrywithproxy:
            registry-host: my-proxy-registry:5000
            use-http-proxy: true

spring.cloud.dataflow.container.http-proxy 프로퍼티를 사용하면 글로벌 Http 프록시를 구성할 수 있으며, 원하는 레지스트리 설정에 use-http-proxy 프로퍼티를 지정해서 프록시를 사용하도록 만들 수 있다. 기본적으로는 프록시를 사용하지 않는다.


전체 목차는 여기에 있습니다.

<< >>

TOP