Information Security Study
젠킨스 파이프라인으로 애플리케이션 자원 사용량 자동으로 로깅하기 본문
젠킨스 파이프라인으로 애플리케이션 자원 사용량 자동으로 로깅하기
해야 할 것
1) 깃허브 레포지토리 생성해서 자원 사용량 기록하는 셸 스크립트를 작성한다.
2) 젠킨스 파이프라인에서 app01, app01-1에게 셸 스크립트 전송한다.
3) 각 app은 셸 스크립트를 실행하고 cpu, 메모리, 디스크 사용량 로깅 및 로그로테이션하고 취합 서버인 log로 전송한다.
4) 로그 서버는 이메일로 로그를 보낸다.
app01, app01-1에서 로그로테이트 설정파일을 작성해야 한다.
이메일로 로그파일 보내는 이유
: 그라파나 같은 모니터링 툴로 볼 수 없는 정보들도 있기 때문이다.
젠킨스에서 주기적 트리거 설정하기
젠킨스 대시보드에서 파이프라인 작업을 클릭해 구성에 들어가 빌드 주기 섹션에서 "Build periodically" 옵션을 선택한다.
이 옵션은 주기적으로 빌드를 트리거하도록 설정한다.
매 분마다 자동으로 빌드되고 싶다면
* * * * *
를 입력하면 된다.
매 분마다 빌드
로그 취합 서버 설정
젠킨스와 같은 가용영역으로 설정한다.
젠킨스와 같은 vpc, 서브넷이어야 한다!!!
나중에 app01과 app01-1이 로그를 보내줄 것이기 때문에 보안 그룹은 22번만 열어두었다.
접속 완료!
각 애플리케이션 서버의 로테이트 설정에 들어가 아래와 같이 수정한다.
/var/log/resource_usage.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 root utmp
postrotate
systemctl reload rsyslog > /dev/null 2>/dev/null || true
endscript
}
테스트 모드로 실행
설정파일의 권한은 위와 같이 변경한다.
그리고 패스워드 없이 접근할 수 있도록 visudo에서 설정해주었다.
권한 에러가 떴다.
경로에 권한을 변경하고
적용 되었는지 확인했다.
이번에도 오류가 나서 확인해보니
로그 파일을 안 만들어뒀다.
그래서 로그파일을 생성하고 소유자도 변경했다.
그런데도 해결이 안돼서 곰곰이 생각해보니
젠킨스 rsa 공개키를 로그서버에 저장하지 않았었다..
젠킨스의 공개키를 복사해서
로그서버의 authorized_keys에 저장했다.
그리고 app01, app01-1 인스턴스에서도 확인해보니 디렉토리가 없어서 생성 후 권한 변경을 했다.
pipeline {
agent any
environment {
LOG_FILE = "/var/log/resource_usage.log"
ROTATED_LOG_FILE = "/var/log/resource_usage.log.1.gz"
REMOTE_USER = "ubuntu"
REMOTE_HOST_APP1 = "ip"
REMOTE_HOST_APP2 = "ip"
REMOTE_DIR = "/var/logs/resource_usage"
GIT_REPO = "레포지토리명"
SSH_CREDENTIALS_ID = "credential key" // Jenkins에서 등록한 SSH 자격 증명 ID
}
stages {
stage('Clone Scripts') {
steps {
// GitHub 저장소에서 스크립트를 클론합니다.
git url: env.GIT_REPO, branch: 'main'
}
}
stage('Prepare Scripts') {
steps {
// 클론한 스크립트에 실행 권한을 부여합니다.
sh 'chmod +x resource_monitor.sh'
}
}
stage('Collect Resource Usage') {
steps {
// 클론한 스크립트를 실행합니다.
sh 'bash resource_monitor.sh'
}
}
stage('Remote Log Rotation') {
steps {
sshagent(credentials: [env.SSH_CREDENTIALS_ID]) {
script {
def remoteHosts = [env.REMOTE_HOST_APP1, env.REMOTE_HOST_APP2]
for (remoteHost in remoteHosts) {
sh """
echo "Performing log rotation on ${remoteHost}..."
ssh ${REMOTE_USER}@${remoteHost} '
if [ -f /etc/logrotate.d/resource_usage ]; then
sudo /usr/sbin/logrotate -f /etc/logrotate.d/resource_usage > /tmp/logrotate.log 2>&1
sudo cat /tmp/logrotate.log || echo "Failed to read logrotate log"
else
echo "Logrotate configuration file not found."
exit 1
fi'
"""
}
}
}
}
}
stage('Print and Send Logs') {
steps {
sshagent(credentials: [env.SSH_CREDENTIALS_ID]) {
script {
def localHostname = sh(script: 'hostname', returnStdout: true).trim()
sh """
echo "Sending log file to remote server..."
rsync -avz $LOG_FILE ${REMOTE_USER}@${REMOTE_HOST_APP1}:$REMOTE_DIR/${localHostname}-resource_usage.log
"""
// 로테이션된 로그 파일을 콘솔에 출력합니다.
sh '''
if [ -f $ROTATED_LOG_FILE ]; then
echo "Rotated log file content:"
gzip -d -c $ROTATED_LOG_FILE
else
echo "No rotated log file found."
fi
'''
}
}
}
}
}
post {
always {
echo 'Pipeline completed.'
}
}
}
위 스크립트로 success가 떴지만
기록이 안돼서 깃 클론 후 셸 스크립트가 실행이 안되는 건가 싶어
직접 인스턴스에 test.sh을 만들어 실행이 되나 봤다.
직접 파워셸에 셸 스크립트 작성하고 실행권한 부여 후 실행하면
로그파일에 잘 저장되는데... 젠킨스로 하면 안된다.
그래서 여러 경로를 모두 찾아보니 app이 아닌 젠킨스가 젠킨스의 자원 사용량을 로깅하고 있었다..
app01, app01-1의 자원 사용량을 로깅할 수 있도록 수정할 것이다.
우선 app01, app01-1의 jar 파일을 실행시켜 서비스가 돌아가도록 했다.
그리고 grep으로 프로세스의 pid를 출력했다.
그리고 app01, app01-1이 로그서버에게 전송해야 하니
각 애플리케이션 인스턴스에서 rsa 키를 발급받고 각각의 공개키를 로그서버의 authorized_keys 파일에 저장해야 한다.
두 애플리케이션 서버의 공개키를 로그 서버의 authorized_keys에 저장 후
셸을 실행하면
전송에 성공했다고 뜬다.
실제로 로그 서버에 들어가보면 로그 파일을 볼 수 있다.
이제 젠킨스를 통해서도 로그가 전송이 되는지 확인할 것이다.
그 전에 로그서버에서 어떤 애플리케이션의 로그인지 쉽게 구분하기 위해
애플리케이션의 name별로(app01, app01-1) 디렉토리를 생성하고
로그 파일명에도 name을 표시하도록 수정했다.
젠킨스에서도 success가 떴고
각 애플리케이션 서버에서 로깅이 잘 되고 있는 것을 확인할 수 있었다.
로그서버에서도 app01, app01-1 디렉토리에 전송이 잘 되었다.
셸 스크립트
#!/bin/bash
# 홈 디렉토리 아래의 로그 파일
USER_LOG_DIR="/home/ubuntu/logs"
LOG_FILE="${USER_LOG_DIR}/resource_usage_${HOSTNAME}.log"
LOG_ROTATE_CONFIG="/home/ubuntu/logrotate.conf"
# 원격 서버 설정
REMOTE_USER="ubuntu"
REMOTE_HOST="ip"
REMOTE_PATH="/home/ubuntu/logs-1"
# 현재 날짜 및 시간
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 애플리케이션 프로세스 ID 찾기 (JAR 파일 기준)
app_pid=$(ps -ef | grep '[j]ava -jar 파일명.jar' | awk '{print $2}' | head -n 1)
if [[ -n "$app_pid" && "$app_pid" =~ ^[0-9]+$ ]]; then
# app의 CPU 및 메모리 사용량
cpu_usage=$(ps -p $app_pid -o %cpu=)
mem_usage=$(ps -p $app_pid -o %mem=)
else
cpu_usage="N/A"
mem_usage="N/A"
fi
# 사용자 디렉토리 아래의 로그 디렉토리 생성
mkdir -p $USER_LOG_DIR
# 로그 파일에 기록
echo "$timestamp, app CPU: $cpu_usage%, app Memory: $mem_usage%" >> $LOG_FILE
# 사용자 홈 디렉토리에 로그 로테이션 설정 파일 생성
cat <<EOF > $LOG_ROTATE_CONFIG
$USER_LOG_DIR/resource_usage_*.log {
daily
rotate 7
compress
missingok
notifempty
create 0644 ubuntu ubuntu
}
EOF
# 로그 로테이션 수행
logrotate -f $LOG_ROTATE_CONFIG
# 로테이션된 로그 파일을 원격 서버로 전송
# 새로 생성된 로그 파일을 전송
scp $LOG_FILE ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/${HOSTNAME}/
# 로테이션된 로그 파일을 전송
for log_file in $(find $USER_LOG_DIR -name "resource_usage_${HOSTNAME}.log.*" ! -name "resource_usage_${HOSTNAME}.log"); do
scp $log_file ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/${HOSTNAME}/
done
파이프라인 스크립트
pipeline {
agent any
environment {
SSH_KEY_ID = 'credential key'
REPO_URL = '레포지토리명'
SCRIPT_NAME = 'resource_monitor.sh'
}
stages {
stage('Clone and Deploy Script') {
steps {
script {
def servers = [
[name: 'app01', host: 'ip', user: 'ubuntu'],
[name: 'app01-1', host: 'ip', user: 'ubuntu']
]
sshagent([SSH_KEY_ID]) {
servers.each { server ->
sh """
ssh -o StrictHostKeyChecking=no ${server.user}@${server.host} '
export HOSTNAME=${server.name} &&
rm -rf /tmp/repository &&
git clone ${REPO_URL} /tmp/repository || echo "Repository already exists" &&
cd /tmp/repository &&
chmod +x ${SCRIPT_NAME} &&
./${SCRIPT_NAME}
'
"""
}
}
}
}
}
}
post {
always {
echo 'Pipeline completed.'
}
}
}
다음에는 로그 서버에서 메일로 보내는 기능을 구현할 것이다.
'네트워크 캠퍼스 > 2차 프로젝트' 카테고리의 다른 글
프로메테우스와 그라파나로 모니터링하기 (0) | 2024.07.25 |
---|---|
인그레스 엔진엑스로 엔진엑스 부하분산하기 (0) | 2024.07.25 |
240719-23 vpc 변경(기본->새vpc), 롤백, 무중단 배포(롤링, 블루/그린) 이어서 (1) | 2024.07.23 |
blue/green 방식 무중단배포 구현하기 (1) | 2024.07.23 |
롤링방식 무중단배포 구현하기 (1) | 2024.07.23 |