Jenkins

Types of Jenkins Projects

TypeDescription
Freestyle簡單、單一任務,如 run test
Pipeline完整交付週期:test → build → … 針對單一分支
Multi-branch Pipeline類似 Pipeline,但支援多分支

Credential Scopes

ScopeDescription
System僅在 Jenkins Server 上可用,不適用於 Jenkins Jobs
Global全域可存取
Project僅限專案使用,僅適用於 multi-branch pipeline

Trigger Build

Push Notification

Version Control 在新 Commit 時通知 Jenkins:

  1. 根據 VCS 安裝 Jenkins Plugin
  2. 設定 Repository Server Hostname
  3. 新增 Access Token / Credential

Polling

Jenkins 定期輪詢檢查。

Plugins

  • Matrix Authorization Strategy
  • Role-based Authorization Strategy
  • Backup: ThinBackup

System Administration

Backup

  • Filesystem Snapshots - 日常備份
  • 使用備份 Plugins
  • 編寫備份 Jenkins instance 的 shell script

Files To Backup

  flowchart TD
	home[$JENKINS_HOME]
	config.xml[Configuration files]
	j[jobs]

	home ----> config.xml
	home ----> j

Pipelines

Jenkinsfile - Declarative

  • 較容易入門
  • pipeline:必須是最上層
  • agent:指定在哪裡執行(Build Agent)
  • stages:工作發生的地方
    • stage
    • steps
pipeline {
	agent any

	stages {
		stage("build") {
			steps {
				echo "building the application..."

				script {
					def test = 2 + 2 > 3 ? 'cool' : 'not cool'
					echo test
				}
			}
		}

		stage("test") {
			steps {
				echo "testing the application..."
			}
		}

		stage("deploy") {
			steps {
				echo "deploying the application..."
			}
		}
	}
}

Go Pipeline Demo

設定:Manage Jenkins -> Tools -> Go

pipeline {
    agent any
    tools {
        go 'Go1.19'
    }

    environment {
        GO111MODULE='on'
    }

    stages {
        stage('Test') {
            steps {
                git '<Repo URL>'
                sh 'go test ./...'
            }
        }
    }
}

Docker Container Agent

pipeline {
    agent {
        docker { image 'golang:latest' }
    }

    stages {
        stage('Dev') {
            steps {
                git 'https://github.com/kodekloudhub/go-webapp-sample.git'
                sh 'go version'
            }
        }
    }
}

Multi Nodes Pipeline

pipeline {
    agent none
    stages {
        // DEV
        stage('Build Dev') {
            agent {
              label {
                label 'dev'
                customWorkspace "/opt/go-app"
              }
            }
            steps {
                sh 'git pull'
            }
        }
        stage('Test Dev') {
            agent {
              label {
                label 'dev'
                customWorkspace "/opt/go-app"
              }
            }
            steps {
                sh 'go test ./...'
            }
        }
        stage('Deploy Dev') {
            agent {
              label {
                label 'dev'
                customWorkspace "/opt/go-app"
              }
            }
            steps {
              script {
                withEnv ( ['JENKINS_NODE_COOKIE=do_not_kill'] ) {
                  sh 'go run main.go &'
                  }
                }
            }
        }
        // PROD
        stage('Build Prod') {
            agent {
              label {
                label 'prod'
                customWorkspace "/opt/go-app"
              }
            }
            steps {
                sh 'git pull'
            }
        }
    }
}

SonarQube Integration

Plugin: SonarQube Scanner

pipeline {
    agent any

    tools {
        jdk 'jdk17'
        maven 'maven'
    }

    stages {
        stage('Build') {
            steps {
                sh "mvn clean package"
            }
        }
        stage('Sonar Analysis') {
            steps {
                withSonarQubeEnv(installationName: 'SonarQube', envOnly: true){
                    sh "mvn sonar:sonar"
                }
            }
        }
    }
}

Scripted Pipeline

  • 第一種語法
  • Groovy engine
  • 進階腳本能力,高靈活性
node {
	// scripted pipeline content
}

Build Agents

  • Windows
  • Linux
  • MacOS
  • Docker
  • 建議:分離 Jenkins Server / Build Server

Security

Access Control

  • Authentication(身份驗證):使用 security realm 完成。Security realm 決定使用者身份和群組成員資格。
  • Authorization(授權):由 authorization strategy 完成。控制使用者(直接或透過群組成員資格)是否擁有權限。

Common Mistakes

  • Anyone can do anything
  • Logged-in users can do anything
  • Anonymous and authenticated users
  • Built-in node(在 built-in node 上執行的建置與 Jenkins 程序擁有相同的檔案系統存取權限)

CLI

Service Management

sudo systemctl status jenkins
sudo systemctl start jenkins
sudo systemctl stop jenkins
sudo systemctl restart jenkins

SSH Authentication

設定 SSH Key:

ls /home/mike/.ssh/
# jenkins_key  jenkins_key.pub

複製 SSH key 到 Jenkins member setting:

cat /home/mike/.ssh/jenkins_key.pub

設定 SSH service 監聽固定 port:

curl -Lv http://localhost:8085/login 2>&1 | grep -i 'x-ssh-endpoint'
# < X-SSH-Endpoint: 8085-port-3972baa465004b83.labs.kodekloud.com:8022

透過 SSH 與 Jenkins 互動:

ssh -i /home/mike/.ssh/jenkins_key -l mike -p 8022 jenkins-server help

重啟 Jenkins:

ssh -i /home/mike/.ssh/jenkins_key -l mike -p 8022 jenkins-server safe-restart

User Authentication

java -jar jenkins-cli.jar -s http://localhost:8085 -auth 'admin:Adm!n321'

Setup

Linux (CentOS)

sudo yum install epel-release -y
sudo yum install java-11-openjdk -y
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo --no-check-certificate
sudo rpm --import http://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
sudo yum install jenkins -y

修改 Port:

sudo vi /lib/systemd/system/jenkins.service
Environment="JENKINS_PORT=8090"

取得初始密碼:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Docker

docker pull jenkins/jenkins:lts-jdk17
docker run -p 9992:8080 -p 50000:50000 -d \
  -e JAVA_OPTS="-Djava.awt.headless=true -Dhudson.plugins.git.GitSCM.ALLOW_LOCAL_CHECKOUT=true" \
  -v "D:\Project-Workspace\Docker-Mount\jenkins_data_17_lts":/var/jenkins_home \
  jenkins/jenkins:lts-jdk17
  • Port 8080:Jenkins Web UI
  • Port 50000:Master / Slave Communication

Import Local Repository

file:///home/path/to/repo

Errors

Failed Loading global config

備份 /root/.jenkins/config.xml,然後刪除 <authorizationStrategy><useSecurity> 標籤,再重啟。