Help us shape the future of Go! Take the 2026 Go Developer Survey

ingress

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2026 License: Apache-2.0 Imports: 41 Imported by: 0

Documentation

Overview

Package ingress 是入口与证书适配器(T2.15/T2.16;架构 §2.6 入口真源): 平台自管 Traefik(global service 每节点,v0.1 单机 1 实例)、路由与证书 经 HTTP provider 由控制面集中下发、控制面内嵌 ACME(lego)集中签发。

纪律(Spike B 实测,spike/b/README.md §6——硬约束):

  • Traefik 只拒绝「显式空 map」与解析失败,**裸 {} 会清空全部路由**; 因此控制面合成配置必须保证 http.routers/services 键存在且非空, 先校验后写(Validate),坏配置不换入内存视图、Traefik 端永远取 不到残缺配置;
  • 配置服务不可达时 Traefik 保留上一份成功配置(原生兜底,实测);
  • 路由发布严格晚于健康门(release-semantics §2.5 不变量)——本包的 PublishRoutes 由发布引擎在首健康→切流之后调用。

核心不出现第三方概念的一般化纪律在本包的反向落实:Traefik/lego 类型 只存在于本包内部,出口是 Route/DynamicConfig 等本包类型;发布引擎经 engine.RoutePublisher 端口(本包 Manager 隐式实现)消费,不感知 Traefik 存在。

Index

Constants

View Source
const (
	// DefaultTraefikImage 是 Traefik 钉版镜像(Spike B 实测版本 v3.5;
	// 升级走镜像钉版变更 + 回归,不追 latest)。
	DefaultTraefikImage = "traefik:v3.5"
	// TraefikCertMountPath 是证书目录在 Traefik 容器内的只读挂载点
	//(tls.certificates 的 certFile/keyFile 以该路径书写)。
	TraefikCertMountPath = "/fleetly-certs"
	// DefaultServersTransportIdleTimeout 是 serversTransport 空闲连接
	// 回收时长。依据 V4 实测(architecture §2.5 连接治理行):keep-alive
	// 连接池会复用已退出的任务,治理主键是应用侧优雅退出,
	// serversTransport 降为辅助——只治理空闲池(90s 默认 → 15s 保守值),
	// 对 in-flight 请求无效。
	DefaultServersTransportIdleTimeout = 15 * time.Second
	// DefaultServersTransportDialTimeout 是后端拨号超时(保守值)。
	DefaultServersTransportDialTimeout = 5 * time.Second
	// DefaultRenewBefore 是证书续期窗口(到期前 30 天,T2.16 交付物)。
	DefaultRenewBefore = 30 * 24 * time.Hour
	// DefaultRenewScanInterval 是续期扫描周期。
	DefaultRenewScanInterval = 12 * time.Hour
	// DefaultACMECADirURL 是 LE production 目录端点(测试用 Pebble:
	// 配置 ingress.acme.ca_dir_url 指向本地 pebble /dir)。
	DefaultACMECADirURL = "https://acme-v02.api.letsencrypt.org/directory"
)

平台钉版与保守缺省(architecture §2.6 入口行 + §2.5 连接治理行)。

View Source
const IngressServiceName = "fleetly-ingress"

IngressServiceName 是平台入口服务名(契约:fleetly-ingress)。

Variables

View Source
var ErrNotSwarmReady = errors.New("docker engine is not an active swarm manager")

ErrNotSwarmReady 是 swarm 未就绪的哨兵(服务壳据此降级重试)。

Functions

func GenerateAccountKey

func GenerateAccountKey() ([]byte, error)

GenerateAccountKey 生成 ACME 账号私钥(ECDSA P256;PEM PKCS8)。

func GenerateToken

func GenerateToken() (string, error)

GenerateToken 生成随机 token(配置端点鉴权;32 字节 hex)。

func MarshalJSONBytes

func MarshalJSONBytes(cfg *DynamicConfig) ([]byte, error)

MarshalJSONBytes 序列化载荷(缩进关闭——Traefik 轮询高频路径的最小形)。

func NewID

func NewID() string

NewID 是台账行的 ULID 生成出口(domains 表;state 层自持同款形态)。

func RouterName

func RouterName(app, service string) string

RouterName 返回 app 服务对应的 router/service 键(fleetly-<app>-<service> ——与 Swarm 服务名同形,键空间唯一且可读)。

func Validate

func Validate(cfg *DynamicConfig) error

Validate 执行 Spike B 纪律校验(先校验后写):

  1. http.routers 键必须存在且非空(裸 {} 与显式空 map 双拒——空合成 由兜底路由承载,恒过本条);
  2. http.services 键必须存在(nil map 序列化为 null,同样是缺键形态; 值可以为空 map——只有内建引用的兜底形态合法,见 isInternalService);
  3. 每个 router 引用的 service 必须存在(悬空引用拒绝——坏 router 会被 Traefik 连同整份配置应用;Traefik 内建服务 @internal 限定名豁免);
  4. 每个 service 必须有非空 server URL。

Types

type ACMEConfig

type ACMEConfig struct {
	// CADirURL 是 ACME 目录端点(ca_dir_url;默认 LE production,测试用
	// Pebble URL)。
	CADirURL string
	// Email 是 ACME 账号邮箱(email;空 = 无 contact 注册)。
	Email string
	// CAPoolFile 是 CA 根证书池 PEM(ca_pool_file;Pebble/私有 CA 场景
	// 信任自定义根)。空 = 系统信任池。
	CAPoolFile string
	// AccountKeyFile 是 ACME 账号私钥文件(account_key_file;空 =
	// <CertDir>/acme-account.key)。
	AccountKeyFile string
	// Enabled 报告是否启用集中签发(enabled;false = 只发布路由不下发
	// TLS 证书——无域名/离线环境的显式关闭位)。nil 缺省 = true。
	Enabled *bool
}

ACMEConfig 是集中 ACME 配置(config 键 ingress.acme.*)。

func (ACMEConfig) ACMEEnabled

func (c ACMEConfig) ACMEEnabled() bool

ACMEEnabled 报告集中签发是否启用。

type CertificatePair

type CertificatePair struct {
	App     string
	Domains []string
	// CertPEM 是证书链 PEM(leaf + 中间;lego Bundle=true 形态)。
	CertPEM []byte
	// KeyPEM 是私钥 PEM(ECDSA P256)。
	KeyPEM []byte
	// NotAfter 是叶证书到期时间(UTC)。
	NotAfter time.Time
	// SHA256 是 CertPEM 内容摘要(台账登记;变更即重发布 TLS 段)。
	SHA256 string
}

CertificatePair 是一张落盘证书(app 级多 SAN 单证书,architecture §2.4 域名行:列表内域名同服务同路由、证书按 app 域名集合出一张)。

func ParsePair

func ParsePair(app string, domains []string, certPEM, keyPEM []byte) (*CertificatePair, error)

ParsePair 解析签发产物(lego Resource 的 PEM bundle)为证书对:叶到期 时间取 bundle 内最小 NotAfter(链任一环到期即证书失效),sha256 为 CertPEM 内容摘要。

type CertificateRef

type CertificateRef struct {
	App      string
	SHA256   string
	NotAfter int64 // UnixNano
}

CertificateRef 是一张已落库证书的引用(文件名 = app 名;sha256 与到期 时间随台账登记)。

type Config

type Config struct {
	// TraefikImage 是入口镜像(钉版;traefik_image)。
	TraefikImage string
	// HTTPPort / HTTPSPort 是宿主发布端口(host 模式 80/443;http_port/
	// https_port)。
	HTTPPort  int
	HTTPSPort int
	// ConfigAddr 是控制面配置端点监听地址(config_addr)。默认 0.0.0.0
	// ——Traefik 任务(容器 netns)须经宿主 IP 访问;鉴权 token 强制,
	// 非回环绑定的暴露面由 token 承担(取舍见 provider.go 注释)。
	ConfigAddr string
	// ConfigAdvertiseIP 是下发给 Traefik 的控制面可达 IP
	//(config_advertise_ip;空 = 自动探测:Swarm advertise addr 优先,
	// 出口本地地址兜底)。Docker Desktop 形态 advertise addr 是 VM 内部
	// IP,须显式配置为宿主可达地址。
	ConfigAdvertiseIP string
	// TokenFile 是配置端点 bearer token 的持久化文件(token_file;首启
	// 生成,与 Traefik 静态配置 --providers.http.headers 同步传递)。
	TokenFile string
	// CertDir 是证书存储根目录(cert_dir;控制面侧明文 PEM,文件权限
	// 0600)。state-model §2.1:证书材料属控制面、独立备份目录。Traefik
	// 经平台自管命名卷(CertVolume)消费证书——控制面签发后经 seed 容器
	// 复制进卷(swarm 不接受 Windows 宿主路径 bind 挂载,实机验证结论;
	// Linux 单机 bind 亦被卷方案统一替代——一条代码路径)。
	CertDir string
	// CertVolume 是 Traefik 证书只读挂载的命名卷(cert_volume)。
	CertVolume string
	// CertSeedImage 是证书 seed 容器镜像(cert_seed_image;stopped 容器 +
	// docker API 拷贝,卷的持久化让 Traefik 重启不丢证书)。
	CertSeedImage string
	// ACME 是集中签发器配置。
	ACME ACMEConfig
	// RenewBefore 是续期窗口(到期前;renew_before_days)。
	RenewBefore time.Duration
	// RenewScanInterval 是续期扫描周期(renew_scan_seconds)。
	RenewScanInterval time.Duration
	// PollInterval 是 Traefik 拉取配置的轮询周期(静态配置参数;供收敛
	// 等待逻辑对齐节奏)。
	PollInterval time.Duration
}

Config 是入口适配器配置(config 键 ingress.*;缺省值经 Normalize 回落, 单一事实源在本包)。

func (Config) Normalize

func (c Config) Normalize() Config

Normalize 回落文档缺省值。

func (Config) Validate

func (c Config) Validate() error

Validate 校验配置不变量(fail-fast 于装配期)。

type DomainCheck

type DomainCheck struct {
	Domain string   `json:"domain"`
	IPs    []string `json:"ips"`
	// Resolved 报告本机是否解析得到至少一个地址。
	Resolved bool `json:"resolved"`
	// HTTP80 是配置 HTTP 端口的探测结果("" = 不可达;否则记录响应状态行)。
	HTTP80 string `json:"http_80,omitempty"`
	// HTTPS443 是配置 HTTPS 端口的 TLS 握手结果("" = 不可达)。
	HTTPS443 string `json:"https_443,omitempty"`
	// CertSubject / CertNotAfter 是 443 端口实收证书的诚实记录
	//(不经信任判定——私有 CA/临期证书照实呈现)。
	CertSubject  string   `json:"cert_subject,omitempty"`
	CertDNSNames []string `json:"cert_dns_names,omitempty"`
	CertNotAfter string   `json:"cert_not_after,omitempty"`
	Err          string   `json:"error,omitempty"`
}

DomainCheck 是单域名的验证报告。HTTP80/HTTPS443 字段名沿用既有 http_80/https_443 契约键(proto 契约面),E4 后承载的是「配置端口」的 探测结果(非默认端口部署下即该端口,不再恒为 80/443)。

func VerifyDomains

func VerifyDomains(ctx context.Context, domains []string, httpPort, httpsPort int) []DomainCheck

VerifyDomains 对域名集执行本机视角验证(并发 1 串行——探测量 ≤ 每服务 5 × 每应用 10 的契约上界,串行足够)。探测端口 httpPort/httpsPort 与 入口发布端口同源(调用方传 Manager 配置;E4,S19)。

type DynamicConfig

type DynamicConfig struct {
	HTTP *HTTPDynamic `json:"http,omitempty"`
	TLS  *TLSDynamic  `json:"tls,omitempty"`
}

DynamicConfig 是 Traefik 动态配置载荷(只承载平台产出的子集;字段名 对齐 Traefik v3 动态配置 JSON 契约)。

func EmptyConfig

func EmptyConfig() *DynamicConfig

EmptyConfig 是显式空 map 载荷(视图未发布时的应答:Traefik 拒绝该载荷 并保留其侧既有配置——「控制面没有好配置时不动入口」语义,Spike B b1 实测「键在值空」的 decode 拒绝路径;裸 {} 的清空形态永不出本包)。

func Synthesize

func Synthesize(routes []Route) *DynamicConfig

Synthesize 从全量路由集合成动态配置(确定性:路由按 app/service 字典 序;域名已由 compose 层归一化排序)。routers/services 键恒存在; serversTransport 平台默认恒注入(V4 连接治理参数)。

type DynamicService

type DynamicService struct {
	LoadBalancer *LoadBalancer `json:"loadBalancer"`
}

DynamicService 是一个负载均衡服务(VIP 形态:单 server 指向 fleetly-<app>-<service> 的 overlay VIP + expose 端口)。

type FileEntry

type FileEntry struct {
	Name string
	Data []byte
	Mode int64
}

FileEntry 是一次容器目录拷贝的单文件载荷(证书卷同步用)。

type ForwardingTimeouts

type ForwardingTimeouts struct {
	DialTimeout     string `json:"dialTimeout,omitempty"`
	IdleConnTimeout string `json:"idleConnTimeout,omitempty"`
}

ForwardingTimeouts 是转发超时(字符串时长形态——Spike B 脚本同款, Traefik v3 HTTP provider 实测接受)。

type HTTPDynamic

type HTTPDynamic struct {
	Routers           map[string]*Router           `json:"routers"`
	Services          map[string]*DynamicService   `json:"services"`
	ServersTransports map[string]*ServersTransport `json:"serversTransports,omitempty"`
}

HTTPDynamic 是 http 段(routers/services 键恒在——空 map 也显式写出, 让「缺键」形态在载荷层面不可能出现)。

type LoadBalancer

type LoadBalancer struct {
	Servers          []Server `json:"servers"`
	ServersTransport string   `json:"serversTransport,omitempty"`
}

LoadBalancer 是 LB 配置(serversTransport 恒引用平台默认连接治理参数, V4 依据见 config.go)。

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager 是入口与证书管理器。

func NewManager

func NewManager(cfg Config, store *state.Store, log *slog.Logger) (*Manager, func(), error)

NewManager 构造入口管理器(cfg 缺省回落;docker client 按 DOCKER_HOST/本机套接字构造)。返回 cleanup 释放 docker 连接。

func NewManagerWithDocker

func NewManagerWithDocker(cfg Config, store *state.Store, dc dockerClient, log *slog.Logger) *Manager

NewManagerWithDocker 以注入的 dockerClient 构造(单测)。

func (*Manager) Config

func (m *Manager) Config() Config

Config 返回生效配置(诊断)。

func (*Manager) EnsureTraefik

func (m *Manager) EnsureTraefik(ctx context.Context) error

EnsureTraefik 幂等收敛入口服务(不存在创建;存在比对差异更新)。 swarm 未就绪返回 ErrNotSwarmReady(服务壳降级重试)。

func (*Manager) Handler

func (m *Manager) Handler(ctx context.Context) (http.Handler, error)

Handler 返回配置端点 HTTP handler(服务壳挂到独立内部端口——取舍见 provider.go 顶部注释)。

func (*Manager) PublishRoutes

func (m *Manager) PublishRoutes(ctx context.Context, in PublishInput) error

PublishRoutes 实现 engine.RoutePublisher:域名台账对账 → Traefik 收敛 与网络接入 → 全量配置收敛(先校验后换视图)→ 证书保障(缺/域名集变化/ 临期即签发;签发失败不阻断已生效的 HTTP 路由,TLS 段随下次成功签发 收敛)。

语义注释(T2.15 设计取舍):发布失败的处置权在调用方(引擎)——部署 不回滚、route.publish_failed 单独告警 + 审计;本方法自身是幂等收敛 (重调即重试)。

func (*Manager) Run

func (m *Manager) Run(ctx context.Context) error

Run 是周期任务:Traefik 收敛 + 全量重发布 + 证书续期扫描(sweep)。 由 fleetlyd ingress 服务壳调用(ctx 取消返回)。收敛失败只降级日志 (下轮重试),不影响控制面其余服务。

func (*Manager) SetConfigPort

func (m *Manager) SetConfigPort(port int)

SetConfigPort 由服务壳在监听确定后回填(挑战应答 URL 依赖)。

func (*Manager) Status

func (m *Manager) Status(ctx context.Context) (Status, error)

Status 读取入口服务实况(Traefik 侧;配置端点健康经 Handler 面探测)。

func (*Manager) WithClock

func (m *Manager) WithClock(f func() time.Time) *Manager

WithClock 注入时钟(单测)。

func (*Manager) WithdrawAppRoutes

func (m *Manager) WithdrawAppRoutes(ctx context.Context, appID string) error

WithdrawAppRoutes 撤销 app 的全部路由(app 删除管线的显式撤销入口, H9):删该 app 域名台账行 → 全量重发布(台账空出的视图自然落 noop 兜底——Traefik 侧真实撤销旧路由)。幂等(无行删除为空操作、重发布 幂等);台账写入方唯一纪律(本包)决定域名清理必须经本通道。失败 语义与 PublishRoutes 同构:处置权在调用方(DeleteApp 侧失败告警)。

type PublishInput

type PublishInput struct {
	AppID   string
	AppName string
	// Services 是入口服务集(有 fleetly.domains label 的服务)。
	Services []ServiceRoutes
}

PublishInput 是一次路由发布的输入(engine.RoutePublisher 契约的载荷; domains/port 来自归一化 compose——首健康后由引擎提取)。

type Route

type Route struct {
	App     string
	Service string
	// Port 是后端目标端口(compose expose 首端口)。
	Port string
	// Domains 是该服务的域名集(归一化 compose spec 产出)。
	Domains []string
	// Cert 标记该 app 证书是否已就绪(就绪则 443 路由 + tls.certificates
	// 下发;未就绪只发 80 路由)。
	Cert *CertificateRef
}

Route 是一条应用路由(app 的一个入口服务;domains 已归一化)。

type Router

type Router struct {
	Rule        string   `json:"rule"`
	EntryPoints []string `json:"entryPoints"`
	Service     string   `json:"service"`
	// Priority 显式优先级(ACME 挑战路由用——压过 host 路由的默认
	// 规则长度优先级)。
	Priority int        `json:"priority,omitempty"`
	TLS      *RouterTLS `json:"tls,omitempty"`
}

Router 是一条路由规则。

type RouterTLS

type RouterTLS struct{}

RouterTLS 非 nil 即启用该路由的 TLS(443 入口路由携带)。

type Server

type Server struct {
	URL string `json:"url"`
}

Server 是一个后端。

type ServersTransport

type ServersTransport struct {
	MaxIdleConnsPerHost int                 `json:"maxIdleConnsPerHost,omitempty"`
	ForwardingTimeouts  *ForwardingTimeouts `json:"forwardingTimeouts,omitempty"`
}

ServersTransport 是连接治理参数集(V4 辅助治理;缺省 fleetly-default 由平台写死,不暴露配置面)。

type ServiceRoutes

type ServiceRoutes struct {
	Service string
	// Port 是后端端口(compose expose 首端口)。
	Port    string
	Domains []string
}

ServiceRoutes 是单个入口服务的路由声明。

type Status

type Status struct {
	Traefik     ingressServiceState
	AdvertiseIP string
	Responder   string
}

Status 是入口状态投影(fleetlyd 诊断)。

type TLSCertificate

type TLSCertificate struct {
	CertFile string `json:"certFile"`
	KeyFile  string `json:"keyFile"`
}

TLSCertificate 是一张证书的文件引用(容器内路径)。

type TLSDynamic

type TLSDynamic struct {
	Certificates []TLSCertificate `json:"certificates,omitempty"`
}

TLSDynamic 是 tls 段:证书集中下发(tls.certificates 文件引用形态, 文件经证书目录只读挂载到达 Traefik)。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL