[CI/CD Pipeline] 5. SonarQube + Jenkins Cloud
- SonarQube 사용하기
- SonarQube + Maven 프로젝트 사용하기
- Bad code 조사하기
- Jenkins + SonarQube 연동
- SonarQube 사용을 위한 Pipeline 사용하기
- Jenkins Multi nodes 구성하기 - Master + Slaves
- Jenkins Node 추가하기
- Jenkins Slave Node 에서 빌드하기
SonarQube 사용하기
정적 분석 도구 SonarQube 와 Jenkins 연동
SonarQube 특징
- Continuous Integration + Analysis (지속적인 통합과 분석을 할 때 사용하는 솔루션)
- 코드에 대한 품질을 높이기 위해서 코드가 가진 Issue, Defect, 복잡성을 분석
- Detect Bugs & Vulnerabilities
- Track Code Smells: 코드안에 불필요한 코드, 이상 여부를 탐지
- 코드의 품질을 높여주는 용도로 사용
- 17 languages 지원
- Java, C#, JavaScript, CloudFormation, Terraform, Kotlin, Ruby, Go, Scala, Flex, Python, PHP, HTML, CSS, XML, VB.NET
- CI/CD Integration
- Extensible, with 50+community plugins
Install SonalQube
docker pull sonarqube
docker run --rm -p 9000:9000 --name sonarqube sonarqube
결과
SonarQube + Maven 프로젝트 사용하기
- Maven Project에 Plugin 설정 추가
- https://docs.sonarqube.org/latest/analysis/scan/sonarqube-for-maven
- SonarQube 플러그인을 추가하게되면 Maven 빌드를 통해서 SonarQube로 정보를 전달할 수 있다.
SonarQube token 생성
- id: admin
- password: admin -> admin123
- My account -> Security -> User Token 생성
- 인증 정보를 위한 토큰 정보 생성 sonar-token: squ_f37e06dc0cc6d7232e388a09f19b78c4db8f430a
Maven build
- mvn sonar:sonar -Dsonar.host.url=http://IP_address:9000 -Dsonar.login=[sonar-token]
SonarQube Projects 확인
- 특별한 문제가 없기 때문에 passed 라고 표시
Bad code 조사하기
- 샘플 프로젝트에 아래 코드 추가
@Controller
public class WelcomeController {
private final Logger logger = LoggerFactory.getLogger(WelcomeController.class);
@GetMapping("/")
public String index(Model model) {
logger.debug("Welcome to njonecompany.com...");
model.addAttribute("msg", getMessage());
model.addAttribute("today", new Date());
System.out.println("index is called by GET /");
return "index";
}
}
- 위 코드처럼 print 문장 삽입
- print 문장이 문제가 되는 부분은 아니지만 실제 운영서버에 print 문장에 의해 IO에 대한 리소스를 사용하기 때문에 프로젝트 성능을 낮춘다.
결과
- 위와 같은 결과를 표시해줌으로써 SonarQube에서 통과되지 않는 경우에 빌드 작업을 진행하지 않고 코드를 개선한 후에 다시 SonarQube에서 문제가 없는 경우에 CI/CD 작업을 진행
Jenkins + SonarQube 연동
Jenkins 관리 -> 플러그인 관리 -> 설치가능 -> SonarQube Scanner
Jenkins 관리 -> Manage Credentials -> Add Credentials
- Jenkins 관리 -> Configure System -> SonarQube servers
- docker inspect network bridge 를 통해 ip 확인
SonarQube 사용을 위한 Pipeline 사용하기
- My-Third-Pipeline 수정
결과
Jenkins Multi nodes 구성하기 - Master + Slaves
Jenkins Master + Slaves
현재까지 Jenkins 를 단일 서버로 구성하여 사용 -> Jenkins Master
Jenkins Master 에서 사용자의 요청에 의해서 빌드, 배포하는 작업을 진행했다. 이제는 자신에게 추가된 Slave 에게 작업을 전달하여 업무를 분할
Jenkins Slave
- Remote에서 실행되는 Jenkins 실행 Worker Node
- Jenkins Master 의 요청 처리 -> 빌드, 배포와 같은 요청 처리
- Master로부터 전달된 Job 실행
- 다양한 운영체제에서 실행 가능
- Jenkins 프로젝트 생성 시 특정 Slave를 선택하여 실행 가능
이렇게 분할해줌으로써 Master Node 는 클라이언트의 빌드, 배포 요청을 받은 다음에 자신이 직접 처리하는게 아닌 리소스가 확보된 Slave Node 에 작업을 전달하고 결과를 받아서 처리할 수 있다.
Jenkins Node 추가하기
Docker Container 형태로 추가
docker run -itd --name jenkins-node1 -p 30022:22 -e container=docker --tmpfs /run --tmpfs /tmp -v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /var/run/docker.sock:/var/run/docker.sock edowon0623/docker:latest /usr/sbin/init
Slave Node Jdk 설치
Jenkins Slave 에서는 Master Node 로 부터 전달받은 Job을 자신이 처리하고 결과를 반환한다. Slave Node 에서 작업을 Master 노드로 부터 전달받은 작업을 처리하기 위해서 JVM이 필요하다.
yum list java*jdk-devel
yum install -y java-11-openjdk-devel.x86_64
Jenkins Master Node 에서 Slave Node 로 SSH 접속하기 위한 Key 생성
ssh-keygen
ssh-copy-id root@[slave node IP]
Add a slave node
- Jenkins 관리 -> 노드 관리 -> 신규 노드
- Number of executors: 추가하고 있는 노드에서 Master 로 부터 작업(빌드, 배포 요청)을 받았을 때 동시에 처리할 수 Job의 최대 개수
- Remote root directory: 해당 경로로 빌드가 성공했을 때 workspace를 만들고 결과물을 복사한다, 없는 경우에 미리 폴더를 만들어야한다.
- Labels: 현재 사용 중인 Jenkins 프로젝트에서 다른 쪽의 프로젝트, 파이프라인이 현재 추가하는 노드를 지칭하고자 할 때 사용하는 이름
- Usage: Use this node as much as possible -> Master 가 어떠한 규칙에 의해서 Slave 를 선택할지를 결정
- Launch method: master 노드에서 slave 노드로 접속할 때 어떤 방식으로 접속할 지에 대한 정보
- Credential 추가
Node 추가 결과
My-First-Project 수정
- Restrict where this project can be run 선택
- Label Expression: slave1
- 해당 프로젝트가 어디에만 빌드, 배포될지를 결정
빌드 결과
Jenkins Slave Node 에서 빌드하기
Pipeline 프로젝트를 slave 노드에서 실행
Build Stage 추가
pipeline {
agent {
label 'slave1'
}
tools {
maven 'Maven3.8.5'
}
stages {
stage('github clone') {
steps {
git branch: 'main', url: 'https://github.com/yoon-youngjin/Construction-of-CI-CD-Pipeline-using-Jenkins.git';
}
}
stage('build') {
steps {
sh '''
echo build start
mvn clean compile package -DskipTests=true
'''
}
}
}
}
- agent: slave1 Node 에 현재 pipeline을 빌드
빌드 결과
Slave2 Node 추가
docker run --privileged --name jenkins-node2 -itd -p 40022:22 -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup --cgroupns=host edowon0623/docker:latest /usr/sbin/init
앞에서 진행한 Jenkins에 Node 추가하는 작업 진행
Slave2 Node에 빌드
pipeline {
agent {
label 'slave2'
}
tools {
maven 'Maven3.8.5'
}
stages {
stage('github clone') {
steps {
git branch: 'main', url: 'https://github.com/yoon-youngjin/Construction-of-CI-CD-Pipeline-using-Jenkins.git';
}
}
stage('build') {
steps {
sh '''
echo build start
mvn clean compile package -DskipTests=true
'''
}
}
}
}
결과