Skip to content

test: k3s deploy action #10

test: k3s deploy action

test: k3s deploy action #10

Workflow file for this run

name: Spring Boot Multi-module K3s Deployment
on:
push:
branches:
- develop
env:
REGISTRY: "ghcr.io"
NAMESPACE: "depromeet"
IMAGE_NAME: "kasukabe-server"
MODULE: "layer-api"
jobs:
setup:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
deploy_target: ${{ steps.set-env.outputs.DEPLOY_TARGET }}
sha_short: ${{ steps.sha_short.outputs.sha_short }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Env
id: set-env
run: |
if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
echo "DEPLOY_TARGET=production" >> $GITHUB_OUTPUT
else
echo "DEPLOY_TARGET=development" >> $GITHUB_OUTPUT
fi
- name: Get short SHA
id: sha_short
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
build:
name: build
needs: [ setup ]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
DEPLOY_TARGET: ${{ needs.setup.outputs.deploy_target }}
REGISTRY: "ghcr.io"
NAMESPACE: "depromeet"
IMAGE_NAME: "kasukabe-server"
# TODO: 멀티모듈 적용시 동적 할당 필요
MODULE: "layer-api"
APPLICATION_SECRET_PROPERTIES: ${{ secrets.APPLICATION_SECRET_PROPERTIES }}
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
SHA_SHORT: ${{ needs.setup.outputs.sha_short }}
steps:
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'corretto'
- name: Checkout sources
uses: actions/checkout@v4
- name: Setup Gradle
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
- name: Create application-secret.properties
run: |
echo "${APPLICATION_SECRET_PROPERTIES}" > ./${{ env.MODULE }}/src/main/resources/application-secret.properties
- name: Build ${{ env.MODULE }} module
run: ./gradlew :${{ env.MODULE }}:build
- name: Run tests:${{ env.MODULE }}
run: ./gradlew :${{ env.MODULE }}:test
- name: login github container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}/${{ env.MODULE }}
- name: push
uses: docker/build-push-action@v4
with:
context: ./${{ env.MODULE }}
platforms: linux/amd64
push: true
tags: |
${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ env.SHA_SHORT }}
${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:latest
deploy:
name: Deploy to K3s
needs: [ build, setup ]
runs-on: ubuntu-latest
env:
DEPLOY_TARGET: ${{ needs.setup.outputs.deploy_target }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install kubectl
uses: azure/setup-kubectl@v1
with:
version: 'v1.21.0'
- name: Set up kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" > $HOME/.kube/config
chmod 600 $HOME/.kube/config
- name: Create K3s deployment files
run: |
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${{ env.MODULE }}-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ${{ env.MODULE }}
template:
metadata:
labels:
app: ${{ env.MODULE }}
spec:
containers:
- name: ${{ env.MODULE }}
image: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:${{ needs.setup.outputs.sha_short }}
ports:
- containerPort: 8080
env:
- name: TZ
value: "Asia/Seoul"
- name: SPRING_PROFILES_ACTIVE
value: "${{ env.DEPLOY_TARGET }}"
volumeMounts:
- name: secret-volume
mountPath: /config/application-secret.properties
subPath: application-secret.properties
- name: log-volume
mountPath: /log
- name: tokens-volume
mountPath: /config/tokens
volumes:
- name: secret-volume
secret:
secretName: app-secret-dev
- name: log-volume
hostPath:
path: /${{ env.DEPLOY_TARGET }}/log/${{ env.MODULE }}
type: DirectoryOrCreate
- name: tokens-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: ${{ env.MODULE }}-service
namespace: default
spec:
selector:
app: ${{ env.MODULE }}
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${{ env.MODULE }}-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: stgapi.layerapp.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ${{ env.MODULE }}-service
port:
number: 80
EOF
- name: Deploy to K3s
run: |
kubectl apply -f deployment.yaml
- name: Verify deployment
run: |
# 최대 대기 시간 설정
# 120 = 2분
timeout=120
elapsed=0
interval=10
while true; do
# 배포 상태 확인
STATUS=$(kubectl rollout status deployment/${{ env.MODULE }}-deployment -n default --timeout=10s)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "Deployment successful!"
exit 0
fi
# 타임아웃 체크
if [ $elapsed -ge $timeout ]; then
echo "Deployment verification timed out after ${timeout} seconds"
kubectl get pods -n default -l app=${{ env.MODULE }}
kubectl describe deployment ${{ env.MODULE }}-deployment -n default
exit 1
fi
echo "Waiting for deployment to complete... (${elapsed}s elapsed)"
sleep $interval
elapsed=$((elapsed + interval))
done
# - name: Clean up old images
# if: success()
# run: |
# kubectl exec -it $(kubectl get pods -l app=${{ env.MODULE }} -n ${{ env.NAMESPACE }} -o jsonpath='{.items[0].metadata.name}') -n ${{ env.NAMESPACE }} -- docker image prune -a -f