cf. 만약 앱이 Spring Actuator 설정이 되어 있지 않다면, 다음 자료를 참고하여 미리 적용, 이미지로 배포되어야 함.
spring-deployment.yaml v1--- 구분자를 기준으로 여러 파일로 나눠서 등록 가능(spring-deployment.yaml, spring-service.yaml)# deployment
apiVersion: apps/v1 # Kubernetes 리소스 안정화(stable) 버전
kind: Deployment
metadata:
name: spring # deployment 이름
spec:
replicas: 1 # 동시에 실행가능한 pod 개수
selector:
matchLabels:
app: spring # Deployment가 관리할 Pod를 고르는 기준(label)
# pod 템플릿
template:
metadata:
labels:
app: spring # app: spring 라벨(selector.matchLabels와 반드시 일치해야 deployment가 pod 관리 가능)
spec:
# Pod 안에서 돌 컨테이너 목록
containers:
- name: spring
image: endermaru/22-5-team1-server
ports:
- containerPort: 8080
---
# service
apiVersion: v1
kind: Service
metadata:
name: spring # 서비스 이름
spec:
type: LoadBalancer
selector:
app: spring # 어떤 pod에 트래픽을 전달할지 -> app: spring 라벨
ports:
- port: 8080 # service port: 다른 Pod나 외부에서 이 서비스에 접근할 때 사용
targetPort: 8080 # target port: 서비스가 선택된 Pod의 컨테이너로 트래픽을 전달할 포트
$ kubectl apply -f spring-deployment.yaml
deployment.apps/spring created
service/spring created
$ minikube service spring
$ kubectl logs spring-64dc785cdf-d57vf
...
No active profile set, falling back to 1 default profile: "default"
...
/actuator/health는 Down(redis 연결 불가)readiness, liveness는 Updefault 프로필 설정spring-deployment.yaml v2spec.template.spec.containers[].env)# deployment
apiVersion: apps/v1 # Kubernetes 리소스 안정화(stable) 버전
kind: Deployment
metadata:
name: spring # deployment 이름
spec:
replicas: 1 # 동시에 실행가능한 pod 개수
selector:
matchLabels:
app: spring # Deployment가 관리할 Pod를 고르는 기준(label)
# pod 템플릿
template:
metadata:
labels:
app: spring # app: spring 라벨(selector.matchLabels와 반드시 일치해야 deployment가 pod 관리 가능)
spec:
# Pod 안에서 돌 컨테이너 목록
containers:
- name: spring
image: endermaru/22-5-team1-server
ports:
- containerPort: 8080
# env 속성으로 환경변수 설정하기
env:
- name: SPRING_PROFILES_ACTIVE
value: local
---
# service
apiVersion: v1
kind: Service
metadata:
name: spring # 서비스 이름
spec:
type: LoadBalancer
selector:
app: spring # 어떤 pod에 트래픽을 전달할지 -> app: spring 라벨
ports:
- port: 8080 # service port: 다른 Pod나 외부에서 이 서비스에 접근할 때 사용
targetPort: 8080 # target port: 서비스가 선택된 Pod의 컨테이너로 트래픽을 전달할 포트
$ kubectl apply -f spring-deployment.yaml
deployment.apps/spring configured
service/spring unchanged
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
spring-54fcc7ddbf-qv78c 1/1 Running 0 80s
$ kubectl logs spring-54fcc7ddbf-qv78c
...
The following 1 profile is active: "local"
...
spring-deployment.yaml v3ConfigMap 리소스를 정의: 모든 key-value 쌍이 컨테이너의 환경변수로 자동 설정Deployment에서도 개별 환경변수를 설정하는 env 대신 ConfigMap 전체를 가져와 환경변수로 등록하는 envFrom 사용# deployment
apiVersion: apps/v1 # Kubernetes 리소스 안정화(stable) 버전
kind: Deployment
metadata:
name: spring # deployment 이름
spec:
replicas: 1 # 동시에 실행가능한 pod 개수
selector:
matchLabels:
app: spring # Deployment가 관리할 Pod를 고르는 기준(label)
# pod 템플릿
template:
metadata:
labels:
app: spring # app: spring 라벨(selector.matchLabels와 반드시 일치해야 deployment가 pod 관리 가능)
spec:
# Pod 안에서 돌 컨테이너 목록
containers:
- name: spring
image: endermaru/22-5-team1-server
ports:
- containerPort: 8080
# ConfigMapRef를 정의해서 환경변수를 가져옴
envFrom:
- configMapRef:
name: spring-config # 사용할 configmap 이름
---
# service
apiVersion: v1
kind: Service
metadata:
name: spring # 서비스 이름
spec:
type: LoadBalancer
selector:
app: spring # 어떤 pod에 트래픽을 전달할지 -> app: spring 라벨
ports:
- port: 8080 # service port: 다른 Pod나 외부에서 이 서비스에 접근할 때 사용
targetPort: 8080 # target port: 서비스가 선택된 Pod의 컨테이너로 트래픽을 전달할 포트
---
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-config
data:
SPRING_PROFILES_ACTIVE: local
SPRING_MAIL_USERNAME: internhasha.dev@gmail.com
# Health Check 상세 보기 & Mail Health Check 비활성화
MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS: "always"
MANAGEMENT_HEALTH_MAIL_ENABLED: "false"
# 다른 환경변수도 설정 가능
# ConfigMap을 새로 추가 & Spring Deployment 업데이트
$ kubectl apply -f spring-deployment.yaml
$ kubectl logs spring-5ddb6b7d4d-ts5dm
...
The following 1 profile is active: "local"
...
# cf. ConfigMap을 변경할 경우 재배포가 자동으로 되지 않으므로 재시작 필요
$ kubectl apply -f spring-deployment.yaml
$ kubectl rollout restart deployment spring
minikube service spring & /actuator/health 경로로 접속{
"status": "DOWN",
"groups": [
"liveness",
"readiness",
"startup"
],
"components": {
"db": {
"status": "UP",
"details": {
"database": "H2",
"validationQuery": "isValid()"
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 1081101176832,
"free": 1019471405056,
"threshold": 10485760,
"path": "/app/.",
"exists": true
}
},
"livenessState": {
"status": "UP"
},
"ping": {
"status": "UP"
},
"readinessState": {
"status": "UP"
},
"redis": {
"status": "DOWN",
"details": {
"error": "org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis"
}
},
"ssl": {
"status": "UP",
"details": {
"validChains": [],
"invalidChains": []
}
}
}
}
ClusterIP 타입 : 클러스터 내부에서만 접근 가능한 가상의 IP 주소를 부여하는 서비스 타입ClusterIP 타입NodePort, LoadBalancer와 달리 외부 접근 불가능redis-deployment.yaml# Redis Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7.0-alpine
ports:
- containerPort: 6379 # 외부에서 Redis에 접근할 포트
---
apiVersion: v1
kind: Service
metadata:
name: redis # application.yml의 redis host 이름과 일치해야함!
# 서비스가 다른 네임스페이스(redisNameSpace)에 있다면
# application.yml의 redis host는 serviceName.redisNameSpace가 되어야 함
spec:
# type을 따로 지정하지 않으면 ClusterIP 타입
selector:
app: redis
ports:
- port: 6379 # application.yml의 redis port와 일치해야 함!
targetPort: 6379
# redis deployment, pod, service를 생성
$ kubectl apply -f redis-deployment.yaml
deployment.apps/redis created
service/redis created
# spring deployment 재시작
$ kubectl rollout restart deployment spring
deployment.apps/spring restarted
# 확인
$ kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/redis-5dd6f67ff-kvt82 1/1 Running 0 23m
pod/spring-67955bb566-b2lc2 1/1 Running 0 79s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d20h
service/redis ClusterIP 10.98.209.17 <none> 6379/TCP 23m
service/spring LoadBalancer 10.98.44.112 <pending> 8080:31628/TCP 58m
minikube service spring & /actuator/health 경로로 접속{
"status": "UP",
"groups": [
"liveness",
"readiness",
"startup"
],
"components": {
"db": {
"status": "UP",
"details": {
"database": "H2",
"validationQuery": "isValid()"
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 1081101176832,
"free": 1019471253504,
"threshold": 10485760,
"path": "/app/.",
"exists": true
}
},
"livenessState": {
"status": "UP"
},
"ping": {
"status": "UP"
},
"readinessState": {
"status": "UP"
},
"redis": {
"status": "UP",
"details": {
"version": "7.0.15"
}
},
"ssl": {
"status": "UP",
"details": {
"validChains": [],
"invalidChains": []
}
}
}
}
┌────────────────────────────────┐
│ External Client │
│ (e.g., Browser, Postman) │
└────────────┬───────────────────┘
│
▼
┌───────────────────────────────┐
│ Service: spring (LoadBalancer)
│ EXTERNAL-IP: 127.0.0.1:12277
└────────────┬──────────────────┘
│
▼
┌──────────────────────────────────┐
│ Pod: spring │
│ - Container: spring │
│ - Env: SPRING_REDIS_HOST=redis
└────────────┬─────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ Service: redis (ClusterIP) │
│ - Internal name: redis:6379 │
└────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────┐
│ Pod: redis │
│ - Container: redis:7.0-alpine│
└──────────────────────────────────┘
kubectl apply를 이용한 생성과 업데이트를 통해 유지보수, 버전관리 등에 있어 유용함metadata.name이 Spring 앱의 host 이름으로 사용됨)