Springboot와 mysql을 연동한 간단한 웹 애플리케이션을 쿠버네티스로 실행시키는 예제입니다.
개인의 실행 경험을 바탕으로 하고있으므로, 더 정확한 정보는 다른 공식문서에서 확인 바랍니다.
글을 쓴 시점의 가장 최신버전의 SpringBoot, mysql:lastest 를 사용하였습니다.
본 예제에서는 스프링 컨테이너를 띄우는것이 주된 관심사였기 때문에 volume에 관한 설정은 제외하였습니다.
아래는 전체 소스코드 입니다.
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.9.25'
id 'org.jetbrains.kotlin.plugin.spring' version '1.9.25'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
id 'org.jetbrains.kotlin.plugin.jpa' version '1.9.25'
}
group = 'hana.k8s'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
kotlin {
compilerOptions {
freeCompilerArgs.addAll '-Xjsr305=strict'
}
}
allOpen {
annotation 'jakarta.persistence.Entity'
annotation 'jakarta.persistence.MappedSuperclass'
annotation 'jakarta.persistence.Embeddable'
}
tasks.named('test') {
useJUnitPlatform()
}
의존성으로는 spring-web, jpa, mysql-connector를 추가하였고
개인 취향으로 kotlin을 사용하였습니다.
spring:
datasource:
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_NAME}
username: ${MYSQL_USERNAME}
password: ${MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://mysql-service:3306/sample_app
# username: root
# password: 111111
mysql연결에 필요한 정보를 작성했습니다.
저는 k8s의 configMap과 secret를 활용할 생각이였기 때문에 해당 부분을 변수로 받아오게끔 하였습니다.
주석으로 표기한 부분은 실제 환경변수가 들어오면 매핑될 String입니다.
참고용으로 표기해 두었습니다.
@RestController
class AppController {
@GetMapping("/")
fun index(): String {
return "hello world"
}
}
간단하게 루트path에 get요청을 받으면 "hello world"를 반환하게 작성하였습니다.
FROM openjdk:17-jdk
COPY build/libs/*SNAPSHOT.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
어려운 작업 없이 빌드된 jar파일을 실행하게끔 작성하였습니다.
apiVersion: v1
kind: Namespace
metadata:
name: my-app
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-deployment
namespace: my-app
spec:
replicas: 1
selector:
matchLabels:
app: backend-app
template:
metadata:
labels:
app: backend-app
spec:
containers:
- name: spring-container
image: spring
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
env:
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: mysql-config
key: mysql_host
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
name: mysql-config
key: mysql_port
- name: MYSQL_NAME
valueFrom:
configMapKeyRef:
name: mysql-config
key: mysql_nane
- name: MYSQL_USERNAME
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql_username
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql_password
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
namespace: my-app
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql-container
image: mysql
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql_password
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: mysql_nane
spring-deployment와 mysql-deployment를 한개의 deployment.yml파일에 위치시켰습니다.
apiVersion: v1
kind: Service
metadata:
name: spring-service
namespace: my-app
spec:
type: NodePort
selector:
app: backend-app
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30000
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
namespace: my-app
spec:
type: NodePort
selector:
app: mysql
ports:
- protocol: TCP
port: 3306
targetPort: 3306
마찬가지로 한개의 service.yml파일에 구분자를 통해서 두개의 service를 정의했습니다.
apiVersion: v1
kind: ConfigMap
metadata:
namespace: my-app
name: mysql-config
data:
mysql_host: "mysql-service"
mysql_port: "3306"
mysql_nane: "sample_app"
configMap에는 mysql 접속정보를 명시했습니다.
별도로 Spring에서만 사용되는 환경변수가 현재는 없기 때문에 mysql-config만 사용하였습니다.
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: my-app
stringData:
mysql_username: "root"
mysql_password: "111111"
마찬가지로 secret에 mysql 접속정보를 명시했습니다.
공개하기에 민감한 정보를 보관한다고 하여
임의로 접속정보의 username, password를 secret에 담아주었습니다.
.gradlew clean build 명령을 통해 프로젝트를 빌드합니다.
docker build -t sprig . 명령을 통해 도커 이미지를 생성합니다.
이미지명은 spring 으로 하였습니다.
kubectl apply -f namespace.yml
kubectl apply -f secret.yml
kubectl apply -f configMap.yml
kubectl apply -f deployment.yml
kubectl apply -f service.yml
kubectl get pods -n my-app 을 통해 pod가 정상적으로 올라왔는지를 확인합니다.

// 여담
spring pod가 몇차례 restart 되어있는 모습을 확인 할 수 있었는데
이는 아마 mysql이 온전히 올라오기 전에
spring이 실행되어 db접속정보가 유효하지 못하기 때문에 pod가 종료되고
deployment에 의해 pod를 다시 실행하는 일련의 과정이 있었던 것으로 추측됩니다.
docker container로 작업을 할 때는 컨테이너의 실행 순서를 지정해주는 설정정보를 필요로 하였는데
k8s의 장애복구능력으로 인해 실행순서를 굳이 지정해주지 않더라도 문제없이 동작하는것 같습니다.
편리하네요...

성공적으로 스프링이 실행되었다!!🥰
코드 쓰실때 마크다운에서
```kotlin 이런식으로 시작하면 언어 키워드 하이라이팅 됩니당