관리 메뉴

피터의 개발이야기

[Kubernetes] Spring에서 쿠버네티스 Pod 정보조회 본문

Kubernetes/Logging & Monitoring

[Kubernetes] Spring에서 쿠버네티스 Pod 정보조회

기록하는 백앤드개발자 2023. 1. 26. 01:42
반응형

[kubernetes] 쿠버네티스 목차

[kubernetes] 모니터링 방법 정리

ㅁ 개요

  지난 글 [Kubernetes] 쿠버네티스API 서버 CURL 접속 방법에서 쿠버네티스API와 REST API 요청을 위한 JWT Token, Service Account 권한 설정을 완료하였다. 이번 글에서는 Spring에서 쿠버네티스 이벤트 정보를 가져오는 방법에 대해서 공부하였다. 아래의 코드를 베이스로 주기적으로 pod 정보를 조회하여 eks fail-over 상황이 발생 시 SMS알람이 발송되도록 개발을 하였다. 하지만 여기서는 pod 정보를 조회하는 부분까지만 정리하였다.

 

1편 [kubernetes] EKS fail-over 상황정리 및 방어방법
2편 [Kubernetes] 쿠버네티스API 서버 CURL 접속 방법
3편 [Kubernetes] Spring에서 쿠버네티스 Pod 정보조회
4편 [kubernetes] kubernetes event exporter

 

ㅁ build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.3.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}

group = 'com.peterica'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
ext['log4j2.version'] = '2.17.1'

repositories {
    mavenCentral()
}
repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // webflux
    implementation('org.springframework.boot:spring-boot-starter-webflux')

    // log4j2
    compile ("org.springframework.boot:spring-boot-starter-log4j2")

    // lombok
    compileOnly 'org.projectlombok:lombok:1.18.6'
    annotationProcessor 'org.projectlombok:lombok:1.18.6'

    // ssl
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.10'
    compile group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.4'

    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
        exclude module: "logback-classic"
    }
}

 

 

ㅁ RestTemplate Config

@Configuration("restTemplateConfigCommon")
public class RestTemplateConfig {

	@Bean
	@Qualifier("restTemplateCommon")
	public RestTemplate restTemplate(RestTemplateBuilder builder) throws NoSuchAlgorithmException, KeyManagementException
	{

		TrustManager[] trustAllCerts = new TrustManager[] {
				new X509TrustManager() {
					public X509Certificate[] getAcceptedIssuers() {
						return new X509Certificate[0];
					}
					public void checkClientTrusted(
							X509Certificate[] certs, String authType) {
					}
					public void checkServerTrusted(
							X509Certificate[] certs, String authType) {
					}
				}
		};
		SSLContext sslContext = SSLContext.getInstance("SSL");
		sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
		CloseableHttpClient httpClient = HttpClients.custom()
				.setSSLContext(sslContext)
				.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
				.build();
		HttpComponentsClientHttpRequestFactory customRequestFactory = new HttpComponentsClientHttpRequestFactory();
		customRequestFactory.setHttpClient(httpClient);
		return builder.requestFactory(() -> customRequestFactory).build();
	}
}

 ㅇ REST API를 호출하기 위해 RestTemplate을 설정하였다. 

 ㅇ 로컬 환경에서 발급된 인증서를 검증할 수 없기 때문에 SSL 증명서 검증을 disable로 하여 Spring Boot Rest Template의 유효 여부에 관계없이 모든 종류의 증명서를 신뢰한다.

 

 

ㅁ RestApiUtil

@Component
@RequiredArgsConstructor
public class RestApiUtil {

    @Value("${config.kubernetes.url}")
    private String API_SERVER;

    @Value("${config.kubernetes.token}")
    private String API_TOKEN;

    private final RestTemplate restTemplateEKS;

    private final String API_URL = "/api/v1/namespaces/default/";

    public static final String RESOURCE_TYPE_POD = "pods";

    public ResponseEntity execute(HttpMethod httpMethod, String resourceType) {

        String url = API_SERVER + API_URL + resourceType;

        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(API_TOKEN);
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity httpEntity = new HttpEntity(headers);

        return restTemplateEKS.exchange(url, httpMethod, httpEntity, Map.class);

    }

}

 

 

ㅁ application.yml

server:
  port: 8080

---
spring:
  profiles: local

logging:
  config: classpath:log4j2-spring.local.xml

config:
  kubernetes:
    url: https://192.168.64.3:8443
    token: eyJhbGciOiJSUzI1NiIsImtp~~~생략

 

 

ㅁ ApiService

@Service
@RequiredArgsConstructor
@Log4j2
public class ApiService {

    private final RestApiUtil restApiUtil;

    public List getResource(String resourceType) {


        try {
            ResponseEntity e = restApiUtil.execute(HttpMethod.GET, resourceType);

            String statusCode = String.valueOf(e.getStatusCode());
            Map response = (Map) e.getBody();

            List<Map> items = (List) response.get("items");

            log.debug("k8s items = {}", items);
            return items.stream()
                    .map(item -> {

                        Map metadata = (Map) item.get("metadata");
                        String name = (String) metadata.get("name");
                        String namespace = (String) metadata.get("namespace");
                        Map status = (Map) item.get("status");
                        String phase = (String) status.get("phase");

                        return PodDto.builder()
                                .name(name)
                                .status(phase)
                                .namespace(namespace)
                                .build();
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("k8s items gathering fail. err={}", e.toString(), e);
            return null;
        }
    }
}

 ㅇ RestApiUtil을 통해 REST API 통신을 하여 POD 정보를 가져온다.

 ㅇ 가져온 정보들은  Map 형태로 response 객체에 저장되고 List items 객체로 케스팅하여 PodDto 리스트 형태로 변환한다.

 

ㅁ PodDto

@Getter
@Setter
@NoArgsConstructor
public class PodDto {

    private String name;
    private String status;
    private String namespace;

    @Builder
    public PodDto(String name, String status, String namespace) {
        this.name = name;
        this.status = status;
        this.namespace = namespace;
    }

}

 ㅇ 위 통신에서 받아온 pod의 정보를 저장하기 위한 DTO 객체이다.

 

 

ㅁ ApiController

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/")
public class ApiController {

    private final ApiService apiService;

    @GetMapping("/pods")
    public List getPods(){
        return apiService.getResource(RESOURCE_TYPE_POD);
    }

}

ㅇ ApiService를 호출하는 /api/pods 서블릿을 설정한다.

ㅇ http://localhost:8080/api/pods 로 호출하였다.

 

 

[{
	"name": "kubectl-test-deploy-6dc65cd5c8-92vcz",
	"status": "Running",
	"namespace": "default"
}]

 ㅇ kubectl-test-deploy의 정보를 JSON형태로 제공해 준다.

 

 ㅇ 웹 브라우저에서 get으로 호출할 때에 json 데이터로 잘 전달되었다.

 

 

 ㅇ kubectl 명령어를 통해 호출하였던 정보와 동일하게 전달되었다.

 

 

ㅁ 함께 보면 좋은 사이트

 

Spring Application으로 Kubernetes에 명령 보내기

Kubernetes는 API 서버 입니다. 이번 글에서는 Spring Applicaiton에서 REST Template를 통해 Kubernetes에 명령을 보내는 방법을 알아보겠습니다.

velog.io

 

Disable SSL verification in Spring WebClient

We can use an insecure TrustManagerFactory that trusts all X.509 certificates without any verification. This will allow any https certificate (self-signed, expired, etc) with WebClient communication.

www.javacodemonk.com

 

Disable SSL validation in Spring RestTemplate

We will configure Spring Boot RestTemplate to disable SSL certificates validation, allowing all certificates (self-signed, expired, non trusted root, etc)

www.javacodemonk.com

 

반응형
Comments