3.7. 관찰 기능 구성


OpenShift Dev Spaces 관찰 기능을 구성하려면 다음을 참조하십시오.

3.7.1. Woopra Telemetry 플러그인

Woopra Telemetry 플러그인 은 Red Hat OpenShift Dev Spaces 설치에서 Segment 및 Woopra로 Telemetry를 전송하도록 빌드된 플러그인입니다. 이 플러그인은 Red Hat에서 호스팅하는 Eclipse Che에서 사용하지만 Red Hat OpenShift Dev Spaces 배포는 이 플러그인을 활용할 수 있습니다. 유효한 Woopra 도메인 및 Segment Write 키 이외의 종속성이 없습니다. plugin.yaml 의 devfile v2에는 플러그인에 전달할 수 있는 4개의 환경 변수가 있습니다.

  • WECDHEPRA_DOMAIN - 이벤트를 보낼 Woopra 도메인입니다.
  • SEGMENT_WRITE_KEY - 이벤트를 Segment 및 Woopra에 보낼 쓰기 키입니다.
  • WECDHEPRA_DOMAIN_ENDPOINT - Woopra 도메인에서 직접 전달하지 않으려면 플러그인은 Woopra 도메인을 반환하는 제공된 HTTP 끝점에서 가져옵니다.
  • SEGMENT_WRITE_KEY_ENDPOINT - Segment 쓰기 키를 직접 전달하지 않으려면 플러그인에서 Segment 쓰기 키를 반환하는 제공된 HTTP 끝점에서 가져옵니다.

Red Hat OpenShift Dev Spaces 설치에서 Woopra 플러그인을 활성화하려면 다음을 수행합니다.

프로세스

  • plugin.yaml devfile v2 파일을 환경 변수가 올바르게 설정된 HTTP 서버에 배포합니다.

    1. CheCluster 사용자 정의 리소스를 구성합니다. 3.1.2절. “CLI를 사용하여 CheCluster 사용자 정의 리소스 구성”을 참조하십시오.

      spec:
        devEnvironments:
          defaultPlugins:
          - editor: eclipse/che-theia/next     1
            plugins:                           2
            - 'https://your-web-server/plugin.yaml'
      1
      원격 분석 플러그인을 설정하는 editorId 입니다.
      2
      Telemetry 플러그인의 devfile v2 정의에 대한 URL입니다.

3.7.2. Telemetry 플러그인 생성

이 섹션에서는 Abstract AnalyticsManager 를 확장하고 다음 메서드를 구현하는 AnalyticsManager 클래스를 생성하는 방법을 설명합니다.

  • IsEnabled() - Telemetry 백엔드가 올바르게 작동하는지 여부를 결정합니다. 이는 항상 true 를 반환하거나 더 복잡한 검사(예: 연결 속성이 누락된 경우 false )를 반환하는 것을 의미할 수 있습니다.
  • destroy() - 원격 분석 백엔드를 종료하기 전에 실행되는 정리 방법입니다. 이 메서드는 WORKSPACE_STOPPED 이벤트를 보냅니다.
  • onActivity() - 일부 활동이 지정된 사용자에게 여전히 발생하고 있음을 알립니다. 이는 주로 WORKSPACE_INACTIVE 이벤트를 보내는 데 사용됩니다.
  • onEvent() - 원격 분석 이벤트를 원격 분석 서버에(예: WORKSPACE_USED 또는 WORKSPACE_STARTED )에 제출합니다.
  • increaseDuration() - 작은 시간 프레임으로 많은 이벤트를 보내는 대신 현재 이벤트의 기간을 늘립니다.

다음 섹션에서 다룹니다.

  • 이벤트를 표준 출력에 에코하는 원격 분석 서버를 생성합니다.
  • OpenShift Dev Spaces 원격 분석 클라이언트를 확장하고 사용자의 사용자 지정 백엔드를 구현합니다.
  • 사용자 지정 백엔드의 Dev Workspace 플러그인을 나타내는 plugin.yaml 파일을 생성합니다.
  • CheCluster 사용자 정의 리소스에서 workspacesDefaultPlugins 속성을 설정하여 OpenShift Dev Spaces 사용자 지정 플러그인의 위치를 지정합니다.

3.7.2.1. 시작하기

이 문서에서는 OpenShift Dev Spaces 원격 분석 시스템을 확장하여 사용자 지정 백엔드와 통신하는 데 필요한 단계를 설명합니다.

  1. 이벤트를 수신하는 서버 프로세스 생성
  2. OpenShift Dev Spaces 라이브러리를 확장하여 이벤트를 서버로 보내는 백엔드를 생성합니다.
  3. 컨테이너에 Telemetry 백엔드 패키징 및 이미지 레지스트리에 배포
  4. 백엔드용 플러그인 추가 및 OpenShift Dev Spaces가 Dev Workspaces에서 플러그인을 로드하도록 지시

원격 분석 백엔드의 완료된 예는 여기에서 확인할 수 있습니다.

3.7.2.2. 이벤트를 수신하는 서버 생성

이 예제에서는 Telemetry 플러그인에서 이벤트를 수신하고 표준 출력에 쓰는 서버를 생성하는 방법을 보여줍니다.

프로덕션 사용 사례의 경우 자체 Telemetry 서버를 생성하는 대신 타사 Telemetry 시스템(예: Segment, Woopra)과 통합하는 것이 좋습니다. 이 경우 공급자의 API를 사용하여 사용자 지정 백엔드에서 시스템으로 이벤트를 보냅니다.

다음 Go 코드는 포트 8080 에서 서버를 시작하고 이벤트를 표준 출력에 씁니다.

예 3.20. main.go

package main

import (
	"io/ioutil"
	"net/http"

	"go.uber.org/zap"
)

var logger *zap.SugaredLogger

func event(w http.ResponseWriter, req *http.Request) {
	switch req.Method {
	case "GET":
		logger.Info("GET /event")
	case "POST":
		logger.Info("POST /event")
	}
	body, err := req.GetBody()
	if err != nil {
		logger.With("err", err).Info("error getting body")
		return
	}
	responseBody, err := ioutil.ReadAll(body)
	if err != nil {
		logger.With("error", err).Info("error reading response body")
		return
	}
	logger.With("body", string(responseBody)).Info("got event")
}

func activity(w http.ResponseWriter, req *http.Request) {
	switch req.Method {
	case "GET":
		logger.Info("GET /activity, doing nothing")
	case "POST":
		logger.Info("POST /activity")
		body, err := req.GetBody()
		if err != nil {
			logger.With("error", err).Info("error getting body")
			return
		}
		responseBody, err := ioutil.ReadAll(body)
		if err != nil {
			logger.With("error", err).Info("error reading response body")
			return
		}
		logger.With("body", string(responseBody)).Info("got activity")
	}
}

func main() {

	log, _ := zap.NewProduction()
	logger = log.Sugar()

	http.HandleFunc("/event", event)
	http.HandleFunc("/activity", activity)
	logger.Info("Added Handlers")

	logger.Info("Starting to serve")
	http.ListenAndServe(":8080", nil)
}

이 코드를 기반으로 컨테이너 이미지를 생성하고 openshift-devspaces 프로젝트에서 OpenShift에 배포로 노출합니다. 예제 Telemetry 서버의 코드는 telemetry-server-example 에서 사용할 수 있습니다. 원격 분석 서버를 배포하려면 리포지토리를 복제하고 컨테이너를 빌드합니다.

$ git clone https://github.com/che-incubator/telemetry-server-example
$ cd telemetry-server-example
$ podman build -t registry/organization/telemetry-server-example:latest .
$ podman push registry/organization/telemetry-server-example:latest

manifest_with_ingress.yamlmanifest_with_route 둘 다 배포 및 서비스에 대한 정의가 포함되어 있습니다. 전자는 Kubernetes 인그레스도 정의하고 후자는 OpenShift 경로를 정의합니다.

매니페스트 파일에서 내보낸 이미지와 일치하도록 이미지호스트 필드와 OpenShift 클러스터의 공용 호스트 이름을 바꿉니다. 그런 다음 실행합니다.

$ kubectl apply -f manifest_with_[ingress|route].yaml -n openshift-devspaces

3.7.2.3. 백엔드 프로젝트 생성

참고

개발 시 신속한 피드백을 받으려면 Dev Workspace 내에서 개발을 수행하는 것이 좋습니다. 이렇게 하면 클러스터에서 애플리케이션을 실행하고 프런트 엔드 Telemetry 플러그인에서 이벤트를 수신할 수 있습니다.

  1. Maven Quarkus 프로젝트 스캐폴드:

    mvn io.quarkus:quarkus-maven-plugin:2.7.1.Final:create \
        -DprojectGroupId=mygroup -DprojectArtifactId=devworkspace-telemetry-example-plugin \
    -DprojectVersion=1.0.0-SNAPSHOT
  2. src/main/java/mygroupsrc/test/java/mygroup 아래에 있는 파일을 제거합니다.
  3. 최신 버전 및 backend-base 의 Maven 좌표는 GitHub 패키지를 참조하십시오.
  4. pom.xml 에 다음 종속성을 추가합니다.

    예 3.21. pom.xml

    <!-- Required -->
    <dependency>
        <groupId>org.eclipse.che.incubator.workspace-telemetry</groupId>
        <artifactId>backend-base</artifactId>
        <version>LATEST VERSION FROM PREVIOUS STEP</version>
    </dependency>
    
    
    <!-- Used to make http requests to the telemetry server -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client-jackson</artifactId>
    </dependency>
  5. GitHub 패키지에서 org.eclipse.che.incubator.workspace-telemetry:backend-base 종속성을 다운로드할 수 있는 read:packages 권한으로 개인 액세스 토큰을 생성합니다.
  6. ~/.m2/settings.xml 파일에 GitHub 사용자 이름, 개인 액세스 토큰 및 che-incubator 리포지토리 세부 정보를 추가합니다.

    예 3.22. settings.xml

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
    http://maven.apache.org/xsd/settings-1.0.0.xsd">
       <servers>
          <server>
             <id>che-incubator</id>
             <username>YOUR GITHUB USERNAME</username>
             <password>YOUR GITHUB TOKEN</password>
          </server>
       </servers>
    
       <profiles>
          <profile>
             <id>github</id>
             <activation>
                <activeByDefault>true</activeByDefault>
             </activation>
             <repositories>
                <repository>
                   <id>central</id>
                   <url>https://repo1.maven.org/maven2</url>
                   <releases><enabled>true</enabled></releases>
                   <snapshots><enabled>false</enabled></snapshots>
                   </repository>
                   <repository>
                   <id>che-incubator</id>
                   <url>https://maven.pkg.github.com/che-incubator/che-workspace-telemetry-client</url>
                </repository>
             </repositories>
          </profile>
       </profiles>
    </settings>

3.7.2.4. AnalyticsManager의 구체적인 구현 생성 및 특수 논리 추가

src/main/java/mygroup 아래에 프로젝트에 두 개의 파일을 생성합니다.

  • MainConfiguration.java - AnalyticsManager 에 제공된 구성이 포함되어 있습니다.
  • analyticsManager.java - Telemetry 시스템과 관련된 논리가 포함되어 있습니다.

예 3.23. MainConfiguration.java

package org.my.group;

import java.util.Optional;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Alternative;

import org.eclipse.che.incubator.workspace.telemetry.base.BaseConfiguration;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@Dependent
@Alternative
public class MainConfiguration extends BaseConfiguration {
    @ConfigProperty(name = "welcome.message")      1
    Optional<String> welcomeMessage;               2
}
1
MicroProfile 구성 주석은 welcome.message 구성을 삽입하는 데 사용됩니다.

백엔드와 관련된 구성 속성을 설정하는 방법에 대한 자세한 내용은 Quarkus 구성 참조 가이드를 참조하십시오.

예 3.24. AnalyticsManager.java

package org.my.group;

import java.util.HashMap;
import java.util.Map;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Alternative;
import javax.inject.Inject;

import org.eclipse.che.incubator.workspace.telemetry.base.AbstractAnalyticsManager;
import org.eclipse.che.incubator.workspace.telemetry.base.AnalyticsEvent;
import org.eclipse.che.incubator.workspace.telemetry.finder.DevWorkspaceFinder;
import org.eclipse.che.incubator.workspace.telemetry.finder.UsernameFinder;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.slf4j.Logger;

import static org.slf4j.LoggerFactory.getLogger;

@Dependent
@Alternative
public class AnalyticsManager extends AbstractAnalyticsManager {

    private static final Logger LOG = getLogger(AbstractAnalyticsManager.class);

    public AnalyticsManager(MainConfiguration mainConfiguration, DevWorkspaceFinder devworkspaceFinder, UsernameFinder usernameFinder) {
        super(mainConfiguration, devworkspaceFinder, usernameFinder);

        mainConfiguration.welcomeMessage.ifPresentOrElse(     1
            (str) -> LOG.info("The welcome message is: {}", str),
            () -> LOG.info("No welcome message provided")
        );
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public void destroy() {}

    @Override
    public void onEvent(AnalyticsEvent event, String ownerId, String ip, String userAgent, String resolution, Map<String, Object> properties) {
        LOG.info("The received event is: {}", event);         2
    }

    @Override
    public void increaseDuration(AnalyticsEvent event, Map<String, Object> properties) { }

    @Override
    public void onActivity() {}
}
1
시작 메시지가 제공된 경우 기록합니다.
2
프런트 엔드 플러그인에서 수신한 이벤트를 기록합니다.

org.my.group.AnalyticsManagerorg.my.group.MainConfiguration 은 대체 빈이므로 src/main/resources/application.propertiesquarkus.arc.selected-alternatives 속성을 사용하여 지정합니다.

예 3.25. application.properties

quarkus.arc.selected-alternatives=MainConfiguration,AnalyticsManager

3.7.2.5. Dev Workspace 내에서 애플리케이션 실행

  1. Dev Workspace에서 DEVWORKSPACE_TELEMETRY_BACKEND_PORT 환경 변수를 설정합니다. 여기서 값은 4167 로 설정됩니다.

    spec:
      template:
        attributes:
          workspaceEnv:
            - name: DEVWORKSPACE_TELEMETRY_BACKEND_PORT
              value: '4167'
  2. Red Hat OpenShift Dev Spaces 대시보드에서 Dev Workspace를 다시 시작합니다.
  3. Dev Workspace의 터미널 창에서 다음 명령을 실행하여 애플리케이션을 시작합니다. --settings 플래그를 사용하여 GitHub 액세스 토큰이 포함된 settings.xml 파일의 위치에 대한 경로를 지정합니다.

    $ mvn --settings=settings.xml quarkus:dev -Dquarkus.http.port=${DEVWORKSPACE_TELEMETRY_BACKEND_PORT}

    이제 애플리케이션은 프런트 엔드 플러그인에서 포트 4167 을 통해 원격 분석 이벤트를 수신합니다.

검증 단계

  1. 다음 출력이 기록되었는지 확인합니다.

    INFO  [org.ecl.che.inc.AnalyticsManager] (Quarkus Main Thread) No welcome message provided
    INFO  [io.quarkus] (Quarkus Main Thread) devworkspace-telemetry-example-plugin 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.7.2.Final) started in 0.323s. Listening on: http://localhost:4167
    INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
    INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes-client, rest-client, rest-client-jackson, resteasy, resteasy-jsonb, smallrye-context-propagation, smallrye-openapi, swagger-ui, vertx]
  2. AnalyticsManageronEvent() 메서드가 프런트 엔드 플러그인에서 이벤트를 수신하는지 확인하려면 l 키를 눌러 Quarkus 실시간 코딩을 비활성화하고 IDE 내의 모든 파일을 편집합니다. 다음 출력을 로깅해야 합니다.

    INFO  [io.qua.dep.dev.RuntimeUpdatesProcessor] (Aesh InputStream Reader) Live reload disabled
    INFO  [org.ecl.che.inc.AnalyticsManager] (executor-thread-2) The received event is: Edit Workspace File in Che

3.7.2.6. isEnabled()구현

예제의 목적을 위해 이 메서드는 호출될 때마다 항상 true 를 반환합니다.

예 3.26. AnalyticsManager.java

@Override
public boolean isEnabled() {
    return true;
}

isEnabled() 에 더 복잡한 논리를 배치할 수 있습니다. 예를 들어 호스팅된 OpenShift Dev Spaces Woopra 백엔드 는 백엔드가 활성화되어 있는지 확인하기 전에 구성 속성이 있는지 확인합니다.

3.7.2.7. onEvent()구현

onEvent() 는 백엔드에서 수신한 이벤트를 원격 분석 시스템으로 전송합니다. 예제 애플리케이션의 경우 원격 분석 서버에서 /event 끝점으로 HTTP POST 페이로드를 보냅니다.

3.7.2.7.1. 예제 Telemetry 서버로 POST 요청 전송

다음 예에서 Telemetry 서버 애플리케이션은 다음 URL에서 OpenShift에 배포됩니다. 여기서 apps-crc.testing 은 OpenShift 클러스터의 수신 도메인 이름입니다.

  1. TelemetryService.java를 만들어 REST REST Client 설정

    예 3.27. TelemetryService.java

    package org.my.group;
    
    import java.util.Map;
    
    import javax.ws.rs.Consumes;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    
    import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
    
    @RegisterRestClient
    public interface TelemetryService {
        @POST
        @Path("/event") 1
        @Consumes(MediaType.APPLICATION_JSON)
        Response sendEvent(Map<String, Object> payload);
    }
    1
    POST 요청을 할 끝점입니다.
  2. src/main/resources/application.properties 파일에서 TelemetryService 의 기본 URL을 지정합니다.

    예 3.28. application.properties

    org.my.group.TelemetryService/mp-rest/url=http://little-telemetry-server-che.apps-crc.testing
  3. TelemetryServiceAnalyticsManager 에 삽입하고 onEvent()POST 요청을 보냅니다.

    예 3.29. AnalyticsManager.java

    @Dependent
    @Alternative
    public class AnalyticsManager extends AbstractAnalyticsManager {
        @Inject
        @RestClient
        TelemetryService telemetryService;
    
    ...
    
    @Override
    public void onEvent(AnalyticsEvent event, String ownerId, String ip, String userAgent, String resolution, Map<String, Object> properties) {
        Map<String, Object> payload = new HashMap<String, Object>(properties);
        payload.put("event", event);
        telemetryService.sendEvent(payload);
    }

    그러면 HTTP 요청을 Telemetry 서버로 전송하고 일정 기간 동안 동일한 이벤트를 자동으로 지연합니다. 기본 기간은 1500밀리초입니다.

3.7.2.8. increaseDuration()구현

많은 원격 분석 시스템은 이벤트 기간을 인식합니다. AbstractAnalyticsManager 는 동일한 시간에 발생하는 유사한 이벤트를 하나의 이벤트로 병합합니다. 이 increaseDuration() 구현은 no-op입니다. 이 방법은 사용자 Telemetry 공급자의 API를 사용하여 이벤트 증가 기간을 반영하도록 이벤트 또는 이벤트 속성을 변경합니다.

예 3.30. AnalyticsManager.java

@Override
public void increaseDuration(AnalyticsEvent event, Map<String, Object> properties) {}

3.7.2.9. onActivity()구현

비활성 타임아웃 제한을 설정하고 onActivity() 를 사용하여 마지막 이벤트 시간이 시간 초과보다 긴 경우 WORKSPACE_INACTIVE 이벤트를 보냅니다.

예 3.31. AnalyticsManager.java

public class AnalyticsManager extends AbstractAnalyticsManager {

    ...

    private long inactiveTimeLimit = 60000 * 3;

    ...

    @Override
    public void onActivity() {
        if (System.currentTimeMillis() - lastEventTime >= inactiveTimeLimit) {
            onEvent(WORKSPACE_INACTIVE, lastOwnerId, lastIp, lastUserAgent, lastResolution, commonProperties);
        }
    }

3.7.2.10. destroy()구현

destroy() 가 호출되면 WORKSPACE_STOPPED 이벤트를 전송하고 연결 풀과 같은 모든 리소스를 종료합니다.

예 3.32. AnalyticsManager.java

@Override
public void destroy() {
    onEvent(WORKSPACE_STOPPED, lastOwnerId, lastIp, lastUserAgent, lastResolution, commonProperties);
}

3.7.2.5절. “Dev Workspace 내에서 애플리케이션 실행” 에 설명된 대로 mvn quarkus:dev 를 실행하고 Ctrl+C 사용하여 애플리케이션을 종료하면 WORKSPACE_STOPPED 이벤트가 서버에 전송됩니다.

3.7.2.11. Quarkus 애플리케이션 패키징

컨테이너에 애플리케이션을 패키징하는 가장 좋은 방법은 Quarkus 설명서 를 참조하십시오. 컨테이너를 빌드하여 선택한 컨테이너 레지스트리로 내보냅니다.

3.7.2.11.1. JVM으로 실행되는 Quarkus 이미지를 빌드하는 샘플 Dockerfile

예 3.33. Dockerfile.jvm

FROM registry.access.redhat.com/ubi8/openjdk-11:1.11

ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'

COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=185 target/quarkus-app/*.jar /deployments/
COPY --chown=185 target/quarkus-app/app/ /deployments/app/
COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/

EXPOSE 8080
USER 185

ENTRYPOINT ["java", "-Dquarkus.http.host=0.0.0.0", "-Djava.util.logging.manager=org.jboss.logmanager.LogManager", "-Dquarkus.http.port=${DEVWORKSPACE_TELEMETRY_BACKEND_PORT}", "-jar", "/deployments/quarkus-run.jar"]

이미지를 빌드하려면 다음을 실행합니다.

mvn package && \
podman build -f src/main/docker/Dockerfile.jvm -t image:tag .
3.7.2.11.2. Quarkus 기본 이미지를 빌드하는 샘플 Dockerfile

예 3.34. Dockerfile.native

FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
WORKDIR /work/
RUN chown 1001 /work \
    && chmod "g+rwX" /work \
    && chown 1001:root /work
COPY --chown=1001:root target/*-runner /work/application

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Dquarkus.http.port=$DEVWORKSPACE_TELEMETRY_BACKEND_PORT}"]

이미지를 빌드하려면 다음을 실행합니다.

mvn package -Pnative -Dquarkus.native.container-build=true && \
podman build -f src/main/docker/Dockerfile.native -t image:tag .

3.7.2.12. 플러그인에 대한 plugin.yaml 생성

Dev Workspace Pod에서 사용자 지정 백엔드를 실행하는 Dev Workspace 플러그인을 나타내는 plugin.yaml devfile v2 파일을 생성합니다. devfile v2에 대한 자세한 내용은 Devfile v2 문서를 참조하십시오.

예 3.35. plugin.yaml

schemaVersion: 2.1.0
metadata:
  name: devworkspace-telemetry-backend-plugin
  version: 0.0.1
  description: A Demo telemetry backend
  displayName: Devworkspace Telemetry Backend
components:
  - name: devworkspace-telemetry-backend-plugin
    attributes:
      workspaceEnv:
        - name: DEVWORKSPACE_TELEMETRY_BACKEND_PORT
          value: '4167'
    container:
      image: YOUR IMAGE            1
      env:
        - name: WELCOME_MESSAGE    2
          value: 'hello world!'
1
3.7.2.11절. “Quarkus 애플리케이션 패키징” 에서 빌드된 컨테이너 이미지를 지정합니다.
2
Example 4에서 welcome.message 선택적 구성 속성 값을 설정합니다.

일반적으로 사용자는 이 파일을 회사 웹 서버에 배포합니다. 이 가이드에서는 OpenShift에서 Apache 웹 서버를 생성하고 플러그인을 호스팅하는 방법을 보여줍니다.

plugin.yaml 파일을 참조하는 ConfigMap 오브젝트를 생성합니다.

$ oc create configmap --from-file=plugin.yaml -n openshift-devspaces telemetry-plugin-yaml

배포, 서비스 및 웹 서버를 노출하는 경로를 생성합니다. 배포는 이 ConfigMap 오브젝트를 참조하고 /var/www/html 디렉터리에 배치합니다.

예 3.36. manifest.yaml

kind: Deployment
apiVersion: apps/v1
metadata:
  name: apache
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apache
  template:
    metadata:
      labels:
        app: apache
    spec:
      volumes:
        - name: plugin-yaml
          configMap:
            name: telemetry-plugin-yaml
            defaultMode: 420
      containers:
        - name: apache
          image: 'registry.redhat.io/rhscl/httpd-24-rhel7:latest'
          ports:
            - containerPort: 8080
              protocol: TCP
          resources: {}
          volumeMounts:
            - name: plugin-yaml
              mountPath: /var/www/html
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600
---
kind: Service
apiVersion: v1
metadata:
  name: apache
spec:
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  selector:
    app: apache
  type: ClusterIP
---
kind: Route
apiVersion: route.openshift.io/v1
metadata:
  name: apache
spec:
  host: apache-che.apps-crc.testing
  to:
    kind: Service
    name: apache
    weight: 100
  port:
    targetPort: 8080
  wildcardPolicy: None
$ oc apply -f manifest.yaml

검증 단계

  • 배포가 시작되면 웹 서버에서 plugin.yaml 을 사용할 수 있는지 확인합니다.

    $ curl apache-che.apps-crc.testing/plugin.yaml

3.7.2.13. Dev Workspace에서 Telemetry 플러그인 지정

  1. 기존 Dev Workspace의 components 필드에 다음을 추가합니다.

    components:
      ...
      - name: telemetry-plugin
        plugin:
          uri: http://apache-che.apps-crc.testing/plugin.yaml
  2. OpenShift Dev Spaces 대시보드에서 Dev Workspace를 시작합니다.

검증 단계

  1. 원격 분석 플러그인 컨테이너가 Dev Workspace Pod에서 실행 중인지 확인합니다. 여기에서는 편집기 내에서 Workspace 보기를 확인하여 확인합니다.

    dev Workspace Telemetry 플러그인
  2. 편집기 내에서 파일을 편집하고 예제 Telemetry 서버의 로그에서 해당 이벤트를 관찰합니다.

3.7.2.14. 모든 Dev Workspace에 대한 Telemetry 플러그인 적용

Telemetry 플러그인을 기본 플러그인으로 설정합니다. 기본 플러그인은 신규 및 기존 Dev Workspaces에 대해 Dev Workspace 시작에 적용됩니다.

  • CheCluster 사용자 정의 리소스를 구성합니다. 3.1.2절. “CLI를 사용하여 CheCluster 사용자 정의 리소스 구성”을 참조하십시오.

    spec:
      devEnvironments:
        defaultPlugins:
        - editor: eclipse/che-theia/next     1
          plugins:                           2
          - 'http://apache-che.apps-crc.testing/plugin.yaml'
    1
    기본 플러그인을 설정하는 편집기 ID입니다.
    2
    devfile v2 플러그인에 대한 URL 목록입니다.

검증 단계

  1. Red Hat OpenShift Dev Spaces 대시보드에서 새 또는 기존 Dev Workspace를 시작합니다.
  2. 3.7.2.13절. “Dev Workspace에서 Telemetry 플러그인 지정” 의 확인 단계에 따라 Telemetry 플러그인이 작동하는지 확인합니다.

3.7.2.15. 서버 로깅 구성

OpenShift Dev Spaces 서버에서 사용할 수 있는 개별 로거의 로그 수준을 미세 조정할 수 있습니다.

전체 OpenShift Dev Spaces 서버의 로그 수준은 Operator의 cheLogLevel 구성 속성을 사용하여 전역적으로 구성됩니다. 3.1.3절. “CheCluster 사용자 정의 리소스 필드 참조”을 참조하십시오. Operator에서 관리하지 않는 설치의 글로벌 로그 수준을 설정하려면 che ConfigMap에서 CHE_LOG_LEVEL 환경 변수를 지정합니다.

CHE_LOGGER_CONFIG 환경 변수를 사용하여 OpenShift Dev Spaces 서버에서 개별 로거의 로그 수준을 구성할 수 있습니다.

3.7.2.15.1. 로그 수준 구성

프로세스

  • CheCluster 사용자 정의 리소스를 구성합니다. 3.1.2절. “CLI를 사용하여 CheCluster 사용자 정의 리소스 구성”을 참조하십시오.

    spec:
      components:
        cheServer:
          extraProperties:
            CHE_LOGGER_CONFIG: "<key1=value1,key2=value2>" 1
    1
    쉼표로 구분된 키-값 쌍 목록입니다. 여기서 키는 OpenShift Dev Spaces 서버 로그 출력에 표시된 대로 로거의 이름이며 값은 필요한 로그 수준입니다.

    예 3.37. WorkspaceManager의 디버그 모드 구성

    spec:
      components:
        cheServer:
          extraProperties:
            CHE_LOGGER_CONFIG: "org.eclipse.che.api.workspace.server.WorkspaceManager=DEBUG"
3.7.2.15.2. 로거 이름 지정

로거의 이름은 해당 로거를 사용하는 내부 서버 클래스의 클래스 이름을 따릅니다.

3.7.2.15.3. HTTP 트래픽 로깅

프로세스

3.7.2.16. dsc를 사용하여 로그 수집

Red Hat OpenShift Dev Spaces 설치는 OpenShift 클러스터에서 실행되는 여러 컨테이너로 구성됩니다. 실행 중인 각 컨테이너에서 수동으로 로그를 수집할 수 있지만 dsc 는 프로세스를 자동화하는 명령을 제공합니다.

dsc 툴을 사용하여 OpenShift 클러스터에서 Red Hat OpenShift Dev Spaces 로그를 수집하는 데 사용할 수 있는 명령은 다음과 같습니다.

DSC 서버:logs

기존 Red Hat OpenShift Dev Spaces 서버 로그를 수집하여 로컬 시스템의 디렉터리에 저장합니다. 기본적으로 로그는 머신의 임시 디렉터리로 다운로드됩니다. 그러나 -d 매개변수를 지정하여 덮어쓸 수 있습니다. 예를 들어 OpenShift Dev Spaces 로그를 /home/user/che-logs/ 디렉터리에 다운로드하려면 명령을 사용합니다.

dsc server:logs -d /home/user/che-logs/

실행하면 dsc server:logs 가 로그 파일을 저장할 디렉터리를 지정하는 콘솔에 메시지를 출력합니다.

Red Hat OpenShift Dev Spaces logs will be available in '/tmp/chectl-logs/1648575098344'

Red Hat OpenShift Dev Spaces가 기본이 아닌 프로젝트에 설치된 경우 dsc server:logs 에는 -n <NAMESPACE > 매개변수가 필요합니다. 여기서 < NAMESPACE >는 Red Hat OpenShift Dev Spaces가 설치된 OpenShift 프로젝트입니다. 예를 들어, my-namespace 프로젝트의 OpenShift Dev Spaces에서 로그를 가져오려면 명령을 사용합니다.

dsc server:logs -n my-namespace
DSC server:deploy
dsc 를 사용하여 설치할 때 OpenShift Dev Spaces 설치 중에 로그가 자동으로 수집됩니다. dsc server:logs 와 마찬가지로 디렉터리 로그는 -d 매개변수를 사용하여 에 저장할 수 있습니다.

추가 리소스

3.7.3. Dev Workspace Operator 모니터링

Dev Workspace Operator가 노출하는 메트릭을 스크랩하도록 OpenShift in-cluster 모니터링 스택을 구성할 수 있습니다.

3.7.3.1. Dev Workspace Operator 지표 수집

클러스터 내 Prometheus 인스턴스를 사용하여 Dev Workspace Operator에 대한 지표를 수집, 저장 및 쿼리하려면 다음을 수행합니다.

사전 요구 사항

  • 조직의 OpenShift Dev Spaces 인스턴스가 Red Hat OpenShift에서 설치 및 실행됩니다.
  • 대상 OpenShift 클러스터에 대한 관리 권한이 있는 활성 oc 세션. CLI 시작하기를 참조하십시오.
  • devworkspace-controller-metrics 서비스는 포트 8443 에 지표를 노출합니다. 이는 기본적으로 사전 구성되어 있습니다.

프로세스

  1. Dev Workspace Operator 지표 서비스를 감지하기 위한 ServiceMonitor를 생성합니다.

    예 3.38. ServiceMonitor

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: devworkspace-controller
      namespace: openshift-devspaces 1
    spec:
      endpoints:
        - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
          interval: 10s 2
          port: metrics
          scheme: https
          tlsConfig:
            insecureSkipVerify: true
      namespaceSelector:
        matchNames:
          - openshift-operators
      selector:
        matchLabels:
          app.kubernetes.io/name: devworkspace-controller
    1
    OpenShift Dev Spaces 네임스페이스입니다. 기본값은 openshift-devspaces 입니다.
    2
    대상이 스크랩되는 비율입니다.
  2. 클러스터 내 Prometheus 인스턴스에서 OpenShift Dev Spaces 네임스페이스에서 ServiceMonitor를 감지할 수 있습니다. 기본 OpenShift Dev Spaces 네임스페이스는 openshift-devspaces 입니다.

    $ oc label namespace openshift-devspaces openshift.io/cluster-monitoring=true

검증

  1. OpenShift Dev Spaces를 새로 설치하려면 대시보드에서 OpenShift Dev Spaces 작업 공간을 생성하여 지표를 생성합니다.
  2. OpenShift 웹 콘솔의 관리자 보기에서 모니터링 메트릭 으로 이동합니다.
  3. PromQL 쿼리를 실행하여 메트릭을 사용할 수 있는지 확인합니다. 예를 들어 devworkspace_started_total 을 입력하고 쿼리 실행을 클릭합니다.

    더 많은 메트릭은 3.7.3.2절. “dev Workspace별 메트릭” 에서 참조하십시오.

작은 정보

누락된 메트릭을 해결하려면 가능한 RBAC 관련 오류에 대한 Prometheus 컨테이너 로그를 확인합니다.

  1. Prometheus Pod의 이름을 가져옵니다.

    $ oc get pods -l app.kubernetes.io/name=prometheus -n openshift-monitoring -o=jsonpath='{.items[*].metadata.name}'
  2. 이전 단계의 Prometheus Pod에서 Prometheus 컨테이너 로그의 마지막 20행을 출력합니다.

    $ oc logs --tail=20 <prometheus_pod_name> -c prometheus -n openshift-monitoring

3.7.3.2. dev Workspace별 메트릭

다음 표에서는 devworkspace-controller-metrics 서비스에서 노출하는 Dev Workspace별 메트릭을 설명합니다.

표 3.40. 지표
이름유형설명라벨

devworkspace_started_total

카운터

Dev Workspace 시작 이벤트 수입니다.

소스,라우팅 클래스

devworkspace_started_success_total

카운터

실행 중인 단계에 성공적으로 들어오는 Dev Workspace 수입니다.

소스,라우팅 클래스

devworkspace_fail_total

카운터

실패한 Dev Workspace 수입니다.

소스,이유

devworkspace_startup_time

히스토그램

Dev Workspace를 시작하는 데 걸린 총 시간(초)입니다.

소스,라우팅 클래스

표 3.41. 라벨
이름설명

소스

Dev Workspace의 controller.devfile.io/devworkspace-source 레이블입니다.

string

라우팅 클래스

Dev Workspace의 spec.routingclass.

"basic|cluster|cluster-tls|web-terminal"

reason

작업 공간 시작 실패 이유

"BadRequest|InfrastructureFailure|Unknown"

표 3.42. 시작 실패 이유
이름설명

BadRequest

Dev Workspace를 생성하는 데 사용되는 잘못된 devfile으로 인한 시작 실패.

InfrastructureFailure

다음과 같은 오류로 인해 시작 실패: CreateContainerError,RunContainerError,FailedScheduling,FailedMount.

알 수 없음

알 수 없는 실패 이유

3.7.3.3. OpenShift 웹 콘솔 대시보드에서 Dev Workspace Operator 지표 보기

Dev Workspace Operator 지표를 수집하도록 클러스터 내 Prometheus 인스턴스를 구성한 후 OpenShift 웹 콘솔의 관리자 화면에서 사용자 정의 대시보드에서 메트릭을 볼 수 있습니다.

사전 요구 사항

  • 조직의 OpenShift Dev Spaces 인스턴스가 Red Hat OpenShift에서 설치 및 실행됩니다.
  • 대상 OpenShift 클러스터에 대한 관리 권한이 있는 활성 oc 세션. CLI 시작하기를 참조하십시오.
  • 클러스터 내 Prometheus 인스턴스는 지표를 수집하고 있습니다. 3.7.3.1절. “Dev Workspace Operator 지표 수집”을 참조하십시오.

프로세스

  • openshift-config-managed 프로젝트에서 대시보드 정의에 대한 ConfigMap을 생성하고 필요한 레이블을 적용합니다.

    1. $ oc create configmap grafana-dashboard-dwo \
        --from-literal=dwo-dashboard.json="$(curl https://raw.githubusercontent.com/devfile/devworkspace-operator/main/docs/grafana/openshift-console-dashboard.json)" \
        -n openshift-config-managed
      참고

      이전 명령에는 업스트림 커뮤니티의 자료에 대한 링크가 포함되어 있습니다. 이 자료에서는 사용 가능한 최신 콘텐츠와 최신 모범 사례를 나타냅니다. 이러한 팁은 Red Hat의 QE 부서에 의해 아직 진행되지 않았으며 다양한 사용자 그룹에서는 아직 검증되지 않았습니다. 이 정보를 신중하게 사용하십시오.

    2. $ oc label configmap grafana-dashboard-dwo console.openshift.io/dashboard=true -n openshift-config-managed
      참고

      대시보드 정의는 Grafana 6.x 대시보드를 기반으로 합니다. OpenShift 웹 콘솔에서 모든 Grafana 6.x 대시보드 기능이 지원되는 것은 아닙니다.

검증 단계

  1. OpenShift 웹 콘솔의 관리자 보기에서 모니터링 대시보드 로 이동합니다.
  2. 대시보드 Che 서버 JVM 으로 이동하여 대시보드 패널에 데이터가 포함되어 있는지 확인합니다.

3.7.3.4. Dev Workspace Operator 대시보드

OpenShift 웹 콘솔 사용자 정의 대시보드는 Grafana 6.x를 기반으로 하며 Dev Workspace Operator에서 다음 지표를 표시합니다.

참고

Grafana 6.x 대시보드의 모든 기능이 OpenShift 웹 콘솔 대시보드로 지원되는 것은 아닙니다.

3.7.3.4.1. dev Workspace 지표

Dev Workspace별 지표는 Dev Workspace Metrics 패널에 표시됩니다.

그림 3.1. Dev Workspace Metrics 패널

'DevWorkspace 시작과 관련된 메트릭이 포함된 Grafana 대시보드 패널
평균 작업 공간 시작 시간
평균 작업 공간 시작 기간입니다.
Workspace 시작
성공 및 실패한 작업 공간 시작 수입니다.
dev Workspace 성공 및 실패
성공적인 Dev Workspace 시작과 실패한 Dev Workspace 시작 간의 비교입니다.
dev Workspace 실패율
실패한 작업 공간 시작 수와 총 작업 공간 시작 수 간의 비율입니다.
dev Workspace 시작 실패 이유

작업 영역 시작 실패의 배포를 표시하는 원형 차트입니다.

  • BadRequest
  • InfrastructureFailure
  • 알 수 없음
3.7.3.4.2. Operator 지표

Operator별 지표가 Operator 지표 패널에 표시됩니다.

그림 3.2. Operator 지표 패널

Operator 메트릭이 포함된 Grafana 대시보드 패널
이동 중 Webhook
서로 다른 Webhook 요청 수를 비교합니다.
작업 대기열 깊이
작업 큐에 있는 조정 요청 수입니다.
메모리
Dev Workspace 컨트롤러 및 Dev Workspace 웹 후크 서버의 메모리 사용량입니다.
초당 평균 조정 수(DWO)
Dev Workspace 컨트롤러의 초당 평균 조정 수입니다.

3.7.4. Dev Spaces 서버 모니터링

OpenShift Dev Spaces를 구성하여 JVM 메모리와 같은 JVM 메트릭을 노출하고 OpenShift Dev Spaces Server에 대한 클래스 로드를 구성할 수 있습니다.

3.7.4.1. OpenShift Dev Spaces 서버 메트릭 활성화 및 노출

OpenShift Dev Spaces는 che-host 서비스의 포트 8087 에 JVM 지표를 노출합니다. 이 동작을 구성할 수 있습니다.

프로세스

3.7.4.2. Prometheus를 사용하여 OpenShift Dev Spaces Server 지표 수집

in-cluster Prometheus 인스턴스를 사용하여 OpenShift Dev Spaces Server에 대한 JVM 지표를 수집, 저장 및 쿼리하려면 다음을 수행합니다.

사전 요구 사항

  • 조직의 OpenShift Dev Spaces 인스턴스가 Red Hat OpenShift에서 설치 및 실행됩니다.
  • 대상 OpenShift 클러스터에 대한 관리 권한이 있는 활성 oc 세션. CLI 시작하기를 참조하십시오.
  • OpenShift Dev Spaces는 포트 8087 에서 지표를 노출합니다. OpenShift Dev Spaces 서버 JVM 메트릭 활성화 및 노출을 참조하십시오.

프로세스

  1. OpenShift Dev Spaces JVM 메트릭 서비스를 감지하기 위한 ServiceMonitor를 생성합니다.

    예 3.39. ServiceMonitor

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: che-host
      namespace: openshift-devspaces 1
    spec:
      endpoints:
        - interval: 10s 2
          port: metrics
          scheme: http
      namespaceSelector:
        matchNames:
          - openshift-devspaces 3
      selector:
        matchLabels:
          app.kubernetes.io/name: devspaces
    1 3
    OpenShift Dev Spaces 네임스페이스입니다. 기본값은 openshift-devspaces 입니다.
    2
    대상이 스크랩되는 비율입니다.
  2. Prometheus가 메트릭을 볼 수 있도록 Role 및 RoleBinding을 생성합니다.

    예 3.40. Role

    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: prometheus-k8s
      namespace: openshift-devspaces 1
    rules:
      - verbs:
          - get
          - list
          - watch
        apiGroups:
          - ''
        resources:
          - services
          - endpoints
          - pods
    1
    OpenShift Dev Spaces 네임스페이스입니다. 기본값은 openshift-devspaces 입니다.

    예 3.41. RoleBinding

    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: view-devspaces-openshift-monitoring-prometheus-k8s
      namespace: openshift-devspaces 1
    subjects:
      - kind: ServiceAccount
        name: prometheus-k8s
        namespace: openshift-monitoring
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: prometheus-k8s
    1
    OpenShift Dev Spaces 네임스페이스입니다. 기본값은 openshift-devspaces 입니다.
  3. 클러스터 내 Prometheus 인스턴스에서 OpenShift Dev Spaces 네임스페이스에서 ServiceMonitor를 감지할 수 있습니다. 기본 OpenShift Dev Spaces 네임스페이스는 openshift-devspaces 입니다.

    $ oc label namespace openshift-devspaces openshift.io/cluster-monitoring=true

검증

  1. OpenShift 웹 콘솔의 관리자 보기에서 모니터링 메트릭 으로 이동합니다.
  2. PromQL 쿼리를 실행하여 메트릭을 사용할 수 있는지 확인합니다. 예를 들어 process_uptime_seconds{job="che-host"} 를 입력하고 Run queries 를 클릭합니다.
작은 정보

누락된 메트릭을 해결하려면 가능한 RBAC 관련 오류에 대한 Prometheus 컨테이너 로그를 확인합니다.

  1. Prometheus Pod의 이름을 가져옵니다.

    $ oc get pods -l app.kubernetes.io/name=prometheus -n openshift-monitoring -o=jsonpath='{.items[*].metadata.name}'
  2. 이전 단계의 Prometheus Pod에서 Prometheus 컨테이너 로그의 마지막 20행을 출력합니다.

    $ oc logs --tail=20 <prometheus_pod_name> -c prometheus -n openshift-monitoring

3.7.4.3. OpenShift 웹 콘솔 대시보드에서 OpenShift Dev Spaces Server 보기

OpenShift Dev Spaces Server JVM 지표를 수집하도록 클러스터 내 Prometheus 인스턴스를 구성한 후 OpenShift 웹 콘솔의 관리자 화면에서 사용자 정의 대시보드에서 메트릭을 볼 수 있습니다.

사전 요구 사항

프로세스

  • openshift-config-managed 프로젝트에서 대시보드 정의에 대한 ConfigMap을 생성하고 필요한 레이블을 적용합니다.

    1. $ oc create configmap grafana-dashboard-devspaces-server \
        --from-literal=devspaces-server-dashboard.json="$(curl https://raw.githubusercontent.com/eclipse-che/che-server/main/docs/grafana/openshift-console-dashboard.json)" \
        -n openshift-config-managed
      참고

      이전 명령에는 업스트림 커뮤니티의 자료에 대한 링크가 포함되어 있습니다. 이 자료에서는 사용 가능한 최신 콘텐츠와 최신 모범 사례를 나타냅니다. 이러한 팁은 Red Hat의 QE 부서에 의해 아직 진행되지 않았으며 다양한 사용자 그룹에서는 아직 검증되지 않았습니다. 이 정보를 신중하게 사용하십시오.

    2. $ oc label configmap grafana-dashboard-devspaces-server console.openshift.io/dashboard=true -n openshift-config-managed
      참고

      대시보드 정의는 Grafana 6.x 대시보드를 기반으로 합니다. OpenShift 웹 콘솔에서 모든 Grafana 6.x 대시보드 기능이 지원되는 것은 아닙니다.

검증 단계

  1. OpenShift 웹 콘솔의 관리자 보기에서 모니터링 대시보드 로 이동합니다.
  2. Dashboard Dev Workspace Operator 로 이동하여 대시보드 패널에 데이터가 포함되어 있는지 확인합니다.

    그림 3.3. 빠른 사실

    *JVM 빠른 사실* 패널

    그림 3.4. JVM 메모리

    *JVM 메모리* 패널

    그림 3.5. JVM Misc

    *JVM Misc* 패널

    그림 3.6. JVM 메모리 풀(heap)

    *JVM 메모리 풀(heap)* 패널

    그림 3.7. JVM 메모리 풀(Non-Heap)

    *JVM 메모리 풀(heap이 아닌)* 패널

    그림 3.8. 가비지 컬렉션

    *JVM 가비지 컬렉션* 패널

    그림 3.9. 클래스 로드

    *JVM 클래스 로드* 패널

    그림 3.10. 버퍼 풀

    *JVM 버퍼 풀* 패널
Red Hat logoGithubRedditYoutubeTwitter

자세한 정보

평가판, 구매 및 판매

커뮤니티

Red Hat 문서 정보

Red Hat을 사용하는 고객은 신뢰할 수 있는 콘텐츠가 포함된 제품과 서비스를 통해 혁신하고 목표를 달성할 수 있습니다.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서, 웹 속성에서 문제가 있는 언어를 교체하기 위해 최선을 다하고 있습니다. 자세한 내용은 다음을 참조하세요.Red Hat 블로그.

Red Hat 소개

Red Hat은 기업이 핵심 데이터 센터에서 네트워크 에지에 이르기까지 플랫폼과 환경 전반에서 더 쉽게 작업할 수 있도록 강화된 솔루션을 제공합니다.

© 2024 Red Hat, Inc.