开发公司级Gradle插件,统一Spring微服务构建与K8s部署流程
解决方案
一、开发自定义Gradle插件统一构建逻辑
1. 插件项目初始化
新建独立的Gradle插件项目(采用Kotlin DSL),把原手动复制的4-5个工具文件中的Docker构建、Nexus发布、K8s部署逻辑全部迁移到该项目中。示例结构:
company-gradle-plugin/ ├── build.gradle.kts ├── settings.gradle.kts └── src/ ├── main/ │ ├── kotlin/ │ │ └── com/company/gradle/plugin/CompanyBuildPlugin.kt │ └── resources/ │ └── META-INF/gradle-plugins/ │ └── com.company.build.properties └── test/
2. 依赖开源插件
在插件的build.gradle.kts中引入所需开源插件,统一管控版本:
plugins { `java-gradle-plugin` `kotlin-dsl` id("com.bmuschko.docker-spring-boot-application") version "9.3.0" id("io.fabric8.kubernetes-gradle-plugin") version "6.8.0" } gradlePlugin { plugins { create("companyBuildPlugin") { id = "com.company.build" implementationClass = "com.company.gradle.plugin.CompanyBuildPlugin" } } }
3. 封装自定义扩展
定义扩展类,让微服务仅需配置少量差异化参数(如镜像仓库地址、K8s命名空间):
open class CompanyBuildExtension( val project: Project ) { var dockerRegistry: String = "registry.company.com" var k8sNamespace: String = "default" var imageTag: String = "${project.version}-${project.extra["gitCommitId"] ?: "unknown"}" }
在插件中注册扩展:
class CompanyBuildPlugin : Plugin<Project> { override fun apply(project: Project) { val extension = project.extensions.create<CompanyBuildExtension>("companyBuild", project) // 后续逻辑基于extension配置展开 } }
4. 发布插件到内部Nexus
配置插件项目发布到公司Nexus仓库,所有微服务只需在build.gradle.kts中添加插件依赖即可:
// 微服务项目的build.gradle.kts plugins { id("com.company.build") version "1.0.0" id("org.springframework.boot") version "3.2.0" }
二、实现单任务完成构建-扫描-部署流程
在自定义插件中创建复合任务fullDeploy,串联所有必要步骤并强制执行顺序:
class CompanyBuildPlugin : Plugin<Project> { override fun apply(project: Project) { val extension = project.extensions.create<CompanyBuildExtension>("companyBuild", project) // 1. 镜像扫描任务(集成Trivy) val scanImage = project.tasks.register<Exec>("scanImage") { commandLine( "trivy", "image", "${extension.dockerRegistry}/${project.name}:${extension.imageTag}", "--severity", "CRITICAL,HIGH", "--exit-code", "1" // 发现高危漏洞时终止流程 ) mustRunAfter("dockerBuildImage") } // 2. 配置Docker插件 project.plugins.apply("com.bmuschko.docker-spring-boot-application") project.extensions.configure<DockerSpringBootApplicationExtension> { images { create { name = "${extension.dockerRegistry}/${project.name}:${extension.imageTag}" setBuildArgs(mapOf("JAR_FILE" to "build/libs/${project.name}-${project.version}.jar")) } } registryCredentials { url = extension.dockerRegistry username = project.findProperty("dockerUsername")?.toString() password = project.findProperty("dockerPassword")?.toString() } } // 3. 配置K8s部署插件 project.plugins.apply("io.fabric8.kubernetes-gradle-plugin") project.extensions.configure<KubernetesExtension> { namespace = extension.k8sNamespace deploy { replicas = 2 imagePullSecrets.add("registry-secret") } } // 4. 复合任务串联所有流程 val fullDeploy = project.tasks.register("fullDeploy") { dependsOn( project.tasks.named("build"), project.tasks.named("dockerBuildImage"), scanImage, project.tasks.named("dockerPushImage"), project.tasks.named("kubernetesDeploy") ) // 强制任务执行顺序 project.tasks.named("dockerBuildImage").get().mustRunAfter("build") project.tasks.named("dockerPushImage").get().mustRunAfter(scanImage) project.tasks.named("kubernetesDeploy").get().mustRunAfter("dockerPushImage") } } }
微服务项目只需执行:
./gradlew fullDeploy -PdockerUsername=xxx -PdockerPassword=xxx
三、K8s部署结构复用方案
1. 内嵌通用K8s资源模板
将99%一致的Deployment、Service、Ingress等资源模板放到插件的src/main/resources/k8s目录,用占位符替换差异化内容:
# src/main/resources/k8s/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{serviceName}} namespace: {{namespace}} spec: replicas: {{replicas}} selector: matchLabels: app: {{serviceName}} template: metadata: labels: app: {{serviceName}} spec: containers: - name: {{serviceName}} image: {{image}} ports: - containerPort: {{port}} env: - name: SPRING_PROFILES_ACTIVE value: {{env}}
2. 模板参数替换
在插件中配置K8s插件加载模板,并通过扩展参数替换占位符:
project.extensions.configure<KubernetesExtension> { namespace = extension.k8sNamespace resources { from(project.resources.text.fromFile("k8s/deployment.yaml") .replace("{{serviceName}}", project.name) .replace("{{namespace}}", extension.k8sNamespace) .replace("{{image}}", "${extension.dockerRegistry}/${project.name}:${extension.imageTag}") .replace("{{port}}", project.extra["servicePort"].toString()) .replace("{{env}}", project.findProperty("env") ?: "dev") ) } }
3. 差异化配置支持
允许个别微服务通过扩展覆盖或追加配置,比如添加自定义环境变量:
// 某微服务的build.gradle.kts companyBuild { k8sNamespace = "special-service" project.extra["servicePort"] = 8081 } kubernetes { env { add("CUSTOM_FEATURE_FLAG", "true") } }
4. 统一管理全局K8s资源
将命名空间、资源配额、服务账户等全局资源单独维护在插件或公司级配置仓库中,通过插件自动应用,避免每个项目重复定义。
内容的提问来源于stack exchange,提问作者George Cimpoies
相关产品推荐
相关产品推荐

