SMALL

 

Spring Boot Admin에서 기본적으로 타겟 client의 application.properties 설정값을 조회할 수 있다.

 

 

그럼 다음으로 해당 설정 값을 바꿀 수 있는 방법에 대해서 알아보자.

 

pom.xml ( dependency 설정 )

		<dependency>
			<groupId>org.springframework.cloud</groupId> 
			<artifactId>spring-cloud-context</artifactId>
		</dependency>

 

application.properties ( spring boot 설정 )

management.endpoint.env.post.enabled=true

 

위의 설정들을 추가하면 아래와 같이 해당 화면의 설정할 수 있는 부분이 생기게 된다. 

 

LIST
SMALL

Spring Boot Admin 화면에서 조회되는 Client들의 상태 정보를 추가적으로 조회할 수 있는 것들이 무엇이 있는지 알아보고 어떻게 설정해야 하는지 파악해보자.

크게 아래와 같이 구분할 수 있을것 같다.

  • JMX-Bean 관리
  • Logger ( Log 내용 실시간 조회 )
  • Build Version정보 파악 
  • Tag 정보 추가

이 기능들은 기본적으로 설정한 Spring Boot Admin 화면에서는 조회되지 않고 추가적으로 설정을 해주어야지 조회가 가능하다.

 

JMX-Bean 관리

우선 이 기능이 무엇이지 알아보도록 하자.

JMX ( Java Management eXtension ) 
-> JMX는 실행 중인 애플리케이션의 상태를 모니터링하고, 설정을 변경할 수 있게 해주는 API
-> JDK 1.5부터 포함된 사양

JConsole과 같은 미리 구현된 모니터링 도구를 이용하여 MBean 서버에 접근할 수 있다.

JMX를 통해 리소스 관리를 하려면 MBeans라는 Managed Beans를 생성해야 하고, 

생성한 MBean을 MBean Server에 등록해야 한다. 

MBean 서버는 등록된 MBeans를 관리하는 agent 역할을 수행하게 된다. 

 

이제 JMX가 무엇인지 알았으니 Spring Boot Admin에서 JMX 기능을 사용하는 방법을 알아보자.

 

pom.xml ( dependency 설정 )

		<dependency>
			<groupId>org.jolokia</groupId>
			<artifactId>jolokia-core</artifactId>
		</dependency>

 

application.yml( spring boot 설정 )

spring:
  jmx:
    enabled: true

 

이렇게 설정을 하면 Spring Boot Admin에 JVM 메뉴 하위에 JMX 메뉴가 추가된다.

여기서 추가한 jolokia라는것은 무엇인지 의문이 들었다.

해당 모듈이 무엇인지 찾아본 내역은 아래와 같다.

Jolokia
-> HTTP 프로토콜을 이용해 손쉽게 JMX 값을 JSON 형식으로 받아볼 수 있게 해주는
    일종의 JMX-HTTP 커넥터

위의 JMX를 설명하며 언급한 JConsole이 JMX를 관리하기 위한 툴이었다면, Jolokia는 JMX에서 관리하는 Bean들의 내용을 조회 및 액션을 수행하기 위한 HTTP 호출 툴(?), 커넥터라고 이해하면 될 것 같다.

 

Logger ( Log 내용 실시간 조회 )

기본으로 제공되는 Spring Boot Admin의 Logger기능은 Log Level를 변경하는 것이다.

거기에 추가적으로 로그의 내용들을 조회하고 싶은경우에는 추가적인 application.yml 파일 설정이 필요하다.

 

application.yml( spring boot 설정 )

logging:
  file:
    name: "/var/log/sample-boot-application.log"    
  pattern:
    file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

 

log파일의 위치를 명시적으로 지정해 주어야한다.

( 추가 적으로 log의 패턴도 지정할 수 있다) 

 

 

Build Version정보 파악 

Spring Boot의 빌드 버전 정보는 META-INF/build-info.properties 위치에서 쉽게 파악할 수 있다.

해당 정보를 생성하기 위해서는 추가적인 설정이 필요하다.

 

pom.xml ( dependency 설정 )

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

해당 정보를 추가해 주면 Spring Boot Admin 화면에서 실행 중인 Appliation의 빌드 버전 조회가 가능해진다.

 

Tag 정보 추가

Tag 정보는 단순히 해당 Application에 대한 정보를 추가적으로 표시하기 위한 용도이다.

관리하는 Appliation의 종류가 많아지는 경우에는 해당 Tag를 통해 좀 더 쉽게 Application들의 관리가 이루어질 수도 있을 것 같다.

 

application.yml( spring boot 설정 )

spring:
  boot:
    admin:
      client:
        instance:
          metadata:
            tags:
              environment: "tag-test1"
info:
  tags:
    environment: "tag-test1"

 

 

 

 

 

 

 

LIST
SMALL

일반적인 환경에서 Spring Boot Application을 띄우는 경우 이외에,

Kubernetes 환경에 Spring Boot Application을 띄우는 경우에 해당 Application에 대한 정보를 모니터링하고 싶은 경우에 사용하는 방법을 알아보도록 하자.

 

아래와 같은 목차로 설명하도록 하겠다.

  • Kubernetes 환경 리소스 생성
  • SpringBootAppliation 설정 ( Server, Client)
  • Dockerimage 생성
  • Kubernetes ( Deployment, Service ) 생성

 

출처 : https://youtu.be/Ql1Gnz4L_-c?t=1500

Kubernetes 환경 리소스 생성

먼저 Spring Boot Admin의 Server에서 Kubernetes관련 정보를 수집할 수 있는 권한이 필요하다.

이에 해당하는 Role, ServiceAccount, RoleBinding 관련 리소스를 생성해보자.

 

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: {user_ns}
  name: admin
rules:
  - apiGroups: ["", "extensions", "apps"]
    resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
    verbs: ["get", "list", "watch"]

 

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin

 

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: admin
  namespace: {user_ns}
subjects:
- kind: ServiceAccount
  name: admin
  apiGroup: ""
roleRef:
  kind: Role
  name: admin
  apiGroup: ""

해당 리소스들의 관계는 Kubernetes 리소스 관련 control을 할 수 있는 Role (권한)이 있고,

해당 권한과 ServiceAccount를 Binding해주는 RoleBinding이 있다.

RoleBinding을 통해서 특정 ServiceAccount는 Kubernetes 리소스를 control 하는 Role을 가지게 된다.

추후에 Kubernetes Deployment를 생성할때 해당 ServiceAccount 정보를 기입하면 해당 Deployment는 Role을 가질 수 있게 된다. 

 

SpringBootAppliation 설정 (Server)

 

pom.xml ( dependency 설정 ) 

		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-starter-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-kubernetes</artifactId>
		</dependency>

 

application.yml( spring boot 설정 )

spring:
  cloud:
    kubernetes:
      discovery:
        service-labels:
          type: spring-boot #해당 label이 붙은 k8s 리소스만의 정보만 조회 가능
  boot:
    admin:
      monitor:
        status-interval: 3s
        status-lifetime: 3s

 

Spring Main Application 

@SpringBootApplication
@EnableAdminServer
@EnableScheduling
@EnableDiscoveryClient // !!
public class SbaK8sServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(SbaK8sServerApplication.class, args);
	}

}

 

SpringBootAppliation 설정 (Client)

 

pom.xml ( dependency 설정 ) 

		<dependency>
			<groupId>de.codecentric</groupId>
			<artifactId>spring-boot-admin-starter-client</artifactId>
		</dependency>

 

application.yml( spring boot 설정 )

server:
  port: 8082

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always

 

Dockerimage 생성

Kubernetes에 Pod를 띄우기 위해서는 Dockerimage를 생성하여 Deployment에 해당 정보를 넣어주어야한다.

여기서는 자세하게 다루지 않고, 생성하기 위한 명령어들만 간단하게 공유하도록 하겠다.

 # client
 docker build -t sba-client:v1 ./
 docker push sba-client:v1
 # server
 docker build -t sba-server:v1 ./
 docker push sba-server:v1

 

Kubernetes  Spring Boot Admin Server( Deployment, Service ) 생성

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: {user_ns}
  name: admin-pod
  labels:
    type: spring-boot
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: admin
    spec:
      serviceAccountName: admin
      containers:
        - image: {sba-server_image_name}
          name: admin
          env:
            - name: management.endpoints.web.exposure.include
              value: "*"
            - name: management.endpoint.health.show-details
              value: "always"
          ports:
            - containerPort: 8080
          resources: {}
          readinessProbe:
            httpGet:
              path: /actuator/health
              port: 8080
            initialDelaySeconds: 10
            timeoutSeconds: 2
            periodSeconds: 5
            failureThreshold: 5
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 8080
            initialDelaySeconds: 20
            timeoutSeconds: 2
            periodSeconds: 8
            failureThreshold: 5
      restartPolicy: Always
  selector:
    matchLabels:
      app: admin

 

apiVersion: v1
kind: Service
metadata:
  namespace: {user_ns}
  name: admin-service
  labels:
    type: spring-boot
spec:
  type: NodePort
  ports:
    - name: "http"
      port: 8080
      targetPort: 8080
  selector:
    app: admin

 

Kubernetes Client ( Deployment, Service ) 생성

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: {user_ns}
  name: {user_pod_name}
  labels:
    type: spring-boot
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: {user_pod_name}
    spec:
      containers:
        - image: {user_image_name}
          name: {user_pod_name}
          env:
            - name: management.endpoints.web.exposure.include
              value: "*"
            - name: management.endpoint.health.show-details
              value: "always"
          ports:
            - containerPort: 8082
          resources: {}
          readinessProbe:
            httpGet:
              path: /actuator/health
              port: 8082
            initialDelaySeconds: 10
            timeoutSeconds: 2
            periodSeconds: 5
            failureThreshold: 5
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 8082
            initialDelaySeconds: 20
            timeoutSeconds: 2
            periodSeconds: 8
            failureThreshold: 5
      restartPolicy: Always
  selector:
    matchLabels:
      app: {user_pod_name}

Service에 대한 내용은 Spring Boot Admin Server와 동일하다. ( port 정보만 중복되지 않도록 바꾸어주면 된다)

 

이번 포스팅의 내용을 대략적으로 보면 기본적으로 Kubernetes의 리소스를 사용하기 위한 설정이 대부분이었던 것 같다.

핵심으로는 Kubernetes환경에서 Spring Boot Admin을 사용하기 위해서 해야 하는 Application에 설정해야 하는 부분에 집중하면 될 것 같다. 

(Server에서 Client를 찾을 수 있도록 Applicaiton에 설정을 추가해주는 부분)

LIST
SMALL

Spring Boot Admin 화면을 통해서 Spring Application들의 상태 정보를 조회하고, 설정 정보를 변경할 수 있다.

이러한 경우에 허용되지 않은 User가 해당 동작을 수행하게 된다면 안될것이다.

그렇기 때문에 SpringBootAdmin에 Security를 추가하는 내역을 알아보도록 하자. 

기본적으로 Spring에서 제공하는 Security의 기능을 사용해보도록 하겠다.

 

각각의 추가되는 설정 정보는 기존에 Spring Boot Admin 설정이 완료된 상태에서 Security 설정을 추가한다는 기준으로 설명을 한다고 생각하면 된다.

( 이전의 설정 내역 정리 : https://joomn11.tistory.com/68 )

 

Server-Side

pom.xml ( dependency 설정 ) 

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

 

application.properties ( spring boot 설정 )

server.port=8000
spring.security.user.name=admin #Added!
spring.security.user.password=admin #Added!
management.endpoints.web.exposure.include=*

 

Security 관련 설정 추가

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	private final AdminServerProperties adminServer;

    public SecurityConfig(AdminServerProperties adminServer) {
        this.adminServer = adminServer;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeRequests()
            .antMatchers(this.adminServer.path("/assets/**")).permitAll() 
            .antMatchers(this.adminServer.path("/login")).permitAll()
            .anyRequest().authenticated() 
            .and()
        .formLogin().loginPage(this.adminServer.path("/login")).successHandler(successHandler).and() 
        .logout().logoutUrl(this.adminServer.path("/logout")).and()
        .httpBasic().and() 
        .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) 
            .ignoringAntMatchers(
                this.adminServer.path("/instances"), 
                this.adminServer.path("/actuator/**") 
            );
    }
}

 

Security 관련 설정은 Spring Boot Admin 자체의 설정이 아니고 Spring에서 제공하는 Security를 사용하기 위한 설정이므로 Spring Security에 대한 지식이 필요하다.

( 현재 설정한 코드는 다른 블로그에 내용을 참고한 것이다 : https://jaehyun8719.github.io/2019/06/20/springboot/admin/)

 

이렇게 설정이 완료된 후에 spring-boot-admin의 server-side를 띄워보면 아래와 같은 login화면을 마주 할 수 있게 된다.

 

Client-Side

그럼 다음으로 security를 사용하기 위한 client-side의 설정을 보도록 하자.

 

먼저 Security관련 설정을 추가하지 않은 경우에 어떻게 되는지 보자.

분명 Client Application을 띄웠는데도 Spring Boot Admin 화면에 나타나지 않게 된다.

Log 내용을 자세하게 보면 아래와 같은 내용이 찍히게 된다.

 

WARN 43396 --- [gistrationTask1] d.c.b.a.c.r.ApplicationRegistrator : Failed to register application as Application(name=spring-boot-application, managementUrl=http://localhost:8089/actuator, healthUrl=http://localhost:8089/actuator/health, serviceUrl=http://localhost:8089) at spring-boot-admin ([http://localhost:8000/instances]): 401 : [no body]. Further attempts are logged on DEBUG level

Server-Side의 Security관련 설정이 있기 때문에 Spring-Boot-Admin에 제대로 등록이 되지 않게 된다.

 

application.properties ( spring boot 설정 )

server.port=8089
spring.boot.admin.client.url=http://localhost:8000
spring.boot.admin.client.instance.service-url=http://localhost:8089
spring.boot.admin.client.instance.metadata.user.name=admin #Added !
spring.boot.admin.client.instance.metadata.user.password=admin #Added !
spring.boot.admin.client.username=admin #Added !
spring.boot.admin.client.password=admin #Added !
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

위와 같이 spring boot admin server-side에 설정된 login정보를 설정해주어야 정상적으로 server에 해당 application이 등록되고 해당 정보를 조회할 수 있었다.

 

 

 

 

 

 

LIST

+ Recent posts