k8s重新部署的配置过程


✅ 一、整体架构总结

项目 说明
Kubernetes 版本 v1.20.0
部署方式 使用官方工具 kubeadm 初始化控制平面,并加入工作节点
节点组成 - yxa-master:控制平面(etcd, apiserver, controller-manager, scheduler) - yxa-worker1:NotReady(CNI 或 CIDR 问题) - yxa-worker2:Ready(可正常调度 Pod)
容器运行时 Docker (通过 docker build 构建应用镜像)
网络插件 Flannel (通过 kube-flannel.yaml 部署,使用 vxlan 模式)
DNS CoreDNS(默认)
监控 metrics-server(当前失败,因镜像拉取问题)

📌 集群状态:可用于测试,但存在稳定性隐患(controller/scheduler 高频重启)

🔧 二、关键配置项解析

1. Kubelet cgroup 驱动配置

文件路径(Ubuntu/Debian):

复制代码
/etc/default/kubelet

内容:

复制代码
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd

作用

强制 kubelet 使用 systemd 作为 cgroup 驱动,必须与 Docker 的驱动一致,否则 kubelet 启动失败或 Pod 无法创建。

为什么用 systemd

  • 现代 Linux 发行版(Ubuntu 18.04+、CentOS 7+)默认使用 systemd 管理服务。
  • 若 kubelet 用 cgroupfs 而系统用 systemd,会导致资源隔离混乱、节点 NotReady。

2. Docker 的 daemon.json 配置

复制代码
# 1. 创建或编辑 daemon.json
sudo mkdir -p /etc/docker
sudo cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

# 2. 重载并重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker

# 3. 验证
docker info | grep -i "cgroup driver"
# 输出应为:Cgroup Driver: systemd

三、实际用到的部署流程(回顾)

  1. 准备阶段

    • 下载 Kubernetes 组件镜像(k8s-images.tar
    • 使用 docker load 导入镜像(离线部署)
    • 配置 kubeadm-config.yaml(指定 podSubnet,如 10.244.0.0/16
  2. 初始化集群

复制代码
  kubeadm init --config=kubeadm-config.yaml
  • 配置 kubelet

    • 设置 KUBELET_EXTRA_ARGS=--cgroup-driver=systemd
    • 启动 kubelet:systemctl enable --now kubelet
  • 部署网络插件

复制代码
  kubectl apply -f kube-flannel.yaml
  • 加入工作节点

复制代码
  kubeadm join <master-ip>:6443 --token ... --discovery-token-ca-cert-hash ...
  • 部署应用(当前目标)

    • 从 GitLab 克隆代码(跳过 SSL 验证)
    • 构建 Docker 镜像
    • 复制镜像到 yxa-worker2
    • imagePullPolicy: Never 部署 Deployment

四、控制平面高频重启问题已修复

问题现象

  • kube-controller-managerkube-schedulerRESTARTS > 200
  • 根本原因:/etc/kubernetes/manifests/ 下的 Static Pod YAML 文件被反复修改(即使内容不变,metadata 变化也会触发重建)

解决方案

  • 对关键 manifest 文件启用 Linux 不可变属性(immutable)

    chattr +i /etc/kubernetes/manifests/kube-apiserver.yaml

    chattr +i /etc/kubernetes/manifests/kube-controller-manager.yaml

    chattr +i /etc/kubernetes/manifests/kube-scheduler.yaml

验证命令

复制代码
lsattr /etc/kubernetes/manifests/kube-*.yaml # 应显示 "i" 标志 

kubectl get pods -n kube-system # RESTARTS 不再增长

五、Kubelet 证书自动轮换已启用(生产就绪)

配置确认

  • /var/lib/kubelet/config.yaml 中已设置:
复制代码
  rotateCertificates: true 
  featureGates: 
    RotateKubeletServerCertificate: true   # (可选但已启用)

自动批准机制

  • 已创建以下 RBAC 规则,实现 CSR 自动批准:
    • auto-approve-renewals-for-nodes → 客户端证书
    • auto-approve-renewals-for-serving-nodes → 服务端证书

当前证书状态

复制代码
notBefore=Dec 18 10:51:28 2025 GMT 

notAfter=Dec 18 10:51:30 2026 GMT

✅ 有效期 1 年,近期签发,完全正常。

验证命令

复制代码
kubectl get csr # 应无 Pending 请求 

openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates

结果 :kubelet 证书将在到期前自动续订,无需人工干预

一键健康检查脚本

复制代码
#!/bin/bash

# 输出分隔符
divider="=========================================================================="

echo "$divider"
echo "=== Kubernetes Cluster Health Check ==="
echo "$divider"

# 1. 检查节点状态
echo "=== Node Status ==="
kubectl get nodes

# 2. 检查关键 Pod 状态
echo -e "\n$divider\n=== Critical Pods (kube-system) ==="
kubectl get pods -n kube-system | grep -E 'controller|scheduler|etcd|apiserver'

# 3. 检查 kubelet 客户端证书有效期
echo -e "\n$divider\n=== Kubelet Client Cert Expiry ==="
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -enddate

# 4. 检查控制平面证书有效期
echo -e "\n$divider\n=== Control Plane Certificates ==="
kubeadm certs check-expiration 2>/dev/null | grep -E "(NAME|apiserver|etcd)"

# 5. 检查 Pending CSR
echo -e "\n$divider\n=== Certificate Signing Requests ==="
kubectl get csr

# 6. 检查 etcd 健康状态
echo -e "\n$divider\n=== Etcd Health Check ==="
ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
  --endpoints=https://127.0.0.1:2379 endpoint health

echo -e "\n$divider\n=== Health Check Complete ==="

#!/bin/bash
# check_cert_expiry.sh
# 用法: ./check_cert_expiry.sh gitlab2.ctjt.cn 30

DOMAIN=${1:-"gitlab2.ctjt.cn"}
DAYS_WARN=${2:-30}  # 提前多少天告警
LOG_FILE="/var/log/cert-check.log"

# 获取证书过期时间戳
EXPIRY_TIMESTAMP=$(echo | openssl s_client -connect "$DOMAIN":443 2>/dev/null | openssl x509 -enddate -noout 2>/dev/null | cut -d= -f2)

if [ -z "$EXPIRY_TIMESTAMP" ]; then
    echo "$(date): ❌ 无法获取 $DOMAIN 的证书信息" | tee -a "$LOG_FILE"
    exit 1
fi

# 转为 Unix 时间戳
EXPIRY_EPOCH=$(date -d "$EXPIRY_TIMESTAMP" +%s 2>/dev/null)
NOW_EPOCH=$(date +%s)
SECONDS_LEFT=$((EXPIRY_EPOCH - NOW_EPOCH))
DAYS_LEFT=$((SECONDS_LEFT / 86400))

# 记录日志
echo "$(date): $DOMAIN 证书剩余有效期: ${DAYS_LEFT} 天 (过期时间: $EXPIRY_TIMESTAMP)" >> "$LOG_FILE"

# 告警逻辑
if [ $DAYS_LEFT -lt 0 ]; then
    MESSAGE="🚨 紧急!$DOMAIN 证书已过期!"
    echo "$MESSAGE"
    # 可在此处添加邮件/钉钉/企业微信通知
elif [ $DAYS_LEFT -le $DAYS_WARN ]; then
    MESSAGE="⚠️ 警告:$DOMAIN 证书将在 $DAYS_LEFT 天后过期($EXPIRY_TIMESTAMP)"
    echo "$MESSAGE"
    # 示例:发送到 syslog 或文件
    logger -t cert-check "$MESSAGE"
else
    echo "✅ $DOMAIN 证书状态正常(剩余 $DAYS_LEFT 天)"
fi

六、内网自签名证书批量部署

复制代码
# 创建 CA 目录
mkdir -p ~/internal-ca/{certs,private,newcerts}
cd ~/internal-ca
echo 1000 > serial
touch index.txt

# 生成根私钥
openssl genrsa -out private/ca.key.pem 4096
chmod 400 private/ca.key.pem

# 生成根证书(有效期 10 年)
openssl req -new -x509 -days 3650 \
  -key private/ca.key.pem \
  -out certs/ca.cert.pem \
  -subj "/CN=Internal Root CA/O=YourOrg"
chmod 444 certs/ca.cert.pem


# 生成 gitlab2 的私钥
openssl genrsa -out gitlab2.key 2048

# 生成 CSR
openssl req -new -key gitlab2.key -out gitlab2.csr -subj "/CN=gitlab2.ctjt.cn"

# 用 CA 签发
openssl ca -batch -config openssl.cnf -extensions v3_req \
  -days 3650 -in gitlab2.csr -out gitlab2.crt

#!/bin/bash
# install-ca.sh
# 用法: curl -s https://your-intranet/ca/install-ca.sh | sudo bash

CA_URL="http://your-intranet.local/ca/certs/ca.cert.pem"
DEST="/usr/local/share/ca-certificates/internal-root-ca.crt"

echo "📥 正在下载内部 CA 证书..."
curl -fL "$CA_URL" -o "$DEST"

if [ $? -eq 0 ]; then
    update-ca-certificates
    echo "✅ 内部 CA 证书已安装并信任!"
else
    echo "❌ 下载失败,请检查网络或 URL"
    exit 1
fi

运行:curl -s http://your-intranet.local/ca/install-ca.sh | sudo bash

七、证书过期的解决方案

方案 1: 使用环境变量绕过 SSL 验证(临时解决方案)

  • 操作
    • 在执行 Git 操作之前设置环境变量 GIT_SSL_NO_VERIFY=1
    • 示例命令:GIT_SSL_NO_VERIFY=1 git pull origin main
  • 优点
    • 可以立即解决问题,无需修改系统或服务器配置。
  • 缺点
    • 安全性降低,因为这会忽略 SSL 证书的验证,建议仅在可信环境中使用。

方案 2: 使用 SSH 协议代替 HTTPS(推荐长期解决方案)

  • 步骤
    1. 生成 SSH 密钥对(如果还没有)。
    2. 将公钥添加到 GitLab 账户中。
    3. 修改本地仓库的远程 URL 为 SSH 地址。
  • 优点
    • 完全避开 HTTPS 证书问题,提升安全性。
    • 一旦配置完成,后续使用更加方便。
  • 适用场景
    • 对于开发人员来说是最理想的长期解决方案。

方案 3: 更新服务器上的 SSL 证书(根本解决方案)

  • 操作
    • 在服务器上生成新的 SSL 证书,并确保其正确配置和安装。
    • 重载 GitLab 配置使更改生效。
  • 优点
    • 解决了证书问题的根本原因,所有用户无需额外操作。
  • 缺点
    • 需要服务器管理员权限以及对服务器进行更改。
    • 如果不是自己管理服务器,则需要联系服务器管理员来执行此操作。

每种方案都有其适用场景和特点,选择最适合你当前情况的方法进行实施。对于大多数开发者而言,采用方案 2,即通过 SSH 进行连接,是既安全又高效的解决方案。


补充

证书配置完整指南

一、你的当前架构(确认)

  • GitLab 部署方式:Docker 容器(仅提供 HTTP,端口 8080)

  • HTTPS 实现方式:Nginx 反向代理(监听 443 端口)

  • 证书存储位置

    /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.pem ← 证书

复制代码
  /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.key   ← 私钥
  • Nginx 配置文件/etc/nginx/conf.d/gitlab2.conf
  • 问题 :证书已于 2024-11-20 过期,需更换。

二、证书类型与选择

类型 是否需要联网 浏览器信任 适用场景 生成方式
Let's Encrypt(公共 CA) ✅ 必须(至少一次) ✅ 自动信任 公网服务、对外访问 certbot
自签名证书 ❌ 完全不需要 ❌ 显示"不安全" 内网、测试、开发 openssl
mkcert(本地 CA) ⚠️ 首次安装需联网 ✅ 本地自动信任 内网开发/测试 mkcert

结论

  • 如果服务器有公网 IP + 域名可解析 → 用 Let's Encrypt
  • 如果纯内网、无外网 → 用 自签名证书mkcert

三、方案 A:使用 Let's Encrypt(推荐用于公网)

前提条件

  1. 域名 gitlab2.ctjt.cn 已在 DNS 服务商(如阿里云)配置 A 记录,指向服务器公网 IP;
  2. 服务器 80 端口对外开放(安全组 + 防火墙);
  3. 临时可停 Nginx(或改用 webroot 模式避免停机)。

操作步骤

复制代码
# 1. 停止 Nginx(standalone 模式需要独占 80 端口) 

sudo systemctl stop nginx 

# 2. 安装 certbot(若未安装) 

sudo apt update && sudo apt install certbot -y 

# 3. 申请证书 

sudo certbot certonly --standalone -d gitlab2.ctjt.cn 

# 按提示输入邮箱、同意条款 

# 4. 复制证书到 Nginx 目录 

sudo cp /etc/letsencrypt/live/gitlab2.ctjt.cn/fullchain.pem /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.pem 

sudo cp /etc/letsencrypt/live/gitlab2.ctjt.cn/privkey.pem /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.key 

# 5. 重载 Nginx 

sudo nginx -t && sudo systemctl reload nginx

自动续期(重要!)

复制代码
# 编辑定时任务 

sudo crontab -e

0 2 1 * * /usr/bin/certbot renew --quiet && /bin/systemctl reload nginx

🔔 注意:自动续期建议后续改用 --webroot--nginx 插件,避免停服务。


四、方案 B:自签名证书(适用于纯内网/离线环境)

特点

  • ✅ 完全离线生成
  • ❌ 浏览器会警告"证书不安全"
  • ✅ 适合内部系统、测试环境

生成命令(一行搞定)

复制代码
sudo openssl req -x509 -nodes -days 3650 \
  -newkey rsa:2048 \
  -keyout /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.key \
  -out /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.pem \
  -subj "/CN=gitlab2.ctjt.cn"

后续操作

复制代码
# 重载 Nginx 

sudo nginx -t && sudo systemctl reload nginx

(可选)手动信任证书(内网设备)

  • .pem 文件导入操作系统"受信任的根证书颁发机构";
  • 或使用 mkcert 替代(见下文)。

五、方案 C:使用 mkcert(内网开发最佳实践)

优势

  • 生成的证书在本地浏览器 自动显示为安全(无警告);
  • 支持多域名、localhost、IP 等。

使用前提

  • 需在 一台联网机器 上首次安装 mkcert 和根证书;
  • 之后可离线生成新证书。

安装与使用(在联网机操作)

复制代码
# 安装 mkcert 

sudo apt install mkcert -y # Ubuntu/Debian 

# 或 brew install mkcert # macOS 

# 安装本地 CA 到系统信任库 

mkcert -install 

# 生成证书 

mkcert gitlab2.ctjt.cn 

# 输出:gitlab2.ctjt.cn.pem 和 gitlab2.ctjt.cn-key.pem 

# 拷贝到离线服务器对应目录即可

六、如何检查证书是否过期?

查看本地 PEM 文件有效期

复制代码
openssl x509 -in /etc/nginx/conf.d/gitlab/gitlab2.ctjt.cn.pem -noout -dates

输出示例:

复制代码
notBefore=Nov 20 00:00:00 2023 GMT 

notAfter=Nov 20 23:59:59 2024 GMT  ← 过期时间

通过网络检查(需服务运行)

复制代码
echo | openssl s_client -connect gitlab2.ctjt.cn:443 2>/dev/null | openssl x509 -noout -dates

七、常见错误与排查

错误 原因 解决
NXDOMAIN 域名无 DNS 解析 在阿里云/腾讯云添加 A 记录
Could not bind to :80 80 端口被占用 systemctl stop nginx 或改用 --webroot
Certificate has expired 证书过期 按上述方案更新证书
浏览器仍报证书错误 Nginx 未重载 / 证书路径错误 检查 ssl_certificate 路径 + nginx -t

八、总结建议

场景 推荐方案
服务器有公网 IP,域名可解析 ✅ Let's Encrypt + 自动续期
纯内网,无外网,接受浏览器警告 ✅ 自签名证书(openssl
内网开发,希望无警告 mkcert(提前在联网机生成)
完全离线且需长期使用 ✅ 自签名证书 + 手动信任

💡 最后提醒

GitLab 容器本身 不需要配置证书 (因为你用的是 Nginx 反向代理)。

所有证书操作都在 Nginx 层面 完成,GitLab 保持 external_url 'http://...' 即可。

相关推荐
IsPrisoner3 小时前
从 Docker 到 Kubernetes:一次“工程视角”的 K8s 核心概念深度梳理
docker·容器·kubernetes
liuxuzxx3 小时前
containerd的CPU过高的问题排查
容器·性能优化·kubernetes
阿里云云原生3 小时前
加入我们,一起定义「Data x AI」的未来
云原生
看-清4 小时前
Docker离线安装部署xxl-job流程
运维·docker·容器
建群新人小猿4 小时前
陀螺匠企业助手-我的日程
android·大数据·运维·开发语言·容器
阿里云云原生4 小时前
告别数据库“膨胀”:Dify x SLS 构建高可用生产级 AI 架构
云原生
孤岛悬城4 小时前
47 Docker镜像编排
docker·容器·云计算
忙里偷闲学python5 小时前
ceph介绍和安装
linux·ceph·kubernetes
隔壁阿布都6 小时前
Docker 安装 MySQL 8.0
mysql·docker·容器