Compare commits

...
Author SHA1 Message Date
tomsun28 0db72b0f02 update 2025-05-04 11:43:51 +08:00
tomsun28 6c7cb62fd8 [refactor] update
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-04 11:26:21 +08:00
tomsun28andCopilot a5b8a95991 Update hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/util/AlertTemplateUtil.java
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-04 09:58:09 +08:00
tomsun28 e5693476f2 Merge branch 'master' into encoding-file-default 2025-05-04 00:07:41 +08:00
tomsun28 650d63d6eb [refactor] update
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-02 16:30:53 +08:00
tomsun28 1f46260469 [refactor] update job
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-02 16:27:20 +08:00
tomsun28 c73e47711e [refactor] update alert fingerprints column max length
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-02 16:06:39 +08:00
tomsun28 826e7b1dd9 [refactor] update alert fingerprints column max length
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-02 15:47:54 +08:00
tomsun28 ecb7f82321 [doc] update blog 2025-05-01 20:31:29 +08:00
tomsun28 5ac13827fb [refactor] set default encoding charset utf8
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-01 20:23:58 +08:00
tomsun28 383ba7d976 [refactor] set default encoding charset utf8
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-05-01 19:16:09 +08:00
20 changed files with 412 additions and 404 deletions
@@ -52,86 +52,84 @@ final class DbAlertStoreHandlerImpl implements AlertStoreHandler {
log.error("The Group Alerts is empty, ignore store");
return groupAlert;
}
// 1. Find existing alert group
GroupAlert existGroupAlert = groupAlertDao.findByGroupKey(groupAlert.getGroupKey());
// 2. Process individual alerts
// Process individual alerts
Set<String> alertFingerprints = new HashSet<>(8);
List<SingleAlert> originalAlerts = groupAlert.getAlerts();
List<SingleAlert> newAlerts = new ArrayList<>();
for (SingleAlert singleAlert : originalAlerts) {
SingleAlert existAlert = singleAlertDao.findByFingerprint(singleAlert.getFingerprint());
if (existAlert != null) {
// Update the existing alert with the ID and creation time from the database
singleAlert.setId(existAlert.getId());
singleAlert.setGmtCreate(existAlert.getGmtCreate());
// Status transition logic
if (CommonConstants.ALERT_STATUS_FIRING.equals(singleAlert.getStatus())) {
// If the alert is firing and the existing alert is not resolved, update the start time and trigger times
if (!CommonConstants.ALERT_STATUS_RESOLVED.equals(existAlert.getStatus())) {
synchronized (singleAlert.getFingerprint().intern()) {
SingleAlert existAlert = singleAlertDao.findByFingerprint(singleAlert.getFingerprint());
if (existAlert != null) {
// Update the existing alert with the ID and creation time from the database
singleAlert.setId(existAlert.getId());
singleAlert.setGmtCreate(existAlert.getGmtCreate());
// Status transition logic
if (CommonConstants.ALERT_STATUS_FIRING.equals(singleAlert.getStatus())) {
// If the alert is firing and the existing alert is not resolved, update the start time and trigger times
if (!CommonConstants.ALERT_STATUS_RESOLVED.equals(existAlert.getStatus())) {
singleAlert.setStartAt(existAlert.getStartAt());
int triggerTimes = Optional.ofNullable(existAlert.getTriggerTimes()).orElse(1)
+ Optional.ofNullable(singleAlert.getTriggerTimes()).orElse(1);
singleAlert.setTriggerTimes(triggerTimes);
}
} else if (CommonConstants.ALERT_STATUS_RESOLVED.equals(singleAlert.getStatus())) {
// If the alert is resolved, set the end time (if not already set) and copy other fields from the existing alert
if (singleAlert.getEndAt() == null) {
singleAlert.setEndAt(System.currentTimeMillis());
}
singleAlert.setStartAt(existAlert.getStartAt());
int triggerTimes = Optional.ofNullable(existAlert.getTriggerTimes()).orElse(1)
+ Optional.ofNullable(singleAlert.getTriggerTimes()).orElse(1);
singleAlert.setTriggerTimes(triggerTimes);
singleAlert.setActiveAt(existAlert.getActiveAt());
singleAlert.setTriggerTimes(existAlert.getTriggerTimes());
}
} else if (CommonConstants.ALERT_STATUS_RESOLVED.equals(singleAlert.getStatus())) {
// If the alert is resolved, set the end time (if not already set) and copy other fields from the existing alert
if (singleAlert.getEndAt() == null) {
singleAlert.setEndAt(System.currentTimeMillis());
}
singleAlert.setStartAt(existAlert.getStartAt());
singleAlert.setActiveAt(existAlert.getActiveAt());
singleAlert.setTriggerTimes(existAlert.getTriggerTimes());
}
SingleAlert savedSingleAlert = singleAlertDao.save(singleAlert);
newAlerts.add(savedSingleAlert);
alertFingerprints.add(savedSingleAlert.getFingerprint());
}
SingleAlert savedSingleAlert = singleAlertDao.save(singleAlert);
newAlerts.add(savedSingleAlert);
alertFingerprints.add(savedSingleAlert.getFingerprint());
}
groupAlert.setAlerts(newAlerts);
// 3. Process resolved alerts
if (existGroupAlert != null) {
List<String> existFingerprints = existGroupAlert.getAlertFingerprints();
if (existFingerprints != null) {
alertFingerprints.addAll(existFingerprints);
}
// Merge group information
groupAlert.setId(existGroupAlert.getId());
groupAlert.setGmtCreate(existGroupAlert.getGmtCreate());
// Merge other historical information to preserve
Map<String, String> existCommonLabels = existGroupAlert.getCommonLabels();
if (existCommonLabels != null) {
Map<String, String> commonLabels = groupAlert.getCommonLabels();
if (commonLabels != null) {
// filter common label in commonLabels and existCommonLabels
commonLabels = commonLabels.entrySet().stream()
.filter(entry -> existCommonLabels.containsKey(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
groupAlert.setCommonLabels(commonLabels);
// Find existing alert group
synchronized (groupAlert.getGroupKey().intern()) {
GroupAlert existGroupAlert = groupAlertDao.findByGroupKey(groupAlert.getGroupKey());
// Process resolved alerts
if (existGroupAlert != null) {
List<String> existFingerprints = existGroupAlert.getAlertFingerprints();
if (existFingerprints != null) {
alertFingerprints.addAll(existFingerprints);
}
}
Map<String, String> existCommonAnnotations = existGroupAlert.getCommonAnnotations();
if (existCommonAnnotations != null) {
Map<String, String> commonAnnotations = groupAlert.getCommonAnnotations();
if (commonAnnotations != null) {
// filter common annotation in commonAnnotations and existCommonAnnotations
commonAnnotations = commonAnnotations.entrySet().stream()
.filter(entry -> existCommonAnnotations.containsKey(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
groupAlert.setCommonAnnotations(commonAnnotations);
// Merge group information
groupAlert.setId(existGroupAlert.getId());
groupAlert.setGmtCreate(existGroupAlert.getGmtCreate());
// Merge other historical information to preserve
Map<String, String> existCommonLabels = existGroupAlert.getCommonLabels();
if (existCommonLabels != null) {
Map<String, String> commonLabels = groupAlert.getCommonLabels();
if (commonLabels != null) {
// filter common label in commonLabels and existCommonLabels
commonLabels = commonLabels.entrySet().stream()
.filter(entry -> existCommonLabels.containsKey(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
groupAlert.setCommonLabels(commonLabels);
}
}
Map<String, String> existCommonAnnotations = existGroupAlert.getCommonAnnotations();
if (existCommonAnnotations != null) {
Map<String, String> commonAnnotations = groupAlert.getCommonAnnotations();
if (commonAnnotations != null) {
// filter common annotation in commonAnnotations and existCommonAnnotations
commonAnnotations = commonAnnotations.entrySet().stream()
.filter(entry -> existCommonAnnotations.containsKey(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
groupAlert.setCommonAnnotations(commonAnnotations);
}
}
}
// Save alert group
groupAlert.setAlertFingerprints(alertFingerprints.stream().toList());
GroupAlert savedGroupAlert = groupAlertDao.save(groupAlert);
savedGroupAlert.setAlerts(groupAlert.getAlerts());
return savedGroupAlert;
}
// 4. Save alert group
groupAlert.setAlertFingerprints(alertFingerprints.stream().toList());
GroupAlert savedGroupAlert = groupAlertDao.save(groupAlert);
savedGroupAlert.setAlerts(groupAlert.getAlerts());
return savedGroupAlert;
}
}
@@ -21,6 +21,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
/**
* Alarm template keyword matching replacement engine tool
@@ -38,11 +39,11 @@ public final class AlertTemplateUtil {
private static final Pattern PATTERN = Pattern.compile("\\$\\{(\\w+)\\}");
public static String render(String template, Map<String, Object> replaceData) {
if (template == null) {
return null;
if (!StringUtils.hasText(template)) {
return template;
}
if (replaceData == null) {
log.warn("The replaceData is null.");
log.warn("The render replace data is null.");
return template;
}
try {
@@ -50,7 +51,7 @@ public final class AlertTemplateUtil {
StringBuilder builder = new StringBuilder();
while (matcher.find()) {
Object objectValue = replaceData.getOrDefault(matcher.group(1), "NullValue");
String value = objectValue.toString();
String value = objectValue != null ? objectValue.toString() : "NullValue";
matcher.appendReplacement(builder, Matcher.quoteReplacement(value));
}
matcher.appendTail(builder);
@@ -57,6 +57,7 @@ class DbAlertStoreHandlerImplTest {
public void setUp() {
groupAlert = new GroupAlert();
singleAlert = new SingleAlert();
singleAlert.setFingerprint("test-fingerprint");
List<SingleAlert> alerts = new ArrayList<>();
alerts.add(singleAlert);
groupAlert.setAlerts(alerts);
@@ -77,11 +78,13 @@ class DbAlertStoreHandlerImplTest {
when(groupAlertDao.findByGroupKey(groupKey)).thenReturn(null);
SingleAlert savedSingleAlert = new SingleAlert();
savedSingleAlert.setFingerprint("test-finger");
when(singleAlertDao.save(any(SingleAlert.class))).thenReturn(savedSingleAlert);
GroupAlert savedGroupAlert = new GroupAlert();
savedGroupAlert.setGroupKey(groupKey);
when(groupAlertDao.save(any(GroupAlert.class))).thenReturn(savedGroupAlert);
dbAlertStoreHandler.store(groupAlert);
verify(singleAlertDao).save(any(SingleAlert.class));
@@ -17,10 +17,10 @@
package org.apache.hertzbeat.collector.dispatch.timer;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.extern.slf4j.Slf4j;
@@ -87,7 +87,7 @@ public class TimerDispatcher implements TimerDispatch, DisposableBean {
for (Metrics metric : addJob.getMetrics()) {
metric.setInterval(0L);
}
addJob.setIntervals(new LinkedList<>(List.of(0L)));
addJob.setIntervals(new ConcurrentLinkedDeque<>(List.of(0L)));
Timeout timeout = wheelTimer.newTimeout(timerJob, addJob.getInterval(), TimeUnit.SECONDS);
currentTempTaskMap.put(addJob.getId(), timeout);
eventListeners.put(addJob.getId(), eventListener);
@@ -86,7 +86,7 @@ public class GroupAlert {
@Schema(title = "Alert Fingerprints", example = "[\"dxsdfdsf\"]")
@Convert(converter = JsonStringListAttributeConverter.class)
@Column(length = 2048)
@Column(length = 8192)
private List<String> alertFingerprints;
@Schema(title = "The creator of this record", example = "tom")
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -114,7 +115,7 @@ public class Job {
/**
* Refresh time list for one cycle of the job
*/
private LinkedList<Long> intervals;
private ConcurrentLinkedDeque<Long> intervals;
/**
* Whether it is a recurring periodic task true is yes, false is no
*/
@@ -328,7 +329,7 @@ public class Job {
* @param metricsIntervals A unique list composed of intervals for all metrics
* Generate a list of refresh intervals for metric collection
*/
public void generateMetricsIntervals(List<Long> metricsIntervals) {
public synchronized void generateMetricsIntervals(List<Long> metricsIntervals) {
// 1. To find the least common multiple (LCM) of all metric refresh intervals
long lcm = lcm(metricsIntervals);
List<Long> refreshTimes = new LinkedList<>();
@@ -348,14 +349,16 @@ public class Job {
for (int i = 1; i < refreshTimes.size(); i++) {
intervals.add(refreshTimes.get(i) - refreshTimes.get(i - 1));
}
setIntervals(intervals);
setIntervals(new ConcurrentLinkedDeque<>(intervals));
}
public long getInterval() {
if (!CollectionUtils.isEmpty(getIntervals())) {
long interval = getIntervals().remove();
getIntervals().add(interval);
return interval;
public synchronized long getInterval() {
if (!CollectionUtils.isEmpty(this.intervals)) {
Long interval = this.intervals.removeFirst();
if (interval != null) {
this.intervals.addLast(interval);
return interval;
}
}
return getDefaultInterval();
}
@@ -1,103 +1,94 @@
# HertzBeat 升级指导-(Docker Mode)
# HertzBeat Upgrade Guide (Docker Mode)
## Docker 方式升级 - Mysql 数据库
## Docker-based Upgrade
1. 数据备份
### 1. Data Backup
- 备份数据库,将 mysql 数据手动做备份,按需备份
- **Back up the database**: Manually back up MySQL data as needed.
```bash
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" <库名> hertzbeat_backup-`date +%Y-%m-%d`.sql #单库备份
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" > hertzbeat_backup-`date +%Y-%m-%d`.sql # 整库备份
```
```bash
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" <DB_NAME> > hertzbeat_backup-`date +%Y-%m-%d`.sql # Single database
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" --all-databases > hertzbeat_backup-`date +%Y-%m-%d`.sql # Full database
```
- 备份配置文件及数据目录
- **Back up configuration files and data directory**:
```bash
mv application.yml application-bak.yml && mv sureness-bak.yml
cp -R data data-`date +%Y-%m-%d`. bak
```
```bash
mv application.yml application-bak.yml && mv sureness.yml sureness-bak.yml
cp -R data data-`date +%Y-%m-%d`.bak
```
2. 关闭 并移除 HertzBeat 容器
### 2. Stop and Remove the HertzBeat Container
```shell
docker stop hertzbeat && docker rm hertzbeat
```
```bash
docker stop hertzbeat && docker rm hertzbeat
```
3. 升级数据库脚本
### 3. Upgrade Database Schema
打开[https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager/src/main/resources/db/migration](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager/src/main/resources/db/migration) 选择你使用的数据库的目录下相应的 `V160__update_column.sql`文件在 Mysql 执行升级 sql。
Navigate to [HertzBeat GitHub Migration Scripts](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager/src/main/resources/db/migration), select the appropriate `V160__update_column.sql` file under your database type (e.g., MySQL), and execute it in MySQL.
4. 更换镜像重新启动 HertzBeat 容器
### 4. Restart HertzBeat with the New Image
```bash
$ docker run -d -p 1157:1157 -p 1158:1158 \
-v $(pwd)/data:/opt/hertzbeat/data \
-v $(pwd)/logs:/opt/hertzbeat/logs \
-v $(pwd)/application.yml:/opt/hertzbeat/config/application.yml \
-v $(pwd)/sureness.yml:/opt/hertzbeat/config/sureness.yml \
--restart=always \
--name hertzbeat apache/hertzbeat:v1.7.0
```
```bash
docker run -d -p 1157:1157 -p 1158:1158 \
-v $(pwd)/data:/opt/hertzbeat/data \
-v $(pwd)/logs:/opt/hertzbeat/logs \
-v $(pwd)/application.yml:/opt/hertzbeat/config/application.yml \
-v $(pwd)/sureness.yml:/opt/hertzbeat/config/sureness.yml \
--restart=always \
--name hertzbeat apache/hertzbeat:v1.7.0
```
5. 升级配置文件
### 5. Update Configuration Files
参考备份配置根据自己的需求基础上进行修改。
Modify the backup configurations as needed:
- `application.yml`一般需要修改以下部分
- **`application.yml`** (Typical modifications):
默认为:
```yaml
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
hikari:
max-lifetime: 120000
jpa:
show-sql: false
database-platform: org.eclipse.persistence.platform.database.MySQLPlatform
database: mysql
properties:
eclipselink:
logging:
level: SEVERE
```
```yaml
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
hikari:
max-lifetime: 120000
- **`sureness.yml`** (Optional, modify for account/password changes):
jpa:
show-sql: false
database-platform: org.eclipse.persistence.platform.database.MySQLPlatform
database: mysql
properties:
eclipselink:
logging:
level: SEVERE
```
```yaml
account:
- appId: admin
credential: hertzbeat
role: [admin]
- appId: tom
credential: hertzbeat
role: [user]
- appId: guest
credential: hertzbeat
role: [guest]
- appId: lili
credential: 94C6B34E7A199A9F9D4E1F208093B489
salt: 123
role: [user]
```
- `sureness.yml`修改是可选的,一般在你需要修改账号密码时
### 6. Add Database Drivers
```yaml
# account info config
# eg: admin has role [admin,user], password is hertzbeat
# eg: tom has role [user], password is hertzbeat
# eg: lili has role [guest], plain password is lili, salt is 123, salted password is 1A676730B0C7F54654B0E09184448289
account:
- appId: admin
credential: hertzbeat
role: [admin]
- appId: tom
credential: hertzbeat
role: [user]
- appId: guest
credential: hertzbeat
role: [guest]
- appId: lili
# credential = MD5(password + salt)
# plain password: hertzbeat
# attention: digest authentication does not support salted encrypted password accounts
credential: 94C6B34E7A199A9F9D4E1F208093B489
salt: 123
role: [user]
```
Due to Apache Foundations license compliance requirements, HertzBeat cannot include GPL-licensed dependencies (e.g., MySQL, Oracle). Users must manually download drivers and place them in the `ext-lib` directory, then mount it to `/opt/hertzbeat/ext-lib`:
6. 添加相应的数据库驱动
由于 apache 基金会对于 license 合规的要求,HertzBeat 的安装包不能包含 mysqloracle 等 gpl 许可的依赖,需要用户自行添加,用户可通过以下链接自行下载驱动 jar 放到本地 `ext-lib`目录下,然后启动时将`ext-lib`挂载到容器的 `/opt/hertzbeat/ext-lib`目录。
mysql[https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.25.zip](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.18.zip)
oracle(如果你要监控 oracle,这两个驱动是必须的):
[https://download.oracle.com/otn-pub/otn_software/jdbc/234/ojdbc8.jar](https://download.oracle.com/otn-pub/otn_software/jdbc/234/ojdbc8.jar)
[https://repo.mavenlibs.com/maven/com/oracle/database/nls/orai18n/21.5.0.0/orai18n-21.5.0.0.jar](https://repo.mavenlibs.com/maven/com/oracle/database/nls/orai18n/21.5.0.0/orai18n-21.5.0.0.jar?utm_source=mavenlibs.com)
- **MySQL Driver**: [Download MySQL Connector/J 8.0.25](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.25.zip)
- **Oracle Driver** (Required for Oracle monitoring):
- [ojdbc8.jar](https://download.oracle.com/otn-pub/otn_software/jdbc/234/ojdbc8.jar)
- [orai18n-21.5.0.0.jar](https://repo.mavenlibs.com/maven/com/oracle/database/nls/orai18n/21.5.0.0/orai18n-21.5.0.0.jar)
@@ -1,43 +1,41 @@
# HertzBeat 从 1.6.1 版本升级到 1.7.0 版本指引-(Helm Mode)
# HertzBeat Upgrade Guide from v1.6.1 to v1.7.0 (Helm Mode)
## 1. 前置准备
1. 确保已安装以下工具:
## 1. Prerequisites
1. Ensure the following tools are installed:
- Helm 3.x
- kubectl
- Git (可选)
- Git (optional)
2. 确认当前部署信息:
2. Verify current deployment information:
```bash
helm list -n <your-namespace>
# 如果你老版本的chart包不见了,可以使用以下命令导出values.yaml文件
# If the old chart package is missing, export values.yaml with:
helm get values hertzbeat -n <your-namespace> > hertzbeat-1.6.1-values.yaml
```
3. 数据备份
3. Data Backup:
> 1. 若使用了自定义监控模版
> **For custom monitoring templates:**
>
> - 需要备份 `kubectl cp hertzbeat/hertzbeat-978477f84-fr894:/opt/hertzbeat/define ./define` 当前运行 pod里面的 `/opt/hertzbeat/define` 目录到当前主机下,如果做了持久化 请拷贝持久化目录
> - `kubectl cp hertzbeat/hertzbeat-978477f84-fr894:/opt/hertzbeat/define ./define`
> - Backup `/opt/hertzbeat/define` from the running pod:
>
> 2. 若使用外置关系型数据库 Mysql, PostgreSQL数据
> ```bash
> kubectl cp hertzbeat/hertzbeat-978477f84-fr894:/opt/hertzbeat/define ./define
> ```
>
> - 一般使用helm部署部署都做了持久化,可以选择拷贝持久化目录,也可以通过mysqldump、pgdump等工具完成备份
> **For external databases (MySQL/PostgreSQL):**
>
> ```bash
> kubectl get pvc -n hertzbeat
> NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
> hertzbeat-database Bound pvc-c63cf479-0033-423b-8466-eb00aa181657 4Gi RWO standard 68d
> hertzbeat-ext-lib Bound pvc-31fee163-1211-424f-8966-e3e805c23ff5 1Gi RWX standard 68d
> hertzbeat-tsdb Bound pvc-4f2ef614-0302-4a4c-8dd4-e68b34e9061c 4Gi RWO standard 68d
> ```
> - Use `mysqldump`/`pg_dump` or copy PVC directories:
>
> ```bash
> kubectl get pvc -n hertzbeat
> ```
## 2. 升级步骤
## 2. Upgrade Steps
### 1. 拉取最新Chart到本地
### 1. Pull the latest Chart
```bash
helm repo update
@@ -45,33 +43,32 @@ helm pull hertzbeat/hertzbeat --version 1.7.0 --untar
cd hertzbeat
```
或者从GitHub仓库获取(按需修改Chart):
Or clone from GitHub:
```bash
git clone https://github.com/hertzbeat/helm-charts.git
cd helm-charts/charts/hertzbeat
```
### 2. 修改values.yaml
### 2. Update values.yaml
比较并合并您的自定义配置到新版本values.yaml:
Compare and merge configurations:
```bash
# 使用diff工具比较新旧values文件
diff -u ../hertzbeat-1.6.1-values.yaml values.yaml
vimdiff 对着修改,改完继续diff,无输出则正常
# Use vimdiff to compare and merge changes
```
常见需要关注的配置项:
Key configurations to check:
- 镜像版本: `image.tag`
- 资源限制: `resources`
- 持久化配置: `persistence`
- 服务类型: `service.type`
- Ingress配置
- 数据库配置(如果使用外部数据库)
- `image.tag`
- `resources`
- `persistence`
- `service.type`
- Ingress settings
- External database configurations
### 3. 测试升级(干运行)
### 3. Dry-run Upgrade
```bash
helm upgrade hertzbeat . -n <your-namespace> \
@@ -80,24 +77,19 @@ helm upgrade hertzbeat . -n <your-namespace> \
--debug
```
### 4. 执行升级
### 4. Execute Upgrade
```bash
helm upgrade hertzbeat . -n <your-namespace> \
--values values.yaml \
--atomic \ # 升级失败自动回滚
--timeout 10m # 设置超时时间
--atomic \ # Auto-rollback on failure
--timeout 10m # Set timeout
```
### 5. 验证升级
### 5. Verify Upgrade
```bash
# 检查发布状态
helm status hertzbeat -n <your-namespace>
# 检查Pod状态
kubectl get pods -n <your-namespace> -l app.kubernetes.io/instance=hertzbeat
# 检查日志
kubectl logs -n <your-namespace> -l app.kubernetes.io/instance=hertzbeat --tail=100
```
@@ -1,94 +0,0 @@
# HertzBeat Upgrade Guide (Docker Mode)
## Docker-based Upgrade
### 1. Data Backup
- **Back up the database**: Manually back up MySQL data as needed.
```bash
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" <DB_NAME> > hertzbeat_backup-`date +%Y-%m-%d`.sql # Single database
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" --all-databases > hertzbeat_backup-`date +%Y-%m-%d`.sql # Full database
```
- **Back up configuration files and data directory**:
```bash
mv application.yml application-bak.yml && mv sureness.yml sureness-bak.yml
cp -R data data-`date +%Y-%m-%d`.bak
```
### 2. Stop and Remove the HertzBeat Container
```bash
docker stop hertzbeat && docker rm hertzbeat
```
### 3. Upgrade Database Schema
Navigate to [HertzBeat GitHub Migration Scripts](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager/src/main/resources/db/migration), select the appropriate `V160__update_column.sql` file under your database type (e.g., MySQL), and execute it in MySQL.
### 4. Restart HertzBeat with the New Image
```bash
docker run -d -p 1157:1157 -p 1158:1158 \
-v $(pwd)/data:/opt/hertzbeat/data \
-v $(pwd)/logs:/opt/hertzbeat/logs \
-v $(pwd)/application.yml:/opt/hertzbeat/config/application.yml \
-v $(pwd)/sureness.yml:/opt/hertzbeat/config/sureness.yml \
--restart=always \
--name hertzbeat apache/hertzbeat:v1.7.0
```
### 5. Update Configuration Files
Modify the backup configurations as needed:
- **`application.yml`** (Typical modifications):
```yaml
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
hikari:
max-lifetime: 120000
jpa:
show-sql: false
database-platform: org.eclipse.persistence.platform.database.MySQLPlatform
database: mysql
properties:
eclipselink:
logging:
level: SEVERE
```
- **`sureness.yml`** (Optional, modify for account/password changes):
```yaml
account:
- appId: admin
credential: hertzbeat
role: [admin]
- appId: tom
credential: hertzbeat
role: [user]
- appId: guest
credential: hertzbeat
role: [guest]
- appId: lili
credential: 94C6B34E7A199A9F9D4E1F208093B489
salt: 123
role: [user]
```
### 6. Add Database Drivers
Due to Apache Foundations license compliance requirements, HertzBeat cannot include GPL-licensed dependencies (e.g., MySQL, Oracle). Users must manually download drivers and place them in the `ext-lib` directory, then mount it to `/opt/hertzbeat/ext-lib`:
- **MySQL Driver**: [Download MySQL Connector/J 8.0.25](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.25.zip)
- **Oracle Driver** (Required for Oracle monitoring):
- [ojdbc8.jar](https://download.oracle.com/otn-pub/otn_software/jdbc/234/ojdbc8.jar)
- [orai18n-21.5.0.0.jar](https://repo.mavenlibs.com/maven/com/oracle/database/nls/orai18n/21.5.0.0/orai18n-21.5.0.0.jar)
@@ -1,95 +0,0 @@
# HertzBeat Upgrade Guide from v1.6.1 to v1.7.0 (Helm Mode)
## 1. Prerequisites
1. Ensure the following tools are installed:
- Helm 3.x
- kubectl
- Git (optional)
2. Verify current deployment information:
```bash
helm list -n <your-namespace>
# If the old chart package is missing, export values.yaml with:
helm get values hertzbeat -n <your-namespace> > hertzbeat-1.6.1-values.yaml
```
3. Data Backup:
> **For custom monitoring templates:**
>
> - Backup `/opt/hertzbeat/define` from the running pod:
>
> ```bash
> kubectl cp hertzbeat/hertzbeat-978477f84-fr894:/opt/hertzbeat/define ./define
> ```
>
> **For external databases (MySQL/PostgreSQL):**
>
> - Use `mysqldump`/`pg_dump` or copy PVC directories:
>
> ```bash
> kubectl get pvc -n hertzbeat
> ```
## 2. Upgrade Steps
### 1. Pull the latest Chart
```bash
helm repo update
helm pull hertzbeat/hertzbeat --version 1.7.0 --untar
cd hertzbeat
```
Or clone from GitHub:
```bash
git clone https://github.com/hertzbeat/helm-charts.git
cd helm-charts/charts/hertzbeat
```
### 2. Update values.yaml
Compare and merge configurations:
```bash
diff -u ../hertzbeat-1.6.1-values.yaml values.yaml
# Use vimdiff to compare and merge changes
```
Key configurations to check:
- `image.tag`
- `resources`
- `persistence`
- `service.type`
- Ingress settings
- External database configurations
### 3. Dry-run Upgrade
```bash
helm upgrade hertzbeat . -n <your-namespace> \
--values values.yaml \
--dry-run \
--debug
```
### 4. Execute Upgrade
```bash
helm upgrade hertzbeat . -n <your-namespace> \
--values values.yaml \
--atomic \ # Auto-rollback on failure
--timeout 10m # Set timeout
```
### 5. Verify Upgrade
```bash
helm status hertzbeat -n <your-namespace>
kubectl get pods -n <your-namespace> -l app.kubernetes.io/instance=hertzbeat
kubectl logs -n <your-namespace> -l app.kubernetes.io/instance=hertzbeat --tail=100
```
@@ -0,0 +1,103 @@
# HertzBeat 升级指导-(Docker Mode)
## Docker 方式升级 - Mysql 数据库
1. 数据备份
- 备份数据库,将 mysql 数据手动做备份,按需备份
```bash
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" <库名> hertzbeat_backup-`date +%Y-%m-%d`.sql #单库备份
mysqldump -h<HOST-IP> -P<PORT> -uroot -p"PASSWORD" > hertzbeat_backup-`date +%Y-%m-%d`.sql # 整库备份
```
- 备份配置文件及数据目录
```bash
mv application.yml application-bak.yml && mv sureness-bak.yml
cp -R data data-`date +%Y-%m-%d`. bak
```
2. 关闭 并移除 HertzBeat 容器
```shell
docker stop hertzbeat && docker rm hertzbeat
```
3. 升级数据库脚本
打开[https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager/src/main/resources/db/migration](https://github.com/apache/hertzbeat/tree/master/hertzbeat-manager/src/main/resources/db/migration) 选择你使用的数据库的目录下相应的 `V160__update_column.sql`文件在 Mysql 执行升级 sql。
4. 更换镜像重新启动 HertzBeat 容器
```bash
$ docker run -d -p 1157:1157 -p 1158:1158 \
-v $(pwd)/data:/opt/hertzbeat/data \
-v $(pwd)/logs:/opt/hertzbeat/logs \
-v $(pwd)/application.yml:/opt/hertzbeat/config/application.yml \
-v $(pwd)/sureness.yml:/opt/hertzbeat/config/sureness.yml \
--restart=always \
--name hertzbeat apache/hertzbeat:v1.7.0
```
5. 升级配置文件
参考备份配置根据自己的需求基础上进行修改。
- `application.yml`一般需要修改以下部分
默认为:
```yaml
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
hikari:
max-lifetime: 120000
jpa:
show-sql: false
database-platform: org.eclipse.persistence.platform.database.MySQLPlatform
database: mysql
properties:
eclipselink:
logging:
level: SEVERE
```
- `sureness.yml`修改是可选的,一般在你需要修改账号密码时
```yaml
# account info config
# eg: admin has role [admin,user], password is hertzbeat
# eg: tom has role [user], password is hertzbeat
# eg: lili has role [guest], plain password is lili, salt is 123, salted password is 1A676730B0C7F54654B0E09184448289
account:
- appId: admin
credential: hertzbeat
role: [admin]
- appId: tom
credential: hertzbeat
role: [user]
- appId: guest
credential: hertzbeat
role: [guest]
- appId: lili
# credential = MD5(password + salt)
# plain password: hertzbeat
# attention: digest authentication does not support salted encrypted password accounts
credential: 94C6B34E7A199A9F9D4E1F208093B489
salt: 123
role: [user]
```
6. 添加相应的数据库驱动
由于 apache 基金会对于 license 合规的要求,HertzBeat 的安装包不能包含 mysqloracle 等 gpl 许可的依赖,需要用户自行添加,用户可通过以下链接自行下载驱动 jar 放到本地 `ext-lib`目录下,然后启动时将`ext-lib`挂载到容器的 `/opt/hertzbeat/ext-lib`目录。
mysql[https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.25.zip](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.18.zip)
oracle(如果你要监控 oracle,这两个驱动是必须的):
[https://download.oracle.com/otn-pub/otn_software/jdbc/234/ojdbc8.jar](https://download.oracle.com/otn-pub/otn_software/jdbc/234/ojdbc8.jar)
[https://repo.mavenlibs.com/maven/com/oracle/database/nls/orai18n/21.5.0.0/orai18n-21.5.0.0.jar](https://repo.mavenlibs.com/maven/com/oracle/database/nls/orai18n/21.5.0.0/orai18n-21.5.0.0.jar?utm_source=mavenlibs.com)
@@ -0,0 +1,103 @@
# HertzBeat 从 1.6.1 版本升级到 1.7.0 版本指引-(Helm Mode)
## 1. 前置准备
1. 确保已安装以下工具:
- Helm 3.x
- kubectl
- Git (可选)
2. 确认当前部署信息:
```bash
helm list -n <your-namespace>
# 如果你老版本的chart包不见了,可以使用以下命令导出values.yaml文件
helm get values hertzbeat -n <your-namespace> > hertzbeat-1.6.1-values.yaml
```
3. 数据备份
> 1. 若使用了自定义监控模版
>
> - 需要备份 `kubectl cp hertzbeat/hertzbeat-978477f84-fr894:/opt/hertzbeat/define ./define` 当前运行 pod里面的 `/opt/hertzbeat/define` 目录到当前主机下,如果做了持久化 请拷贝持久化目录
> - `kubectl cp hertzbeat/hertzbeat-978477f84-fr894:/opt/hertzbeat/define ./define`
>
> 2. 若使用外置关系型数据库 Mysql, PostgreSQL数据
>
> - 一般使用helm部署部署都做了持久化,可以选择拷贝持久化目录,也可以通过mysqldump、pgdump等工具完成备份
>
> ```bash
> kubectl get pvc -n hertzbeat
> NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
> hertzbeat-database Bound pvc-c63cf479-0033-423b-8466-eb00aa181657 4Gi RWO standard 68d
> hertzbeat-ext-lib Bound pvc-31fee163-1211-424f-8966-e3e805c23ff5 1Gi RWX standard 68d
> hertzbeat-tsdb Bound pvc-4f2ef614-0302-4a4c-8dd4-e68b34e9061c 4Gi RWO standard 68d
> ```
## 2. 升级步骤
### 1. 拉取最新Chart到本地
```bash
helm repo update
helm pull hertzbeat/hertzbeat --version 1.7.0 --untar
cd hertzbeat
```
或者从GitHub仓库获取(按需修改Chart):
```bash
git clone https://github.com/hertzbeat/helm-charts.git
cd helm-charts/charts/hertzbeat
```
### 2. 修改values.yaml
比较并合并您的自定义配置到新版本values.yaml:
```bash
# 使用diff工具比较新旧values文件
diff -u ../hertzbeat-1.6.1-values.yaml values.yaml
vimdiff 对着修改,改完继续diff,无输出则正常
```
常见需要关注的配置项:
- 镜像版本: `image.tag`
- 资源限制: `resources`
- 持久化配置: `persistence`
- 服务类型: `service.type`
- Ingress配置
- 数据库配置(如果使用外部数据库)
### 3. 测试升级(干运行)
```bash
helm upgrade hertzbeat . -n <your-namespace> \
--values values.yaml \
--dry-run \
--debug
```
### 4. 执行升级
```bash
helm upgrade hertzbeat . -n <your-namespace> \
--values values.yaml \
--atomic \ # 升级失败自动回滚
--timeout 10m # 设置超时时间
```
### 5. 验证升级
```bash
# 检查发布状态
helm status hertzbeat -n <your-namespace>
# 检查Pod状态
kubectl get pods -n <your-namespace> -l app.kubernetes.io/instance=hertzbeat
# 检查日志
kubectl logs -n <your-namespace> -l app.kubernetes.io/instance=hertzbeat --tail=100
```
+1 -1
View File
@@ -44,7 +44,7 @@ if [ ! -d $LOGS_DIR ]; then
fi
# JVM Configuration
JAVA_OPTS=" -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
JAVA_OPTS=" -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
# JVM Configuration
JAVA_MEM_OPTS=" -server -XX:SurvivorRatio=6 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$LOGS_DIR"
+1 -1
View File
@@ -51,7 +51,7 @@ if not exist %LOGS_DIR% (
)
rem JVM Configuration
set JAVA_OPTS= -Duser.timezone=Asia/Shanghai -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
set JAVA_OPTS= -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
set JAVA_MEM_OPTS= -server -XX:SurvivorRatio=6 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=%LOGS_DIR%
+1 -1
View File
@@ -82,7 +82,7 @@ if [ ! -d $LOGS_DIR ]; then
fi
# JVM Configuration
JAVA_OPTS=" -Duser.timezone=Asia/Shanghai -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
JAVA_OPTS=" -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
JAVA_MEM_OPTS=" -server -XX:SurvivorRatio=6 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$LOGS_DIR"
+2 -2
View File
@@ -47,9 +47,9 @@ fi
# JVM Configuration
if [ -z "$JAVA_OPTS" ]; then
JAVA_OPTS=" -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
JAVA_OPTS=" -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
else
JAVA_OPTS="${JAVA_OPTS} -Doracle.jdbc.timezoneAsRegion=false"
JAVA_OPTS="${JAVA_OPTS} -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false"
fi
# JVM Configuration
+1 -1
View File
@@ -52,7 +52,7 @@ if not exist %LOGS_DIR% (
rem JVM Configuration
set JAVA_OPTS= -Duser.timezone=Asia/Shanghai -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
set JAVA_OPTS= -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
set JAVA_MEM_OPTS= -server -XX:SurvivorRatio=6 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=%LOGS_DIR%
+1 -1
View File
@@ -86,7 +86,7 @@ fi
# JVM Configuration
JAVA_OPTS=" -Duser.timezone=Asia/Shanghai -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
JAVA_OPTS=" -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -Doracle.jdbc.timezoneAsRegion=false --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED"
JAVA_MEM_OPTS=" -server -XX:SurvivorRatio=6 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$LOGS_DIR"
@@ -85,6 +85,9 @@ export class MonitorEditComponent implements OnInit {
if (message.code === 0) {
let paramValueMap = new Map<String, Param>();
this.monitor = message.data.monitor;
if (this.monitor.scrape == null || this.monitor.scrape == undefined) {
this.monitor.scrape = 'static';
}
this.grafanaDashboard = message.data.grafanaDashboard != undefined ? message.data.grafanaDashboard : new GrafanaDashboard();
this.collector = message.data.collector == null ? '' : message.data.collector;
this.titleSvc.setTitleByI18n(`monitor.app.${this.monitor.app}`);