☰
Spinnaker Rosco halconfig 配置骨架解析:Halyard 拼接机制、弃用迁移与烘焙默认值配置指南
2026/9/25 5:53:41 网站建设 项目流程
  • 后端
  • DevOps
  • 云原生
  • 微服务

【免费下载链接】spinnaker

Spinnaker is an open source, multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence.

项目地址:https://gitcode.com/gh_mirrors/sp/spinnaker
点击查看免费下载

本文围绕 Spinnaker 开源仓库rosco/halconfig目录展开,系统讲解 Rosco(镜像烘焙服务)骨架配置文件的定位、Halyard 部署时配置拼接的工作原理、该目录当前的弃用状态,以及在现代 Rosco 版本中设置默认配置值的正确姿势——涵盖 halconfig 目录、halconfig/rosco.yml、halconfig/images.yml 与 packer 模板目录 的全部内容,并对照 rosco-core 源码 给出实现级证据。读完本文,你将掌握 Rosco 烘焙配置的来龙去脉,能够正确判断哪些配置该写进 halconfig、哪些该迁移到rosco-web/config/rosco.yml或代码默认值,并理解 packer 模板与bakeryDefaults的配合关系。

一、halconfig 目录是什么:Rosco 的“骨架配置”

rosco/halconfig/README.md开门见山地说明了该目录的定位:

This directory contains a skeleton rosco config to which Halyard concatenates its generated deployment-specific config.

即rosco/halconfig存放的是 Rosco 的骨架(skeleton)配置,Halyard(Spinnaker 部署管理工具)在生成部署专属配置时,会把两部分内容**拼接(concatenate)**到一起:骨架配置提供通用默认值,Halyard 生成的配置提供当前部署环境的具体值。这与 Spinnaker 其他微服务的 halconfig 目录设计一脉相承。

当前目录内共包含三类文件:

文件作用
README.md目录用途与弃用说明
rosco.yml骨架主配置:redis、server、以及各云厂商的bakeryDefaults
images.yml更早期的骨架镜像配置(同样已弃用)
packer/Rosco 使用的 Packer 构建模板与安装脚本

骨架配置中的环境变量占位符

halconfig/rosco.yml 的最典型特征是大量使用${...}占位符,其中一部分引用 Halyard 生成的服务配置,另一部分引用环境变量:

redis: connection: ${services.redis.baseUrl:redis://localhost:6379} server: port: ${services.rosco.port:8087} address: ${services.rosco.host:localhost}
  • ${services.redis.baseUrl:redis://localhost:6379}:优先取 Halyard 生成的services.redis.baseUrl,取不到时回退到redis://localhost:6379;
  • ${services.rosco.port:8087}:取 Halyard 的services.rosco.port,默认回退8087(即 Rosco 的默认 HTTP 端口);
  • ${services.rosco.host:localhost}:绑定地址默认localhost。

这一设计正是“骨架 + Halyard 拼接”的直观体现:骨架文件用带默认值的占位符描述通用行为,具体部署值由 Halyard 注入。

二、重要现状:halconfig 配置已被弃用

README 同时给出了明确的弃用声明,这是理解该目录时最重要的一点:

These configs aredeprecatedand in general should not be further updated. To set a default config value, either set the value inrosco-web/config/rosco.ymlor set a default in the code reading the config property.

即rosco/halconfig下的配置已弃用,原则上不应继续更新。需要设置默认配置值时,官方推荐两条迁移路径:

  1. 在 rosco-web/config/rosco.yml 中设置默认值——这是当前 Rosco 运行时真正加载的配置文件;
  2. 在读取该配置属性的代码中设置默认值——即 Spring 的${property:defaultValue}语法或代码内直接兜底。

为什么会有这种迁移?

从部署视角看,Rosco 的镜像内实际使用的配置位于/opt/rosco/config/,而 halconfig 中的内容只服务于 Halyard 拼接流程。随着 Spinnaker 部署模型向"统一配置(unified config)"演进,halconfig 骨架的维护成本与歧义(例如多份 yml 的默认值到底以谁为准)超过了它的价值,因此社区选择收敛配置入口。halconfig/images.yml同样处于弃用状态,它列出的 AWS/Azure/Docker/GCE 基础镜像定义,在 halconfig/rosco.yml 中已有更完整的对应版本。

三、当前权威配置入口:rosco-web/config/rosco.yml

按 README 的指引,rosco-web/config/rosco.yml 才是现版本应维护默认值的位置。它涵盖了骨架配置的全部核心项,并补充了 halconfig 中没有的细节,逐项说明如下。

3.1 服务端口与烘焙目录

server: port: 8087 rosco: configDir: /opt/rosco/config/packer jobs: local: timeoutMinutes: 30
  • server.port:Rosco HTTP 端口,默认8087(Dockerfile 的健康检查也探测该端口);
  • rosco.configDir:Packer 模板与脚本所在目录。镜像内固定为/opt/rosco/config/packer,由 Dockerfile.ubuntu 第 78 行COPY halconfig/packer /opt/rosco/config/packer把本仓库的 packer 目录拷入镜像,configDir最终会以{{user \configDir`}}` 形式注入每个 Packer 模板;
  • rosco.jobs.local.timeoutMinutes:本地 Job 执行的超时时间,默认 30 分钟,防止烘焙任务悬挂。

在源码侧,CloudProviderBakeHandler.groovy 通过@Value('${rosco.config-dir}')读取该路径,并在produceBakeRecipe中拼接出模板文件的完整路径:"$configDir/$finalTemplateFileName",再交给PackerCommandFactory生成最终的packer build命令。

3.2 Packer 行为参数

packer: # Set this if running Packer >= 1.4.0 for timestamp prepended output timestamp: false # Add additional parameters that will always be passed to "packer build" here # additionalParameters: # - on-error=abort # - -var "bakedBy=Rosco"
  • packer.timestamp:Packer 1.4.0+ 起,构建日志会自带时间戳前缀,Rosco 解析日志时按此开关适配;
  • packer.additionalParameters:需要无条件附加到每次packer build的参数列表,例如on-error=abort(失败即中止)或自定义-var。

3.3 软件源仓库(debian / yum / chocolatey)

# debianRepository: http://dl.bintray.com/spinnaker/ospackages trusty main;http://other.repo.com/repo/packages trusty main # yumRepository: https://jfrog.bintray.com/yum/repos/some-package # chocolateyRepository: https://chocolatey.org/api/v2/
  • debianRepository:烘焙 Debian 系镜像时追加到/etc/apt/sources.list.d/spinnaker.list的 apt 源,多个源用分号分隔;
  • yumRepository:烘焙 RPM 系镜像时写入/etc/yum.repos.d/的 yum 源;
  • chocolateyRepository:烘焙 NuGet 系(Windows)镜像时的 chocolatey 源;
  • 均支持空格分隔的多源列表,并且可以在某个baseImage上通过customRepository覆盖全局配置。

源码印证见 CloudProviderBakeHandler.groovy:三个仓库分别由@Value('${debian-repository:}')、@Value('${yum-repository:}')、@Value('${chocolatey-repository:}')注入,在produceBakeRecipe中按packageType(DEB/RPM/NUPKG)选择对应仓库写入parameterMap.repository,最终传给模板中的install_packages.sh。

3.4 默认云厂商与需要 root 的模板

defaultCloudProviderType: aws templatesNeedingRoot: aws-chroot.json
  • defaultCloudProviderType:未显式指定云厂商时的默认值,本仓库中为aws;
  • templatesNeedingRoot:列出需要以 root 身份执行/usr/bin/packer的模板(本仓库为aws-chroot.json,chroot 构建必须挂载块设备)。Rosco 默认以spinnaker用户运行、无 sudo 权限,因此使用这些模板前需在/etc/sudoers.d/spinnaker中添加:
spinnaker ALL=(ALL) NOPASSWD: /usr/bin/packer

README 与配置注释均特别提示:为 spinnaker 授予 packer 的免密 sudo 存在被恶意利用控制机器的风险,需谨慎评估。源码侧,CloudProviderBakeHandler.groovy 将templates-needing-root读取为列表,并在getBaseCommand中判断:若模板文件名命中列表,则在 packer 命令前加sudo前缀,否则为空串。

四、bakeryDefaults:各云厂商的基础镜像骨架

halconfig/rosco.yml 的主体是按云厂商划分的bakeryDefaults配置(在rosco-web/config/rosco.yml中缺失的部分在此补全),其通用结构为:

<provider>: enabled: ${<PROVIDER>_ENABLED:false} bakeryDefaults: templateFile: <模板文件名> baseImages: - baseImage: id: <镜像 ID,即 base_os> shortDescription: ... detailedDescription: ... packageType: deb | rpm | nupkg virtualizationSettings: - region: ... instanceType: ... sourceImage / sourceAmi / sourceImageId: ... sshUserName: ...

4.1 统一的启用开关与条件装配

每个厂商都以enabled: ${XXX_ENABLED:false}开头(如${AWS_ENABLED:false}、${GOOGLE_ENABLED:false}、${DOCKER_ENABLED:false})。这个开关在源码中对应 Spring 的@ConditionalOnProperty:

  • RoscoAWSConfiguration.groovy 标注@ConditionalOnProperty('aws.enabled');
  • AWSBakeryDefaultsBean.java 同样以@ConditionalOnProperty("aws.enabled")控制awsBakeryDefaultsBean,并通过@ConfigurationProperties("aws.bakery-defaults")将 yml 中的aws.bakeryDefaults段映射为配置对象。

也就是说,只有对应enabled: true的厂商才会装配BakeHandler与默认值 Bean,并在@PostConstruct阶段注册进 DefaultCloudProviderBakeHandlerRegistry。

注意:配置注释特别提醒,XXX_ENABLED这类环境变量并不在 spinnaker/spinnaker 项目的 unified config 中定义。若要把本段配置拷贝到预构建镜像的rosco-local.yml,必须把AWS_ENABLED换成SPINNAKER_AWS_ENABLED(其他厂商同理),或显式设enabled: true。

4.2 AWS:最完整的骨架示例

AWS 段的bakeryDefaults覆盖了模板选择、虚拟化类型与竞拍价:

aws: enabled: ${AWS_ENABLED:false} bakeryDefaults: awsAssociatePublicIpAddress: true templateFile: aws-ebs.json defaultVirtualizationType: hvm baseImages: - baseImage: id: ubuntu shortDescription: v12.04 detailedDescription: Ubuntu Precise Pangolin v12.04 packageType: deb templateFile: aws-ebs.json virtualizationSettings: - region: us-east-1 virtualizationType: hvm instanceType: t2.micro sourceAmi: ami-d4aed0bc sshUserName: ubuntu spotPrice: 0 spotPriceAutoProduct: Linux/UNIX (Amazon VPC)

关键参数含义:

  • awsAssociatePublicIpAddress:构建实例是否分配公网 IP(默认true);
  • templateFile:默认 Packer 模板,AWS 默认aws-ebs.json;注释指出需要share_with/copy_to能力时应换成aws-multi-ebs.json,此时还需设置环境变量SPINNAKER_AWS_DEFAULT_ACCOUNT(要共享 AMI 的账号 ID)与SPINNAKER_AWS_DEFAULT_REGION;
  • defaultVirtualizationType:默认虚拟化类型hvm(对应源码 AWSBakeryDefaultsBean.java 中${aws.bakery-defaults.default-virtualization-type:hvm}的读取与兜底);
  • spotPrice:竞拍价上限,auto表示自动探测最优竞拍价,0表示按需实例(默认);
  • spotPriceAutoProduct:使用spotPrice: auto时的必填项,取值限定为Linux/UNIX、Linux/UNIX (Amazon VPC)、SUSE Linux、Windows、Windows (Amazon VPC)等;
  • 每个virtualizationSettings由region + virtualizationType + instanceType + sourceAmi + sshUserName唯一确定一种可烘焙镜像组合,同一baseImage下可并列多个 region 与虚拟化类型(如 hvm 用t2.micro、pv 用m3.medium)。

配置注释还说明:baseImage级可覆盖默认模板(templateFile)与全局软件源(customRepository),例如customRepository: http://dl.bintray.com/spinnaker/ospackages bionic main。

4.3 Google(GCE):镜像族与镜像二选一

google: enabled: ${GOOGLE_ENABLED:false} bakeryDefaults: zone: us-central1-f network: default useInternalIp: false templateFile: gce.json baseImages: - baseImage: id: xenial shortDescription: v16.04 detailedDescription: Ubuntu Xenial Xerus v16.04 packageType: deb isImageFamily: true virtualizationSettings: sourceImageFamily: ubuntu-1604-lts
  • sourceImage与sourceImageFamily二选一,同时设置时sourceImage优先;
  • isImageFamily: true时 Deck 会在 UI 提示该选项代表"镜像族"而非具体镜像;
  • zone、network、useInternalIp为 GCE 构建实例的默认参数。

4.4 Azure:publisher / offer / sku 三元组

azure: enabled: ${AZURE_ENABLED:false} bakeryDefaults: templateFile: azure-linux.pkr.hcl baseImages: - baseImage: id: ubuntu-1604 shortDescription: v16.04 detailedDescription: Ubuntu Server 16.04-LTS publisher: Canonical offer: UbuntuServer sku: 16.04-LTS version: 16.04.201612140 osType: Linux packageType: deb

Azure 的源镜像通过 Marketplace 的publisher/offer/sku/version描述,Windows 基础镜像额外指定templateFile: azure-windows.pkr.hcl与packageType: nupkg。同时注意仓库中已同时提供 azure-linux.pkr.hcl 与更新的托管镜像版本 azure-linux-managed-image.pkr.hcl。

4.5 Docker:最简烘焙模型

docker: enabled: ${DOCKER_ENABLED:false} bakeryDefaults: targetRepository: ${DOCKER_TARGET_REPOSITORY:} templateFile: docker.json baseImages: - baseImage: id: precise shortDescription: v12.04 detailedDescription: Ubuntu Precise Pangolin v12.04 packageType: deb virtualizationSettings: sourceImage: ubuntu:precise

Docker 烘焙以sourceImage(基础镜像 tag)为输入、targetRepository(目标仓库)为输出,不涉及 region 与实例类型。

4.6 阿里云 / 华为云 / 腾讯云

  • 阿里云(alicloud):以region + instanceType + sourceImage + sshUserName定义,如cn-hangzhou区域ecs.c5.large实例、ubuntu_16_04_64_20G_alibase_20190620.vhd源镜像,模板 alicloud.json;
  • 华为云(huaweicloud):bakeryDefaults中直接包含一组认证与网络参数占位符:authUrl、username、password、projectName、domainName、insecure、vpcId、subnetId、eipBandwidthSize(默认 2)、securityGroup,源镜像以不可变的 UUID(sourceImageId)标识,可在控制台或镜像 API 查询;
  • 腾讯云(tencentcloud):secretId、secretKey认证,virtualizationSettings含region/zone/instanceType/sourceImageId/sshUsername,覆盖 Ubuntu 16.04、Debian 9.0、CentOS 7.6 三类基础镜像。

4.7 一份独立的镜像清单:images.yml

halconfig/images.yml 是更早形态的骨架镜像定义,结构与bakeryDefaults.baseImages一致(AWS 的 ubuntu/trusty/windows-2012-r2、Azure 的五个 Marketplace 镜像、Docker 的 precise/trusty、GCE 的 xenial/bionic 镜像族)。它与 halconfig/rosco.yml 存在部分重复,同样随目录整体弃用,阅读时应以rosco.yml中的bakeryDefaults为准。

五、Packer 模板骨架:烘焙命令的落地形态

rosco/halconfig/packer存放的是直接喂给 Packer 的构建模板与脚本。它们遵循"变量占位符 + 统一安装脚本"模式:所有运行时值通过{{user \xxx`}}` 注入,软件安装统一走 install_packages.sh。

5.1 统一的变量契约

以 aws-ebs.json 为例,其variables定义了各云厂商模板共通的契约字段:

变量含义
appversion/build_host/build_info_url写入镜像标签/描述的构建元数据
repository本次烘焙使用的软件源(由 3.3 节的仓库配置决定)
package_typedeb/rpm/nupkg
packages要安装的包名(空格分隔)
upgrade是否先执行系统升级(unattended-upgrade/yum update)
configDir模板与脚本所在目录,用于定位install_packages.sh

aws-ebs.json使用amazon-ebsbuilder,把source_ami烘焙为ami_name,并把appversion、build_host、build_info_url写入 AMI 标签、packages写入运行标签;aws-subnet_id/aws_vpc_id默认从环境变量AWS_SUBNET_ID/AWS_VPC_ID读取。

5.2 各模板的差异定位

  • aws-chroot.json:amazon-chrootbuilder,直接在块设备上烘焙、不启动实例,因此需要 root 权限(对应templatesNeedingRoot),并通过disable_services=true环境变量让install_packages.sh临时创建/usr/sbin/policy-rc.d阻止服务自动启动(规避 chroot 环境中的服务启动坑);
  • aws-multi-ebs.json:在aws-ebs.json基础上增加ami_users(share_with_1..10,默认全部为SPINNAKER_AWS_DEFAULT_ACCOUNT)与ami_regions(copy_to_1..5,默认全部为SPINNAKER_AWS_DEFAULT_REGION),实现 AMI 跨账号共享与跨区域复制;aws-multi-chroot.json 为对应 chroot 版本;
  • aws-windows-2012-r2.json:Windows 基础镜像,配合 packer/scripts 下的 PowerShell 脚本(如windows-install-packages.ps1、windows-configure-chocolatey.ps1)完成 NuGet 包安装;
  • gce.json:googlecomputebuilder,支持artifactFile文件 provisioner(把 artifacts 传入/tmp/artifacts.json)与manifestpost-processor 输出manifestFile,供 PackerManifestService 解析烘焙产物 ID;
  • docker.json:dockerbuilder +docker-tag/docker-pushpost-processor,把基础镜像安装包后提交为新镜像并推送至docker_target_repository;
  • azure-linux.pkr.hcl:采用 Packer HCL2 语法(source "azure-arm"+build块),变量以sensitive = true声明azure_client_id/azure_client_secret防止日志泄露,并在构建末尾执行waagent -force -deprovision+user完成 Azure 镜像通用化。

5.3 install_packages.sh:烘焙过程中的"安装引擎"

install_packages.sh 是所有模板共用的软件安装脚本,核心逻辑:

  • set -e保证构建失败即中止;
  • 先打印脱敏后的repository(用sed s/^.*@//g剥离凭据部分),避免仓库 URL 中的凭据泄漏;
  • get_artifact_references:把仓库列表写入/tmp/repos,若存在/tmp/artifacts.json(GCE 等通过 file provisioner 传入的工件清单),用jq解析每个 artifact 的reference——最后一段是包名、其余段是安装源;
  • provision_deb:向/etc/apt/sources.list.d/spinnaker.list追加 deb 源,upgrade=true时执行unattended-upgrade -v,然后按顺序apt-get install各包,结束后清理源文件;
  • provision_rpm:为每个源生成/tmp/spinnaker-<ts>-<i>.repo并移入/etc/yum.repos.d/,upgrade=true时yum update,再逐个yum install;
  • disable_services=true时(chroot 模板)创建/移除policy-rc.d以控制服务启动。

六、从源码看配置如何被消费:一次烘焙的完整链路

把配置文件与源码串起来,一次烘焙请求的消费链路如下(对应 CloudProviderBakeHandler.groovy 的produceBakeRecipe):

  1. 读取烘焙默认值:getBakeryDefaults()返回由@ConfigurationProperties("aws.bakery-defaults")等映射的bakeryDefaults对象(仅在xxx.enabled=true时装配,见 RoscoConfiguration.groovy 与各厂商 Configuration);
  2. 匹配基础镜像:findBaseImage按bakeRequest.base_os在baseImages中查找id匹配项,找不到则抛IllegalArgumentException;
  3. 定位虚拟化设置:findVirtualizationSettings(region, bakeRequest)根据 region 与请求参数选择对应的virtualizationSettings;
  4. 组装参数:buildParameterMap把 region、实例类型、源镜像等填入模板变量;repository按 packageType 从全局仓库或customRepository决定;
  5. 拼接命令:getBaseCommand按templatesNeedingRoot决定是否加sudo,PackerCommandFactory.buildPackerCommand生成完整packer build命令,configDir作为变量一并传入;
  6. 注册与执行:厂商配置在@PostConstruct中把BakeHandler注册进 DefaultCloudProviderBakeHandlerRegistry,由 Rosco API 分派执行。

此外,RoscoConfiguration中的 BakeStore 基于 Jedis 使用 Redis 记录烘焙状态,这也解释了骨架配置中redis.connection为什么是必须项——Rosco 不依赖 Halyard 默认的 Redis 部署,而是直接连接redis://localhost:6379(可经${services.redis.baseUrl}覆盖)。

七、实战建议:面对 halconfig 该怎么做

基于 README 的弃用声明与仓库现状,落地时建议遵循以下原则:

  1. 不再修改 halconfig:rosco/halconfig下的rosco.yml、images.yml保留只读,作为理解烘焙默认值历史形态与迁移的参考;
  2. 默认值写到 rosco-web/config/rosco.yml:新增厂商默认值、模板默认值、仓库配置等一律落到 rosco-web/config/rosco.yml;
  3. 环境变量启用厂商:在部署环境设置SPINNAKER_AWS_ENABLED=true等(对应enabled: ${AWS_ENABLED:false}的占位符),而非直接改 halconfig;
  4. 模板与脚本随镜像分发:packer/目录经 Dockerfile.ubuntu 拷贝到/opt/rosco/config/packer,若要自定义模板,应在构建镜像时替换该目录内容,并保持变量契约(configDir、repository、package_type、packages、upgrade)不变;
  5. root 权限按需最小化:仅当确实使用aws-chroot.json等需要 root 的模板时,才按 3.4 节配置 sudoers 规则,并充分评估安全风险。

结语

rosco/halconfig是 Spinnaker Rosco 服务配置体系从"Halyard 拼接骨架"向"统一配置文件 + 代码默认值"演进的历史见证。理解它的定位与弃用逻辑,能帮助你在实际部署中快速判断:默认值应写进 rosco-web/config/rosco.yml,厂商开关应通过环境变量控制,而bakeryDefaults与 packer 模板的配合关系(baseImage匹配 →virtualizationSettings定位 →parameterMap组装 →install_packages.sh安装)则构成了 Rosco 镜像烘焙能力的完整闭环。

  • 后端
  • DevOps
  • 云原生
  • 微服务

【免费下载链接】spinnaker

Spinnaker is an open source, multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence.

项目地址:https://gitcode.com/gh_mirrors/sp/spinnaker
点击查看免费下载
上一篇:dosemu2完全指南:如何在Linux系统中无缝运行经典DOS程序
下一篇:Gammazero/Deque:Go语言高性能环形缓冲区双端队列完全指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询