2017年3月30日 星期四

快速架一個 CI Server - Jenkins 環境建置

本篇主要目的為建立 Jenkins 環境,關於 Jenkins 設定則另外介紹

Environment Setup

  • CentOS Linux release 7.3.1611 (Core)
  • JDK 1.7.0.131
  • Tomcat 7.0.76
  • Jenkins 2.48

Linux 作業系統就不多說了,我是安裝在 VM 上
Jenkins 官網中並沒有說明記憶體最低需求,但建議給 16GB (您真是愛開玩笑呢)
我給它 6GB,Jenkins plugins 不要裝太多還夠用


1. Install JDK 1.7


因為產品是以 JDK 1.7 進行開發的,最好保持環境一致

1.1 2017/06/05 更新


Oracle 已不提供 JDK 1.7 的載點,從GOOGLE找到FTP載點下載 jdk-7u80-linux-x64.tar.gz,並手動安裝
安裝 Tomcat7 之後,再安裝 JDK 1.7的話,有可能會被 OpenJDK 蓋過設定。記得RECHECK
  1. tar -xzvf jdk-7u80-linux-x64.tar.gz
  2. sudo mv jdk1.7.0_80/ /usr/lib/jvm/
  3.  
  4. sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.7.0_80/bin/java" 1
  5. sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.7.0_80/bin/javac" 1
  6. sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.7.0_80/bin/javaws" 1
  7.  
  8. sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      auto mode
  1            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      manual mode
  2            /usr/lib/jvm/jdk1.7.0_80/bin/java                1         manual mode

Press enter to keep the current choice[*], or type selection number: 2
Java Version
  1. java -version
java version "1.7.0_80" 
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

1.2 In CentOS 7 (Older way)


  1. # 下載 JDK 1.7
  2. wget \
  3. --no-cookies \
  4. --no-check-certificate \
  5. --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" \
  6. -O jdk-7u80-linux-x64.rpm \
  7. http://download.oracle.com/otn-pub/java/jdk/7u80-b15/jdk-7u80-linux-x64.rpm
  8.  
  9. # root 權限安裝
  10. rpm -ivh jdk-7u80-linux-x64.rpm
  11.  
  12. # Java will be installed into /usr/java
  13. ll /usr/java/
total 4
lrwxrwxrwx 1 root root   16 Mar  6 10:52 default -> /usr/java/latest
drwxr-xr-x 8 root root 4096 Mar  6 10:52 jdk1.7.0_80
lrwxrwxrwx 1 root root   21 Mar  6 10:52 latest -> /usr/java/jdk1.7.0_80

1.3 In Ubuntu OS (Older way)


參考 https://help.ubuntu.com/community/Java
  1. sudo add-apt-repository ppa:webupd8team/java
  2. sudo apt-get update
  3. sudo apt-get install oracle-java7-installer

安裝成功後,路徑應為 /usr/lib/jvm/java-7-oracle


2. Install Tomcat 7


因為產品是使用 Java Servlet ,所以選擇 Tomcat 7
  1. # 下載 Tomcat 7 tar,直接佈署
  2. wget http://ftp.tc.edu.tw/pub/Apache/tomcat/tomcat-7/v7.0.76/bin/apache-tomcat-7.0.76.tar.gz
  3.  
  4. # 解壓縮
  5. tar -xf apache-tomcat-7.0.76.tar.gz
  6.  
  7. # 搬到 /usr/local/tomcat7,需要 root 權限
  8. mv apache-tomcat-7.0.76 /usr/local/tomcat7
當要執行/結束 Tomcat 7 時,可以下指令
  1. # 先移動到 Tomcat7 目錄
  2. cd /usr/local/tomcat7/
  3.  
  4. # Start script
  5. ./bin/startup.sh
  6.  
  7. # Shutdown script
  8. ./bin/shutdown.sh

2.1 Tomcat Service Script


不過每次都要這麼做,其實也蠻累的
重點是,我還想讓它可以開機時啟動啊

2.1.1 Systemctl command


CentOS 7 使用 systemctl 取代 service 指令

i). Tomcat 7 Environment Setup

Tomcat 建議可以建立 setenv.sh/setenv.bat 來設定環境
在執行 catalina.sh 時,如果 setenv.sh 存在時就會自動執行
預設是不存在,所以手動建立新檔案 /usr/local/tomcat7/bin/setenv.sh
可參考 https://gist.github.com/patmandenver/cadb5f3eb567a439ec01

  1. #
  2. # Cutom Environment Variables for Tomcat
  3. #
  4. ############################################
  5. export JAVA_HOME=/usr/java/jdk1.7.0_80/jre
  6. export PATH=${JAVA_HOME}/bin:${PATH}
  7.  
  8. ############################################
  9. #
  10. # JAVA_OPTS
  11. # You could do all this in one export command
  12. # But I am going to be long winded and explain
  13. # Why and add links
  14. #
  15. # Oracle Notes
  16. # - https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
  17. # - A good visual
  18. # https://redstack.wordpress.com/2011/01/06/visualising-garbage-collection-in-the-jvm/
  19. #############################################
  20.  
  21. # -server
  22. # Select the java HotSpot Server JVM
  23. # The 64-bit version of the JDK support only the Server VM,
  24. # so in that case the option is implicit
  25. # ... so it's redundant to today's world but it make me feel good.
  26. export JAVA_OPTS="-server"
  27.  
  28. # -Xms/Xmx
  29. # Xms Sets the initial size of the Heap
  30. # Xmx sets the Maximum size of the Heap.
  31. # http://stackoverflow.com/questions/16087153/what-happens-when-we-set-xmx-and-xms-equal-size
  32. # http://crunchify.com/jvm-tuning-heapsize-stacksize-garbage-collection-fundamental/
  33. export JAVA_OPTS="$JAVA_OPTS -Xms1024M -Xmx1024M"
  34.  
  35. # -NewSize/MaxNewSize
  36. # Set the size of the young generation
  37. # Most newly created objects are made here
  38. # Objects taht did not become unreachbale and survice the young
  39. # Generation heap are copied to the Old Generation
  40. # See http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection
  41. # https://redstack.wordpress.com/2011/01/06/visualising-garbage-collection-in-the-jvm/
  42. export JAVA_OPTS="$JAVA_OPTS -XX:NewSize=512m -XX:MaxNewSize=512m"
  43.  
  44. # -PermSize/MaxPermSize
  45. # Store classes and interned character strings
  46. # http://stackoverflow.com/questions/12114174/what-does-xxmaxpermsize-do
  47. # Warning!
  48. # Decprecated in Java 8!! replace -XX:MetaspaceSize !!!
  49. export JAVA_OPTS="$JAVA_OPTS -XX:PermSize=256m -XX:MaxPermSize=256m"
  50.  
  51. # -HeapDumpPath
  52. # Set the file where the heap dump will write out its error
  53. export JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=/usr/local/tomcat/logs/java_heapdump_pid_%p.log"
  54.  
  55. # -java.security.egd
  56. # This one is abit of a debate
  57. # If you don't set this it will use /dev/random on startup
  58. # which can block and make tomcat startup slower.
  59. # But it's technically more secure... but no one has shown
  60. # a way to break the results of urandom which is faster.
  61. # For more details see.
  62. # http://www.2uo.de/myths-about-urandom/
  63. export JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
  64.  
  65. #################################################
  66. # CATALINA_OPTS
  67. # This are basically JAVA_OPTS but only used by tomcat
  68. # and only run on Tomcat start see
  69. # http://stackoverflow.com/questions/11222365/catalina-opts-vs-java-opts-what-is-the-difference
  70. # for more details
  71. #
  72. ################################################
  73.  
  74. # Add tomcat pid
  75. CATALINA_PID="$CATALINA_BASE/tomcat.pid"


ii). Tomcat 7 Systemctl Script

在 /usr/lib/systemd/system 中,新建新檔案 tomcat7.service
由於指定了一般使用者 ciserver,所以 PIDFile path 要在這個使用者有權限的地方
(不然通常是放在 /var/run/)
  1. [Unit]
  2. Description=Apache Tomcat 7
  3. After=syslog.target network.target
  4.  
  5. [Service]
  6. Type=forking
  7.  
  8. PIDFile=/usr/local/tomcat7/tomcat.pid
  9. ExecStart=/usr/local/tomcat7/bin/startup.sh
  10. ExecReload=/bin/kill -s HUP $MAINPID
  11. ExecStop=/bin/kill -s QUIT $MAINPID
  12. PrivateTmp=true
  13.  
  14. User=ciserver
  15. Group=ciserver
  16.  
  17. [Install]
  18. WantedBy=multi-user.target

常用指令 (需 root)
  1. # 當修改檔案內容後,都需要重新 LOAD
  2. systemctl daemon-reload
  3.  
  4. # 執行
  5. systemctl start systemd-tomcat
  6.  
  7. # 停止
  8. systemctl stop systemd-tomcat
  9.  
  10. # 開機時自動執行
  11. systemctl enable systemd-tomcat
  12.  
  13. # 取消開機自動執行
  14. systemctl disable systemd-tomcat

2.1.2 Service command (Older way)


上網找了大大提供的 tomcat service script
下載並修改內容中的名稱與路徑,放到 /etc/init.d/tomcat7
  1. #!/bin/bash
  2. #
  3. # tomcat
  4. #
  5. # chkconfig: 345 96 30
  6. # description: Start up the Tomcat servlet engine.
  7. #
  8. # processname: java
  9. # pidfile: /var/run/tomcat.pid
  10. #
  11. ### BEGIN INIT INFO
  12. # Provides: tomcat
  13. # Required-Start: $network $syslog
  14. # Required-Stop: $network $syslog
  15. # Should-Start: distcache
  16. # Short-Description: start and stop Apache HTTP Server
  17. # Description: implementation for Servlet 2.5 and JSP 2.1
  18. ## END INIT INFO
  19.  
  20. # Source function library.
  21. . /etc/init.d/functions
  22.  
  23. ## tomcat installation directory. *[改這裡]
  24. PROCESS_NAME=tomcat
  25.  
  26. ## *[改這裡]
  27. CATALINA_HOME="/usr/local/tomcat7/"
  28.  
  29. ## run as a diffent user. *[改這裡]
  30. TOMCAT_USER=ciserver
  31.  
  32. ## Path to the pid, runnning info file
  33. pidfile=${PIDFILE-/var/run/${PROCESS_NAME}.pid};
  34. lockfile=${LOCKFILE-/var/lock/subsys/${PROCESS_NAME}};
  35.  
  36. RETVAL=0
  37.  
  38. case "$1" in
  39. start)
  40. PID=`pidofproc -p ${pidfile} ${PROCESS_NAME}`
  41. if [[ (-n ${PID}) && ($PID -gt 0) ]]; then
  42. logger -s "${PROCESS_NAME}(pid ${PID}) is already running."
  43. exit;
  44. fi
  45. if [ -f $CATALINA_HOME/bin/startup.sh ];
  46. then
  47. logger -s "Starting Tomcat"
  48. /bin/su -l ${TOMCAT_USER} -c "$CATALINA_HOME/bin/startup.sh -Dprocessname=${PROCESS_NAME}"
  49. PID=`ps -eaf|grep processname=${PROCESS_NAME}|grep -v grep|awk '{print $2}'`
  50. RETVAL=$?
  51. [ $RETVAL = 0 ] && touch ${lockfile}
  52. [ $RETVAL = 0 ] && echo "${PID}" > ${pidfile}
  53. fi
  54. ;;
  55. stop)
  56. PID=`pidofproc -p ${pidfile} ${PROCESS_NAME}`
  57. ## if PID valid run shutdown.sh
  58. if [[ -z ${PID} ]];then
  59. logger -s "${PROCESS_NAME} is not running."
  60. exit;
  61. fi
  62.  
  63. if [[ (${PID} -gt 0) && (-f $CATALINA_HOME/bin/shutdown.sh) ]];
  64. then
  65. logger -s "Stopping Tomcat"
  66. /bin/su -l ${TOMCAT_USER} -c "$CATALINA_HOME/bin/shutdown.sh"
  67. RETVAL=$?
  68. [ $RETVAL = 0 ] && rm -f ${lockfile}
  69. [ $RETVAL = 0 ] && rm -f ${pidfile}
  70. fi
  71. ;;
  72. status)
  73. status -p ${pidfile} ${PROCESS_NAME}
  74. RETVAL=$?
  75. ;;
  76. restart)
  77. $0 stop
  78. $0 start
  79. ;;
  80. version)
  81. if [ -f $CATALINA_HOME/bin/version.sh ];
  82. then
  83. logger -s "Display Tomcat Version"
  84. /bin/su -l ${TOMCAT_USER} -c "$CATALINA_HOME/bin/version.sh"
  85. RETVAL=$?
  86. fi
  87. ;;
  88. *)
  89. echo $"Usage: $0 {start|stop|restart|status|version}"
  90. exit 1
  91. ;;
  92. esac
  93. exit $RETVAL

2.2 tomcat-users.xml 設定檔


Setup User Accounts ,讓 Jenkins 把 Web 專案佈署在 Tomcat7 上
  1. cd /usr/local/tomcat7
  2.  
  3. # Edit conf/tomcat-users.xml file and paste inside <tomcat-users></tomcat-users>
  4. <!-- For IDE/Jenkins can manager tomcat -->
  5. <role rolename="manager-script" />
  6. <user username="manager" password="_SECRET_PASSWORD_" roles="manager-script" />

2.3 Enable HTTPS + AuthBind


自己產生一個憑證供使用
  1. cd /usr/local/tomcat7/
  2. mkdir keystore
  3. cd keystore
  4.  
  5. # Generate the keystore
  6. # keytool -genkey -alias tomcat -keyalg RSA -keysize 2048 -keystore tomcat.keystore
Enter keystore password:                   # {password}自行輸入
Re-enter new password: 
What is your first and last name?
  [Unknown]:  Clone Lin
What is the name of your organizational unit?
  [Unknown]:  private
What is the name of your organization?
  [Unknown]:  private
What is the name of your City or Locality?
  [Unknown]:  Taiwan
What is the name of your State or Province?
  [Unknown]:  Clone
What is the two-letter country code for this unit?
  [Unknown]:  tw
Is CN=Clone Lin, OU=private, O=private, L=Taiwan, ST=Clone, C=tw correct?
  [no]:  yes

Enter key password for 
 (RETURN if same as keystore password):  
Re-enter new password:


# ll
total 4
-rw-rw-r-- 1 clone clone 2232 Mar  9 08:44 tomcat.keystore
修改 tomcat server 設定,開啟 SSL/TLS port 443
  1. cd /usr/locat/tomcat7/
  2.  
  3. # Edit conf/server.xml
  4. <Connector port="443" protocol="HTTP/1.1"
  5. maxThreads="200"
  6. redirectPort="8443"
  7. URIEncoding="UTF-8"
  8. scheme="https" secure="true" SSLEnabled="true"
  9. keystoreFile="/usr/local/tomcat7/keystore/tomcat.keystore"
  10. keystorePass="_SECRET_PASSWORD_"
  11. clientAuth="false" sslProtocol="TLS" />

當 Bind port number < 1024 時,會需要 root 權限。但我又不想讓 tomcat 有 root 權限
這裡使用 AuthBind 使 User 可以成功 Bind port 443

因為 CentOS 沒辦法使用 yum 安裝,所以要下載編譯後安裝
GitHub : https://github.com/tootedom/authbind-centos-rpm

  1. # 下載並編譯安裝
  2. wget http://ftp.debian.org/debian/pool/main/a/authbind/authbind_2.1.1.tar.gz
  3. tar -xf authbind_2.1.1.tar.gz
  4. cd authbind-2.1.1/
  5. make
  6. # root 權限安裝
  7. make install
  8.  
  9. # 開啟 tomcat 將使用的port (這裡的動作都要root 權限)
  10. touch /etc/authbind/byport/443
  11. chmod 500 /etc/authbind/byport/443
  12. chown {username}:{group} /etc/authbind/byport/443
  13.  
  14. # Tomcat 若是 yum 安裝,預設帳號與群組是 “tomcat”
  15.  
  16. # 修改啟動 Tomcat Server 的腳本
  17. # 可以修改 /usr/local/tomcat/bin/catalina.sh or /usr/local/tomcat/bin/startup.sh
  18. # 這裡選擇修改 startup.sh
  19. # 將原本執行的指令註解,新增 authbind --deep。修改後結果如下:
  20.  
  21. #exec "$PRGDIR"/"$EXECUTABLE" start "$@"
  22. exec authbind --deep "$PRGDIR"/"$EXECUTABLE" start "$@"

到這一步,重啟Tomcat Server就可以了

2.4 Iptables rules


預設是擋掉的,自已增加規則
這裡用 8080 port 舉例,443 port 也是用相同做法
(iptables -A means Append; iptables -I means Insert)
  1. # 嚴謹一點的像是
  2. iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT -m comment --comment "Tomcat Server port"
  3.  
  4. # 簡單一點的就是
  5. iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
  6.  
  7. # 顯示目前 IPTABLES 規則
  8. iptables-save
  9.  
  10. # 儲存 IPTABLES 規則
  11. # CentOS 已經改用 Firewalld 取代 IPTABLES 了,可以使用下列指令新增規則
  12. # 若不加上 --permanent 表示為 Runtime rule,不會儲存
  13. firewall-cmd --zone=public --add-port=443/tcp --permanent
  14.  
  15. # 重新載入,確認是否成功
  16. firewall-cmd --reload

3. Install Jenkins 2.48


官網 : https://jenkins.io/

有兩種安裝方式,一種是下載 war 檔案,放到 tomcat/webapp 中執行口別一種是使用 RPM 安
裝方式
這裡使用 war 方式安裝
  1. # 選擇 stable 版本
  2. wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war
  3. cp jenkins.war /usr/local/tomcat7/webapps/

打開 Browser,輸入 URL: http://127.0.0.1/jenkins/
第一次安裝 Jenkins 時,會提示輸入安裝密碼
按照提示將密碼貼到對應的輸入框即可

  1. cat /home/clone/.jenkins/secrets/initialAdminPassword
60a9fe50f451436b987979704006b33a

安裝類型有 通用安裝 / 自定義安裝

安裝過程較長,成功畫面如下


上圖是測試安裝的截圖,是英文版的
後來選擇 Jenkins stable 版本,安裝後是中文版的

沒有留言:

張貼留言