OpenResty系统信息OpenResty在表ngx.conf里提供了六个功能接口，可以获取自身的一些信息：debug：是否算Debug版本prefix：工作目录，即启动时“-p”参数指定的目录nginx_version：大版本号，即内部NGINX的版本号nginx_configure:编译的使用的配置参数subsystem：当前所在的子系统，取值为“http”或“stream”ngx_lua_version：当前所在子系统的版本号注意： prefix和nginx_configure这两个接口是函数的形式。接口的示例代码如下：ngx.say(nginx.config.debug) ngx.say(nginx.config.prefix()) ngx.say(nginx.config.nginx_version) ngx.say(nginx.config.nginx_configure()) ngx.say(nginx.config.subsystem()) ngx.say(nginx.config.ngx_lua_version())OpenResty运行日志函数ngx.log(log_level)记录罗OpenResty的运行日志，用法类似Lua的标准库函数print，可以接受任意多个参数，记录任意信息。print()=ngx.NOTICEngx.log的第一个参数是日志级别。ngx.STDERR：日志直接打印到标准输出，最高级别的日志ngx.EMERG：发生了紧急情况（emergency），需要立即处理ngx.ALERT：发生了严重错误，可能需要报警给运维系统ngx.CRIT：发生了严重错误（critical）ngx.ERR：普通的错误，业务中发生了意外ngx.WARN：警告信息，业务正常，但可能需要检查警告的来源ngx.NOTICE：提醒信息，仅仅算告知，通常可以忽略ngx.INFO：一般的信息ngx.DEBUG：调试可用的信息，只有debug版本才会启用业务逻辑关键点INFO或者WARN，捕获error级别的错误信息OpenResty时间日期对于Web服务来说，能够随时获取正确的时间与日期是非常重要的。OpenResty为此提供罗很多时间日期相关的函数，可以满足绝大多数场景的应用。这些时间日期函数不会引发昂贵的系统调用（ngx.updatetime除外），几乎没有成本。所以在应用程序中应对尽量使用它们操作时间而不是使用Lua标准库里的os。当前时间ngx.say(ngx.today()) #本地时间，格式是“yyyy-mm-dd” ngx.say(ngx.localtime()) #本地时间，格式是“yyyy-mm-dd hh:mm:ss” ngx.say(ngx.utctime()) #utc时间，格式是“yyyy-mm-dd hh:mm:ss”时间戳ngx.time ngx.now时间戳
当拿到一台新服务器时，第一件事永远是根据实际业务来对服务器进行标准化设置。脚本特点智能系统识别 自动识别RHEL系(CentOS, RHEL, openEuler等)和Debian系(Ubuntu, Debian等)系统根据不同系统使用对应的包管理器(yum/dnf/apt)全面标准化配置高速软件源配置(阿里云镜像)基础运维工具安装Vim高级配置(语法高亮、Tab设置等)Shell别名与环境变量优化精确时间同步(chrony)内核参数优化(文件描述符、网络参数等)企业级审计系统(history增强+auditd)个性化登录欢迎界面SSH安全加固健壮性与错误处理Root权限检查配置文件备份机制兼容性处理详细的进度提示与状态反馈企业级安全特性操作审计追踪(谁、何时、从哪、做了什么)sudo特权操作监控SSH安全加固系统关键文件监控使用方法将脚本保存为server_init.sh赋予执行权限: chmod +x server_init.sh以root身份运行: sudo ./server_init.sh 警告: 脚本会修改系统关键配置，建议先在测试环境验证。特别是SSH安全加固部分会禁用密码登录，务必先配置好SSH密钥认证。这个脚本已经全面优化，可以适用于企业环境中大部分Linux服务器的标准化初始化需求，让运维工作更加高效、安全、规范。下载地址：{abtn icon="fa-download" color="#ff6800" href="https://www.xiaohetao.xyz/usr/uploads/2025/12/467932042.shh" radius="" content="点击下载"/}1.配置高速软件源使用的https://linuxmirrors.cn/提供的脚本bash <(curl -sSL https://linuxmirrors.cn/main.sh) \ --source mirrors.aliyun.com \ --protocol https \ --use-intranet-source false \ --install-epel true \ --backup true \ --upgrade-software false \ --clean-cache false \ --ignore-backup-tips2.安装运维工具包安装必需工具#centos系统基础工具包 dnf insta1l -y vim-enhanced #增强版Vim(带彩色高亮) dnf instal1 -y wget cur1 #下载工具(必须) dnfinsta11 -y net-tools #网络工具(ifconfig、netstat) dnfinsta11 -y rzsz #文件上传下载(比scp简单) dnf install -y tree # 树状显示目录 dnf install -y bash-completion #命令自动补全(新手神器) dnf install -y git # 代码管理 dnf insta11-y htop iotop iftop #增强版任务/i0/网络管理器Ubuntu系统把dnf换成apt即可。让工具更好用的配置# 1. Vim配置：从“勉强能用”到“得心应手” echo "正在配置Vim：告别默认vi的‘地狱模式’..." cat > /etc/vimrc <<'EOF' " 基础必改项 set number " 显示行号 - 没有行号的编辑器是在猜谜吗？ syntax enable " 语法高亮 - 一眼看出字符串、注释、关键字 set tabstop=2 " Tab宽度2空格（根据团队规范调整） set expandtab " Tab转空格 - 保证代码在所有人机器上显示一致 " 搜索增强 set incsearch " 边输入边高亮 set hlsearch " 保持高亮直到下次搜索 " 防止粘贴乱码 if has("mouse") set mouse=a " 启用鼠标（可以拖动、滚轮） endif set paste " 自动识别粘贴模式 EOF # 2. Shell别名：把复杂命令变成“肌肉记忆” echo "正在植入‘命令快捷键’..." cat >> /etc/bashrc <<'EOF' # ==== 安全防护 ==== alias rm='rm -i' # 删除文件时确认 alias cp='cp -i' # 覆盖文件时确认 alias mv='mv -i' # 覆盖文件时确认 # ==== 效率革命 ==== # 经典ls进化史：l → la → ll → llt alias l='ls -CF' alias la='ls -A' alias ll='ls -lhF --color=auto --time-style=long-iso' alias llt='ll -t' # 按时间排序，查日志必备 # ==== 网络诊断快捷键 ==== alias ports='ss -tulanp' # 比netstat更快的现代工具 alias listen='ports | grep LISTEN' # 只看监听端口 alias myip='curl -s icanhazip.com' # 最快获取公网IP # ==== 目录快跳 ==== alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' alias cdlog='cd /var/log' alias cdetc='cd /etc/sysconfig"' EOF 让配置立即生效 source /etc/bashrc 2>/dev/null || true # 定义欢迎脚本路径 WELCOME_SCRIPT="/etc/profile.d/welcome.sh"创建 welcome.sh 内容# 只在交互式 shell 中显示（避免 ssh 执行命令时干扰） if $- != *i* ; then return fi # 获取真实用户（支持 sudo/su） get_real_user() { if -n "$SUDO_USER" ; then echo "${SUDO_USER}(via sudo)" elif -f /proc/self/loginuid && "$(cat /proc/self/loginuid)" != "4294967295" ; then local uid=$(cat /proc/self/loginuid) id -un "$uid" 2>/dev/null || whoami else whoami fi } # 获取源IP get_client_ip() { if -n "$SSH_CLIENT" ; then echo "$SSH_CLIENT" | awk '{print $1}' elif -n "$SSH_CONNECTION" ; then echo "$SSH_CONNECTION" | awk '{print $3}' else echo "localhost" fi } # 显示欢迎信息（仅首次登录显示一次，避免重复） if [ -z "$WELCOME_SHOWN" ]; then export WELCOME_SHOWN=1 echo "" echo "******************************************************************" echo "* 🌟 欢迎登录企业运维服务器！ *" echo "* *" echo "* 🔒 安全审计提示： *" echo "* • 操作用户: $(get_real_user)" echo "* • 登录时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "* • 源 IP 地址: $(get_client_ip)" echo "* *" echo "* ⚠️ 重要声明： *" echo "* 本系统已启用操作审计，所有命令将记录： *" echo "* - 执行者身份（穿透 sudo/su） *" echo "* - 执行时间 *" echo "* - 源 IP 地址 *" echo "* - 工作目录和命令内容 *" echo "* *" echo "* 📊 实时系统状态： *" # 磁盘使用（根分区） # 磁盘使用（根分区） DISK_ROOT=$(df -h / 2>/dev/null | awk 'NR==2 {print $5}') # 内存使用率 MEM_USED=$(free 2>/dev/null | awk 'NR==2 {printf "%.0f%%", $3/$2 * 100}') # CPU 负载 LOAD=$(uptime 2>/dev/null | awk -F'load average:' '{print $2}' | xargs) # 登录用户数 USERS=$(who 2>/dev/null | wc -l) echo "* 💾 根分区使用: ${DISK_ROOT:-N/A}" echo "* 🧠 内存使用率: ${MEM_USED:-N/A}" echo "* ⚡ 系统负载: ${LOAD:-N/A}" echo "* 👥 当前登录: ${USERS} 个会话" echo "* *" echo "* 📞 安全支持: security@gaokun.edu *" echo "******************************************************************" echo "" fi EOF # 设置脚本权限（必须可执行） chmod +x "$WELCOME_SCRIPT" # 验证文件是否存在且可执行 if -f "$WELCOME_SCRIPT" && -x "$WELCOME_SCRIPT" ; then echo "✅ 成功部署登录欢迎提示！" echo "📍 文件位置: $WELCOME_SCRIPT" echo "" echo "💡 效果预览（当前用户）：" # 手动 source 测试（不退出当前会话） source "$WELCOME_SCRIPT" echo "" echo "📌 说明：" echo "1. 所有新登录用户将自动看到此提示" echo "2. 提示包含实时系统状态（磁盘、内存、负载）" echo "3. 支持 sudo/su 身份穿透识别" echo "4. 不会影响非交互式命令（如 scp、ssh cmd）" else echo "❌ 部署失败！请检查权限和磁盘空间" exit 1 fi echo "🎯 配置已生效！来体验几个‘效率魔法’：" echo "1. 输入 'll' - 看看和普通ls的差别" echo "2. 输入 'cdetc' - 直接跳到配置目录" echo "3. 输入 'listen' - 秒看所有监听端口" 3.配置时间同步chrony -- 传统的NTPd 更适合虚拟化和云环境，启动快，收敛快，抗网络抖动性更强的工具配置时间同步可以解决下面的问题：日志时间错乱证书验证失败分布式系统数据不一致定时任务不执行等等以下配置仅供参考，事实上chrony配置比较简单。# 配置国内时间服务器（替换默认的国外服务器） cat > /etc/chrony.conf <<'EOF' server ntp.aliyun.com iburst server ntp1.aliyun.com iburst server ntp2.aliyun.com iburst # 允许同步的网段（根据实际情况调整） allow 192.168.0.0/16 # 时间误差过大时的处理方式 makestep 1.0 3 # 启用硬件时间同步 rtcsync # 日志配置 logdir /var/log/chrony EOF # 启动并设置开机自启 systemctl enable --now chronyd # 强制立即同步 chronyc -a makestep # 查看同步状态 echo "当前时间：$(date)" echo "时间源状态：" chronyc sources -v 4.内核优化警惕“'To many open files”，部分案例：Elasticsearch官方强制要求调高FD限制Elasticsearch在处理大量索引和分片时，会同时打开成千上万个文件（每个段文件、每个网络连接都占一个FD）。其官方文档明确警告：“The default limit of 1024 open file descriptors is far too low for Elasticsearch.You must increase it to at least 65536.”Elasticsearch官方文档：File Descriptors无数用户在部署ES后遭遇写入失败、节点离群，根因都是未调整此配置。Redis因FD耗尽拒绝新客户端连接Redis为每个客户端连接、主从复制流、AOF文件等分配FD。当 ulimit -n 过低时，即使内存充足，Redis也会报错：1Error accepting client connection: accept: Too many open filesRedis官方FAQ专门列出此问题，并指导用户修改 /etc/security/limits.conf ：Redis Optimization Guide – File DescriptorsGitLab 2017年重大事故中，FD限制拖慢恢复在GitLab因误删生产数据库导致全球中断的著名事件中，团队在恢复备份时遇到严重瓶颈。官方复盘报告指出：The restore process was slowed by system limits on open files.”（恢复过程因系统对打开文件数量的限制而变慢）— GitLab Post-Mortem, Feb 2017虽然FD不是主因，但它显著延长了故障恢复时间，凸显了系统级调优的重要性。特别是一些机器没有提前进行调优的时候，到了关键时刻不一定能想得起来。内核优化# 1. 修改进程可打开文件数（解决‘Too many open files’） cat >> /etc/security/limits.conf <<'EOF' # 所有用户的基础限制 * soft nofile 65535 # 软限制（可临时超过） * hard nofile 65535 # 硬限制（最大上限） # 进程数限制（防止fork炸弹） * soft nproc 65535 * hard nproc 65535 # root用户的限制（通常更高） root soft nofile 100000 root hard nofile 100000 EOF # 2. 修改系统级限制（影响所有进程） cat >> /etc/sysctl.conf <<'EOF' # 增加系统最大文件打开数 fs.file-max = 1000000 # 增加TCP连接数（应对高并发） net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 # 加快TCP回收（应对短连接） net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 # 注意：在内核4.12+已移除，这里仅作演示 # 增加内存分配（应对大量连接） net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 EOF # 3. 立即生效（无需重启） sysctl -p 修改内核是个 危险操作 ，配错了可能导致系统无法启动。一定要做好测试， 灰度上线发布 。5.审计日志与系统安全加固为什么需要操作审计？1、安全合规要求2、故障排查刚需（运维必须会）3、团队管理利器（主管必须懂）怎么做？History增强+Auditd系统审计echo "🔍 [6/6] 正在部署‘企业级运维天眼系统’：谁？在什么时间？从哪来？做了什么？" # ============================================ # 第一部分：增强的History审计（记录命令） # ============================================ cat >> /etc/profile <<'EOF' # ==================== 智能History审计配置 ==================== # 获取登录用户的真实IP（SSH登录记录IP，本地登录记录localhost） USER_IP=$(who -u am i 2>/dev/null | awk '{print $NF}' | sed -e 's/[()]//g') if -z "$USER_IP" ; then # 如果是本地登录，尝试获取主机IP USER_IP=$(hostname -i 2>/dev/null || echo "localhost") fi # 核心：判断是否通过sudo切换身份 # $SUDO_USER：如果通过sudo执行命令，这个变量记录原始用户 if -n "$SUDO_USER" ; then REAL_USER="$SUDO_USER(as root)" # 记录真实用户+权限提升标记 else REAL_USER=$(whoami) # 记录当前用户 fi # 设置History格式：时间 | 真实用户 | IP地址 | 工作目录 | 执行的命令 export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S | $REAL_USER | $USER_IP | \$(pwd) | " export HISTSIZE=20000 # 内存中保存20000条命令 export HISTFILESIZE=40000 # 历史文件保存40000条命令 # 重要：防止某些命令被忽略（如空格开头） export HISTCONTROL=ignoredups:ignorespace # 设置不想被记录的命令（这些命令太常见，记录会浪费空间） export HISTIGNORE="ls:ll:la:cd:pwd:exit:history:h" # 关键配置：实时同步history到文件（防止终端异常退出丢失记录） shopt -s histappend PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND" # 创建审计日志目录 mkdir -p /var/log/audit chmod 750 /var/log/audit 用户登录/登出审计（每次登录都会记录） echo "$(date '+%Y-%m-%d %H:%M:%S') | $REAL_USER | $USER_IP | 登录系统 | 工作目录: \$(pwd)" >> /var/log/user_audit.log EOF # ============================================ # 第二部分：Sudo操作审计（特权命令记录） # ============================================ echo "配置Sudo操作审计..." # 创建Sudo审计配置 cat > /etc/sudoers.d/audit <<'EOF' # Sudo命令审计配置 Defaults logfile=/var/log/sudo_audit.log # 所有sudo命令记录到这个文件 Defaults log_input # 记录输入内容（如编辑文件的内容） Defaults log_output # 记录命令输出（谨慎开启，可能很大） Defaults iolog_dir=/var/log/sudo-io/%{user} # 每个用户的输入输出分开存放 # 重要：设置命令执行超时（防止命令卡住） Defaults timestamp_timeout=5 # sudo密码5分钟后需要重新输入 Defaults passwd_timeout=1 # 密码输入超时1分钟 EOF chmod 440 /etc/sudoers.d/audit # 必须440权限，保护配置文件 # 创建审计日志文件 touch /var/log/user_audit.log touch /var/log/sudo_audit.log chmod 600 /var/log/user_audit.log chmod 600 /var/log/sudo_audit.log # ============================================ # 第三部分：Auditd系统级审计（内核级监控） # ============================================ echo "安装和配置Auditd系统审计服务..." # 安装auditd if command -v dnf &> /dev/null; then dnf install -y audit audit-libs > /dev/null 2>&1 elif command -v yum &> /dev/null; then yum install -y audit audit-libs > /dev/null 2>&1 fi # 配置auditd规则 cat > /etc/audit/rules.d/99-ops-audit.rules <<'EOF' # ========== 运维操作审计规则 ========== # 1. 监控用户和权限变更 -w /etc/passwd -p wa -k user_changes # 监控用户账户变更 -w /etc/group -p wa -k group_changes # 监控用户组变更 -w /etc/shadow -p wa -k shadow_changes # 监控密码文件变更 -w /etc/sudoers -p wa -k sudoers_changes # 监控sudo权限变更 -w /etc/ssh/sshd_config -p wa -k ssh_changes # 监控SSH配置变更 # 2. 监控系统关键目录（防篡改） -w /etc/ -p wa -k etc_changes # 监控/etc目录所有写操作 -w /usr/bin/ -p wa -k bin_changes # 监控系统命令目录 -w /usr/sbin/ -p wa -k sbin_changes -w /var/log/ -p wa -k log_changes # 监控日志目录（防删日志） -w /root/.ssh/ -p wa -k root_ssh # 监控root的SSH密钥 # 3. 监控特权命令使用（谁提权了？） -w /bin/su -p x -k privilege_escalation # 监控su命令执行 -w /usr/bin/sudo -p x -k privilege_escalation # 监控sudo命令执行 -w /usr/bin/passwd -p x -k password_changes # 监控密码修改 # 4. 监控文件删除操作（谁删了文件？） -a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -k delete_files -a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -k delete_files # 5. 监控网络配置变更 -w /etc/hosts -p wa -k hosts_changes # 监控hosts文件 -w /etc/resolv.conf -p wa -k dns_changes # 监控DNS配置 # 6. 监控防火墙配置变更 -w /etc/sysconfig/iptables -p wa -k firewall_changes -w /etc/firewalld/ -p wa -k firewalld_changes # 7. 监控系统服务变更 -w /usr/lib/systemd/system/ -p wa -k service_changes -w /etc/systemd/system/ -p wa -k service_changes # 8. 监控定时任务变更 -w /etc/crontab -p wa -k cron_changes -w /etc/cron.hourly/ -p wa -k cron_changes -w /etc/cron.daily/ -p wa -k cron_changes -w /etc/cron.weekly/ -p wa -k cron_changes -w /var/spool/cron/ -p wa -k user_cron_changes # 9. 监控内核模块加载（防Rootkit） -w /sbin/insmod -p x -k kernel_modules -w /sbin/rmmod -p x -k kernel_modules -w /sbin/modprobe -p x -k kernel_modules EOF # 启用并启动auditd服务 systemctl enable auditd > /dev/null 2>&1 # 检查auditd是否已在运行，避免冲突 if systemctl is-active auditd &> /dev/null; then echo "auditd服务已在运行，重新加载规则..." auditctl -R /etc/audit/rules.d/99-ops-audit.rules > /dev/null 2>&1 else systemctl start auditd > /dev/null 2>&1 fi echo "✅ 企业级审计系统部署完成！" echo "" 企业里面生产还需做哪些?1、定期备份审计日志 -- 合规化需要，有些企业是每周一次内部审查2、告警的机制，关键操作实时告警(修改密码，删除日志)3、集中化的日志管理，比如ELKvsxsl9g，把所有的服务器日志集中存储，防止日志被纂改4、堡垒机(lumpseryer):统一管理服务器的访问权限、所有的操作视频回放。5、SSH安全加固。6.企业级监控与性能基线企业级监控与性能基线部署完上述的所有环境之后，还需要针对企业内部的一些实际环境进行定制化的软件安装1、安装企业内部工具包CI\CD2、配置sar数据收集3、部署监控告警系统:如:zabki、Prometheus+Gra34、设置性能的基线:了解服务器在正常状态下的表现，当出现异常的时候能够快速识别
topic 相关说明：红色的是必需要指定的参数使用bin/kafka-topics.sh 可查看所有的参数信息参数描述--bootstrap-server <String: server connect to> 连接kafka broker主机名称和端口号--topic <String: topic> 操作的topic名称--create创建主题--delete删除主题--alter修改主题--list查看所有主题--describe查看主题详细描述--partitions <Integer: # of partitions>设置分区数--replication-factor <Integer: replication factor>设置分区副本--config <String: name=value>更新系统默认的配置root@kf1:/opt/kafka# bin/kafka-topics.sh --bootstrap-server kf1:9092 --describe --topic first Topic: first TopicId: o4AxZZfwQhG-QR38nHUGxQ PartitionCount: 3 ReplicationFactor: 3 Configs: min.insync.replicas=1,segment.bytes=1073741824 Topic: first Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,2,3 Elr: LastKnownElr: Topic: first Partition: 1 Leader: 2 Replicas: 2,3,1 Isr: 2,3,1 Elr: LastKnownElr: Topic: first Partition: 2 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2 Elr: LastKnownElr: Topic: 主题名称TopicId: 主题IDPartitionCount: 分区数量ReplicationFactor: 副本数量Configs: min.insync.replicas=1,segment.bytes=1073741824Topic:Partition: 分区IDLeader: 副本的leaderReplicas: 副本存储位置Isr: 连接的副本LastKnownElr
kafka2.8.0版本引入了基于Raft共识协议的新特性，它允许kafka集群在没有ZooKeeper的情况下运行。为了剥离和去除ZooKeeper，Kafka引入了自己的KRaft（Kafka Raft Metadata Mode）。KRaft是一个新的元数据管理架构，基于Raft一致性算法实现的一种内置元数据管理方式，旨在替代ZooKeeper的元数据管理功能。KRaft的优势有以下几点：简化部署：Kafka 集群不再依赖外部的 ZooKeeper 集群，简化了部署和运维的复杂性。KRaft 将所有协调服务嵌入 Kafka 自身，不再依赖外部系统，这样大大简化了部署和管理，因为管理员只需关注 Kafka 集群。高效的一致性协议：Raft 是一种简洁且易于理解的一致性算法，易于调试和实现。KRaft 利用 Raft 协议实现了强一致性的元数据管理，优化了复制机制。提高性能：由于元数据管理不再依赖 ZooKeeper，Kafka 集群的性能得到了提升，尤其是在元数据读写方面。增强可扩展性：KRaft 模式支持更大的集群规模，可以有效地扩展到数百万个分区。提高元数据操作的扩展性：新的架构允许更多的并发操作，并减少了因为扩展性问题导致的瓶颈，特别是在高负载场景中。更快的控制器故障转移：控制器（Controller）的选举和故障转移速度更快，提高了集群的稳定性。消除 ZooKeeper 作为中间层之后，Kafka 的延迟性能有望得到改善，特别是在涉及选主和元数据更新的场景中。KRaft模式下，kafka集群中的一些节点被指定为控制器（Controller），它们负责集群的元数据管理和共识服务，所有的元数据都存储在kafka内部的主题中，而不是ZooKeeper，控制器通过KRaft协议来确保元数据在集群中的准确复制，这种模式使用了基于时间的存储模型，通过定期快照来保证元数据日志不会无限增长。完全自主：因为是自家产品，所以产品的架构设计，代码开发都可以自己说了算，未来架构走向完全控制在自己手上。控制器（Controller）节点的去中心化：KRaft 模式中，控制器节点由一组 Kafka 服务进程代替，而不是一个独立的 ZooKeeper 集群。这些节点共同负责管理集群的元数据，通过 Raft 实现数据的一致性。日志复制和恢复机制：利用 Raft 的日志复制和状态机应用机制，KRaft 实现了对元数据变更的强一致性支持，这意味着所有控制器节点都能够就集群状态达成共识。动态集群管理：KRaft允许动态地向集群中添加或移除节点，而无需手动去ZooKeeper中更新配置，这使得集群管理更为便捷。下载在 kakfa官网 下载最新的安装包，推荐下载已经编译好的二进制包。wget https://dlcdn.apache.org/kafka/4.1.1/kafka_2.13-4.1.1.tgz tar -xzf kafka_2.13-4.1.1.tgz mv kafka_2.13-4.1.1 /opt/kafka修改配置文件修改位于config目录下的server.properties############################# Server Basics ############################# #定义节点角色。broker，处理消息存储、生产者/消费者请求；controller，管理集群元数据（分区状态、副本分配）。 process.roles=broker,controller # 节点id，要求集群内唯一，每个节点的id都要不同（如 1、2、3）。 node.id=1 #Controller节点启动时发现的初始服务器列表（用于加入集群）。 controller.quorum.bootstrap.servers=kf1:9093,kf2:9093,kf3:9093 #controller集群成员列表，集群内部选举和同步元数据，所有 Controller 节点必须在此列表中，且数量需满足多数派（如 3 节点集群需至少 2 个在线）。 controller.quorum.voters=1@kf1:9093,2@kf2:9093,3@kf3:9093 ############################# Socket Server Settings ##################### #节点绑定的网络接口和端口。PLAINTEXT:Broker服务端口（接收客户端请求），CONTROLLER:Controller间通信端口。 listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 #Broker 之间通信使用的监听器名称 inter.broker.listener.name=PLAINTEXT #客户端实际连接的地址（Broker 会返回此地址给客户端）。 advertised.listeners=PLAINTEXT://192.168.88.51:9092,CONTROLLER://192.168.88.51:9093 #Controller 节点间通信使用的监听器名称 controller.listener.names=CONTROLLER #监听器名称与安全协议的映射关系。 listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL #处理网络请求的线程数（如接收请求、发送响应）。 num.network.threads=3 #处理磁盘 I/O 的线程数（如读写日志文件）。 num.io.threads=8 #Socket 缓冲区 socket.send.buffer.bytes=102400 #发送数据缓冲区大小（100KB）。 socket.receive.buffer.bytes=102400 #接收数据缓冲区大小（100KB）。 socket.request.max.bytes=104857600 #请求最大长度（100MB），防止 OOM。 ############################# Log Basics ############################# #消息日志存储目录（可配置多个路径，逗号分隔）。 log.dirs=/opt/kafka_data # 日志目录（可选） kafka_logs_dir=/var/log/kafka #分区与恢复 num.partitions=3 #新建 Topic 的默认分区数。 num.recovery.threads.per.data.dir=1 #每个日志目录用于崩溃恢复的线程数。 ############################# Internal Topic Settings #################### #副本因子与 ISR offsets.topic.replication.factor=3 # __consumer_offsets 副本数（生产环境建议 ≥3） share.coordinator.state.topic.replication.factor=2 # Share Group 状态主题副本数 share.coordinator.state.topic.min.isr=2 #share.coordinator.state.topic：Kafka Share Group 协调器的状态主题（内部主题）。min.isr：最小同步副本数（Minimum In-Sync Replicas），即写入操作需确认的最小同步副本数量（含 Leader）。配置值 1：表示向 share.coordinator.state.topic写入数据时，只需 Leader 副本确认即可认为成功（无需等待 Follower 副本同步）。逻辑：ISR（In-Sync Replicas，同步副本集）是 Leader 副本及与其保持同步的 Follower 副本的集合。min.isr=1意味着只要 Leader 副本存活且可写，写入就成功（即使没有其他同步副本）。 transaction.state.log.replication.factor=3 #transaction.state.log：Kafka 事务协调器的状态日志主题。事务协调器负责管理分布式事务（如跨分区/主题的事务提交/中止），该主题存储事务元数据（如事务 ID、参与者列表、状态（进行中/已提交/已中止）、超时时间等）。replication.factor：副本因子，即主题每个分区的副本总数（含 Leader 副本）。配置值 1：表示 transaction.state.log的每个分区仅有 1 个副本（仅 Leader 副本，无 Follower 副本）。逻辑：副本因子决定数据冗余度。replication.factor=1意味着数据仅存储在单个 Broker 上，无任何备份。 transaction.state.log.min.isr=3 #transaction.state.log：指定该参数作用于 事务状态日志（而非普通业务 Topic）。min.isr：即“最小同步副本数”，表示事务状态日志的每个分区，必须至少有 N 个副本（包括 Leader 副本）与 Leader 保持同步，否则该分区会进入“不可用”状态（无法写入新事务记录）。当事务状态日志的某个分区进行写入时，Kafka 会确保该分区的 同步副本集（ISR）大小 ≥ 3。只有当至少 3 个副本（Leader + 2 个 Follower）都成功复制了事务日志条目后，才会向生产者返回“事务提交成功”的响应。 default.replication.factor=3 #普通主题默认的副本因子数量 ############################# Log Flush Policy ############################ #日志保留策略 log.retention.hours=168 #日志保留时间（168 小时 = 7 天）。 log.segment.bytes=1073741824 #单个日志分段大小（1GB），达到后滚动生成新文件。 log.retention.check.interval.ms=300000 #检查日志保留的间隔（5 分钟）。在节点2上修改node.id=2 advertised.listeners=PLAINTEXT://192.168.88.52:9092,CONTROLLER://192.168.88.52:9093在节点3上修改node.id=3 advertised.listeners=PLAINTEXT://192.168.88.53:9092,CONTROLLER://192.168.88.53:9093初始化集群并启动首次启动时执行#在任一节点执行，仅执行一次，生成唯一集群ID bin/kafka-storage.sh random-uuid 0jQIB8NvQ3muEJg2vXIRRA #在每个节点执行，格式化存储 bin/kafka-storage.sh format -t 0jQIB8NvQ3muEJg2vXIRRA -c config/server.propertie Formatting metadata directory /opt/kafka_data with metadata.version 4.1-IV1.启动服务配置开机自启创建service文件vim /etc/systemd/system/kafka.service [Unit] Description=Apache Kafka Server Documentation=http://kafka.apache.org/documentation.html Requires=network.target remote-fs.target After=network.target remote-fs.target [Service] Type=simple User=kafka Group=kafka ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties ExecStop=/opt/kafka/bin/kafka-server-stop.sh Restart=on-abnormal RestartSec=10 KillMode=mixed TimeoutStopSec=30 Environment="LOG_DIR=/var/log/kafka" Environment="KAFKA_HEAP_OPTS=-Xmx1G -Xms1G" # 显式设置堆内存 # 日志重定向 StandardOutput=file:/var/log/kafka/service.log StandardError=file:/var/log/kafka/service-error.log [Install] WantedBy=multi-user.target# 重载 systemd 配置 sudo systemctl daemon-reload创建 Kafka 专用用户和目录# 创建系统用户 sudo useradd -r -s /sbin/nologin kafka # 创建数据/日志目录 sudo mkdir -p /opt/kafka_data sudo mkdir -p /var/log/kafka sudo chown -R kafka:kafka /opt/kafka_data /var/log/kafka # 授权 Kafka 安装目录 sudo chown -R kafka:kafka /opt/kafka按顺序启动节点可以使用systemctl命令或者手动的方式启动服务，#systemctl启动 systemctl enable --now kafka #前台启动 bin/kafka-server-start.sh config/server.properties #后台启动 nohup bin/kafka-server-start.sh config/server.properties &查看集群状态bin/kafka-broker-api-versions.sh --bootstrap-server 127.0.0.1:9092 # 192.168.88.51:9092 Broker 对外提供服务的 IP:端口（客户端实际连接的地址）。 #id: 1 Broker 的唯一标识 broker.id（集群中必须唯一，此处为 1、2、3）。 # rack: null 机架信息（未配置，故为 null，用于副本跨机架分布策略）。 #isFenced: false Broker 未被“隔离”（正常工作状态，若为 true则无法处理请求）。 192.168.88.51:9092 (id: 1 rack: null isFenced: false) -> ( Produce(0): 0 to 13 [usable: 13], #Produce(0) API 名称（Produce，消息生产 API），括号内 0是该 API 的 固定 key（Kafka 定义）。 #0 to 13 该 API 支持的 版本范围（从 v0 到 v13，共 14 个版本）。 #usable: 13 客户端与 Broker 协商后 实际使用的版本（取双方都支持的最高版本，性能最优）。 Fetch(1): 4 to 18 [usable: 18], ListOffsets(2): 1 to 10 [usable: 10], Metadata(3): 0 to 13 [usable: 13], OffsetCommit(8): 2 to 9 [usable: 9], OffsetFetch(9): 1 to 9 [usable: 9], FindCoordinator(10): 0 to 6 [usable: 6], JoinGroup(11): 0 to 9 [usable: 9], Heartbeat(12): 0 to 4 [usable: 4], LeaveGroup(13): 0 to 5 [usable: 5], SyncGroup(14): 0 to 5 [usable: 5], DescribeGroups(15): 0 to 6 [usable: 6], ListGroups(16): 0 to 5 [usable: 5], SaslHandshake(17): 0 to 1 [usable: 1], ApiVersions(18): 0 to 4 [usable: 4], CreateTopics(19): 2 to 7 [usable: 7], DeleteTopics(20): 1 to 6 [usable: 6], DeleteRecords(21): 0 to 2 [usable: 2], InitProducerId(22): 0 to 5 [usable: 5], OffsetForLeaderEpoch(23): 2 to 4 [usable: 4], AddPartitionsToTxn(24): 0 to 5 [usable: 5], AddOffsetsToTxn(25): 0 to 4 [usable: 4], EndTxn(26): 0 to 5 [usable: 5], WriteTxnMarkers(27): 1 [usable: 1], TxnOffsetCommit(28): 0 to 5 [usable: 5], DescribeAcls(29): 1 to 3 [usable: 3], CreateAcls(30): 1 to 3 [usable: 3], DeleteAcls(31): 1 to 3 [usable: 3], DescribeConfigs(32): 1 to 4 [usable: 4], AlterConfigs(33): 0 to 2 [usable: 2], AlterReplicaLogDirs(34): 1 to 2 [usable: 2], DescribeLogDirs(35): 1 to 4 [usable: 4], SaslAuthenticate(36): 0 to 2 [usable: 2], CreatePartitions(37): 0 to 3 [usable: 3], CreateDelegationToken(38): 1 to 3 [usable: 3], RenewDelegationToken(39): 1 to 2 [usable: 2], ExpireDelegationToken(40): 1 to 2 [usable: 2], DescribeDelegationToken(41): 1 to 3 [usable: 3], DeleteGroups(42): 0 to 2 [usable: 2], ElectLeaders(43): 0 to 2 [usable: 2], IncrementalAlterConfigs(44): 0 to 1 [usable: 1], AlterPartitionReassignments(45): 0 to 1 [usable: 1], ListPartitionReassignments(46): 0 [usable: 0], OffsetDelete(47): 0 [usable: 0], DescribeClientQuotas(48): 0 to 1 [usable: 1], AlterClientQuotas(49): 0 to 1 [usable: 1], DescribeUserScramCredentials(50): 0 [usable: 0], AlterUserScramCredentials(51): 0 [usable: 0], DescribeQuorum(55): 0 to 2 [usable: 2], UpdateFeatures(57): 0 to 2 [usable: 2], DescribeCluster(60): 0 to 2 [usable: 2], DescribeProducers(61): 0 [usable: 0], UnregisterBroker(64): 0 [usable: 0], DescribeTransactions(65): 0 [usable: 0], ListTransactions(66): 0 to 2 [usable: 2], ConsumerGroupHeartbeat(68): 0 to 1 [usable: 1], ConsumerGroupDescribe(69): 0 to 1 [usable: 1], GetTelemetrySubscriptions(71): UNSUPPORTED, PushTelemetry(72): UNSUPPORTED, ListConfigResources(74): 0 to 1 [usable: 1], DescribeTopicPartitions(75): 0 [usable: 0], ShareGroupHeartbeat(76): 1 [usable: 1], ShareGroupDescribe(77): 1 [usable: 1], ShareFetch(78): 1 [usable: 1], ShareAcknowledge(79): 1 [usable: 1], AddRaftVoter(80): 0 [usable: 0], RemoveRaftVoter(81): 0 [usable: 0], InitializeShareGroupState(83): 0 [usable: 0], ReadShareGroupState(84): 0 [usable: 0], WriteShareGroupState(85): 0 [usable: 0], DeleteShareGroupState(86): 0 [usable: 0], ReadShareGroupStateSummary(87): 0 [usable: 0], StreamsGroupHeartbeat(88): UNSUPPORTED, StreamsGroupDescribe(89): UNSUPPORTED, DescribeShareGroupOffsets(90): 0 [usable: 0], AlterShareGroupOffsets(91): 0 [usable: 0], DeleteShareGroupOffsets(92): 0 [usable: 0] ) 192.168.88.52:9092 (id: 2 rack: null isFenced: false) -> ( …… ) 192.168.88.53:9092 (id: 3 rack: null isFenced: false) -> ( …… )
ZooKeeper 是一个分布式协调服务，常用于管理配置、命名和同步服务。长期以来，Kafka 使用 ZooKeeper 负责管理集群元数据、控制器选举和消费者组协调等任务理，包括主题、分区信息、ACL（访问控制列表）等。ZooKeeper 为 Kafka 提供了选主（leader election）、集群成员管理等核心功能，为 Kafka提供了一个可靠的分布式协调服务，使得 Kafka能够在多个节点之间进行有效的通信和管理。然而，随着 Kafka的发展，其对 ZooKeeper的依赖逐渐显露出一些问题，这些问题也是下面 Kafka去除 Zookeeper的原因。kafka 2.8+ 为什么要移除zookeeper组件呢?kafka 4.0+版本彻底移除了zookeeper组件1.复杂性增加ZooKeeper 是独立于 Kafka 的外部组件，需要单独部署和维护，因此，使用 ZooKeeper 使得 Kafka的运维复杂度大幅提升。运维团队必须同时管理两个分布式系统（Kafka和 ZooKeeper），这不仅增加了管理成本，也要求运维人员具备更高的技术能力。2. 性能瓶颈作为一个协调服务，ZooKeeper 并非专门为高负载场景设计， 因此，随着集群规模扩大，ZooKeeper在处理元数据时的性能问题日益突出。例如，当分区数量增加时，ZooKeeper需要存储更多的信息，这导致了监听延迟增加，从而影响Kafka的整体性能。在高负载情况下，ZooKeeper可能成为系统的瓶颈，限制了Kafka的扩展能力。3. 一致性问题Kafka 内部的分布式一致性模型与 ZooKeeper 的一致性模型有所不同。由于 ZooKeeper和 Kafka控制器之间的数据同步机制不够高效，可能导致状态不一致，特别是在处理集群扩展或不可用情景时，这种不一致性会影响消息传递的可靠性和系统稳定性。4.发展自己的生态Kafka 抛弃 ZooKeeper，最核心的原因：Kafka生态强大了，需要自立门户，这样就不会被别人卡脖子。纵观国内外，有很多这样鲜活的例子，当自己弱小时，会先选择使用别家的产品，当自己羽翼丰满时，再选择自建完善自己的生态圈。但是一些旧版的kafka仍需配置ZooKeeper服务，因为Kafka依赖ZooKeeper进行集群协调、Broker注册、Topic管理等操作。安装ZooKeeperJava环境ZooKeeper是基于Java开发的，因此在部署时需要确保机器上有Java运行环境（JRE/JDK）。检查当前 Java 环境首先确认系统是否已安装 Java，以及版本是否符合要求java -version openjdk version "25.0.1" 2025-10-21 OpenJDK Runtime Environment (build 25.0.1+8-Ubuntu-124.04) OpenJDK 64-Bit Server VM (build 25.0.1+8-Ubuntu-124.04, mixed mode, sharing)若提示 command not found，说明未安装 Java，需继续安装java -version 找不到命令 “java”，但可以通过以下软件包安装它： apt install openjdk-17-jre-headless # version 17.0.17+10-1~24.04, or apt install openjdk-21-jre-headless # version 21.0.9+10-1~24.04 apt install default-jre # version 2:1.17-75 apt install openjdk-19-jre-headless # version 19.0.2+7-4 apt install openjdk-20-jre-headless # version 20.0.2+9-1 apt install openjdk-22-jre-headless # version 22~22ea-1 apt install openjdk-11-jre-headless # version 11.0.29+7-1ubuntu1~24.04 apt install openjdk-25-jre-headless # version 25.0.1+8-1~24.04 apt install openjdk-8-jre-headless # version 8u472-ga-1~24.04 root@zookeeper1:~/zookeeper# apt install openjdk-11-jre-headless 正在读取软件包列表... 完成 正在分析软件包的依赖关系树... 完成 正在读取状态信息... 完成 将会同时安装下列软件： alsa-topology-conf alsa-ucm-conf ca-certificates-java java-common libasound2-data libasound2t64 建议安装： default-jre alsa-utils libasound2-plugins libnss-mdns fonts-dejavu-extra fonts-ipafont-gothic fonts-ipafont-mincho fonts-wqy-microhei | fonts-wqy-zenhei fonts-indic下载并解压ZooKeeper点击 ZooKeeper下载列表 ，下载最新版本的安装包。wget -O zookeeper-3.9.4-bin.tar.gz https://dlcdn.apache.org/zookeeper/zookeeper-3.9.4/apache-zookeeper-3.9.4-bin.tar.gz tar -xf zookeeper-3.9.4-bin.tar.gz mv apache-zookeeper-3.9.4-bin/ /opt/zookeeper注意:集群模式至少需要三台服务器，强烈建议拥有奇数台服务器。如果你只有两台服务器，那么如果其中一台故障，机器数量不足以形成多数法定人数。两台服务器本质上比单台服务器稳定性差，因为存在两个单点故障。配置所有的服务器都拥有相同的配置文件。在ZooKeeper目录下的conf目录中，有个配置文件的示例，拷贝这个文件并修改其中的部分内容cp conf/zoo_sample.cfg conf/zoo.cfg修改项：tickTime=2000 initLimit=10 syncLimit=5 dataDir=/var/zookeeper/data dataLogDir=/var/zookeeper/logs clientPort=2181 server.1=192.168.88.31:2888:3888 server.2=192.168.88.32:2888:3888 server.3=192.168.88.33:2888:3888说明：tickTime：ZooKeeper 使用的基本时间单位（毫秒）。它用于读取心跳，最小会话超时时间是tickTime的两倍。initLimit：用来限制法定人数服务器连接领导者所需时间的超时syncLimit：限制服务器与领导者的过时距离dataDir：存储内存数据库快照的位置，除非另有说明，存储数据库更新的事务日志。dataLogDir：存储日志文件的位置clientPort：用于监听客户端连接的端口server.1=192.168.88.31:2888:3888 集群地址，“2888”和“3888”。对等节点使用前一个端口连接其他节点。这种连接是必要的，以便对等端能够通信，例如达成更新顺序的一致。更具体地说，ZooKeeper服务器利用该端口将追随者连接到领导者。当出现新的领导者时，跟随者会通过该端口与该领导者开启TCP连接。由于默认领导人选举也使用TCP，我们目前要求领导人选举需要另一个端口。这是服务器条目的第二个端口。确保dataDir和dataLogDir目录存在，如果不存在就创建它们。配置myid 在data/目录下，按集群顺序依次创建myid文件并写入id信息。#88.31机器上 echo 1 >myid #88.32机器上 echo 2 >myid #88.33机器上 echo 3 >myid开启服务bin/zkServer.sh start /usr/bin/java ZooKeeper JMX enabled by default Using config: /root/zookeeper/bin/../conf/zoo.cfg Starting zookeeper ... STARTED root@zookeeper2:~/zookeeper# bin/zkServer.sh status /usr/bin/java ZooKeeper JMX enabled by default Using config: /root/zookeeper/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Client SSL: false. Mode: leader 配置开机启动（service服务）vim /etc/systemd/system/zookeeper.service [Unit] Description=Apache ZooKeeper Service Documentation=https://zookeeper.apache.org After=network.target [Service] Type=forking ExecStart=/root/zookeeper/bin/zkServer.sh start ExecStop=/root/zookeeper/bin/zkServer.sh stop ExecReload=/root/zookeeper/bin/zkServer.sh restart Restart=on-failure [Install] WantedBy=multi-user.target systemctl daemon-reload systemctl enable zookeeper --now
Kafka定义kafka传统定义：Kafka是一个分布式的基于发布/订阅模式的消息列队（Message Queue），主要应用于大数据实时处理领域。发布/订阅：消息的发布者不会将消息直接发送给特定的订阅者，而是将发布的消息分为不同的类别，订阅者只接收感兴趣的消息。Kafka最新定义：Kafka是一个开源的 分布式事件流平台 （Event Streaming Platform），用于高性能 数据管道、流分析、数据集成和关键任务应用 。消息队列目前企业中比较常见的消息列队产品有Kafka、ActiveMQ、RabbitMQ、RocketMQ等。在大数据场景主要采用Kafka作为消息列队。在JavaEE开发中主要采用ActiveMQ、RabbitMQ、RocketMQ。传统消息列队的应用场景主要应用场景包括：缓冲/消峰、解耦和异步通信。缓冲/消峰有助于控制和优化数据流经过系统的速度，解决生产消息和消费消息的处理速度不一致的情况。解耦允许独立的扩展或修改两边的处理过程，只需要确保它们遵守同样的接口约束。异步通信允许用户把一个消息放入队列，但并不立即处理它，然后在需要的时候再去处理它们。消息列队的两种模式1.点对点模式：消费者主动拉取数据，消息收到后清除消息2.发布/订阅模式：可以有多个topic主题（浏览、点赞、收藏、评论等）消费者消费数据之后，不删除数据每个消费者相互独立，都可以消费到数据Kafka特点数据吞吐量巨大：需要能够快速收集各个渠道的海量日志集群容错性高：允许集群内少量节点崩溃功能不需要太复杂：kafka的设计目标算高吞吐量、低延迟和可扩展性，主要关注消息传递而不是消息处理，所以kafka没有支持死信列队、顺序消息等高级功能允许少量数据丢失：在海量的应用日志中，少量的日志丢失算不会影响结果的。所以kafka的设计初衷算允许少量数据丢失的。当然，kafka本身也在不断优化数据安全问题。Kafka基础架构为方便扩展，提高吞吐量，一个topic分为多个partition配合分区的设计，提出消费者组的概念，组内每个消费者并行消费为提高可用性，为每个partition增加若干副本，类似NameNode HAZK中记录谁是leader，Kafka.8.0以后可以配置不采用ZKProducer：消息生产者，向Kafka broker发消息的客户端Consumer：消息消费者，向Kafka broker拉取消息的客户端Topic：主题，存储各种各样的数据注：一个分区的数据只能由一个消费者来消费。
集群信息显示 Kubernetes 版本：kubectl version显示集群信息：kubectl cluster-info列出集群中的所有节点：kubectl get node查看一个具体的节点详情：kubectl describe node <node-name>5.列出所有命名空间：kubectl get namespaces列出所有命名空间中的所有 pod：kubectl get pods --all-namespacesPod信息列出特定命名空间中的 pod：kubectl get pods -n <namespace>查看一个 Pod 详情：kubectl describe pod <pod-name> -n <namespace>查看 Pod 日志：kubectl logs <pod-name> -n <namespace>尾部 Pod 日志：kubectl logs -f <pod-name> -n <namespace>在 pod 中执行命令：kubectl exec -it <pod-name> -n <namespace> -- <command>Pod 亲和性和反亲和性列出 pod 的 pod 亲和性规则：kubectl get pod <pod-name> -n <namespace> -o=jsonpath='{.spec.affinity}'列出 pod 的 pod 反亲和性规则：kubectl get pod <pod-name> -n <namespace> -o=jsonpath='{.spec.affinity.podAntiAffinity}'节点污点 列出节点污点：kubectl describe node <node-name> | grep TaintsPod 优先级和抢占 列出优先级：kubectl get priorityclassesPod 开销 列出 pod 中的开销：kubectl get pod <pod-name> -n <namespace> -o=jsonpath='{.spec.overhead}'Pod 健康检查检查 Pod 准备情况：kubectl get pods <pod-name> -n <namespace> -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'检查 Pod 事件：kubectl get events -n <namespace> --field-selector involvedObject.name=<pod-name>服务信息Service信息列出命名空间中的所有服务：kubectl get svc -n <namespace>查看一个服务详情：kubectl describe svc <service-name> -n <namespace>更改和验证 Webhook 配置列出变异 webhook 配置：kubectl get mutatingwebhookconfigurations列出验证 Webhook 配置：kubectl get validatingwebhookconfigurationsPod 网络策略 列出命名空间中的 pod 网络策略：kubectl get networkpolicies -n <namespace>部署相关Deployment信息列出命名空间中的所有Deployment：kubectl get deployments -n <namespace>查看一个Deployment详情：kubectl describe deployment <deployment-name> -n <namespace>查看滚动发布状态：kubectl rollout status deployment/<deployment-name> -n <namespace>查看滚动发布历史记录：kubectl rollout history deployment/<deployment-name> -n <namespace>作业和 CronJob列出命名空间中的所有作业：kubectl get jobs -n <namespace>查看一份工作详情：kubectl describe job <job-name> -n <namespace>列出命名空间中的所有 cron 作业：kubectl get cronjobs -n <namespace>查看一个 cron 作业详情：kubectl describe cronjob <cronjob-name> -n <namespace>StatefulSet信息列出命名空间中的所有 StatefulSet：kubectl get statefulsets -n <namespace>查看一个 StatefulSet详情：kubectl describe statefulset <statefulset-name> -n <namespace>ConfigMap 和Secret信息列出命名空间中的 ConfigMap：kubectl get configmaps -n <namespace>查看一个ConfigMap详情：kubectl describe configmap <configmap-name> -n <namespace>列出命名空间中的 Secret：kubectl get secrets -n <namespace>查看一个Secret详情：kubectl describe secret <secret-name> -n <namespace>命名空间信息查看一个命名空间详情：kubectl describe namespace <namespace-name>资源使用情况检查 pod 的资源使用情况：kubectl top pod <pod-name> -n <namespace>检查节点资源使用情况：kubectl top nodes持久卷和持久卷声明列出PV：kubectl get pv查看一个PV详情：kubectl describe pv <pv-name>列出命名空间中的 PVC：kubectl get pvc -n <namespace>查看PVC详情：kubectl describe pvc <pvc-name> -n <namespace>容量信息列出按容量排序的持久卷 (PV)：kubectl get pv --sort-by=.spec.capacity.storage查看PV回收策略：kubectl get pv <pv-name> -o=jsonpath='{.spec.persistentVolumeReclaimPolicy}'列出所有存储类别：kubectl get storageclasses存储卷快照列出存储卷快照：kubectl get volumesnapshot -n <namespace>查看存储卷快照详情：kubectl describe volumesnapshot <snapshot-name> -n <namespace>资源反序列化 反序列化并打印 Kubernetes 资源：kubectl get <resource-type> <resource-name> -n <namespace> -o=json网络信息显示命名空间中 Pod 的 IP 地址：kubectl get pods -n <namespace> -o custom-columns=POD:metadata.name,IP:status.podIP --no-headers列出命名空间中的所有网络策略：kubectl get networkpolicies -n <namespace>查看一个网络策略详情：kubectl describe networkpolicy <network-policy-name> -n <namespace>Ingress和服务网格列出命名空间中的所有Ingress：kubectl get ingress -n <namespace>查看一个Ingress详情：kubectl describe ingress <ingress-name> -n <namespace>列出命名空间中的所有 VirtualServices (Istio)：kubectl get virtualservices -n <namespace>查看一个 VirtualService (Istio)详情：kubectl describe virtualservice <virtualservice-name> -n <namespace>节点诊断获取特定节点上运行的 Pod 列表：kubectl get pods --field-selector spec.nodeName=<node-name> -n <namespace>Pod 网络故障排除运行网络诊断 Pod（例如 busybox）进行调试：kubectl run -it --rm --restart=Never --image=busybox net-debug-pod -- /bin/bash测试从 Pod 到特定端点的连接：kubectl exec -it <pod-name> -n <namespace> -- curl <endpoint-url>跟踪从一个 Pod 到另一个 Pod 的网络路径：kubectl exec -it <source-pod-name> -n <namespace> -- traceroute <destination-pod-ip>检查 Pod 的 DNS 解析：kubectl exec -it <pod-name> -n <namespace> -- nslookup <domain-name>资源使用情况资源配额和限制列出命名空间中的资源配额：kubectl get resourcequotas -n <namespace>查看一个资源配额详情：kubectl describe resourcequota <resource-quota-name> -n <namespace>自定义资源定义 (CRD)列出命名空间中的自定义资源：kubectl get <custom-resource-name> -n <namespace>查看自定义资源详情：kubectl describe <custom-resource-name> <custom-resource-instance-name> -n <namespace>使用这些命令时，请记住将<namespace>, <pod-name>, <service-name>, <deployment-name>, <statefulset-name>, <configmap-name>, <secret-name>, <namespace-name>, <pv-name>, <pvc-name>, <node-name>, <network-policy-name>, <resource-quota-name>, <custom-resource-name>, 和替换为你的特定值。<custom-resource-instance-name>这些命令应该可以帮助你诊断 Kubernetes 集群以及在其中运行的应用程序。资源伸缩和自动伸缩Deployment伸缩：kubectl scale deployment <deployment-name> --replicas=<replica-count> -n <namespace>设置Deployment的自动伸缩：kubectl autoscale deployment <deployment-name> --min=<min-pods> --max=<max-pods> --cpu-percent=<cpu-percent> -n <namespace>检查水平伸缩器状态：kubectl get hpa -n <namespace>配置和资源验证验证 Kubernetes YAML 文件而不应用它：kubectl apply --dry-run=client -f <yaml-file>验证 pod 的安全上下文和功能：kubectl auth can-i list pods --as=system:serviceaccount:<namespace>:<serviceaccount-name>安全和授权RBAC和安全性列出命名空间中的角色和角色绑定：kubectl get roles,rolebindings -n <namespace>查看角色或角色绑定详情：kubectl describe role <role-name> -n <namespace>Pod 安全策略 (PSP) 列出所有 Pod 安全策略（如果启用）：kubectl get psp事件：查看最近的集群事件：kubectl get events --sort-by=.metadata.creationTimestamp按特定命名空间过滤事件：kubectl get events -n <namespace>Pod 安全标准（PodSecurity 准入控制器） 列出 PodSecurityPolicy (PSP) 违规行为：kubectl get psp -A | grep -vE 'NAME|REVIEWED'服务帐户列出命名空间中的服务帐户：kubectl get serviceaccounts -n <namespace>查看一个服务帐户详情：kubectl describe serviceaccount <serviceaccount-name> -n <namespace>清空节点和解除封锁清空节点以进行维护：kubectl drain <node-name> --ignore-daemonsets解除对节点的封锁：kubectl uncordon <node-name>资源清理强制删除 pod（不推荐）：kubectl delete pod <pod-name> -n <namespace> --grace-period=0 --force节点故障排除检查节点情况：kubectl describe node <node-name> | grep Conditions -A5列出节点容量和可分配资源：kubectl describe node <node-name> | grep -E "Capacity|Allocatable"临时容器 运行临时调试容器：kubectl debug -it <pod-name> -n <namespace> --image=<debug-image> -- /bin/sh资源指标 获取 Pod 的 CPU 和内存使用情况：kubectl top pod -n <namespace>kuelet诊断 查看节点上的kubelet日志：kubectl logs -n kube-system kubelet-<node-name>使用Telepresence 进行高级调试 使用 Telepresence 调试 pod：telepresence --namespace <namespace> --swap-deployment <pod-name>Kubeconfig 和上下文列出可用的上下文：kubectl config get-contexts切换到不同的上下文：kubectl config use-context <context-name>Pod 中断预算 (PDB)列出命名空间中的所有 PDB：kubectl get pdb -n <namespace>查看一个PDB详情：kubectl describe pdb <pdb-name> -n <namespace>资源锁诊断（如果使用资源锁）列出服务的服务端点：kubectl get endpoints <service-name> -n <namespace>检查 Pod 中的 DNS 配置：kubectl exec -it <pod-name> -n <namespace> -- cat /etc/resolv.conf自定义指标（Prometheus、Grafana） 查询Prometheus指标：用于kubectl port-forward访问Prometheus和Grafana服务来查询自定义指标。节点条件 自定义查询输出：kubectl get nodes -o custom-columns=NODE:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status -l 'node-role.kubernetes.io/worker='审核日志 检索审核日志（如果启用）：检查 Kubernetes 审核日志配置以了解审核日志的位置。节点操作系统详细信息获取节点的操作系统信息：kubectl get node <node-name> -o jsonpath='{.status.nodeInfo.osImage}'这些命令应该涵盖 Kubernetes 中的各种诊断场景。确保将、、等占位符替换为集群和用例的实际值。其他诊断命令
journalctl是systemd日志系统的查询工具。当你某个服务启动失败或出现错误时，系统会提示你使用这个工具来排查。使用grep、awk这类工具对日志进行处理时，可能遇到下面的情况导致排查困难。日志文件太大，grep半天没反应想看某个时间段的日志，结果要写一堆复杂的正则表达式系统重启后，之前的日志找不到了想看某个服务的完整日志链路，结果要翻好几个不同的文件基础用法直接使用journalctl命令，会看到系统从启动开始的所有日志。不过这样看起来会很乱，而且信息量巨大。加个-f参数，就像tail -f一样，可以实时显示最新的日志。当怀疑某个服务有问题的时候，开着这个命令，然后去操作一下，立马就能看到相关的日志输出。按时间查看日志#查看今天的日志 journalctl --since today #或者看昨天的： journalctl --since yesterday #看某个时间段的 journalctl --since "2024-01-15 14:00:00" --until "2024-01-15 15:00:00"按服务查看日志#只看nginx服务的日志 journalctl -u nginx #实时监控某个服务： journalctl -u nginx -f #有时候一个服务重启了好几次，你想看它的历史记录： journalctl -u nginx --since "1 hour ago"进阶技巧按优先级过滤#只显示错误级别的日志 journalctl -p err查看内核日志journalctl -k该命令等同于dmesg，但是journalctl的输出格式更友好，而且可以结合其他参数使用。按进程ID查看 有时候你知道某个进程有问题，可以直接按PID查看：journalctl _PID=1234查看启动信息 想看系统启动过程中发生了什么：journalctl -b如果系统重启过多次，你想看上一次启动的日志：journalctl -b -1这个功能在排查系统启动异常时特别有用。高级功能JSON格式输出 有时候你需要程序化处理日志，可以用JSON格式：journalctl -u nginx -o json这样输出的每一行都是一个JSON对象，方便后续处理。查看磁盘使用情况 journal日志会占用磁盘空间，你可以查看当前使用情况：journalctl --disk-usage如果空间不够，可以清理旧日志：journalctl --vacuum-time=7d只保留最近7天的日志。导出日志 有时候需要把日志发给其他人分析：journalctl -u myapp --since today > app_logs.txt反向查看日志 从最新的日志开始看：journalctl -r这个在查看最近发生的问题时很有用。配置优化持久化存储 默认情况下，有些系统的journal日志是存储在内存中的，重启后就丢失了。要启用持久化存储：sudo mkdir -p /var/log/journal sudo systemd-tmpfiles --create --prefix /var/log/journal sudo systemctl restart systemd-journald限制日志大小 编辑/etc/systemd/journald.conf：SystemMaxUse=1G SystemMaxFileSize=100M这样可以避免日志占用太多磁盘空间。常见问题和解决方案日志查看权限问题 有时候普通用户看不到某些日志，需要加入systemd-journal组：sudo usermod -a -G systemd-journal username日志时间显示问题 如果时间显示不对，可能是时区设置问题：journalctl --utc使用UTC时间显示。性能问题 如果journalctl查询很慢，可能是因为日志文件太大。可以考虑：清理旧日志调整日志级别使用更精确的过滤条件一些小技巧# 查看最近的错误日志，按时间倒序 journalctl -p err -r --since "1 hour ago" # 查看某个用户的所有日志 journalctl _UID=1000 # 查看系统启动耗时 systemd-analyze blame
curl简介全称是"Client URL"，顾名思义就是一个URL客户端工具。它最大的特点就是支持的协议特别多，HTTP、HTTPS、FTP、FTPS、SCP、SFTP、LDAP等等，基本上你能想到的网络协议它都支持。curl测试API接口非常方便。比如说要测试一个REST API，用curl简直不要太方便：[root@webtest ~]# curl -X GET https://v2.jinrishici.com/token {"status":"success","data":"5w1dZp7lNh+NpR0Ws6OG6TGCqp/2UgMf"}这样就能快速看到接口返回的数据，比打开浏览器或者用Postman要快多了。curl还有个很牛的地方就是它的参数特别丰富，几乎可以模拟任何HTTP请求。想要发送POST请求？没问题：curl -X POST -H "Content-Type: application/json" -d '{"name":"张三","age":25}' https://api.example.com/users需要带认证信息？也很简单：curl -u username:password https://api.example.com/protected 或者用Bearer token： curl -H "Authorization: Bearer your_token_here" https://api.example.com/datawgetwget简介wgetwget的全称是"Web Get"，它主要是用来从网络上获取文件的。相比curl，wget更专注于下载这一件事，在下载方面它做得确实很出色。wget有个递归下载功能。有一次需要备份一个静态网站，用wget一条命令就搞定了：wget -r -np -k -L -p https://example.com/这条命令会把整个网站都下载下来，包括CSS、JS、图片等所有资源，而且还会自动调整链接，下载完直接就能在本地打开。wget还有个很实用的功能就是断点续传。下载大文件的时候网络断了不用担心，加个-c参数就能接着下载：wget -c https://example.com/bigfile.zip 这个功能在网络不稳定的时候简直是救命稻草。两者的主要区别在哪里？最大的区别就是设计理念不同。curl更像是一个瑞士军刀，什么都能干，但是每样都不是最专业的；wget就像是一个专业的下载工具，在下载这件事上做得特别精细。从使用场景来说，一般是这样选择的：需要测试API、发送复杂HTTP请求的时候用curl单纯下载文件，特别是大文件或者需要递归下载的时候用wget需要在脚本里处理HTTP响应数据的时候用curl需要镜像整个网站或者批量下载的时候用wgetcurl的高级用法说到curl的高级用法，那可真是太多了。我经常用到的几个技巧分享给大家：保存响应头信息有时候需要查看服务器返回的头信息，可以用-I参数：curl -I https://www.baidu.com或者既要响应体又要响应头：curl -i https://api.example.com/data 跟随重定向默认情况下curl不会跟随重定向，需要加-L参数：curl -L https://short.url/abc123 设置超时时间网络不好的时候设置个超时时间很有必要：curl --connect-timeout 10 --max-time 30 https://slow.server.com使用代理需要通过代理访问的时候：curl --proxy http://proxy.server:8080 https://example.com 上传文件curl还能上传文件，这个功能很多人不知道：curl -X POST -F "file=@/path/to/file.txt" https://upload.example.com保存和使用Cookie处理需要登录的网站时，Cookie管理很重要：#保存cookie curl -c cookies.txt -d "username=admin&password=123456" https://example.com/login # 使用cookie curl -b cookies.txt https://example.com/protectedwget的实用技巧wget虽然看起来简单，但是用好了也很强大。限制下载速度在服务器上下载大文件的时候，为了不影响其他服务，可以限制下载速度：wget --limit-rate=200k https://example.com/bigfile.zip后台下载下载大文件时可以放到后台运行：wget -b https://example.com/hugefile.iso下载进度会保存在wget-log文件里，可以用tail命令查看： tail -f wget-log批量下载有个URL列表文件的话，可以批量下载：wget -i urls.txturls.txt文件里每行一个URL就行。设置重试次数网络不稳定的时候可以设置重试：wget --tries=3 --waitretry=2 https://unstable.server.com/file.zip递归下载的高级选项递归下载网站的时候，有很多参数可以控制行为：wget -r -np -nd -A "*.pdf" -R "*.html" https://example.com/documents/这条命令会递归下载所有PDF文件，但是排除HTML文件，而且不创建目录结构。实际工作中的应用场景监控网站可用性写个简单的脚本监控网站是否正常：#!/bin/bash response=$(curl -s -o /dev/null -w "%{http_code}" https://mywebsite.com) if [ $response -eq 200 ]; then echo "网站正常" else echo "网站异常，状态码：$response" fi自动化部署脚本部署的时候经常需要下载最新的安装包：#!/bin/bash # 获取最新版本号 latest_version=$(curl -s https://api.github.com/repos/user/project/releases/latest | grep tag_name | cut -d '"' -f 4) # 下载最新版本 wget https://github.com/user/project/releases/download/${latest_version}/project-${latest_version}.tar.gz API接口测试 测试POST接口的时候，curl特别方便： # 测试用户注册接口 curl -X POST \ -H "Content-Type: application/json" \ -d '{ "username": "testuser", "email": "test@example.com", "password": "123456" }' \ https://api.example.com/register文件备份定期备份重要文件到远程服务器：#!/bin/bash # 打包文件 tar -czf backup-$(date +%Y%m%d).tar.gz /important/data/ # 上传到远程服务器 curl -T backup-$(date +%Y%m%d).tar.gz ftp://backup.server.com/backups/ --user username:password常见问题和解决方案用这两个工具的时候，经常会遇到一些问题，常见的几个：SSL证书问题有时候遇到自签名证书或者证书有问题的网站，可以跳过证书验证：# curl跳过证书验证 curl -k https://self-signed.example.com # wget跳过证书验证 wget --no-check-certificate https://self-signed.example.com/file.zip不过这样做有安全风险，生产环境要谨慎使用。中文文件名乱码下载中文文件名的文件时可能会乱码，可以设置编码：wget --restrict-file-names=nocontrol https://example.com/中文文件.zip大文件下载超时下载大文件时经常会超时，可以调整超时设置：# curl设置超时 curl --connect-timeout 30 --max-time 3600 -O https://example.com/bigfile.zip # wget设置超时 wget --timeout=30 --read-timeout=3600 https://example.com/bigfile.zip
资源估算很关键，既关系到成本控制，也影响业务稳定性。CPU资源估算公式和方法CPU的估算相对来说比较复杂，因为不同类型的应用对CPU的需求差别很大。我总结了一套比较实用的计算方法。基础CPU需求计算公式CPU核心数 = (并发用户数 × 单用户CPU消耗 × 安全系数) / CPU利用率目标关键参数说明并发用户数：同时在线并产生请求的用户数单用户CPU消耗：每个用户请求平均消耗的CPU时间安全系数：通常取1.5-2.0CPU利用率目标：建议控制在70%以下不同应用类型的CPU需求参考表应用类型单用户CPU消耗(ms)推荐配置(1000并发)备注静态网站5-102-4核主要是文件读取简单Web应用20-504-8核基础CRUD操作复杂业务系统100-2008-16核复杂查询和计算实时计算200-50016-32核大量数据处理图像/视频处理500-100032核以上CPU密集型任务实际计算示例假设我们有一个电商网站：预期并发用户：2000人应用类型：复杂业务系统单用户CPU消耗：150ms安全系数：1.8CPU利用率目标：70%计算过程：CPU核心数 = (2000 × 0.15 × 1.8) / 0.7 = 771 / 0.7 ≈ 11核 建议配置：12-16核CPU内存需求精确计算内存的估算相对简单一些，但也有一套科学的计算方法。内存需求计算公式总内存需求 = 系统基础内存 + 应用内存 + 连接内存 + 缓存内存 + 预留内存各组件内存需求详细表格组件类型基础占用计算公式说明操作系统1-2GB固定值Linux系统基础占用Java应用512MB-2GB堆内存 + 非堆内存JVM参数配置Node.js应用100-500MB根据代码复杂度相对轻量Python应用50-200MB根据框架和库Django/Flask差异较大Go应用10-100MB编译型语言内存占用很小MySQL128MB起InnoDB缓冲池大小建议总内存的70%Redis根据数据量数据大小 × 1.2包含持久化开销Nginx2-10MB连接数 × 2KB反向代理占用连接内存计算公式连接内存 = 最大连接数 × 单连接内存占用不同服务的单连接内存占用：HTTP连接：2-8KB数据库连接：1-4MBWebSocket连接：4-16KB实际内存计算案例以电商网站为例：并发用户：2000人技术栈：Java + MySQL + Redis数据量：用户数据50万条，商品数据10万条组件计算过程内存需求操作系统固定2GBJava应用堆内存4GB + 非堆1GB5GBHTTP连接2000 × 8KB16MBMySQL数据量约2GB，缓冲池设置8GBRedis热点数据500MB × 1.2600MB预留空间总量的20%3GB总计 约19GB建议配置：24GB或32GB内存存储空间规划计算存储的估算看起来简单，实际上坑也不少。我整理了一套比较完整的计算方法。存储需求计算公式总存储需求 = 业务数据 + 日志文件 + 备份空间 + 系统文件 + 增长预留不同数据类型的存储需求表数据类型单条记录大小增长系数备注用户基础信息1-2KB1.5包含索引开销订单记录2-5KB2.0关联数据较多商品信息5-20KB1.8包含图片路径等日志记录200-500B1.2压缩后存储图片文件100KB-2MB1.0原始大小视频文件10MB-1GB1.0原始大小日志文件存储计算日志存储需求 = 日请求量 × 单条日志大小 × 保留天数日志类型单条大小保留期压缩比访问日志300-500B30天0.3应用日志200-800B7天0.4错误日志500-2KB90天0.5数据库日志100-300B7天0.3存储计算实例电商网站存储需求计算：数据类型数量单条大小小计增长系数最终需求用户数据50万1.5KB750MB1.51.1GB商品数据10万15KB1.5GB1.82.7GB订单数据100万3KB3GB2.06GB访问日志100万/天400B400MB/天30天12GB应用日志50万/天600B300MB/天7天2.1GB图片文件20万张500KB100GB1.0100GB备份空间业务数据×3 33GB系统文件固定 20GB 20GB总计 约177GB建议配置：250GB SSD + 500GB HDD的组合网络带宽需求计算网络带宽经常被忽视，但其实很重要。带宽需求计算公式所需带宽(Mbps) = 并发用户数 × 平均页面大小(MB) × 8 × 安全系数 / 页面加载时间(秒)不同业务场景的带宽需求表业务类型平均页面大小目标加载时间安全系数单用户带宽需求企业官网2-5MB3秒1.520-42Kbps电商平台3-8MB2秒2.048-128Kbps视频网站10-50MB5秒1.829-144Kbps直播平台持续流量实时2.52-8Mbps游戏平台小数据包<100ms3.0100-500Kbps带宽计算实例电商网站带宽需求：并发用户：2000人平均页面大小：5MB目标加载时间：2秒安全系数：2.0计算过程：所需带宽 = 2000 × 5 × 8 × 2.0 / 2 = 40,000 Mbps = 40 Gbps优化建议：使用CDN减少源站压力图片压缩和懒加载静态资源缓存优化后实际需求可能只需要200-500Mbps数据库资源专项计算数据库的资源需求和应用服务器不太一样，需要单独考虑。数据库CPU计算公式数据库CPU需求 = (QPS × 平均查询时间 × CPU使用率) / 1000不同数据库的资源需求对比表数据库类型CPU效率内存需求存储IO适用场景MySQL中等中等高通用OLTPPostgreSQL高中等中等复杂查询MongoDB中等高中等文档存储Redis高高低缓存/会话Elasticsearch低高高全文搜索数据库内存分配建议表组件MySQLPostgreSQLMongoDB缓冲池70-80%25%50%连接缓存5-10%10%10%查询缓存5-10%25%20%系统预留10-20%40%20%数据库性能基准测试表配置MySQL QPSPostgreSQL QPSMongoDB QPSRedis QPS2核4GB1,000-2,000800-1,5002,000-4,00050,000-80,0004核8GB3,000-5,0002,500-4,0006,000-10,000100,000-150,0008核16GB8,000-12,0006,000-10,00015,000-25,000200,000-300,00016核32GB15,000-25,00012,000-20,00030,000-50,000400,000-600,000注：QPS数据基于标准OLTP场景，实际性能会因查询复杂度而变化容器化环境资源计算现在容器化部署越来越流行，资源计算方式也有所不同。容器资源计算公式容器总资源 = Σ(单容器资源 × 副本数 × 资源超分比)Kubernetes资源配置参考表服务类型CPU RequestCPU LimitMemory RequestMemory Limit副本数建议Web前端100m500m128Mi512Mi3-5API服务200m1000m256Mi1Gi3-10数据库1000m2000m2Gi4Gi1-3缓存服务100m500m512Mi2Gi2-3消息队列200m800m512Mi2Gi2-3容器资源超分配比例表资源类型开发环境测试环境生产环境说明CPU4:12:11.5:1超分比例内存2:11.5:11.2:1相对保守存储3:12:11:1生产不超分ROI计算公式投资回报率 = (收益增长 - 成本增长) / 成本增长 × 100%示例：通过性能优化，响应时间从3秒降到1秒，转化率提升20%，月收入增加10万，而优化成本只有2万，那么ROI就是400%监控指标和告警阈值设置监控系统一定要做好，这是运维的眼睛。我总结了一套完整的监控指标体系。核心监控指标阈值表指标类型正常范围警告阈值严重阈值监控频率CPU使用率<60%70%85%1分钟内存使用率<70%80%90%1分钟磁盘使用率<70%80%90%5分钟磁盘IO等待<10%20%40%1分钟网络带宽<60%70%85%1分钟响应时间<500ms1s3s实时错误率<0.1%1%5%实时连接数<1000根据配置根据配置1分钟应用层监控指标表指标Java应用Node.js应用Python应用Go应用堆内存使用<80%N/A<80%<80%GC频率<10次/分钟N/A<5次/分钟<1次/分钟线程数<500N/A<200<1000连接池<80%<80%<80%<80%性能测试和容量规划光有理论计算还不够，性能测试是验证估算准确性的重要手段。性能测试场景设计表测试类型并发用户数持续时间目标指标测试目的基准测试10-5010分钟建立基线了解基础性能负载测试预期并发30分钟响应时间<1s验证正常负载压力测试1.5×预期15分钟系统不崩溃找到性能瓶颈峰值测试3×预期5分钟快速恢复验证突发处理稳定性测试0.8×预期24小时无内存泄漏长期稳定性性能测试工具对比表工具适用场景并发能力学习成本报告质量JMeter通用Web测试中等中等好wrk简单HTTP测试高低一般LoadRunner企业级测试很高高很好ArtilleryNode.js友好中等低好Gatling高性能测试很高中等很好实际案例：电商平台完整资源规划下面用一个完整的案例来演示整个资源估算过程。业务需求分析某电商平台预期指标：注册用户：100万日活用户：10万峰值并发：5000人商品数量：50万日订单量：1万单图片文件：100万张详细资源计算过程1. Web服务器资源计算CPU需求：并发用户：5000人单用户CPU消耗：100ms（复杂业务）安全系数：1.8CPU利用率目标：70%CPU核心数 = (5000 × 0.1 × 1.8) / 0.7 = 1286核 考虑到单机限制，建议配置：8台 × 16核 = 128核内存需求：组件计算需求系统基础8台 × 2GB16GBJava应用8台 × 8GB64GB连接内存5000 × 8KB40MB预留20%16GB总计 96GB2. 数据库服务器资源计算预估QPS：查询QPS：2000写入QPS：500总QPS：2500根据性能基准表，需要8核16GB配置，考虑到安全系数，建议配置：16核32GB3. 缓存服务器资源计算Redis内存需求：用户会话：10万 × 2KB = 200MB商品缓存：5万 × 10KB = 500MB查询缓存：预估1GB总计：1.7GB × 1.5 = 2.6GB建议配置：4核8GB4. 存储需求计算数据类型计算过程存储需求用户数据100万 × 2KB × 1.53GB商品数据50万 × 20KB × 1.818GB订单数据365万 × 5KB × 2.036GB图片文件100万 × 800KB800GB日志文件计算得出50GB备份空间业务数据 × 3171GB总计 1078GB5. 带宽需求计算使用CDN优化后：动态内容：5000用户 × 100KB × 8 / 2秒 = 2Gbps考虑安全系数：2Gbps × 1.5 = 3Gbps实际配置：500Mbps（CDN分担大部分流量）最终配置方案服务器类型配置数量月成本Web服务器16核32GB8台10.8万数据库服务器16核32GB SSD2台3.2万缓存服务器4核8GB2台0.8万负载均衡标准配置2台0.4万CDN服务500GB流量-0.5万总计 15.7万/月动态扩容策略静态配置往往无法应对业务的快速变化，动态扩容策略很重要。自动扩容触发条件表指标扩容阈值缩容阈值冷却时间扩容步长CPU使用率>70%<30%5分钟+1台内存使用率>80%<40%5分钟+1台响应时间>1秒<300ms3分钟+2台队列长度>100<102分钟+1台错误率>1%<0.1%10分钟+2台扩容成本效益分析扩容方式响应时间成本增加适用场景垂直扩容5-10分钟50-100%短期突发水平扩容2-5分钟20-50%持续增长预热扩容即时10-30%可预期峰值写在最后服务器资源估算确实是个技术活，需要综合考虑业务需求、技术架构、成本预算等多个因素。通过这些公式和表格，可以更科学地进行资源规划：核心要点回顾CPU估算：基于并发用户数和单用户消耗计算内存估算：分组件计算，预留20%安全空间存储估算：考虑数据增长和备份需求带宽估算：结合CDN优化，避免过度配置成本控制：对比不同方案，选择最优性价比实用建议基于实际业务需求估算，不要拍脑袋决定预留适当的扩容空间，但不要过度设计重视监控和性能测试，数据说话根据实际运行情况及时调整优化考虑动态扩容，应对业务变化最重要的是，要有持续优化的意识。系统上线只是开始，后续的监控、调优、扩容才是重头戏。技术在发展，业务在变化，资源配置也要跟着调整。没有完美的架构，只有合适的架构。资源估算也是一样，关键是要找到性能、成本、可靠性之间的平衡点。