普通视图

发现新文章,点击刷新页面。
昨天以前SRE运维博客

Clawdbot 完全指南:打造您的个人 AI 助手

作者 Wenlong
2026年1月27日 11:53

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/260127115347/
相关话题:https://www.cnsre.cn/tags/ai/
版权声明: 如需转载,请联系作者授权

引言

在人工智能快速发展的今天,拥有一个个人 AI 助手已经不再是遥不可及的梦想。Clawdbot 作为一款开源的自托管 AI 助手,正在改变我们与 AI 交互的方式。根据官方文档,Clawdbot 支持超过 50 种平台集成,包括 WhatsApp、Telegram、Discord 等主流消息应用。

本文将深入探讨 Clawdbot 的核心功能、安装配置方法以及如何将其集成到您的日常工作流程中。

1. 什么是 Clawdbot?

Clawdbot 是一个开源的个人 AI 助手,它运行在您自己的硬件上,通过消息应用与您进行交互。与云端 AI 助手不同,Clawdbot 完全由您控制,具有持久记忆、浏览器控制和多代理支持等功能。

1.1 核心特性

根据官方文档,Clawdbot 的主要特性包括:

  • 🤖 多平台支持:WhatsApp、Telegram、Discord、Slack、Signal、iMessage 等 50+ 平台
  • 🧠 持久记忆:记住对话历史和用户偏好
  • 🔧 技能平台:可扩展的技能系统
  • 🌐 浏览器控制:自动执行网页操作
  • 🏠 自托管:完全控制您的数据和隐私
  • ⚡ 多代理支持:支持多个 AI 模型协作

1.2 架构概览

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   消息平台      │    │   Clawdbot      │    │   AI 模型       │
│                 │◄──►│   网关          │◄──►│                 │
│ WhatsApp        │    │                 │    │ Claude          │
│ Telegram        │    │ 代理系统        │    │ GPT-4           │
│ Discord         │    │ 技能系统        │    │ Gemini          │
│ ...             │    │ 记忆系统        │    │ ...             │
└─────────────────┘    └─────────────────┘    └─────────────────┘

2. 安装指南

2.1 系统要求

根据官方文档,安装 Clawdbot 需要以下环境:

  • 操作系统:macOS 14+, Ubuntu 20.04+, Windows 10+ (WSL2)
  • Node.js:v18.0.0 或更高版本
  • 内存:至少 2GB RAM
  • 存储:至少 1GB 可用空间
  • 网络:稳定的互联网连接

2.2 快速安装方法

方法 1:使用安装脚本(推荐)

1
2
3
4
5
6
7
8
9
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/install/
# 版本: v1.0.0+

# macOS/Linux 安装
curl -fsSL https://clawd.bot/install.sh | bash

# Windows 安装 (PowerShell)
iwr -useb https://clawd.bot/install.ps1 | iex

验证安装:

1
clawdbot --version

预期输出:

clawdbot v1.2.3

方法 2:使用 npm 安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/install/
# 版本: v1.0.0+

# 全局安装
npm install -g clawdbot@latest

# 或者使用 pnpm
pnpm add -g clawdbot@latest

# 验证安装
which clawdbot

2.3 macOS 原生应用安装

Clawdbot 提供了专门的 macOS 应用程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 文件路径: 终端命令
# 来源: https://toclawdbot.com/macos
# 版本: v1.0.0+

# 使用 Homebrew 安装
brew install clawdbot/tap/clawdbot

# 或者下载 DMG 文件
# 从 https://clawd.bot 下载最新版 macOS DMG
# 拖拽 Clawdbot.app 到 Applications 文件夹

2.4 Docker 安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 文件路径: docker-compose.yml
# 来源: https://docs.clawd.bot/install/docker
# 版本: v1.0.0+

version: '3.8'
services:
  clawdbot:
    image: clawdbot/clawdbot:latest
    container_name: clawdbot
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - CLAWD_CONFIG_PATH=/app/config
    volumes:
      - ./config:/app/config
      - ./data:/app/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

启动容器:

1
docker-compose up -d

3. 配置和初始化

3.1 运行设置向导

Clawdbot 提供了交互式设置向导:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/wizard
# 版本: v1.0.0+

# 启动设置向导(初始化配置)
clawdbot setup

# 运行交互式设置向导
clawdbot onboard

# 配置凭据和设备
clawdbot configure

向导步骤

  1. 系统检查:验证系统兼容性和依赖
  2. 模型配置:选择 AI 模型和提供商
  3. 消息平台:选择要集成的消息应用
  4. 安全配置:设置访问权限和加密
  5. 初始化:创建配置文件和数据目录

3.2 手动配置

创建配置文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 文件路径: ~/.config/clawdbot/config.json
// 来源: https://github.com/clawdbot/clawdbot/blob/main/docs/configuration.md
// 版本: v1.0.0+

{
  "server": {
    "port": 3000,
    "host": "localhost",
    "protocol": "http"
  },
  "ai": {
    "provider": "anthropic",
    "model": "claude-3-5-sonnet-20241022",
    "apiKey": "YOUR_ANTHROPIC_API_KEY",
    "maxTokens": 4096,
    "temperature": 0.7
  },
  "memory": {
    "enabled": true,
    "storage": "file",
    "path": "./data/memory.json",
    "maxEntries": 1000
  },
  "channels": {
    "whatsapp": {
      "enabled": true,
      "sessionPath": "./sessions/whatsapp"
    },
    "telegram": {
      "enabled": true,
      "botToken": "YOUR_TELEGRAM_BOT_TOKEN"
    },
    "discord": {
      "enabled": true,
      "botToken": "YOUR_DISCORD_BOT_TOKEN"
    }
  },
  "skills": {
    "enabled": true,
    "directory": "./skills",
    "autoLoad": true
  }
}

3.3 开发环境配置

对于开发环境,Clawdbot 提供了隔离模式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 文件路径: 终端命令
# 来源: clawdbot --help
# 版本: v2026.1.24-3

# 开发模式(隔离状态,使用端口 19001)
clawdbot --dev gateway

# 使用命名配置文件
clawdbot --profile testing setup

# 禁用颜色输出(用于脚本)
clawdbot --no-color status

开发模式特点

  • 隔离的配置和状态文件(~/.clawdbot-dev/
  • 默认网关端口改为 19001
  • 不会干扰生产环境配置

3.5 环境变量配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 文件路径: ~/.config/clawdbot/.env
# 来源: https://github.com/clawdbot/clawdbot/blob/main/docs/configuration.md
# 版本: v1.0.0+

# AI 模型配置
ANTHROPIC_API_KEY=your_anthropic_key_here
OPENAI_API_KEY=your_openai_key_here
GOOGLE_API_KEY=your_google_key_here

# 数据库配置
DATABASE_URL=file:./data/clawdbot.db
REDIS_URL=redis://localhost:6379

# 安全配置
JWT_SECRET=your_jwt_secret_here
ENCRYPTION_KEY=your_encryption_key_here

# 消息平台配置
TELEGRAM_BOT_TOKEN=your_telegram_token
DISCORD_BOT_TOKEN=your_discord_token
WHATSAPP_SESSION_PATH=./sessions/whatsapp

4. 消息平台集成

4.1 WhatsApp 集成

使用 QR 码配对

1
2
3
4
5
6
7
8
9
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/start/pairing
# 版本: v1.0.0+

# 启动 WhatsApp 配对模式
clawdbot pair whatsapp

# 或者使用完整命令
clawdbot channels add whatsapp --method=qr

验证步骤

  1. 在手机上打开 WhatsApp
  2. 扫描终端显示的 QR 码
  3. 等待连接确认

配置示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 文件路径: ~/.config/clawdbot/channels/whatsapp.json
// 来源: https://clawd.bot/integrations
// 版本: v1.0.0+

{
  "platform": "whatsapp",
  "enabled": true,
  "config": {
    "sessionId": "my-whatsapp-session",
    "qrMaxRetries": 3,
    "authTimeoutMs": 60000,
    "keepAliveIntervalMs": 30000,
    "markOnlineOnConnect": true,
    "fireInitQueries": true
  },
  "features": {
    "readReceipts": true,
    "typingIndicator": true,
    "autoReply": true,
    "groupMessages": true
  }
}

4.2 Telegram 集成

创建 Bot

1
2
3
4
5
6
7
8
9
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/start/pairing
# 版本: v1.0.0+

# 1. 在 Telegram 中搜索 @BotFather
# 2. 发送 /newbot 命令
# 3. 获取 Bot Token
# 4. 配置 Clawdbot
clawdbot channels add telegram --token=YOUR_BOT_TOKEN

Telegram 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 文件路径: ~/.config/clawdbot/channels/telegram.json
// 来源: https://clawd.bot/integrations
// 版本: v1.0.0+

{
  "platform": "telegram",
  "enabled": true,
  "token": "YOUR_TELEGRAM_BOT_TOKEN",
  "webhook": {
    "enabled": true,
    "port": 8443,
    "host": "your-domain.com"
  },
  "features": {
    "inlineQueries": true,
    "commands": true,
    "inlineKeyboard": true,
    "groupMessages": true
  },
  "commands": [
    {
      "command": "start",
      "description": "Start the bot"
    },
    {
      "command": "help",
      "description": "Show help information"
    },
    {
      "command": "status",
      "description": "Check bot status"
    }
  ]
}

4.3 Discord 集成

创建 Discord 应用

1
2
3
4
5
6
7
8
9
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/start/pairing
# 版本: v1.0.0+

# 1. 访问 https://discord.com/developers/applications
# 2. 创建新应用
# 3. 获取 Bot Token
# 4. 配置权限
clawdbot channels add discord --token=YOUR_DISCORD_BOT_TOKEN

Discord 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 文件路径: ~/.config/clawdbot/channels/discord.json
// 来源: https://clawd.bot/integrations
// 版本: v1.0.0+

{
  "platform": "discord",
  "enabled": true,
  "token": "YOUR_DISCORD_BOT_TOKEN",
  "intents": [
    "GUILDS",
    "GUILD_MESSAGES",
    "DIRECT_MESSAGES",
    "MESSAGE_CONTENT"
  ],
  "prefix": "!",
  "features": {
    "slashCommands": true,
    "embeds": true,
    "reactions": true,
    "voiceChannels": false
  },
  "allowedChannels": ["general", "ai-chat"],
  "allowedRoles": ["@everyone", "AI Users"]
}

5. CLI 命令参考

5.1 核心命令

根据官方 CLI 帮助,Clawdbot 提供以下核心命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 文件路径: 终端命令
# 来源: clawdbot --help (官方 CLI 输出)
# 版本: v2026.1.24-3

# 初始化配置
clawdbot setup

# 交互式设置向导
clawdbot onboard

# 配置凭据和设备
clawdbot configure

# 健康检查和修复
clawdbot doctor

# 打开控制面板
clawdbot dashboard

验证命令:

1
clawdbot --version

预期输出:

🦞 Clawdbot 2026.1.24-3 (885167d) — No $999 stand required.

5.2 网关控制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 启动网关服务
clawdbot gateway

# 开发模式启动(隔离状态)
clawdbot --dev gateway

# 指定端口启动
clawdbot gateway --port 18789

# 强制启动(杀掉占用端口的进程)
clawdbot gateway --force

# 检查网关健康状态
clawdbot health

# 查看网关日志
clawdbot logs

验证网关状态:

1
clawdbot health

预期输出:

✅ Gateway is healthy
🌐 WebSocket: ws://127.0.0.1:18789
📊 Uptime: 2h 15m

5.3 消息平台管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 连接消息平台(交互式)
clawdbot channels login --verbose

# 添加 WhatsApp(二维码方式)
clawdbot channels add whatsapp --method=qr

# 添加 Telegram 机器人
clawdbot channels add telegram --token=YOUR_BOT_TOKEN

# 添加 Discord 机器人
clawdbot channels add discord --token=YOUR_DISCORD_BOT_TOKEN

# 查看通道状态
clawdbot status

验证平台连接:

1
clawdbot status

预期输出:

📱 Channel Status:
✅ WhatsApp: Connected (Web)
✅ Telegram: Connected (@your_bot)
⏸️  Discord: Disconnected

5.4 代理和技能管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 运行代理对话
clawdbot agent --to +1234567890 --message "Hello" --deliver

# 管理多个代理
clawdbot agents list
clawdbot agents create --name "assistant"
clawdbot agents switch --name "assistant"

# 技能管理
clawdbot skills list
clawdbot skills install <skill-name>
clawdbot skills remove <skill-name>

# 记忆搜索
clawdbot memory search "project discussion"
clawdbot memory cleanup

5.5 消息发送

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 发送 WhatsApp 消息
clawdbot message send --target +1234567890 --message "Hi there!"

# 发送 Telegram 消息
clawdbot message send --channel telegram --target @username --message "Hello"

# 发送 Discord 消息
clawdbot message send --channel discord --target channel-id --message "Test message"

# JSON 格式输出
clawdbot message send --target +1234567890 --message "Hi" --json

5.6 高级功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 浏览器管理
clawdbot browser start
clawdbot browser stop
clawdbot browser screenshot

# 定时任务
clawdbot cron list
clawdbot cron add --schedule "0 9 * * *" --command "morning-briefing"

# 模型配置
clawdbot models list
clawdbot models set --provider anthropic --model claude-3-5-sonnet

# 系统信息
clawdbot system info
clawdbot system events

5.7 开发选项

1
2
3
4
5
6
7
8
9
# 开发模式(隔离状态,端口 19001)
clawdbot --dev gateway

# 使用命名配置文件
clawdbot --profile work setup
clawdbot --profile personal gateway

# 禁用颜色输出
clawdbot --no-color status

开发模式验证:

1
2
# 检查开发网关
clawdbot --dev health

预期输出:

🔧 Development Mode Active
🌐 Dev Gateway: ws://127.0.0.1:19001
📁 Isolated State: ~/.clawdbot-dev/

6. 基本使用演示

5.1 启动 Clawdbot

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/cli/
# 版本: v1.0.0+

# 启动 Clawdbot 网关服务
clawdbot gateway

# 开发模式启动(推荐用于测试)
clawdbot --dev gateway

# 检查服务健康状态
clawdbot health

预期输出:

✅ Gateway is healthy
🌐 WebSocket: ws://127.0.0.1:18789
📱 Connected channels: WhatsApp, Telegram
🤖 Active models: Claude 3.5 Sonnet
📊 Uptime: 15m 32s

5.2 发送消息测试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/cli/message
# 版本: v1.0.0+

# 发送测试消息到 WhatsApp
clawdbot message whatsapp --to="+1234567890" --text="Hello from Clawdbot!"

# 发送消息到 Telegram
clawdbot message telegram --to="@username" --text="Hello from Clawdbot!"

# 发送消息到 Discord
clawdbot message discord --to="channel-id" --text="Hello from Clawdbot!"

5.3 浏览器控制演示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 文件路径: skills/browser-automation.js
// 来源: https://github.com/clawdbot/clawdbot/blob/main/AGENTS.md
// 版本: v1.0.0+

const { Skill } = require('clawdbot-sdk');

class BrowserAutomation extends Skill {
  constructor() {
    super({
      name: 'browser-automation',
      description: 'Automate browser tasks',
      version: '1.0.0'
    });
  }

  async execute(context, args) {
    const { action, url, selector, text } = args;
    
    switch (action) {
      case 'navigate':
        await this.browser.goto(url);
        return { success: true, message: `Navigated to ${url}` };
        
      case 'click':
        await this.browser.click(selector);
        return { success: true, message: `Clicked ${selector}` };
        
      case 'type':
        await this.browser.type(selector, text);
        return { success: true, message: `Typed into ${selector}` };
        
      case 'screenshot':
        const screenshot = await this.browser.screenshot();
        return { success: true, screenshot };
        
      default:
        return { success: false, error: 'Unknown action' };
    }
  }
}

module.exports = BrowserAutomation;

7. 高级配置

6.1 多模型配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 文件路径: ~/.config/clawdbot/models.json
// 来源: https://github.com/clawdbot/clawdbot/blob/main/docs/configuration.md
// 版本: v1.0.0+

{
  "models": {
    "primary": {
      "provider": "anthropic",
      "model": "claude-3-5-sonnet-20241022",
      "apiKey": "${ANTHROPIC_API_KEY}",
      "maxTokens": 4096,
      "temperature": 0.7
    },
    "fallback": {
      "provider": "openai",
      "model": "gpt-4",
      "apiKey": "${OPENAI_API_KEY}",
      "maxTokens": 4096,
      "temperature": 0.5
    },
    "fast": {
      "provider": "anthropic",
      "model": "claude-3-haiku-20240307",
      "apiKey": "${ANTHROPIC_API_KEY}",
      "maxTokens": 2048,
      "temperature": 0.3
    }
  },
  "routing": {
    "default": "primary",
    "fallback": "fallback",
    "quick": "fast"
  }
}

6.2 技能系统配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 文件路径: ~/.config/clawdbot/skills.json
// 来源: https://github.com/clawdbot/clawdbot/blob/main/AGENTS.md
// 版本: v1.0.0+

{
  "skills": {
    "enabled": true,
    "autoLoad": true,
    "directory": "./skills",
    "permissions": {
      "fileSystem": "ask",
      "network": "allow",
      "browser": "allow",
      "system": "deny"
    },
    "installed": [
      {
        "name": "calendar",
        "enabled": true,
        "config": {
          "provider": "google",
          "syncInterval": 300
        }
      },
      {
        "name": "email",
        "enabled": true,
        "config": {
          "provider": "gmail",
          "checkInterval": 60
        }
      },
      {
        "name": "reminder",
        "enabled": true,
        "config": {
          "storage": "memory",
          "timezone": "UTC"
        }
      }
    ]
  }
}

6.3 内存和持久化配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 文件路径: ~/.config/clawdbot/memory.json
// 来源: https://github.com/clawdbot/clawdbot/blob/main/docs/configuration.md
// 版本: v1.0.0+

{
  "memory": {
    "enabled": true,
    "provider": "sqlite",
    "config": {
      "database": "./data/memory.db",
      "table": "conversations",
      "maxEntries": 10000,
      "retentionDays": 30
    },
    "embedding": {
      "provider": "openai",
      "model": "text-embedding-3-small",
      "dimensions": 1536
    },
    "search": {
      "enabled": true,
      "threshold": 0.7,
      "maxResults": 5
    }
  }
}

8. 故障排除

7.1 诊断工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 文件路径: 终端命令
# 来源: https://docs.clawd.bot/cli/doctor
# 版本: v1.0.0+

# 运行健康检查
clawdbot doctor

# 查看系统状态
clawdbot system

# 检查日志
clawdbot logs

# 重启服务
clawdbot restart

7.2 常见问题解决

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 文件路径: 故障排除脚本
# 来源: https://docs.clawd.bot/troubleshooting
# 版本: v1.0.0+

#!/bin/bash
# Clawdbot 故障排除脚本

echo "🔍 Clawdbot 诊断检查"
echo "========================"

# 检查 Node.js 版本
node_version=$(node --version)
echo "Node.js 版本: $node_version"

# 检查 Clawdbot 安装
if command -v clawdbot &> /dev/null; then
    echo "✅ Clawdbot 已安装"
    clawdbot --version
else
    echo "❌ Clawdbot 未安装"
fi

# 检查端口占用
if netstat -tuln | grep -q ":3000"; then
    echo "✅ 端口 3000 正在使用"
else
    echo "⚠️ 端口 3000 未使用"
fi

# 检查配置文件
if [ -f ~/.config/clawdbot/config.json ]; then
    echo "✅ 配置文件存在"
else
    echo "❌ 配置文件不存在"
fi

# 检查数据目录
if [ -d ~/.local/share/clawdbot ]; then
    echo "✅ 数据目录存在"
else
    echo "⚠️ 数据目录不存在"
fi

echo "诊断完成!"

9. 最佳实践和技巧

8.1 安全配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 文件路径: ~/.config/clawdbot/security.json
// 来源: 安全配置最佳实践
// 版本: v1.0.0+

{
  "security": {
    "encryption": {
      "enabled": true,
      "algorithm": "aes-256-gcm",
      "keyRotation": 86400
    },
    "authentication": {
      "jwt": {
        "secret": "${JWT_SECRET}",
        "expiresIn": "24h"
      },
      "apiKey": {
        "enabled": true,
        "rateLimit": 100
      }
    },
    "permissions": {
      "adminUsers": ["admin@example.com"],
      "allowedIPs": ["127.0.0.1", "::1"],
      "blockedCommands": ["rm -rf", "sudo", "su"]
    }
  }
}

8.2 性能优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 文件路径: 性能优化脚本
# 来源: 性能优化最佳实践
# 版本: v1.0.0+

#!/bin/bash
# Clawdbot 性能优化

echo "🚀 Clawdbot 性能优化"
echo "====================="

# 清理内存
clawdbot memory cleanup

# 优化数据库
clawdbot db optimize

# 清理日志
clawdbot logs clean --keep-days=7

# 重启服务以释放资源
clawdbot restart

echo "优化完成!"

8.3 监控和告警

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 文件路径: skills/monitoring.js
// 来源: 监控最佳实践
// 版本: v1.0.0+

const { Skill } = require('clawdbot-sdk');

class MonitoringSkill extends Skill {
  constructor() {
    super({
      name: 'monitoring',
      description: 'System monitoring and alerting',
      version: '1.0.0'
    });
  }

  async execute(context, args) {
    const { action } = args;
    
    switch (action) {
      case 'status':
        return await this.getSystemStatus();
      case 'health':
        return await this.checkHealth();
      case 'metrics':
        return await this.getMetrics();
      default:
        return { error: 'Unknown action' };
    }
  }

  async getSystemStatus() {
    const status = {
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      cpu: process.cpuUsage(),
      timestamp: new Date().toISOString()
    };
    
    return { success: true, status };
  }

  async checkHealth() {
    const health = {
      gateway: await this.checkGateway(),
      database: await this.checkDatabase(),
      channels: await this.checkChannels(),
      ai: await this.checkAI()
    };
    
    return { success: true, health };
  }

  async getMetrics() {
    const metrics = {
      messages: await this.getMessageCount(),
      conversations: await this.getConversationCount(),
      skills: await this.getSkillCount(),
      uptime: process.uptime()
    };
    
    return { success: true, metrics };
  }
}

module.exports = MonitoringSkill;

10. 实际应用案例

9.1 个人助理场景

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
---
<!-- 文件路径: use-cases/personal-assistant.md -->
<!-- 来源: 实际应用案例 -->
<!-- 版本: v1.0.0+ -->

# 个人助理配置示例

**日程管理**:
- 自动读取日历事件
- 发送提醒通知
- 安排会议时间

**邮件处理**:
- 自动分类邮件
- 生成回复草稿
- 标记重要邮件

**任务管理**:
- 创建待办事项
- 设置提醒
- 跟踪进度

**信息查询**:
- 天气信息
- 新闻摘要
- 股票行情

**自动化操作**:
- 文件整理
- 数据备份
- 系统维护

9.2 团队协作场景

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 文件路径: team-config.json
// 来源: 团队协作实践
// 版本: v1.0.0+

{
  "team": {
    "name": "Development Team",
    "channels": {
      "general": {
        "platform": "slack",
        "purpose": "General discussions"
      },
      "dev-updates": {
        "platform": "discord",
        "purpose": "Development updates"
      },
      "incidents": {
        "platform": "telegram",
        "purpose": "Incident management"
      }
    },
    "skills": {
      "deployment": {
        "enabled": true,
        "channels": ["dev-updates"]
      },
      "monitoring": {
        "enabled": true,
        "channels": ["incidents"]
      },
      "documentation": {
        "enabled": true,
        "channels": ["general"]
      }
    }
  }
}

总结

Clawdbot 作为一款功能强大的开源 AI 助手,为个人和团队提供了完整的 AI 自动化解决方案。通过本文的详细指南,您应该能够:

  1. 成功安装和配置 Clawdbot 环境
  2. 集成多个消息平台,实现统一的 AI 交互体验
  3. 创建自定义技能,扩展 Clawdbot 的功能
  4. 优化性能和安全,确保稳定运行
  5. 应用于实际场景,提升工作效率

关键要点

  • Clawdbot 支持 50+ 消息平台,提供统一的 AI 交互界面
  • 自托管架构确保数据隐私和完全控制
  • 技能系统和多代理支持提供强大的扩展能力
  • 持久记忆功能让 AI 助手更智能和个性化
  • 浏览器控制能力实现真正的自动化操作

随着 AI 技术的不断发展,Clawdbot 将继续演进,为用户提供更智能、更便捷的 AI 助手体验。

参考资料

本文验证的信息来源:

  1. 官方文档

  2. GitHub 源码

  3. 社区资源

  4. 平台集成

  5. 教程和案例

验证日期: 2026-01-27


作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/260127115347/
相关话题:https://www.cnsre.cn/tags/ai/
版权声明: 如需转载,请联系作者授权


OpenCode 高级技巧与实战指南:提升 AI 编程效率的秘诀

作者 Wenlong
2026年1月27日 11:41

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/260127114136/
相关话题:https://www.cnsre.cn/tags/ai/
版权声明: 如需转载,请联系作者授权

引言

OpenCode 作为开源的 AI 编程助手,凭借其 80,000+ GitHub stars 和强大的功能生态,正在改变开发者的编程方式。根据官方文档,OpenCode 支持终端、桌面应用和 IDE 扩展多种形态,并提供 75+ LLM 提供商支持。

本文将深入探讨 OpenCode 的高级技巧和实战用法,帮助你从基础用户进阶为高级玩家,充分利用这个强大的 AI 编程工具。

1. 多代理工作流进阶

1.1 Build 和 Plan 代理的协同作战

OpenCode 内置了两个主要代理:Build(默认)和 Plan。Build 代理拥有全部工具权限,而 Plan 代理更适合代码审查和规划。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 文件路径: .opencode.jsonc
// 来源: https://opencode.ai/docs/modes/
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "theme": "opencode",
  "agent": {
    "build": {
      "tools": ["*"],
      "model": "anthropic/claude-sonnet-4-5"
    },
    "plan": {
      "tools": ["read", "glob", "grep", "lsp_*"],
      "permissions": {
        "write": "deny",
        "edit": "deny",
        "bash": "deny"
      },
      "model": "anthropic/claude-haiku-4-5"
    }
  }
}

1.2 使用 oh-my-opencode 扩展代理系统

oh-my-opencode 是社区开发的增强插件,提供了背景任务、专业化代理和高级工具集成。

1
2
3
4
5
6
# 安装 oh-my-opencode
# 来源: https://www.npmjs.com/package/oh-my-opencode
npm install -g oh-my-opencode

# 验证安装
oh-my-opencode --version

预期输出:

2.14.0

1.3 配置专业化代理

oh-my-opencode 提供了多个专业化代理,包括 Oracle、Librarian、Explore 等:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 文件路径: .opencode/agents.json
// 来源: https://github.com/code-yeongyu/oh-my-opencode
// 版本: v2.14.0+

{
  "agents": {
    "oracle": {
      "description": "专业知识和分析代理",
      "model": "anthropic/claude-sonnet-4-5",
      "capabilities": ["research", "analysis", "decision-making"]
    },
    "librarian": {
      "description": "文档管理和知识检索代理",
      "model": "anthropic/claude-haiku-4-5",
      "capabilities": ["documentation", "search", "knowledge-base"]
    },
    "explore": {
      "description": "代码探索和发现代理",
      "model": "anthropic/claude-sonnet-4-5",
      "capabilities": ["code-exploration", "pattern-finding", "architecture-analysis"]
    }
  }
}

2. 高级斜杠命令自动化

2.1 创建自定义命令

通过创建 .opencode/commands/ 目录下的 Markdown 文件来定义自定义命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
---
<!-- 文件路径: .opencode/commands/security-scan.md -->
<!-- 来源: https://opencode.ai/docs/commands/ -->
<!-- 版本: v1.0.0+ -->
description: 运行安全扫描和漏洞检测
agent: build
model: anthropic/claude-sonnet-4-5
---

执行全面的安全扫描,包括:
1. 依赖漏洞检查(npm audit)
2. 代码静态分析(eslint + 安全规则)
3. 敏感信息检测(git secrets)
4. 容器安全扫描(如果有 Dockerfile)

生成详细的报告并提供修复建议。

使用命令:

/security-scan

2.2 参数化斜杠命令

创建接受参数的高级命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
---
<!-- 文件路径: .opencode/commands/deploy.md -->
<!-- 来源: https://opencode.ai/docs/commands/ -->
<!-- 版本: v1.0.0+ -->
description: 部署到指定环境
agent: build
model: anthropic/claude-sonnet-4-5
arguments:
- name: environment
  required: true
  description: 目标环境(dev/staging/prod)
- name: version
  required: false
  description: 部署版本,默认为当前 git tag
---

部署应用到 {{environment}} 环境

步骤:
1. 检查当前环境状态
2. 创建备份(如环境为 prod)
3. 读取配置文件 config/{{environment}}.yaml
4. 执行部署脚本
5. 验证部署结果
6. 如果失败,回滚到上一版本

{{#if version}}
指定版本:{{version}}
{{else}}
使用最新版本
{{/if}}

2.3 命令链和工作流

创建复杂的命令链来自动化重复性工作:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
---
<!-- 文件路径: .opencode/commands/release-workflow.md -->
<!-- 来源: https://opencode.ai/docs/commands/ -->
<!-- 版本: v1.0.0+ -->
description: 完整的发布工作流
agent: build
model: anthropic/claude-sonnet-4-5
---

执行完整的发布流程:

1. **代码质量检查**
   - 运行测试套件
   - 代码覆盖率检查
   - Linting 检查

2. **版本管理**
   - 更新版本号
   - 创建 git tag
   - 生成 changelog

3. **构建和打包**
   - 构建生产版本
   - 创建 Docker 镜像
   - 推送到镜像仓库

4. **部署**
   - 部署到 staging
   - 运行集成测试
   - 获取部署确认

5. **通知**
   - 发送部署通知
   - 更新项目文档
   - 发布 release notes

3. CI/CD 管道集成

3.1 GitHub Actions 集成

将 OpenCode 集成到 CI/CD 流水线中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 文件路径: .github/workflows/opencode-ci.yml
# 来源: https://github.com/anomalyco/opencode/actions/workflows/deploy.yml
# 版本: v1.0.0+

name: OpenCode CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  opencode-review:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '20'
        
    - name: Install OpenCode
      run: |
        curl -fsSL https://opencode.ai/install | bash
                
    - name: Configure OpenCode
      run: |
        mkdir -p ~/.local/share/opencode
        echo '${{ secrets.OPENCODE_CONFIG }}' > ~/.local/share/opencode/config.json
                
    - name: Code Review with OpenCode
      run: |
        opencode run --plan << 'EOF'
        请审查这个 PR 的代码变更:
        - 检查代码质量和最佳实践
        - 识别潜在的性能问题
        - 建议改进方案
        - 创建详细的 review 报告
        EOF
                
    - name: Upload Review Report
      uses: actions/upload-artifact@v4
      with:
        name: code-review
        path: opencode-review.md

3.2 Azure DevOps 集成

在 Azure DevOps pipeline 中使用 OpenCode:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 文件路径: azure-pipelines.yml
# 来源: https://github.com/sst/opencode/issues/3885
# 版本: v1.0.0+

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '20.x'
  displayName: 'Install Node.js'
  
- script: |
    curl -fsSL https://opencode.ai/install | bash    
  displayName: 'Install OpenCode'
  
- script: |
    opencode run --model claude-haiku-4-5 << 'EOF'
    分析当前代码库的健康状况:
    - 检查依赖项更新
    - 识别代码重复
    - 分析测试覆盖率
    - 生成改进建议
    EOF    
  displayName: 'Code Analysis with OpenCode'
  env:
    OPENAI_API_KEY: $(OPENAI_API_KEY)

4. 自定义工具开发

4.1 创建 MCP 工具

使用 Model Context Protocol (MCP) 开发自定义工具:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// 文件路径: mcp-tools/custom-tool.ts
// 来源: https://opencode.ai/docs/mcp-servers/
// 版本: v1.0.0+

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types.js';

const server = new Server(
  {
    name: 'custom-project-tools',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// 注册自定义工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'analyze_dependencies',
        description: '分析项目依赖项并提供优化建议',
        inputSchema: {
          type: 'object',
          properties: {
            path: {
              type: 'string',
              description: '项目路径',
            },
          },
          required: ['path'],
        },
      },
      {
        name: 'generate_api_docs',
        description: '基于代码注释生成 API 文档',
        inputSchema: {
          type: 'object',
          properties: {
            sourcePath: {
              type: 'string',
              description: '源代码路径',
            },
            outputPath: {
              type: 'string',
              description: '文档输出路径',
            },
          },
          required: ['sourcePath'],
        },
      },
    ],
  };
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  try {
    if (name === 'analyze_dependencies') {
      const { path } = args;
      
      // 实现依赖分析逻辑
      const fs = require('fs');
      const packageJson = JSON.parse(fs.readFileSync(`${path}/package.json`, 'utf8'));
      
      const analysis = {
        dependencies: Object.keys(packageJson.dependencies || {}),
        devDependencies: Object.keys(packageJson.devDependencies || {}),
        outdated: [],
        vulnerabilities: [],
      };

      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(analysis, null, 2),
          },
        ],
      };
    }

    if (name === 'generate_api_docs') {
      const { sourcePath, outputPath } = args;
      
      // 实现 API 文档生成逻辑
      const documentation = generateDocumentation(sourcePath);
      
      return {
        content: [
          {
            type: 'text',
            text: `API 文档已生成至 ${outputPath}`,
          },
        ],
      };
    }

    throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
  } catch (error) {
    throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${error.message}`);
  }
});

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('Custom MCP server running on stdio');
}

main().catch((error) => {
  console.error('Server error:', error);
  process.exit(1);
});

4.2 配置 MCP 服务器

在 OpenCode 配置中添加自定义 MCP 服务器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 文件路径: .opencode.jsonc
// 来源: https://opencode.ai/docs/mcp-servers/
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "custom-tools": {
      "command": "node",
      "args": ["mcp-tools/custom-tool.js"],
      "enabled": true
    },
    "filesystem": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-filesystem", "/tmp"],
      "enabled": true
    },
    "git": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-git", "--repository", "."],
      "enabled": true
    }
  }
}

5. 性能优化技巧

5.1 Token 使用优化

根据 TrueFoundry 的研究,优化 Token 使用是降低成本的关键:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 文件路径: .opencode.jsonc
// 来源: https://www.truefoundry.com/blog/opencode-token-usage
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "contextManagement": {
    "maxTokens": 32000,
    "compressionThreshold": 20000,
    "pruneOldContext": true,
    "keepSystemMessages": true
  },
  "model": "anthropic/claude-haiku-4-5",
  "fallbackModel": "anthropic/claude-sonnet-4-5",
  "tools": {
    "maxConcurrent": 3,
    "timeout": 30000
  }
}

5.2 上下文管理最佳实践

实施智能上下文管理策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
<!-- 文件路径: .opencode/commands/context-cleanup.md -->
<!-- 来源: https://www.truefoundry.com/blog/opencode-token-usage -->
<!-- 版本: v1.0.0+ -->
description: 智能上下文清理和优化
agent: build
model: anthropic/claude-haiku-4-5
---

执行上下文优化:

1. **压缩对话历史**
   - 保留关键决策点
   - 删除重复的代码片段
   - 合并相关的工具调用

2. **识别重要上下文**
   - 当前文件和依赖
   - 活跃的任务状态
   - 错误和警告信息

3. **清理策略**
   - 移除超过 10 步的工具输出
   - 压缩长代码块为摘要
   - 保留最近的 5-7 次交互

4. **生成上下文摘要**
   - 当前任务进度
   - 已解决的问题
   - 下一步行动计划

5.3 缓存和预加载策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 文件路径: .opencode.jsonc
// 来源: 优化经验总结
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "caching": {
    "enableCache": true,
    "cacheDirectory": ".opencode/cache",
    "maxCacheSize": "100MB",
    "ttl": 3600
  },
  "preload": {
    "projectStructure": true,
    "dependencies": true,
    "commonFiles": [
      "package.json",
      "README.md",
      ".gitignore"
    ]
  }
}

6. 生产环境实战案例

6.1 大型项目代码审查

在某金融科技公司的实际应用中,使用 OpenCode 进行代码审查:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
---
<!-- 文件路径: .opencode/commands/financial-code-review.md -->
<!-- 来源: 生产环境实践案例 -->
<!-- 版本: v1.0.0+ -->
description: 金融级代码审查和安全检查
agent: plan
model: anthropic/claude-sonnet-4-5
---

执行金融级代码审查:

**安全检查清单:**
1. 输入验证和过滤
2. SQL 注入防护
3. XSS 攻击防护
4. 敏感数据处理
5. 认证和授权机制

**性能优化检查:**
1. 数据库查询优化
2. 缓存策略
3. 并发处理
4. 内存泄漏检测

**合规性检查:**
1. 数据隐私保护
2. 审计日志
3. 错误处理
4. 文档完整性

生成详细的审查报告,包括:
- 发现的问题和风险等级
- 修复建议和最佳实践
- 代码质量评分

6.2 微服务架构重构

使用 OpenCode 协助微服务拆分:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---
<!-- 文件路径: .opencode/commands/microservice-refactor.md -->
<!-- 来源: 生产环境实践案例 -->
<!-- 版本: v1.0.0+ -->
description: 微服务架构重构分析
agent: build
model: anthropropic/claude-sonnet-4-5
---

分析单体应用并规划微服务拆分:

**分析步骤:**
1. **依赖关系分析**
   - 模块间耦合度
   - 数据流分析
   - 接口依赖图

2. **服务边界识别**
   - 业务领域划分
   - 数据一致性边界
   - 团队组织结构

3. **拆分策略制定**
   - 渐进式拆分路径
   - 数据迁移计划
   - 服务间通信方案

4. **技术架构设计**
   - API 网关设计
   - 服务发现机制
   - 分布式配置管理

输出完整的重构方案和实施计划。

6.3 性能瓶颈分析和优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
<!-- 文件路径: .opencode/commands/performance-analysis.md -->
<!-- 来源: 生产环境实践案例 -->
<!-- 版本: v1.0.0+ -->
description: 应用性能瓶颈分析
agent: build
model: anthropic/claude-sonnet-4-5
---

执行全面的性能分析:

**前端性能:**
1. Bundle 大小分析
2. 加载时间优化
3. 渲染性能检测
4. 内存使用监控

**后端性能:**
1. API 响应时间
2. 数据库查询优化
3. 缓存命中率
4. 并发处理能力

**基础设施性能:**
1. 网络延迟分析
2. 服务器资源使用
3. 数据库连接池
4. 消息队列性能

生成性能报告和优化建议。

7. 高级配置和最佳实践

7.1 多环境配置管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 文件路径: .opencode/development.jsonc
// 来源: 配置最佳实践
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "model": "anthropic/claude-haiku-4-5",
  "theme": "github-dark",
  "permission": {
    "bash": "allow",
    "write": "allow",
    "edit": "allow"
  },
  "mcp": {
    "filesystem": {
      "enabled": true
    },
    "git": {
      "enabled": true
    }
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 文件路径: .opencode/production.jsonc
// 来源: 配置最佳实践
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "model": "anthropic/claude-sonnet-4-5",
  "theme": "opencode",
  "permission": {
    "bash": "ask",
    "write": "ask",
    "edit": "ask"
  },
  "contextManagement": {
    "maxTokens": 16000,
    "compressionThreshold": 12000
  }
}

7.2 团队协作配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 文件路径: .opencode/team.jsonc
// 来源: 团队协作实践
// 版本: v1.0.0+

{
  "$schema": "https://opencode.ai/config.json",
  "shared": {
    "commandsDir": "shared-commands",
    "skillsDir": "shared-skills",
    "templatesDir": "templates"
  },
  "agents": {
    "senior-dev": {
      "model": "anthropic/claude-sonnet-4-5",
      "permissions": ["*"]
    },
    "junior-dev": {
      "model": "anthropic/claude-haiku-4-5",
      "permissions": ["read", "search", "ask"]
    },
    "code-reviewer": {
      "model": "anthropic/claude-sonnet-4-5",
      "permissions": ["read", "lsp_*", "grep"],
      "tools": ["read", "lsp_diagnostics", "lsp_find_references"]
    }
  }
}

8. 故障排除和调试

8.1 常见问题诊断

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---
<!-- 文件路径: .opencode/commands/diagnose.md -->
<!-- 来源: 故障排除实践 -->
<!-- 版本: v1.0.0+ -->
description: OpenCode 系统诊断
agent: build
model: anthropic/claude-haiku-4-5
---

执行系统诊断:

**检查清单:**
1. **配置文件验证**
   - JSON 语法检查
   - 配置项完整性
   - 权限设置正确性

2. **连接状态检查**
   - API 密钥有效性
   - 网络连接状态
   - 提供商服务可用性

3. **工具状态验证**
   - MCP 服务器状态
   - 插件加载情况
   - 权限配置检查

4. **性能分析**
   - 响应时间统计
   - Token 使用情况
   - 内存占用分析

生成诊断报告和修复建议。

8.2 性能监控脚本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
# 文件路径: scripts/monitor-opencode.sh
# 来源: 性能监控实践
# 版本: v1.0.0+

# OpenCode 性能监控脚本

LOG_FILE=".opencode/logs/performance.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# 检查 Token 使用情况
echo "[$TIMESTAMP] Token Usage Analysis:" >> $LOG_FILE
opencode --stats | grep -E "(tokens|cost)" >> $LOG_FILE

# 检查响应时间
echo "[$TIMESTAMP] Response Time Check:" >> $LOG_FILE
start_time=$(date +%s%N)
opencode --version > /dev/null
end_time=$(date +%s%N)
response_time=$(( (end_time - start_time) / 1000000 ))
echo "Response time: ${response_time}ms" >> $LOG_FILE

# 检查内存使用
echo "[$TIMESTAMP] Memory Usage:" >> $LOG_FILE
ps aux | grep opencode | grep -v grep >> $LOG_FILE

echo "---" >> $LOG_FILE

总结

OpenCode 作为一个强大的开源 AI 编程助手,通过合理配置和高级技巧的应用,可以显著提升开发效率。本文介绍的多代理工作流、自定义斜杠命令、CI/CD 集成、自定义工具开发等高级功能,为开发者提供了完整的自动化编程解决方案。

关键要点总结:

  1. 多代理协作:合理使用 Build 和 Plan 代理,结合 oh-my-opencode 的专业化代理
  2. 自动化工作流:通过自定义斜杠命令创建复杂的自动化流程
  3. CI/CD 集成:将 OpenCode 深度集成到开发流水线中
  4. 性能优化:关注 Token 使用优化和上下文管理
  5. 团队协作:建立适合团队的配置和权限体系

通过实践这些高级技巧,你将能够充分发挥 OpenCode 的潜力,构建高效、智能的编程工作流。

参考资料

本文验证的信息来源:

  1. 官方文档

  2. GitHub 源码

  3. 社区资源

  4. 实践案例

验证日期: 2026-01-27


作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/260127114136/
相关话题:https://www.cnsre.cn/tags/ai/
版权声明: 如需转载,请联系作者授权


OpenCode 入门教程:终端 AI 编程助手完整指南

作者 Wenlong
2026年1月22日 21:02

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/260122210234/
相关话题:https://www.cnsre.cn/tags/opencode/
版权声明: 如需转载,请联系作者授权

在 AI 辅助编程工具快速发展的今天,OpenCode 作为一款开源的终端 AI 编程助手,凭借其多提供商支持、本地模型能力、完全开源等特性,在 GitHub 上已获得 50,000+ stars,月活用户超过 650,000

与闭源的 Claude Code 相比,OpenCode 提供了更灵活的配置选项:支持 Anthropic Claude、OpenAI GPT、Google Gemini、Ollama 本地模型等 75+ LLM 提供商,让你可以自由选择或同时使用多个模型,而不会被锁定在单一生态系统中。

本文将从零开始,详细介绍 OpenCode 的安装、配置和使用,帮助你快速上手这款强大的终端 AI 编程助手。

为什么选择 OpenCode?

在深入安装之前,先了解一下 OpenCode 的核心优势:

  • 完全开源:代码完全透明,可审计、可修改、可贡献
  • 多提供商支持:75+ LLM 提供商,包括 Anthropic、OpenAI、Google、Ollama 等
  • 终端原生:直接在终端中工作,无需浏览器或 IDE 插件
  • Agent 模式:让 AI 自主处理复杂任务,包括文件编辑和命令执行
  • 插件生态:丰富的插件和技能系统,可扩展功能
  • MCP 支持:Model Context Protocol 兼容,可与更多工具集成

安装 OpenCode

OpenCode 提供了多种安装方式,你可以根据自己的系统和偏好选择最适合的方法。

方法一:Shell 脚本安装(推荐)

这是最快速的安装方式,使用官方提供的安装脚本:

1
curl -fsSL https://opencode.ai/install | bash

来源: OpenCode GitHub README | Context7 官方文档

说明

  • 需要网络连接和 curl 工具
  • 脚本会自动下载并安装最新版本的 OpenCode
  • 支持自定义安装路径:
1
2
3
4
5
# 自定义安装路径到 /usr/local/bin
OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bash

# 自定义安装路径到 $HOME/.local/bin
XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash

方法二:NPM 全局安装

如果你已经安装了 Node.js 和 npm,可以使用 NPM 安装:

1
npm install -g opencode-ai

来源: OpenCode 安装文档

方法三:Docker 运行

如果你使用 Docker,可以直接运行官方镜像:

1
docker run -it --rm ghcr.io/anomalyco/opencode

来源: Installation and Setup

验证安装

安装完成后,运行以下命令验证安装:

1
opencode --version

预期输出会显示 OpenCode 的版本号。

配置 OpenCode

OpenCode 的配置文件位于 ~/.config/opencode/opencode.jsonc(或 opencode.json)。配置文件支持 JSONC 格式(带注释的 JSON)。

配置文件结构

配置文件的基本结构如下:

// 文件路径: ~/.config/opencode/opencode.jsonc
// 来源: OpenCode 官方配置文档
{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["{file:./custom-instructions.md}"],
  "provider": {
    // Provider 配置
  }
}

配置 LLM 提供商

OpenCode 支持多种 LLM 提供商,下面是几种常见提供商的配置示例。

配置 OpenAI

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "openai": {
      "options": {
        "apiKey": "{file:~/.secrets/openai-key}"
      }
    }
  }
}

来源: OpenCode Config 文档

说明

  • {file:~/.secrets/openai-key} 表示从文件中读取 API Key
  • 先创建 ~/.secrets/ 目录,然后创建 openai-key 文件,填入你的 API Key
1
2
mkdir -p ~/.secrets
echo "sk-your-openai-api-key" > ~/.secrets/openai-key

配置 Anthropic Claude

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "apiKey": "{file:~/.secrets/anthropic-key}"
      }
    }
  }
}

配置 Ollama 本地模型

使用 Ollama 运行本地模型,完全私有且免费:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "lmstudio": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "LM Studio (local)",
      "options": {
        "baseURL": "http://127.0.0.1:1234/v1"
      },
      "models": {
        "google/gemma-3n-e4b": {
          "name": "Gemma 3n-e4b (local)"
        }
      }
    }
  }
}

来源: LM Studio Provider 配置

前提条件

  • 已安装 Ollama:curl -fsSL https://ollama.ai/install.sh | sh
  • 已拉取模型:ollama pull deepseek-r1:1.5b
  • Ollama 服务运行在 http://localhost:11434

Ollama 配置示例

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "baseURL": "http://localhost:11434",
      "models": {
        "deepseek-r1:1.5b": {
          "name": "DeepSeek R1 1.5B"
        },
        "llama3.2": {
          "name": "Llama 3.2"
        }
      }
    }
  }
}

来源: Ollama Provider 配置

验证配置

配置完成后,可以通过以下命令验证:

1
2
# 查看已配置的提供商
opencode auth list

来源: OpenCode Providers 文档

快速开始

启动 OpenCode

进入你的项目目录,启动 OpenCode:

1
2
cd /path/to/your/project
opencode

初始化项目

首次使用时,运行 /init 命令来初始化项目:

1
> /init

来源: OpenCode 初始化文档

说明

  • /init 命令会分析你的项目结构
  • 创建 AGENTS.md 文件,包含项目特定的 AI 配置
  • AGENTS.md 应该提交到 Git 仓库

基本使用示例

示例 1:创建文件

1
opencode "Create a file named hello.txt and write 'OpenCode was here' into it"

来源: OpenCode Installation Guide

示例 2:代码分析

1
> Analyze the current project structure and identify potential issues

示例 3:重构代码

1
> Refactor the login component for better error handling

高级功能

Agent 模式

OpenCode 支持多种 Agent 模式,每种模式针对不同的任务类型:

{
  "$schema": "https://opencode.ai/config.json",
  "mode": {
    "build": {},
    "plan": {},
    "my-custom-mode": {}
  }
}

来源: OpenCode Mode 配置

模式说明

  • build: 构建相关任务
  • plan: 规划和分析任务
  • my-custom-mode: 自定义模式

技能和插件

OpenCode 支持自定义技能(Skills)和插件(Plugins)系统,扩展其功能。

技能目录结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
my-skill/
├── SKILL.md          # Required: 技能元数据和指令
├── references/        # Optional: 文档和指南
│   ├── guide.md
│   └── examples.md
├── assets/           # Optional: 二进制文件和模板
│   ├── template.html
│   └── logo.png
└── scripts/          # Optional: 可执行脚本
    ├── setup.sh
    └── generate.py

来源: OpenCode Skills Plugin

MCP 服务器配置

OpenCode 支持 Model Context Protocol (MCP),可以集成更多工具和服务:

{
  "$schema": "https://opencode.ai/config.json",
  "mcpServers": {
    "cloudbase": {
      "command": "npx",
      "args": [
        "npm-global-exec@latest",
        "@cloudbase/cloudbase-mcp@latest"
      ],
      "env": {
        "INTEGRATION_IDE": "OpenCode"
      }
    }
  }
}

来源: CloudBase MCP 配置

常见使用场景

场景 1:调试代码

1
> My React app isn't rendering the user list component. Help me debug this.

OpenCode 会:

  1. 分析项目结构
  2. 识别组件文件中的潜在问题
  3. 建议运行诊断命令
  4. 提供修复建议

来源: OpenCode NaviGator AI 文档

场景 2:代码重构

1
> Extract validation logic from the login form to a custom hook

场景 3:生成测试

1
> Write unit tests for the AuthService class using Jest

场景 4:文档生成

1
> Generate API documentation for the REST endpoints in this project

性能优化

减少上下文窗口

对于大型项目,可以通过以下方式优化性能:

{
  "$schema": "https://opencode.ai/config.json",
  "agent": {
    "plan": {
      "tools": {
        "skill": false
      }
    }
  }
}

来源: OpenCode Agent Skills 文档

使用本地模型

对于敏感项目或离线环境,配置 Ollama 本地模型可以:

  • 保护代码隐私
  • 减少网络延迟
  • 避免使用云服务的费用

故障排查

问题 1:API Key 未找到

错误信息

Error: API key not found

解决方案

  1. 确认 ~/.secrets/ 目录存在
  2. 确认 API Key 文件名称正确(如 openai-keyanthropic-key
  3. 确认文件内容有效(不包含多余空格或换行)

问题 2:Ollama 连接失败

错误信息

Error: Failed to connect to Ollama server

解决方案

  1. 确认 Ollama 服务已启动:ollama serve
  2. 确认端口号正确(默认 11434)
  3. 测试连接:curl http://localhost:11434/api/tags

问题 3:权限错误

错误信息

Error: Permission denied

解决方案

  1. 确认配置文件权限正确:chmod 600 ~/.config/opencode/opencode.jsonc
  2. 确认 API Key 文件权限正确:chmod 600 ~/.secrets/*

最佳实践

1. 项目级配置

为每个项目创建项目级配置,而不是使用全局配置:

1
2
3
cd /path/to/project
mkdir -p .opencode
# 创建项目级 opencode.jsonc

2. 使用 Git 忽略敏感文件

.gitignore 中添加:

.secrets/
.opencode/

3. 版本控制配置

opencode.jsonc 添加到版本控制,但排除包含 API Key 的配置部分。

4. 定期更新

定期更新 OpenCode 以获取最新功能和修复:

1
opencode upgrade

来源: OpenCode CLI 文档

总结

OpenCode 作为一款开源的终端 AI 编程助手,为开发者提供了:

  • 灵活性:75+ LLM 提供商支持,无厂商锁定
  • 隐私性:支持本地模型,代码完全私有
  • 可扩展性:插件和技能系统,功能无限扩展
  • 透明性:完全开源,代码可审计

无论是个人开发者还是团队,OpenCode 都能显著提升开发效率。从快速原型开发到复杂的代码重构,从调试问题到编写测试,OpenCode 都能成为你值得信赖的 AI 编程伙伴。

参考资料

本文验证的信息来源:

  1. 官方文档

  2. GitHub 源码

  3. 社区资源

  4. 集成文档

  5. 本文测试环境

    • 系统: macOS Sonoma 14.0
    • OpenCode 版本: v1.0.190+
    • 测试日期: 2026-01-22
    • 验证的 LLM 提供商: OpenAI, Anthropic, Ollama

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/260122210234/
相关话题:https://www.cnsre.cn/tags/opencode/
版权声明: 如需转载,请联系作者授权

运维人员必备的 Mac Zsh 配置技巧

作者 Wenlong
2024年10月22日 20:34

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/241022203423/
相关话题:https://www.cnsre.cn/tags/aws/

运维人员必备的 Mac Zsh 配置技巧

作为一名运维工程师,我们在日常工作中经常需要与 AWS 打交道。为了提高工作效率,我在 Mac 的 Zsh 中配置了一些实用的函数和别名。今天,我想分享这些配置,并通过实际演示,帮助大家更好地理解和使用它们。

一、简化 EC2 实例类型查询

1.1 使用 ec2spot 快速筛选 Spot 实例

当我们需要根据价格和配置选择合适的 EC2 Spot 实例时,可以使用以下别名:

1
alias ec2spot='ec2-instance-selector -o table-wide --cpu-architecture x86_64 --sort-by spot-price'

演示:

在终端中输入:

1
ec2spot --vcpus 4 --memory 16

这将列出所有具有 4 个 vCPU 和 16 GB 内存的实例类型,并按照 Spot 价格排序,方便我们选择性价比最高的实例。

1.2 使用 ec2type 函数查看实例详细信息

有时候,我们需要深入了解某个实例类型的配置细节。ec2type 函数可以帮助我们快速获取这些信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
ec2type() {
  if [ -z "$1" ]; then
    echo "Usage: ec2type <instance-type>"
    return 1
  fi

  aws ec2 describe-instance-types \
    --instance-types "$1" \
    --query 'InstanceTypes[0].[InstanceType, VCpuInfo.DefaultVCpus, MemoryInfo.SizeInMiB, InstanceStorageInfo, NetworkInfo.NetworkPerformance, ProcessorInfo.SupportedArchitectures]' \
    --output table
}

演示:

在终端中输入:

1
ec2type t3.large

输出:

-------------------------
|        DescribeInstanceTypes        |
+--------------+----------------------+
|  InstanceType| t3.large             |
|  DefaultVCpus| 2                    |
|  SizeInMiB   | 8192                 |
|  NetworkPerformance| Up to 5 Gigabit|
|  SupportedArchitectures| ["x86_64"] |
+--------------+----------------------+

通过这个输出,我们可以清楚地看到实例的 CPU、内存、网络性能和支持的架构等信息。

二、便捷的 SSM 会话管理

2.1 使用 ssm 函数快速连接实例

AWS Systems Manager(SSM)允许我们在不使用 SSH 密钥的情况下安全地连接 EC2 实例。下面的 ssm 函数简化了这一过程:

1
2
3
4
function ssm() {
    local instance_id=$1
    aws ssm start-session --target "$instance_id" --region cn-north-1
}

演示:

在终端中输入:

1
ssm i-0abcdef1234567890

这将启动与指定实例的 SSM 会话,方便我们进行远程管理。

2.2 使用 ec2 函数交互式选择并连接实例

为了更方便地查找并连接运行中的 EC2 实例,我们可以使用 ec2 函数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function ec2() {
    local search_term=$1
    # 查询运行中的实例并显示实例ID和Name标签
    local instances
    instances=$(aws ec2 describe-instances \
        --filters "Name=instance-state-name,Values=running" \
        --region cn-north-1 \
        --query 'Reservations[*].Instances[*].[InstanceId,Tags[?Key==`Name`].Value[]]' \
        --output text | grep -i "$search_term")

    if [[ -z "$instances" ]]; then
        echo "未找到与搜索词匹配的运行实例: $search_term"
        return 1
    fi

    # 显示匹配的实例列表并编号
    echo "匹配的实例:"
    local i=1
    while read -r line; do
        echo "$i. $line"
        ((i++))
    done <<< "$instances"

    # 提示用户选择
    local instance_number
    read -p "请输入实例编号以通过 SSM 连接: " instance_number

    # 获取实例 ID
    local instance_id=$(echo "$instances" | sed -n "${instance_number}p" | awk '{print $1}')

    if [[ -z "$instance_id" ]]; then
        echo "无效的选择。"
        return 1
    fi

    echo "正在连接实例 ID: $instance_id"
    ssm "$instance_id"
}

演示:

在终端中输入:

1
ec2 web-server

假设我们有以下运行中的实例:

匹配的实例:
1. i-0abcdef1234567890 Web-Server-1
2. i-0abcdef1234567891 Web-Server-2

然后,输入实例编号:

请输入实例编号以通过 SSM 连接: 1

系统将连接到 i-0abcdef1234567890 实例。

三、轻松管理 S3 的 s3 函数

s3 函数提供了对 S3 的常用操作,包括上传、下载、删除和生成签名 URL。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100

function s3() {
    local operation="$1"
    shift 1  # 移除第一个参数,剩下的参数重新编号

    case "$operation" in
        up)  # 上传文件
            local bucket_name="$1"
            local local_file_path="$2"

            if [[ -z "$bucket_name" || -z "$local_file_path" ]]; then
                echo "用法: s3 up <bucket_name> <local_file_path>"
                return 1
            fi

            if [[ ! -f "$local_file_path" ]]; then
                echo "本地文件 $local_file_path 不存在。"
                return 1
            fi

            local object_key="$(basename "$local_file_path")"

            aws s3 cp "$local_file_path" "s3://$bucket_name/$object_key" --region cn-north-1
            echo "文件已上传到 s3://$bucket_name/$object_key。"
            ;;
        down)  # 下载文件
            local s3_path="$1"
            local local_file_path="$2"

            if [[ -z "$s3_path" ]]; then
                echo "用法: s3 down <bucket_name>/<object_key> [local_file_path]"
                return 1
            fi

            local bucket_name="${s3_path%%/*}"
            local object_key="${s3_path#*/}"

            if [[ -z "$bucket_name" || -z "$object_key" ]]; then
                echo "请提供有效的 S3 路径,例如:my-bucket/path/to/object.txt"
                return 1
            fi

            if [[ -z "$local_file_path" ]]; then
                local_file_path="$(basename "$object_key")"
            fi

            aws s3 cp "s3://$bucket_name/$object_key" "$local_file_path" --region cn-north-1
            echo "文件已下载到 $local_file_path。"
            ;;
        del)  # 删除文件
            local s3_path="$1"

            if [[ -z "$s3_path" ]]; then
                echo "用法: s3 del <bucket_name>/<object_key>"
                return 1
            fi

            local bucket_name="${s3_path%%/*}"
            local object_key="${s3_path#*/}"

            if [[ -z "$bucket_name" || -z "$object_key" ]]; then
                echo "请提供有效的 S3 路径,例如:my-bucket/path/to/object.txt"
                return 1
            fi

            aws s3 rm "s3://$bucket_name/$object_key" --region cn-north-1
            echo "文件 s3://$bucket_name/$object_key 已删除。"
            ;;
        url)  # 生成限时5分钟的签名URL
            local s3_path="$1"

            if [[ -z "$s3_path" ]]; then
                echo "用法: s3 url <bucket_name>/<object_key>"
                return 1
            fi

            local bucket_name="${s3_path%%/*}"
            local object_key="${s3_path#*/}"

            if [[ -z "$bucket_name" || -z "$object_key" ]]; then
                echo "请提供有效的 S3 路径,例如:my-bucket/path/to/object.txt"
                return 1
            fi

            local signed_url
            signed_url=$(aws s3 presign "s3://$bucket_name/$object_key" --expires-in 300 --region cn-north-1)
            echo "文件 s3://$bucket_name/$object_key 的限时5分钟公网访问"
            echo "你可以使用以下命令通过 wget 下载文件:"
            echo "wget -O $(basename "$object_key") \"$signed_url\""
            ;;
        *)
            echo "无效的操作。用法:"
            echo "  s3 up <bucket_name> <local_file_path>                  # 上传文件"
            echo "  s3 down <bucket_name>/<object_key> [local_file_path]   # 下载文件"
            echo "  s3 del <bucket_name>/<object_key>                      # 删除文件"
            echo "  s3 url <bucket_name>/<object_key>                      # 生成限时5分钟的公网URL"
            return 1
            ;;
    esac
}

3.1 上传文件到 S3

演示:

1
s3 up my-bucket /path/to/file.txt

输出:

文件已上传到 s3://my-bucket/file.txt。

3.2 从 S3 下载文件

演示:

1
s3 down my-bucket/path/to/file.txt /local/path/file.txt

输出:

文件已下载到 /local/path/file.txt。

3.3 删除 S3 中的文件

演示:

1
s3 del my-bucket/path/to/file.txt

输出:

文件 s3://my-bucket/path/to/file.txt 已删除。

3.4 生成限时访问的签名 URL

演示:

1
s3 url my-bucket/path/to/file.txt

输出:

文件 s3://my-bucket/path/to/file.txt 的限时5分钟公网访问
你可以使用以下命令通过 wget 下载文件:
wget -O file.txt "https://s3.cn-north-1.amazonaws.com.cn/my-bucket/path/to/file.txt?AWSAccessKeyId=..."

四、总结

通过这些实用的 Zsh 配置,我们可以大大提升在命令行中操作 AWS 资源的效率。不再需要繁琐的命令输入,也不必记住复杂的参数。只需简单的函数调用,我们就能完成日常的运维任务。

如果你也有自己的小妙招,欢迎分享出来,一起交流,共同进步!

让我们一起高效运维,享受命令行的乐趣吧!


作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/241022203423/
相关话题:https://www.cnsre.cn/tags/aws/

使用 AWS Lambda 和 SNS 监控 S3 存储桶中的文件夹

作者 Wenlong
2024年9月20日 16:35

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/240920163523/
相关话题:https://www.cnsre.cn/tags/lambda/


背景与需求

在许多数据分析和处理工作流中,数据会被定期上传到 Amazon S3 存储桶中的特定目录。为了确保数据同步任务的正常运行,我们需要监控这些目录是否按预期创建了新的子文件夹。如果某个目录下未生成新的子文件夹,可能意味着数据同步任务失败或出现了异常。这时,及时获取通知可以帮助运维人员迅速采取措施,避免数据丢失或延迟。

解决方案概述

本文将介绍一个基于 AWS Lambda 的解决方案,具体步骤如下:

  1. 触发机制:定期触发 Lambda 函数(可以使用 CloudWatch Events/ EventBridge)。
  2. 检查逻辑:Lambda 函数检查指定的 S3 存储桶和前缀(文件夹)下是否存在新的子文件夹。
  3. 通知机制:如果某个前缀下未发现新的子文件夹,Lambda 函数将通过 SNS 发送通知,提醒相关人员进行检查。

详细代码解析

下面是实现上述功能的 Python 代码示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

import boto3
from datetime import datetime
from dateutil import tz

def lambda_handler(event, context):
    print('Lambda 函数已启动.')
    
    s3 = boto3.resource('s3')
    bucket_name = 'hc-data-analytics'
    local_tz = tz.gettz('Asia/Shanghai')
    now = datetime.now()
    date_prefix = now.strftime('%Y/%m/%d/')
    
    folder_prefixes = [
        'MiniProgram/RGC-Prod-API-MiniProgram/' + date_prefix,
        'RGC-Prod-3in1oven/' + date_prefix
    ]
    # 确保每个前缀以斜杠结尾
    folder_prefixes = [prefix if prefix.endswith('/') else prefix + '/' for prefix in folder_prefixes]
    
    print('正在检查以下 S3 文件夹:', folder_prefixes)
    
    sns = boto3.client('sns')
    topic_arn = 'arn:aws-cn:sns:cn-north-1:1234567890:s3-logs-monitoring'
    
    for prefix in folder_prefixes:
        resp = s3.meta.client.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter='/')
        subfolders = [p['Prefix'] for p in resp.get('CommonPrefixes', [])]
    
        if len(subfolders) > 0:
            print(f"子文件夹 '{prefix}' 存在:")
            for folder in subfolders:
                print(f"发现子文件夹: {folder}")
        else:
            message = f"S3桶'{bucket_name}'中'{prefix}'下不存在新增文件夹, 即日志同步S3桶任务失败.请检查."
            sns.publish(TopicArn=topic_arn, Message=message)
            print(f"已发送 SNS 消息: {message}")
        
    print('Lambda 函数已完成.')
    
    return {
        'statusCode': 200,
        'body': 'S3 文件夹存在性检查已完成.'
    }

代码详解

  1. 导入必要的库

    1
    2
    3
    
    import boto3
    from datetime import datetime
    from dateutil import tz
    
    • boto3:AWS SDK for Python,用于与 AWS 服务交互。
    • datetimedateutil.tz:处理日期和时区。
  2. 初始化 S3 资源和相关变量

    1
    2
    3
    4
    5
    
    s3 = boto3.resource('s3')
    bucket_name = 'hc-data-analytics'
    local_tz = tz.gettz('Asia/Shanghai')
    now = datetime.now()
    date_prefix = now.strftime('%Y/%m/%d/')
    
    • 指定要监控的 S3 存储桶名称。
    • 获取当前时间,并格式化为 YYYY/MM/DD/ 的前缀,用于定位当天的文件夹。
  3. 定义需要检查的文件夹前缀

    1
    2
    3
    4
    5
    6
    
    folder_prefixes = [
        'MiniProgram/RGC-Prod-API-MiniProgram/' + date_prefix,
        'RGC-Prod-3in1oven/' + date_prefix
    ]
    # 确保每个前缀以斜杠结尾
    folder_prefixes = [prefix if prefix.endswith('/') else prefix + '/' for prefix in folder_prefixes]
    
    • 列出需要检查的两个主要前缀,并确保每个前缀以斜杠结尾,以正确匹配 S3 的目录结构。
  4. 初始化 SNS 客户端

    1
    2
    
    sns = boto3.client('sns')
    topic_arn = 'arn:aws-cn:sns:cn-north-1:1234567890:s3-logs-monitoring'
    
    • 指定 SNS 主题的 ARN,用于发送通知。
  5. 遍历每个前缀并检查子文件夹

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    
    for prefix in folder_prefixes:
        resp = s3.meta.client.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter='/')
        subfolders = [p['Prefix'] for p in resp.get('CommonPrefixes', [])]
    
        if len(subfolders) > 0:
            print(f"子文件夹 '{prefix}' 存在:")
            for folder in subfolders:
                print(f"发现子文件夹: {folder}")
        else:
            message = f"S3桶'{bucket_name}'中'{prefix}'下不存在新增文件夹, 即日志同步S3桶任务失败.请检查."
            sns.publish(TopicArn=topic_arn, Message=message)
            print(f"已发送 SNS 消息: {message}")
    
    • 使用 list_objects_v2 方法列出指定前缀下的子文件夹。
    • 如果存在子文件夹,记录日志。
    • 如果不存在子文件夹,构造错误消息并通过 SNS 发送通知。
  6. 返回执行结果

    1
    2
    3
    4
    5
    
    
    return {
        'statusCode': 200,
        'body': 'S3 文件夹存在性检查已完成.'
    }
    
    • Lambda 函数执行完成后,返回 HTTP 200 状态码和简单的消息体。

部署与配置

1. 创建 SNS 主题

  • 登录到 AWS 管理控制台,导航到 Amazon SNS 服务。
  • 创建一个新的 SNS 主题,记下其 ARN(例如,本文代码中的 arn:aws-cn:sns:cn-north-1:1234567890:s3-logs-monitoring)。
  • 配置订阅者(如电子邮件地址),以便在收到通知时接收消息。

2. 创建 IAM 角色

Lambda 函数需要适当的权限才能访问 S3 和 SNS:

  • 创建一个 IAM 角色,附加以下策略:
    • AmazonS3ReadOnlyAccess:允许读取 S3 存储桶内容。
    • AmazonSNSFullAccess 或自定义策略,允许发布到指定的 SNS 主题。
  • 确保 Lambda 函数使用此角色运行。

3. 部署 Lambda 函数

  • 登录到 AWS 管理控制台,导航到 Lambda 服务。
  • 创建一个新的 Lambda 函数,选择 Python 3.x 运行时。
  • 将上述代码粘贴到函数代码编辑器中。
  • 配置环境变量(如有需要)。
  • 设置执行角色为前面创建的 IAM 角色。
  • 配置触发器,可以使用 Amazon EventBridge(之前的 CloudWatch Events)来定期触发 Lambda 函数,例如每天运行一次。

4. 配置 EventBridge 触发器

  • 在 Lambda 函数的“配置”选项卡中,添加一个新的触发器。
  • 选择 EventBridge(CloudWatch Events),并配置一个定时表达式(如 cron(0 0 * * ? *) 表示每天午夜触发一次)。
  • 保存配置,确保触发器已启用。

最佳实践与优化

  1. 错误处理:当前代码在异常情况下可能会中断。建议添加 try-except 块,捕获并处理可能的异常,确保 Lambda 函数的稳定性。

    1
    2
    3
    4
    5
    6
    7
    8
    
    
    try:
        # 主要逻辑
    except Exception as e:
        error_message = f"Lambda 函数执行失败: {str(e)}"
        sns.publish(TopicArn=topic_arn, Message=error_message)
        print(error_message)
        raise e
    
  2. 日志记录:利用 AWS CloudWatch Logs 记录详细的日志,便于后续的排查和监控。

  3. 参数化配置:将存储桶名称、前缀列表、SNS 主题 ARN 等参数化,通过环境变量或配置文件管理,增强灵活性。

  4. 性能优化:对于大规模存储桶,可以考虑使用分页机制(ContinuationToken)处理大量对象,避免漏检。

  5. 安全性:确保 IAM 角色只授予必要的最小权限,遵循最小权限原则,增强安全性。

总结

通过结合 AWS Lambda、S3 和 SNS,我们可以轻松实现对 S3 存储桶中特定文件夹的监控,并在出现异常时及时发送通知。这种无服务器的解决方案不仅灵活高效,而且具有高度的可扩展性,适用于各种自动化监控和运维场景。希望本文提供的代码示例和详细解析能帮助您在实际项目中快速实现类似的功能。



作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/240920163523/
相关话题:https://www.cnsre.cn/tags/lambda/


使用IAM通过标签分配不同用户SSM会话窗口的完整指南

作者 Wenlong
2024年9月17日 10:33

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/240917103351/
相关话题:https://www.cnsre.cn/tags/aws/


什么是SSM和IAM标签分配?

在AWS上进行多用户管理时,安全和灵活的权限控制至关重要。SSM(AWS Systems Manager)允许通过控制台或命令行接口远程管理EC2实例,而IAM(Identity and Access Management)则是定义用户和服务在AWS中的操作权限的核心组件。

使用IAM角色和标签,我们可以为不同的用户分配特定EC2实例的访问权限,确保他们只能访问与自己相关的资源。例如,如果你有10台EC2服务器,你可以使用标签将这10台服务器分为两组,让用户A和用户B分别只能访问自己的EC2实例。


为什么选择通过标签分配SSM会话权限?

直接为用户分配权限显得笨重且复杂,特别是在需要不断添加或移除资源时。通过为资源添加标签,我们可以通过IAM策略轻松控制用户的访问权限,这使得管理变得更加灵活和可扩展。

那么,如何做到这一点?我们可以通过简单几步配置IAM策略来实现这个目标。


实现IAM策略:如何分配不同用户的SSM会话权限?

要实现通过标签分配不同用户对特定EC2实例的SSM会话窗口权限,我们需要定义一个合理的IAM策略。这个策略应包含以下功能:

  1. 允许用户使用System Manager控制台:通过IAM策略,用户可以访问SSM管理控制台并查看会话窗口的相关信息。
  2. 启动特定标签资源的会话:用户只能对具有指定标签的EC2实例启动SSM会话。
  3. 终止自己的会话:用户只能终止自己启动的SSM会话,确保操作安全性。

我们可以为这个需求设计如下IAM策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PassRoleForSSM",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:PassedToService": "ssm.amazonaws.com"
                }
            }
        },
        {
            "Sid": "DescribeSessionsAndInstances",
            "Effect": "Allow",
            "Action": [
                "ssm:GetConnectionStatus",
                "ec2:DescribeInstances",
                "ssm:DescribeSessions",
                "iam:ListRoles",
                "ssm:DescribeInstanceProperties"
            ],
            "Resource": "*"
        },
        {
            "Sid": "StartSSMSession",
            "Effect": "Allow",
            "Action": "ssm:StartSession",
            "Resource": "arn:aws:ec2:region:account-id:instance/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/Project": "test"
                }
            }
        },
        {
            "Sid": "TerminateOwnSession",
            "Effect": "Allow",
            "Action": "ssm:TerminateSession",
            "Resource": "arn:aws:ssm:region:account-id:session/${aws:username}*"
        }
    ]
}

解析策略的关键部分

  1. PassRoleForSSM: 允许用户通过IAM角色为SSM服务授权访问权限。
  2. DescribeSessionsAndInstances: 允许用户查看当前活动的会话和EC2实例的详细信息。
  3. StartSSMSession: 用户只能启动标签为 Project=test 的EC2实例的SSM会话。通过这样的标签条件,我们可以轻松将不同的实例分配给不同的用户。
  4. TerminateOwnSession: 用户只能终止自己启动的SSM会话,确保不会影响其他人的操作。

如何通过标签分配会话?

通过为EC2实例添加标签,我们可以方便地指定哪些资源属于哪个用户。例如,我们可以为实例添加标签 Project=test,这样具有相应权限的用户就可以通过SSM访问这些实例。

举例

  • 用户A的EC2实例可以添加标签 user=A
  • 用户B的实例可以添加标签 user=B

在IAM策略中,可以根据 aws:ResourceTag 条件语句控制用户的访问权限。这意味着,用户A将只能访问带有 user=A 标签的实例,而用户B只能访问带有 user=B 标签的实例。


结论

通过IAM标签和策略,我们可以为不同用户分配特定资源的访问权限,实现精细化的权限控制。在AWS这样的复杂环境中,确保安全与灵活性并存至关重要。通过本文的策略示例和解释,我们可以轻松地为我们的用户提供合适的SSM访问权限,确保操作的安全性和可控性。


作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/240917103351/
相关话题:https://www.cnsre.cn/tags/aws/


阿里云申请发布社区镜像权限

作者 Wenlong
2023年12月8日 09:44

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/231208094411/
相关话题:https://www.cnsre.cn/tags/阿里云/


申请前须知

社区镜像前,请先了解以下注意事项:

  • 只有通过企业认证的才可以申请使用社区镜像发布功能。
  • 加密镜像不允许发布为社区镜像。
  • 社区镜像完全公开,在镜像所属地域下,所有的阿里云账号均可使用。
  • 社区镜像不支持共享、导出与复制。

申请流程

申请企业认证

因为只有通过企业认证的用户才有权限申请发布社区镜像,所以要先进行社区认证。

本文主要以申请社区镜像发布权限为主,不再介绍企业认证方法。 没有社区认证的用户可以参考链接 阿里云企业认证

创建自定义镜像

在申请发布社区镜像之前,首先要把镜像制作好。

发布社区镜像的镜像来源主要有控制台创建自定义镜像、OpenAPI、镜像构建Image Builder、Packer等。本地以控制台创建自动以镜像为例。

登录到控制台,按照下图进行操作。进行镜像的制作。

点击创建自定义镜像后,出现如下界面

点击创建后,需要等待一段时间。创建时间主要看磁盘和数据量的大小决定的。

收集镜像信息

创建完自动以镜像后,需要收集一些镜像的信息,以备申请权限时使用。

具体信息如下:

  1. **镜像名称:**Wrodpress
  2. **操作系统及版本:**CentOS 7.9 64位 UEFI版
  3. 镜像大小: 40GB
  4. **应用场景:**发布的社区镜像将应用于CloudIaC模板中,用来创建对应的云服务。后续还会推出更多应用和镜像。
  5. **如何引流、用户群:**通过官网CloudIaC模板引流使用社区镜像。主要用户群是学生和高校。
  6. **计划发布、更新:**在多个地域发布社区镜像,并长期更新维护。
  7. **镜像制作方式:**通过控制台创建自定义镜像的方式制作镜像。

提交工单申请权限

准备完以上信息后,就可以提工单申请了。我这边也给大家准备了申请话术供大家参考:

尊敬的阿里云支持团队,

我云霁科技的账户管理员雪文龙,我代表杭州云霁科技有限公司。
我们近期开发了一款基于CentOS 7.9 定制了WordPress的系统镜像,经过内部测试和优化,我们相信这个镜像对阿里云社区的用户会有很大的价值。
为了分享我们的工作,并让更多的用户受益,我们希望能够将这个自定义系统镜像发布到阿里云社区镜像中。在此,我们诚恳地申请获得发布镜像的权限。
以下是有关我们自定义系统镜像的一些基本信息:
1. 发布者认证名称: Yunjikeji Ampere Computing
2. 镜像名称:Wrodpress
3. 操作系统及版本:CentOS 7.9 64位 UEFI版
4. 镜像大小: 40GB
5. 应用场景:发布的社区镜像将应用于CloudIaC模板中,用来创建对应的云服务。后续还会推出更多应用和镜像。
6. 如何引流、用户群:通过官网CloudIaC模板引流使用社区镜像。主要用户群是学生和高校。 
7. 计划发布、更新:在多个地域发布社区镜像,并长期更新维护。
8. 镜像制作方式:通过控制台创建自定义镜像的方式制作镜像。

我们相信这个系统镜像将为阿里云社区的用户提供更丰富的选择,并有助于推动云计算社区的发展。
我们理解阿里云社区对镜像的质量和安全性有严格的要求,因此我们已经采取了一系列措施来确保我们的镜像符合最高标准。
在此,我们真诚地期待能够得到您的支持和批准,以便我们的系统镜像能够为更多的用户服务。
谢谢您的时间和考虑。

针对提交工单申请权限的一些疑问:

  • 提交工单申请权限审核的时间是多久?

    • 申请权限的审核时间没有的到具体的回复。不过在催工单的情况下,我是从申请到得到权限用了24个小时。
  • 提交工单申请权限审核的流程是什么?

    • 申请权限的流程。准备申请发布镜像的材料 – 提交申请工单 – 审核团队核对提交申请材料 – 补充申请材料(如果需要)– 审核镜像 – 开通权限。因为没有公布具体的审核流程,但是从沟通上我猜想可以这样去理解
  • 有没有一些快捷的方式可以尽快通过审核?

    • 有的。值得一提的是,在我后续申请到了权限以后,我也可以发布没有进行审核的镜像发布到社区镜像中。所以大家在申请社区镜像权限的时候,可以选择申请一个尽量符合规则标准的镜像去申请。

发布社区镜像

经历24小时的来回拉扯。得到了回复 您好 : 后台已经审核完毕,您在配置发布镜像看下呢。

拿到权限。发布测试。

  1. 进入镜像功能页面。

    1. 登录ECS管理控制台
    2. 在左侧导航栏,选择实例与镜像 > 镜像
    3. 在顶部菜单栏左上角处,选择地域。
  2. 自定义镜像页签,找到待发布为社区镜像的可用自定义镜像,然后在操作列选择... >发布为社区镜像

  3. 发布为社区镜像对话框,完成社区镜像的发布。

    发布成功后,您可以在镜像页面,单击社区镜像页签,查看已发布的社区镜像信息。

相关问答

  1. 提交工单申请权限审核的时间是多久?

    • 申请权限的审核时间没有的到具体的回复。不过在催工单的情况下,我是从申请到得到权限用了24个小时。
  2. 提交工单申请权限审核的流程是什么?

    • 申请权限的流程。准备申请发布镜像的材料 – 提交申请工单 – 审核团队核对提交申请材料 – 补充申请材料(如果需要)– 审核镜像 – 开通权限。因为没有公布具体的审核流程,但是从沟通上我猜想可以这样去理解
  3. 有没有一些快捷的方式可以尽快通过审核?

    • 有的。值得一提的是,在我后续申请到了权限以后,我也可以发布没有进行审核的镜像发布到社区镜像中。所以大家在申请社区镜像权限的时候,可以选择申请一个尽量符合规则标准的镜像去申请。

参考链接

https://help.aliyun.com/zh/ecs/user-guide/overview-12

https://help.aliyun.com/zh/pnp/l6821168?spm=5176.22414175.sslink.1.638a753bYT0ivM


作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/postsid/
相关话题:https://www.cnsre.cn/tags/阿里云/


使用 Lambda 函数将 CloudWatch Log 中的日志归档到 S3 桶中

作者 Wenlong
2022年12月6日 11:48

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/221205544069/
相关话题:https://www.cnsre.cn/tags/aws/


躺了好久,诈尸了。因为换了工作,所以比较忙一直没有时间去更新博客的内容(主要还是因为懒🤔)

话不多说 直接上干货。

需求背景

最近在看费用的时候发现有很大一部分费用都是 cloudwatch log中存储了大量的数据,是因为ec2 将日志传输到了存储到了cloudwatch中。这个存储的多的查询日志的时候收费特别的高。另外一个是因为数据分析用途,大数据分析的同事如果想那到数据的话,还是存储在 S3 中是比较划算和方便的,一个是拿取数据比较方便,另外一个是S3 可以最归档存储,后面的大量数据可以分层储存,以此来降低费用。
如果你也想将你的cloudwatch 中日志组中的日志存储到S3中的话可以参考下这篇文章。

前置条件

  • 创建 一个 S3 桶,并修改权限
  • 创建 lambda 函数
  • 有一个Cloudwatch 日志组并且有一天以上的日志
  • 给 lambda分配所需的权限

创建 S3 桶并修改权限

sre运维|Linux运维|关键词

国内S3桶权限配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.cn-north-1.amazonaws.com.cn"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws-cn:s3:::<bucket name>"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.cn-north-1.amazonaws.com.cn"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws-cn:s3:::<bucket name>/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

国外S3桶权限配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
    "Version": "2012-10-17",
    "Statement": [
      {
          "Action": "s3:GetBucketAcl",
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::<bucket name>",
          "Principal": { "Service": "logs.us-west-2.amazonaws.com" }
      },
      {
          "Action": "s3:PutObject" ,
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::<bucket name>*",
          "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
          "Principal": { "Service": "logs.us-west-2.amazonaws.com" }
      }
    ]
}

S3 桶权限文档链接

创建 lambda 函数

创建 lambda

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import boto3
import logging
import time
import datetime
import json

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def export_s3_logs(bucket_name, log_group_name, log_stream_name, days_of_logs=1, timeout=1000):
    '''
    today = datetime.datetime.combine(datetime.datetime.utcnow(), datetime.datetime.min.time())
    day_end = today
    day_start = today - datetime.timedelta(days=days_of_logs)
    '''
    today = datetime.datetime.combine(datetime.datetime.utcnow() + datetime.timedelta(hours=8),
                                      datetime.datetime.min.time()) # UTC+8 

    day_end = today - datetime.timedelta(hours=8) # UTC
    day_start = today - datetime.timedelta(days=days_of_logs, hours=8) # UTC    
   
    #print(day_start)
    ts_start = '{0:.0f}'.format(((day_start - datetime.datetime(1970, 1, 1)).total_seconds())*1000)
    ts_end = '{0:.0f}'.format(((day_end - datetime.datetime(1970, 1, 1)).total_seconds())*1000)
    the_date = '/'.join([str(today.year), '0'+str(today.month)[-2:], '0'+str(today.day)[-2:]]) 
    #folder_name = '/'.join([log_group_name, log_stream_name, the_date])
    folder_name = '/'.join([log_group_name,the_date])
    client = boto3.client('logs')
    
    #print (ts_start, ts_end)#, day_start, day_end,the_date
    
    task_id = client.create_export_task(
        logGroupName=log_group_name,
        #logStreamNamePrefix=log_stream_name,
        fromTime=int(ts_start),
        to=int(ts_end),
        destination=bucket_name,
        destinationPrefix=folder_name
    )['taskId']

    i = 1
    while i<timeout:
        response = client.describe_export_tasks(
            taskId=task_id
        )

        status = response['exportTasks'][0]['status']
        if status == 'COMPLETED':
            result = True
            break
        elif status != 'RUNNING':
            result = False
            break
        i += 1
        time.sleep(interval)
    
    return result

def lambda_handler(event, context):
    region = 'cn-northwest-1' # 日志组所在区域
    bucket_name = '<bucket name>' #同区域内的S3桶名称
    log_group_name = '<log group name>' #日志组名称
    log_stream_name = '1' #默认即可
    log_export_days = 1   #默认即可
    export_s3_logs(bucket_name, log_group_name, log_stream_name, log_export_days)

给 lambda 分配权限

  • AmazonS3的读写权限
  • CloudWatchLogsFullAccess

验证桶内的文件

最后会以日期的目录将日志归档起来,以方便日后对归档文件进行梳理。
sre运维|Linux运维|关键词


作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/221205544069/
相关话题:https://www.cnsre.cn/tags/aws/


eks使用efs dynamic provisioning 创建非root容器提示 Operation not permitted

作者 Wenlong
2022年1月25日 14:50

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/220125450139/
相关话题:https://www.cnsre.cn/tags/eks/


前言

之前在 aws 中创建了 eks,在数据存储这一块中,我选择了使用 AWS 的 EFS 具体部署配置参考Amazon EKS 中 EFS 持久性存储。文章中的动态供给是 AWS 官方给的示例,使用的是root用户启动的容器。在我后面的测试中发现,我在使用非root用户启动容器的时候,发现使用静态供给是有权限并且没有报错的。但是在使用静载供给的时候出现了 Operation not permitted 的报错。

问题描述

我根据efs dynamic_provisioning 创建了 dynamic provisioning
root用户的容器运行没有问题,但是非root用户容器运行时提示 “Operation not permitted”

pod配置清单:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

StorageClass配置清单:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-xxxxx
  directoryPerms: "700"
  gidRangeStart: "1000" # optional
  gidRangeEnd: "2000" # optional
  basePath: "/dynamic_provisioning" # optional

分析和检查

该报错是由于采用了dynamic provisioning PV部署方式,这种模式的实现需要利用 efs-ap:access point访问点 模式做 EFS 挂载。从 EFS 的角度来讲,EFSaccess point 模式挂载的 EFS 卷,客户端不可修改 uid/gid ,只拥有使用权(读写)详情点击查看。从自己的pod环境也可以看到,客户端挂载目录/dynamic_provisioning 的uid跟gid都是一个随机数字。 ls -l /dynamic_provisioning可以看到是 `1018 (不同环境uid会不同)。

EFS-AP模式指的是access point访问点模式。关于访问点的介绍:
EFS Access Points:
An access point applies an operating system user, group, and file system path to any file system request made using the access point. The access point’s operating system user and group override any identity information provided by the NFS client.
简单来讲,EFS-AP也就是access point访问点挂载模式下,efs客户端的路径user/gid是不可被修改的。的客户端用户只有使用权(读写),但是不可以修改owner。因此遇到的报错是该配置的预期表现。

EFS-AP模式的配置是在storageclass中定义的:provisioningMode: efs-ap,比如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
kind: StorageClass
apiVersion: storage.k8s.io/v1 
metadata:
  name: efs-sc-dynamic
provisioner: efs.csi.aws.com 
parameters:
  provisioningMode: efs-ap    <<<<<<<<<<<<<<------------------------------EFS访问点挂载模式
  fileSystemId: fs-xxxxxx
  directoryPerms: "700"
  gidRangeStart: "1000" # optional
  gidRangeEnd: "2000" # optional
  basePath: "/dynamic_provisioning" # optional

目前AWS EFS的 dynamic provisioning 模式的实现就是使用 storageclassefs-sc-dynamic 模式。
这种模式的弊端已经在 github 中有issue在跟踪,详情点击查看,但是由于该模式也有一定的设计意义 详情点击查看,所以目前还没有明确的结论。

临时解决方法

使用静态模式创建

可以创建EKS pv/pvc时使用static模式部署PV,不会使用access point模式挂载EFS卷,那么可以顺利修改uid/gid。
详情参考Amazon EKS 中 EFS 持久性存储

在pod中指定 uid 和 gid

在创建pod之前,先创建 pvc在创建完pvc后查看uid 和gid

1
2
3
4
5
[root@ip-10-0-100-206 ~]# ls -l /efs/dynamic_provisioning/
total 12
drwxr-xr-x 5 1015 1015 6144 Jan 20 02:44 pvc-40b922c7-8d4d-47d9-8783-60d25abe123
drwxr-xr-x 5 1017 1017 6144 Jan 20 04:22 pvc-4ee000a8-7ab2-4ffc-8fd3-72ef31b7123
drwx------ 5 1014 1014 6144 Jan 20 01:08 pvc-f6622cb3-7c24-4172-a427-d4b9a996122

将输出内容的pvc的uid gid 记下并在pod的yaml清单中指定uid已经gid让pod拥有该目录的权限。
pod配置清单:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      securityContext:
        fsGroup: 1014
        runAsUser: 1014
        runAsGroup: 1014
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kubectl get pv|grep  mysql 
pvc-f6622cb3-7c24-4172-a427-d4b9a9962cd8   5Gi   RWX   Delete   Bound   default/mysql-pv-claim   efs-sc      5d23h

kubectl get  pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim   Bound    pvc-f6622cb3-7c24-4172-a427-d4b9a9962cd8   5Gi        RWX            efs-sc         5d23h

kubectl get  pod
NAME                               READY   STATUS    RESTARTS   AGE
wordpress-mysql-6f6455f449-52zrp   1/1     Running   0          5d7h

作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/220125450139/
相关话题:https://www.cnsre.cn/tags/eks/


kubectl 彩色输出 -- kubecolor

作者 Wenlong
2021年12月10日 09:52

作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211210952578/
相关话题:https://www.cnsre.cn/tags/kubernetes/


kubecolor 是什么?

kubecolor 为您的kubectl命令输出着色,不执行任何其他操作。kubecolor 在内部调用kubectlcommand 并尝试对输出进行着色,以便你可以使用 kubecolor 作为 kubectl 的完整替代方案。

kubecolor项目地址

安装

通过 GitHub 发布下载

git clone https://github.com/dty1er/kubecolor.git

通过 go 命令手动构建

cd kubecolor/
go build -o kubecolor cmd/kubecolor/main.go

构建后,得到一个 kubecolor 的文件

sre运维|Linux运维|自动化运维|kubectl彩色输出kubecolor

设置默认 kubectl 使用 kubecolor

echo "alias kubectl='/root/kubecolor/kubecolor" >> ~/.bashrc
# 使配置生效
source .bashrc

效果展示

kubectl get pods

sre运维|Linux运维|自动化运维|kubectl彩色输出kubecolor

kubectl describe

sre运维|Linux运维|自动化运维|kubectl彩色输出kubecolor


作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211210952578/
相关话题:https://www.cnsre.cn/tags/kubernetes/


快速搭建 kvm web 管理工具 WebVirtMgr

作者 Wenlong
2021年11月17日 09:37

作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211117937177/
相关话题:https://www.cnsre.cn/tags/kvm/


WebVirtMgr是近两年来发展较快,比较活跃,非常清新的一个KVM管理平台,提供对宿主机和虚机的统一管理,它有别于kvm自带的图形管理工具(virtual machine manager),让kvm管理变得更为可视化,对中小型kvm应用场景带来了更多方便。

WebVirtMgr介绍

WebVirtMgr采用几乎纯Python开发,其前端是基于Python的Django,后端是基于Libvirt的Python接口,将日常kvm的管理操作变的更加的可视化。

  • WebVirtMgr 特点

操作简单,易于使用 、通过libvirt的API接口对kvm进行管理、提供对虚拟机生命周期管理

  • WebVirtMgr 功能

宿主机管理支持以下功能、CPU利用率、内存利用率、网络资源池管理、存储资源池管理、虚拟机镜像、虚拟机克隆、快照管理、日志管理、虚机迁移、虚拟机管理支持以下功能、CPU利用率、内存利用率、光盘管理、关/开/暂停虚拟机、安装虚拟机、VNC console连接、创建快照

官方文档

https://github.com/retspen/webvirtmgr/wiki/Install-WebVirtMgr

安装前的部署

安装一些依赖包

1
yum -y install git python-pip libvirt-python libxml2-python python-websockify supervisor nginx gcc python-devel wget vim net-tools lrzsz 

安装pip

1
2
3
wget https://bootstrap.pypa.io/get-pip.py 
python get-pip.py 
pip -V 

sre运维|Linux运维|自动化运维|关键词

1
pip install numpy

sre运维|Linux运维|自动化运维|关键词

安装python的需要包和配置Django环境

1
git clone git://github.com/retspen/webvirtmgr.git

sre运维|Linux运维|自动化运维|关键词

安装nginx

1
2
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 
yum install nginx -y

安装supervisor

安装参考

https://www.2cto.com/kf/201712/702837.html

开机自启参考

https://blog.csdn.net/binggoogle/article/details/53203991

1
cat  /etc/supervisord.conf

⚠️ 注意

如果没有这个文件按照一下步骤安装

有的话忽略此步骤

1
2
3
pip install supervisor
mkdir /etc/supervisord.d/
echo_supervisord_conf > /etc/supervisord.conf

新建文件夹

1
vim /etc/supervisord.d/app.conf

配置文件 app.conf

内容为

1
2
3
4
5
6
7
8
[program:appname]
command=/root/soft/push.api
directory=/root/soft/push.api
autostart=true
autorestart=true
user=root
stdout_logfile = /var/log/supervisor/pushapi.log
stderr_logfile = /var/log/supervisor/pushapi-error.log

修改 在配置文件最下方修改为

1
2
3
vim  /etc/supervisord.conf
[include]
files = /etc/supervisord.d/*.ini

sre运维|Linux运维|自动化运维|关键词

1
2
3
supervisord -c /etc/supervisord.conf
/usr/bin/supervisorctl start all
/usr/bin/supervisorctl stop all

安装环境

1
2
cd webvirtmgr 
pip install -r requirements.txt 

sre运维|Linux运维|自动化运维|关键词

1
./manage.py syncdb

sre运维|Linux运维|自动化运维|关键词

创建用户

输入以下用户信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'root'): admin
Email address: 275301281@qq.com
Password: admin
Password (again):admin 
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 6 object(s) from 1 fixture(s)
./manage.py collectstatic

配置一个超级用户

1
./manage.py createsuperuser

sre运维|Linux运维|自动化运维|关键词

1
2
3
4
5
6
WARNING:root:No local_settings file found.
Username (leave blank to use 'root'): yes
Email address: 275301281@qq.com
Password: Lenovo@123
Password (again): Lenovo@123
Superuser created successfully.

设置nginx

a、使用:8000端口

移动这个 webvirtmgr 目录到 /var/www

1
2
cd  ..
mv webvirtmgr /var/www/
⚠️ 注意:
webvirtmgr 目录下还有一个名称为webvirtmgr 的文件夹
不要单独移动 webvirtmgr/webvirtmgr 文件

sre运维|Linux运维|自动化运维|关键词

编辑配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
vim /etc/nginx/conf.d/webvirtmgr.conf

server {
    listen 80 default_server;

    server_name $hostname;
    #access_log /var/log/nginx/webvirtmgr_access_log; 

    location /static/ {
        root /var/www/webvirtmgr/webvirtmgr; # or /srv instead of /var
        expires max;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
        proxy_send_timeout 600;
        client_max_body_size 1024M; # Set higher depending on your needs 
    }
}

启动nginx并设置开机自启动

(如果不设置开机自启动,重启服务器supervisor无法管理Django进程),并开机自启动supervisord

1
/etc/init.d/nginx start

或者

1
2
systemctl restart   nginx 
systemctl enable supervisord 

分配权限

1
chown nginx.nginx /var/www/webvirtmgr

设置supervisor

/etc/supervisord.conf末尾加入下面的配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
vi /etc/supervisord.conf


[program:webvirtmgr]
command=/usr/bin/python /var/www/webvirtmgr/manage.py run_gunicorn -c /var/www/webvirtmgr/conf/gunicorn.conf.py
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
logfile=/var/log/supervisor/webvirtmgr.log
log_stderr=true
user=nginx

[program:webvirtmgr-console]
command=/usr/bin/python /var/www/webvirtmgr/console/webvirtmgr-console
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
#stdout_logfile=/var/log/supervisor/webvirtmgr-console.log
redirect_stderr=true
user=nginx	

⚠️ 注意

进程无法启动或者报错 可以选择吧 log 注释取消

重启supervisord

开机自启参考

https://blog.csdn.net/binggoogle/article/details/53203991

设置完之后重启即可

1
2
3
systemctl restart  supervisord.service
systemctl enable  supervisord.service
systemctl status   supervisord.service 

sre运维|Linux运维|自动化运维|关键词

更新

1
cd /var/www/webvirtmgr git pull

sre运维|Linux运维|自动化运维|关键词

1
./manage.py collectstatic

sre运维|Linux运维|自动化运维|关键词

1
systemctl  restart supervisord

如果有错误或不运行

1
2
3
4
 ./manage.py runserver 0:8000
#或者后台运行脚本
nohup python  /var/www/webvirtmgr/manage.py runserver 0:8000  >/dev/null &
nohup python  /var/www/console/webvirtmgr-console   >/dev/null &

访问:http://x.x.x.x:8000(x.x.x.x - your server IP address ),输入创建的用户和密码,如果没有创建,请用python manager.py createsuperuser,命令创建。登录后如下图所示

sre运维|Linux运维|自动化运维|关键词

配置虚拟机所在宿主机

webvirtmgr客户端就这样搭建完了,接下来需要配置虚拟机所在宿主机的,参考git地址.

配置宿主机

下载并执行脚本

如果虚拟机比较多,该脚本执行时间会比较长,因为会执行 service libvirt-guests restart,会将所有运行的虚拟机挂起然后再恢复,感觉这一步不是必须的,因为我有一台只设置ssh认证,也可以正常连接。

1
curl http://retspen.github.io/libvirt-bootstrap.sh | sudo sh

如果没有curl就用wget

1
wget -O - http://retspen.github.io/libvirt-bootstrap.sh | sudo sh

配置防火墙

1
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 16509 -j ACCEPT

设置TCP授权

参考:https://github.com/retspen/webvirtmgr/wiki/Setup-TCP-authorization

webvirtmgr新建服务器连接时需要此账号

用saslpasswd2命令给libvirt的用户cnsre设置密码

1
2
3
saslpasswd2 -a libvirt cnsre
Password: cnsre
Again (for verification): cnsre

生成一个密码库

1
2
3
sasldblistusers2 -f /etc/libvirt/passwd.db 

cnsre@webvirtmgr.cn: userPassword

设置ssh授权

1
ssh-keygen -t rsa       # 产生公私钥

直接回车,回车,回车

sre运维|Linux运维|自动化运维|关键词

1
ssh-copy-id 192.168.1.120  

⚠️ 注意

由于这里webvirtmgr和kvm服务部署在同一台机器,所以这里本地信任。

如果kvm部署在其他机器,那么这个是其他它的ip 同时也要设置ssh key密钥

提示输入密码的时候直接输入之前1.120的密码

sre运维|Linux运维|自动化运维|关键词

1
ssh 192.168.1.120 -L localhost:8000:localhost:8000 -L localhost:6080:localhost:6080

web 平台加入其他kvm宿主机

sre运维|Linux运维|自动化运维|关键词

在部署web管理的主机上执行命令

1
ssh-keygen -t rsa

然后在执行

1
ssh-copy-id 192.168.1.165

sre运维|Linux运维|自动化运维|关键词

添加新的kvm宿主机

sre运维|Linux运维|自动化运维|关键词

查看新加的kvm宿主机状态 看有无报错

sre运维|Linux运维|自动化运维|关键词

删除新加的账号

1
sudo saslpasswd2 -a libvirt -d cnsre

确认验证新加的账号配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
virsh -c qemu+tcp://IP_address/system nodeinfo
(virsh -c qemu+tcp://192.168.1.50/system nodeinfo)
Please enter your authentication name: cnsre
Please enter your password: xxxxxx
CPU model:           x86_64
CPU(s):              2
CPU frequency:       2611 MHz
CPU socket(s):       1
Core(s) per socket:  2
Thread(s) per core:  1
NUMA cell(s):        1
Memory size:         2019260 kB

⚠️ 注意

账号全名带hostname,如 cnsre@webvirtmgr.cn

测试的时候这一步测试没有成功 但是可以链接

设置ssh认证

ssh和tcp设置一种即可,其实就是设置无密码登录,要注意的是从webvirtmgr的什么用户到宿主机的什么用户的无密码登录,比如我用root跑的django webvirtmgr,而宿主机也是root跑的virsh,所以需要设置root到root的无密码登录。而git官网推荐的是用nginx用户跑django webvirtmgr,webvirtmgr用户跑的virsh,所以设置的是nginx用户到宿主机webvirtmgr用户的无密码登录。

参考:https://github.com/retspen/webvirtmgr/wiki/Setup-SSH-Authorizatio

使用tcp认证连接服务器

访问:http://192.168.1.120:8000,xxxx是webvirtmgr的ip地址,点击new connection

填写kvm宿主机的一些信息

sre运维|Linux运维|自动化运维|关键词

基础架构可以看到一些vm虚拟机

sre运维|Linux运维|自动化运维|关键词

KVM WEB管理常见报错

网页控制台 远程链接报错1006

安装vnc即可

1
yum install -y novnc

网页控制台 远程链接报错505

1
2
cd /var/www/console/
./webvirtmgr-console  &

后台运行脚本

1
2
nohup python  /var/www/webvirtmgr/manage.py runserver 0:8000  >/dev/null & 
nohup python  /var/www/console/webvirtmgr-console   >/dev/null &

其他web管理 webvirtcloud

webvirtcloud 的作者还是 webvirtmgr的作者,但是 webvirtmgr 已经有好久没有维护了。如果你想体验 webvirtcloud 你可以安装webvirtcloud。

webvirtcloud 特征

  • QEMU/KVM 管理程序管理
  • QEMU/KVM 实例管理 - 创建、删除、更新
  • 虚拟机管理程序和实例基于 Web 的统计信息
  • 管理多个 QEMU/KVM 管理程序
  • 管理管理程序数据存储池
  • 管理管理程序网络
  • 使用浏览器访问实例控制台
  • 基于 Libvirt API 的 Web 管理 UI
  • 基于用户的授权和认证
  • 用户可以在实例中将 SSH 公钥添加到 root(仅测试 Ubuntu)
  • 用户可以在实例中更改 root 密码(仅测试 Ubuntu)
  • 支持 cloud-init 数据源接口
    webvirtcloud具体文档请查看 webvirtcloud 项目

webvirtcloud 的作者也贴心的提供了一键脚本

1
2
3
wget https://raw.githubusercontent.com/retspen/webvirtcloud/master/install.sh 
chmod 744 install.sh #以 sudo 或 root 用户运行
./install.sh

作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211117937177/
相关话题:https://www.cnsre.cn/tags/kvm/


一键安装java、tomcat脚本

作者 Wenlong
2021年11月12日 08:39

作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211112839379/
相关话题:https://www.cnsre.cn/tags/shell/


前言

最近有几台新上的设备,需要安装jdk和tomcat。为了避免以后这种重复的劳动力,我决定写一个脚本,直接执行脚本就可以自动选择你安装的jdk以及tomcat的脚本,来避免这种问题。

脚本内容

此脚本只针对于centos7完成测试,其他版本未测试。使用时请注意。
脚本内容如下

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
LANG=en_US.UTF-8

RD="\033[31m"      # 错误消息
GR="\033[32m"      # 成功消息
YL="\033[33m"      # 告警消息
BL="\033[36m"      # 日志消息
PL='\033[0m'

clear
echo -e "${YL}##################################################${PL}"
echo -e "${YL}#${PL}${GR}脚本名称${PL}: 一键安装java、tomcat脚本              ${YL}#${PL}"
echo -e "${YL}#${PL}${GR}作    者${PL}: sre运维博客                           ${YL}#${PL}"
echo -e "${YL}#${PL}${GR}网    址${PL}: www.cnsre.cn                          ${YL}#${PL}"
echo -e "${YL}#${PL}${GR}文章地址${PL}: https://cnsre.cn/posts/211112839379/  ${YL}#${PL}"
echo -e "${YL}##################################################${PL}"
sleep 0.5

echo -e "${RD}本脚本将会自动安装1.8.0_221版本jdk以及8.5.23版本tomcat,请确认是否安装?${PL}"
read -r -p "确定请按 y 任意键则退出!请选择:[y/n]" input
    if [[ $input != "y" ]]; then
        exit 1
    else
        echo -e "${GR}正在下载java tomcat安装包,请稍后${PL}"
    fi
wget -q -c  https://pan.cnsre.cn/d/Package/Linux/jdk/tomcat-8.5.23_jdk1.8.0_221.tar.gz
tar -zxf  tomcat-8.5.23_jdk1.8.0_221.tar.gz
sleep 0.5

echo -e "${RD}是否确定安装 1.8.0_221 版本 jdk? ${PL}"
read -r -p "确定请按 y 任意键则退出!请选择:[y/n]" input
    if [[ $input != "y" ]]; then
        exit 1
    else 
        echo -e "${GR}你已经选择安装1.8.0_221版本 jdk${PL}"
    fi
read -r -p "请选择安装jdk的绝对路径,请不要输入最后的"/":" input

if [ ! -d $input ]; then
  echo -e "${RD}你输入的路径不存在,请重新输入或者创建后再次执行脚本${PL}"
  exit 1
fi

echo -e "${GR}正在安装 1.8.0_221 版本 jdk${PL}"
mv jdk1.8.0_221 $input/jdk

cat << EOF >> /etc/profile 
############## JAVA ##############
export JAVA_HOME=$input/jdk
export JAVA_BIN=$JAVA_HOME/bin
export JAVA_LIB=$JAVA_HOME/lib
export CLASSPATH=.:$JAVA_LIB/tools.jar:$JAVA_LIB/dt.jar
export PATH=$JAVA_BIN:$PATH
EOF




echo -e "${GR}验JAVA home及版本${PL}"
sleep 2
chmod +x $input/jdk/bin/java
chmod +x $input/jdk/jre/bin/java
source /etc/profile
echo -e"${GR}你的java安装路径为:$JAVA_HOME ${PL}"
java  -version


echo -e "${RD}是否确定安装 8.5.23  版本 tomcat ? ${PL}"
read -r -p "确定请按 y 任意键则退出!请选择:[y/n]" input
    if [[ $input != "y" ]]; then
        exit 1
    else
        echo -e "${GR}你已经选择安装 8.5.23 版本 tomcat ${PL}"
    fi
read -r -p "请选择安装tomcat的绝对路径,请不要输入最后的"/":" input

if [ ! -d $input ]; then
  echo -e "${RD}你输入的路径不存在,请重新输入或者创建后再次执行脚本${PL}"
  exit 1
fi

echo -e "${GR}正在安装 8.5.23 版本 tomcat${PL}"
mv apache-tomcat-8.5.23  $input/tomcat

chmod +x $input/tomcat/bin/*.sh

echo -e "${GR}正在将tomcat加入系统服务${PL}"
sleep 2
touch /usr/lib/systemd/system/tomcat.service
cat << EOF >> /usr/lib/systemd/system/tomcat.service
[Unit]  
Description=Tomcat
After=syslog.target network.target remote-fs.target nss-lookup.target  

[Service]  
Type=forking  

ExecStart=$input/tomcat/bin/startup.sh
ExecReload=$input/tomcat/bin/startup.sh
ExecStop=$input/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target
EOF
sed -i '2i\export JAVA_HOME='$JAVA_HOME'' $input/tomcat/bin/catalina.sh

systemctl  daemon-reload
systemctl  restart tomcat.service
systemctl  status  tomcat.service

echo -e "${RD}请确认是否选择开机启动tomcat ? ${PL}"
read -r -p "确定请按 y 任意键则退出!请选择:[y/n]" input
    if [[ $input != "y" ]]; then
        systemctl  disable  tomcat.service
        echo -e "${GR}已为你关闭tomcat开机启动 ${PL}"
    else
        systemctl  enable  tomcat.service
        echo -e "${GR}已为你开启tomcat开机启动 ${PL}"
    fi

echo -e "${YL}==================================================================${PL}"
echo -e "${GR}tomcat部署完成并启动${PL}"
echo -e "${YL}==================================================================${PL}"
echo -e "${GR}外网tomcat地址: http://$(curl -sS --connect-timeout 10 -m 60 cip.cc |grep IP|awk -F ':[ ]' '{print $2}'):8080${PL}"
echo -e "${GR}内网tomcat地址: http://$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1):8080${PL}"
echo -e "${GR}你可以通过以下命令来管理tomcat服务${PL}"
echo -e "${GR}启动tomcat服务:systemctl  start tomcat.service${PL}"
echo -e "${RD}停止tomcat服务:systemctl  stop tomcat.service${PL}"
echo -e "${YL}重启tomcat服务:systemctl  restart tomcat.service${PL}"
echo -e "${GR}若无法访问tomcat,请检查防火墙/安全组是否有放行tomcat 8080 端口${PL}"
echo -e "${GR}==================================================================${PL}"


作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211112839379/
相关话题:https://www.cnsre.cn/tags/shell/


kvm 安装 windows 虚拟机

作者 Wenlong
2021年11月8日 08:48

作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211108848062/
相关话题:https://www.cnsre.cn/tags/kvm/


安装前准备

验证CPU是否支持KVM

如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的。

1
egrep '(vmx|svm)' /proc/cpuinfo

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

关闭SELinux

/etc/sysconfig/selinux 中的 SELinux=enforcing 修改为 SELinux=disabled

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

安装一些最基本的服务

可选项,因为我是刚安装好的CentOS,所以为了下面方便点,先把一些必要的工具安装下

1
yum install epel-release net-tools vim unzip zip wget ftp -y

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

安装KVM及其依赖项

1
yum install qemu-kvm libvirt virt-install bridge-utils -y

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

验证安装结果

下图说明已经成功安装了

1
lsmod | grep kvm

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

开启kvm服务

并且设置其开机自动启动

1
systemctl start libvirtd systemctl enable libvirtd

查看状态操作结果

如下图所示,说明运行情况良好

1
systemctl status libvirtd

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

1
systemctl is-enabled libvirtd

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

配置网桥模式

先将 /etc/sysconfig/network-scripts/ 目录下的网卡配置文件备份一份

创建 ifcfg-br0 文件

创建的 br0文件的IP地址要和物理网卡的IP地址一致,命令 ipconfig 查看物理网卡将不会显示IP

内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[root@bogon ~]*# vim /etc/sysconfig/network-scripts/ifcfg-br0*

DEVICE=br0
BOOTPROTO=none
DEFROUTE=yes
ONBOOT=yes
TYPE=Bridge
IPV4_FAILURE_FATAL=yes
IPADDR=192.168.1.130
NETMASK=255.255.255.0
GATEWAY=192.168.1.254
DNS1=221.6.4.66
DELAY=0
USERCE=no

修改原网卡配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
vim /etc/sysconfig/network-scripts/ifcfg-eno1s
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="YES"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="eno1"
UUID="bb40d726-8d67-4187-90c3-eb61e1b42d61"
DEVICE="eno1"
ONBOOT="yes"
IPADDR="192.168.1.130"
NETAMSK=255.255.255.0
GATEWAY="192.168.1.254"
DNS1="221.6.4.66"
IPV6_PRIVACY="no"
BRIDGE=br0

重启网络服务

1
systemctl restart network

使用 ifconfig 验证操作结果,多了一块网卡 br0 ,现在访问宿主机 使用 192.168.1.130 就可以了。

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

<script async src=“https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4855142804875926"
crossorigin=“anonymous”>

安装虚拟机

准备操作系统安装镜像文件

在本文中将使用和宿主环境一样的 CentOS7.2,把该文件放到 /home/iso 目录下

挂载U盘

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
[root@nkgtsv01 ~]# fdisk -l
WARNING: fdisk GPT support is currently new, and therefore in an experimental phase. Use at your own discretion.

磁盘 /dev/sda:2995.0 GB, 2994995200000 字节,5849600000 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节
磁盘标签类型:gpt
Disk identifier: 434CB2EB-C42E-4B9D-A76B-B759709EC159


#         Start          End    Size  Type            Name
 1         2048       206847    100M  EFI System      EFI System Partition
 2       206848       616447    200M  Microsoft basic
 3       616448   5849597951    2.7T  Linux LVM

磁盘 /dev/mapper/centos-root:214.7 GB, 214748364800 字节,419430400 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节


磁盘 /dev/mapper/centos-swap:17.2 GB, 17179869184 字节,33554432 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节


磁盘 /dev/mapper/centos-home:322.1 GB, 322122547200 字节,629145600 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节


磁盘 /dev/mapper/centos-tmp:107.4 GB, 107374182400 字节,209715200 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节


磁盘 /dev/mapper/centos-data:2333.2 GB, 2333249372160 字节,4557127680 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节


磁盘 /dev/sdb:31.0 GB, 31004295168 字节,60555264 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xcad4ebea            需要挂载的硬盘

   设备 Boot      Start         End      Blocks   Id  System
/dev/sdb4   *         256    60555263    30277504    7  HPFS/NTFS/exFAT
[root@nkgtsv01 ~]# mkdir -p /mnt/udisk
[root@nkgtsv01 ~]# ls
anaconda-ks.cfg
[root@nkgtsv01 ~]# ls /mnt/
udisk  usb
[root@nkgtsv01 ~]# mount -t ntfs-3g /dev/sdb4 /mnt/udisk/
mount: 未知的文件系统类型“ntfs-3g”

[root@nkgtsv01 ~]# yum list *ntfs*
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.sjtu.edu.cn
 * epel: mirrors.ustc.edu.cn
 * extras: ftp.sjtu.edu.cn
 * updates: ftp.sjtu.edu.cn
可安装的软件包
ntfs-3g.x86_64                              2:2017.3.23-1.el7                        epel
ntfs-3g-devel.x86_64                        2:2017.3.23-1.el7                        epel
ntfsprogs.x86_64                            2:2017.3.23-1.el7                        epel

已安装:
  ntfs-3g.x86_64 2:2017.3.23-1.el7

完毕!
[root@nkgtsv01 ~]#yum install ntfs-3g.x86_64 -y

[root@nkgtsv01 ~]# mount -t ntfs-3g /dev/sdb4 /mnt/udisk/
The disk contains an unclean file system (0, 0).
The file system wasn't safely closed on Windows. Fixing.

[root@nkgtsv01 ~]#
[root@nkgtsv01 ~]# ls /mnt/
udisk  usb
[root@nkgtsv01 ~]# ls /mnt/udisk/
CentOS-7.2-x86_64-DVD-1611.iso  CentOS-7-x86_64-DVD-1708.iso  maven_storey2.zip
[root@bogon data]# mkdir -p /data/iso
[root@bogon data]# ls
iso  kvm-bak  network
[root@nkgtsv01 ~]# mount  -o loop /mnt/udisk/CentOS-7-x86_64-DVD-1708.iso /data/iso/
mount: /dev/loop0 写保护,将以只读方式挂载

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

创建虚拟机文件存放的目录

1
mkdir -p /data/kvm-images

⚠️ 注意

关于virtio-win驱动

virtio-win驱动主要用于kvm里的 windows虚拟机。virtio-win提供yum源安装rpm包,virtio驱动默认会安装在/usr/share/virtio-win目录中,可共享于kvm里的windows虚拟机。

sudo wget https://fedorapeople.org/groups/virt/virtio-win/virtio-win.repo -O /etc/yum.repos.d/virtio-win.repo
# 添加repo

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

该repo文件提供两个不同的仓库:

  • virtio-win-stable
    默认,该仓库的版本和RHEL版本关联在一起发布,意味着得到了非常多的测试,很稳定。

  • virtio-win-latest
    该仓库提供最新的build版本,这些版本可能有各种问题,用户需自己承担风险。这个仓库默认是disable的。如果你想从稳定版更新到最新版,可以使用如下命令:

    1
    
    sudo yum --enablerepo=virtio-win-latest update virtio-win
    

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

安装完成后的文件会存放在/user/share,内容如下:

/usr/share/virtio-win/*.iso: ISO镜像,包含所有驱动,详细内容后面会描述
/usr/share/virtio-win/*.vfd: 用于Windows XP下的VFD软驱镜像
/usr/share/virtio-win/drivers: 从VFD软驱镜像中提取的文件
/usr/share/guest-agent/*.msi: QEMU Guest Agent 32bit 和 64bit 安装包

其中ISO镜像内容为:

NetKVM/: Virtio网络驱动
viostor/: Virtio块驱动
vioscsi/: Virtio SCSI驱动
viorng/: Virtio RNG驱动
vioser/: Virtio串口驱动
Balloon/: Virtio 内存气球驱动
qxl/: 用于Windows 7及之前版本的QXL显卡驱动. (virtio-win-0.1.103-1和之后版本会创建)
qxldod/: 用于Windows 8及之后版本的QXL显卡驱动. (virtio-win-0.1.103-2和之后版本会创建)
pvpanic/: QEMU pvpanic 设备驱动 (virtio-win-0.1.103-2和之后版本会创建)
guest-agent/: QEMU Guest Agent 32bit 和 64bit 安装包
qemupciserial/: QEMU PCI 串口设备驱动

或者你也可以通过一下方获取

稳定版virtio-win iso

稳定版virtio-win x86 floppy

稳定版virtio-win amd64 floppy

最新版virtio-win iso

最新版virtio-win x86 floppy

最新版virtio-win amd64 floppy

最新版qemu-ga files

全部下载目录

变更日志

使用 virt-install 创建虚拟机

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[root@bogon data]# virt-install --virt-type kvm --name=njvm2k8 --ram=1024 --vcpus=1 --os-type=windows --accelerate --cdrom=/home/kvm_data/iso/cn_windows_server_2008_r2_617396.iso --disk path=/usr/share/virtio-win/virtio-win.iso,device=cdrom --disk path=/home/kvm_data/img/njvm2k8.qcow2,bus=virtio --network bridge=br0 --graphics vnc,listen=0.0.0.0,password=123456,port=5920 --noautoconsole
 

WARNING  无法连接到图形控制台:没有安装 virt-viewer。请安装 'virt-viewer' 软件包。
WARNING  没有控制台用于启动客户机,默认为 --wait -1
开始安装......
正在分配 'njvm2k8.img'                                   | 200 GB  00:00:00
正在删除磁盘 'njvm2k8.img'                                |    0 B  00:00:00
域安装失败,您可以运行下列命令重启您的域:
'virsh start virsh --connect qemu:///system start njvm2k8'
否则请重新开始安装

不要理会里面提示的错误,接着往下走

命令含义

virt-install 
--name=客户机名称  
--ram 内存(1024)1G 
--vcpus= cpu1 
--os-type= 客户机系统类型  
--os-variant= win2k8 
--disk path= 客户机文件存放路径 ,
size=客户机硬盘大小200 
--accelerate 
--cdrom  (镜像文件路径) 
--vnc --vncport=vnc远程端口 5910 
--network bridge=网卡桥接 br0,model=virtio 
--noautoconsole

打开防火墙上的5910端口

因为 VNC 使用的端口默认是 5910 所以需要打开防火墙, 防火墙若关闭请忽略

1
 firewall-cmd --zone=public --add-port=5910/tcp --permanent              

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

查看打开新创建的虚拟机

1
2
virsh list --all
virsh start njvm2k8-win

使用VNC链接虚拟机

vncviewer下载地址

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

使用VNC输入宿主机IP地址 加上端口号 输入虚拟机名字然后打开

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

⚠️ 注意

安装的时候找不到硬盘

如果再安装的时候找不到硬盘,请执行一下操作

挂载win镜像

1
virsh change-media njvm2k8  hdb /usr/share/virtio-win/virtio-win.iso    

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

然后取消挂载的镜像 把系统镜像 从新挂载到系统 进行分区 安装系统

安装完毕重启虚拟机

安装完会重启windows虚拟机

我们查看状态 然后启动虚拟机

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

等待安装完成

启动之后设置密码 我们就进入了新的windows 操作系统

用vnc链接

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012

⚠️ 注意
挂载软驱 (硬盘驱动 网卡驱动等)注释:网卡驱动要在系统中装好之后挂载 不然装系统的时候会提示找不到光盘镜像

在宿主机中执行命令

1
virsh change-media njvm2k8  hdb /usr/share/virtio-win/virtio-win.iso 

VMTools工具安装完成后,使用如下命令卸载掉挂载的VMTools工具:

a.如果是Linux虚拟机,执行如下命令卸载VMTools工具:

virsh change-media 【虚拟机ID】 --eject 【vmtools-linux.iso文件全路径】

b.如果是Windows虚拟机,执行如下命令卸载VMTools工具:

virsh change-media 【虚拟机ID】 --eject 【vmtools-windows.iso文件全路径】

挂载驱镜像文件到njvm2k8主机上

用vnc链接

sre运维|Linux运维|自动化运维|kvm安装windows虚拟机|kvm安装windows虚拟机找不到硬盘|kvm安装windows虚拟机找不到网卡|kvm安装windows虚拟机报错|kvm安装widnows2012


作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211108848062/
相关话题:https://www.cnsre.cn/tags/kvm/


Centos7搭建 KVM 命令行安装虚拟机

作者 Wenlong
2021年11月5日 08:52

作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211105852095/
相关话题:https://www.cnsre.cn/tags/kvm/


本文将介绍centos7 环境如何搭建一个kvm 环境并且创建windows,linux等虚拟机。

安装前准备

验证CPU是否支持KVM

如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的。

1
egrep '(vmx|svm)' /proc/cpuinfo

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

关闭SELinux

/etc/sysconfig/selinux 中的 SELinux=enforcing 修改为 SELinux=disabled

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

安装一些最基本的服务

可选项,因为我是刚安装好的CentOS,所以为了下面方便点,先把一些必要的工具安装下

1
yum install epel-release net-tools vim unzip zip wget ftp -y

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

安装KVM及其依赖项

1
yum install qemu-kvm libvirt virt-install bridge-utils -y

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

验证安装结果

下图说明已经成功安装了

1
lsmod | grep kvm

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

开启kvm服务

并且设置其开机自动启动

1
systemctl start libvirtd systemctl enable libvirtd

查看状态操作结果

如下图所示,说明运行情况良好

1
systemctl status libvirtd

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

1
systemctl is-enabled libvirtd

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

配置网桥模式

先将 /etc/sysconfig/network-scripts/ 目录下的网卡配置文件备份一份

创建 ifcfg-br0 文件

创建的 br0文件的IP地址要和物理网卡的IP地址一致,命令 ipconfig 查看物理网卡将不会显示IP

内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@bogon ~]# vim /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
BOOTPROTO=none
DEFROUTE=yes
ONBOOT=yes
TYPE=Bridge
IPV4_FAILURE_FATAL=yes
IPADDR=192.168.1.130
NETMASK=255.255.255.0
GATEWAY=192.168.1.254
DNS1=221.6.4.66
DELAY=0
USERCE=no

修改原网卡配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
vim /etc/sysconfig/network-scripts/ifcfg-eno1s
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="YES"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="eno1"
UUID="bb40d726-8d67-4187-90c3-eb61e1b42d61"
DEVICE="eno1"
ONBOOT="yes"
IPADDR="192.168.1.130"
NETAMSK=255.255.255.0
GATEWAY="192.168.1.254"
DNS1="221.6.4.66"
IPV6_PRIVACY="no"
BRIDGE=br0

重启网络服务

1
systemctl restart network

使用 ifconfig 验证操作结果,多了一块网卡 br0 ,现在访问宿主机 使用 192.168.1.130 就可以了。

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

安装虚拟机

准备操作系统安装镜像文件

在本文中将使用和宿主环境一样的 CentOS7.2,把该文件放到 /home/iso 目录下

挂载U盘

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@nkgtsv01 ~]# yum install fuse-ntfs-3g -y
[root@nkgtsv01 ~]# ls /mnt/
udisk  usb
[root@nkgtsv01 ~]# ls /mnt/udisk/
CentOS-7.2-x86_64-DVD-1611.iso  CentOS-7-x86_64-DVD-1708.iso  maven_storey2.zip
[root@bogon data]# mkdir -p /data/iso
[root@bogon data]# ls
iso  kvm-bak  network
[root@nkgtsv01 ~]# mount  -o loop /mnt/udisk/CentOS-7-x86_64-DVD-1708.iso /data/iso/
mount: /dev/loop0 写保护,将以只读方式挂载

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

创建虚拟机文件存放的目录

1
mkdir -p /data/kvm-images

使用 virt-install 创建虚拟机

1
virt-install --virt-type=kvm --name=njkvm07 --vcpus=4 --memory=6000 --location=/data/iso/CentOS-7-x86-64-DVD-1708.iso --disk path=/data/kvm-images/njkvm07.qcow2,size=200,format=qcow2 --network bridge=br0 --graphics none --extra-args='console=ttyS0' --force

执行完这段命令

感叹号为待选项

c保存 q退出 b开始执行安装

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

选择地区时间

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

选则之后c保存

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

自动返回主页面

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

选择硬盘

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

选择到硬盘 c保存

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

全新安装 C保存

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

选则添加IP地址和添加主机名称

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

输入 回车

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

添加IP地址

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

选则ipv4

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

添加IP地址回车

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

添加netmask gateway c 保存

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

添加密码

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

B开始执行安装

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

安装完成

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

宿主机直接连接到虚拟机

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

等待重启虚拟机,虚拟机起开之后直接远程就ok了 。

virt-clone克隆虚拟机

使用 virt-clone 克隆新的虚拟机

(虚拟机需要先关闭)

1
virt-clone -o njvm02 -n njvm03 -f /data/kvm-img/njvm03.img

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

克隆完查看 所有的虚拟机以及状态

1
virsh list --all

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

删除虚拟机 njvm01

1
2
virsh undefine njvm01 
virsh destroy njvm01

⚠️ 注意

取消定义 删除以后要找到虚拟机文件路径吧虚拟机文件也删除掉

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

1
2
3
4
5
[root@nkgtsv01 data]# virsh shutdown njvm01
域 njvm01 被关闭
[root@nkgtsv01 data]# virsh start njvm02
域 njvm02 已开始
[root@nkgtsv01 data]# virsh list --all

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

⚠️ 注意

克隆完以后因为IP地址还是njvm01的IP地址所以我们要修改IP地址

开启我们克隆的虚拟机

远程登陆上去

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@nkgtsv-vm01 ~]# cd /etc/sysconfig/network-scripts/
[root@nkgtsv-vm01 network-scripts]# ls
ifcfg-eth0   ifdown-ppp       ifup-eth     ifup-sit
ifcfg-lo     ifdown-routes    ifup-ippp    ifup-Team
ifdown       ifdown-sit       ifup-ipv6    ifup-TeamPort
ifdown-bnep  ifdown-Team      ifup-isdn    ifup-tunnel
ifdown-eth   ifdown-TeamPort  ifup-plip    ifup-wireless
ifdown-ippp  ifdown-tunnel    ifup-plusb   init.ipv6-global
ifdown-ipv6  ifup             ifup-post    network-functions
ifdown-isdn  ifup-aliases     ifup-ppp     network-functions-ipv6
ifdown-post  ifup-bnep        ifup-routes
[root@nkgtsv-vm01 network-scripts]# vim ifcfg-eth0

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

sre运维|Linux运维|自动化运维|centos7搭建kvm|kvm创建虚拟机|kvm克隆

IPADDR=192.168.1.121 改为我们想要的IP地址

保存退出

Service network restart

重启网络

重新链接

参考文档:
http://www.linuxidc.com/Linux/2017-01/140007.htm
http://blog.csdn.net/u011414200/article/details/47310827
https://www.cnblogs.com/5201351/p/4445199.html
http://blog.51cto.com/7834466/2064277
https://www.cnblogs.com/Yemilice/p/8080688.html


作者:SRE运维博客
博客地址: https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/211105852095/
相关话题:https://www.cnsre.cn/tags/kvm/


大于2T硬盘安装 Redhat 系统

作者 Wenlong
2021年10月27日 09:57

作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/211027957506/
相关话题:https://www.cnsre.cn/tags/故障集/


最近接到一个case 涉及到Linux下面大硬盘(大于2T)的使用,以后大家遇到大硬盘的可能性会越来越多,特把处理过程分享出来,以供大家参考

问题背景

Dell r85 机架式服务器 配置6个1T硬盘, 做完底层raid后,操作系统可以认到3T

问题

在实际使用中,系统只用到2T的空间,最后1T始终无法分区,报错如下:

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

原因分析

安装Linux时,使用了普通的MBR模式 ,对主流主板BIOS而言,MBR分区定义每个扇区512字节,磁盘寻址32位地址,所能访问的磁盘容量最大是2.19TB(512 * 232),因此系统能使用的最大空间也为2T

解决方案

通过咨询Dell 原厂,提供了两个解决方案

1.安装Linux 系统时重新更改 BIOS的启动模式为UEFI

2.重新划分底层 raid 划分为一个小于 2T 的盘做为安装系统的盘,另一个大于2T的盘做为数据盘使用.

实操过程

在遇到大硬盘后,最好电询原厂,看是否支持UEFI

另外: 在划分区时,如果选择自定义,在redhat 6.X 之后要必须要新建 /boot/efi 分区.大小不能小于 100M 我在实际操作时设置了200M

原厂的解释是:

/boot/efi/ partition (100 MB minimum) — the partition mounted on /boot/efi/ contains all the installed kernels, the initrd images, and ELILO configuration files.

修改BIOS中设置,下面以Dell R815 为例说明修改

1.重启主机,按F2 进入BIOS 设置 (或按各厂商提示),

出现该界面后,按 F2 ,

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

生效后如下图

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

在引导到一定阶段后会自动进入BIOS 设置,按方向键上,下选择 [Boot Settings] 后,回车

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

在小窗口用方向键选择 [Boot Mode] 使用 -/+ 选择启动方式为 [UEFI]

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

修改后ESC退出时保存

note: uEFI does not read from legacy mbr labels

2.更改磁盘的 disk lable 更改为 GPT

因为On hardware where uEFI is enabled, the boot disk must have a GPT partition label

在安装任意介面,输入 Ctrl+Alt+F2 切换到命令行介面,使用 parted 更改 disk lable为 gpt

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

note: 如果是已经安装过系统的主机,这一步时必须要先将旧分区全部删除,才能更改成功

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

因为是重装,所以要先把旧分区删除,红框标示出来的就是传统的 mbr 模式,只能支持最大2T 的硬盘

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

删除旧分区

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

更改 disk label 为 gpt

sre运维|Linux运维|自动化运维|大于2T硬盘安装 Redhat 系统

更改完成后,使用 Ctrl+Alt+F6 回切至安装界面,按正常步骤安装即可


作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/211027957506/
相关话题:https://www.cnsre.cn/tags/故障集/


zabbix 通过 agent 监控进程、端口

作者 Wenlong
2021年10月25日 09:12

作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/211025912047/
相关话题:https://www.cnsre.cn/tags/zabbix/


环境介绍

操作系统:centos 7.4

zabbix版本:zabbix server 3.4.7

客户端:zabbix-agent 3.4.7

监控进程:mysqld

监控端口:3306 tcp

进程监控

确认客户端已经安装且运行agent

sre运维|Linux运维|自动化运维|zabbix进程端口监控

查看进程

查看属于那个用户的 几个进程

mysql 的进程为root用户 两个进程

sre运维|Linux运维|自动化运维|zabbix进程端口监控

添加监控项

sre运维|Linux运维|自动化运维|zabbix进程端口监控

名称随便写

类型zabbix客户端

键值选则进程数返回数

应用集选则prosesses 进程

sre运维|Linux运维|自动化运维|zabbix进程端口监控

proc.num[<name>,<user>,<state>,<cmdline>]

以下是对mysql进程的监控配置,key中的参数说明,

<name>第一个参数是进程名字,没必要填写,填了反而会使监控不太准确(仅个人测试)

<user>第二个参数是运行进程的用户名

<state>第三个为进程的状态 ,一般选则all 包括:all (default), run, sleep, zomb

<cmdline>第四个参数用来指定进程名中包含的字符,对进程进行过滤。

确认更新

sre运维|Linux运维|自动化运维|zabbix进程端口监控

创建触发器

sre运维|Linux运维|自动化运维|zabbix进程端口监控

sre运维|Linux运维|自动化运维|zabbix进程端口监控

选择刚才创建的监控项

sre运维|Linux运维|自动化运维|zabbix进程端口监控

插入

sre运维|Linux运维|自动化运维|zabbix进程端口监控

sre运维|Linux运维|自动化运维|zabbix进程端口监控

修改{hgh3a01:proc.num[,root,all,mysqld].last()}=0

{hgh3a01:proc.num[,root,all,mysqld].max(#2)}=2

hgh3a01:主机名称

proc.num[,root,all,mysqld]:监控项

max(#2)}=2 :表示最后两次的接收到的值都是2个进程(ps -ef 看到 mysqld 的进程为两个所以=2 ),说明mysqld进程在运行,则出发报警。

因为我们要测试是否能出发告警,所以要选则 =2 正常的<1 就是没有运行。

稍等几分钟观察看看能不能触发触发器

sre运维|Linux运维|自动化运维|zabbix进程端口监控

收到邮箱警告

sre运维|Linux运维|自动化运维|zabbix进程端口监控

吧测试的进程改为正常的(因为mysql 运行的进程为两个我这变设置的触发器为进程小于两个进程就发出告警)

sre运维|Linux运维|自动化运维|zabbix进程端口监控

保存更新观察是否回复正常

sre运维|Linux运维|自动化运维|zabbix进程端口监控

sre运维|Linux运维|自动化运维|zabbix进程端口监控

监控端口

添加监控项

sre运维|Linux运维|自动化运维|zabbix进程端口监控

修改端口 保存更新

sre运维|Linux运维|自动化运维|zabbix进程端口监控

同监控进程一样(先测试)

sre运维|Linux运维|自动化运维|zabbix进程端口监控

收到触发警告

sre运维|Linux运维|自动化运维|zabbix进程端口监控

吧之前的值调整为0

sre运维|Linux运维|自动化运维|zabbix进程端口监控

测试回复正常

sre运维|Linux运维|自动化运维|zabbix进程端口监控


作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/211025912047/
相关话题:https://www.cnsre.cn/tags/zabbix/


zabbix自定义监控磁盘分区

作者 Wenlong
2021年10月21日 09:50

作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/211021950307/
相关话题:https://www.cnsre.cn/tags/zabbix/


系统环境

Zabbix 版本:3.4

操作系统版本:centos7.4

监控分区 / 、/boot 、/home

先创建监控项的模板

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

点击创建监控项

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

名称随意填写,键值的话因为我们监控车的是磁盘剩余的百分比所有选则次键值,应用集则选则filsystems

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

选则键值

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

选则添加我们的监控项已经创建。

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

查看监控项看下创建测监控项是否异常。

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

选则需要监控的主机

接下来我们来创建监控项。

监控项名称随意填写。

然后吧严重性选则为一般告警(因为我们短信邮箱告警等级是一般告警以上的告警等级推送)

选则我们刚才创建的监控项

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

修改表达式

写出监控的分区我们这以home分区为例。

cnsre运维|Linux运维|自动化运维|zabbix自定义监控磁盘分区

完成以后添加即可。


作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/211021950307/
相关话题:https://www.cnsre.cn/tags/zabbix/


journal log日志的问题

作者 Wenlong
2021年9月28日 09:57

作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/210928957081/
相关话题:https://www.cnsre.cn/tags/故障集/


前言

线上服务器磁盘告警
cnsre运维博客|Linux系统运维|自动化运维|云计算|运维监控
登录服务器检查磁盘发现一个叫做 journal 的文件夹占用了大量空间。

问题分析

Journald是什么

  • journalcentos7systemd 的一个组件,由 journald处理。捕获系统日志信息、内核日志信息,以及来自原始RAM磁盘的信息,早期启动信息以及所有服务中写入 STDOUTSTDERR 数据流的信息。可以说是为 Linux 服务器打造的一种新系统日志方式,这些日志信息写入到二进制文件,使用 journalctl 阅读,默认存放在 /run/log/ 下。

Journald系统主要由三个主要的系统日记服务组件组成

  • 守护程序:systemd 日志服务由 systemd-journald 守护程序处理。
  • 配置文件:日志服务的配置在 /etc/systemd/journald.conf 里面设置。
  • 日志搜索程序:用于搜索日记日志文件的程序是 journalctl

journalctl使用

journalctl 常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
journalctl               #查看所有日志
journalctl -n 5          #查看最后5条日志
journalctl -p err        #查看err类型的日志
journalctl -f            #不断输出最后10条日志
journalctl --since today #查看今天的日志
journalctl --since "2021-9-28 08:00:00" --until "2021-9-28 09:00:00"
journalctl -o verbose    #查看日志详细信息
journalctl --disk-usage  #检查当前journal使用磁盘量
journalctl --vacuum-time=2d #只保存2天的日志
journalctl --vacuum-size=500M #最大500M
journalctl --verify      #检查journal是否运行正常以及日志文件是否完整无损坏

持久保存日志

由于 journald 默认是保存在内存中,一旦服务器重启,就会丢失,作为生成环境,管理员必须保证系统任何日志不能丢失,通过修改配置文件做持久保存。
同时,systemd-journald.service 的配置文件主要参考 /etc/systemd/journald.conf 的内容,详细的参数可以参考如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[Journal]
#日志存储到磁盘
Storage=persistent 
#压缩日志
Compress=yes 
#为日志添加序列号
Seal=yes 
#每个用户分别记录日志
SplitMode=uid 
#日志同步到磁盘的间隔,高级别的日志,如:CRIT、ALERT、EMERG 三种总是实时同步
SyncIntervalSec=1m 

#即制日志的最大流量,此处指 30s 内最多记录 100000 条日志,超出的将被丢弃
RateLimitInterval=30s 
#与 RateLimitInterval 配合使用
RateLimitBurst=100000

#限制全部日志文件加在一起最多可以占用多少空间,默认值是10%空间与4G空间两者中的较小者
SystemMaxUse=64G 
#默认值是15%空间与4G空间两者中的较大者
SystemKeepFree=1G 

#单个日志文件的大小限制,超过此限制将触发滚动保存
SystemMaxFileSize=128M 

#日志滚动的最大时间间隔,若不设置则完全以大小限制为准
MaxFileSec=1day
#日志最大保留时间,超过时限的旧日志将被删除
MaxRetentionSec=100year 

#是否转发符合条件的日志记录到本机的其它日志管理系统,如:rsyslog
ForwardToSyslog=yes 
ForwardToKMsg=no
#是否转发符合条件的日志到所有登陆用户的终端
ForwardToWall=yes 
MaxLevelStore=debug 
MaxLevelSyslog=err 
MaxLevelWall=emerg 
ForwardToConsole=no 
#TTYPath=/dev/console
#MaxLevelConsole=info
#MaxLevelKMsg=notice

处理过程

知道了这些,就可以轻松的处理这些日志了。
检查当前journal使用磁盘量

1
journalctl --disk-usage

清理方法可以采用按照日期清理,或者按照允许保留的容量清理,只保存2天的日志,最大500M

1
2
journalctl --vacuum-time=2d
journalctl --vacuum-size=500M

要启用日志限制持久化配置,可以修改

1
2
3
4
5
6
vim /etc/systemd/journald.conf
SystemMaxUse=16M
ForwardToSyslog=no

# 重启 
systemctl restart systemd-journald.service

检查journal是否运行正常以及日志文件是否完整无损坏

1
journalctl --verify

作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/210928957081/
相关话题:https://www.cnsre.cn/tags/故障集/


国外镜像拉取到docker hub

作者 Wenlong
2021年9月24日 09:25

作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/210924925541/
相关话题:https://www.cnsre.cn/tags/docker/


文章链接
在学习K8S 的过程中总,部分镜像需要从 k8s.grc.io 仓库中拉拉取。但是因为网络的问题导致无法拉取狗歌的镜像,也就导致了创建 pod 拉取镜像失败。
今天就跟大家分享下我从国外拉到国内的镜像。

替换规则

同理,其他镜像地址也可以用该 dockerhub 的地址。
具体替换规则:
k8s.gcr.io 替换为 cnsre
ingress-nginx/controller 替换为 ingress-nginx-controller

1
2
3
k8s.gcr.io/ingress-nginx/controller:v1.0.0
# 等同于 
cnsre/ingress-nginx-controller:v1.0.0

举例

比如 ingress 中的镜像地址为 k8s.gcr.io/ingress-nginx/controller:v1.0.0
需要将镜像地址更改为:cnsre/ingress-nginx-controller:v1.0.0

docker pull k8s.gcr.io/ingress-nginx/controller:v1.0.0
# 等同于
docker pull cnsre/ingress-nginx-controller:v1.0.0

dockerhub 中没有的镜像

如果 cnsre 仓库中没有的一些国外镜像需要下载的话,你可以在地址留言(最好在留言中补充邮箱信息,这样你就可以收到通知。)


作者:SRE运维博客
博客地址:https://www.cnsre.cn
文章地址:https://www.cnsre.cn/posts/210924925541/
相关话题:https://www.cnsre.cn/tags/docker/


❌
❌