// CD流水线核心接口(参考知识库[1][2][3])
public interface ContinuousDeliveryPipeline {
// 自动化构建与测试
void buildAndTest(String repositoryUrl);
// 容器化部署
void containerizeDeployment(String targetEnv);
// 蓝绿部署策略
void blueGreenDeploy(String newVersion);
// 监控与回滚
void monitorAndRollback(double failureThreshold);
}
// 实现类:集成Jenkins+Docker+Kubernetes
public class JavaCDPipeline implements ContinuousDeliveryPipeline {
private final JenkinsClient jenkins;
private final DockerClient docker;
private final KubernetesClient k8s;
public JavaCDPipeline() {
this.jenkins = new JenkinsClient("http://jenkins-master");
this.docker = new DockerClient("unix:///var/run/docker.sock");
this.k8s = new KubernetesClient("https://k8s-cluster");
}
// 后续方法实现略...
}
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>17source>
<target>17target>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.jacocogroupId>
<artifactId>jacoco-maven-pluginartifactId>
<executions>
<execution>
<goals>
<goal>prepare-agentgoal>
goals>
execution>
<execution>
<id>generate-reportid>
<phase>testphase>
<goals>
<goal>reportgoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>com.spotifygroupId>
<artifactId>dockerfile-maven-pluginartifactId>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}repository>
<tag>${project.version}tag>
configuration>
plugin>
plugins>
build>
project>
/* Jenkinsfile(参考知识库[2][5][6][8]) */
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'registry.example.com'
K8S_NAMESPACE = 'production'
}
stages {
stage('代码拉取') {
steps {
git url: 'https://github.com/example/java-app.git'
}
}
stage('构建与测试') {
steps {
// Maven构建与测试
sh 'mvn clean test -DskipITs'
// 静态代码扫描(SonarQube)
withSonarQubeEnv('sonarqube-server') {
sh 'mvn sonar:sonar'
}
// 测试覆盖率检查
step([$class: 'JacocoPublisher',
execPattern: '**/target/*.exec',
classPattern: '**/target/classes',
sourcePattern: 'src/main/java'])
}
}
stage('容器化构建') {
steps {
// 构建Docker镜像
sh 'docker build -t ${DOCKER_REGISTRY}/${project}/:${env.BUILD_ID} .'
// 镜像签名(参考知识库[8])
sh 'docker trust sign ${DOCKER_REGISTRY}/${project}/:${env.BUILD_ID}'
// 推送镜像
sh 'docker push ${DOCKER_REGISTRY}/${project}/:${env.BUILD_ID}'
}
}
stage('蓝绿部署') {
steps {
// 生成新部署的命名空间
script {
def newNamespace = "blue-green-${UUID.randomUUID().toString().take(8)}"
sh "kubectl create namespace ${newNamespace}"
// 应用新配置
env.K8S_DEPLOYMENT_NS = newNamespace
sh "kubectl apply -f k8s/deployment.yaml -n ${newNamespace}"
}
}
}
stage('流量切换') {
when {
expression { return env.ENVIRONMENT == 'production' }
}
steps {
// 流量逐步切换(参考知识库[6])
sh "kubectl set image deployment/my-app deployment=image:${env.BUILD_ID} -n ${env.K8S_DEPLOYMENT_NS}"
input message: '确认新版本稳定后继续?'
}
}
}
post {
always {
// 清理旧镜像
sh "docker image prune -f"
}
failure {
// 自动回滚(参考知识库[6])
sh "kubectl rollout undo deployment/my-app -n ${env.K8S_DEPLOYMENT_NS}"
notifyDiscord('部署失败,请检查流水线日志')
}
}
}
# Dockerfile(参考知识库[4][8])
# 构建阶段
FROM maven:3.8.6-jdk-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段
FROM eclipse-temurin:17-jre-focal
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
CMD ["java", "-jar", "app.jar"]
# deployment.yaml(参考知识库[5][6])
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: java-container
image: registry.example.com/my-java-app:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "production"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
imagePullSecrets:
- name: regcred
// Kubernetes客户端操作(参考知识库[6])
public class BlueGreenDeployer {
private final KubernetesClient client;
public BlueGreenDeployer() {
this.client = new DefaultKubernetesClient();
}
public void deployNewVersion(String newImageTag) {
// 创建新命名空间
String newNs = "green-" + System.currentTimeMillis();
client.namespaces().createOrReplace(new NamespaceBuilder()
.withNewMetadata().withName(newNs).endMetadata()
.build());
// 应用新部署配置
Deployment deployment = client.apps().deployments()
.load(new ClassPathResource("deployment-green.yaml").getInputStream())
.replaceParam("IMAGE_TAG", newImageTag)
.replaceParam("NAMESPACE", newNs)
.createOrReplace();
// 等待新部署就绪
client.apps().deployments().inNamespace(newNs).withName("my-java-app")
.waitUntilCondition(new DeploymentCondition() {
@Override
public boolean test(Deployment deployment) {
return deployment.getStatus().getAvailableReplicas() == deployment.getStatus().getReplicas();
}
}, 5, TimeUnit.MINUTES);
// 切换入口流量
client.services().inNamespace("ingress").withName("my-ingress")
.edit()
.editSpec()
.addToSelector("environment", newNs)
.endSpec()
.done();
}
}
// 监控与回滚实现(参考知识库[6])
public class AutoRollbackService {
private final KubernetesClient client;
private final PrometheusClient prometheus;
public void monitorAndRollback() {
// 监控HTTP错误率
Double errorRate = prometheus.query("avg(rate(http_request_errors_total{job=\"my-java-app\"}[5m]))");
if (errorRate > 0.1) {
// 自动回滚到前一个版本
client.apps().deployments().inNamespace("production")
.withName("my-java-app")
.rollout().undo();
sendAlert("部署失败,已触发自动回滚");
}
}
}
// 安全扫描实现(参考知识库[8])
public class SecurityScanner {
private final DockerClient docker;
public void scanImage(String imageTag) {
// 使用Trivy进行镜像扫描
ProcessBuilder pb = new ProcessBuilder(
"trivy", "image", "--format", "json", imageTag);
Process process = pb.start();
String scanResult = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8);
// 解析结果并触发告警
if (parseVulnerabilities(scanResult) > 10) {
sendAlert("高危漏洞检测到,禁止部署:" + imageTag);
}
}
}
// 镜像签名实现(参考知识库[8])
public class ImageSigner {
private final DockerClient docker;
public void signImage(String imageRef) {
// 使用Notary进行签名
ProcessBuilder pb = new ProcessBuilder(
"docker", "trust", "sign", imageRef);
pb.redirectErrorStream(true);
Process process = pb.start();
process.waitFor();
// 验证签名
if (!process.exitValue() == 0) {
throw new RuntimeException("签名失败");
}
}
}
// CD服务主入口(参考知识库[1][2][5])
@Service
public class CDDeploymentService {
private final JenkinsClient jenkins;
private final DockerClient docker;
private final KubernetesClient k8s;
@Autowired
public CDDeploymentService(JenkinsClient jenkins,
DockerClient docker,
KubernetesClient k8s) {
this.jenkins = jenkins;
this.docker = docker;
this.k8s = k8s;
}
@Transactional
public void triggerDeployment(String repoUrl) {
// 触发Jenkins流水线
String jobName = "java-cd-pipeline-" + UUID.randomUUID().toString();
jenkins.createPipelineJob(jobName, generatePipelineScript(repoUrl));
jenkins.buildJob(jobName);
// 监控部署状态
while (!jenkins.getJobStatus(jobName).isCompleted()) {
Thread.sleep(30_000);
}
if (jenkins.getJobResult(jobName).isFailed()) {
throw new RuntimeException("部署流水线失败");
}
}
private String generatePipelineScript(String repoUrl) {
return """
pipeline {
agent any
stages {
stage('代码拉取') { steps { git url: '%s' } }
stage('构建与测试') { steps { sh 'mvn clean test' } }
stage('容器化') { steps { sh 'docker build -t app:latest .' } }
stage('部署') { steps { sh 'kubectl apply -f k8s/deployment.yaml' } }
}
}
""".formatted(repoUrl);
}
}
# application-cd.properties(参考知识库[8])
docker.registry=registry.example.com
k8s.namespace=production
jenkins.url=http://jenkins-master:8080
prometheus.url=http://prometheus.monitoring:9090
trivy.image=quay.io/trivy/trivy:latest
通过本文,你已掌握: