spring boot - certmanager를 통해 http2 설정 및 테스트 (2/2)

개요

이전 문서에서 쿠버네티스 환경에 cert-manager를 설치해서 환경구성을 완료했다면, 이번 문서에서는 spring boot 환경 구성 및 테스트까지 알아 볼 수 있도록 합니다.



준비

http2 테스트를 위해선 다음과 같은 테스트 환경이 필요합니다.

  • key, crt 파일
    • 해당 파일은 이전 문서에서 진행 후 생성된 secrets에서 추출합니다.
  • 테스트용 API 서버
    • Spring Boot로 간단하게 환경구성 합니다.
    • kubernetes 환경에 배포를 위해 Dockerfile 과 deployment, service yaml 까지 준비합니다.

spring boot 서버 기본 구성은 아래와 같이 진행했습니다.

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

group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/test")
    public String getTest() {
        return "test";
    }
}



방법

로컬 테스트

인증파일 추출

cert-manager를 통해 생성된 secrets 파일을 보면 ca.crt, tls.crt, tls.key 파일이 있습니다. 이 중, tls.crt, tls.key 파일을 추출해보도록 합니다.

secrets 파일을 json 형식으로 읽은 뒤, data.tls.key(crt)를 가져온 다음, 인코딩된 base64를 디코딩 한 다음, 파일로 만드는 명령어 입니다.

# tls.key
kubectl get secrets selfsigned-cert-tls -o jsonpath='{.data.tls\.key}' | base64 --decode >> tls.key
# tls.crt
kubectl get secrets selfsigned-cert-tls -o jsonpath='{.data.tls\.crt}' | base64 --decode >> tls.crt

추출된 파일은 spring boot로 만든 서버 중 원하는 경로 또는 관리하는 경로에 위치시켜 주도록 합니다.
이번 문서에서는 classpath 경로인 src/main/resources 하위에 위치시키도록 합니다.



application.yaml

http2 설정을 위해 application.yaml에 설정을 추가 및 tls.key, tls.crt 파일의 경로를 잡아줘야 합니다.

server:
  ssl:
    enabled: true
    certificate: classpath:tls.crt
    certificate-private-key: classpath:tls.key
  http2:
    enabled: true



테스트 진행

서버를 실행 하고나서, 브라우저에서 API를 호출 하면 다음과 같은 사실을 알아낼 수 있습니다.

  • https 실행
  • h2(http2) 프로토콜 실행




쿠버네티스 테스트

Dockerfile 생성

쿠버네티스 배포를 위해 먼저 컨테이너 이미지를 만들 수 있도록 Dockerfile를 작성합니다.
build/libs 하위에 있는 jar를 파일을 찾아 app.jar 파일로 복사하여 실행할 수 있도록 합니다.

FROM eclipse-temurin:11.0.16.1_1-jdk
ENV TZ=Asia/Seoul
#COPY ./target/*.jar app.jar
COPY ./build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

jar 생성

Dockerfile을 통해 이미지에 jar파일을 복사하기 위해 동작할 수 있는 jar파일을 생성해야 합니다.
gradle 기준으로 다음과 같습니다.

gradle clean bootJar



image 빌드

Dockerfile과 jar파일까지 준비 되었으면, 이미지를 빌드 할 수 있도록 합니다.

docker build -t http2-test:0.0.1 .



deployment, service yaml 작성

쿠버네티스에 배포하기 위한 deployment와 배포된 pod에 접근하기 위한 service를 생성할 수 있는 yaml을 작성합니다.

deployment.yaml

yaml 작성 시 이전 문서에서 진행된 cert-manager를 통해 만들어진 secrets를 volumeMount하여 컨테이너 내부에 마운트 할 수 있도록 작성합니다. 마운트된 파일은 환경변수를 통해서 매핑할 수 있도록 합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http2-test-deployment
  labels:
    app.kubernetes.io/name: spring
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: spring
  template:
    metadata:
      labels:
        app.kubernetes.io/name: spring
    spec:
      containers:
        - name: http2-test
          # 로컬에서 빌드한 이미지를 작성하면 된다.
          image: http2-test:1.0.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
              name: spring-port
          # 인증서 파일을 매핑하는 환경변수
          env:
            - name: SERVER_SSL_CERTIFICATE
              value: /etc/secret-volume/tls.crt
            - name: SERVER_SSL_CERTIFICATE-PRIVATE-KEY
              value: /etc/secret-volume/tls.key
          # secrets에 있는 인증서를 특정 디렉토리에 마운트
          volumeMounts:
            - name: tls-secret-volume
              mountPath: /etc/secret-volume
      # secrets에 있는 인증서를 특정 디렉토리에 마운트하기 위해 볼륨 설정
      volumes:
        - name: tls-secret-volume
          secret:
            # cert-manager에 인증서 설정하면서 생긴 secrets명
            secretName: selfsigned-cert-tls

작성 완료된 yaml은 배포할 수 있도록 합니다.

kubectl apply -f deployment.yaml

service.yaml

deployment.yaml에서 작성한 container port와 label selector를 잘 맞춰서 작성해주도록 합니다.
NodePort로 타입을 지정하여 pod에 접근 할 수 있도록 합니다.

apiVersion: v1
kind: Service
metadata:
  name: http2-test-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: spring
  ports:
    - protocol: TCP
      port: 8080
      targetPort: spring-port
      name: http2-test-port

작성 완료된 yaml은 배포할 수 있도록 합니다.

kubectl apply -f service.yaml

테스트

정상적으로 배포가 완료 되었다면 다음과 같이 실행하는 모습을 확인할 수 있습니다.

이제, NodePort로 생성된 port를 통해 접근하여, https와 http2 프로토콜이 정상적으로 적용되었는지 확인할 수 있도록 합니다.

정상적으로 동작하는 것을 확인할 수 있습니다.
또한, deployment.yaml에서 volumeMount 이용하여 인증파일을 마운트 한 것은 다음과 같이 pod에 직접적으로 접근하여 확인할 수 있습니다.

kubectl exec -it {pod명} -- bash
# pod 내부에서
cd /etc/secret-volume
ls



예제코드는 아래 깃허브 주소 링크를 참고하시면 됩니다.
https://github.com/devy1540/http2-test

이것으로 cert-manager를 통해 spring boot http2 설정 및 테스트에 대해 알아봤습니다.
감사합니다.