PHP source deploy with jenkins
젠킨스를 이용한 PHP 소스 배포
이 배포 방식은
꽤 오래전 얘기지만 전 직장에서 개발중인 웹서비스의 대부분이 PHP 를 이용하여 개발되고 있고 효과적이고 일관된 배포 방법이 없을까 고민하다 직접 스크립트를 작성하게 되었습니다.
이 방법은 젠킨스에서 제공되는 variables 를 일부 활용했습니다. 동작 방식은 간단하며, 이를 응용하면 다른 것들도 가능합니다.
동작 방식을 간다하게 설명하자면 빌드 시 Execute shell 에 등록된 배포 스크립트가 실행되고 배포 스크립트는 서버 리스트에 있는 아이피를 읽으면서 반복문을 이용해 배포될 서버에 rsync 를 이용하여 싱크 되는 방식입니다.
PHP 는 인터프리터 언어이기 때문에 웹 서버의 정지 없이 소스 복사만 해 주어도 새로운 소스가 반영 되기 때문입니다.
이 방법은 사전에 SSH KEY 인증을 통해 로그인 없이 접속 가능하도록 설정해 주셔야 하며 Rsync 패키지가 설치되어 있어야 합니다.
배포 스크립트 작성
우선 serverlist 파일과 배포 스크립트의 지속적인 관리를 위해 GIT 에 새 프로젝트를 만들었습니다.
Git Project : serverscript
배포스크립트 작성
파일명 : deployScriptMulti.bash
#!/bin/bash ## since 2015.06.29 ## author fallboyz@umount.net ## script usage ## sh deployScript SOURCE_DIR ## ex) ## sh deployScript jenkins_project if [ $1 ] then SOURCE_NAME=$1 else echo "Please enter the jenkins project name." exit fi ## EXCLUDE DIRECTORY 체크 EXCLUDE_CUSTOM="" if [ $# -gt 1 ] then for i in $(seq 1 $#) do j="$"$i eval DIR=$j EXCLUDE_CUSTOM=$EXCLUDE_CUSTOM" --exclude="$DIR done fi SOURCE_DIR="/data/apps/src/jenkins/workspace/"${SOURCE_NAME}"/" while read line do arr=$(echo $line | tr " " "\n") TARGET_PATH="" TARGET_USER="" TARGET_PORT="22" i=0 for p in $arr do i=$(($i+1)) if [ "$i" = "1" ] && [ $SOURCE_NAME != $p ] then break fi if [ "$i" = "1" ] then continue fi if [ "$i" = "2" ] then TARGET_PATH=$(echo $p) continue fi if [ "$i" = "3" ] then TARGET_USER=$(echo $p) continue fi if [ "$i" = "4" ] then TARGET_PORT=$(echo $p) continue fi PROJECT_IP=$(echo $p) TARGET_DIR=${TARGET_USER}"@"${PROJECT_IP}":"${TARGET_PATH} EXCLUDE_OPTION="--exclude=.svn --exclude=.git --exclude=.gitignore" rsync -atrpz --omit-dir-times --stats --delete -e "ssh -p "${TARGET_PORT}" -i /data/apps/src/jenkins/.ssh/id_rsa" ${EXCLUDE_OPTION} ${EXCLUDE_CUSTOM} ${SOURCE_DIR} ${TARGET_DIR} # 디버깅용 #echo "rsync -atrpz --omit-dir-times --stats --delete -e ssh -i /data/apps/src/jenkins/.ssh/id_rsa" ${EXCLUDE_OPTION} ${EXCLUDE_CUSTOM} ${SOURCE_DIR} ${TARGET_DIR} #echo "TARGET_USER="${TARGET_USER}"==" #echo "PROJECT_IP="${PROJECT_IP}"==" #echo "TARGET_PATH="${TARGET_PATH}"==" #echo "EXCLUDE_OPTION="${EXCLUDE_OPTION}"==" #echo "SOURCE_DIR="${SOURCE_DIR}"==" #echo "TARGET_DIR="${TARGET_DIR}"==" #echo "EXCLUDE_CUSTOM="${EXCLUDE_CUSTOM}"==" #rsync -atrpz --omit-dir-times --stats --delete -e "ssh -i /data/apps/src/jenkins/.ssh/id_rsa" ${EXCLUDE_OPTION} ${EXCLUDE_CUSTOM} ${SOURCE_DIR} ${TARGET_DIR} #echo "rsync -atrpz --omit-dir-times --stats --delete -e ssh -i /data/apps/src/jenkins/.ssh/id_rsa" ${EXCLUDE_OPTION} ${EXCLUDE_CUSTOM} ${SOURCE_DIR} ${TARGET_DIR} #rsync -atrpz --omit-dir-times --stats --delete -e ssh -i /data/apps/src/jenkins/.ssh/id_rsa --exclude=.svn /data/apps/src/je:/opt/HomePage/BITTRADE2/WebAppnsoft syncuser@61.78.62.120 #echo $i "=" $p "=" $SERVER_PARAM "=" $TARGET_DIR "=" $SOURCE_DIR "=" $EXCLUDE_CUSTOM done done < "/data/apps/src/jenkins/workspace/serverscript/projectscript/serverlistmulti.txt"
서버리스트 파일 작성
배포할 서버가 다수인 경우에는 서버 IP 를 띄어쓰기를 이용하여 나열해 주시고 해당 파일은 unix(LF), 캐릭터셋은 utf8 을 사용해 주시기 바랍니다.
파일명 : serverlistmulti.txt
## 배포서버 리스트 파일 ## since 2015.06.29 ## author fallboyz@umount.net ## Usage : [jenkins_프로젝트명] [배포될_서버_디렉토리_경로] [배포할_서버의_리눅스_계정] [SSH_포트] [서버IP_1] [서버IP_2] [서버IP_3] [서버IP_4] ... ## sample list ## ## umount.net QA_umount.net /data/www/umount.net umount 22 10.19.10.5 LIVE_umount.net /data/www/umount.net umount 22 10.19.11.5 10.19.11.6 10.19.11.7 ## test.umount.net QA_test.umount.net /data/www/test.umount.net umount 2222 172.16.11.5 172.16.11.6 #################
배포 설정
이제는 jenkins에도 새 프로젝트를 생성해 줍니다.
Jenkins Project : serverscript
생성한 프로젝트의 구성에 들어가서 위에 생성한 Git 리포지토리를 등록 후 빌드해 줍니다.

이제 실제 웹 서비스(PHP) 소스가 관리되는 프로젝트를 생성해 줍니다.
Jenkins Project : QA_umount.net
구성에 들어가서 매개변수 사용에 체크를 해 줍니다. 매개변수는 String Parameter 를 이용 하며 해당 플러그인이 없다면 플러그인 관리에서 플러그인을 설치 해 주시면 됩니다.
매개변수 명 : param
Default Value : [jenkins_프로젝트명] [exclude file or exclude directory]
ex) QA_umount.net /readme.txt /document /class/config.php
Default Value에 있는 exclude 영역은 배포 시 제외할 파일이나 디렉토리를 나열한 것입니다. 필수 항목이 아니며, 빌드 시 임의로 추가하실 수 도 있습니다. 아래 이미지와 같이 제외할 파일이나 디렉토리가 여러개인 경우에 띄어쓰기를 이용하여 계속 나열 해 주시면 됩니다.

이제 소스 코드 관리에서 PHP 소스가 있는 Git 리포지토리를 등록해 줍니다.

마지막으로 Excute shell 에서 실제 배포를 실행하는 스크립트를 지정해 줍니다. 스크립트 파일도 젠킨스 프로젝트로 존재하기 때문에 해당 스크립트의 전체 경로를 적고 매개 변수를 뒤에 넣어줍니다.
sh /data/apps/src/jenkins/workspace/serverscript/projectscript/deployScriptMulti.bash $param

배포 테스트
모든 설정이 마무리 되었습니다. Build 버튼이 Build with parameter 로 변경되었을 것입니다. 해당 버튼을 누르면 바로 빌드가 되지 않고 위에서 매개변수를 설정할 때와 비슷한 화면으로 전환 됩니다. 바로 빌드를 진행하거나 exclude 파일 또는 디렉토리를 추가 작성하고 빌드를 진행하시면 됩니다.

이와 같은 방식의 배포를 이전 직장에서 처음 제안하고 직접 시범을 보여주면서 개발자들을 설득했으며, 현재도 위의 방식으로 배포를 하고 있습니다. 이 방법은 반드시 정답은 아닙니다. 단점도 있고 이보다 더 좋은 아이디어가 있을 수도 있습니다.