fedctl 是 eBay Tess 平台用于管理联邦控制平面(FCP, Federation Control Plane)的核心工具。本文从仓库结构出发,详细介绍 fedctl 的构建方式、使用方法、资源配置、权限要求以及控制平面的退役流程,帮助团队成员系统性地掌握 FCP 的运维体系。
一、仓库整体框架与结构 fed-release 仓库是 fedctl 工具的配置输入仓库 ,不包含 fedctl 的源代码(源码在 github.corp.ebay.com/ebaytess/fedctl)。仓库的作用是存放各个 FCP 实例的配置文件以及 fedctl 生成的 Kubernetes 对象 YAML 文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 fed-release/ ├── BUILD.bazel # Bazel 构建入口(顶层) ├── WORKSPACE # Bazel workspace 定义 ├── README.md # 仓库说明文档 ├── pub.asc # GPG 公钥(用于 git-crypt) ├── hack/ # 运维脚本集合 │ ├── fedctl-run.sh # 下载并执行 fedctl 的入口脚本 │ ├── fedctl-bump.sh # 更新 FEDCTL_VERSION 文件 │ ├── fedctl-handle-merge.sh # PR 合并后的流水线触发脚本 │ ├── fedctl-apply-with-lease.sh │ ├── fedctl-global-join-with-lease.sh │ ├── lib.sh # 公共 shell 函数库 │ ├── drift/ # 镜像漂移检测脚本 │ └── join/ # join 相关辅助脚本 ├── instances/ # 各控制平面实例配置目录 │ ├── fcp/ # FCP(主联邦控制平面)实例 │ │ ├── README.md │ │ ├── common/ # 跨实例共享配置(k8sclusters.json、证书等) │ │ ├── dev/ # fcp-dev 环境 │ │ │ ├── cfg.toml # 核心配置文件 │ │ │ ├── FEDCTL_VERSION # 当前使用的 fedctl 版本号 │ │ │ ├── secrets/ # 加密的 kubeconfig / 证书等(git-crypt) │ │ │ ├── cm/ # ConfigMap 配置 │ │ │ ├── health/ # 健康检查对象 │ │ │ ├── flowschema/ # APF FlowSchema 配置 │ │ │ ├── pdi/ # PDI assertion 对象 │ │ │ ├── fcp-dev/ # 聚合器(aggregator)集群的生成产物 YAML │ │ │ ├── 130/ # host cluster 130 的生成产物 YAML │ │ │ └── 140/ # host cluster 140 的生成产物 YAML │ │ ├── preprod/ │ │ ├── prod/ │ │ └── soak-dev/ │ ├── fcp-sddz/ # SDDZ 环境的 FCP 实例 │ ├── apps/ # Apps 控制平面实例 │ ├── tnet/ # TNet 控制平面实例 │ └── tm/ # TM 控制平面实例 └── runbooks/ # 运维手册 ├── design.md # FCP 架构设计文档 ├── dev.md # 开发环境搭建指南 ├── release.md # 发布流程 ├── rbac.md # 权限说明 ├── wrap-up.md # 发布收尾步骤 └── ...(其他专项 runbook)
FCP 组件架构概览 FCP 是一个无节点、无 kubelet 的纯 API 控制平面 ,所有 FCP 组件以普通 Deployment 的形式运行在现有 Tess host cluster 中,并跨多个 host cluster 分布以实现 HA。核心组件包括:
组件
说明
etcd
由定制化 etcd-operator 管理,支持多 host cluster 跨 AZ 部署
kube-apiserver
标准 K8s apiserver,禁用部分 API,启用聚合扩展
ebay-apiserver
自定义 Tess 扩展 apiserver,服务 Account/Group 等自定义 API
admission-apiserver
准入 apiserver,负责所有 webhook 校验与变更
webhook
认证/授权 webhook(Keystone token + TessRBAC)
kube-controller-manager
标准 controller-manager,大量 controller 已禁用
FCM(ebay-controller-manager)
Federation Controller Manager,包含 sync controller、account controller 等
FCM-AP
Access Point 相关 controller
FCM-ATC
流量控制相关 controller(Admin Traffic Control)
FCM-NSVC
NameService controller
audit-transformer
审计日志转换器
PSCP controller
安全策略同步 controller
上述所有 apiserver 组件(kube-apiserver、ebay-apiserver、admission-apiserver、webhook)共享同一个 Pod,通过 loopback 地址(127.x.x.x)互相通信,以减少网络开销。
二、如何构建 fedctl fedctl 的源代码位于 github.corp.ebay.com/ebaytess/fedctl,fed-release 仓库本身不包含 fedctl 的构建过程。
方式一:直接下载预编译二进制 这是 CI/CD 流水线(Tekton)使用的方式,由 hack/fedctl-run.sh 自动完成:
1 2 3 4 5 6 7 fedctl_version=$(cat "${artifact_dir} /FEDCTL_VERSION" ) bin="hack/cache/fedctl-${fedctl_version} " wget -O "$bin " \ "https://dl.tess.io/bin/fedctl?version=${fedctl_version} &platform=linux-amd64" chmod +x "$bin "
每个实例目录下的 FEDCTL_VERSION 文件记录该实例使用的 fedctl 版本,例如:
1 instances/fcp/dev/FEDCTL_VERSION
方式二:从源码构建(开发调试) 在 fedctl 源码仓库中直接用 go run 运行:
1 2 3 4 5 6 7 8 9 10 git clone git@github.corp.ebay.com:ebaytess/fedctl.git cd fedctlgit checkout <fedctl_tag> go run cmd/fedctl/main.go <subcommand> [flags] go build -o fedctl cmd/fedctl/main.go ./fedctl <subcommand> [flags]
方式三:通过 Docker 容器运行(本地测试) 1 2 3 4 5 docker run -v $(pwd ):/scratch/fed-release --rm \ hub.tess.io/sig-core-cicd/fedctl-base:v0.2 \ bash -c "OFFLINE=false \ INSTANCE_CFG=/scratch/fed-release/instances/fcp/dev/cfg.toml \ /scratch/fed-release/hack/fedctl-run.sh generate"
更新 fedctl 版本 1 2 3 INSTANCE_CFG=instances/fcp/dev/cfg.toml \ hack/fedctl-bump.sh <new_version>
三、fedctl 的使用方式 fedctl 的所有操作都通过子命令(subcommand)+ 配置文件(cfg.toml) 驱动。
核心使用模式 1 2 3 4 5 6 INSTANCE_CFG=instances/fcp/dev/cfg.toml \ hack/fedctl-run.sh <subcommand> [extra flags] fedctl <subcommand> --config=instances/fcp/dev/cfg.toml [flags]
主要子命令
子命令
功能
kubeconfig-builder
为 FCP 生成 kubeconfig 文件
etcd-init
初始化/更新 etcd 集群(通过 etcd-operator)
apiserver-init
初始化/更新 apiserver、kube-controller-manager 等
fcm-init
初始化/更新 Federation Controller Manager
nsvc-init
初始化/更新 NameService controller
join
将单个 member cluster 加入 FCP
join-all
将所有 sync candidate clusters 加入 FCP
assert-init
初始化 assertion(端到端测试)框架
health-init
初始化健康检查 monitor
install-pscp-controller
部署 PSCP 安全策略 controller
pdi-init
初始化 PDI(Pre-Delivery Inspection)assertion
generate
仅生成 YAML 文件,不 apply(用于 offline/dry-run)
azkubeconfig-init
为 AZ 控制平面生成 kubeconfig
典型发布流程 cfg.toml 中通过 subcommands 字段定义按序执行的子命令列表:
1 2 3 4 5 6 7 8 9 10 11 subcommands = [ "etcd-init" , "apiserver-init" , "fcm-init" , "nsvc-init" , "join-all" , "assert-init" , "health-init" , "install-pscp-controller" , "pdi-init" , ]
标准发布步骤(每个子命令先 dry-run,再正式 apply):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 go run cmd/fedctl/main.go kubeconfig-builder \ --config=${config_toml} \ --kubeconfig=/tmp/fcp \ --artifact-dir=${artifact_dir} for cmd in etcd-init apiserver-init fcm-init join-all; do go run cmd/fedctl/main.go ${cmd} \ --config=${config_toml} \ --artifact-dir=${artifact_dir} \ --kubeconfig=/tmp/fcp \ --generate-only go run cmd/fedctl/main.go ${cmd} \ --config=${config_toml} \ --artifact-dir=${artifact_dir} \ --kubeconfig=/tmp/fcp done
--generate-only 标志只生成 YAML 文件到 artifact_dir,不实际 apply 到集群,用于审查变更内容。
四、fedctl 是否包含 Namespace 创建与容量分配 Namespace 创建 fedctl 本身负责在 host cluster 创建 FCP 相关的 Namespace (如 fcp-dev、member-fcp-dev),这些 Namespace 通过 cfg.toml 中的以下参数控制:
1 2 3 4 federation-name = "fcp-dev" namespace-annotations = "application.tess.io/name=fcp,environment.tess.io/name=dev,identity.alpha.tess.io/default-posixuser=true" namespace-labels = "account.tess.io/name=fcp" cluster-namespace = "member-fcp-dev"
但FCP 作为 API 层使用的上游 Namespace (即 FCP 在父 FCP 中注册自身所需的 Account/Group/Namespace)需要手动提前创建 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 kubectl apply -f - <<EOF apiVersion: identity.tess.io/v1alpha1 kind: Group metadata: name: ${tess_group} --- apiVersion: identity.tess.io/v1alpha1 kind: Account metadata: name: ${tess_acct} --- apiVersion: v1 kind: Namespace metadata: name: ${federation_name} annotations: application.tess.io/name: ${tess_app} environment.tess.io/name: ${real_tess_env} labels: account.tess.io/name: ${tess_acct} EOF
容量分配(Quota) fedctl 不负责配额分配 ,配额需要在运行 fedctl 之前通过 http://go/arq 手动申请。
需要为以下 Namespace 申请配额:
<fcp-name> namespace(运行 apiserver/etcd 的主 namespace):
Quota 类型
资源
参考值
best-effort-pods
pods
7
object-counts
configmaps
1
object-counts
secrets
18
object-counts
services
3
object-counts
loadbalancer services
1
object-counts
nodeport services
1
<fcp-name>-fcm namespace(运行 FCM 的 namespace):
Quota 类型
资源
参考值
best-effort-pods
pods
2
object-counts
configmaps
1
object-counts
secrets
4
实际生产所需配额需根据副本数计算:etcd × 副本数 + apiserver × 副本数 + kube-controller-manager + fcm + fcm-ap + ...
五、组件资源配置:CPU/Memory、Label Selector 与 Tolerations 所有组件的资源配置均在各实例的 cfg.toml 中统一管理,fedctl 将这些参数渲染为 Deployment YAML 后 apply 到集群。
CPU/Memory 资源配置 以 fcp-dev 的 cfg.toml 为例,各组件配置键的命名规律为 <component>-cpu-request、<component>-memory-limit 等:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 etcd-cpu-limit = "12" etcd-cpu-request = "4" etcd-memory-limit = "60Gi" etcd-memory-request = "10Gi" etcd-events-cpu-limit = "3" etcd-events-cpu-request = "1" etcd-events-memory-limit = "10Gi" etcd-events-memory-request = "3Gi" apiserver-cpu-limit = "16" apiserver-cpu-request = "2" apiserver-memory-limit = "150G" apiserver-memory-request = "80G" ebay-cpu-limit = "12" ebay-cpu-request = "1" ebay-memory-limit = "120G" ebay-memory-request = "60G" webhook-cpu-limit = "1" webhook-cpu-request = "100m" webhook-memory-limit = "20G" webhook-memory-request = "4G" admission-cpu-limit = "4" admission-cpu-request = "50m" admission-memory-limit = "80G" admission-memory-request = "20G" proxy-sidecar-cpu-limit = "0.5" proxy-sidecar-cpu-request = "10m" proxy-sidecar-memory-limit = "200M" proxy-sidecar-memory-request = "50M" tfc-cpu-request = 3 tfc-memory-request = "12Gi" tfc-cpu-limit = 8 tfc-memory-limit = "115Gi" fed-ap-cpu-request = 4 fed-ap-memory-request = "4Gi" fed-ap-cpu-limit = 20 fed-ap-memory-limit = "16Gi" az-ap-cpu-request = 1 az-ap-memory-request = "4Gi" az-ap-cpu-limit = 8 az-ap-memory-limit = "16Gi" cluster-ap-cpu-request = 4 cluster-ap-memory-request = "8Gi" cluster-ap-cpu-limit = 20 cluster-ap-memory-limit = "48Gi" fcm-atc-cpu-request = 2 fcm-atc-memory-request = "3Gi" fcm-atc-cpu-limit = 6 fcm-atc-memory-limit = "9Gi" fcm-nsvc-cpu-request = 8 fcm-nsvc-memory-request = "4Gi" fcm-nsvc-cpu-limit = 20 fcm-nsvc-memory-limit = "100Gi" audit-transformer-cpu-limit = "3" audit-transformer-cpu-request = "50m" audit-transformer-memory-limit = "8Gi" audit-transformer-memory-request = "50Mi" tfc-in-cluster-cpu-request = "500m" tfc-in-cluster-memory-request = "1Gi" tfc-in-cluster-cpu-limit = 1 tfc-in-cluster-memory-limit = "4Gi" aim-cpu-request = 1 aim-cpu-limit = 2 aim-memory-request = "3Gi" aim-memory-limit = "6Gi"
副本数配置 副本数按 host cluster 维度分别指定,格式为 <cluster_id>=<count>:
1 2 3 4 5 6 7 8 9 10 11 apiserver-replicas = "130=4,140=4" host-cluster-replicas = "130=3,140=4" fcm-replicas = "130=1,140=1" controller-manager-replicas = "130=1,140=1"
Template Label Selector fedctl 通过 deployment-labels 和 pod-labels 参数为各组件的 Deployment 和 Pod 注入 label,用于 health monitor 和其他控制器的选择器:
1 2 3 4 5 6 deployment-labels = "fcm=applicationinstance.tess.io/name=fcp-ebay-controller-manager-dev,\ controller-manager=applicationinstance.tess.io/name=fcp-controller-manager-dev,\ apiserver=application.tess.io/name=fcp-apiserver\\,applicationinstance.tess.io/name=fcp-apiserver-dev,\ etcd-operator=application.tess.io/name=fcp-etcd\\,applicationinstance.tess.io/name=fcp-etcd-dev" pod-labels = "fcm=applicationinstance.tess.io/name=fcp-ebay-controller-manager-dev,..."
格式为 <component>=<label-key>=<label-value>,多个 label 间用 \\, 分隔(转义逗号)。
健康检查 label selector 通过独立参数配置:
1 2 3 4 5 6 7 8 apiserver-healthmonitor-labels = "apiserver-release=controlplane" ap-healthmonitor-labels = "ap-fed-release=canary" health-monitor-labels = "master@fcp-dev:apiserver-release=controlplane,ap-fed-release=canary"
Tolerations 配置 Tolerations 在 cfg.toml 中统一配置,应用于所有 FCP 组件的 Pod:
1 2 tolerations = "dedicated=highmem:NoSchedule"
格式为 <key>=<value>:<effect>,如需强制调度到特定节点,配合 node-selector 使用:
六、如何退役(Decomm)和销毁一个 FCP Apiserver 目前 fed-release 仓库中没有专用的”一键退役”命令,FCP apiserver 的退役是一个手动分步骤 的过程。
步骤一:确认健康状态与备份 1 2 3 4 etcd-operator-backup-s3-bucket = "fcp-dev-2" etcd-operator-backup-max-backups = "288"
步骤二:从 cfg.toml 中缩容组件 将 apiserver 副本数归零,然后重新运行 apiserver-init:
1 2 3 apiserver-replicas = "130=0,140=0" controller-manager-replicas = "130=0,140=0"
1 2 3 4 go run cmd/fedctl/main.go apiserver-init \ --config=${config_toml} \ --artifact-dir=${artifact_dir} \ --kubeconfig=/tmp/fcp
步骤三:清理 fedctl 管理的生成物(Pruning) fedctl 使用 kubectl apply 语义,不会自动删除旧对象。需要手动找出并删除过期对象:
1 2 3 4 5 6 7 8 9 10 11 cd ${artifact_dir} find . -type f -mmin +120 -ls kubectl --kubeconfig=${kubeconfig} --context=<context> \ [-n <namespace>] delete <kind> <name> find . -type f -mmin +120 -delete
步骤四:清理 member cluster 中的资源 对于每个已 join 的 member cluster,需要删除 fedctl 在其中创建的资源(ServiceAccount、ClusterRoleBinding、Deployment 等):
1 2 3 4 5 kubectl --kubeconfig=${kubeconfig} --context=<cluster_id> \ -n member-fcp-dev delete deploy fcm fcm-ap fcm-ap-canary kubectl --kubeconfig=${kubeconfig} --context=<cluster_id> \ delete clusterrolebinding fed-member-fcp-dev:fcm
步骤五:清理 FCP 中的 Cluster 对象与配置 1 2 3 4 5 6 7 8 9 vi instances/fcp/${FCP_INSTANCE} /cfg.toml go run cmd/fedctl/main.go join-all \ --config=${config_toml} \ --artifact-dir=${artifact_dir} \ --kubeconfig=/tmp/fcp
步骤六:回滚方案 如果退役过程出现问题,简单回滚方式是还原 cfg.toml 并重新运行发布流程 :
1 2 3 4 git revert HEAD go run cmd/fedctl/main.go etcd-init --config=... --kubeconfig=... go run cmd/fedctl/main.go apiserver-init --config=... --kubeconfig=...
极端情况(数据损坏)可从 etcd 备份恢复,参考 runbooks/etcd-backup-and-restore.md。
七、fedctl 使用所需的权限 1. 基本 FCP Admin 权限 运行 fedctl 的用户或 CI 服务账号需要是 FCP admin group 成员:
1 2 admin-users = [ "group:fcp_admin" , "l=qa+ou=sig-core-cicd-dev,o=sig-core-cicd,dc=tess,dc=ebay,dc=com" ]
2. Join 命令的特殊权限 join 子命令需要在 member cluster 中拥有 impersonation 权限,这通过 sig-security 仓库的 PR 申请:
参考 sig-security#268 格式提交 PR,合并后等待约 10 分钟生效。
3. git-crypt 解密权限 fed-release 仓库使用 git-crypt 加密 secrets/ 目录下的敏感文件(kubeconfig、证书、云服务凭据等)。需要请现有协作者将你的 GPG 公钥添加到仓库:
1 2 3 4 5 6 7 8 9 10 gpg --gen-key gpg --export --armor your@email.com > pub.asc gpg --import pub.asc git-crypt add-gpg-user --trusted new-user@ebay.com git-crypt unlock
4. sig-security 权限(sync controller 写入权限) sync controller 在 member cluster 中变更资源需要特殊授权,通过 sig-security 仓库管理:
参考 sig-security#3284 格式申请。
5. kubeconfig 访问权限 fedctl 通过 secrets/kubeconfig 访问 host cluster 和 member cluster,该 kubeconfig 中的 ServiceAccount token 需要具备以下权限:
host cluster:在 FCP namespace 内创建/更新 Deployment、ConfigMap、Secret、Service 等
member cluster:通过 cd 或 continuous-deployment ServiceAccount 访问(具备 namespace-admin ClusterRole)
总结
主题
关键点
构建
下载预编译二进制(生产)或 go run(开发),版本由 FEDCTL_VERSION 文件管理
使用
子命令 + cfg.toml 驱动,建议先 --generate-only 审查再正式 apply
Namespace
fedctl 负责 host/member cluster 的 FCP namespace;父 FCP 中的账号体系需手动创建
容量分配
fedctl 不管理 Quota,需提前通过 go/arq 申请
资源配置
所有 CPU/Memory/副本数均在 cfg.toml 中配置,label selector 通过 deployment-labels 设置
退役
无专用命令,需手动缩容 → 清理生成物 → 清理 member cluster → 提 PR 删除配置
权限
需要 FCP admin group 成员身份 + git-crypt 解密权限 + sig-security 申请(join/sync)
fedctl 将复杂的多集群控制平面编排抽象为声明式配置,通过 cfg.toml 单文件驱动整个 FCP 生命周期管理,配合 Tekton 流水线实现全自动化发布,是 eBay Tess 平台控制平面运维体系的核心。