Kubernetes 1.35.4 源码修改指南:证书有效期延长至 100 年
Kubernetes 1.35.4 源码修改指南:证书有效期延长至 100 年
适用版本:Kubernetes v1.35.4
修改目标:将 kubeadm 生成的证书有效期从默认的 1 年(组件证书)/ 10 年(CA 证书)延长至 100 年
运行环境:Linux (amd64)、Go 1.25+、Docker(可选)
一、背景说明
kubeadm 初始化集群时,会自动生成一套 PKI 证书体系:
|
|
|
|
|
|
10 年 | ca.crt
front-proxy-ca.crt、etcd/ca.crt |
|
|
1 年 | apiserver.crt
apiserver-kubelet-client.crt、etcd/healthcheck-client.crt 等 |
虽然 kubeadm 提供了 kubeadm certs renew all 命令用于证书续期,但在生产环境中频繁续期仍然是一个运维负担。本文将基于 Kubernetes 1.35.4 源码,详细说明如何通过修改源码并重新编译的方式,从根本上将证书有效期延长至 100 年。
二、Kubernetes 1.35.4 源码关键位置分析
在 v1.35.4 版本中,证书有效期的控制分散在三个关键位置:
2.1 证书有效期常量定义
文件:cmd/kubeadm/app/constants/constants.go
// 第 47-50 行
// CertificateValidityPeriod 定义 kubeadm 生成的所有签名证书的有效期(非 CA 证书)
CertificateValidityPeriod = time.Hour * 24 * 365// 默认 1 年
// CACertificateValidityPeriod 定义 kubeadm 生成的所有 CA 证书的有效期
CACertificateValidityPeriod = time.Hour * 24 * 365 * 10// 默认 10 年
2.2 kubeadm 签发证书时使用有效期
文件:cmd/kubeadm/app/util/pkiutil/pki_helpers.go
// 第 624 行 - 签发非 CA 证书(apiserver、etcd 等组件证书)
notAfter := notBefore.Add(kubeadmconstants.CertificateValidityPeriod)
// 第 667 行 - 签发自签名 CA 证书(ca、front-proxy-ca、etcd-ca)
notAfter := notBefore.Add(kubeadmconstants.CACertificateValidityPeriod)
2.3 client-go 通用 CA 证书工具
文件:staging/src/k8s.io/client-go/util/cert/cert.go
// 第 40 行
const duration365d = time.Hour * 24 * 365
// 第 79 行 - NewSelfSignedCACert 函数内
NotAfter: now.Add(duration365d * 10).UTC(), // 默认 10 年
此文件位于 staging 目录中,是独立的 Go 模块(k8s.io/client-go),被 kubelet、controller-manager 等组件引用。修改此处影响范围更广。
三、修改步骤(可直接复制执行)
步骤 1:进入源码目录并确认当前配置
# 进入 kubernetes 源码根目录
cd /path/to/kubernetes
# 确认修改前的默认值
grep -n "CertificateValidityPeriod\|CACertificateValidityPeriod" cmd/kubeadm/app/constants/constants.go
步骤 2:修改证书有效期常量(核心修改)
修改 ①:kubeadm 常量 — 组件证书有效期 1 年 → 100 年
文件:cmd/kubeadm/app/constants/constants.go 第 48 行
# macOS 使用以下命令(Linux 将 sed -i '' 改为 sed -i)
sed -i '''s/CertificateValidityPeriod = time.Hour \* 24 \* 365$/CertificateValidityPeriod = time.Hour * 24 * 365 * 100/' \
cmd/kubeadm/app/constants/constants.go
修改后效果:
// 修改前
CertificateValidityPeriod = time.Hour * 24 * 365// 1 年
// 修改后
CertificateValidityPeriod = time.Hour * 24 * 365 * 100// 100 年
修改 ②:kubeadm 常量 — CA 证书有效期 10 年 → 100 年
文件:cmd/kubeadm/app/constants/constants.go 第 50 行
# macOS 使用以下命令(Linux 将 sed -i '' 改为 sed -i)
sed -i '''s/CACertificateValidityPeriod = time.Hour \* 24 \* 365 \* 10$/CACertificateValidityPeriod = time.Hour * 24 * 365 * 100/' \
cmd/kubeadm/app/constants/constants.go
修改后效果:
// 修改前
CACertificateValidityPeriod = time.Hour * 24 * 365 * 10// 10 年
// 修改后
CACertificateValidityPeriod = time.Hour * 24 * 365 * 100// 100 年
修改 ③:client-go CA 证书有效期 10 年 → 100 年
文件:staging/src/k8s.io/client-go/util/cert/cert.go 第 79 行
# macOS 使用以下命令(Linux 将 sed -i '' 改为 sed -i)
sed -i '''s/NotAfter: now.Add(duration365d \* 10).UTC(),/NotAfter: now.Add(duration365d * 100).UTC(),/' \
staging/src/k8s.io/client-go/util/cert/cert.go
修改后效果:
// 修改前
NotAfter: now.Add(duration365d * 10).UTC(), // 10 年
// 修改后
NotAfter: now.Add(duration365d * 100).UTC(), // 100 年
步骤 3:验证修改结果
# 验证所有修改是否生效
echo"=== constants.go 修改结果 ==="
grep -n "CertificateValidityPeriod\|CACertificateValidityPeriod" cmd/kubeadm/app/constants/constants.go
echo""
echo"=== cert.go 修改结果 ==="
grep -n "NotAfter.*now.Add" staging/src/k8s.io/client-go/util/cert/cert.go
预期输出:
=== constants.go 修改结果 ===
48: CertificateValidityPeriod = time.Hour * 24 * 365 * 100
50: CACertificateValidityPeriod = time.Hour * 24 * 365 * 100
=== cert.go 修改结果 ===
79: NotAfter: now.Add(duration365d * 100).UTC(),
四、编译 kubeadm(支持 amd64 和 arm64)
macOS 前置依赖
macOS 默认的 tar 是 BSD 版本,Kubernetes 构建系统要求 GNU tar。编译前先安装:
# 安装 GNU 工具链
brew install gnu-tar
# 确认 GNU tar 可用(若安装在 /opt/homebrew/opt/gnu-tar/libexec/gnubin 则需加入 PATH)
which gtar || echo'export PATH="/opt/homebrew/opt/gnu-tar/libexec/gnubin:$PATH"' >> ~/.zshrc
Kubernetes 1.35.4 的 kubeadm 属于 Server 类组件,官方支持的编译目标平台为:
|
|
|
|
|
|
linux/amd64 |
|
|
|
linux/arm64 |
|
方法一:本地 Go 环境编译(推荐)
macOS 注意:确保 GNU tar 已安装(
brew install gnu-tar),否则构建脚本校验阶段会报错Cannot find GNU tar。
1.1 仅编译当前架构
# 确保 Go 版本 >= 1.25.0
go version
# 编译 kubeadm(自动识别当前 CPU 架构,产物位于 _output/bin/kubeadm)
make WHAT=cmd/kubeadm GOFLAGS=-v
# 查看编译后的版本和架构信息
_output/bin/kubeadm version
file _output/bin/kubeadm
1.2 同时编译 amd64 和 arm64(交叉编译)
# 设置目标平台列表,用空格分隔
export KUBE_BUILD_PLATFORMS="linux/amd64 linux/arm64"
# 编译 kubeadm,同时输出两个架构的二进制文件
make WHAT=cmd/kubeadm GOFLAGS=-v
编译产物输出路径:
# 编译完成后,产物按平台分别存放
_output/bin/linux/amd64/kubeadm # x86_64 二进制
_output/bin/linux/arm64/kubeadm # ARM64 二进制
# 查看各架构文件信息
file _output/bin/linux/amd64/kubeadm
# 输出:kubeadm: ELF 64-bit LSB executable, x86-64 ...
file _output/bin/linux/arm64/kubeadm
# 输出:kubeadm: ELF 64-bit LSB executable, ARM aarch64 ...
提示:macOS (darwin) 交叉编译 Linux 目标需要 Go 交叉编译工具链支持,Go 1.25 已内置,无需额外配置。
1.3 单独编译某个架构
# 仅编译 amd64
KUBE_BUILD_PLATFORMS="linux/amd64" make WHAT=cmd/kubeadm GOFLAGS=-v
# 仅编译 arm64
KUBE_BUILD_PLATFORMS="linux/arm64" make WHAT=cmd/kubeadm GOFLAGS=-v
1.4 编译其他组件
# 编译单个组件(当前架构)
make WHAT=cmd/kubelet GOFLAGS=-v # kubelet
make WHAT=cmd/kube-apiserver GOFLAGS=-v # kube-apiserver
make WHAT=cmd/kubectl GOFLAGS=-v # kubectl
# 同时编译多个组件 + 多架构
KUBE_BUILD_PLATFORMS="linux/amd64 linux/arm64" \
make WHAT="cmd/kubeadm cmd/kubelet cmd/kubectl" GOFLAGS=-v
# 编译所有组件(耗时较长)
make all
方法二:容器化编译(无需本地 Go 环境,天然支持多架构)
如果不希望配置本地 Go 开发环境,可以使用 Kubernetes 官方编译镜像(内置所有交叉编译工具链):
# 在源码根目录执行,启动编译容器
cd build/
# 编译当前架构的 kubeadm
./run.sh make kubeadm
# 同时编译 amd64 和 arm64
KUBE_BUILD_PLATFORMS="linux/amd64 linux/arm64" ./run.sh make kubeadm
# 产物与本地编译路径一致
ls -lh ../_output/bin/linux/amd64/kubeadm
ls -lh ../_output/bin/linux/arm64/kubeadm
build/run.sh 会自动拉取匹配当前源码版本的 registry.k8s.io/build-image/kube-cross 镜像,该镜像已预置所有目标平台的交叉编译工具链,在容器内完成编译。
方法三:Docker 手动指定平台编译
# 拉取编译镜像(以 go.work 中指定的 Go 1.25 为准)
docker pull registry.k8s.io/build-image/kube-cross:v1.35.0-go1.25.0-bullseye.0
# 编译 amd64 和 arm64
docker run --rm \
-v $(pwd):/go/src/k8s.io/kubernetes \
-w /go/src/k8s.io/kubernetes \
-e KUBE_BUILD_PLATFORMS="linux/amd64 linux/arm64" \
registry.k8s.io/build-image/kube-cross:v1.35.0-go1.25.0-bullseye.0 \
make WHAT=cmd/kubeadm GOFLAGS=-v
编译产物汇总
编译完成后,产物目录结构如下:
_output/bin/
├── linux/
│ ├── amd64/
│ │ └── kubeadm # x86_64 可执行文件(≈ 45 MB)
│ └── arm64/
│ └── kubeadm # ARM64 可执行文件(≈ 42 MB)
部署时根据目标节点架构选择对应的二进制文件即可:
# amd64 节点部署
scp _output/bin/linux/amd64/kubeadm root@<amd64-node>:/usr/bin/kubeadm
# arm64 节点部署
scp _output/bin/linux/arm64/kubeadm root@<arm64-node>:/usr/bin/kubeadm
五、部署与验证
5.1 备份现有环境(重要!)
# 备份原始 kubeadm 二进制
cp /usr/bin/kubeadm /usr/bin/kubeadm.bak.$(date +%Y%m%d)
# 备份当前证书目录
cp -r /etc/kubernetes/pki /etc/kubernetes/pki.bak.$(date +%Y%m%d)
5.2 替换 kubeadm 二进制
# 将编译好的 kubeadm 复制到系统路径
cp _output/bin/kubeadm /usr/bin/kubeadm
chmod +x /usr/bin/kubeadm
# 确认版本
kubeadm version
5.3 场景一:初始化新集群(自动使用 100 年有效期)
直接使用修改后的 kubeadm 初始化集群,生成的证书自动为 100 年有效期:
kubeadm init \
--kubernetes-version=v1.35.4 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=<your-api-server-ip>
初始化完成后验证证书有效期:
# 查看所有证书到期时间
kubeadm certs check-expiration
# 查看单个证书详情(验证是否为 100 年)
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep -A2 "Validity"
openssl x509 -in /etc/kubernetes/pki/ca.crt -text -noout | grep -A2 "Validity"
openssl x509 -in /etc/kubernetes/pki/front-proxy-ca.crt -text -noout | grep -A2 "Validity"
预期输出示例(100 年有效期):
Validity
Not Before: May 6 08:00:00 2026 GMT
Not After : May 3 08:00:00 2126 GMT
5.4 场景二:已有集群更新证书
如果集群已经存在,使用修改后的 kubeadm 续期所有证书:
# 第一步:续期所有证书(将使用新的 100 年有效期)
kubeadm certs renew all
# 第二步:验证续期结果
kubeadm certs check-expiration
# 第三步:重启控制平面组件(静态 Pod 管理方式)
# 方法 A:移走 manifest 再移回(推荐、安全)
mkdir -p /root/k8s-manifest-backup
mv /etc/kubernetes/manifests/*.yaml /root/k8s-manifest-backup/
sleep 10 # 等待旧 Pod 停止
mv /root/k8s-manifest-backup/*.yaml /etc/kubernetes/manifests/
# 方法 B:直接重启 kubelet
systemctl restart kubelet
# 第四步:更新本地 kubectl 配置
cp /etc/kubernetes/admin.conf ~/.kube/config
# 第五步:验证集群状态
kubectl get nodes
kubectl get pods -A
5.5 场景三:更新 kubeconfig 文件中的客户端证书
# kubeadm 生成的 kubeconfig 文件内嵌了客户端证书
# 需要重新生成以确保客户端证书也使用 100 年有效期
# 重新生成 admin.conf(100 年 = 876600 小时)
kubeadm kubeconfig user --client-name=kubernetes-admin --validity-period=876600h
# 或者重新生成所有 kubeconfig 文件
kubeadm init phase kubeconfig all --config=kubeadm-config.yaml
提示:kubeadm v1.35.4 已支持通过
--validity-period参数指定 kubeconfig 证书有效期,但由于已修改常量,默认值即为 100 年,无需额外指定。
六、编译容器镜像(可选,替换控制平面组件)
如果需要替换控制平面组件的容器镜像(使 kube-apiserver、kube-controller-manager、kube-scheduler 也使用修改后的代码):
# 编译所有组件
make all
# 使用官方脚本构建镜像
KUBE_DOCKER_REGISTRY=your-registry.example.com \
KUBE_BUILD_CONFORMANCE=n \
build/release-images.sh
# 生成的镜像包括:
# - your-registry.example.com/kube-apiserver:v1.35.4-dirty
# - your-registry.example.com/kube-controller-manager:v1.35.4-dirty
# - your-registry.example.com/kube-scheduler:v1.35.4-dirty
# - your-registry.example.com/kube-proxy:v1.35.4-dirty
使用自定义镜像部署集群:
cat > kubeadm-config.yaml <<EOF
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
imageRepository: your-registry.example.com
kubernetesVersion: v1.35.4
# 以下两个字段可选,因为修改源码后默认值已是 100 年
certificateValidityPeriod: 876600h # 100 年 = 365 * 24 * 100
caCertificateValidityPeriod: 876600h # 100 年
EOF
kubeadm init --config=kubeadm-config.yaml
七、常见问题与排查
7.1 编译报错:Go 版本不匹配
# 查看 go.work 要求的 Go 版本
head -5 go.work
# 确保本地 Go 版本匹配
go version
# 版本不匹配时切换到容器化编译方式(方法二或方法三)
7.2 编译产物找不到
# 确认编译产物位置(默认在 _output/bin/ 下)
ls -lh _output/bin/
# 自定义输出路径示例
make WHAT=cmd/kubeadm OUT_DIR=_custom_output
7.3 证书续期后 apiserver 无法启动
# 验证证书链是否完整
openssl verify -CAfile /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/apiserver.crt
# 查看 apiserver 容器日志
crictl logs $(crictl ps --name kube-apiserver -q)
# 确保证书目录权限正确
ls -la /etc/kubernetes/pki/
7.4 恢复原始 kubeadm(回滚操作)
# 恢复备份的 kubeadm 二进制
cp /usr/bin/kubeadm.bak.20260506 /usr/bin/kubeadm
# 恢复备份的证书
rm -rf /etc/kubernetes/pki
cp -r /etc/kubernetes/pki.bak.20260506 /etc/kubernetes/pki
# 重启 kubelet 使静态 Pod 生效
systemctl restart kubelet
八、修改文件总览
|
|
|
|
|
|
|
|
cmd/kubeadm/app/constants/constants.go |
|
* 365
* 365 * 100 |
|
|
|
cmd/kubeadm/app/constants/constants.go |
|
* 365 * 10
* 365 * 100 |
|
|
|
staging/src/k8s.io/client-go/util/cert/cert.go |
|
duration365d * 10
duration365d * 100 |
|
九、Kubernetes 1.35.4 完整调用链说明
理解调用链有助于判断修改是否完整覆盖所有证书生成路径:
kubeadm init / kubeadm certs renew
│
├── phases/certs/certlist.go (GetConfig 方法)
│ ├── 读取 CertificateValidityPeriod → 设置非 CA 证书 NotAfter
│ └── 读取 CACertificateValidityPeriod → 设置 CA 证书 NotAfter
│
├── util/pkiutil/pki_helpers.go
│ ├── NewSignedCert() 函数 第 624 行
│ │ └── notAfter = notBefore.Add(CertificateValidityPeriod) ← 常量
│ └── NewSelfSignedCACert() 函数 第 667 行
│ └── notAfter = notBefore.Add(CACertificateValidityPeriod) ← 常量
│
└── phases/kubeconfig/kubeconfig.go 第 476 行
└── notAfter = startTime.Add(CertificateValidityPeriod) ← 生成 kubeconfig 证书
client-go(staging 模块,被 kubelet 等组件引用)
└── util/cert/cert.go → NewSelfSignedCACert() 第 79 行
└── NotAfter: now.Add(duration365d * 10) ← 硬编码,需单独修改
十、其他可自定义参数说明
在 kubeadm v1.35.4 中,除了证书有效期常量外,还可以通过以下参数影响证书生成:
|
|
|
|
CertificateBackdate |
constants.go:46 |
time.Minute * 5),用于应对节点间时间偏移 |
EncryptionAlgorithm |
v1beta4/defaults.go:61 |
|
certificateValidityPeriod |
|
|
caCertificateValidityPeriod |
|
|
如需进一步自定义,可修改对应的常量或配置文件字段。
十一、总结
通过修改 3 个文件中的 3 处关键代码,即可将 Kubernetes 1.35.4 集群的证书有效期从默认的 1~10 年延长至 100 年。核心操作流程:
-
1. 修改常量 — constants.go中的CertificateValidityPeriod和CACertificateValidityPeriod各乘以 100 -
2. 修改底层工具 — cert.go中的 CA 证书默认有效期乘以 100 -
3. 重新编译 — make WHAT=cmd/kubeadm编译新二进制 -
4. 替换部署 — 用新编译的 kubeadm 初始化集群或续期已有证书
所有 sed 命令可直接复制执行,无需手动编辑文件,确保修改的一致性和可重复性。
免责声明:本文档仅供技术研究和学习参考。修改 Kubernetes 源码可能影响集群的合规性和安全性,请在生产环境操作前充分测试。
夜雨聆风