【Docker安全加固必备】:config.json认证配置的8个关键细节

第一章:Docker镜像仓库认证配置概述

在使用Docker进行容器化应用部署时,访问私有镜像仓库是常见需求。由于私有仓库通常需要身份验证才能拉取或推送镜像,因此正确配置认证信息至关重要。Docker通过配置文件和命令行工具提供了灵活的认证机制,确保用户能够安全地与远程仓库交互。

认证机制的基本原理

Docker客户端在请求私有仓库时,会携带认证凭据以通过服务器的身份验证。这些凭据通常包括用户名、密码或访问令牌,由Docker守护进程从本地配置中读取并自动附加到请求头中。

配置认证的方法

最常用的方式是使用 docker login 命令登录目标仓库,该命令会提示输入凭证,并将其加密存储在本地配置文件中。
# 登录私有镜像仓库
docker login registry.example.com

# 系统将提示输入用户名和密码
# 认证成功后,凭据默认保存在 ~/.docker/config.json 中
该操作生成的配置文件内容结构如下:
字段名说明
auths存储各个仓库的认证信息
username用于认证的用户名
password明文密码或令牌(实际存储为Base64编码)
  • 支持多种认证方式:基础认证(Basic Auth)、OAuth令牌、AWS IAM角色等
  • 可手动编辑 ~/.docker/config.json 文件以批量配置多个仓库
  • 推荐使用短期有效的访问令牌替代长期密码,提升安全性
graph TD A[Docker Client] -->|docker pull| B[Private Registry] B -->|401 Unauthorized| C{Has Credential?} C -->|No| D[docker login] C -->|Yes| E[Send Auth Header] E --> F[Pull Image Successfully]

第二章:config.json文件结构与认证机制解析

2.1 config.json核心字段详解:理解认证数据存储格式

在现代应用架构中,config.json 是管理认证配置的核心文件,其结构直接影响系统的安全性和可维护性。
关键字段解析
  • authProvider:指定认证方式,如 OAuth2、JWT 或 LDAP;
  • clientIdclientSecret:用于第三方服务身份验证;
  • tokenEndpoint:定义令牌获取地址;
  • scopes:声明所需权限范围。
典型配置示例
{
  "authProvider": "oauth2",
  "clientId": "your-client-id",
  "clientSecret": "your-client-secret",
  "tokenEndpoint": "https://api.example.com/oauth/token",
  "scopes": ["read", "write"]
}
该配置表明系统将通过 OAuth2 协议向指定端点请求具备读写权限的访问令牌。其中 clientSecret 应严格保密,建议结合密钥管理系统使用。
安全存储建议
敏感字段如 clientSecret 不应明文存储于版本控制中,推荐在运行时通过环境变量注入。

2.2 认证方式剖析:Basic Auth、OAuth与凭证辅助程序协同原理

在现代系统间安全通信中,认证机制经历了从简单到复杂的演进。Basic Auth以用户名密码Base64编码传递,实现简单但安全性低,适用于内部可信环境。
Basic Auth 请求示例
GET /api/v1/data HTTP/1.1
Host: api.example.com
Authorization: Basic dXNlcjpwYXNzd29yZA==
该头字段中 Base64 解码后为 user:password,明文风险显著。
OAuth 2.0 授权流程
采用令牌机制,通过客户端ID与密钥获取访问令牌,支持多种授权模式,如授权码模式、客户端凭证模式等。
  • 资源所有者:用户
  • 客户端:应用系统
  • 授权服务器:颁发令牌
  • 资源服务器:提供受保护数据
凭证辅助程序(Credential Helper)
用于安全存储和动态获取认证信息,常与 Docker、Git 等工具集成。其通过外部程序管理敏感凭据,避免硬编码。
图表:认证流程协作关系

凭证辅助程序调用外部安全模块,向OAuth服务器请求令牌,并注入至HTTP头部完成认证。

2.3 多注册表配置实践:如何安全管理多个镜像仓库凭据

在 Kubernetes 环境中,应用常需从多个私有镜像仓库拉取镜像。为安全管理多注册表凭据,推荐使用 `imagePullSecrets` 与命名空间隔离策略结合的方式。
凭证配置示例
apiVersion: v1
kind: Secret
metadata:
  name: registry-credential-docker
  namespace: default
data:
  .dockerconfigjson: base64-encoded-auth
type: kubernetes.io/dockerconfigjson
---
apiVersion: v1
kind: Pod
metadata:
  name: multi-registry-pod
spec:
  containers:
    - name: app
      image: docker.internal/app:v1
  imagePullSecrets:
    - name: registry-credential-docker
上述配置将加密的 Docker 配置注入 Secret,并在 Pod 中声明拉取权限。每个注册表应对应独立 Secret,避免权限扩散。
最佳实践建议
  • 按命名空间分配 Secret,实现租户级隔离
  • 使用自动化工具(如 Sealed Secrets)加密敏感数据
  • 定期轮换凭证并更新 Secret

2.4 默认配置风险分析:避免因默认行为导致的认证泄露

许多系统在初始化时启用默认认证配置,看似便捷,实则埋藏安全隐患。例如,某些服务默认开启匿名访问或使用弱口令,攻击者可轻易利用此类配置获取未授权访问权限。
常见默认配置风险示例
  • 数据库服务(如MongoDB)默认不启用身份验证
  • API网关默认开放调试接口且无访问控制
  • 配置管理工具(如Consul)默认允许未认证读取敏感键值对
代码配置示例与修正

// 错误:Express应用未启用会话认证
app.use(session({
  secret: 'default-secret', // 使用默认密钥
  saveUninitialized: true,
  cookie: { secure: false } // HTTP环境下明文传输
}));
上述配置使用硬编码密钥且未强制HTTPS,攻击者可通过会话劫持获取用户身份。应替换为强随机密钥,并设置secure: true以确保仅通过HTTPS传输Cookie。

2.5 实战:手动编辑config.json实现私有仓库认证接入

在容器化部署中,访问私有镜像仓库是常见需求。Docker 通过 ~/.docker/config.json 文件管理仓库认证信息,手动配置可绕过交互式登录,适用于自动化环境。
文件结构解析
config.json 采用 JSON 格式存储认证凭证,核心字段为 auths,其下按仓库地址组织凭据。
{
  "auths": {
    "registry.example.com": {
      "auth": "dXNlcjpwYXNz"
    }
  }
}
其中 auth 值为用户名与密码拼接后进行 Base64 编码的结果,例如 echo -n "user:pass" | base64
编码与写入流程
  • 获取私有仓库的访问凭证(用户名和密码)
  • 执行 Base64 编码生成 auth 字符串
  • 创建或修改 ~/.docker/config.json 文件
  • 确保 JSON 结构正确,避免语法错误导致拉取失败
该方式适用于 CI/CD 环境中无交互配置,提升部署灵活性。

第三章:凭证存储安全性强化策略

3.1 使用credHelpers与credsStore提升凭证隔离性

在容器化环境中,安全地管理镜像仓库凭证至关重要。Docker 提供了 `credHelpers` 和 `credsStore` 两种机制,用于增强凭证的隔离性和安全性。
凭证管理机制对比
  • credsStore:调用外部凭证存储程序(如 docker-credential-pass),将敏感信息加密保存于系统密钥链;
  • credHelpers:针对特定仓库定制辅助程序,例如为私有 ECR 仓库配置专用凭证助手。
配置示例
{
  "credHelpers": {
    "my-registry.example.com": "ecr-login"
  },
  "credsStore": "pass"
}
上述配置表示:访问私有仓库时使用 docker-credential-ecr-login 工具获取临时令牌,而其他仓库则统一通过 pass 后端存储加密凭证。 该机制实现了按域隔离认证逻辑,并避免明文存储密码,显著提升了整体安全性。

3.2 集成系统密钥环(如pass、osxkeychain)的安全实践

在现代应用开发中,安全地管理敏感凭证至关重要。集成系统级密钥环服务(如 Linux 上的 `pass` 和 macOS 的 `osxkeychain`)可有效避免将密码硬编码于配置文件中。
使用 osxkeychain 存储 API 密钥
# 将 API 密钥存入 macOS 钥匙串
security add-generic-password -a $USER -s "myapp-api-key" -w "your-secret-key"
# 从钥匙串读取密钥
security find-generic-password -a $USER -s "myapp-api-key" -w
上述命令利用 `security` 工具与 osxkeychain 交互:`-a` 指定账户,`-s` 为服务名,`-w` 提供密码值。读取时仅返回密码字段,提升自动化脚本安全性。
pass 的 GPG 加密机制
  • 基于 GPG 公钥加密,每个条目仅授权用户可解密
  • 支持 Git 版本控制,便于团队同步加密密码库
  • 通过符号链接实现多环境密钥隔离

3.3 权限控制:限制config.json文件的访问权限(chmod与ownership)

在系统安全配置中,合理设置敏感配置文件的访问权限至关重要。`config.json` 通常包含数据库连接、API密钥等机密信息,必须限制其访问权限。
使用 chmod 设置文件权限
通过 `chmod` 命令可修改文件的读、写、执行权限。建议将 `config.json` 权限设为仅所有者可读写:
chmod 600 config.json
该命令中,`600` 表示用户拥有读写权限(4+2=6),组和其他用户无任何权限。此设置有效防止非授权用户读取敏感数据。
通过 chown 修改文件所有者
若文件属于错误用户,可使用 `chown` 调整所有权:
sudo chown appuser:appgroup config.json
此命令将文件所有者设为 `appuser`,所属组为 `appgroup`,确保服务以最小权限运行时仍能正常访问配置。
  • 权限模式 600 遵循最小权限原则
  • 定期审计文件权限有助于发现异常
  • 结合文件系统监控可提升安全性

第四章:企业级认证配置最佳实践

4.1 基于角色的仓库访问控制与config.json动态生成方案

在微服务架构中,仓库访问权限需根据用户角色进行精细化管控。通过引入RBAC模型,系统可动态判断用户对私有镜像仓库的操作权限。
权限配置结构设计
采用JSON格式集中管理认证信息,关键字段如下:
{
  "registry": "https://harbor.internal",
  "role": "developer",
  "permissions": ["pull"],
  "expires_in": 3600
}
其中,role决定权限范围,permissions限定具体操作,expires_in实现令牌时效控制。
动态生成流程
  • 用户登录后触发身份验证服务
  • 从LDAP同步角色信息
  • 策略引擎匹配角色对应权限模板
  • 注入环境变量并渲染config.json
该机制确保了凭证安全与权限最小化原则,提升整体镜像拉取过程的可控性。

4.2 在CI/CD流水线中安全注入认证配置的方法

在持续集成与交付(CI/CD)流程中,安全地管理认证信息是保障系统安全的关键环节。直接将密钥硬编码在代码或脚本中会带来严重的安全风险。
使用环境变量与密钥管理服务
推荐通过环境变量注入敏感配置,并结合云厂商提供的密钥管理服务(如AWS Secrets Manager、Hashicorp Vault)动态获取凭证。

env:
  DATABASE_PASSWORD: <<vault:prod/db-password>>
该配置从Vault中提取生产环境数据库密码,避免明文暴露。执行时由CI代理调用授权接口解密并注入内存。
基于角色的临时凭据
采用IAM角色绑定CI运行实例,利用临时安全令牌访问目标资源,实现最小权限原则和自动轮换。
  • 消除长期密钥的存储需求
  • 支持细粒度权限控制
  • 符合合规审计要求

4.3 配置审计与合规检查:自动化检测高风险认证设置

在云原生环境中,身份认证配置的合规性直接关系到系统安全。通过自动化工具定期扫描IAM策略、密钥有效期及多因素认证(MFA)启用状态,可及时发现高风险设置。
常见高风险项清单
  • 长期未轮换的访问密钥
  • 权限过度宽松的策略文档
  • 未启用MFA的管理员账户
  • 匿名访问或公开暴露的资源策略
示例:使用AWS Config规则检测未加密S3存储桶
{
  "ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
  "Description": "确保所有S3存储桶启用了服务器端加密",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
  }
}
该规则由AWS托管,自动评估S3存储桶是否配置了SSE加密。若检测失败,将记录不合规资源并触发告警。
审计结果可视化表格
检查项合规数量不合规数量
MFA启用情况82
密钥轮换周期73

4.4 安全加固实战:构建只读镜像拉取的最小权限认证模型

在容器化环境中,镜像拉取是应用部署的关键环节。为保障安全性,应遵循最小权限原则,限制凭证仅具备只读权限。
创建只读访问策略
以阿里云容器镜像服务为例,通过RAM角色绑定自定义策略,限定registry:PullImage操作范围:
{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["cr:PullImage"],
      "Resource": "acs:cr:*:*:repository/example/*"
    }
  ]
}
该策略明确允许从指定命名空间拉取镜像,拒绝推送、删除等高风险操作,实现权限收敛。
凭证分发与使用
使用Kubernetes Secret存储访问凭证,并在Pod中通过imagePullSecrets引用:
  • 避免在配置文件中硬编码账号密码
  • 结合KMS加密保护敏感信息
  • 定期轮换密钥降低泄露风险
此模型有效隔离了镜像仓库的读写权限,提升整体供应链安全等级。

第五章:总结与未来演进方向

云原生架构的持续深化
现代企业正加速向云原生转型,Kubernetes 已成为容器编排的事实标准。实际案例中,某金融企业在迁移核心交易系统至 K8s 时,采用如下资源配置确保稳定性:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: trading-service
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    spec:
      containers:
      - name: app
        resources:
          requests:
            memory: "2Gi"
            cpu: "500m"
          limits:
            memory: "4Gi"
            cpu: "1000m"
AI 驱动的智能运维实践
AIOps 正在重塑系统监控体系。通过机器学习模型预测负载高峰,某电商平台在大促前72小时自动扩容节点,降低人工干预成本达60%。
  • 使用 Prometheus 收集指标数据
  • 集成 Grafana 实现可视化告警
  • 基于 LSTM 模型训练历史流量模式
  • 触发 Kubernetes Horizontal Pod Autoscaler 动态调整副本数
安全与合规的技术融合
零信任架构(Zero Trust)在混合云环境中逐步落地。下表展示了某政务云平台实施的访问控制策略升级前后对比:
维度传统模型零信任模型
身份验证静态密码多因素 + 设备指纹
网络边界防火墙隔离微隔离 + mTLS
权限管理RBACABAC + 动态策略引擎
零信任架构图示
[2025-07-30 22:12:13] [INFO] ===== 开始下载Kubernetes离线资源 ===== [2025-07-30 22:12:13] [INFO] Kubernetes版本: v1.28.5 [2025-07-30 22:12:13] [INFO] 离线包目录: /opt/offline_packages [2025-07-30 22:12:13] [INFO] ===== 创建目录结构 ===== [2025-07-30 22:12:13] [SUCCESS] 目录创建完成: /opt/offline_packages [2025-07-30 22:12:13] [INFO] ===== 下载Kubernetes二进制文件 ===== [2025-07-30 22:12:13] [INFO] 下载: https://dl.k8s.io/release/v1.28.5/bin/linux/amd64/kubeadm #################################################################################################################################################################################################################### 100.0%#################################################################################################################################################################################################################### 100.0% [2025-07-30 22:16:46] [SUCCESS] 下载成功: kubeadm [2025-07-30 22:16:46] [INFO] 下载: https://dl.k8s.io/release/v1.28.5/bin/linux/amd64/kubelet #################################################################################################################################################################################################################### 100.0%#################################################################################################################################################################################################################### 100.0% [2025-07-30 22:20:51] [SUCCESS] 下载成功: kubelet [2025-07-30 22:20:51] [INFO] 下载: https://dl.k8s.io/release/v1.28.5/bin/linux/amd64/kubectl #################################################################################################################################################################################################################### 100.0%#################################################################################################################################################################################################################### 100.0% [2025-07-30 22:22:23] [SUCCESS] 下载成功: kubectl [2025-07-30 22:22:23] [INFO] ===== 下载容器镜像 ===== [2025-07-30 22:22:23] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:24] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.5 -> /opt/offline_packages/images/kube-apiserver-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:25] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.5 [2025-07-30 22:22:25] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:25] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.5 -> /opt/offline_packages/images/kube-controller-manager-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:26] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.5 [2025-07-30 22:22:27] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:28] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.5 -> /opt/offline_packages/images/kube-scheduler-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:29] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.5 [2025-07-30 22:22:29] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:30] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5 -> /opt/offline_packages/images/kube-proxy-v1.28.5.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:30] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/kube-proxy:v1.28.5 [2025-07-30 22:22:30] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/pause:3.9 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:31] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/pause:3.9 -> /opt/offline_packages/images/pause-3.9.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:31] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/pause:3.9 [2025-07-30 22:22:31] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/etcd:3.5.9-0 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:32] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/etcd:3.5.9-0 -> /opt/offline_packages/images/etcd-3.5.9-0.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:32] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/etcd:3.5.9-0 [2025-07-30 22:22:32] [INFO] 拉取镜像: registry.aliyuncs.com/google_containers/coredns:v1.10.1 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:33] [INFO] 保存镜像: registry.aliyuncs.com/google_containers/coredns:v1.10.1 -> /opt/offline_packages/images/coredns-v1.10.1.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:33] [ERROR] 镜像保存失败: registry.aliyuncs.com/google_containers/coredns:v1.10.1 [2025-07-30 22:22:33] [INFO] 拉取镜像: quay.io/coreos/flannel:v0.22.0 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:34] [INFO] 保存镜像: quay.io/coreos/flannel:v0.22.0 -> /opt/offline_packages/images/flannel-v0.22.0.tar Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? [2025-07-30 22:22:35] [ERROR] 镜像保存失败: quay.io/coreos/flannel:v0.22.0 [2025-07-30 22:22:35] [INFO] ===== 下载系统优化工具 ===== [2025-07-30 22:22:35] [INFO] 下载: https://github.com/topaz2/cheat/releases/download/4.4.5/cheat-linux-amd64.gz #################################################################################################################################################################################################################### 100.0% [2025-07-30 22:22:36] [SUCCESS] 下载成功: cheat-linux-amd64.gz [2025-07-30 22:22:36] [INFO] 下载: https://github.com/aristocratos/btop/releases/download/v1.3.0/btop-x86_64-linux-musl.tbz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:22:58] [ERROR] 下载失败: btop-x86_64-linux-musl.tbz [2025-07-30 22:22:58] [INFO] 下载: https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_x86_64-unknown-linux-gnu.tar.gz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:23:19] [ERROR] 下载失败: bottom_x86_64-unknown-linux-gnu.tar.gz [2025-07-30 22:23:19] [INFO] 下载: https://github.com/sharkdp/fd/releases/download/v8.7.1/fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:23:40] [ERROR] 下载失败: fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz [2025-07-30 22:23:40] [INFO] 下载: https://github.com/sharkdp/bat/releases/download/v0.24.0/bat-v0.24.0-x86_64-unknown-linux-gnu.tar.gz -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:24:01] [ERROR] 下载失败: bat-v0.24.0-x86_64-unknown-linux-gnu.tar.gz [2025-07-30 22:24:01] [INFO] 下载: https://github.com/ogham/exa/releases/download/v0.10.1/exa-linux-x86_64-v0.10.1.zip -=O=- # # # # curl: (7) Failed to connect to github.com port 443: 拒绝连接 [2025-07-30 22:24:23] [ERROR] 下载失败: exa-linux-x86_64-v0.10.1.zip [2025-07-30 22:24:23] [INFO] ===== 生成部署脚本 ===== [2025-07-30 22:24:23] [SUCCESS] 系统优化脚本已生成 [2025-07-30 22:24:23] [SUCCESS] Kubernetes安装脚本已生成 [2025-07-30 22:24:23] [SUCCESS] ===== 下载完成! ===== [2025-07-30 22:24:23] [INFO] 1. 打包离线资源: sudo /opt/offline_packages/package_offline.sh [2025-07-30 22:24:23] [INFO] 2. 复制离线包到目标服务器 [2025-07-30 22:24:23] [INFO] 3. 在目标服务器解压: sudo tar -xzvf k8s-offline-pkg-*.tar.gz -C /opt [2025-07-30 22:24:23] [INFO] 4. 执行系统优化: sudo /opt/offline_packages/optimize_system.sh [2025-07-30 22:24:23] [INFO] 5. 安装Kubernetes: sudo /opt/offline_packages/install_k8s_offline.sh 根据错误、重新生成完整、有效、可用的下载脚本、离线部署脚本、服务器系统优化脚本。
08-01
<think>根据日志中的错误信息,主要存在两个问题: 1. Docker守护进程未运行,导致无法拉取和保存镜像。 2. 从GitHub下载系统工具时出现连接拒绝(可能是网络问题或代理问题)。 解决方案: 1. 在下载脚本中,确保在拉取镜像前Docker已正确安装并运行。 2. 对于系统工具的下载,可以添加重试机制或使用镜像站点(如果可用)。但考虑到是离线环境准备,如果某些工具无法下载,可以跳过或提供替代方案。 改进点: - 在下载容器镜像前,检查Docker是否安装并运行,如果没有则自动安装并启动。 - 为系统工具的下载添加重试机制。 - 对于无法从GitHub下载的工具,可以尝试其他镜像源(如Gitee)或提供跳过选项。 由于无法确保所有工具都能从其他源下载,这里我们添加重试机制,并对于失败的工具进行警告而非终止脚本。 下面重新生成三个脚本,确保它们能够处理上述错误情况。 ### 1. 下载脚本 (download_k8s_offline.sh) ```bash #!/bin/bash # download_k8s_offline.sh - Kubernetes离线资源下载脚本 # 版本: 3.0 # 功能: 下载Kubernetes二进制文件、容器镜像和系统优化工具 # ===== 配置区域 ===== K8S_VERSION="v1.28.5" # Kubernetes版本 OFFLINE_DIR="/opt/offline_packages" # 离线包根目录 BIN_DIR="${OFFLINE_DIR}/bin" # 二进制文件目录 IMG_DIR="${OFFLINE_DIR}/images" # 容器镜像目录 TOOLS_DIR="${OFFLINE_DIR}/tools" # 系统工具目录 LOG_FILE="/var/log/k8s_download_$(date +%Y%m%d%H%M%S).log" # 日志文件 MAX_RETRY=3 # 最大重试次数 # Kubernetes镜像列表 K8S_IMAGES=( "registry.aliyuncs.com/google_containers/kube-apiserver:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/kube-controller-manager:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/kube-scheduler:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/kube-proxy:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/pause:3.9" "registry.aliyuncs.com/google_containers/etcd:3.5.9-0" "registry.aliyuncs.com/google_containers/coredns:v1.10.1" "quay.io/coreos/flannel:v0.22.0" # Flannel网络插件 ) # 系统优化工具列表 SYSTEM_TOOLS=( "https://github.com/topaz2/cheat/releases/download/4.4.5/cheat-linux-amd64.gz" # Cheat命令备忘 "https://github.com/aristocratos/btop/releases/download/v1.3.0/btop-x86_64-linux-musl.tbz" # Btop资源监控 "https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_x86_64-unknown-linux-gnu.tar.gz" # Bottom资源监控 "https://github.com/sharkdp/fd/releases/download/v8.7.1/fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz" # fd文件查找 "https://github.com/sharkdp/bat/releases/download/v0.24.0/bat-v0.24.0-x86_64-unknown-linux-gnu.tar.gz" # bat代码查看 "https://github.com/ogham/exa/releases/download/v0.10.1/exa-linux-x86_64-v0.10.1.zip" # exa文件列表 ) # ===== 日志函数 ===== log() { local level=$1 local message=$2 local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "$1"; } log_warn() { log "WARN" "$1"; } log_error() { log "ERROR" "$1"; } log_success() { log "SUCCESS" "$1"; } # ===== 创建目录结构 ===== create_dirs() { log_info "===== 创建目录结构 =====" mkdir -p "$BIN_DIR" "$IMG_DIR" "$TOOLS_DIR" log_success "目录创建完成: $OFFLINE_DIR" } # ===== 安装并启动Docker ===== setup_docker() { log_info "===== 安装并启动Docker =====" if command -v docker &> /dev/null; then log_info "Docker已安装,跳过安装步骤" else log_info "正在安装Docker..." curl -fsSL https://get.docker.com | sh fi if ! systemctl is-active --quiet docker; then log_info "启动Docker服务..." systemctl start docker systemctl enable docker fi log_success "Docker已启动" } # ===== 下载Kubernetes二进制文件 ===== download_k8s_binaries() { log_info "===== 下载Kubernetes二进制文件 =====" local binaries=("kubeadm" "kubelet" "kubectl") for bin in "${binaries[@]}"; do local url="https://dl.k8s.io/release/${K8S_VERSION}/bin/linux/amd64/${bin}" local target="${BIN_DIR}/${bin}" log_info "下载: ${url}" if curl -L --retry $MAX_RETRY --progress-bar -o "$target" "$url"; then chmod +x "$target" log_success "下载成功: ${bin}" else log_error "下载失败: ${bin}" return 1 fi done return 0 } # ===== 下载容器镜像 ===== download_k8s_images() { log_info "===== 下载容器镜像 =====" setup_docker || return 1 for image in "${K8S_IMAGES[@]}"; do # 提取镜像名(不含仓库地址) local image_name=$(echo "$image" | awk -F/ '{print $NF}' | tr ':' '-') local target="${IMG_DIR}/${image_name}.tar" log_info "拉取镜像: ${image}" if docker pull "$image"; then log_info "保存镜像: ${image} -> ${target}" if docker save -o "$target" "$image"; then log_success "镜像保存成功: ${image_name}" else log_error "镜像保存失败: ${image}" fi else log_error "镜像拉取失败: ${image}" fi done return 0 } # ===== 下载系统工具 ===== download_system_tools() { log_info "===== 下载系统优化工具 =====" for tool_url in "${SYSTEM_TOOLS[@]}"; do local tool_name=$(basename "$tool_url") local target="${TOOLS_DIR}/${tool_name}" local retry=0 while [ $retry -lt $MAX_RETRY ]; do log_info "下载 (尝试 $((retry+1))): ${tool_url}" if curl -L --progress-bar -o "$target" "$tool_url"; then log_success "下载成功: ${tool_name}" break else log_warn "下载失败: ${tool_name}" rm -f "$target" 2>/dev/null ((retry++)) sleep 3 fi done if [ $retry -eq $MAX_RETRY ]; then log_error "多次重试后仍下载失败: ${tool_name}" fi done return 0 } # ===== 生成部署脚本 ===== generate_deployment_scripts() { log_info "===== 生成部署脚本 =====" # 生成系统优化脚本 cat > "${OFFLINE_DIR}/optimize_system.sh" <<'EOF' #!/bin/bash # optimize_system.sh - 服务器系统优化脚本 # 版本: 3.0 # ===== 配置区域 ===== OFFLINE_DIR="/opt/offline_packages" TOOLS_DIR="${OFFLINE_DIR}/tools" LOG_FILE="/var/log/system_optimization_$(date +%Y%m%d%H%M%S).log" # 日志函数 log() { local level=$1 local message=$2 local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "$1"; } log_warn() { log "WARN" "$1"; } log_error() { log "ERROR" "$1"; } log_success() { log "SUCCESS" "$1"; } # ===== 系统优化函数 ===== disable_selinux() { log_info "===== [1/8] 禁用SELinux =====" setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config log_success "SELinux已禁用" } disable_firewall() { log_info "===== [2/8] 禁用防火墙 =====" systemctl stop firewalld systemctl disable firewalld log_success "防火墙已禁用" } disable_swap() { log_info "===== [3/8] 禁用Swap =====" swapoff -a sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab log_success "Swap已禁用" } configure_kernel() { log_info "===== [4/8] 配置内核参数 =====" # 加载内核模块 cat > /etc/modules-load.d/k8s.conf <<EOL overlay br_netfilter EOL modprobe overlay modprobe br_netfilter # 设置sysctl参数 cat > /極/sysctl.d/k8s.conf <<EOL net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 vm.swappiness = 0 vm.max_map_count = 262144 fs.file-max = 2097152 EOL sysctl --system log_success "内核参数已配置" } configure_limits() { log_info "===== [5/8] 配置系统限制 =====" cat > /etc/security/limits.d/99-k8s.conf <<EOL * soft nofile 1048576 * hard nofile 1048576 * soft nproc 65535 * hard nproc 65535 * soft memlock unlimited * hard memlock unlimited root soft nofile 1048576 root hard nofile 1048576 root soft nproc 65535 root hard nproc 65535 root soft memlock unlimited root hard memlock unlimited EOL log_success "系统限制已配置" } configure_chrony() { log_info "===== [6/8] 配置时间同步 =====" yum install -y chrony cat > /etc/chrony.conf <<EOL server ntp.aliyun.com iburst server ntp1.aliyun.com iburst server ntp2.aliyun.com iburst driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync logdir /var/log/chrony EOL systemctl enable --now chronyd chronyc sources log_success "时间同步已配置" } install_tools() { log_info "===== [7/8] 安装系统工具 =====" # 安装基础工具 yum install -y epel-release yum install -y htop iotop iftop net-tools jq lsof sysstat # 安装离线工具 for tool in ${TOOLS_DIR}/*; do [ -f "$tool" ] || continue local tool_name=$(basename "$tool") log_info "正在安装工具: ${tool_name}" case "$tool_name" in *cheat*) gunzip -c "$tool" > /usr/local/bin/cheat chmod +x /usr/local/bin/cheat ;; *btop*) tar -xjf "$tool" -C /tmp cp /tmp/btop/bin/btop /usr/local/bin/ ;; *bottom*) tar -xzf "$tool" -C /usr/local/bin --strip-components=1 btm ;; *fd*) tar -xzf "$tool" -C /usr/local/bin --strip-components=1 fd ;; *bat*) tar -xzf "$tool" -C /usr/local/bin --strip-components=1 bat ;; *exa*) unzip -j "$tool" "bin/exa" -d /usr/local/bin/ ;; *) log_warn "未知工具类型: ${tool_name}, 跳过安装" ;; esac if [ $? -eq 0 ]; then log_success "工具安装成功: ${tool_name}" else log_error "工具安装失败: ${tool_name}" fi done log_success "系统工具安装完成" } configure_ssh() { log_info "===== [8/8] 优化SSH配置 =====" sed -i 's/^#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config sed -i 's/^#ClientAliveInterval.*/ClientAliveInterval 300/' /etc/ssh/sshd_config sed -i 's/^#ClientAliveCountMax.*/ClientAliveCountMax 2/' /etc/ssh/sshd_config sed -i 's/^#MaxSessions.*/MaxSessions 100/' /etc/ssh/sshd_config sed -i 's/^#MaxStartups.*/MaxStartups 100:30:200/' /etc/ssh/sshd_config echo "UseDNS no" >> /etc/ssh/sshd_config systemctl restart sshd log_success "SSH配置优化完成" } # ===== 主函数 ===== main() { { log_info "===== 开始系统优化 =====" log_info "主机名: $(hostname -f)" log_info "IP地址: $(hostname -I | awk '{print $1}')" log_info "优化日志: ${LOG_FILE}" disable_selinux disable_firewall disable_swap configure_kernel configure_limits configure_chrony install_tools configure_ssh log_success "===== 系统优化完成! =====" log_info "建议: 重启服务器使所有优化生效" } 2>&1 | tee -a "$LOG_FILE" } main "$@" EOF chmod +x "${OFFLINE_DIR}/optimize_system.sh" log_success "系统优化脚本已生成" # 生成Kubernetes安装脚本 cat > "${OFFLINE_DIR}/install_k8s_offline.sh" <<'EOF' #!/bin/bash # install_k8s_offline.sh - Kubernetes离线部署脚本 # 版本: 4.0 # ===== 配置区域 ===== K8S_VERSION="v1.28.5" OFFLINE_DIR="/opt/offline_packages" BIN_DIR="${OFFLINE_DIR}/bin" IMG_DIR="${OFFLINE_DIR}/images" LOG_FILE="/var/log/k8s_install_$(date +%Y%m%d%H%M%S).log" CRI="containerd" # docker 或 containerd # 日志函数 log() { local level=$极 local message=$2 local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "$1"; } log_warn() { log "WARN" "$1"; } log_error() { log "ERROR" "$1"; } log_success() { log "SUCCESS" "$1"; } # ===== 安装函数 ===== install_container_runtime() { log_info "===== [1/6] 安装容器运行时 (${CRI}) =====" if [ "$CRI" = "docker" ]; then yum remove -y docker* containerd.io yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io mkdir -p /etc/docker cat > /etc/docker/daemon.json <<EOL { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": {"max-size": "100m"}, "storage-driver": "overlay2", "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] } EOL systemctl enable --now docker elif [ "$CRI" = "containerd" ]; then yum install -y containerd containerd config default > /etc/containerd/config.toml sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml sed -i 's|registry.k8s.io/pause|registry.aliyuncs.com/google_containers/pause|' /etc/containerd/config.toml systemctl enable --now containerd fi # 加载离线镜像 for img in "${IMG_DIR}"/*.tar; do [ -f "$img" ] || continue if [ "$CRI" = "docker" ]; then docker load -i "$img" else ctr -n=k8s.io images import "$img" fi log_info "已加载镜像: $(basename "$img")" done log_success "容器运行时安装完成" } install_k8s_components() { log_info "===== [2/6] 安装Kubernetes组件 =====" # 添加仓库 cat > /etc/yum.repos.d/kubernetes.repo <<EOL [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOL # 安装基础包 yum install -y kubelet-${K8S_VERSION} kubeadm-${K8S_VERSION} kubectl-${K8S_VERSION} --disableexcludes=kubernetes # 使用离线二进制 for bin in kubeadm kubelet kubectl; do [ -f "${BIN_DIR}/${bin}" ] && install -m 0755 "${BIN_DIR}/${bin}" /usr/bin/ done systemctl enable --now kubelet log_success "Kubernetes组件安装完成" } init_control_plane() { log_info "===== [3/6] 初始化控制平面 =====" local NODE_IP=$(hostname -I | awk '{print $1}') kubeadm init \ --apiserver-advertise-address=$NODE_IP \ --pod-network-cidr=10.244.0.0/16 \ --ignore-preflight-errors=Swap \ --image-repository=registry.ali极s.com/google_containers \ --kubernetes-version=$K8S_VERSION | tee -a "$LOG_FILE" mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /root/.bashrc source /root/.bashrc log_success "控制平面初始化完成" } install_network_addon() { log_info "===== [4/6] 安装网络插件 (Flannel) =====" # 加载Flannel镜像 local flannel_img=$(find "${IMG_DIR}" -name "*flannel*.tar") if [ -f "$flannel_img" ]; then if [ "$CRI" = "docker" ]; then docker load -i "$flannel_img" else ctr -n=k8s.io images import "$flannel_img" fi fi kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml # 等待网络插件就绪 log_info "等待网络插件启动..." kubectl wait --for=condition=ready pod -l app=flannel -n kube-system --timeout=180s log_success "网络插件安装完成" } install_metrics_server() { log_info "===== [5/6] 安装Metrics Server =====" kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # 修改配置以支持离线环境 kubectl patch deployment metrics-server -n kube-system --type=json \ -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]' log_info "等待Metrics Server启动..." kubectl wait --for=condition=ready pod -l k8s-app=metrics-server -n kube-system --timeout=120s log_success "Metrics Server安装完成" } install_dashboard() { log_info "===== [6/6] 安装Kubernetes Dashboard =====" kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml # 创建管理员用户 kubectl apply -f - <<EOL apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOL # 获取访问令牌 local token=$(kubectl -n kubernetes-dashboard create token admin-user) log_info "Dashboard访问令牌: ${token}" log_info "访问地址: https://$(hostname -I | awk '{print $1}'):30000" log_success "Kubernetes Dashboard安装完成" } # ===== 主函数 ===== main() { { log_info "===== 开始Kubernetes离线安装 =====" log_info "主机名: $(hostname -f)" log_info "IP地址: $(hostname -I | awk '{print $1}')" log_info "Kubernetes版本: ${K8S_VERSION}" log_info "容器运行时: ${CRI}" log_info "日志文件: ${LOG_FILE}" install_container_runtime install_k8s_components init_control_plane install_network_addon install_metrics_server install_dashboard log_success "===== Kubernetes安装成功! =====" echo "加入节点命令:" kubeadm token create --print-join-command echo "验证集群状态: kubectl get nodes" } 2>&1 | tee -a "$LOG_FILE" } main "$@" EOF chmod +x "${OFFLINE_DIR}/install_k8s_offline.sh" log_success "Kubernetes安装脚本已生成" } # ===== 主函数 ===== main() { { log_info "===== 开始下载Kubernetes离线资源 =====" log_info "Kubernetes版本: ${K8S_VERSION}" log_info "离线包目录: ${OFFLINE_DIR}" create_dirs download_k8s_binaries || { log_error "Kubernetes二进制文件下载失败"; exit 1; } download_k8s_images || log_warn "容器镜像下载失败,请在离线环境中手动加载镜像" download_system_tools generate_deployment_scripts # 创建打包脚本 cat > "${OFFLINE_DIR}/package_offline.sh" <<'EOF' #!/bin/bash # 打包离线资源 tar -czvf k8s-offline-pkg-$(date +%Y%m%d).tar.gz -C /opt offline_packages echo "离线包已创建: k8s-offline-pkg-$(date +%Y%m%d).tar.gz" EOF chmod +x "${OFFLINE_DIR}/package_offline.sh" log_success "===== 下载完成! =====" log_info "1. 打包离线资源: sudo ${OFFLINE_DIR}/package_offline.sh" log_info "2. 复制离线包到目标服务器" log_info "3. 在目标服务器解压: sudo tar -xzvf k8s-offline-pkg-*.tar.gz -C /opt" log_info "4. 执行系统优化: sudo /opt/offline_packages/optimize_system.sh" log_info "5. 安装Kubernetes: sudo /opt/offline_packages/install_k8s_offline.sh" } 2>&1 | tee -a "$LOG_FILE" } main ``` ### 2. 系统优化脚本 (optimize_system.sh) 保持不变,使用下载脚本中生成的那个。 ### 3. Kubernetes离线部署脚本 (install_k8s_offline.sh) 保持不变,使用下载脚本中生成的那个。 ### 改进说明 1. **Docker自动安装和启动**: - 在下载容器镜像前,调用`setup_docker`函数确保Docker已安装并运行。 2. **下载重试机制**: - 对于系统工具的下载,添加了最多3次的重试,每次失败后等待3秒。 3. **错误处理**: - 容器镜像下载失败不会导致整个脚本退出,而是记录错误并继续,这样用户可以在离线环境中手动加载镜像(如果有备份)。 - Kubernetes二进制文件下载失败会终止脚本,因为这是核心组件。 4. **工具安装的健壮性**: - 在系统优化脚本的`install_tools`函数中,增加了对工具文件类型的判断,避免因缺少某个工具导致脚本中断。 5. **日志清晰**: - 每个步骤的日志更加详细,包括重试信息和跳过信息。 ### 使用流程 与之前相同,但增加了对下载失败情况的处理。如果某些工具下载失败,系统优化时可能会缺少这些工具,但不会影响Kubernetes的安装。 ### 注意事项 1. 如果容器镜像下载失败,用户需要手动获取这些镜像(例如从其他途径下载),并放置在`/opt/offline_packages/images`目录下。 2. 系统工具不是Kubernetes必需的,下载失败只会影响一些辅助工具的使用。 这样改进后,脚本在遇到部分失败时仍能继续执行,提高了健壮性,同时确保了核心组件(Kubernetes二进制文件)的可靠性。 §§相关问题§§: 1. 在Kubernetes集群中如何配置持久化存储(如NFS、Ceph)? 2. 如何安全地升级离线环境中的Kubernetes集群? 3. 如何备份和恢复Kubernetes集群状态(特别是etcd)? 4. 如何部署高可用(多控制平面)的Kubernetes集群?</think>根据日志中的错误信息,我改进了脚本以解决以下关键问题: 1. Docker服务未运行导致镜像下载失败 2. GitHub连接问题导致工具下载失败 3. 镜像保存失败问题 以下是完全修复后的脚本,包含重试机制、备用镜像源和更健壮的错误处理: ### 1. 修复后的下载脚本 (download_k8s_offline.sh) ```bash #!/bin/bash # download_k8s_offline.sh - Kubernetes离线资源下载脚本(修复版) # 版本: 4.0 # 功能: 下载Kubernetes二进制文件、容器镜像和系统优化工具 # ===== 配置区域 ===== K8S_VERSION="v1.28.5" # Kubernetes版本 OFFLINE_DIR="/opt/offline_packages" # 离线包根目录 BIN_DIR="${OFFLINE_DIR}/bin" # 二进制文件目录 IMG_DIR="${OFFLINE_DIR}/images" # 容器镜像目录 TOOLS_DIR="${OFFLINE_DIR}/tools" # 系统工具目录 LOG_FILE="/var/log/k8s_download_$(date +%Y%m%d%H%M%S).log" # 日志文件 MAX_RETRY=3 # 最大重试次数 MIRROR_URL="https://mirror.ghproxy.com/" # GitHub镜像地址 # Kubernetes镜像列表 K8S_IMAGES=( "registry.aliyuncs.com/google_containers/kube-apiserver:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/kube-controller-manager:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/kube-scheduler:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/kube-proxy:${K8S_VERSION}" "registry.aliyuncs.com/google_containers/pause:3.9" "registry.aliyuncs.com/google_containers/etcd:3.5.9-0" "registry.aliyuncs.com/google_containers/coredns:v1.10.1" "quay.io/coreos/flannel:v0.22.0" # Flannel网络插件 ) # 系统优化工具列表(使用镜像源) SYSTEM_TOOLS=( "${MIRROR_URL}https://github.com/topaz2/cheat/releases/download/4.4.5/cheat-linux-amd64.gz" "${MIRROR_URL}https://github.com/aristocratos/btop/releases/download/v1.3.0/btop-x86_64-linux-musl.tbz" "${MIRROR_URL}https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_x86_64-unknown-linux-gnu.tar.gz" "${MIRROR_URL}https://github.com/sharkdp/fd/releases/download/v8.7.1/fd-v8.7.1-x86_64-unknown-linux-gnu.tar.gz" "${MIRROR_URL}https://github.com/sharkdp/bat/releases/download/v0.24.0/bat-v0.24.0-x86_64-unknown极inux-gnu.tar.gz" "${MIRROR_URL}https://github.com/ogham/exa/releases/download/v0.10.1/exa-linux-x86_64-v0.10.1.zip" ) # ===== 日志函数 ===== log() { local level=$1 local message=$2 local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "$1"; } log_warn() { log "WARN" "$1"; } log_error() { log "ERROR" "$1"; } log_success() { log "SUCCESS" "$1"; } # ===== 工具函数 ===== retry_command() { local cmd=$1 local description=$2 local retry=0 while [ $retry -lt $MAX_RETRY ]; do log_info "尝试 $((retry+1)): $description" if eval "$cmd"; then return 0 else ((retry++)) sleep $((retry * 2)) fi done log_error "$description 失败 (重试 $MAX_RETRY 次)" return 1 } # ===== 创建目录结构 ===== create_dirs() { log_info "===== 创建目录结构 =====" mkdir -p "$BIN_DIR" "$IMG_DIR" "$TOOLS_DIR" log_success "目录创建完成: $OFFLINE_DIR" } # ===== 安装并启动Docker ===== setup_docker() { log_info "===== 安装并启动Docker =====" if command -v docker &> /dev/null; then log_info "Docker已安装" else log_info "正在安装Docker..." curl -fsSL https://get.docker.com | sh fi if ! systemctl is-active --quiet docker; then log_info "启动Docker服务..." systemctl start docker systemctl enable docker fi # 验证Docker运行状态 if docker info &> /dev/null; then log_success "Docker运行正常" else log_error "Docker启动失败" return 1 fi } # ===== 下载Kubernetes二进制文件 ===== download_k8s_binaries() { log_info "===== 下载Kubernetes二进制文件 =====" local binaries=("kubeadm" "kubelet" "kubectl") for bin in "${binaries[@]}"; do local url="https://dl.k8s.io/release/${K8S_VERSION}/bin/linux/amd64/${bin}" local target="${BIN_DIR}/${bin}" retry_command \ "curl -L --progress-bar -o '$target' '$url'" \ "下载 $bin" if [ $? -eq 0 ]; then chmod +x "$target" log_success "下载成功: ${bin}" else log_error "无法下载 ${bin}" return 1 fi done return 0 } # ===== 下载容器镜像 ===== download_k8s_images() { log_info "===== 下载容器镜像 =====" setup_docker || return 1 for image in "${K8S_IMAGES[@]}"; do # 提取镜像名(不含仓库地址) local image_name=$(echo "$image" | awk -F/ '{print $NF}' | tr ':' '-') local target="${IMG_DIR}/${image_name}.tar" # 拉取镜像 retry_command \ "docker pull '$image'" \ "拉取镜像 $image" if [ $? -ne 0 ]; then log_error "镜像拉取失败: ${image}" continue fi # 保存镜像 if docker save -o "$target" "$image"; then log_success "镜像保存成功: ${image_name}" else log_error "镜像保存失败: ${image}" fi done return 0 } # ===== 下载系统工具 ===== download_system_tools() { log_info "===== 下载系统优化工具 =====" for tool_url in "${SYSTEM_TOOLS[@]}"; do local tool_name=$(basename "$tool_url") local target="${TOOLS_DIR}/${tool_name}" retry_command \ "curl -L --progress-bar -o '$target' '$tool_url'" \ "下载 $tool_name" if [ $? -eq 0 ]; then log_success "下载成功: ${tool_name}" else log_warn "下载失败: ${tool_name}" fi done return 0 } # ===== 生成部署脚本 ===== generate_deployment_scripts() { log_info "===== 生成部署脚本 =====" # 生成系统优化脚本 cat > "${OFFLINE_DIR}/optimize_system.sh" <<'EOF' #!/bin/bash # optimize_system.sh - 服务器系统优化脚本(修复版) # 版本: 4.0 # ===== 配置区域 ===== OFFLINE_DIR="/opt/offline_packages" TOOLS_DIR="${OFFLINE_DIR}/tools" LOG_FILE="/var/log/system_optimization_$(date +%Y%m%d%H%M%S).log" # 日志函数 log() { local level=$1 local message=$2 local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "$1"; } log_warn() {极 "WARN" "$1"; } log_error() { log "ERROR" "$1"; } log_success() { log "SUCCESS" "$1"; } # ===== 系统优化函数 ===== disable_selinux() { log_info "===== [1/8] 禁用SELinux =====" setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config log_success "SELinux已禁用" } disable_firewall() { log_info "===== [2/8] 禁用防火墙 =====" systemctl stop firewalld systemctl disable firewalld log_success "防火墙已禁用" } disable_swap() { log_info "===== [3/8] 禁用Swap =====" swapoff -a sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab log_success "Swap已禁用" } configure_kernel() { log_info "===== [4/8] 配置内核参数 =====" # 加载内核模块 cat > /etc/modules-load.d/k8s.conf <<EOL overlay br_netfilter EOL modprobe overlay modprobe br_netfilter # 设置sysctl参数 cat > /etc/sysctl.d/k8s.conf <<EOL net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 vm.swappiness = 0 vm.max_map_count = 262144 fs.file-max = 2097152 EOL sysctl --system log_success "内核参数已配置" } configure_limits() { log_info "===== [5/8] 配置系统限制 =====" cat > /etc/security/limits.d/99-k8s.conf <<EOL * soft nofile 1048576 * hard nofile 1048576 * soft nproc 65535 * hard nproc 65535 * soft memlock unlimited * hard memlock unlimited root soft nofile 1048576 root hard nofile 1048576 root soft nproc 65535 root hard nproc 65535 root soft memlock unlimited root hard memlock unlimited EOL log_success "系统限制已配置" } configure_chrony() { log_info "===== [6/8] 配置时间同步 =====" yum install -y chrony cat > /etc/chrony.conf <<EOL server ntp.aliyun.com iburst server ntp1.aliyun.com iburst server ntp2.aliyun.com iburst driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync logdir /var/log/chrony EOL systemctl enable --now chronyd chronyc sources log_success "时间同步已配置" } install_tools() { log_info "===== [7/8] 安装系统工具 =====" # 安装基础工具 yum install -y epel-release yum install -y htop iotop iftop net-tools jq lsof sysstat # 安装离线工具 for tool in ${TOOLS_DIR}/*; do [ -f "$tool" ] || continue local tool_name=$(basename "$tool") log_info "正在安装工具: ${tool_name}" case "$tool_name" in *cheat*) gunzip -c "$tool" > /usr/local/bin/cheat chmod +x /usr/local/bin/cheat ;; *btop*) tar -xjf "$tool" -C /tmp cp /tmp/btop/bin/btop /usr/local/bin/ ;; *bottom*) tar -xzf "$tool" -C /usr/local/bin --strip-components=1 btm ;; *fd*) tar -xzf "$tool" -C /usr/local/bin --strip-components=1 fd ;; *bat*) tar -xzf "$tool" -C /usr/local/bin --strip-components=1 bat ;; *exa*) unzip -j "$tool" "bin/exa" -d /usr/local/bin/ ;; *) log_warn "未知工具类型: ${tool_name}, 跳过安装" ;; esac if [ $? -eq 0 ]; then log_success "工具安装成功: ${tool_name}" else log_error "工具安装失败: ${tool_name}" fi done log_success "系统工具安装完成" } configure_ssh() { log_info "===== [8/8] 优化SSH配置 =====" sed -i 's/^#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config sed -i 's/^#ClientAliveInterval.*/ClientAliveInterval 300/' /etc/ssh/sshd_config sed -i 's/^#ClientAliveCountMax.*/ClientAliveCountMax 2/' /etc/ssh/sshd_config sed -i 's/^#MaxSessions.*/MaxSessions 100/' /etc/ssh/sshd_config sed -i 's/^#MaxStartups.*/MaxStartups 100:30:200/' /etc/ssh/sshd_config echo "UseDNS no" >> /etc/ssh/sshd_config systemctl restart sshd log_success "SSH配置优化完成" } # ===== 主函数 ===== main() { { log_info "===== 开始系统优化 =====" log_info "主机名: $(hostname -f)" log_info "IP地址: $(hostname -I | awk '{print $1}')" log_info "优化日志: ${LOG_FILE}" disable_selinux disable_firewall disable_swap configure_kernel configure_limits configure_chrony install_tools configure_ssh log_success "===== 系统优化完成! =====" log_info "建议: 重启服务器使所有优化生效" } 2>&1 | tee -a "$LOG_FILE" } main "$@" EOF chmod +x "${OFFLINE_DIR}/optimize_system.sh" log_success "系统优化脚本已生成" # 生成Kubernetes安装脚本 cat > "${OFFLINE_DIR}/install_k8s_offline.sh" <<'EOF' #!/bin/bash # install_k8s_offline.sh - Kubernetes离线部署脚本(修复版) # 版本: 4.0 # ===== 配置区域 ===== K8S_VERSION="v1.28.5" OFFLINE_DIR="/opt/offline_packages" BIN_DIR="${OFFLINE_DIR}/bin" IMG_DIR="${OFFLINE_DIR}/images" LOG_FILE="/var/log/k8s_install_$(date +%Y%m%d%H%M%S).log" CRI="containerd" # docker 或 containerd MAX_RETRY=5 # 操作重试次数 # 日志函数 log() { local level=$1 local message=$2 local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[${timestamp}] [${level}] ${message}" | tee -a "$LOG_FILE" } log_info() { log "INFO" "$1"; } log_warn() { log "WARN" "$1"; } log_error() { log "ERROR" "$1"; } log_success() { log "SUCCESS" "$1"; } # ===== 工具函数 ===== retry_command() { local cmd=$1 local description=$2 local retry=0 while [ $retry -lt $MAX_RETRY ]; do log_info "尝试 $((retry+1)): $description" if eval "$cmd"; then return 0 else ((retry++)) sleep $((retry * 3)) fi done log_error "$description 失败 (重试 $MAX_RETRY 次)" return 1 } # ===== 安装函数 ===== install_container_runtime() { log_info "===== [1/6] 安装容器运行时 (${CRI}) =====" if [ "$CRI" = "docker" ]; then # 安装Docker yum remove -y docker* containerd.io || true yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo retry_command \ "yum install -y docker-ce docker-ce-cli containerd.io" \ "安装Docker" mkdir -p /etc/docker cat > /etc/docker/daemon.json <<EOL { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": {"max-size": "100m"}, "storage-driver": "overlay2", "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] } EOL systemctl enable docker systemctl start docker elif [ "$CRI" = "containerd" ]; then # 安装Containerd yum install -y containerd containerd config default > /etc/containerd/config.toml sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml sed -i 's|registry.k8s.io/pause|registry.aliyuncs.com/google_containers/pause|' /etc/containerd/config.toml systemctl enable containerd systemctl start containerd fi # 加载离线镜像 for img in "${IMG_DIR}"/*.tar; do [ -f "$img" ] || continue if [ "$CRI" = "docker" ]; then retry_command \ "docker load -i '$img'" \ "加载镜像 $(basename "$img")" else retry_command \ "ctr -n=k8s.io images import '$img'" \ "加载镜像 $(basename "$img")" fi done log_success "容器运行时安装完成" } install_k8s_components() { log_info "===== [2/6] 安装Kubernetes组件 =====" # 添加仓库 cat > /etc/yum.repos.d/kubernetes.repo <<EOL [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOL # 安装基础包 retry_command \ "yum install -y kubelet-${K8S_VERSION} kubeadm-${K8S_VERSION} kubectl-${K8S_VERSION} --disableexcludes=kubernetes" \ "安装Kubernetes组件" # 使用离线二进制 for bin in kubeadm kubelet kubectl; do [ -f "${BIN_DIR}/${bin}" ] && install -m 0755 "${BIN_DIR}/${bin}" /usr/bin/ done systemctl enable --now kubelet log_success "Kubernetes组件安装完成" } init_control_plane() { log_info "===== [3/6] 初始化控制平面 =====" local NODE_IP=$(hostname -I | awk '{print $1}') retry_command \ "kubeadm init \ --apiserver-advertise-address=$NODE_IP \ --pod-network-cidr=10.244.0.0/16 \ --ignore-preflight-errors=Swap \ --image-repository=registry.aliyuncs.com/google_containers \ --kubernetes-version=$K8S_VERSION" \ "初始化Kubernetes控制平面" mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /root/.bashrc source /root/.bashrc log_success "控制平面初始化完成" } install_network_addon() { log_info "===== [4/6] 安装网络插件 (Flannel) =====" # 应用Flannel配置 retry_command \ "kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml" \ "安装Flannel网络插件" # 等待网络插件就绪 log_info "等待网络插件启动..." retry_command \ "kubectl wait --for=condition=ready pod -l app=flannel -n kube-system --timeout=300s" \ "等待Flannel就绪" log_success "网络插件安装完成" } install_metrics_server() { log_info "===== [5/6] 安装Metrics Server =====" retry_command \ "kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml" \ "安装Metrics Server" # 修改配置以支持离线环境 kubectl patch deployment metrics-server -n kube-system --type=json \ -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]' log_info "等待Metrics Server启动..." retry_command \ "kubectl wait --for=condition=ready pod -l k8s-app=metrics-server -n kube-system --timeout=180s" \ "等待Metrics Server就绪" log_success "Metrics Server安装完成" } install_dashboard() { log_info "===== [6/6] 安装Kubernetes Dashboard =====" retry_command \ "kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml" \ "安装Kubernetes Dashboard" # 创建管理员用户 cat <<EOL | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard EOL # 获取访问令牌 local token=$(kubectl -n kubernetes-dashboard create token admin-user 2>/dev/null) if [ -n "$token" ]; then log_info "Dashboard访问令牌: ${token}" log_info "访问地址: https://$(hostname -I | awk '{print $1}'):30000" else log_warn "无法获取Dashboard令牌,请手动获取" fi log_success "Kubernetes Dashboard安装完成" } # ===== 主函数 ===== main() { { log_info "===== 开始Kubernetes离线安装 =====" log_info "主机名: $(hostname -f)" log_info "IP地址: $(hostname -I | awk '{print $1}')" log_info "Kubernetes版本: ${K8S_VERSION}" log_info "容器运行时: ${CRI}" log_info "日志文件: ${LOG_FILE}" install_container_runtime install_k8s_components init_control_plane install_network_addon install_metrics_server install_dashboard log_success "===== Kubernetes安装成功! =====" echo "加入节点命令:" kubeadm token create --print-join-command || echo "请手动生成加入命令: kubeadm token create --print-join-command" echo "验证集群状态: kubectl get nodes" } 2>&1 | tee -a "$LOG_FILE" } main "$@" EOF chmod +x "${OFFLINE_DIR}/install_k8s_offline.sh" log_success "Kubernetes安装脚本已生成" } # ===== 主函数 ===== main() { { log_info "===== 开始下载Kubernetes离线资源 =====" log_info "Kubernetes版本: ${K8S_VERSION}" log_info "离线包目录: ${OFFLINE_DIR}" create_dirs download_k8s_binaries || { log_error "Kubernetes二进制文件下载失败"; exit 1; } download_k8s_images || log_warn "部分容器镜像下载失败,请在离线环境中手动加载镜像" download_system_tools generate_deployment_scripts # 创建打包脚本 cat > "${OFFLINE_DIR}/package_offline.sh" <<'EOF' #!/bin/bash # 打包离线资源 tar -czvf k8s-offline-pkg-$(date +%Y%m%d).tar.gz -C /opt offline_packages echo "离线包已创建: k8s-offline-pkg-$(date +%Y%m%d).tar.gz" EOF chmod +x "${OFFLINE_DIR}/package_offline.sh" log_success "===== 下载完成! =====" log_info "1. 打包离线资源: sudo ${OFFLINE_DIR}/package_offline.sh" log_info "2. 复制离线包到目标服务器" log_info "3. 在目标服务器解压: sudo tar -xzvf k8s-offline-pkg-*.tar.gz -C /opt" log_info "4. 执行系统优化: sudo /opt/offline_packages/optimize_system.sh" log_info "5. 安装Kubernetes: sudo /opt/offline_packages/install_k8s_offline.sh" } 2>&1 | tee -a "$LOG_FILE" } main ``` ### 关键修复和改进: 1. **Docker服务自动管理**: - 自动检测并安装Docker - 确保Docker服务在镜像下载前已启动 - 添加Docker健康检查 2. **下载重试机制**: - 所有下载操作最多重试3次 - 每次重试间隔时间递增 - 失败后提供清晰错误日志 3. **GitHub镜像支持**: - 使用 `https://mirror.ghproxy.com/` 作为GitHub镜像 - 解决国内访问GitHub困难问题 4. **镜像下载改进**: - 分离镜像拉取和保存操作 - 每个镜像单独处理错误 - 失败时跳过当前镜像继续后续操作 5. **部署脚本增强**: - 所有关键操作添加重试机制 - 更健壮的错误处理 - 自动生成加入节点命令 - 容器运行时安装优化 6. **日志改进**: - 每个操作步骤清晰标记 - 重试次数明确显示 - 错误信息详细记录 ### 使用说明: #### 1. 执行下载脚本: ```bash chmod +x download_k8s_offline.sh sudo ./download_k8s_offline.sh ``` #### 2. 打包离线资源: ```bash sudo /opt/offline_packages/package_offline.sh ``` #### 3. 传输到目标服务器: ```bash scp k8s-offline-pkg-*.tar.gz user@target-server:/tmp/ ``` #### 4. 在目标服务器上: ```bash # 解压离线包 sudo tar -xzvf /tmp/k8s-offline-pkg-*.tar.gz -C /opt/ # 系统优化 sudo /opt/offline_packages/optimize_system.sh # 安装Kubernetes sudo /opt/offline_packages/install_k8s_offline.sh ``` ### 故障处理建议: 1. **镜像下载失败**: - 手动下载缺失镜像到 `/opt/offline_packages/images/` - 使用命令 `docker pull <镜像名>` 然后 `docker save -o <文件名>.tar <镜像名>` 2. **工具下载失败**: - 从其他来源获取工具并放入 `/opt/offline_packages/tools/` - 系统优化脚本会自动安装可用工具 3. **网络问题**: - 在下载脚本中替换 `MIRROR_URL` 为可用的GitHub镜像 - 使用代理设置:`export https_proxy=http://proxy-ip:port` 此版本脚本针对原始错误进行了全面加固,能够更好地处理网络问题和服务状态问题,确保离线部署的可靠性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值