Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ The script downloads the latest release, extracts it to `/usr/local/pulse`, and

## Configuration

Pulse reads a `config.yml` file from the **current working directory**. The file has two sections:
Pulse reads a `config.yml` file from the **current working directory**. The file has the following sections:

- **`services`** — a map of service names to lists of `host:port` addresses for TCP connectivity checks
- **`elasticsearch`** — Elasticsearch-specific configuration with credentials for authenticated HTTP health checks
- **`kibana`** — Kibana-specific configuration with credentials for authenticated HTTP status checks
- **`redis`** — Redis-specific configuration with optional password for protocol-level checks
- **`minio`** — MinIO-specific configuration with credentials and addresses for authenticated connection checks

```yaml
Expand All @@ -60,17 +63,32 @@ services:
- 10.0.31.131:30310
nacos:
- 10.0.31.131:30848
redis:
- 10.0.1.38:6379
- 10.0.1.38:6380
kafka:
- 10.0.1.30:9092
elasticsearch:
- 10.0.1.24:9300
kibana:
- 10.0.1.26:5601
zookeeper:
- 10.0.1.27:3000
- 10.0.1.27:2181,10.0.1.28:2181,10.0.1.29:2181
zk-ui:
- 10.0.1.27:9090

elasticsearch:
addresses:
- 10.0.1.24:9200
- 10.0.1.25:9200
- 10.0.1.26:9200
username: elastic
password: changeme

kibana:
addresses:
- 10.0.1.26:5601
username: elastic
password: changeme

redis:
password: ""
addresses:
- 10.0.1.38:6379
- 10.0.1.38:6380

minio:
username: minioadmin
Expand All @@ -79,7 +97,9 @@ minio:
- 10.0.1.35:9000
```

Add or remove services under `services` as needed — any service name is accepted. The `minio` section is optional; omit it if you do not need MinIO checks.
**Elasticsearch** connects via the HTTP API (`/_cluster/health`) and supports Basic Auth. `username` and `password` are optional — omit them for clusters with security disabled.

Add or remove services under `services` as needed — any service name is accepted. The `elasticsearch`, `kibana`, `redis`, and `minio` sections are optional; omit them if not needed.

## Usage

Expand All @@ -93,9 +113,10 @@ Pulse will:

1. Load `config.yml`.
2. Attempt a TCP connection to every address under `services` (3-second timeout per address).
3. Attempt an authenticated connection to every MinIO address using the provided `username` and `password`.
4. Print a report to standard output.
5. Write detailed logs to `logs/<timestamp>/`.
3. Check the Elasticsearch cluster health via HTTP API using optional Basic Auth credentials.
4. Attempt an authenticated connection to every MinIO address using the provided `username` and `password`.
5. Print a report to standard output.
6. Write detailed logs to `logs/<timestamp>/`.

### Example output

Expand Down Expand Up @@ -170,7 +191,7 @@ cp docker/config.yml config.yml
|----|-----|---------------------|
| Nacos | <http://localhost:8848/nacos> | nacos / nacos |
| MinIO console | <http://localhost:9001> | minioadmin / minioadmin |
| Kibana | <http://localhost:5601> | |
| Kibana | <http://localhost:5601> | elastic / changeme |
| ZooKeeper Navigator | <http://localhost:9090> | — |

### Tear down
Expand Down Expand Up @@ -207,7 +228,7 @@ Use the provided build scripts in the `build/` directory, or set the environment
```
pulse/
├── build/ # Platform-specific build scripts
├── checker/ # TCP connection checker package
├── checker/ # TCP and Elasticsearch connection checker package
├── config/ # YAML configuration loader package
├── logger/ # Structured logger (success / failure / report)
├── scripts/ # Installation script
Expand Down
39 changes: 39 additions & 0 deletions checker/elasticsearch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// checker/elasticsearch.go
package checker

import (
"fmt"
"io"
"net/http"
"time"
)

// CheckElasticsearch 通过 Elasticsearch HTTP API(/_cluster/health)验证单个节点的连通性。
// 若提供了 username 或 password,则使用 HTTP Basic Auth 进行认证。
func CheckElasticsearch(address, username, password string, timeout time.Duration) error {
client := &http.Client{Timeout: timeout}
url := fmt.Sprintf("http://%s/_cluster/health", address)

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return fmt.Errorf("创建请求失败: %w", err)
}

if username != "" || password != "" {
req.SetBasicAuth(username, password)
}

resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("连接失败: %w", err)
}
defer resp.Body.Close()
if _, err = io.Copy(io.Discard, resp.Body); err != nil {
return fmt.Errorf("读取响应失败: %w", err)
}

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("HTTP 状态 %d", resp.StatusCode)
}
return nil
}
1 change: 0 additions & 1 deletion checker/zookeeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"
)


// CheckZookeeperConnection 验证 Zookeeper 节点的连通性,使用 Zookeeper 四字命令 "ruok"。
// connectString 可以是单个 "host:port",也可以是标准 Zookeeper 连接字符串,
// 例如 "host1:2181,host2:2181,host3:2181" 或 "host1:2181,host2:2181/chroot"。
Expand Down
13 changes: 8 additions & 5 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ services:
- 10.0.1.30:9092
- 10.0.1.31:9092
- 10.0.1.32:9092
elasticsearch:
- 10.0.1.24:9300
- 10.0.1.25:9300
- 10.0.1.26:9300
zookeeper:
- 10.0.1.27:2181,10.0.1.28:2181,10.0.1.29:2181
zk-ui:
Expand All @@ -26,6 +22,14 @@ redis:
- 10.0.1.40:6379
- 10.0.1.40:6380

elasticsearch:
addresses:
- 10.0.1.24:9200
- 10.0.1.25:9200
- 10.0.1.26:9200
username: elastic
password: changeme

kibana:
addresses:
- 10.0.1.26:5601
Expand All @@ -37,4 +41,3 @@ minio:
password: minioadmin
addresses:
- 10.0.1.35:9000

18 changes: 13 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import (
// NetworkConfig 定义了各个服务的地址列表,键为服务名称,值为字符串数组
type NetworkConfig map[string][]string

// ElasticsearchConfig 保存 Elasticsearch 集群的连接参数
type ElasticsearchConfig struct {
Addresses []string `yaml:"addresses"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}

// KibanaConfig 定义了 Kibana 服务的连接配置,支持用户名和密码认证
type KibanaConfig struct {
Addresses []string `yaml:"addresses"`
Expand All @@ -32,12 +39,13 @@ type RedisConfig struct {
Addresses []string `yaml:"addresses"`
}

// AppConfig 顶层配置结构,包含通用 TCP 服务、MinIO、Kibana 和 Redis 专项配置
// AppConfig 顶层配置结构,包含通用 TCP 服务、MinIO、Kibana、RedisElasticsearch 专项配置
type AppConfig struct {
Services NetworkConfig `yaml:"services"`
Minio *MinioConfig `yaml:"minio"`
Kibana KibanaConfig `yaml:"kibana"`
Redis RedisConfig `yaml:"redis"`
Services NetworkConfig `yaml:"services"`
Minio *MinioConfig `yaml:"minio"`
Kibana KibanaConfig `yaml:"kibana"`
Redis RedisConfig `yaml:"redis"`
Elasticsearch *ElasticsearchConfig `yaml:"elasticsearch"`
}

// LoadConfig 从指定文件中读取 YAML 配置,并解析为 AppConfig 类型
Expand Down
9 changes: 6 additions & 3 deletions docker/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ services:
kafka:
- localhost:9092

elasticsearch:
- localhost:9300

redis:
password: ""
addresses:
- localhost:6379

elasticsearch:
addresses:
- localhost:9200
username: elastic
password: changeme

kibana:
addresses:
- localhost:5601
Expand Down
13 changes: 8 additions & 5 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# Default credentials
# MinIO console http://localhost:9001 minioadmin / minioadmin
# Nacos console http://localhost:8848/nacos nacos / nacos
# Kibana http://localhost:5601
# Kibana http://localhost:5601 elastic / changeme
# ZK Navigator http://localhost:9090

version: "3.9"
Expand Down Expand Up @@ -113,12 +113,13 @@ services:
environment:
discovery.type: single-node
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
xpack.security.enabled: "false"
xpack.security.enabled: "true"
ELASTIC_PASSWORD: "changeme"
ports:
- "9200:9200" # HTTP API
- "9300:9300" # transport (inter-node / monitored by Pulse)
- "9200:9200" # HTTP API (monitored by Pulse)
- "9300:9300" # transport (inter-node)
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:9200/_cluster/health"]
test: ["CMD", "curl", "-sf", "-u", "elastic:changeme", "http://localhost:9200/_cluster/health"]
interval: 30s
timeout: 10s
retries: 5
Expand All @@ -130,6 +131,8 @@ services:
container_name: pulse-kibana
environment:
ELASTICSEARCH_HOSTS: "http://elasticsearch:9200"
ELASTICSEARCH_USERNAME: "elastic"
ELASTICSEARCH_PASSWORD: "changeme"
ports:
- "5601:5601"
depends_on:
Expand Down
11 changes: 10 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func main() {
}
}

// ── 通用 TCP 服务检测(zookeeper 使用专用检测器)────────────────────
// ── 通用 TCP 服务检测(zookeeper/kafka 使用专用检测器)───────────────
for service, addresses := range cfg.Services {
results[service] = ServiceResult{Success: []string{}, Failure: []string{}}

Expand All @@ -98,6 +98,15 @@ func main() {
}
}

// ── Elasticsearch 集群(HTTP API + 可选 Basic Auth)──────────────────
if cfg.Elasticsearch != nil {
results["elasticsearch"] = ServiceResult{Success: []string{}, Failure: []string{}}
for _, addr := range cfg.Elasticsearch.Addresses {
err := checker.CheckElasticsearch(addr, cfg.Elasticsearch.Username, cfg.Elasticsearch.Password, timeout)
recordResult(results, "elasticsearch", addr, err, successLogger, failureLogger)
}
}

// ── MinIO 认证连接检测 ────────────────────────────────────────────────
if cfg.Minio != nil {
results["minio"] = ServiceResult{Success: []string{}, Failure: []string{}}
Expand Down
Loading