CI/CD DevOps 流水线项目:在 Kubernetes 上部署 Java 应用程序
介绍
在当今快节奏的软件开发环境中,对于追求敏捷性、效率和高质量软件交付的组织而言,实施 DevOps 实践至关重要。本项目演示了如何使用Jenkins实现强大的持续集成/持续部署 (CI/CD)流水线,从而实现从开发到部署的整个软件生命周期的自动化。
建筑学
目标
该项目的主要目标是实现软件交付自动化,提高速度、可靠性和效率,同时最大限度地减少人工干预。主要目标包括:
- 自动化 CI/CD 管道:实施基于 Jenkins 的无缝 CI/CD 管道,以简化构建、测试和部署流程。
- DevOps 工具的集成:利用Maven、SonarQube、Trivy、Nexus Repository、Docker、Kubernetes、Prometheus 和 Grafana实现端到端自动化。
- 代码质量和安全:通过静态代码分析(SonarQube)和安全漏洞扫描(Trivy)提高软件质量。
- 可扩展部署:确保Kubernetes 集群上的部署可靠、可扩展且负载均衡。
- 自动通知:启用构建和部署状态的电子邮件警报。
- 强大的监控和警报:实施Prometheus 和 Grafana进行实时系统健康监控和性能分析。
使用的工具和技术
工具 | 目的 |
---|---|
詹金斯 | CI/CD 管道编排 |
Maven | 构建自动化和依赖管理 |
SonarQube | 静态代码分析以确保质量 |
琐事 | Docker镜像漏洞扫描 |
Nexus 存储库 | 工件管理和版本控制 |
Docker | 容器化以实现一致性和可移植性 |
Kubernetes | 可扩展部署的容器编排 |
Gmail 集成 | 构建和部署更新的电子邮件通知 |
普罗米修斯和格拉法纳 | 系统指标的监控和可视化 |
AWS EC2 | 基础设施配置和托管 |
基础设施设置:AWS 上的虚拟机
为了支持此管道,AWS EC2 实例已为各种 DevOps 工具进行了配置:
🔹 Kubernetes 主节点:管理集群状态、调度和协调。🔹
Kubernetes工作节点(2) :托管和执行容器化应用程序。🔹
SonarQube服务器:执行静态代码分析以确保代码质量。🔹 Nexus 存储库管理器:管理构建工件、依赖项和 Docker 镜像。🔹 Jenkins 服务器 :协调 CI/CD 流程并集成 DevOps 工具。🔹监控服务器 :运行Prometheus 和 Grafana进行实时系统监控。
每个实例都配置了必要的 CPU、内存和存储资源。我们采用了访问控制和网络配置等安全最佳实践来保护基础设施。
EC2实例:
安全组:
使用 Kubeadm 设置 Kubernetes 集群
先决条件
- 具有sudo 权限的Ubuntu 操作系统(Xenial 或更高版本)
- t2.medium实例类型或更高版本
- 互联网接入
- 确保所有 AWS 实例都位于同一安全组中
- 打开端口 6443以允许工作节点加入集群
1️⃣ 准备 Kubernetes 安装节点
在Master 节点和 Worker 节点上分别运行以下命令:
# Disable swap
sudo swapoff -a
加载所需的内核模块:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
设置sysctl参数:
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
2️⃣ 安装 CRI-O 运行时
sudo apt-get update -y
sudo apt-get install -y software-properties-common curl apt-transport-https ca-certificates gpg
sudo curl -fsSL https://pkgs.k8s.io/addons:/crio:/prerelease:/main/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/prerelease:/main/deb/ /" | sudo tee /etc/apt/sources.list.d/cri-o.list
sudo apt-get update -y
sudo apt-get install -y cri-o
sudo systemctl enable crio --now
3️⃣ 安装 Kubernetes 软件包
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update -y
sudo apt-get install -y kubelet=1.29.0-* kubectl=1.29.0-* kubeadm=1.29.0-*
4️⃣ 在主节点上初始化 Kubernetes 集群
sudo kubeadm config images pull
sudo kubeadm init
mkdir -p "$HOME"/.kube
sudo cp -i /etc/kubernetes/admin.conf "$HOME"/.kube/config
sudo chown "$(id -u)":"$(id -g)" "$HOME"/.kube/config
安装Calico作为网络插件:
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml
检索工作节点的加入命令:
kubeadm token create --print-join-command
5️⃣ 加入工作节点
运行从主节点获取的加入命令:
sudo kubeadm join <master-ip>:6443 --token <your-token> --discovery-token-ca-cert-hash sha256:<hash> --v=5
在主节点上验证集群状态:
kubectl get nodes
设置 DevOps 工具
Jenkins 安装
sudo apt install openjdk-17-jre-headless -y
wget -O /usr/share/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/" | sudo tee /etc/apt/sources.list.d/jenkins.list
sudo apt-get update
sudo apt-get install jenkins -y
Docker 安装
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
Nexus 存储库设置
docker run -d --name nexus -p 8081:8081 sonatype/nexus3:latest
检索 Nexus管理员密码:
docker exec -it <container_id> cat /nexus-data/admin.password
第 2 部分:设置私有 Git 存储库
按照以下步骤创建私有 Git 存储库,生成个人访问令牌,连接到存储库并安全地推送代码。
1.创建私有 Git 仓库
- 登录您喜欢的 Git 托管平台(例如,GitHub、GitLab、Bitbucket)。
- 导航到“存储库”部分。
- 单击“新建存储库”并将其可见性设置为“私有”。
- 复制存储库 URL 以供稍后使用。
2. 生成个人访问令牌(PAT)
- 转到您的帐户设置。
- 找到开发人员设置(GitHub)或访问令牌部分(GitLab、Bitbucket)。
- 生成具有所需权限的新个人访问令牌 (PAT),例如:
- repo(用于完整存储库访问)
- read:packages(如果访问包)
- 复制并安全保存令牌,因为它不会再次显示。
3. 本地克隆存储库
- 打开终端或 Git Bash。
- 导航到您想要存储存储库的目录。
- 运行以下命令,替换
<repository_URL>
为您的实际存储库链接:
git clone <repository_URL>
- 导航到克隆的存储库文件夹:
cd <repository_name>
4. 将代码添加到存储库
- 在存储库目录中移动或创建项目文件。
5. 暂存并提交变更
- 暂存所有文件以供提交:
git add .
- 使用有意义的消息提交阶段性变更:
git commit -m "Initial commit: Added project files"
6. 将更改推送到私有存储库
- 将您的更改推送到远程存储库:
git push
- 如果这是您第一次推送,请设置上游分支并推送:
git push -u origin main
main
(如果适用,请用master
或任何其他分支名称替换。)
7. 使用个人访问令牌进行身份验证
- 当系统提示输入凭据时:
- 用户名:输入您的 GitHub/GitLab/Bitbucket 用户名。
- 密码:使用个人访问令牌 (PAT)代替您的密码。
8.验证推送
- 转到您的 Git 托管平台并打开存储库。
- 您应该会看到已提交的文件已成功上传。
第 3 部分:Jenkins 中的 CI/CD 设置
安装所需的 Jenkins 插件
在设置 CI/CD 管道之前,请安装以下 Jenkins 插件:
-
Eclipse Temurin 安装程序
- 使 Jenkins 能够安装和配置 Eclipse Temurin JDK(以前称为 AdoptOpenJDK)。
- 转到Jenkins 仪表板 → 管理 Jenkins → 管理插件 → 可用选项卡。
- 搜索Eclipse Temurin Installer,选择它,然后单击Install without restart。
-
管道 Maven 集成
- 为 Jenkins Pipelines 添加 Maven 支持,允许在脚本中使用 Maven 命令。
- 通过在插件管理器中搜索Pipeline Maven Integration来安装它。
-
配置文件提供程序
- 允许在 Jenkins 中集中存储配置文件(属性、XML、JSON)。
- 通过插件管理器安装。
-
SonarQube 扫描仪
- 集成 SonarQube 以便在构建期间进行代码质量和安全分析。
- 在插件管理器中搜索SonarQube Scanner并安装它。
-
Kubernetes CLI
- 使 Jenkins 能够使用与 Kubernetes 集群进行交互
kubectl
。 - 从插件管理器安装它。
- 使 Jenkins 能够使用与 Kubernetes 集群进行交互
-
Kubernetes 插件
- 允许 Jenkins 代理作为 Kubernetes pod 运行,实现动态扩展。
- 通过插件管理器安装。
-
Docker插件
- 使 Jenkins 能够与 Docker 交互以构建和管理容器。
- 从插件管理器安装它。
-
Docker 管道插件
- 通过构建、发布和管理 Docker 容器的步骤扩展 Jenkins Pipeline。
- 通过插件管理器安装它。
安装后,在管理 Jenkins → 全局工具配置中配置这些插件,并在需要时设置凭据。
创建 Jenkins CI/CD 管道
安装插件后,在 Jenkins 中创建一个新的Pipeline作业并使用以下脚本:
Jenkinsfile:用于 Java 应用程序部署的 CI/CD 管道
pipeline {
environment {
SCANNER_HOME = tool 'sonar-scanner'
}
tools {
jdk 'jdk17'
maven 'maven3'
}
stages {
stage('Git Checkout') {
steps {
git branch: 'main', credentialsId: 'git-cred', url: 'https://github.com/jaiswaladi246/Boardgame.git'
}
}
stage('Compile') {
steps {
sh "mvn compile"
}
}
stage('Run Tests') {
steps {
sh "mvn test"
}
}
stage('Trivy File System Scan') {
steps {
sh "trivy fs --format table -o trivy-fs-report.html ."
}
}
stage('SonarQube Code Analysis') {
steps {
withSonarQubeEnv('sonar') {
sh '''
$SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=BoardGame -Dsonar.projectKey=BoardGame -Dsonar.java.binaries=.
'''
}
}
}
stage('Quality Gate Check') {
steps {
script {
waitForQualityGate abortPipeline: false, credentialsId: 'sonar-token'
}
}
}
stage('Build Artifact') {
steps {
sh "mvn package"
}
}
stage('Publish Artifacts to Nexus') {
steps {
withMaven(globalMavenSettingsConfig: 'global-settings', jdk: 'jdk17', maven: 'maven3', traceability: true) {
sh "mvn deploy"
}
}
}
stage('Build and Tag Docker Image') {
steps {
script {
withDockerRegistry(credentialsId: 'docker-cred', toolName: 'docker') {
sh "docker build -t jaiswaladi246/Boardgame:latest ."
}
}
}
}
stage('Docker Image Security Scan') {
steps {
script {
withDockerRegistry(credentialsId: 'docker-cred', toolName: 'docker') {
sh "trivy image --format table -o trivy-image-report.html jaiswaladi246/Boardgame:latest"
}
}
}
}
stage('Push Docker Image to Registry') {
steps {
script {
withDockerRegistry(credentialsId: 'docker-cred', toolName: 'docker') {
sh "docker push jaiswaladi246/Boardgame:latest"
}
}
}
}
stage('Deploy to Kubernetes') {
steps {
withKubeConfig(credentialsId: 'k8-cred', namespace: 'webapps', serverUrl: 'https://172.31.8.22:6443') {
sh "kubectl apply -f deployment-service.yaml"
sh "kubectl get pods -n webapps"
}
}
}
}
post {
always {
script {
def jobName = env.JOB_NAME
def buildNumber = env.BUILD_NUMBER
def pipelineStatus = currentBuild.result ?: 'UNKNOWN'
def body = """
${jobName} - Build ${buildNumber}
Pipeline Status: ${pipelineStatus.toUpperCase()}
Check the console output.
"""
emailext(
subject: "${jobName} - Build ${buildNumber} - ${pipelineStatus.toUpperCase()}",
body: body,
to: 'jaiswaladi246@gmail.com',
from: 'jenkins@example.com',
replyTo: 'jenkins@example.com',
mimeType: 'text/html',
attachmentsPattern: 'trivy-image-report.html'
)
}
}
}
}
管道故障
-
Git 签出
- 使用凭证从 GitHub 克隆项目。
-
构建和测试
- 使用 Maven 编译项目并运行测试。
-
安全扫描
- 使用 Trivy 扫描文件系统和 Docker 镜像中的漏洞。
-
SonarQube 代码分析
- 运行 SonarQube 扫描以查找代码质量和安全问题。
-
质量门检查
- 确保在继续之前通过 SonarQube 质量门。
-
构建和发布工件
- 打包应用程序并将其推送至 Nexus。
-
Docker 镜像构建和推送
- 构建 Docker 镜像并将其推送到注册表。
-
部署到 Kubernetes
- 使用将应用程序部署到 Kubernetes 集群
kubectl
。
- 使用将应用程序部署到 Kubernetes 集群
-
通知
- 发送包含管道状态和 Trivy 安全报告的电子邮件通知。
第 4 部分:监控设置
Prometheus 安装和设置
下载 Prometheus 和 Exporters
- 从以下位置下载 Prometheus、Node Exporter 和 Blackbox Exporter:👉 Prometheus 下载
安装并运行 Prometheus
- 解压下载的
.tar.gz
文件。 - 导航到解压的目录并运行:
./prometheus &
- 默认情况下,Prometheus 在端口 9090上运行。
- 在浏览器中访问:
http://<instance_IP>:9090
安装并运行 Blackbox Exporter
- 提取 Blackbox Exporter
.tar.gz
文件。 - 导航到解压的目录并运行:
./blackbox_exporter &
Grafana 安装和设置
下载并安装 Grafana
- 从以下位置下载 Grafana:👉 Grafana 下载
或者,在 Ubuntu 上安装 Grafana
在监控虚拟机上运行以下命令:
sudo apt-get install -y adduser libfontconfig1 musl
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_10.4.2_amd64.deb
sudo dpkg -i grafana-enterprise_10.4.2_amd64.deb
启动 Grafana 服务
sudo /bin/systemctl start grafana-server
- Grafana默认在端口 3000上运行。
- 在浏览器中访问:
http://<instance_IP>:3000
配置 Prometheus
修改 Prometheus 配置(prometheus.yaml
)
编辑文件以包含 Blackbox Exporter:
scrape_configs:
- job_name: 'blackbox'
metrics_path: /probe
params:
module: [http_2xx] # Checks for HTTP 200 response
static_configs:
- targets:
- http://prometheus.io # HTTP Target
- https://prometheus.io # HTTPS Target
- http://example.com:8080 # HTTP on port 8080
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: <instance_IP>:9115
- 替换
<instance_IP>
为您的服务器的 IP 地址。
重启 Prometheus
- 查找 Prometheus 进程 ID:
pgrep prometheus
- 终止现有进程并重新启动 Prometheus。
在 Grafana 中添加 Prometheus 作为数据源
- 登录 Grafana (
http://<instance_IP>:3000
)。 - 导航至设置 → 数据源 → 添加数据源。
- 选择Prometheus作为源。
- 输入Prometheus 服务器 URL (
http://<instance_IP>:9090
)。 - 保存并测试连接。
- 从 Grafana 的公共仪表板库导入Prometheus 仪表板。
🚀您使用 Prometheus 和 Grafana 的监控设置现已准备就绪!
结果:
詹金斯管道:
普罗米修斯:
黑匣子:
格拉法纳:
应用:
结论
DevOps CI/CD 流水线项目的成功实施,标志着我们在提升软件交付流程的效率、可靠性和质量方面取得了重要的里程碑。通过自动化软件开发生命周期的关键环节,包括编译、测试、部署和监控,该项目实现了软件版本的快速、一致交付,从而缩短了产品上市时间并提高了客户满意度。
致谢贡献
我要对DevOps Shack的出色项目和实施指南表示感谢。
最后的想法
展望未来,该项目的影响远不止于其直接效益,它还将为软件开发实践的持续改进和创新铺平道路。通过拥抱 DevOps 原则并利用尖端工具和技术,我们为未来项目的开展奠定了坚实的基础。CI/CD 流水线的可扩展性、灵活性和弹性确保其能够适应不断变化的需求和技术进步,使我们的组织在竞争激烈的市场环境中获得长期成功。
参考
-
Jenkins 文档:https://www.jenkins.io/doc/
-
SonarQube 文档:https://docs.sonarqube.org/latest/
-
Nexus 存储库管理器文档:https://help.sonatype.com/repomanager3
-
Docker 文档:https://docs.docker.com/
-
Kubernetes 文档:https://kubernetes.io/docs/
-
Prometheus 文档:https://prometheus.io/docs/
-
Grafana 文档:https://grafana.com/docs/
这些资源在整个项目生命周期中提供了宝贵的见解、指导和支持,使我们能够有效地实现目标。
🛠️作者与社区
这个项目由Harshhaa 💡精心打造。
我期待您的反馈!欢迎分享您的想法。