2024-1-12

This commit is contained in:
yovinchen 2024-01-12 10:13:34 +08:00
parent 9135570293
commit 175bc392aa
404 changed files with 12604 additions and 52 deletions

View File

@ -4,19 +4,15 @@
"type": "split",
"children": [
{
"id": "45758c4f6e50afca",
"id": "fba6ba71c6e0e7b2",
"type": "tabs",
"children": [
{
"id": "048751669f9281f8",
"id": "09dba63fa2c08f99",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "HomeBrew/Mac OS 神器 HomeBrew.md",
"mode": "source",
"source": false
}
"type": "empty",
"state": {}
}
}
]
@ -49,7 +45,7 @@
"type": "search",
"state": {
"query": "",
"matchingCase": false,
"matchingCase": true,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
@ -85,7 +81,7 @@
"state": {
"type": "backlink",
"state": {
"file": "HomeBrew/Mac OS 神器 HomeBrew.md",
"file": "面试题资料.pdf",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
@ -102,7 +98,7 @@
"state": {
"type": "outgoing-link",
"state": {
"file": "HomeBrew/Mac OS 神器 HomeBrew.md",
"file": "面试题资料.pdf",
"linksCollapsed": false,
"unlinkedCollapsed": true
}
@ -125,7 +121,7 @@
"state": {
"type": "outline",
"state": {
"file": "HomeBrew/Mac OS 神器 HomeBrew.md"
"file": "面试题资料.pdf"
}
}
}
@ -146,12 +142,46 @@
"command-palette:打开命令面板": false
}
},
"active": "048751669f9281f8",
"active": "8afd0c6afa6fd8cc",
"lastOpenFiles": [
"Docker 2375端口开启外网访问.md",
"软件测试/软件测试-安全测试.md",
"软件测试/软件测试-黑白盒测试.md",
"软件测试/软件测试-软测基础.md",
"软件测试/软件测试-自动化测试.md"
"青空笔记/Java设计模式笔记/Java设计模式.md",
"面试题资料.pdf",
"青空笔记/Java设计模式笔记/Java设计模式.md",
"数据库系统原理/单元复习资料/数据库复习3.md",
"数据库系统原理/单元复习资料/数据库第二章.png",
"数据库系统原理/练习题/第二次上机.md",
"数据库导论/笔记/数据库笔记05——查询数据——2022-03-17.md",
"数据库导论/笔记/数据库笔记06——视图——2022-04-05.md",
"数据库系统原理/练习题/第四次上级.md",
"数据库系统原理/单元复习资料/数据库复习4.md",
"数据库导论/笔记/数据库笔记01——数据库使用笔记.md",
"教程/网站面板/aaPanel-宝塔面板国际版安装教程(宝塔海外版).md",
"Activti 流程管理.md",
"面试/面试/Redis面试题-参考回答.md",
"面试/面试/消息中间件面试题-参考回答.md",
"面试/面试/框架篇面试题-参考回答.md",
"面试/面试/多线程相关面试题.md",
"面试/面试/Java集合相关面试题.md",
"六大设计模式.md",
"面试/面试/微服务面试题-参考回答.md",
"面试/面试/常见技术场景.md",
"面试/HashMap/HashMap集合(高级).md",
"面试/面试/img/image-20230521233600556.png",
"面试/面试/img/线程池的执行原理.jpg",
"面试/面试/img/简单工厂.jpg",
"面试/面试/img/image-20230521233926897.png",
"面试/面试/img/image-20230521233715574.png",
"面试/面试/img/image-20230521233934644.png",
"面试/面试/img/image-20230521233554657.png",
"面试/面试/img/image-20230521233150276.png",
"面试/面试/img/image-20230521233220905.png",
"面试/面试/设计模式.md",
"面试/面试/img",
"面试/面试/MySQL面试题-参考回答.md",
"面试/面试/JVM相关面试题.md",
"面试/面试",
"开发工具/Docker基本命令.md",
"HomeBrew/Mac OS 神器 HomeBrew.md",
"Docker 2375端口开启外网访问.md"
]
}

View File

@ -1,9 +1,5 @@
# Activti流程管理
```java
Activti提供的主要的接口服务其中主要用到

View File

@ -1,25 +0,0 @@
docker镜像配置
```
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
"registry-mirrors": [
"https://9kkc1zdn.mirror.aliyuncs.com"
]
}
```
恢复docekr数据
```
docker load -i all_images.tar
```

View File

@ -0,0 +1,71 @@
CentOS 配置国内 yum 源
## CentOS 7 x86-64
```shell
CentOS 7 x86-64
//进入root切换至yum.repos.d目录
cd /etc/yum.repos.d/
//创建新文件夹并将源文件备份为repo.bak
mkdir backup && mv *repo backup/
//下载国内yum源文件
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
//163
##wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
//生成缓存
yum clean all && yum makecache
```
## CentOS Stream 8 x86-64
````shell
CentOS Stream 8 x86-64
//进入root切换至yum.repos.d目录
cd /etc/yum.repos.d/
//创建新文件夹并将源文件备份为repo.bak
mkdir backup && mv *repo backup/
//下载国内yum源文件
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo
//更新下载yum源地址
sed -i -e"s|mirrors.cloud.aliyuncs.com|mirrors.aliyun.com|g " /etc/yum.repos.d/CentOS-*
sed -i -e "s|releasever|releasever-stream|g" /etc/yum.repos.d/CentOS-*
//生成缓存
yum clean all && yum makecache
````
## CentOS Stream 9 x86-64
```shell
CentOS Stream 9 x86-64
//进入root切换至yum.repos.d目录
cd /etc/yum.repos.d/
//创建新文件夹并将源文件备份为repo.bak
mkdir backup && mv *repo backup/
//下载国内yum源文件
sed -i 's|metalink|#metalink|g' /etc/yum.repos.d/*.repo
sed -i '/name=CentOS Stream $releasever - BaseOS/a baseurl=https://mirrors.aliyun.com/centos-stream/$stream/BaseOS/$basearch/os/' /etc/yum.repos.d/*.repo
sed -i '/name=CentOS Stream $releasever - AppStream/a baseurl=https://mirrors.aliyun.com/centos-stream/$stream/AppStream/$basearch/os/' /etc/yum.repos.d/*.repo
sed -i '/name=CentOS Stream $releasever - Extras packages/a baseurl=https://mirrors.aliyun.com/centos-stream/SIGs/$stream/extras/$basearch/extras-common/' /etc/yum.repos.d/*.repo
//生成缓存
yum clean all && yum makecache
```

View File

@ -0,0 +1,60 @@
首先检查docker-compose的安装情况
```shell
docker-compose -v
```
创建Docker-Compose
```shell
cd /var/lib
mkdir docker-compose
```
编辑docker-compose文件
```shell
vi docker-compose.yml
```
在文件夹下编写`docker-compose.yml`文件
```yml
version: "3"
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:1.20.5
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "10800:3000"
- "2222:22"
```
启动docker-compose
```shell
docker-compose up -d
```
检查运行情况
```shell
docker ps
docker-compose ps
```

View File

@ -0,0 +1,40 @@
首先检查docker-compose的安装情况
```shell
docker-compose -v
```
在文件夹下编写`docker-compose.yml`文件
```yml
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
```
启动docker-compose
```shell
docker-compose up -d
```
检查运行情况
```shell
docker ps
docker-compose ps
```
```
admin@example.com
changeme
```

View File

@ -0,0 +1,312 @@
# Centos 9单节点安装kubernetes、KubeSpherearm64
[TOC]
首先说一下什么使用centos 7 因为我的mac PD虚拟机安装不上包括centos Stream 8为此只能换到centos Stream 9 了我的云服务上跑的都是Centos 7暂时用不惯 Ubuntu 。KubeSphere最新版本中部分组件不支持arm64在后面的启动可查包组件中会提到如何解决。
下面是我搭建版本以及环境版本
| | |
| ---------- | ------------------------ |
| 操作系统 | Centos Stream 9 |
| 系统配置 | 4核16GB内存 64GB磁盘空间 |
| kubernetes | 1.22.12 |
| kubesphere | 3.4.0 |
## 环境需求配置
### 官方支持的操作系统及最低配置
| 操作系统 | 最低配置 |
| :----------------------------------------------------- | :---------------------------------- |
| **Ubuntu** *16.04*, *18.04*, *20.04*, *22.04* | 2 核 CPU4 GB 内存40 GB 磁盘空间 |
| **Debian** *Buster*, *Stretch* | 2 核 CPU4 GB 内存40 GB 磁盘空间 |
| **CentOS** *7.x* | 2 核 CPU4 GB 内存40 GB 磁盘空间 |
| **Red Hat Enterprise Linux 7** | 2 核 CPU4 GB 内存40 GB 磁盘空间 |
| **SUSE Linux Enterprise Server 15/openSUSE Leap 15.2** | 2 核 CPU4 GB 内存40 GB 磁盘空间 |
### 以下是支持的容器版本
| 支持的容器 | 版本 |
| :---------------------------- | :------- |
| Docker | 19.3.8 + |
| containerd | 最新版 |
| CRI-O试验版未经充分测试 | 最新版 |
| iSula试验版未经充分测试 | 最新版 |
### Kubernetes依赖
| 依赖项 | Kubernetes 版本 ≥ 1.18 | Kubernetes 版本 < 1.18 |
| :-------- | :--------------------- | :--------------------- |
| socat | 必须 | 可选但建议 |
| conntrack | 必须 | 可选但建议 |
| ebtables | 可选但建议 | 可选但建议 |
| ipset | 可选但建议 | 可选但建议 |
## 配置软件依赖
### 设置服务器hostname名称
```shell
#查看主机名称
hostname
#更改名称
hostnamectl --static set-hostname master
#查看主机名称核验
hostnamectl status
#可以重启一下服务器
#reboot
```
### 关闭防火墙
```shell
systemctl disable firewalld
systemctl stop firewalld
systemctl status firewalld
```
### 关闭swap分区
```shell
swapoff -a
echo "vm.swappiness=0" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
```
### 配置epel源国内服务器Centos7
```shell
rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
```
### Centos Stream 9更换了dnf包管理器
> 首先需要安装extra包并确保已安装了centos-release-stream包
>
> ```shell
> sudo dnf install -y centos-release-stream
> ```
>
> 然后使用下面的命令从EPEL存储库安装软件包
>
> ```shell
> sudo dnf install -y epel-release
> ```
>
> 相较于以前的CentOS 7和8版本CentOS Stream 9使用dnf作为默认的包管理器而不是yum。dnf包管理器相较于yum提供了更好地性能依赖解决和自动同步功能。
>
> 建议在安装任何新的软件包之前,确保系统已经更新至最新状态:
>
> ```shell
> sudo dnf update -y
> ```
>
> 注意EPEL存储库中存在由社区提供和维护的大量软件包。将这些包添加到服务器可能会给您带来未知的安全风险。在使用来自EPEL的软件包之前请确保您都确定其安全性。
### 更新yum
```shell
yum -y update
```
### 安装依赖组件
```shell
yum install -y ebtables socat ipset conntrack
```
### 下载 KubeKey
```shell
curl -sfL https://get-kk.kubesphere.io | VERSION=v3.0.10 sh -
#访问gtihub受限制
#export KKZONE=cn
#curl -sfL https://get-kk.kubesphere.io | VERSION=v3.0.10 sh -
```
### 添加kk权限
```shell
chmod +x kk
```
### 开始安装(最小化安装)
模版
```shell
./kk create cluster [--with-kubernetes version] [--with-kubesphere version]
```
示例:同时安装 Kubernetes 和 KubeSphere
```shell
./kk create cluster --with-kubernetes v1.22.12 --with-kubesphere v3.4.0
```
- 安装 KubeSphere 3.4 的建议 Kubernetes 版本v1.20.x、v1.21.x、v1.22.x、v1.23.x、* v1.24.x、* v1.25.x 和 * v1.26.x。带星号的版本可能出现边缘节点部分功能不可用的情况。因此如需使用边缘节点推荐安装 v1.23.x。如果不指定 Kubernetes 版本KubeKey 将默认安装 Kubernetes v1.23.10。有关受支持的 Kubernetes 版本的更多信息,请参见[支持矩阵](https://www.kubesphere.io/zh/docs/v3.4/installing-on-linux/introduction/kubekey/#支持矩阵)。
- 一般来说,对于 All-in-One 安装,您无需更改任何配置。
- 如果您在这一步的命令中不添加标志 `--with-kubesphere`,则不会部署 KubeSphereKubeKey 将只安装 Kubernetes。如果您添加标志 `--with-kubesphere` 时不指定 KubeSphere 版本,则会安装最新版本的 KubeSphere。
- KubeKey 会默认安装 [OpenEBS](https://openebs.io/) 为开发和测试环境提供 LocalPV 以方便新用户。对于其他存储类型,请参见[持久化存储配置](https://www.kubesphere.io/zh/docs/v3.4/installing-on-linux/persistent-storage-configurations/understand-persistent-storage/)。
输入 `yes` 继续安装流程。
### 验证安装结果
```shell
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
```
输出信息会显示 Web 控制台的 IP 地址和端口号,默认的 NodePort 是 `30880`。现在,您可以使用默认的帐户和密码 (`admin/P@88w0rd`) 通过 `<NodeIP>:30880` 访问控制台。
输出结果
```shell
#####################################################
### Welcome to KubeSphere! ###
#####################################################
Console: http://10.211.55.30:30880
Account: admin
Password: P@88w0rd
NOTES
1. After you log into the console, please check the
monitoring status of service components in
"Cluster Management". If any service is not
ready, please wait patiently until all components
are up and running.
2. Please change the default password after login.
#####################################################
https://kubesphere.io 2023-10-26 16:18:18
#####################################################
```
检查 KubeSphere 相关组件的运行状况
```shell
kubectl get pod --all-namespaces
```
## 启用可插拔组件(可选)
用于默认的最小化安装。若要在 KubeSphere 中启用其他组件,请参见[启用可插拔组件](https://www.kubesphere.io/zh/docs/v3.4/pluggable-components/)。
### KubeSphere DevOps 系统
基于 [Jenkins](https://jenkins.io/) 的 KubeSphere DevOps 系统是专为 Kubernetes 中的 CI/CD 工作流设计的,它提供了一站式的解决方案,帮助开发和运维团队用非常简单的方式构建、测试和发布应用到 Kubernetes。它还具有插件管理、[Binary-to-Image (B2I)](https://www.kubesphere.io/zh/docs/v3.4/project-user-guide/image-builder/binary-to-image/)、[Source-to-Image (S2I)](https://www.kubesphere.io/zh/docs/v3.4/project-user-guide/image-builder/source-to-image/)、代码依赖缓存、代码质量分析、流水线日志等功能。
DevOps 系统为用户提供了一个自动化的环境,应用可以自动发布到同一个平台。它还兼容第三方私有镜像仓库(如 Harbor和代码库如 GitLab/GitHub/SVN/BitBucket。它为用户提供了全面的、可视化的 CI/CD 流水线,打造了极佳的用户体验,而且这种兼容性强的流水线能力在离线环境中非常有用。
有关更多信息,请参见 [DevOps 用户指南](https://www.kubesphere.io/zh/docs/v3.4/devops-user-guide/)。
#### 在安装KubeSphere后启动 DevOps
1. 以 `admin` 用户登录控制台,点击左上角的**平台管理**,选择**集群管理**。
2. 点击**定制资源定义**,在搜索栏中输入 `clusterconfiguration`,点击搜索结果查看其详细页面。
信息
定制资源定义CRD允许用户在不新增 API 服务器的情况下创建一种新的资源类型,用户可以像使用其他 Kubernetes 原生对象一样使用这些定制资源。
3. 在**自定义资源**中,点击 `ks-installer` 右侧的更多中,选择**编辑 YAML**。
4. 在该 YAML 文件中,搜索 `devops`,将 `enabled``false` 改为 `true`。完成后,点击右下角的**确定**,保存配置。
```yaml
devops:
enabled: true # 将“false”更改为“true”。
```
5.在 kubectl 中执行以下命令检查安装过程:
```shell
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
```
#### 不兼容的pod镜像包括以下
| 镜像名称 | 官方提供版本 | 自测暂时可用版本 | DockerHub地址 |
| --------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| minio | docker.io/minio/minio:RELEASE.2019-08-07T01-59-21Z | docker.io/minio/minio:RELEASE.2022-07-29T19-40-48Z | https://hub.docker.com/layers/minio/minio/RELEASE.2022-07-29T19-40-48Z/images/sha256-cc1067cf3d480ffc8636784bde413e4c52575da6471833fb0d3b17d38cb3cefd?context=explore |
| mc | docker.io/minio/mc:RELEASE.2019-08-07T23-14-43Z | docker.io/minio/mc:RELEASE.2022-07-29T19-17-16Z | https://hub.docker.com/layers/minio/mc/RELEASE.2022-07-29T19-17-16Z/images/sha256-5849d1feb6d60e215175a12011d0be5580a79ed4251cd0f6c824a1a24332a28a?context=explore |
| argocd_applicationset | registry.cn-beijing.aliyuncs.com/kubesphereio/argocd-applicationset:v0.4.1 | docker.io/baloisemichaelmuehlebach/argocd-applicationset:v0.4.1 | https://hub.docker.com/layers/baloisemichaelmuehlebach/argocd-applicationset/v0.4.1/images/sha256-f6a0b73b48e92c9b9977bde40c360c9b813c06845a7526469186dc7c2bb3a75f?context=explore |
| jenkins | registry.cn-beijing.aliyuncs.com/kubesphereio/ks-jenkins:v3.4.0-2.319.3-1 | docker.io/kubesphere/ks-jenkins:v3.4.1-2.319.3 | https://hub.docker.com/layers/kubesphere/ks-jenkins/v3.4.1-2.319.3/images/sha256-15a40d2da981451e903e1a59f5e6963e4291f20153eddb3d922dd965ccc1f6d3?context=explore |
| default-http-backend | registry.cn-beijing.aliyuncs.com/kubesphereio/defaultbackend-arm64:1.4 | mirrorgooglecontainers/defaultbackend-arm64:1.4 | https://hub.docker.com/layers/mirrorgooglecontainers/defaultbackend-arm/1.4/images/sha256-f02490f65b15e347661216d55b8fc0b5d7e472aa0b1ef9241be4eea880a3c594?context=explore |
![image-20231027094147632](https://lsky.hhdxw.top/imghub/2023/10/image-202310271698370908.png)
#### 更换方式
##### 1.直接在开启devops配置中设置仓库以及标签
直接在上文中`ks-installer`**编辑 YAML**文件中添加Docker的仓库repository与标签tag信息
![image-20231027102441263](https://lsky.hhdxw.top/imghub/2023/10/image-202310271698373481.png)
```yaml
spec:
mc_tag: RELEASE.2022-07-29T19-17-16Z
mc_repo: docker.io/minio/mc
minio_repo: docker.io/minio/minio
minio_tag: RELEASE.2022-07-29T19-40-48Z
argocd_applicationset_repo: docker.io/baloisemichaelmuehlebach/argocd-applicationset
argocd_applicationset_tag:v0.4.1
jenkins_repo: docker.io/kubesphere/ks-jenkins
jenkins_tag: v3.4.1-2.319.3
```
##### 2.创建项目后,在项目中**编辑 YAML**中重新创建
1. 以 `admin` 用户登录控制台,点击左上角的**平台管理**,选择**集群管理**。
2. 点击**应用负载**下级目录**工作负载**,查看项目状态异常的项目点击进入项目。
3. 在**更多操作**中,选择**编辑 YAML**,找到如下内容更换完成并保存。
```yaml
image: >-
registry.cn-beijing.aliyuncs.com/kubesphereio/ks-jenkins:v3.4.0-2.319.3-1
#上述内容更换为下面,此处只举例,具体参考上面的表格
image: 'docker.io/kubesphere/ks-jenkins:v3.4.1-2.319.3'
```
4. 系统会自动启动新的副本,稍作等待副本完成后自动会删除错误的副本,如果没有启动可以在**更多操作**中,选择**重新创建**。
5. 另外可以在修改记录中查看修改对比记录
![image-20231027102325546](https://lsky.hhdxw.top/imghub/2023/10/image-202310271698373405.png)
#### 注意:
本人确认正在使用上述特定版本号的服务,并确认在目前的使用过程中暂未出现问题。然而,这在任何程度上都不能被视为是对您个人使用此版本的保证或建议。
请您知悉,上述版本号仅供参考,并不能保证与所有的硬件、软件环境或与所有的使用场景完全兼容。在您决定使用该版本时,您需要自行评估可能存在的风险,其中可能包括但不限于功能不全、系统不稳定、可能存在的安全问题等情况。
对于因对我个人版本号使用情况的借鉴引发的任何形式的损失或问题,我个人以及相关的产品或服务提供者无需负担任何责任。如果您在使用过程中遇到任何问题,建议直接联系相关的产品或服务的提供者以寻求技术支持。
#### 附录:
新版本的`minio`会让部分功能无法使用,`RELEASE.2022-10-29T06-21-33Z`版本以后可能不兼容。
![image-202310271698374117](https://lsky.hhdxw.top/imghub/2023/10/image-202310271698374117.png)
#### 验证组件的安装
执行以下命令来检查容器组的状态:
```shell
kubectl get pod -n kubesphere-devops-system
```
如果组件运行成功,输出结果如下:
```shell
NAME READY STATUS RESTARTS AGE
devops-jenkins-5cbbfbb975-hjnll 1/1 Running 0 40m
s2ioperator-0 1/1 Running 0 41m
```

View File

@ -0,0 +1,642 @@
# 多节点部署Kubernetes集群
[TOC]
## 编辑环境
将主机名指向本机IP**主机名只能包含:字母、数字、-(横杠)、.(点)**
### 获取主机名
```shell
hostname
```
#### 临时设置主机名
```shell
hostname 主机名
```
#### 永久设置主机名
```shell
sudo echo '主机名' > /etc/hostname
```
#### 编辑 hosts
```shell
sudo vim /etc/hosts
```
```shell
10.211.55.20 k8s-node1 #集群主节点
10.211.55.21 k8s-node2 #集群node节点
10.211.55.19 k8s-node3 #集群node节点
```
### 同步时间
```shell
sudo yum -y install ntpdate
sudo ntpdate ntp1.aliyun.com
sudo systemctl status ntpdate
sudo systemctl start ntpdate
sudo systemctl status ntpdate
sudo systemctl enable ntpdate
```
Centos9中ntp 软件包已被替换为 chrony
```shell
sudo yum -y install chrony
sudo systemctl start chronyd
sudo systemctl enable chronyd
sudo systemctl restart chronyd
sudo chronyc makestep
date
```
### 安装并配置 bash-completion添加命令自动补充
```shell
sudo yum -y install bash-completion
source /etc/profile
```
### 关闭防火墙
```shell
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
```
### 开通全部端口
```shell
firewall-cmd --zone=public --add-port=1-65535/udp --permanent
firewall-cmd --zone=public --add-port=1-65535/tcp --permanent
firewall-cmd --reload
```
### 打开端口转发
```shell
firewall-cmd --add-masquerade --permanent # 端口转发
firewall-cmd --reload
firewall-cmd --list-all
firewall-cmd --list-all --zone=trusted
```
### 关闭交换空间
```shell
free -h
sudo swapoff -a
sudo sed -i 's/.*swap.*/#&/' /etc/fstab
free -h
```
### 关闭 selinux
```shell
getenforce
cat /etc/selinux/config
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
cat /etc/selinux/config
```
## 安装Docker
### 卸载旧Docekr
```shell
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
```
### 更新一下环境:
```
yum -y update
```
### 安装一些必要的系统工具:
```
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
```
### 添加软件源信息:
```
sudo yum install -y yum-utils
```
```
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #国内阿里源
```
```
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo #docker官方镜像源
```
### 安装 Docker
```
sudo yum install docker-ce docker-ce-cli containerd.io
```
### 启动 Docker 后台服务
```
sudo systemctl start docker
sudo systemctl enable docker
```
### 测试运行 hello-world
```
docker run hello-world
```
## 编辑Kubernetes环境
### 修改containerd
```shell
#停止containerd
sudo systemctl stop containerd.service
sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
sudo containerd config default > $HOME/config.toml
sudo cp $HOME/config.toml /etc/containerd/config.toml
```
```shell
vi /etc/containerd/config.toml
```
```shell
# 修改 /etc/containerd/config.toml 文件后,要将 docker、containerd 停止后,再启动
sudo sed -i "s#registry.k8s.io/pause#registry.aliyuncs.com/google_containers/pause#g" /etc/containerd/config.toml
# https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#containerd-systemd
# 确保 /etc/containerd/config.toml 中的 disabled_plugins 内不存在 cri
sudo sed -i "s#SystemdCgroup = false#SystemdCgroup = true#g" /etc/containerd/config.toml
```
```shell
sudo systemctl enable --now containerd.service
# sudo systemctl status containerd.service
# sudo systemctl status docker.service
sudo systemctl start docker.service
# sudo systemctl status docker.service
sudo systemctl enable docker.service
sudo systemctl enable docker.socket
sudo systemctl list-unit-files | grep docker
```
```shell
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors":[
"https://9kkc1zdn.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com/",
"https://docker.mirrors.ustc.edu.cn/",
"https://registry.docker-cn.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
```
### 重启
```shell
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo docker info
sudo systemctl status docker.service
sudo systemctl status containerd.service
```
### 添加阿里云镜像仓库注意其中电脑版本例如aarch64、x86_64、ppc64le、armhfp、390x
```shell
# 文档https://developer.aliyun.com/mirror/kubernetes
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-aarch64/
# 是否开启本仓库
enabled=1
# 是否检查 gpg 签名文件
gpgcheck=0
# 是否检查 gpg 签名文件
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
```
## 安装K8s依赖
```shell
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
```
```shell
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
```
```shell
# 通过运行以下指令确认 br_netfilter 和 overlay 模块被加载:
lsmod | grep br_netfilter
lsmod | grep overlay
```
```shell
# 通过运行以下指令确认 net.bridge.bridge-nf-call-iptables、net.bridge.bridge-nf-call-ip6tables 和 net.ipv4.ip_forward 系统变量在你的 sysctl 配置中被设置为 1
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
```
```shell
#1.27.3版本
sudo yum install -y kubelet-1.27.3-0 kubeadm-1.27.3-0 kubectl-1.27.3-0 --disableexcludes=kubernetes --nogpgcheck
# 安装最新版
# sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes --nogpgcheck
systemctl daemon-reload
sudo systemctl restart kubelet
sudo systemctl enable kubelet
```
### 查看kubelet日志
```shell
# k8s 未初始化时kubelet 可能无法启动
journalctl -xefu kubelet
```
### 查看kubelet状态
```shell
# k8s 未初始化时kubelet 可能无法启动
sudo systemctl status kubelet
```
## 以上命令所有节点均相同
## 控制面板:初始化(主节点)
```shell
kubeadm init --image-repository=registry.aliyuncs.com/google_containers
# 指定集群的IP
# kubeadm init --image-repository=registry.aliyuncs.com/google_containers --apiserver-advertise-address=192.168.80.60
# --apiserver-advertise-addressAPI 服务器所公布的其正在监听的 IP 地址。如果未设置,则使用默认网络接口。存在多个网卡时推荐设置此参数
# --pod-network-cidr指明 pod 网络可以使用的 IP 地址段。如果设置了这个参数,控制平面将会为每一个节点自动分配 CIDRs。
# --service-cidr默认值"10.96.0.0/12",为服务的虚拟 IP 地址另外指定 IP 地址段
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 或者在环境变量中添加export KUBECONFIG=/etc/kubernetes/admin.conf
# 添加完环境变量后刷新环境变量source /etc/profile
kubectl cluster-info
# 初始化失败后可进行重置重置命令kubeadm reset
# 执行成功后,会出现类似下列内容:
#kubeadm join 10.211.55.20:6443 --token opnt8d.m1db0aosc8q7013p \
# --discovery-token-ca-cert-hash sha256:bf4601f8a84e77cd4a67ad1cfbf59be5c5aac7cf5e2efc16809a7a044389913e
#
# kubeadm token create --print-join-command
```
## node 节点:加入集群(子节点操作)
```shell
# 运行的内容来自上方执行结果
kubeadm join 10.211.55.20:6443 --token opnt8d.m1db0aosc8q7013p \
--discovery-token-ca-cert-hash sha256:bf4601f8a84e77cd4a67ad1cfbf59be5c5aac7cf5e2efc16809a7a044389913e
# kubeadm token create --print-join-command
```
## 控制面板
```shell
kubectl get pods --all-namespaces -o wide
```
```shell
[root@localhost ~]# kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-7bdc4cb885-h685f 0/1 Pending 0 71s <none> <none> <none> <none>
kube-system coredns-7bdc4cb885-rrlbq 0/1 Pending 0 71s <none> <none> <none> <none>
kube-system etcd-k8s-node1 1/1 Running 0 76s 10.211.55.20 k8s-node1 <none> <none>
kube-system kube-apiserver-k8s-node1 1/1 Running 0 78s 10.211.55.20 k8s-node1 <none> <none>
kube-system kube-controller-manager-k8s-node1 1/1 Running 0 76s 10.211.55.20 k8s-node1 <none> <none>
kube-system kube-proxy-64rdg 1/1 Running 0 71s 10.211.55.20 k8s-node1 <none> <none>
kube-system kube-scheduler-k8s-node1 1/1 Running 0 78s 10.211.55.20 k8s-node1 <none> <none>
```
```shell
kubectl get nodes -o wide
```
```shell
[root@localhost ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-node1 NotReady control-plane 2m7s v1.27.3 10.211.55.20 <none> CentOS Stream 9 5.14.0-373.el9.aarch64 containerd://1.6.24
```
### 控制面板:配置网络,选择 Calico 配置
归档文档https://docs.tigera.io/archive/
| **Kubernetes 版本** | **Calico 版本** | **Calico 文档** | **Calico 配置** |
| ---------------------- | --------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1.18、1.19、1.20 | 3.18 | https://docs.tigera.io/archive/v3.18/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.18/manifests/calico.yaml |
| 1.19、1.20、1.21 | 3.19 | https://docs.tigera.io/archive/v3.19/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.19/manifests/calico.yaml |
| 1.19、1.20、1.21 | 3.20 | https://docs.tigera.io/archive/v3.20/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.20/manifests/calico.yaml |
| 1.20、1.21、1.22 | 3.21 | https://docs.tigera.io/archive/v3.21/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.21/manifests/calico.yaml |
| 1.21、1.22、1.23 | 3.22 | https://docs.tigera.io/archive/v3.22/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.22/manifests/calico.yaml |
| 1.21、1.22、1.23 | 3.23 | https://docs.tigera.io/archive/v3.23/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.23/manifests/calico.yaml |
| 1.22、1.23、1.24、1.25 | 3.24 | https://docs.tigera.io/archive/v3.24/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.24/manifests/calico.yaml |
| 1.22、1.23、1.24 | 3.25 | https://docs.tigera.io/archive/v3.25/getting-started/kubernetes/requirements | https://docs.tigera.io/archive/v3.25/manifests/calico.yaml |
| 1.24、1.25、1.26、1.27 | 3.26(最新版,从 2023 年 5 月开始正式更新,未测试) | https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements | https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml |
```shell
# 下载 依赖
wget --no-check-certificate https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
```
```shell
# 修改 calico.yaml 文件
vim calico.yaml
```
```shell
# 在 - name: CLUSTER_TYPE 下方添加如下内容
- name: CLUSTER_TYPE
value: "k8s,bgp"
# 下方为新增内容
- name: IP_AUTODETECTION_METHOD
value: "interface=网卡名称"
# 网卡名称通过ip addr进行查询
# INTERFACE_NAME=ens33
# sed -i '/k8s,bgp/a \ - name: IP_AUTODETECTION_METHOD\n value: "interface=INTERFACE_NAME"' calico.yaml
# sed -i "s#INTERFACE_NAME#$INTERFACE_NAME#g" calico.yaml
```
```shell
# 配置网络
kubectl apply -f calico.yaml
```
### 控制面板:查看 pods、nodes
```shell
kubectl get nodes -o wide
kubectl get pods --all-namespaces -o wide
```
## k8s安装与配置已完成下面内容是测试。
### 控制面板:创建 nginx 服务
```shell
# 带 命名空间、Service 的完整版参见https://jihulab.com/xuxiaowei-cloud/xuxiaowei-cloud/-/blob/main/docs/deployment/nginx-deployment.yaml
cat > nginx.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.23.2
ports:
- containerPort: 80
EOF
cat nginx.yaml
kubectl apply -f nginx.yaml
# 编辑
# kubectl edit deployment nginx-deployment
```
### 查看服务
```shell
kubectl get pods --all-namespaces -o wide
kubectl get pods -o wide
# 控制面板查看pod,svc
kubectl get pod,svc -o wide
```
```shell
# 控制面板:设置服务(将多个 nginx-deployment 的 pod 绑定在一起,通过一个 Service 端口统一对外提供)
kubectl expose deployment nginx-deployment --type=NodePort --name=nginx-service
# 带 命名空间、Service 的完整版参见https://jihulab.com/xuxiaowei-cloud/xuxiaowei-cloud/-/blob/main/docs/deployment/nginx-deployment.yaml
```
### 再次查看
```shell
# 控制面板查看pod,svc
kubectl get pod,svc -o wide
```
### 删除部署
```shell
kubectl delete -f nginx.yaml
```
```shell
kubectl delete deployment pod名称
```
## 其他辅助
### CentOS 命令自动补充
1. 安装 bash-completion
```shell
yum install -y bash-completion
```
2. 拷贝 kubernetes 的自动补全脚本到系统补全目录中
```shell
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
```
3. 重新加载环境变量,使设置生效
```shell
source ~/.bashrc
```
### Token 相关命令
1. 控制平面节点上运行以下命令来获取令牌
```shell
kubeadm token list
```
2. 默认情况下,令牌会在 24 小时后过期,可以通过在控制平面节点上运行以下命令来创建新令牌
```shell
kubeadm token create
```
### 相关命令
1. 查看更多信息
```shell
-o wide
```
2. 查看所有命名空间
```shell
--all-namespaces
```
3. 查看指定命名空间
```shell
-n 命名空间
```
4. 查看所有 pod
```shell
kubectl get pods --all-namespaces -o wide
```
5. 查看 pod 描述
```shell
kubectl -n 命名空间 describe pod 名称
```
6. 删除 pod
```shell
kubectl -n 命名空间 delete pod 名称
```
7. 进入 pod
```shell
kubectl exec -it pod名称 bash
```
8. 查看 Service Account
```shell
kubectl get sa --all-namespaces
```
```shell
kubectl -n 命名空间 get sa
```
9. 查看 pv
```shell
kubectl get pv
```
10. 查看 pvc
```shell
kubectl get pvc
```
11. 查看角色绑定
```shell
kubectl get rolebinding --all-namespaces -o wide
```
## 常见报错
### 子节点环境变量没有配置
```shel
[root@k8s-node2 ~]# kubectl get nodes
E1020 09:02:20.228531 3007 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1020 09:02:20.228894 3007 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1020 09:02:20.230721 3007 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1020 09:02:20.232525 3007 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
E1020 09:02:20.234259 3007 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
The connection to the server localhost:8080 was refused - did you specify the right host or port?
```
首先先进入`/etc/kubernetes`文件夹下面然后查看你的配置文件
1.27版本使用的名称为`kubelet.conf`以前版本应该是`admin.conf`
配置环境变量
```shell
echo "export KUBECONFIG=/etc/kubernetes/kubelet.conf" >> ~/.bash_profile
source ~/.bash_profile
```
现在就已经正常了

View File

@ -0,0 +1,553 @@
# 本地部署K8s集群(一键部署)
[TOC]
## 准备 Linux 主机
### 系统要求
| **Ubuntu** *16.0418.0420.04* | CPU2 核内存4 G硬盘40 G |
| ------------------------------------------------------------ | -------------------------------- |
| **Debian** *BusterStretch* | CPU2 核内存4 G硬盘40 G |
| **CentOS** *7*.x | CPU2 核内存4 G硬盘40 G |
| **Red Hat Enterprise Linux** *7* | CPU2 核内存4 G硬盘40 G |
| **SUSE Linux Enterprise Server** *15* **/openSUSE Leap** *15.2* | CPU2 核内存4 G硬盘40 G |
- CPU 必须为 x86_64暂时不支持 Arm 架构的 CPU。
- 系统应该为纯净镜像不包含其他服务
### 节点要求
- 所有节点必须都能通过 `SSH` 访问。
- 所有节点时间同步。
- 所有节点都应使用 `sudo`/`curl`/`openssl`/`tar`。
### 容器要求(可以不安装容器)
| 支持的容器运行时 | 版本 |
| :---------------------------- | :------ |
| Docker | 19.3.8+ |
| containerd | 最新版 |
| CRI-O试验版未经充分测试 | 最新版 |
| iSula试验版未经充分测试 | 最新版 |
### 依赖项要求
| 依赖项 | Kubernetes 版本 ≥ 1.18 | Kubernetes 版本 < 1.18 |
| :---------- | :--------------------- | :--------------------- |
| `socat` | 必须 | 可选,但建议安装 |
| `conntrack` | 必须 | 可选,但建议安装 |
| `ebtables` | 可选,但建议安装 | 可选,但建议安装 |
| `ipset` | 可选,但建议安装 | 可选,但建议安装 |
### 网络和 DNS 要求
- 请确保 `/etc/resolv.conf` 中的 DNS 地址可用,否则,可能会导致集群中的 DNS 出现问题。
- 网络配置使用防火墙规则或安全组,请务必确保基础设施组件可以通过特定端口相互通信。建议您关闭防火墙。
### 演示机器准备
| 主机 IP | 主机名 | 角色 | 配置 |
| :-------------- | :----- | :------------------ | -------------------------------- |
| 192.168.188.138 | master | control plane, etcd | CPU4 核内存8 G硬盘40 G |
| 192.168.188.143 | node1 | worker | CPU4 核内存8 G硬盘40 G |
| 192.168.188.144 | node2 | worker | CPU4 核内存8 G硬盘40 G |
## 初始化系统环境
所有服务器均需执行
### 更新yum源
```shell
yum -y update
```
### 配置主机名
```shell
#查看主机名称
hostname
#更改名称 hostnamectl --static set-hostname 服务器名称
hostnamectl --static set-hostname master
#查看主机名称核验
hostnamectl status
#可以重启一下服务器
#reboot
```
### 关闭防火墙
```shell
systemctl disable firewalld
systemctl stop firewalld
```
### 打开端口转发
```shell
firewall-cmd --add-masquerade --permanent # 端口转发
firewall-cmd --reload
firewall-cmd --list-all
firewall-cmd --list-all --zone=trusted
```
### 开放全部端口
```shell
firewall-cmd --zone=public --add-port=1-65535/udp --permanent
firewall-cmd --zone=public --add-port=1-65535/tcp --permanent
firewall-cmd --reload
```
### 禁用 SELinux
```shell
# 使用 sed 修改配置文件,实现彻底的禁用
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 使用命令实现临时禁用这一步其实不做也行KubeKey 会自动配置
setenforce 0
```
### 关闭swap分区
```shell
swapoff -a
echo "vm.swappiness=0" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
```
### 配置epel源国内服务器
```
rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
```
### 配置服务器时区
```shell
#配置服务器时区为 Asia/Shanghai
timedatectl set-timezone Asia/Shanghai
#验证
timedatectl
```
### 配置时间同步
```shell
#安装 chrony 作为时间同步软件
yum install chrony -y
```
```shell
#修改配置文件 /etc/chrony.conf修改 ntp 服务器配置。
vi /etc/chrony.conf
# 删除所有的 server 配置
# server 0.centos.pool.ntp.org iburst
# server 1.centos.pool.ntp.org iburst
# server 2.centos.pool.ntp.org iburst
# server 3.centos.pool.ntp.org iburst
# 增加国内的 ntp 服务器,或是指定其他常用的时间服务器
pool cn.pool.ntp.org iburst
```
```shell
#重启并设置 chrony 服务开机自启动。
systemctl enable chronyd --now
```
```shell
#验证 chrony 同步状态。
chronyc sourcestats -v
```
```shell
# 正常的输出结果如下
[root@master ~]# chronyc sourcestats -v
210 Number of sources = 4
.- Number of sample points in measurement set.
/ .- Number of residual runs with same sign.
| / .- Length of measurement set (time).
| | / .- Est. clock freq error (ppm).
| | | / .- Est. error in freq.
| | | | / .- Est. offset.
| | | | | | On the -.
| | | | | | samples. \
| | | | | | |
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
==============================================================================
tock.ntp.infomaniak.ch 41 22 297m -0.227 0.504 -12ms 4011us
makaki.miuku.net 26 10 312m -0.014 0.497 +27ms 4083us
electrode.felixc.at 22 15 241m -0.399 1.350 -49ms 6966us
ntp5.flashdance.cx 38 14 315m +0.363 0.600 +27ms 4865us
关闭系统防火墙
```
### 安装依赖组件
```shell
yum install -y ebtables socat ipset conntrack
```
### 配置基于 SSH 密钥的身份验证(可选)
仅需在`master` 主节点运行
```shell
#使用 ssh-keygen 命令生成一个新的 SSH 密钥对,一直按回车直到生密钥对
ssh-keygen -t ed25519
```
```shell
#将 SSH 公钥从 master 节点发送到其他节点。命令执行时输入 yes以接受服务器的 SSH 指纹,然后在出现提示时输入 root 用户的密码。
ssh-copy-id root@192.168.188.143
ssh-copy-id root@192.168.188.144
```
```shell
#验证登录
ssh root@192.168.188.143
ssh root@192.168.188.144
```
```shell
#输出结果如下
[root@master ~]# ssh root@192.168.188.143
Last login: Tue Oct 24 00:29:36 2023 from 192.168.188.138
[root@node1 ~]#
```
### 升级 CentOS7 内核(可选)
仅需主`master` 主节点运行
CentOS 7.9 的默认内核版本为 **3.10.0-1160.102.1**,与其他操作系统内核版本动辄 5.x、6.x 相比
### 查看当前系统内核版本
```shell
uname -r
# 3.10.0-1160.102.1.el7.x86_64
```
### 查询当前系统与 Kernel 相关的软件包
```shell
#查询当前系统安装了哪些跟 Kernel 有关的软件包,升级内核的时候,一定要把已安装的相关 kernel 包一起升级。 
rpm -qa | grep kernel
#kernel-3.10.0-1160.102.1.el7.x86_64
#kernel-tools-3.10.0-1160.102.1.el7.x86_64
#kernel-tools-libs-3.10.0-1160.102.1.el7.x86_64
```
### 增加 ELRepo 软件源
```shell
#导入 RPM GPG public key
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
#安装 ELRepo
yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
```
### 查询可用的内核软件包
```shell
#启用新增加的 ELRepo 软件仓库,查询可用的内核软件包。
yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
```
```shell
[root@master ~]# yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
已加载插件fastestmirror
Loading mirror speeds from cached hostfile
* elrepo-kernel: mirrors.tuna.tsinghua.edu.cn
可安装的软件包
kernel-lt-devel.x86_64 5.4.258-1.el7.elrepo elrepo-kernelkernel-lt-doc.noarch 5.4.258-1.el7.elrepo elrepo-kernelkernel-lt-headers.x86_64 5.4.258-1.el7.elrepo elrepo-kernelkernel-lt-tools-libs-devel.x86_64 5.4.258-1.el7.elrepo elrepo-kernelkernel-ml.x86_64 6.5.8-1.el7.elrepo elrepo-kernelkernel-ml-devel.x86_64 6.5.8-1.el7.elrepo elrepo-kernelkernel-ml-doc.noarch 6.5.8-1.el7.elrepo elrepo-kernelkernel-ml-headers.x86_64 6.5.8-1.el7.elrepo elrepo-kernelkernel-ml-tools.x86_64 6.5.8-1.el7.elrepo elrepo-kernelkernel-ml-tools-libs.x86_64 6.5.8-1.el7.elrepo elrepo-kernelkernel-ml-tools-libs-devel.x86_64 6.5.8-1.el7.elrepo elrepo-kernelperf.x86_64 5.4.258-1.el7.elrepo elrepo-kernelpython-perf.x86_64 5.4.258-1.el7.elrepo elrepo-kernel[root@master ~]#
#当前最新 lt 版内核为 5.4.258-1 a信用最新版本内核
```
### 安装新版本内核
```shell
#只安装内核,同时安装其他包会报错
yum --enablerepo=elrepo-kernel install kernel-lt
#安装成功会提示
#Complete!
```
### 配置新内核引导系统
```shell
#查看已经安装的 kernel 信息
grubby --info=ALL | grep ^kernel
#kernel=/boot/vmlinuz-5.4.258-1.el7.elrepo.x86_64
#kernel=/boot/vmlinuz-3.10.0-1160.102.1.el7.x86_64
#kernel=/boot/vmlinuz-3.10.0-1062.el7.x86_64
#kernel=/boot/vmlinuz-0-rescue-fc61eb831f5b4eda852bfd7c596c8c87
```
```shell
#查看当前系统默认内核
grubby --default-kernel
#/boot/vmlinuz-3.10.0-1160.102.1.el7.x86_64
```
```shell
#修改系统默认内核为新内核
grubby --set-default "/boot/vmlinuz-5.4.258-1.el7.elrepo.x86_64"
```
```shell
#查看系统默认内核
grubby --default-kernel
/boot/vmlinuz-5.4.258-1.el7.elrepo.x86_64
```
```shell
#重启
reboot
```
进入引导画面后选中最新的内核默认启动
![image-20231024093226585](https://lsky.hhdxw.top/imghub/2023/10/image-202310241698111147.png)
### 重启系统并查看系统内核
```shell
#查看内核版本信息
uname -rs
#Linux 5.4.258-1.el7.elrepo.x86_64
```
```shell
#查看已经安装的内核相关软件
rpm -qa | grep kernel
#kernel-lt-5.4.258-1.el7.elrepo.x86_64
#kernel-lt-tools-3.10.0-1160.102.1.el7.elrepo.x86_64
#kernel-3.10.0-1160.102.1.el7.x86_64
#kernel-3.10.0-1062.el7.x86_64
#kernel-lt-tools-libs-3.10.0-1160.102.1.el7.elrepo.x86_64
```
```shell
# 卸载旧版本的 kernel-tools 相关软件包
yum remove kernel-tools-3.10.0-1160.102.1.el7.x86_64 kernel-tools-libs-3.10.0-1160.102.1.el7.x86_64
# 安装新版本的 kernel-tools 相关软件包
yum --enablerepo=elrepo-kernel install kernel-lt-tools kernel-lt-tools-libs
```
## 下载 KubeKey
下面只需要 `master` 主节点运行即可
先执行以下命令以确保您从正确的区域下载 KubeKey。
```shell
export KKZONE=cn
```
执行以下命令下载 KubeKey
```shell
curl -sfL https://get-kk.kubesphere.io | VERSION=v3.0.7 sh -
```
`kk` 添加可执行权限:
```shell
chmod +x kk
```
## 创建集群
### 查看 KubeKey 支持的 Kubernetes 版本列表
```shell
./kk version --show-supported-k8s
```
### 创建配置文件
命令如下:
```shell
./kk create config [--with-kubernetes version] [--with-kubesphere version] [(-f | --file) path]
```
- 安装 KubeSphere 3.3 的建议 Kubernetes 版本v1.20.x、v1.21.x、* v1.22.x、* v1.23.x 和 * v1.24.x。带星号的版本可能出现边缘节点部分功能不可用的情况。因此如需使用边缘节点推荐安装 v1.21.x。如果不指定 Kubernetes 版本KubeKey 将默认安装 Kubernetes v1.23.10。
- 如果您在此步骤的命令中不添加标志 `--with-kubesphere`,则不会部署 KubeSphere只能使用配置文件中的 `addons` 字段安装,或者在您后续使用 `./kk create cluster` 命令时再次添加这个标志。
- 如果您添加标志 `--with-kubesphere` 时不指定 KubeSphere 版本,则会安装最新版本的 KubeSphere。
示例默认K8s版本1.23.10KubeSphere3.3.2
```shell
./kk create config --with-kubesphere 3.3.2
```
### 编辑配置文件
如果不改名称,那么将创建默认文件 `config-sample.yaml`
```shell
vi config-sample.yaml
```
### 主机
请参照上方示例在 `hosts` 下列出您的所有机器并添加详细信息。
`name`:实例的主机名。
`address`:任务机和其他实例通过 SSH 相互连接所使用的 IP 地址。根据您的环境,可以是公有 IP 地址或私有 IP 地址。例如,一些云平台为每个实例提供一个公有 IP 地址,用于通过 SSH 访问。在这种情况下,您可以在该字段填入这个公有 IP 地址。
`internalAddress`:实例的私有 IP 地址。
### roleGroups
- `etcd`etcd 节点名称
- `control-plane`:主节点名称
- `worker`:工作节点名称
### 提示
- 在安装 KubeSphere 之前,您可以使用 `hosts` 下提供的信息(例如 IP 地址和密码)通过 SSH 的方式测试任务机和其他实例之间的网络连接。
- 在安装前,请确保端口 `6443` 没有被其他服务占用,否则在安装时会产生冲突(`6443` 为 API 服务器的默认端口)。
### 示例:
```yml
apiVersion: kubekey.kubesphere.io/v1alpha2
kind: Cluster
metadata:
name: sample
spec:
hosts:
- {name: master, address: 192.168.188.138, internalAddress: 192.168.188.138, user: root, password: root}
#上面配置ssh密钥对以后可以使用秘钥直接访问,如没有配置,请使用下面注释内容通过远程访问
- {name: node1, address: 192.168.188.143, internalAddress: 192.168.188.143, privateKeyPath: "~/.ssh/id_ed25519"}
- {name: node2, address: 192.168.188.144, internalAddress: 192.168.188.144, privateKeyPath: "~/.ssh/id_ed25519"}
#- {name: node1, address: 192.168.188.143, internalAddress: 192.168.188.143, user: root, password: root}
#- {name: node2, address: 192.168.188.144, internalAddress: 192.168.188.144, user: root, password: root}
roleGroups:
etcd:
- master
control-plane:
- master
worker:
- node1
- node2
```
### 使用配置文件创建集群
```shell
./kk create cluster -f config-sample.yaml
```
如果使用其他名称,则需要将上面的 `config-sample.yaml` 更改为您自己的文件。
整个安装过程可能需要 10 到 20 分钟,具体取决于您的计算机和网络环境。
### 验证安装
安装完成后,您会看到如下内容:
```shell
#####################################################
### Welcome to KubeSphere! ###
#####################################################
Console: http://192.168.188.138:30880
Account: admin
Password: P@88w0rd
NOTES
1. After you log into the console, please check the
monitoring status of service components in
"Cluster Management". If any service is not
ready, please wait patiently until all components
are up and running.
2. Please change the default password after login.
#####################################################
https://kubesphere.io 2023-10-24 00:37:49
#####################################################
```
## 安装插件
### devops
`admin` 用户登录控制台,点击左上角的**平台管理**,选择**集群管理**。
点击**定制资源定义**,在搜索栏中输入 `clusterconfiguration`,点击搜索结果查看其详细页面。
定制资源定义CRD允许用户在不新增 API 服务器的情况下创建一种新的资源类型,用户可以像使用其他 Kubernetes 原生对象一样使用这些定制资源。
在**自定义资源**中,点击 `ks-installer` 右侧的更多,选择**编辑 YAML**。
在该 YAML 文件中,搜索 `devops`,将 `enabled``false` 改为 `true`。完成后,点击右下角的**确定**,保存配置。
```
devops:
enabled: true # 将“false”更改为“true”。
```
添加`minio`版本,在spec下面添加下面四个地址
```shell
spec:
minio_repo: docker.io.minio/minio
minio_tag: RELEASE.2021-12-29T06-49-06Z
mc_repo: docker.io.minio/mc
mac_tag: RELEASE.2021-12-29T06-52-55Z
```
在 kubectl 中执行以下命令检查安装过程:
```
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
```
## 卸载插件
### devops
卸载 DevOps
```
helm uninstall -n kubesphere-devops-system devops
kubectl patch -n kubesphere-system cc ks-installer --type=json -p='[{"op": "remove", "path": "/status/devops"}]'
kubectl patch -n kubesphere-system cc ks-installer --type=json -p='[{"op": "replace", "path": "/spec/devops/enabled", "value": false}]'
```
删除 DevOps 资源:
```
# 删除所有 DevOps 相关资源
for devops_crd in $(kubectl get crd -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | grep "devops.kubesphere.io"); do
for ns in $(kubectl get ns -ojsonpath='{.items..metadata.name}'); do
for devops_res in $(kubectl get $devops_crd -n $ns -oname); do
kubectl patch $devops_res -n $ns -p '{"metadata":{"finalizers":[]}}' --type=merge
done
done
done
# 删除所有 DevOps CRD
kubectl get crd -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | grep "devops.kubesphere.io" | xargs -I crd_name kubectl delete crd crd_name
# 删除 DevOps 命名空间
kubectl delete namespace kubesphere-devops-system
```

View File

@ -611,7 +611,7 @@ FROM [base_image]
#### 2⽤于将⽂件复制到镜像中源可以使URL或者本地⽂件也可以⼀个压缩⽂件⾃动解压
```shell
ADD
ADD [--chown=<user>:<group>] [源路径] [⽬标路径]
```
#### 3⽤于将⽂件拷⻉到镜像中源只能是本地⽂件
@ -656,3 +656,59 @@ VOLUME <路径>
VOLUME ["路径1", "路径2"...]
```
#### 8声明镜像创建者
```shell
MAINTAINER user_name
```
## Docker 开放2375端口
开启端口命令 --permanent永久生效没有此参数重启后失效
```shell
firewall-cmd --zone=public --add-port=2375/tcp --permanent
```
重新载入
```shell
firewall-cmd --reload
```
使用 vimvi 编辑docker服务配置文件
```shell
vim /lib/systemd/system/docker.service
```
找到如下配置行
```shell
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
```
将其注释掉或者直接删除,替换成下面的配置行.然后保存退出
```shell
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
```
重新加载docker配置并重启服务
```shell
systemctl daemon-reload && systemctl restart docker
```
然后直接在命令行客户端输入如下命令IP地址改为自己的
```shell
curl http://IP地址:2375/version
```
或者在浏览器直接访问IP地址改为自己的
```shell
http://IP地址:2375/version
```

View File

@ -0,0 +1,99 @@
更新一下环境:
```
yum -y update
```
安装一些必要的系统工具:
```
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
```
添加软件源信息:
```
sudo yum install -y yum-utils
```
国内阿里源
```
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
```
docker官方镜像源
```
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
```
安装 Docker
```
sudo yum install docker-ce docker-ce-cli containerd.io
```
启动 Docker 后台服务
```
sudo systemctl start docker
sudo systemctl enable docker
```
测试运行 hello-world
```
docker run hello-world
```
部分镜像源
```shell
sudo vim /etc/docker/daemon.json
```
镜像源
```
{
"registry-mirrors": [
"https://9kkc1zdn.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com/",
"https://docker.mirrors.ustc.edu.cn/",
"https://registry.docker-cn.com"
"https://hub.docker.com"
]
}
```
上传地址设置
```json
```
重启开启镜像源
```shell
systemctl daemon-reload
systemctl restart docker
```
安装 Docker-compose
```shell
yum install docker-compose-plugin
```
开放所有端口
```shell
firewall-cmd --zone=public --add-port=1-65535/udp --permanent
firewall-cmd --zone=public --add-port=1-65535/tcp --permanent
firewall-cmd --reload
```

View File

@ -0,0 +1,62 @@
开启端口命令 --permanent永久生效没有此参数重启后失效
```
firewall-cmd --zone=public --add-port=2375/tcp --permanent
```
重新载入
```
firewall-cmd --reload
```
使用 vim 编辑docker服务配置文件
```
vim /lib/systemd/system/docker.service
```
找到如下配置行
```
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
```
将其注释掉或者直接删除,替换成下面的配置行.然后保存退出
```
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
```
重新加载docker配置并重启服务
```
systemctl daemon-reload && systemctl restart docker
```
然后直接在命令行客户端输入如下命令IP地址改为自己的
```
curl http://IP地址:2375/version
```
或者在浏览器直接访问IP地址改为自己的
```
http://IP地址:2375/version
```
```xml
{
"insecure-registries": [
"10.211.55.2:8082"
],
"registry-mirrors": [
"10.211.55.2:8082"
]
}
```

View File

@ -0,0 +1,62 @@
ELK Stack 是一个用于日志管理和分析的开源工具组合它是一套开源免费、功能强大的日志分析管理系统。ELK可以将我们的系统日志、网站日志、应用系统日志等各种日志进行收集、过滤、清洗、然后进行集中存放并可用于实时检索、分析。这三款软件都是开源软件通常配合使用而且又先后归于Elastic.co公司名下故又称为ELK Stack。官网 https://www.elastic.co/cn/elastic-stack
## 1.Elasticsearch简称为ES
它是一个实时的分布式搜索和分析引擎基于Lucene库。ES可以处理大规模数据集并提供快速的搜索、聚合和分析能力。它具有分布式架构可以通过水平扩展来处理海量数据并提供高可用性和容错机制。
- 作用:用于存储、搜索和分析大规模数据集,提供快速的搜索、聚合和分析能力。
- 使用:
- 存储数据ES使用分片和副本机制在多个节点上分布和复制数据以实现高可用性和容错性。
- 搜索和查询ES支持全文搜索、近实时搜索和复杂的查询操作可以通过API进行搜索和过滤。
- 聚合和分析ES提供聚合功能可以对数据进行汇总和统计并支持数据可视化。
- 可扩展性和分布式部署ES可以通过水平扩展来处理大规模数据并在集群中自动管理数据分布和负载均衡。
## 2.Logstash
它是一个灵活的数据收集、处理和传输工具。Logstash可以从多种来源如日志文件、数据库、消息队列等收集数据并对数据进行预处理、转换和标准化。它还支持多种输出方式可以将处理后的数据发送到Elasticsearch等目标存储或分析系统。
- 作用:用于收集、处理和传输各种类型的数据,以准备数据供后续分析和存储。
- 使用:
- 数据收集Logstash支持从多种来源如日志文件、数据库、消息队列等收集数据。
- 数据处理Logstash提供丰富的过滤器插件可以对数据进行解析、转换和标准化以便后续处理和分析。
- 数据传输Logstash支持将处理后的数据发送到各种目标存储或分析系统如Elasticsearch、Kafka等。
## 3.Kibana
它是一个用于数据可视化和分析的开源工具。Kibana提供了一个直观易用的Web界面可以通过图表、表格、地图等形式展示和分析Elasticsearch中的数据。用户可以使用Kibana创建仪表盘、查询数据、构建可视化报告等。
- 作用:用于通过图表、表格、地图等形式对数据进行可视化和分析。
- 使用:
- 数据查询与展示Kibana提供一个直观易用的Web界面用户可以使用Kibana查询和过滤Elasticsearch中的数据并以图表、表格等形式展示数据。
- 仪表盘创建Kibana支持创建自定义的仪表盘将多个可视化组件整合到一个页面上以实现更全面和直观的数据展示。
- 报表和警报Kibana还提供报表功能可以将可视化结果导出为PDF或CSV格式同时支持设置警报以便实时监控数据指标并触发相应的操作。
## 4.ELK Stack的典型工作流程
1. 数据收集Logstash作为数据收集器从各种数据源如日志文件、数据库、消息队列等中收集数据并进行过滤、解析和标准化处理。
2. 数据存储经过处理后的数据被发送到Elasticsearch进行索引和存储。Elasticsearch使用分片和副本机制将数据分布和复制在多个节点上以实现高可用性和容错性。
3. 数据可视化和分析用户可以通过Kibana访问Elasticsearch中的数据使用Kibana的Web界面进行数据查询、过滤、聚合和可视化操作。Kibana提供了丰富的图表、表格、地图等可视化组件用户可以创建仪表盘、报表和警报以便实时监控和分析数据。
## 5.ELK Stack的优点
1. 灵活和可扩展ELK Stack的三个组件都是开源的并且具有良好的可扩展性。可以根据需求扩展集群规模处理大规模数据集满足不断增长的数据量和用户需求。
2. 实时性ELK Stack能够实时处理和分析数据可以快速响应变化并提供近实时的搜索和可视化结果。
3. 丰富的功能ELK Stack提供了丰富的功能和插件支持可以进行复杂的数据处理、搜索、聚合和可视化操作。用户可以根据需求自定义工作流程并满足各种数据分析和业务监控的需求。
4. 强大的查询能力Elasticsearch作为核心组件提供了强大的全文搜索和复杂查询功能可以高效地检索和过滤数据。
## 6.ELK Stack的缺点
1. 学习较难对于初学者来说ELK Stack的学习不易特别是对于不熟悉分布式系统和复杂查询语法的人来说。
2. 需要一定的硬件资源由于ELK Stack处理大规模数据集和实时分析的能力需要一定的硬件资源支持包括存储空间、计算能力和网络带宽等。
3. 数据安全性和权限管理ELK Stack在数据安全性和权限管理方面需要额外的配置和注意以确保只有授权的用户可以访问和操作数据。

View File

@ -0,0 +1,417 @@
ELK Stack
https://www.51cto.com/article/707776.html
这次先讲解 ELK Stack 的方式,这种方式对我们的代码无侵入,核心思想就是收集磁盘的日志文件,然后导入到 Elasticsearch。
比如我们的应用系统通过 logback 把日志写入到磁盘文件,然后通过这一套组合的中间件就能把日志采集起来供我们查询使用了。
流程如下:
- 先使用 Filebeat 把日志收集起来,然后把数据再传给 Logstash。
- 通过 Logstash 强大的数据清洗功能。
- 最终把数据写入到 Elasticsearch 中。
- 并由 Kibana 进行可视化。
温馨提示:以下案例都在一台 ubuntu 虚拟机上完成,内存分配了 6G。
### 一、部署 Elasticsearch
数据库获取 elasticsearch 镜像:
```
docker pull elasticsearch:7.7.1
```
创建挂载目录:
```
mkdir -p /data/elk/es/{config,data,logs}
```
赋予权限:
```
chown -R 1000:1000 /data/elk/es
```
创建配置文件:
```
cd /data/elk/es/config
touch elasticsearch.yml
-----------------------配置内容----------------------------------
cluster.name: "my-es"
network.host: 0.0.0.0
http.port: 9200
```
启动 elasticsearch 容器:
```
docker run -it -d -p 9200:9200 -p 9300:9300 --name es -e ES_JAVA_OPTS="-Xms1g -Xmx1g" -e "discovery.type=single-node" --restart=always -v /data/elk/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /data/elk/es/data:/usr/share/elasticsearch/data -v /data/elk/es/logs:/usr/share/elasticsearch/logs elasticsearch:7.7.1
```
验证 elasticsearch 是否启动成功:
```
curl http://localhost:9200
```
### 二、部署 Kibana 可视化工具
#### 2.1 安装 Kibana
获取 kibana 镜像:
```
docker pull kibana:7.7.1
```
获取elasticsearch容器 ip
```
docker inspect --format '{{ .NetworkSettings.IPAddress }}' es
```
结果172.17.0.2
创建 kibana 配置文件:
```
mkdir -p /data/elk/kibana/
vim /data/elk/kibana/kibana.yml
```
配置内容:
```
#Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: ["http://172.17.0.2:9200"]
xpack.monitoring.ui.container.elasticsearch.enabled: true
```
#### 2.2 运行 kibana
```
docker run -d --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name kibana -p 5601:5601 -v /data/elk/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml kibana:7.7.11.
```
访问 http://192.168.56.10:5601。这个 IP 是服务器的 IP。Kibana 控制台的界面如下所示,打开 kibana 时,首页会提示让你选择加入一些测试数据,点击 try our sample data 按钮就可以了。
### 三、部署 logstash 日志过滤、转换工具
#### 3.1 安装 Java JDK
```
yum install java-1.8.0-openjdk.x86_64
```
修改 /etc/profile 文件:
```
sudo vim /etc/profile
```
添加如下的内容到你的 .profile 文件中:
```
# JAVA
JAVA_HOME="/usr/lib/jdk/jdk-12"
PATH="$PATH:$JAVA_HOME/bin"
```
再在命令行中打入如下的命令:
```
source /etc/profile1.
```
查看 java 是否配置成功:
```
java -version
```
#### 3.2 安装 logstash
下载 logstash 安装包:
```
curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-7.7.1.tar.gz
```
解压安装:
```
tar -xzvf logstash-7.7.1.tar.gz
```
要测试 Logstash 安装,请运行最基本的 Logstash 管道。例如:
```
cd logstash-7.7.1
bin/logstash -e 'input { stdin { } } output { stdout {} }'
```
等 Logstash 完成启动后,我们在 stdin 里输入以下文字,我们可以看到如下的输出:
当我们打入一行字符然后回车,那么我们马上可以在 stdout 上看到输出的信息。如果我们能看到这个输出,说明我们的 Logstash 的安装是成功的。
我们进入到 Logstash 安装目录,并修改 config/logstash.yml 文件。我们把 config.reload.automatic 设置为 true。
```yaml
config.reload.automatic: true
```
另外一种运行 Logstash 的方式,也是一种最为常见的运行方式,运行时指定 logstash 配置文件。
#### 3.3 配置 logstash
Logstash 配置文件有两个必需元素,输入(inputs)和输出(ouputs),以及一个可选元素 filters。输入插件配置来源数据过滤器插件在你指定时修改数据输出插件将数据写入目标。
创建 kibana 配置文件 weblog.conf
```
mkdir -p /logstash-7.7.1/streamconf
vim /logstash-7.7.1/streamconf/weblog.conf
```
配置内容如下:
```
input {
tcp {
port => 9900
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
mutate {
convert => {
"bytes" => "integer"
}
}
geoip {
source => "clientip"
}
useragent {
source => "agent"
target => "useragent"
}
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
}
output {
stdout { }
elasticsearch {
hosts => ["localhost:9200"]
}
}
```
在上面我们同时保留两个输出stdout 及 elasticsearch。事实上我们可以定义很多个的输出。stdout 输出对于我们初期的调试是非常有帮助的。等我们完善了所有的调试,我们可以把上面的 stdout 输出关掉。
等更新完这个配置文件后,我们在另外一个 console 中发送第一个 log
```
head -n 1 weblog-sample.log | nc localhost 9900
```
这个命令的意思:我们使用 nc 应用读取第一行数据,然后发送到 TCP 端口号 9900并查看 console 的输出。
这里的 weblog-sample.log 为样例数据,内容如下,把它放到本地作为日志文件。
```
14.49.42.25 - - [12/May/2019:01:24:44 +0000] "GET /articles/ppp-over-ssh/
HTTP/1.1" 200 18586 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US;
rv:1.9.2b1) Gecko/20091014 Firefox/3.6b1 GTB5"
```
logstash 控制台打印出了 weblog-samle.log 中的内容:
![image-20240104174304131](https://lsky.hhdxw.top/imghub/2024/01/image-202401041704361384.png)
这一次,我们打开 Kibana执行命令成功看到 es 中的这条记录。
```
GET logstash/_search
```
![image-20240104174326473](https://lsky.hhdxw.top/imghub/2024/01/image-202401041704361406.png)
### 四、部署 Filebeat 日志收集工具
#### 4.1 安装 Filebeat
```
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.7.1-linux-x86_64.tar.gz
tar xzvf filebeat-7.7.1-linux-x86_64.tar.gz
```
请注意:由于 ELK 迭代比较快,我们可以把上面的版本 7.7.1 替换成我们需要的版本即可。我们先不要运行 Filebeat。
#### 4.2 配置 Filebeat
我们在 Filebeat 的安装目录下,可以创建一个这样的 filebeat_apache.yml 文件,它的内容如下,首先先让 filebeat 直接将日志文件导入到 elasticsearch来确认 filebeat 是否正常工作。
```
filebeat.inputs:
- type: log
enabled: true
paths:
- /home/vagrant/logs/*.log
output.elasticsearch:
hosts: ["192.168.56.10:9200"]
```
paths 对应你的日志文件夹路径,我配置的是这个:/home/vagrant/logs/*.log之前配置成 /home/vagrant/logs 不能正常收集。另外这里可以放入多个日志路径。
#### 4.3 测试 Filebeat
在使用时,你先要启动 Logstash然后再启动 Filebeat。
```
bin/logstash -f weblog.conf
```
然后,再运行 Filebeat -c 表示运行指定的配置文件,这里是 filebeat_apache.yml。
```
./filebeat -e -c filebeat_apache.yml
```
运行结果如下所示一定要确认下控制台中是否打印了加载和监控了我们指定的日志。如下图所示有三个日志文件被监控到了error.log、info.log、debug.log
我们可以通过这个命令查看 filebeat 的日志是否导入成功了:
```
curl http://localhost:9200/_cat/indices?v
```
这个命令会查询 Elasticsearch 中所有的索引如下图所示filebeat-7.7.1-* 索引创建成功了。因为我没有配置索引的名字,所以这个索引的名字是默认的。
在 kibana 中搜索日志,可以看到导入的 error 的日志了。不过我们先得在 kibana 中创建 filebeat 的索引(点击 create index pattern 按钮,然后输入 filebeat 关键字,添加这个索引),然后才能在 kibana 的 Discover 控制台查询日志。
#### 4.4 Filebeat + Logstash
接下来我们配置 filebeat 收集日志后,输出到 logstash然后由 logstash 转换数据后输出到 elasticsearch。
```yaml
filebeat.inputs:
- type: log
enabled: true
paths:
- /home/vagrant/logs/*.log
output.logstash:
hosts: ["localhost:9900"]
```
修改 logstash 配置文件:
```
vim /logstash-7.7.1/streamconf/weblog.conf
```
配置了 input 为 beats修改了 useragent
```
input {
beats {
port => "9900"
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
mutate {
convert => {
"bytes" => "integer"
}
}
geoip {
source => "clientip"
}
useragent {
source => "user_agent"
target => "useragent"
}
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
}
output {
stdout {
codec => dots {}
}
elasticsearch {
hosts=>["192.168.56.10:9200"]
index => "apache_elastic_example"
}
}
```
然后重新启动 logstash 和 filebeat。有个问题这次启动 filebeat 的时候,只监测到了一个 info.log 文件,而 error.log 和 debug.log 没有监测到,导致只有 info.log 导入到了 Elasticsearch 中。filebeat 只监测到了 info.log 文件
logstash 输出结果如下,会有格式化后的日志:
我们在 Kibana dev tools 中可以看到索引 apache_elastic_example说明索引创建成功日志也导入到了 elasticsearch 中。
另外注意下 logstash 中的 grok 过滤器,指定的 message 的格式需要和自己的日志的格式相匹配,这样才能将我们的日志内容正确映射到 message 字段上。
例如我的 logback 的配置信息如下:
而我的 logstash 配置如下,和 logback 的 pettern 是一致的。
```yaml
grok {
match => { "message" => "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n" }
}
```
然后我们在 es 中就能看到日志文件中的信息了。如下图所示:
至此Elasticsearch + Logstash + Kibana + Filebeat 部署成功,可以愉快地查询日志了~
后续升级方案:
- 加上 Kafka。
- 加上 Grafana 监控。
- 链路追踪。

View File

@ -0,0 +1,451 @@
`GrayLog`是一个轻量型的分布式日志管理平台,一个开源的日志聚合、分析、审计、展示和预警工具。在功能上来说,和 ELK类似但又比 ELK要简单轻量许多。依靠着更加简洁高效部署使用简单的优势很快受到许多公司的青睐。
![](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704805912.png)
官网https://www.graylog.org/
>- `GrayLog`方案的优势
>- 一体化方案安装方便不像ELK有3个独立系统间的集成问题。
>- 采集原始日志并可以事后再添加字段比如http_status_coderesponse_time等等。
>
>- 自己开发采集日志的脚本并用curl/nc发送到`Graylog Server`发送格式是自定义的GELF`Flunted`和`Logstash`都有相应的输出GELF消息的插件。自己开发带来很大的自由度。实际上只需要用`inotifywait`监控日志的modify事件并把日志的新增行用curl/netcat发送到`Graylog Server`就可。
>
>- 搜索结果高亮显示,就像`google`一样。
>
>- 搜索语法简单,比如: `source:mongo AND reponse_time_ms:>5000`,避免直接输入`elasticsearch`搜索json`语法`
>
>- 搜索条件可以导出为`elasticsearch`的搜索json`文本`,方便直接开发调用`elasticsearch rest api`的搜索脚本。
## Graylog工作流程
![img](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704762652.jpeg)
## 最小化安装基本框架
![img](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704762728.png)
流程如下:
- 微服务中的`GrayLog`客户端发送日志到`GrayLog`服务端
- `GrayLog`把日志信息格式化,存储到`Elasticsearch`
- 客户端通过浏览器访问`GrayLog``GrayLog`访问`Elasticsearch`
这里`MongoDB`是用来存储`GrayLog`的配置信息的,这样搭建集群时,`GrayLog`的各节点可以共享配置。
- `MongoDB` 用于存储配置元信息和配置数据(无需太多硬件资源配置)
- `Elasticsearch` 用于存储日志数据内存大以及更高的磁盘IO
- `Graylog` 用于读取日志、展示日志。CPU密集
缺点:
- 系统无冗余、容易出现单点故障,适合测试阶段
## 大型生产环境架构
![img](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704762891.png)
>- 客户访问和日志源面对的是前端的`LB``LB`通过`Graylog REST API `负载管理Graylog集群
>- `Elasticsearch` 使用集群方案,多节点存储数据,达到备份冗余、负载的效应
>- `MongoDB` 集群,具备自动的容错功能(auto-failover),自动恢复的(auto-recovery)的高可用
>- 各组件方便伸缩扩展
## 安装部署
使用 docker-compose 最小化安装
```
#部署Elasticsearch
docker run -d \
--name elasticsearch \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--privileged \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:7.17.5
#部署MongoDB(使用之前部署的服务即可)
docker run -d \
--name mongodb \
-p 27017:27017 \
--restart=always \
-v mongodb:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=xlcs \
-e MONGO_INITDB_ROOT_PASSWORD=123321 \
mongo:4.4
#部署
docker run \
--name graylog \
-p 9000:9000 \
-p 12201:12201/udp \
-e GRAYLOG_HTTP_EXTERNAL_URI=http://<IP>:9000/ \
-e GRAYLOG_ELASTICSEARCH_HOSTS=http://<IP>:9200/ \
-e GRAYLOG_ROOT_TIMEZONE="Asia/Shanghai" \
-e GRAYLOG_WEB_ENDPOINT_URI="http://<IP>:9000/:9000/api" \
-e GRAYLOG_PASSWORD_SECRET="somepasswordpepper" \
-e GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 \
-e GRAYLOG_MONGODB_URI=mongodb://xlcs:123321@<IP>:27017/admin \
-d \
graylog/graylog:4.3
```
命令解读:
- 端口信息:
- - `-p 9000:9000``GrayLog`的http服务端口9000
- `-p 12201:12201/udp``GrayLog`的GELF UDP协议端口用于接收从微服务发来的日志信息
- 环境变量
- - `-e GRAYLOG_HTTP_EXTERNAL_URI`对外开放的ip和端口信息这里用9000端口
- `-e GRAYLOG_ELASTICSEARCH_HOSTS``GrayLog`依赖于`ES`,这里指定`ES`的地址
- `-e GRAYLOG_WEB_ENDPOINT_URI`对外开放的API地址
- `-e GRAYLOG_PASSWORD_SECRET`:密码加密的秘钥
- `-e GRAYLOG_ROOT_PASSWORD_SHA2`:密码加密后的密文。明文是`admin`,账户也是`admin`
- `-e GRAYLOG_ROOT_TIMEZONE="Asia/Shanghai"``GrayLog`容器内时区
- `-e GRAYLOG_MONGODB_URI`:指定`MongoDB`的链接信息
- `graylog/graylog:4.3`使用的镜像名称版本为4.3
查看运行状态
![image-20240109092047285](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704763247.png)
访问地址 http://<IP>:9000/ 如果可以看到如下界面说明启动成功。
![image-20240109092430238](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704763470.png)
通过 `admin/admin`登录,即可看到欢迎页面,目前还没有数据:
![image-20240109092519114](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704763519.png)
## 简单使用以及介绍
>- `Search` 搜索:该选项允许您按特定条件搜索和筛选日志数据,例如时间范围、源、消息和其他字段。还可以将搜索保存为仪表板小部件或警报。
>- `Streams`流用于实时处理和过滤传入的日志数据。可以根据特定规则和条件创建流Graylog 将自动对数据进行分类和索引以供进一步分析。
>- `Alerts` 警报:警报允许您为特定事件或条件设置通知。例如,可以设置警报以在出现突然错误峰值或在日志中出现特定消息时通知。
>- `Dashboards` 仪表板:仪表板允许您以有意义的方式可视化日志数据。可以创建自定义仪表板,其中包含图表、图形和表格,显示想要监控的数据。
>- `Enterprise` 企业版高级版功能提供额外的功能如基于角色的访问控制、LDAP/AD集成和集群以实现高可用性和可扩展性。
>- `Security` 安全性:该选项提供加密、身份验证和授权等安全功能,以确保日志数据受到保护。
>- `System` 系统:该选项提供系统级别的设置和配置,例如管理用户、设置输入和输出插件以及监控系统性能。
### 1.配置 `Inputs`
部署完成`GrayLog`后,需要配置`Inputs`才能接收微服务发来的日志数据。
第一步,在`System`菜单中选择`Inputs`
![image-20240109094050433](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704764450.png)
第二步,在页面的下拉选框中,选择`GELF UDP`
![5037550cc85d85f5fe12861a64843466](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704764674.png)
然后点击`Launch new input`按钮:
![21110bb0182c00ebea37f4e235375fd3](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704764708.png)
点击`save`保存:
![image-20240109094333858](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704764614.png)
可以看到,`GELF UDP Inputs `保存成功。
### 2.整合微服务
现在GrayLog的服务端日志收集器已经准备好我们还需要在项目中添加GrayLog的客户端将项目日志发送到GrayLog服务中保存到ElasticSearch。
基本步骤如下:
- 引入GrayLog客户端依赖
- 配置Logback集成GrayLog的Appender
- 启动并测试
导入依赖:
```xml
<dependency>
<groupId>biz.paluch.logging</groupId>
<artifactId>logstash-gelf</artifactId>
<version>1.15.0</version>
</dependency>
```
配置`Logback`,在配置文件中增加 `GELF`的`appender`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 说明:
1、日志级别及文件 日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中。
2、日志级别可以根据开发环境进行配置为方便统一管理查看日志日志文件路径统一由LOG_PATH:-.配置在/home/项目名称/logs
-->
<configuration>
<!-- 引入默认设置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 编码格式设置 -->
<property name="ENCODING" value="UTF-8"/>
<!-- 日志文件的存储地址由application.yml中的logging.path配置根路径默认同项目路径 -->
<!-- <property name="LOG_HOME" value="${LOG_PATH:-./logs}"/>-->
<property name="LOG_HOME" value="/Users/yovinchen/Desktop/project/xlcs/xlcs-parent/data/logs"/>
<property name="LOG_FILE_MAX_SIZE" value="100MB"/>
<property name="LOG_FILE_MAX_HISTORY" value="180"/>
<property name="LOG_TOTAL_SIZE_CAP" value="100GB"/>
<!--应用名称-->
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="springBoot"/>
<!-- 常规输出格式:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<property name="NORMAL_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}.%method@%line - %msg%n"/>
<!-- 彩色输出格式magenta洋红boldMagenta粗红yan青色·#══> -->
<property name="CONSOLE_LOG_PATTERN"
value="%boldMagenta([%d{yyyy-MM-dd HH:mm:ss.SSS}]) %red([%thread]) %boldMagenta(%-5level) %blue(%logger{20}.%method@%line) %magenta(·#═>) %cyan(%msg%n)"/>
<!-- ==========================控制台输出设置========================== -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- ==========================按天输出DEBUG日志设置========================== -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--设置文件命名格式-->
<FileNamePattern>${LOG_HOME}/${APP_NAME}/debug/${POD_NAME}-%d{yyyy-MM-dd}-%i.log</FileNamePattern>
<!--设置日志文件大小超过就重新生成文件默认10M-->
<maxFileSize>${LOG_FILE_MAX_SIZE}</maxFileSize>
<!--日志文件保留天数默认30天-->
<maxHistory>${LOG_FILE_MAX_HISTORY}</maxHistory>
<totalSizeCap>${LOG_TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level> <!-- 设置拦截的对象为INFO级别日志 -->
<onMatch>ACCEPT</onMatch> <!-- 当遇到了DEBUG级别时启用该段配置 -->
<onMismatch>DENY</onMismatch> <!-- 没有遇到DEBUG级别日志时屏蔽该段配置 -->
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${NORMAL_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- ==========================按天输出日志设置========================== -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--设置文件命名格式-->
<FileNamePattern>${LOG_HOME}/${APP_NAME}/info/${POD_NAME}-%d{yyyy-MM-dd}-%i.log</FileNamePattern>
<!--设置日志文件大小超过就重新生成文件默认10M-->
<maxFileSize>${LOG_FILE_MAX_SIZE}</maxFileSize>
<!--日志文件保留天数默认30天-->
<maxHistory>${LOG_FILE_MAX_HISTORY}</maxHistory>
<totalSizeCap>${LOG_TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level> <!-- 设置拦截的对象为INFO级别日志 -->
<onMatch>ACCEPT</onMatch> <!-- 当遇到了INFO级别时启用该段配置 -->
<onMismatch>DENY</onMismatch> <!-- 没有遇到INFO级别日志时屏蔽该段配置 -->
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${NORMAL_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- ==========================按天输出ERROR级别日志设置========================== -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--设置文件命名格式-->
<FileNamePattern>${LOG_HOME}/${APP_NAME}/error/${POD_NAME}-%d{yyyy-MM-dd}-%i.log</FileNamePattern>
<!--设置日志文件大小超过就重新生成文件默认10M-->
<maxFileSize>${LOG_FILE_MAX_SIZE}</maxFileSize>
<!--日志文件保留天数默认30天-->
<maxHistory>${LOG_FILE_MAX_HISTORY}</maxHistory>
<totalSizeCap>${LOG_TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level> <!-- 设置拦截的对象为ERROR级别日志 -->
<onMatch>ACCEPT</onMatch> <!-- 当遇到了ERROR级别时启用该段配置 -->
<onMismatch>DENY</onMismatch> <!-- 没有遇到ERROR级别日志时屏蔽该段配置 -->
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${NORMAL_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!--druid慢查询日志输出没有使用druid监控的去掉这部分以及下面的一个相关logger-->
<appender name="DRUID_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--设置文件命名格式-->
<FileNamePattern>${LOG_HOME}/${APP_NAME}/druid/SlowSql_${POD_NAME}-%d{yyyy-MM-dd}-%i.log</FileNamePattern>
<!--设置日志文件大小超过就重新生成文件默认10M-->
<maxFileSize>${LOG_FILE_MAX_SIZE}</maxFileSize>
<!--日志文件保留天数默认30天-->
<maxHistory>${LOG_FILE_MAX_HISTORY}</maxHistory>
<totalSizeCap>${LOG_TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level> <!-- 设置拦截的对象为ERROR级别日志 -->
<onMatch>ACCEPT</onMatch> <!-- 当遇到了ERROR级别时启用该段配置 -->
<onMismatch>DENY</onMismatch> <!-- 没有遇到ERROR级别日志时屏蔽该段配置 -->
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${NORMAL_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- ===日志输出级别OFF level > FATAL > ERROR > WARN > INFO > DEBUG > ALL level=== -->
<logger name="com.asiainfo" level="INFO"/>
<logger name="org.springframework.boot.web.embedded.tomcat.TomcatWebServer" level="INFO"/>
<logger name="org.springframework" level="WARN"/>
<logger name="com.baomidou.mybatisplus" level="WARN"/>
<logger name="org.apache.kafka.clients.NetworkClient" level="INFO"/>
<logger name="org.apache.kafka.clients.consumer.ConsumerConfig" level="INFO"/>
<!--druid相关logger-->
<logger name="com.alibaba.druid.filter.stat.StatFilter" level="ERROR">
<appender-ref ref="DRUID_FILE"/>
<appender-ref ref="CONSOLE"/>
</logger>
<appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender">
<!--GrayLog服务地址-->
<host>udp:<IP></host>
<!--GrayLog服务端口-->
<port>12201</port>
<version>1.1</version>
<!--当前服务名称-->
<facility>${appName}</facility>
<extractStackTrace>true</extractStackTrace>
<filterStackTrace>true</filterStackTrace>
<mdcProfiling>true</mdcProfiling>
<timestampPattern>yyyy-MM-dd HH:mm:ss,SSS</timestampPattern>
<maximumMessageSize>8192</maximumMessageSize>
</appender>
<!-- ======开发环境:打印控制台和输出到文件====== -->
<springProfile name="dev"><!-- 由application.yml中的spring.profiles.active配置 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="GELF"/>
</root>
</springProfile>
<!-- ======测试环境:打印控制台和输出到文件====== -->
<springProfile name="test"><!-- 由application.yml中的spring.profiles.active配置 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DEBUG_FILE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="GELF"/>
</root>
</springProfile>
<!-- ======生产环境:打印控制台和输出到文件====== -->
<springProfile name="prod"><!-- 由application.yml中的spring.profiles.active配置 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DEBUG_FILE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="GELF"/>
</root>
</springProfile>
</configuration>
```
点击`search`按钮即可看到日志数据:
![image-20240109095535652](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704765336.png)
### 3.日志回收策略
到此graylog的基础配置就算完成了已经可以收到日志数据。
但是在实际工作中,服务日志会非常多,这么多的日志,如果不进行存储限制,那么不久就会占满磁盘,查询变慢等等,而且过久的历史日志对于实际工作中的有效性也会很低。
Graylog则自身集成了日志数据限制的配置可以通过如下进行设置
![image-20240109145002566](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704783002.png)
选择`Default index set`的`Edit`按钮:
![38fba6a5b77842928d69838c6e366c62](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785689.png)
GrayLog有3种日志回收限制触发以后就会开始回收空间删除索引
![2c6218061870d65547522aebf22335e3](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785718.png)
分别是:
- `Index Message Count`:按照日志数量统计,默认超过`20000000`条日志开始清理
- `Index Size`:按照日志大小统计,默认超过`1GB`开始清理
- `Index Message Count`按照日志日期清理默认日志存储1天
### 4.搜索语法
在search页面可以完成基本的日志搜索功能
![c645ec766d0f2eb6109fab1344d04cd1](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785655.png)
```shell
#不指定字段默认从message字段查询
输入undo
#输入两个关键字关系为or
undo 统计
#加引号是需要完整匹配
"undo 统计"
#指定字段查询level表示日志级别ERROR3、WARNING4、NOTICE5、INFO6、DEBUG7
level: 6
#或条件
level:(6 OR 7)
```
更多查询官网文档https://docs.graylog.org/docs/query-language
### 5.自定义展示字段
![bd999948509ec96203230c1a1139ce78](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785625.png)
效果如下:
![image-20240109153728442](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785848.png)
### 6.日志统计仪表盘
GrayLog支持把日志按照自己需要的方式形成统计报表并把许多报表组合一起形成DashBoard仪表盘方便对日志统计分析。
创建仪表盘
![image-20240109153845240](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785925.png)
![9585c83b65fc665c3a9db3055c997c8f](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704788275.png)
![image-20240109153955165](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704785995.png)
在这里创建小组件
![f29f62d315bee87d182a570f408da69c](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704788310.png)
![image-20240109161518566](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704788119.png)
![image-20240109161531180](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704788131.png)
![image-20240109161550617](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704788151.png)
![image-20240109161648891](https://lsky.hhdxw.top/imghub/2024/01/image-202401091704788209.png)

View File

@ -0,0 +1,117 @@
Harbor是一个开源的可信云原生注册表用于存储、签名和扫描内容。它为开源Docker发行版添加了安全、身份和管理等功能。
## 自动安装
```console
curl -LO https://raw.githubusercontent.com/bitnami/containers/main/bitnami/harbor-portal/docker-compose.yml
curl -L https://github.com/bitnami/containers/archive/main.tar.gz | tar xz --strip=2 containers-main/bitnami/harbor-portal && cp -RL harbor-portal/config . && rm -rf harbor-portal
docker-compose up
```
## 手动安装
### 1、下载安装包
```shell
wget https://github.com/goharbor/harbor/releases/download/v2.7.4/harbor-offline-installer-v2.7.4.tgz
```
### 2、解压安装包,进入目录并展示文件
```shell
tar -xvf harbor-offline-installer-v2.7.4.tar
cd harbor
ll
```
![image-20231208150823727](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702019310.png)
### 3、复制harbor.yml配置文件并编辑
```shell
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
```
### 4、编辑文件内容如图
![image-20231208151131781](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702019492.png)
### 5、启动项目
```shell
./install.sh
```
即可看到安装,等待安装完毕即可。
## 简单使用
首先进入页面输入上面设置的密码登录默认访问80端口ip:80
![image-20231208151408705](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702019649.png)
进入页面后新建一个项目例如 `public`
![image-20231208151853837](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702019934.png)
访问级别是公开存储限制为无限镜像代理可以去配置aliyun此代理是用户在harbor仓库中找不到对应镜像然后去代理仓库中查找镜像
![image-20231208152259575](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702020179.png)
打开另外一台服务器,配置`docker`镜像设置
```shell
sudo vim /etc/docker/daemon.json
```
将下面的内容复制进去(`<ip>`更换为上述`Harbor`服务器地址)
```xml
{
"registry-mirrors": [
"https://hub.docker.com",
"http://<ip>:80"
],
"insecure-registries" : [
"<ip>:80"
]
}
```
保存退出,然后重新加载配置启动`docker`
```shell
sudo systemctl daemon-reload
sudo systemctl restart docker
```
在本地镜像(下载了一个`redis`作为演示)打一个标签
```shell
#下载镜像
docker pull redis
#给镜像打标签
# redis:latest 被打标签的本地镜像
# <ip>:80/public/redis:v1新的标签名称
# <ip> 是指定的 IP 地址80 是端口号public/redis:v1 是新的标签。
docker tag redis:latest <ip>:80/public/redis:v1
#登录远程Harbor仓库
docker login -u <username> -p <password> http://<ip>:80
#推送镜像
docker push <ip>:80/public/redis:v1
```
![image-20231208154658318](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702021618.png)
在`Harbor`中就可以看到镜像了
![image-20231208230150057](https://lsky.hhdxw.top/imghub/2023/12/image-202312081702047710.png)

View File

@ -0,0 +1,9 @@
```shell
docker run -p 9000:9000 -p 9090:9090 --name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=minio" \
-e "MINIO_SECRET_KEY=password" \
-v database:/data \
minio/minio server \
/data --console-address ":9090" -address ":9000"
```

View File

@ -0,0 +1,429 @@
![img](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704267879.png)
Nexus 3 是一款由 Sonatype 公司开发的仓库管理工具。它是一个用于存储、发布和管理软件组件的集中式仓库,特别适用于 Java 开发人员。Nexus 3 支持 Maven、Gradle 和其他构建工具,并提供了强大的搜索、版本控制和权限管理功能。使用 Nexus 3 可以帮助团队更好地组织和共享代码库,并提高开发效率。
## 1.Nexus 3 的安装
### 1.docker启动命令
或者可以使用Docker-Compose进行编排
linux x86-64
```shell
docker run -d -p 8081:8081 --name nexus sonatype/nexus3
```
aarch64
```shell
docker run -d -p 8081:8081 -p 8082:8082 -p 8083:8083 --name nexus klo2k/nexus3
```
### 2.访问 Nexus 3
通过访问 http://localhost:8081 进入Nexus 3 的网站
![image-20231227152301705](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703661782.png)
### 3.获取密码并登录
![image-20231227154319306](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703662999.png)
点击页面右上角的"Sign in",按弹窗提示找到默认密码
- 默认账号admin
- 默认密码:容器内的 "/nexus-data/admin.password"
- 会提示重置密码,改个记得住的密码(或者用默认密码),后面配置需要用到
在命令行中使用下面的命令进行获取密码
```shell
docker exec nexus cat /nexus-data/admin.password
```
### 4.修改密码并设置
![image-20231227152749263](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703662069.png)
默认开启匿名访问
![image-20231227152900691](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703662141.png)
这就基本安装完成
![image-20231227154643340](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703663203.png)
## 2.内容介绍
![](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703663203.png)
右侧分为四个一级菜单分别是 `Welcome` `Search` `Browse` `Upload`
- Welcome
- 欢迎界面,展示仓库的数据
- Total components : 总组件数量
- Unique logins : 登录数量30天内
- Peak requests per minute : 每分钟峰值请求24小时内
- Peak requests per day : 每天的峰值请求30天内
![image-20231227172644727](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703669205.png)
- Search
- 用于在所有仓库中,搜索是否存在某个`jar`包(依赖)
- Group组织如果我们想搜索 Spring Framework 的构件,可以使用 group:org.springframework 进行查询。
- Artifact构件如果我们想搜索 Spring Framework 的 web 模块,可以使用 artifact:spring-web 进行查询。
- Version版本如果我们想搜索 Spring Framework 版本为 5.3.10.RELEASE 的构件,可以使用 version:5.3.10.RELEASE 进行查询。另外,如果想模糊匹配多个版本,可以使用通配符 ,例如 version:5.3. 可以匹配到所有 5.3.x 版本。
- Base Version基本版本如果我们想搜索 Spring Framework 的 SNAPSHOT 版本,可以使用 baseVersion:5.3.11-SNAPSHOT 进行查询。这样就可以忽略掉 SNAPSHOT 部分,只匹配基本版本号为 5.3.11 的构件。
- Classifier分类器如果我们想搜索 Spring Framework 的 Windows 版本构件,可以使用 classifier:windows 进行查询。另外,有些 Maven 项目会为不同的环境打包不同的构件,例如 dev、test、prod 等,可以使用 classifier 进行搜索。
- Extension扩展名如果我们只想搜索 jar 文件,可以使用 extension:jar 进行查询。另外,如果我们想搜索所有类型的构件,可以省略该查询条件,默认会搜索所有扩展名的文件。
![](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703669229.png)
- Browse
- 检查该nexus私服拥有多少私有的仓库
- maven-central 是一个代理仓库,它代表了 Maven 中央仓库,它是默认的 Maven 仓库,包含了大量的开源 Java 类库和框架,可以改成国内代理,如阿里云([https://maven.aliyun.com/repository/public](https://maven.aliyun.com/repository/public))
- maven-public 是一个托管的仓库,它允许将自己的库发布到其中,并使其可供其他人使用。
- maven-releases 是一个托管的仓库,用于发布稳定版本的库。
- maven-snapshots 是一个托管的仓库,用于发布开发中或者测试版的库。
![image-20231227172852084](https://lsky.hhdxw.top/imghub/2023/12/image-202312271703669332.png)
- Upload
- 上传 jar 包到私有仓库
- 点击仓库后可以进行上传 jar 包
![image-20240102150816215](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704247153.png)
## 3. Jar包推送仓库
### 1.修改项目pom.xml文件配置
- 直接改造Maven项目或者新建一个Maven项目
- 执行"mvn package"能打包出jar的项目就行
- 如下在pom.xml添加nexus3地址信息
- 与dependencies/build同级
```xml
<dependencies>...略</dependencies>
<build>...略</build>
<distributionManagement>
<repository>
<id>maven-releases</id>
<name>maven-releases</name>
<url>${这里填写从nexus页面上复制的maven-releases的url}</url>
</repository>
<snapshotRepository>
<id>maven-snapshots</id>
<name>maven-snapshots</name>
<url>${这里填写从nexus页面上复制的maven-snapshots的url}</url>
</snapshotRepository>
</distributionManagement>
```
![image-20240103151816700](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266297.png)
- 推送包
- 执行 "mvn deoloy"
- 此时报错 "...status: 401 Unauthorized",说明项目配置正确
### 2.修改Maven软件配置
- 打开 _${maven根目录}/conf/settings.xml_
- 增加nexus账号密码
- id要和在项目pom.xml中配置的一致
```xml
<servers>
<server>
<id>maven-releases</id>
<username>admin</username>
<password>${密码}</password>
</server>
<server>
<id>maven-snapshots</id>
<username>admin</username>
<password>${密码}</password>
</server>
</servers>
```
![image-20240103151929256](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266369.png)
- 再次执行"mvn deploy"就不会报错了
- 刷新nexus页面上可以看到上传的包
- 项目版本不带"-SNAPSHOT"在"maven-releases"目录
- 否则在"maven-releases"目录
### 3.使用deploy推送
![image-20240103152221677](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266542.png)
![image-20240103152112596](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266473.png)
![image-20240103152000386](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266400.png)
## 4. 引用jar包
### 1.修改Maven软件配置
- 打开 _${maven根目录}/conf/settings.xml_
- 启用镜像,如果有其他镜像可以注释掉
- 重启IDEpom.xml中像线上的库一样添加dependency即可使用
```xml
<mirror>
<id>nexus-public</id>
<mirrorOf>*</mirrorOf>
<name>私有仓库</name>
<url>${这里填写从nexus页面上复制的maven-public的url}</url>
</mirror>
```
![image-20240103151929256](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266369.png)
### 2.项目引入jar包
```xml
<dependency>
<groupId>com.example</groupId>
<artifactId>mini-demo</artifactId>
<version>0.0.1-20231206.141630-1</version>
</dependency>
```
- 可以看到没有刷新之前是爆红显示在本地找不到该jar包
![image-20240103152406703](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266647.png)
- 刷新Maven后就可以看到成功引入该jar包
![image-20240103152426226](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704266666.png)
## 5.docker镜像拉取
### 1.创建一个存储库
![image-20240103160627759](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704269188.png)
- 选择如下配置
- Type 选择 File 或者 S3自行配置
- Name 可以自行设置(这里默认 docker
- 然后不选择容量提示,点击确认保存
![image-20240103161409621](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704269650.png)
### 2.创建镜像仓库
![image-20240103162040214](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704270040.png)
- 仓库分三种
- Docker (group) 是指在一个集群环境中使用 Docker。在这种情况下多个 Docker 容器被组织成一个群组,共享资源并通过集中的管理方式进行操作。这使得容器之间可以相互通信和协调,并且可以提供高可用性和负载均衡等功能。
- Docker (hosted) 是指在托管环境中使用 Docker。这意味着 Docker 引擎和容器管理系统(如 Docker Swarm 或 Kubernetes被部署在第三方云服务提供商或托管服务上。这样用户可以将自己的应用程序打包为容器并在托管环境中运行而无需关心底层基础设施的维护和管理。
- Docker (proxy) 是指在 Docker 网络中使用代理服务器。代理服务器充当位于容器和外部网络之间的中间人,转发请求和响应。使用代理服务器可以提供额外的安全性、负载均衡和缓存等功能,并允许容器与外部网络进行通信,同时隔离容器内部网络。
#### 1.创建代理仓库 Docker (proxy)
![image-20240103162218913](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704270139.png)
- Docker仓库配置设置
- Name 仓库名称,命名为 docker-registry-163
- Online 是否接受传入,选择勾选接受传入
- HTTP http连接器配置为 http 使用,不配置
- HTTPS https连接器配置为 https 使用,不配置
- HTTP连接器和HTTPS连接器用于配置Docker仓库使用的协议。HTTP连接器使用HTTP协议而HTTPS连接器使用HTTPS协议。
- Allow anonymous docker pull 允许匿名 docker 拉取,默认开启
- Enable Docker V1 APl 启动 Docker V1 API ,默认开启
- Remote storage 远程存储代理仓库设置为163镜像库其他也可
- Docker Index Docker 索引选择为Docker Hub
- Use the Nexus Repository truststore 使用Nexus存储库信任存储默认不开启
- 默认情况下不开启表示是否使用Nexus存储库的信任存储。开启后Nexus会使用自己的存储库来管理信任证书。
- Foreign Layer Caching 外层缓存,默认不启用
- 外层缓存可以提高Docker镜像的下载速度和性能。
- Maximum component age 最大构建年龄默认1440
- 如果一些镜像或组件已经存在于仓库中超过了这个时间,它们将被自动清理掉以释放空间。
- Maximum metadata age 最大元数据年龄默认1440
- 仓库中存储的元数据metadata的最长保留时间。这些元数据包括标签tag、索引index等信息。
- 限制存储空间:通过设置最大构建年龄和最大元数据年龄,可以控制仓库中存储的镜像和相关组件的数量和大小。当镜像或组件的存在时间超过设定的最大年龄时,它们将被自动清理,从而释放存储空间。
- 管理版本控制Docker 镜像和相关组件可能会随着时间的推移多次更新和构建。通过设置最大构建年龄,您可以确保仓库中只保留最新的镜像和组件,这有助于避免过时的版本占用存储空间。
- 提高性能:仓库中存储的元数据(如标签、索引等)也会随着时间的推移不断增长。通过设置最大元数据年龄,可以定期清理过时的元数据,从而提高仓库的性能和响应速度。
- 维护仓库健康:定期清理过时的镜像、组件和元数据有助于保持仓库的健康状态。它可以防止仓库变得杂乱不堪,减少潜在的错误和故障。
- Blob store 存储库,选择前面设置的 docker
- Not found cache enabled 未找到启用的缓存,默认勾选
- 用于启用或禁用 "Not Found Cache" 功能。当启用此功能时,如果某个请求在仓库中未找到所需的内容(例如镜像或组件),仓库将会缓存这个"未找到"的结果。这样,当后续的请求再次发生时,仓库可以更快地响应,而不必重新执行相同的查询
- Not found cache TTL 未找到缓存TTL默认1440
- 指 "Not Found Cache" 功能中缓存的超时时间。一旦某个未找到的结果被缓存起来,在经过一段时间后(即 TTL 时间)将会自动过期并从缓存中清除。
- Cleanup Policies 清理政策,不做更改
- 用于定义清理操作的策略。它允许您指定仓库中过期或不再需要的镜像、组件或其他资源的自动清理规则。可以根据各种条件(例如最后访问时间、构建日期等)来定义清理政策,以确保仓库保持干净和高效。
![image-20240103162453578](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704270293.png)
![image-20240103162505966](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704270306.png)
#### 2.创建主仓库 Docker (group)
- 配置
- Name 为 docker-registry
- HTTP 对外接口为 8082前面创建时候启用8082端口
- 勾选允许匿名拉取
- 勾选 Docker V1 API
- 存储库设置为 docker
- Member repositories 存储库设置为前面创建的 docker-registry-163
![image-20240103165831888](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704272312.png)
#### 3.启用 Docker
![image-20240103170429111](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704272669.png)
#### 4.对应服务器配置镜像仓库
- ip以及配置
- Nexus 3 安装在了本地电脑的 docker 中本地IP 10.211.55.2
- 目标服务器 CentOS Stream 9 aarch64 IP 10.211.55.40
```sh
vim /etc/docker/daemon.json
```
在文件中写入下面的配置
```json
{
"insecure-registries": [
"10.211.55.2:8082"
],
"registry-mirrors": [
"http://10.211.55.2:8082"
]
}
```
重启 Docker
```sh
systemctl daemon-reload
systemctl restart docker
```
## 6.docker镜像推送
#### 1.nexus 3 配置
创建 docker-private 存储库
![image-20240103231907873](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704295148.png)
- 创建镜像仓库 docker(hosted)
- HTTP 端口 8083
- 开启匿名拉取
- 开启 Docker V1 API 接口
- 存储库 docker-private
![image-20240103232044665](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704295245.png)
docker-registry 仓库中增加存储库 docker-private
![image-20240103232319285](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704295399.png)
- 创建角色
- Role ID 角色ID ,设置为 docker-publish
- Role Name 角色名称,设置为 docker-publish
- Role Description 角色描述,设置为 docker-publish
- Privilegs 权限,设置为 nx-repository-admin-docker-docker-private-*
- nx-repository-admin-docker-docker-private-* 代表Docker 仓库中的私有仓库。这个特权表示被赋予的角色将对私有 Docker 仓库具有管理权限,包括创建、删除、推送和拉取镜像等操作。
- Roles 角色,设置为 nx-admin
![image-20240103232509055](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704295509.png)
![image-20240103232522379](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704295522.png)
- 创建用户
- ID 设置为docker
- Fisrst Name 设置为docker
- Last Name 设置为docker
- Email 设置为docker@gmail
- Password 设置为docker
- status 状态,设置为 Active
- Roles 角色,赋予 docker-publish
![image-20240103233251898](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704295972.png)
#### 2.配置服务器
- ip以及配置
- Nexus 3 安装在了本地电脑的 docker 中本地IP 10.211.55.2
- 目标服务器 CentOS Stream 9 aarch64 IP 10.211.55.40
```sh
vim /etc/docker/daemon.json
```
在文件中写入下面的配置
```json
{
"insecure-registries": [
"10.211.55.2:8082",
"10.211.55.2:8083"
],
"registry-mirrors": [
"http://10.211.55.2:8082"
]
}
```
```sh
//重启 Docker
systemctl daemon-reload
systemctl restart docker
//查看本地镜像
docker images
//打标签
docker tag redis:latest 10.211.55.2:8083/redis:v1.0
//登录仓库
docker login -u docker -p docker 10.211.55.2:8083
//推送打标签的镜像
docker push 10.211.55.2:8083/redis:v1.0
```
![image-20240103234013588](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704296413.png)
在本地仓库就能看到上传的镜像了
![image-20240103234244993](https://lsky.hhdxw.top/imghub/2024/01/image-202401031704296565.png)

View File

@ -26,8 +26,8 @@ docker images
### 4、运行镜像
```she l
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
```shell
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
```
1. `-d` 表示在后台以守护进程的方式运行容器。

View File

@ -18,6 +18,9 @@ docker pull rabbitmq
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq
```
```shell
docker run -d --restart=always -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:3.8-management
```
### 4.安装插件
找到镜像ID
@ -29,7 +32,7 @@ docker ps
进入容器
```shell
docker exec -it 镜像ID /bin/bash
docker exec -it my-rabbit /bin/bash
```
安装插件

View File

@ -0,0 +1,438 @@
## 什么是APM
随着微服务架构的流行,一次请求往往需要涉及到多个服务,因此服务性能监控和排查就变得更复杂
- 不同的服务可能由不同的团队开发、甚至可能使用不同的编程语言来实现
- 服务有可能布在了几千台服务器,横跨多个不同的数据中心
因此就需要一些可以帮助理解系统行为、用于分析性能问题的工具以便发生故障的时候能够快速定位和解决问题这就是APM系统全称是**A**pplication **P**erformance **M**onitor当然也有叫 **A**pplication **P**erformance **M**anagement tools
APM最早是谷歌公开的论文提到的 [Google Dapper](http://bigbully.github.io/Dapper-translation)。Dapper是Google生产环境下的分布式跟踪系统自从Dapper发展成为一流的监控系统之后给google的开发者和运维团队帮了大忙所以谷歌公开论文分享了Dapper。
## 技术选型
市面上的全链路监控理论模型大多都是借鉴Google Dapper论文重点关注以下三种APM组件
- [**Zipkin**](https://link.juejin.im/?target=http%3A%2F%2Fzipkin.io%2F)由Twitter公司开源开放源代码分布式的跟踪系统用于收集服务的定时数据以解决微服务架构中的延迟问题包括数据的收集、存储、查找和展现。
- [**Pinpoint**](https://pinpoint.com/)一款对Java编写的大规模分布式系统的APM工具由韩国人开源的分布式跟踪组件。
- [**Skywalking**](https://skywalking.apache.org/zh/)国产的优秀APM组件是一个对JAVA分布式应用程序集群的业务运行情况进行追踪、告警和分析的系统。现在是Apache的顶级项目之一。
选项就是对比各个系统的使用差异,主要对比项:
1. **探针的性能**
主要是agent对服务的吞吐量、CPU和内存的影响。微服务的规模和动态性使得数据收集的成本大幅度提高。
2. **collector的可扩展性**
能够水平扩展以便支持大规模服务器集群。
3. **全面的调用链路数据分析**
提供代码级别的可见性以便轻松定位失败点和瓶颈。
4. **对于开发透明,容易开关**
添加新功能而无需修改代码,容易启用或者禁用。
5. **完整的调用链应用拓扑**
自动检测应用拓扑,帮助你搞清楚应用的架构
三者对比如下:
| 对比项 | zipkin | pinpoint | skywalking |
| ---------------- | ------ | -------- | ---------- |
| 探针性能 | 中 | 低 | **高** |
| collector扩展性 | **高** | 中 | **高** |
| 调用链路数据分析 | 低 | **高** | 中 |
| 对开发透明性 | 中 | **高** | **高** |
| 调用链应用拓扑 | 中 | **高** | 中 |
| 社区支持 | **高** | 中 | **高** |
综上所述使用skywalking是最佳的选择。
## SkyWalking 是什么
![](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704861050.png)
SkyWalking是一款采用Java语言开发的分布式应用性能监控系统,支持跟踪、监控和诊断分布式系统,特别是以微服务架构和云原生应用为代表的新一代大规模分布式系统,专为微服务、云原生架构和基于容器Docker、K8s、Mesos架构而设计。它提供了实时应用拓扑分析、应用性能指标监控、调用链路追踪、慢服务检测、性能优化建议等功能。
## SkyWalking 功能
- 多种监控手段。可以通过语言探针和 service mesh 获得监控是数据。
- 多个语言自动探针。包括 Java、.NET Core、Node.JS、Go。
- 轻量高效。无需大数据平台,和大量的服务器资源。
- 模块化。UI、存储、集群管理都有多种机制可选。
- 支持告警。
- 优秀的可视化解决方案。
- 开源免费,社区活跃
## 用来解决什么问题
SkyWalking作为新一代APM系统,主要解决了以下几方面的问题:
- 分布式系统监控难题:在复杂的分布式系统中,调用链路蔓延多个服务,难以跟踪。SkyWalking提供了全链路追踪能力,可以清晰还原整个调用流程。
- 应用性能监控不足很多系统对性能指标的监控不够全面和深入。SkyWalking可以从多个维度监控应用性能,找到瓶颈。
- 故障定位时间长:系统发生问题后,通过日志难以定位根因。而SkyWalking的追踪信息可以快速定位故障服务。
- 依赖关系复杂度高微服务系统中间依赖关系错综复杂。SkyWalking提供服务拓扑 map,一目了然。
- 监控成本高许多APM工具需要PAYLOAD接入,增加额外开销。SkyWalking使用无侵入式探针,减少系统侵入。
- 技术栈限制严重旧监控系统只支持少数语言。SkyWalking提供Java、.NET等主流语言的探针。
- 监控视图单一较老的APM系统UI功能简陋。SkyWalking提供丰富的时序图、拓扑图等可视化监控视图。
- 云原生支持不足早期APM系统不支持新型微服务技术栈。SkyWalking在云原生支持上做了大量优化。
总之,SkyWalking作为新一代解决方案,很好地解决了传统APM系统在分布式链路跟踪和应用监控等方面的痛点,值得推荐使用。
## SkyWalking 整体架构
![架构图](https://skywalking.apache.org/zh/2020-04-19-skywalking-quick-start/0081Kckwly1gkl533fk5xj31pc0s8h04.jpg)
- 上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。
- 下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。
- 右部分 Storage Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。
- 左部分 SkyWalking UI :负责提供控台,查看链路等等。
## 简单使用
### 1.安装单机环境
使用 Docker-compose 启动容器,我的服务器有点扛不住所以使用本地虚拟机来运行IP地址为10.211.55.50系统使用的是CentOS Stream 9
```yaml
version: "3"
services:
elasticsearch:
image: elasticsearch:8.4.2
container_name: elasticsearchsky
ports:
- "9200:9200"
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:9200/_cluster/health || exit 1"] #⼼跳检测,成功之后不再执⾏后⾯的退出
interval: 60s #⼼跳检测间隔周期
timeout: 10s
retries: 3
start_period: 60s #⾸次检测延迟时间
environment:
discovery.type: single-node #单节点模式
ingest.geoip.downloader.enabled: "false"
bootstrap.memory_lock: "true"
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
TZ: "Asia/Shanghai"
xpack.security.enabled: "false" #单机模式
ulimits:
memlock:
soft: -1
hard: -1
skywalking-oap:
image: apache/skywalking-oap-server:9.3.0
container_name: skywalking-oap
depends_on:
elasticsearch:
condition: service_healthy
links:
- elasticsearch
environment:
SW_HEALTH_CHECKER: default
SW_STORAGE: elasticsearch
SW_STORAGE_ES_CLUSTER_NODES: 10.211.55.50:9200
JAVA_OPTS: "-Xms2048m -Xmx2048m"
TZ: Asia/Shanghai
SW_TELEMETRY: prometheus
healthcheck:
test: ["CMD-SHELL", "/skywalking/bin/swctl ch"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
restart: on-failure
ports:
- "11800:11800"
- "12800:12800"
skywalking-ui:
image: apache/skywalking-ui:9.3.0
container_name: skywalking-ui
depends_on:
skywalking-oap:
condition: service_healthy
links:
- skywalking-oap
ports:
- "8080:8080"
environment:
SW_OAP_ADDRESS: http://10.211.55.50:12800
SW_HEALTH_CHECKER: default
TZ: Asia/Shanghai
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080 || exit 1"] #⼼跳检测,成功之后不再执⾏后⾯的退出
interval: 60s #⼼跳检测间隔周期
timeout: 10s
retries: 3
start_period: 60s #⾸次检测延迟时间
```
```yaml
version: '3.8'
services:
elasticsearch:
# image: docker.elastic.co/elasticsearch/elasticsearch-oss:${ES_VERSION}
image: elasticsearch:7.9.0
container_name: elasticsearch
# --restart=always 开机启动,失败也会一直重启;
# --restart=on-failure:10 表示最多重启10次
restart: always
ports:
- "9200:9200"
- "9300:9300"
healthcheck:
test: [ "CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1" ]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
environment:
- discovery.type=single-node
# 锁定物理内存地址防止elasticsearch内存被交换出去,也就是避免es使用swap交换分区频繁的交换会导致IOPS变高
- bootstrap.memory_lock=true
# 设置时区
- TZ=Asia/Shanghai
# - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
oap:
image: apache/skywalking-oap-server:8.9.1
container_name: oap
restart: always
# 设置依赖的容器
depends_on:
elasticsearch:
condition: service_healthy
# 关联ES的容器通过容器名字来找到相应容器解决IP变动问题
links:
- elasticsearch
# 端口映射
ports:
- "11800:11800"
- "12800:12800"
# 监控检查
healthcheck:
test: [ "CMD-SHELL", "/skywalking/bin/swctl ch" ]
# 每间隔30秒执行一次
interval: 30s
# 健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败;
timeout: 10s
# 当连续失败指定次数后,则将容器状态视为 unhealthy默认 3 次。
retries: 3
# 应用的启动的初始化时间,在启动过程中的健康检查失效不会计入,默认 0 秒。
start_period: 10s
environment:
# 指定存储方式
SW_STORAGE: elasticsearch
# 指定存储的地址
SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
SW_HEALTH_CHECKER: default
SW_TELEMETRY: prometheus
TZ: Asia/Shanghai
# JAVA_OPTS: "-Xms2048m -Xmx2048m"
ui:
image: apache/skywalking-ui:8.9.1
container_name: skywalking-ui
restart: always
depends_on:
oap:
condition: service_healthy
links:
- oap
ports:
- "8088:8080"
environment:
SW_OAP_ADDRESS: http://oap:12800
TZ: Asia/Shanghai
```
![image-20240110101134534](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704852694.png)
访问 http://10.211.55.50:8080就能看到SkyWalking UI的面板了
![image-20240110103640735](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704854201.png)
### 2.下载 SkyWalking Agent
下载 SkyWalking Agent 地址https://skywalking.apache.org/downloads/
![image-20240110095842377](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704851923.png)
```shell
# 下载完成后解压
tar xvf apache-skywalking-java-agent-9.1.0.tgz
```
![image-20240110101843212](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704853123.png)
### 3.项目引入SkyWalking Agent
![image-20240110102208214](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704853328.png)
在IDEA编辑运行配置增加虚拟机选项如下所示
javaagent上面下载的jar包的路径
Dskywalking.agent.service_name服务组::服务名称
Dskywalking.collector.backend_serviceSkyWalking地址
```shell
-javaagent:/Users/yovinchen/Desktop/project/skywalking-agent/skywalking-agent.jar
-Dskywalking.agent.service_name=ms::xlcs-parent-service-acl
-Dskywalking.collector.backend_service=10.211.55.50:11800
```
然后运行项目就能够在SkyWalking UI中看到服务
![image-20240110103640735](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704854201.png)
## 功能介绍
### 普通服务
#### 服务
##### Service 服务
![image-20240110103640735](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704854201.png)
首页中展示的是现有的服务项
- **Service Groups服务组** 将服务按照某种逻辑分组的方式展示,有助于对大型系统中服务的管理和监控。
- **Service Names服务名称** 表示不同的服务单元或模块的名称,每个服务都会有一个唯一的服务名称用于标识。
- **Load (calls / min)(负载 - 调用次数 / 分钟):** 指每个服务单位时间内的调用次数,反映了服务的负载情况。
- **Success Rate (%)(成功率):** 表示服务成功处理的请求在总请求数中的比率,以百分比形式表示。
- **Latency (ms)(延迟):** 表示服务处理请求所需的时间,通常以毫秒为单位。
- **Apdex应用程序性能指数** 是一种度量应用程序性能的指标,基于用户对延迟的感知。它将用户体验划分为满意、可容忍和不满意三个级别,通过比较满意请求的数量和所有请求的总数,计算出一个衡量应用性能的指数。
##### Topology 拓扑结构
![image-20240110104159073](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704854519.png)
展示的是该项目调用的拓扑结构图,可以清楚的看到各服务之间的调用情况
##### Trace 链路追踪
![image-20240110104657552](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704854818.png)
在这里可以通过查询查看详细程序的调用链路、详细的调用时间、调用的模块、我们可以通过这些信息判断出哪一个服务/SQL查询比较慢进而去优化。
下面是一些不同的展示方式便于分析问题
![image-20240110105041733](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855042.png)
![image-20240110105052331](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855052.png)
![image-20240110105102508](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855063.png)
##### Log 日志
![image-20240110105137090](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855097.png)
#### 虚拟数据库
SkyWalking 可以通过分析项目中的调用情况推断出相应的数据库
![image-20240110105548556](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855349.png)
- **Service Names服务名称** 在虚拟数据库中,可能指代不同数据库或数据库集群的特定名称,用于标识和区分各个数据库服务单元。
- **Latency (ms)(延迟):** 表示在处理请求时所需的时间,以毫秒为单位。对于数据库而言,延迟可能表示执行查询、读取或写入数据所需的时间。
- **Successful Rate (%)(成功率):** 表示成功执行的请求在总请求数中的比率,用百分比表示。对于数据库,可能表示成功完成查询或事务的比率。
- **Traffic (calls / min)(流量 - 调用次数 / 分钟):** 指代在一分钟内数据库所收到的请求或调用次数。这可能包括查询、写入或其他与数据库相关的操作。
#### 虚拟缓存
SkyWalking 可以通过分析项目中的调用情况推断出相应的缓存
![image-20240110105603828](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855364.png)
- **Service Names服务名称** 在虚拟缓存中,这可能是不同缓存服务或缓存集群的特定名称,用于标识和区分各个缓存服务单元。
- **Access Latency (ms)(访问延迟):** 表示从缓存中获取数据所需的时间,通常以毫秒为单位。这是指从发出请求到获得所需数据的时间。
- **Successful Access Rate (%)(成功访问率):** 表示从缓存成功获取数据的请求在总请求数中的比率,以百分比表示。对于缓存而言,这代表着有效利用缓存的程度。
- **Access Traffic (calls / min)(访问流量 - 调用次数 / 分钟):** 表示在一分钟内针对缓存的访问请求次数。这可能包括读取、写入或其他缓存操作的总次数。
#### 虚拟消息队列
SkyWalking 可以通过分析项目中的调用情况推断出相应的消息队列
![image-20240110105618984](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704855379.png)
- **Service Names服务名称** 这指代不同的服务单元或者模块的名称,每个服务可能是消息队列的一个实例,消费者、生产者或者其他与消息传递相关的组件。
- **Transmission Latency (ms)(传输延迟):** 表示消息从生产者发送到消费者接收所需的时间。这个指标衡量了消息在系统中传输的速度,通常以毫秒为单位。
- **Consume Successful Rate (%)(消费成功率):** 表示消费者成功接收并处理消息的比率,即成功消费的消息数量占总消息量的百分比。
- **Consume Traffic (calls / min)(消费流量 - 调用次数 / 分钟):** 表示消费者消费消息的频率,即消费者在一分钟内处理的消息数量。
- **Produce Successful Rate (%)(生产成功率):** 表示生产者成功将消息发送到消息队列或者系统中的比率,即成功发送的消息数量占总发送消息量的百分比。
- **Produce Traffic (calls / min)(生产流量 - 调用次数 / 分钟):** 表示生产者向消息队列或者系统发送消息的频率,即在一分钟内发送的消息数量。
### 基础设施
#### linux
SkyWalking 可以实现监控 Linux 系统情况
![image-20240111111955577](https://lsky.hhdxw.top/imghub/2024/01/image-202401111704943196.png)
Linux服务器接入SkyWalking需要两个工具:
node_exporter pentelemetry-collector
https://github.com/prometheus/node_exporter/releases
```shell
wget -i https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-arm64.tar.gz
```
通过命令解压
```shell
tar -xvf node_exporter-1.7.0.linux-arm64.tar.gz
```
创建一个系统服务,让node_exporter能够开机自启并通过系统管控
```shell
vim /etc/systemd/system/node_exporter.service
```
```yaml
[Unit]
Description=node exporter service
Documentation=https://prometheus.io
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/root/node_exporter-1.7.0.linux-arm64/node_exporter #这里是node_exporter的解压地址
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
执行命令刷新系统服务
```
systemctl daemon-reload
```
开启node_exporter服务
```
systemctl start node_exporter
```
这里服务默认监听9100端口,请勿占用,就完成了node_exporter的安装

View File

@ -0,0 +1,36 @@
先更新源,并且安装必要的依赖软件
```shell
sudo apt update
sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
```
导入源仓库的 GPG key
```shell
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```
添加 Docker APT 软件源
```shell
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
```
安装 Docker 最新版本
```shell
sudo apt install docker-ce docker-ce-cli containerd.io
```
至此安装完成。
输入命令验证是否安装成功查看是否显示Docker版本号。
```shell
docker version
```
```shell
sudo apt-get update
sudo apt install docker-compose-plugin
```

View File

@ -0,0 +1 @@
yufei83721@gmail.com

View File

@ -0,0 +1,22 @@
```
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms512m -Xmx512m" \
-d elasticsearch:7.8.0
```
```
docker exec -it elasticsearch /bin/bash
```
```
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.5/elasticsearch-analysis-ik-7.17.5.zip
```
```
docker restart elasticsearch
```
```
docker run -d --name kibana --link elasticsearch:elasticsearch -p 5601:5601 kibana:7.8.0
```

View File

@ -0,0 +1,99 @@
version: "3"
networks:
dronenet:
services:
server:
image: gitea/gitea:1.20.5
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- dronenet
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "2222:22"
- "10800:3000"
drone-server:
image: drone/drone:latest
container_name: drone-server
ports:
- "1380:80"
- "8000:8000"
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dnmp/drone/:/var/lib/drone/:rw
restart: always
environment:
- DRONE_GITEA_SERVER=http://10.211.55.12:10800
- DRONE_DEBUG=true
- DRONE_GIT_ALWAYS_AUTH=false
- DRONE_GITEA_CLIENT_ID=30503c87-93d0-4678-81d0-d8ea2aef8f25
- DRONE_GITEA_CLIENT_SECRET=gto_hdtxrgkyhpuzsggn5xeoujnub7q4hdsbafd56zl23rx2ppknxska
- DRONE_RUNNER_CAPACITY=2
- DRONE_SERVER_HOST=10.211.55.12
- DRONE_SERVER_PROTO=http
- DRONE_RPC_SECRET=9c3921e3e748aff725d2e16ef31fbc42
- DRONE_TLS_AUTOCERT=false
- DRONE_USER_CREATE=username:yovinchen,admin:true
- TZ=Asia/Shanghai
networks:
- dronenet
drone-agent:
image: drone/agent:latest
container_name: drone-agent
command: agent
restart: always
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_SERVER=http://10.211.55.12:9000
- DRONE_RPC_SECRET=9c3921e3e748aff725d2e16ef31fbc42
- DRONE_DEBUG=true
- DRONE_LOGS_DEBUG=true
- DRONE_LOGS_PRETTY=true
- DRONE_LOGS_NOCOLOR=false
- TZ=Asia/Shanghai
networks:
- dronenet
docker pull drone/drone:2
docker stop drone
docker rm drone
docker run -d --name=drone \
--env=DRONE_GITEA_SERVER=http://10.211.55.12:10800 \
--env=DRONE_GITEA_CLIENT_ID=52c774fd-f670-400f-9e7b-8bcd68cfa75a \
--env=DRONE_GITEA_CLIENT_SECRET=gto_ozlilshmhxn2atjz5po2gn6tickcwijt4hleobwnqhhbh5vxovva \
--env=DRONE_RPC_SECRET=aaf5eab277a8d9236d822025aeaa4530 \
--env=DRONE_SERVER_HOST=10.211.55.12:1080 \
--env=DRONE_SERVER_PROTO=http \
--publish=1080:80 \
--publish=4443:443 \
--restart=always \
--detach=true \
drone/drone:2
docker pull drone/drone-runner-docker:1
docker stop drone-runner
docker rm drone-runner
docker run -d --name=drone-runner \
--link drone:drone \
-p 9030:3000 \
--env=DRONE_RPC_PROTO=http \
--env=DRONE_RPC_HOST=10.211.55.12:1080 \
--env=DRONE_RPC_SECRET=aaf5eab277a8d9236d822025aeaa4530 \
--env=DRONE_RUNNER_CAPACITY=2 \
--env=DRONE_RUNNER_NAME=my-first-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
drone/drone-runner-docker:1

View File

@ -0,0 +1,15 @@
```
docker run -d -uroot -p 9095:8080 -p 50000:50000 --name jenkins -v /home/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime jenkins/jenkins
```
```
docker run \
-u root \
--rm \
-d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkinsci/blueocean
```

View File

@ -0,0 +1,8 @@
```
docker run -d --name nacos-server -p 8848:8848 -p 9848:9848 \
-e MODE=standalone \
-e JVM_XMS=512m \
-e JVM_XMX=512m \
-v /logs/nacos:/home/nacos/logs \
nacos/nacos-server:v2.2.3
```

View File

@ -0,0 +1,209 @@
## MinIO是什么
![](https://lsky.hhdxw.top/imghub/2024/01/image-202401101704861743.png)
官方解释MinIO 是一个基于Apache License v2.0开源协议的[对象存储](https://cloud.tencent.com/product/cos?from_column=20065&from=20065)服务。它兼容亚马逊S3云存储服务接口非常适合于存储大容量非结构化的数据例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等而一个对象文件可以是任意大小从几kb到最大5T不等。
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
## MinIO有哪些优势
### 1. 开发文档全面
MinIO作为一款基于Golang 编程语言开发的一款高性能的分布式式存储方案的开源项目,有十分完善的官方文档。。
官网文档地址https://docs.min.io/cn/
### 2.高性能
MinIO号称是目前速度最快的对象存储服务器。在标准硬件上对象存储的读/写速度最高可以高达183 GB/s和171 GB/s。对象存储可以作为主存储层用来处理Spark、Presto、TensorFlow、H2O.ai等各种复杂工作负载以及成为Hadoop HDFS的替代品。
MinIO用作云原生应用程序的主要存储和传统对象存储相比云原生应用程序需要更高的吞吐量和更低的延迟。而这些都是MinIO能够达成的性能指标。
### 3.容器化集成方便
MinIO提供了与k8s、etcd、docker等主流容器化技术深度集成方案。
## 安装MinIo服务
想要安装Minio有两种方案第一种是直接在服务器上安装还有一种是使用Docker快速部署。
官方文档https://www.minio.org.cn/docs/cn/minio
### 直接安装
安装包下载页面https://dl.min.io/server/minio/release/我们需要选择好对应架构和系统的安装包比如Ubuntu/Debian系统下我们可以像这样安装
```sh
wget https://dl.min.io/server/minio/release/linux-amd64/minio_20230831153116.0.0_amd64.deb -O minio.deb
sudo dpkg -i minio.deb
```
在CentOS/Redhat(RHEL)系统下,可以像这样安装:
```sh
wget https://dl.min.io/server/minio/release/linux-amd64/minio-20230831153116.0.0.x86_64.rpm -O minio.rpm
sudo dnf install minio.rpm
```
安装完成后我们需要创建一个用于存放minio文件数据的目录
```sh
sudo mkdir /mnt/minio
```
然后创建一个minio使用的用户并为此用户分配对应目录的访问权限
```sh
groupadd -r minio-user
useradd -M -r -g minio-user minio-user
chown minio-user:minio-user /mnt/minio
```
接着我们需要创建Minio的配置文件
```sh
sudo vim /etc/default/minio
```
编写以下内容到配置文件中:
```properties
#系统管理员账号和密码
MINIO_ROOT_USER=minio
MINIO_ROOT_PASSWORD=password
#设置用于存储数据的目录
MINIO_VOLUMES="/mnt/minio"
#项目接口访问地址
MINIO_SERVER_URL="http://0.0.0.0:9000"
#配置其他选项,比如后台管理系统的地址
MINIO_OPTS="--console-address 0.0.0.0:9090"
```
配置完成之后就可以启动Minio服务了
```sh
sudo systemctl enable minio.service
sudo systemctl start minio.service
```
### 使用Docker安装
对于各位小伙伴本地开发测试这里更推荐使用Docker镜像安装非常简单快捷本地安装好Docker客户端之后只需要执行以下命令就能快速部署
```sh
docker run -p 9000:9000 -p 9090:9090 --name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=minio" \
-e "MINIO_SECRET_KEY=password" \
-v database:/data \
minio/minio server \
/data --console-address ":9090" -address ":9000"
```
非常方便快捷。
------
## 使用Java操作对象存储
前面我们搭建好了对象存储服务,接着就可以开始愉快地使用了。
### 基本使用
Minio已经为我们提供了封装好的依赖我们只需要直接使用即可
```xml
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.3.9</version>
</dependency>
```
接着我们需要创建一个Minio客户端用于访问对象存储服务器
```java
MinioClient client = MinioClient.builder()
.endpoint("http://localhost:9000") //对象存储服务地址注意是9000那个端口
.credentials("minio", "password") //账户直接使用管理员
.build();
```
对于Java的相关操作可以说非常全面包含对桶的操作、对象操作等等文档地址https://www.minio.org.cn/docs/cn/minio/linux/developers/java/API.html这里我们先演示一下文件上传
```java
//首先找到我们需要上传的文件
File file = new File("/Users/nagocoler/Downloads/test.jpg");
//构造一个输入流用于文件传输
FileInputStream stream = new FileInputStream(file);
//填写上传的相关参数使用PutObjectArgs的Builder来完成
PutObjectArgs put = PutObjectArgs.builder()
.bucket("test") //设置需要上传的桶名称
.object("666.jpg") //设置上传后保存的文件名称
.stream(stream, file.length(), -1) //配置流以及大小还有分片大小
.build();
client.putObject(put); //使用putObject方法完成上传操作
```
这样就可以将文件上传到对象存储服务器中了。
接着是下载文件:
```java
//填写下载相关的参数使用GetObjectArgs来完成
GetObjectArgs get = GetObjectArgs.builder()
.bucket("test") //设置需要下载的桶名称
.object("666.jpg") //设置下载后保存的文件名称
.build();
GetObjectResponse response = client.getObject(get);
//使用输出流保存下载的文件到本地
FileOutputStream stream = new FileOutputStream("/Users/nagocoler/Downloads/download.png");
stream.write(response.readAllBytes());
stream.close();
```
最后是删除桶里的文件:
```java
RemoveObjectArgs remove = RemoveObjectArgs.builder()
.bucket("test") //设置需要删除文件的桶名称
.object("666.jpg") //设置删除的文件名称
.build();
client.removeObject(remove); //删就完事
```
### 服务器文件上传和下载
实例代码:
```java
@RestController
@RequestMapping("/")
public class FileController {
@Resource
MinioClient client;
@PostMapping("upload")
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
InputStream stream = file.getInputStream();
String name = UUID.randomUUID().toString();
PutObjectArgs args = PutObjectArgs.builder()
.bucket("test")
.object("upload/"+name)
.stream(stream, file.getSize(), -1)
.build();
client.putObject(args);
return name;
}
@GetMapping("file/{name}")
public void file(@PathVariable("name") String name,
HttpServletResponse response) throws Exception{
GetObjectResponse object = client.getObject(GetObjectArgs.builder().bucket("test").object("upload/"+name).build());
ServletOutputStream stream = response.getOutputStream();
stream.write(object.readAllBytes());
}
}
```

View File

@ -1 +0,0 @@
{}

92
杂记/typora快捷键.md Normal file
View File

@ -0,0 +1,92 @@
[TOC]
## 摘要
您可以使用快捷键快速插入或修改样式或者执行Typora支持的其他操作。 您可以在菜单栏中的每个菜单项的右侧找到快捷键。
### 自动完成
在macOS上您可以`Esc`按键打开内联数学预览功能,自动完成表情符号等操作。
| 功能 | 热键Windows / Linux | 热键macOS |
| ------------------ | ----------------------- | ------------------- |
| 新建 | Ctrl + N | Command + N |
| 打开在新窗户 | Ctrl + Shift + N | Command + Shift + N |
| 新建标签 | *(不支持)* | Command + T |
| 打开 | Ctrl + O | Command + O |
| 快速打开 | Ctrl + P | Command + Shift + O |
| 重新打开关闭的文件 | Ctrl + Shift + T | Command + Shift + T |
| 保存 | Ctrl + S | Command + S |
| 另存为/重复 | Ctrl + Shift + S | Command + Shift + S |
### 编辑
| 功能 | 热键Windows / Linux | 热键macOS |
| --------------------------------- | -------------------------- | ----------------------------------- |
| 新段落 | Shift + Enter | Shift + Enter |
| 剪切 | Ctrl + X | Command + X |
| 复制 | Ctrl + C | Command + C |
| 粘贴 | Ctrl + V | Command + V |
| 复制 | Ctrl + Shift + C | Command + Shift + C |
| 粘贴为纯文本 | Ctrl + Shift + V | Command + Shift + V |
| 全选 | Ctrl + A | Command + A |
| 选择行/句子 选择行(在表中) | Ctrl + L | Command + L |
| 删除行(在表中) | Ctrl + Shift +delete | Command + Shift +delete |
| 选择样式范围 选择单元格(在表中) | Ctrl + E | Command + E |
| 选择单词 | Ctrl + D | Command + D |
| 删除单词 | Ctrl + Shift + D | Command + Shift + D |
| 跳到顶部 | Ctrl +主页 | Command +↑ |
| 跳转到选择 | Ctrl + J | Command + J |
| 跳到Buttom | Ctrl +结束 | Command+↓ |
| 查找 | Ctrl + F | Command + F |
| 查找下一个 | F3 / Enter | Command + G / Enter |
| 查找上一个 | Shift + F3 / Shift + Enter | Command + Shift + G / Shift + Enter |
### 段
| 功能 | 热键Windows / Linux | 热键macOS |
| ------------ | ----------------------- | -------------------- |
| 标题1至6 | Ctrl + 1/2/3/4/5/6 | 指令+ 1/2/3/4/5/6 |
| 段 | Ctrl + 0 | Command + 0 |
| 增加标题级别 | Ctrl + = | Command+ = |
| 降低标题级别 | Ctrl + - | Command+ - |
| 表格 | Ctrl + T | Command + Option + T |
| 代码块 | Ctrl + Shift + K | Command + Option + C |
| 数学块 | Ctrl + Shift + M | Command + Option + B |
| 引用 | Ctrl + Shift + Q | Command + Option + Q |
| 有序列表 | Ctrl + Shift + [ | Command + Option + O |
| 无序列表 | Ctrl + Shift +] | Command + Option + U |
| 缩进 | Ctrl + [ / Tab | Command + [ / Tab |
### 格式
| 功能 | 热键Windows / Linux | 热键macOS |
| -------- | ----------------------- | --------------------- |
| 加粗 | Ctrl + B | Command + B |
| 斜体 | Ctrl + I | Command + I |
| 下划线 | Ctrl + U | Command + U |
| 代码 | Ctrl + Shift +` |Command + Shift + `|
| Strike | Alt + Shift + 5 | Ctrl + Shift +` |
| 超链接 | Ctrl + K | Command + K |
| 图片 | Ctrl + Shift + I | Command + Control + I |
| 清除格式 | Ctrl + \ | Command+ \ |
### 视图
| 功能 | 热键Windows / Linux | 热键macOS |
| -------------------- | ----------------------- | --------------------- |
| 切换边栏 | Ctrl + Shift + L | Command + Shift + L |
| 大纲 | Ctrl + Shift + 1 | Command + Control+ 1 |
| 文章 | Ctrl + Shift + 2 | Command + Control + 2 |
| 文件树 | Ctrl + Shift + 3 | Command + Control + 3 |
| 源代码模式 | Ctrl + / | Command + / |
| 对焦模式 | F8 | F8 |
| 打字机模式 | F9 | F9 |
| 切换全屏 | F11 | Command + Option + F |
| 真实大小 | Ctrl + Shift + 0 | *(不支持)* |
| 放大 | Ctrl + Shift + = | *(不支持)* |
| 缩小 | Ctrl + Shift +- | *(不支持)* |
| 在打开的文档之间切换 | Ctrl + Tab | Command +` |
| 切换DevTools | Ctrl + Shift + I | -- |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,169 @@
### MySQL面试题-文稿
>**面试官:**MySQL中如何定位慢查询?
>
>**候选人:**
>
>嗯~我们当时做压测的时候有的接口非常的慢接口的响应时间超过了2秒以上因为我们当时的系统部署了运维的监控系统Skywalking 在展示的报表中可以看到是哪一个接口比较慢并且可以分析这个接口哪部分比较慢这里可以看到SQL的具体的执行时间所以可以定位是哪个sql出了问题
>
>如果项目中没有这种运维的监控系统其实在MySQL中也提供了慢日志查询的功能可以在MySQL的系统配置文件中开启这个慢日志的功能并且也可以设置SQL执行超过多少时间来记录到一个日志文件中我记得上一个项目配置的是2秒只要SQL执行的时间超过了2秒就会记录到日志文件中我们就可以在日志文件找到执行比较慢的SQL了。
>
>**面试官:**那这个SQL语句执行很慢, 如何分析呢?
>
>**候选人:**如果一条sql执行很慢的话我们通常会使用mysql自动的执行计划explain来去查看这条sql的执行情况比如在这里面可以通过key和key_len检查是否命中了索引如果本身已经添加了索引也可以判断索引是否有失效的情况第二个可以通过type字段查看sql是否有进一步的优化空间是否存在全索引扫描或全盘扫描第三个可以通过extra建议来判断是否出现了回表的情况如果出现了可以尝试添加索引或修改返回字段来修复
>
>**面试官:**了解过索引吗?(什么是索引)
>
>**候选人:**嗯索引在项目中还是比较常见的它是帮助MySQL高效获取数据的数据结构主要是用来提高数据检索的效率降低数据库的IO成本同时通过索引列对数据进行排序降低数据排序的成本也能降低了CPU的消耗
>
>**面试官:**索引的底层数据结构了解过嘛 ?
>
>**候选人:**MySQL的默认的存储引擎InnoDB采用的B+树的数据结构来存储索引选择B+树的主要的原因是第一阶数更多路径更短第二个磁盘读写代价B+树更低非叶子节点只存储指针叶子阶段存储数据第三是B+树便于扫库和区间查询,叶子节点是一个双向链表
>
>**面试官:**B树和B+树的区别是什么呢?
>
>**候选人**第一在B树中非叶子节点和叶子节点都会存放数据而B+树的所有的数据都会出现在叶子节点在查询的时候B+树查找效率更加稳定
>
>第二在进行范围查询的时候B+树效率更高因为B+树都在叶子节点存储,并且叶子节点是一个双向链表
>
>**面试官:**什么是聚簇索引什么是非聚簇索引 ?
>
>**候选人:**
>
>好的~聚簇索引主要是指数据与索引放到一块B+树的叶子节点保存了整行数据,有且只有一个,一般情况下主键在作为聚簇索引的
>
>非聚簇索引值的是数据与索引分开存储B+树的叶子节点保存对应的主键,可以有多个,一般我们自己定义的索引都是非聚簇索引
>
>**面试官:**知道什么是回表查询嘛 ?
>
>**候选人:**嗯,其实跟刚才介绍的聚簇索引和非聚簇索引是有关系的,回表的意思就是通过二级索引找到对应的主键值,然后再通过主键值找到聚集索引中所对应的整行数据,这个过程就是回表
>
>【**备注**:如果面试官直接问回表,则需要先介绍聚簇索引和非聚簇索引】
>
>**面试官:**知道什么叫覆盖索引嘛 ?
>
>**候选人:**嗯~,清楚的
>
>覆盖索引是指select查询语句使用了索引在返回的列必须在索引中全部能够找到如果我们使用id查询它会直接走聚集索引查询一次索引扫描直接返回数据性能高。
>
>如果按照二级索引查询数据的时候返回的列中没有创建索引有可能会触发回表查询尽量避免使用select *,尽量在返回的列中都包含添加索引的字段
>
>**面试官:**MYSQL超大分页怎么处理 ?
>
>**候选人:**嗯超大分页一般都是在数据量比较大时我们使用了limit分页查询并且需要对数据进行排序这个时候效率就很低我们可以采用覆盖索引和子查询来解决
>
>先分页查询数据的id字段确定了id之后再用子查询来过滤只查询这个id列表中的数据就可以了
>
>因为查询id的时候走的覆盖索引所以效率可以提升很多
>
>**面试官:**索引创建原则有哪些?
>
>**候选人:**嗯这个情况有很多不过都有一个大前提就是表中的数据要超过10万以上我们才会创建索引并且添加索引的字段是查询比较频繁的字段一般也是像作为查询条件排序字段或分组的字段这些。
>
>还有就是我们通常创建索引的时候都是使用复合索引来创建一条sql的返回值尽量使用覆盖索引如果字段的区分度不高的话我们也会把它放在组合索引后面的字段。
>
>如果某一个字段的内容较长,我们会考虑使用前缀索引来使用,当然并不是所有的字段都要添加索引,这个索引的数量也要控制,因为添加索引也会导致新增改的速度变慢。
>
>**面试官:**什么情况下索引会失效 ?
>
>**候选人:**嗯,这个情况比较多,我说一些自己的经验,以前遇到过的
>
>比如,索引在使用的时候没有遵循最左匹配法则,第二个是,模糊查询,如果%号在前面也会导致索引失效。如果在添加索引的字段上进行了运算操作或者类型转换也都会导致索引失效。
>
>我们之前还遇到过一个就是,如果使用了复合索引,中间使用了范围查询,右边的条件索引也会失效
>
>所以通常情况下想要判断出这条sql是否有索引失效的情况可以使用explain执行计划来分析
>
>**面试官:**sql的优化的经验
>
>**候选人:**嗯这个在项目还是挺常见的当然如果直说sql优化的话我们会从这几方面考虑比如
>
>建表的时候、使用索引、sql语句的编写、主从复制读写分离还有一个是如果量比较大的话可以考虑分库分表
>
>**面试官:**创建表的时候,你们是如何优化的呢?
>
>**候选人:**这个我们主要参考的阿里出的那个开发手册《嵩山版》就比如在定义字段的时候需要结合字段的内容来选择合适的类型如果是数值的话像tinyint、int 、bigint这些类型要根据实际情况选择。如果是字符串类型也是结合存储的内容来选择char和varchar或者text类型
>
>**面试官:**那在使用索引的时候,是如何优化呢?
>
>**候选人:**【参考索引创建原则 进行描述】
>
>**面试官:**你平时对sql语句做了哪些优化呢
>
>**候选人:**嗯这个也有很多比如SELECT语句务必指明字段名称不要直接使用select * 还有就是要注意SQL语句避免造成索引失效的写法如果是聚合查询尽量用union all代替union union会多一次过滤效率比较低如果是表关联的话尽量使用innerjoin 不要使用用left join right join如必须使用 一定要以小表为驱动
>
>**面试官:**事务的特性是什么?可以详细说一下吗?
>
>**候选人:**嗯这个比较清楚ACID分别指的是原子性、一致性、隔离性、持久性我举个例子
>
>A向B转账500转账成功A扣除500元B增加500元原子操作体现在要么都成功要么都失败
>
>在转账的过程中数据要一致A扣除了500B必须增加500
>
>在转账的过程中隔离性体现在A像B转账不能受其他事务干扰
>
>在转账的过程中,持久性体现在事务提交后,要把数据持久化(可以说是落盘操作)
>
>**面试官**:并发事务带来哪些问题?
>
>**候选人**
>
>我们在项目开发中,多个事务并发进行是经常发生的,并发也是必然的,有可能导致一些问题
>
>第一是脏读, 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
>
>第二是不可重复读:比如在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
>
>第三是幻读Phantom read幻读与不可重复读类似。它发生在一个事务T1读取了几行数据接着另一个并发事务T2插入了一些数据时。在随后的查询中第一个事务T1就会发现多了一些原本不存在的记录就好像发生了幻觉一样所以称为幻读。
>
>**面试官**怎么解决这些问题呢MySQL的默认隔离级别是
>
>**候选人**:解决方案是对事务进行隔离
>
>MySQL支持四种隔离级别分别有
>
>第一个是未提交读read uncommitted它解决不了刚才提出的所有问题一般项目中也不用这个。第二个是读已提交read committed它能解决脏读的问题的但是解决不了不可重复读和幻读。第三个是可重复读repeatable read它能解决脏读和不可重复读但是解决不了幻读这个也是mysql默认的隔离级别。第四个是串行化serializable它可以解决刚才提出来的所有问题但是由于让是事务串行执行的性能比较低。所以我们一般使用的都是mysql默认的隔离级别:可重复读
>
>**面试官**undo log和redo log的区别
>
>**候选人**好的其中redo log日志记录的是数据页的物理变化服务宕机可用来同步数据而undo log 不同它主要记录的是逻辑日志当事务回滚时通过逆操作恢复原来的数据比如我们删除一条数据的时候就会在undo log日志文件中新增一条delete语句如果发生回滚就执行逆操作
>
>redo log保证了事务的持久性undo log保证了事务的原子性和一致性
>
>**面试官**:事务中的隔离性是如何保证的呢?(你解释一下MVCC)
>
>**候选人**事务的隔离性是由锁和mvcc实现的。
>
>其中mvcc的意思是多版本并发控制。指维护一个数据的多个版本使得读写操作没有冲突它的底层实现主要是分为了三个部分第一个是隐藏字段第二个是undo log日志第三个是readView读视图
>
>隐藏字段是指在mysql中给每个表都设置了隐藏字段有一个是trx_id(事务id)记录每一次操作的事务id是自增的另一个字段是roll_pointer(回滚指针),指向上一个版本的事务版本记录地址
>
>undo log主要的作用是记录回滚日志存储老版本数据在内部会形成一个版本链在多个事务并行操作某一行记录记录不同事务修改数据的版本通过roll_pointer指针形成一个链表
>
>readView解决的是一个事务查询选择版本的问题在内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据不同的隔离级别快照读是不一样的最终的访问的结果不一样。如果是rc隔离级别每一次执行快照读时生成ReadView如果是rr隔离级别仅在事务中第一次执行快照读时生成ReadView后续复用
>
>**面试官**MySQL主从同步原理
>
>**候选人**MySQL主从复制的核心就是二进制日志(DDL数据定义语言语句和 DML数据操纵语言语句),它的步骤是这样的:
>
>第一:主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。
>
>第二:从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志 Relay Log 。
>
>第三:从库重做中继日志中的事件,将改变反映它自己的数据
>
>**面试官**你们项目用过MySQL的分库分表吗
>
>**候选人**
>
>嗯,因为我们都是微服务开发,每个微服务对应了一个数据库,是根据业务进行拆分的,这个其实就是垂直拆分。
>
>**面试官**:那你之前使用过水平分库吗?
>
>**候选人**
>
>嗯,这个是使用过的,我们当时的业务是(xxx),一开始,我们也是单库,后来这个业务逐渐发展,业务量上来的很迅速,其中(xx)表已经存放了超过1000万的数据我们做了很多优化也不好使性能依然很慢所以当时就使用了水平分库。
>
>我们一开始先做了3台服务器对应了3个数据库由于库多了需要分片我们当时采用的mycat来作为数据库的中间件。数据都是按照id自增取模的方式来存取的。
>
>当然一开始的时候那些旧数据我们做了一些清洗的工作我们也是按照id取模规则分别存储到了各个数据库中好处就是可以让各个数据库分摊存储和读取的压力解决了我们当时性能的问题

View File

@ -0,0 +1,278 @@
# Redis相关面试题
>**面试官**:什么是缓存穿透 ? 怎么解决 ?
>
>**候选人**
>
>嗯~~,我想一下
>
>缓存穿透是指查询一个一定**不存在**的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。这种情况大概率是遭到了攻击。
>
>解决方案的话,我们通常都会用布隆过滤器来解决它
>**面试官**:好的,你能介绍一下布隆过滤器吗?
>
>**候选人**
>
>嗯,是这样~
>
>布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是redisson实现的布隆过滤器。
>
>它的底层主要是先去初始化一个比较大数组里面存放的二进制0或1。在一开始都是0当一个key来了之后经过3次hash计算模于数组长度找到数据的下标然后把数组中原来的0改为1这样的话三个数组的位置就能标明一个key的存在。查找的过程也是一样的。
>
>当然是有缺点的布隆过滤器有可能会产生一定的误判我们一般可以设置这个误判率大概不会超过5%其实这个误判是必然存在的要不就得增加数组的长度其实已经算是很划分了5%以内的误判率一般的项目也能接受,不至于高并发下压倒数据库。
>
>
>**面试官**:什么是缓存击穿 ? 怎么解决 ?
>
>**候选人**
>
>嗯!!
>
>缓存击穿的意思是对于设置了过期时间的key缓存在某个时间点过期的时候恰好这时间点对这个Key有大量的并发请求过来这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。
>
>解决方案有两种方式:
>
>第一可以使用互斥锁当缓存失效时不立即去load db先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db的操作并回设缓存否则重试get缓存的方法
>
>第二种方案可以设置当前key逻辑过期大概是思路如下
>
>①在设置key的时候设置一个过期时间字段一块存入缓存中不给当前key设置过期时间
>
>②当查询的时候从redis取出数据后判断时间是否过期
>
>③:如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新
>
>当然两种方案各有利弊:
>
>如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等,也有可能产生死锁的问题
>
>如果选择key的逻辑删除则优先考虑的高可用性性能比较高但是数据同步这块做不到强一致。
>**面试官**:什么是缓存雪崩 ? 怎么解决 ?
>
>**候选人**
>
>嗯!!
>
>缓存雪崩意思是设置缓存时采用了相同的过期时间导致缓存在某一时刻同时失效请求全部转发到DBDB 瞬时压力过重雪崩。与缓存击穿的区别雪崩是很多key击穿是某一个key缓存。
>
>解决方案主要是可以将缓存失效时间分散开比如可以在原有的失效时间基础上增加一个随机值比如1-5分钟随机这样每一个缓存的过期时间的重复率就会降低就很难引发集体失效的事件。
>**面试官**redis做为缓存mysql的数据如何与redis进行同步呢双写一致性
>
>**候选人**就说我最近做的这个项目里面有xxxx**根据自己的简历上写**的功能需要让数据库与redis高度保持一致因为要求时效性比较高我们当时采用的读写锁保证的强一致性。
>
>我们采用的是redisson实现的读写锁在读的时候添加共享锁可以保证读读不互斥读写互斥。当我们更新数据的时候添加排他锁它是读写读读都互斥这样就能保证在写数据的同时是不会让其他线程读数据的避免了脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。
>**面试官**:那这个排他锁是如何保证读写、读读互斥的呢?
>
>**候选人**其实排他锁底层使用也是setnx保证了同时只能有一个线程操作锁住的方法
>**面试官**:你听说过延时双删吗?为什么不用它呢?
>
>**候选人**:延迟双删,如果是写操作,我们先把缓存中的数据删除,然后更新数据库,最后再延时删除缓存中的数据,其中这个延时多久不太好确定,在延时的过程中可能会出现脏数据,并不能保证强一致性,所以没有采用它。
>
>**面试官**redis做为缓存mysql的数据如何与redis进行同步呢双写一致性
>
>**候选人**就说我最近做的这个项目里面有xxxx**根据自己的简历上写**)的功能,数据同步可以有一定的延时(符合大部分业务)
>
>我们当时采用的阿里的canal组件实现数据同步不需要更改业务代码部署一个canal服务。canal服务把自己伪装成mysql的一个从节点当mysql数据更新以后canal会读取binlog数据然后在通过canal的客户端获取到数据更新缓存即可。
>**面试官**redis做为缓存数据的持久化是怎么做的
>
>**候选人**在Redis中提供了两种数据持久化的方式1、RDB 2、AOF
>**面试官**:这两种持久化方式有什么区别呢?
>
>**候选人**RDB是一个快照文件它是把redis内存存储的数据写到磁盘上当redis实例宕机恢复数据的时候方便从RDB的快照文件中恢复数据。
>
>AOF的含义是追加文件当redis操作写命令的时候都会存储这个文件中当redis实例宕机恢复数据的时候会从这个文件中再次执行一遍命令来恢复数据
>**面试官**:这两种方式,哪种恢复的比较快呢?
>
>**候选人**RDB因为是二进制文件在保存的时候体积也是比较小的它恢复的比较快但是它有可能会丢数据我们通常在项目中也会使用AOF来恢复数据虽然AOF恢复的速度慢一些但是它丢数据的风险要小很多在AOF文件中可以设置刷盘策略我们当时设置的就是每秒批量写入一次命令
>**面试官**Redis的数据过期策略有哪些 ?
>
>**候选人**
>
>嗯~在redis中提供了两种数据过期删除策略
>
>
>第一种是惰性删除在设置该key过期时间后我们不去管它当需要该key时我们在检查其是否过期如果过期我们就删掉它反之返回该key。
>
>第二种是 定期删除就是说每隔一段时间我们就对一些key进行检查删除里面过期的key
>
>定期清理的两种模式:
>
>- SLOW模式是定时任务执行频率默认为10hz每次不超过25ms以通过修改配置文件redis.conf 的 **hz** 选项来调整这个次数
>- FAST模式执行频率不固定每次事件循环会尝试执行但两次间隔不低于2ms每次耗时不超过1ms
>
>Redis的过期删除策略**惰性删除 + 定期删除**两种策略进行配合使用。
>**面试官**Redis的数据淘汰策略有哪些 ?
>
>**候选人**
>
>嗯这个在redis中提供了很多种默认是noeviction不删除任何数据内部不足直接报错
>
>是可以在redis的配置文件中进行设置的里面有两个非常重要的概念一个是LRU另外一个是LFU
>
>LRU的意思就是最少最近使用用当前时间减去最后一次访问时间这个值越大则淘汰优先级越高。
>
>LFU的意思是最少频率使用。会统计每个key的访问频率值越小淘汰优先级越高
>
>我们在项目设置的allkeys-lru挑选最近最少使用的数据淘汰把一些经常访问的key留在redis中
>**面试官**数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的数据都是热点数据 ?
>
>**候选人**
>
>嗯,我想一下~~
>
>可以使用 allkeys-lru (挑选最近最少使用的数据淘汰)淘汰策略,那留下来的都是经常访问的热点数据
>**面试官**Redis的内存用完了会发生什么
>
>**候选人**
>
>嗯~这个要看redis的数据淘汰策略是什么如果是默认的配置redis内存用完以后则直接报错。我们当时设置的 allkeys-lru 策略。把最近最常访问的数据留在缓存中。
>**面试官**Redis分布式锁如何实现 ?
>
>**候选人**在redis中提供了一个命令setnx(SET if not exists)
>
>由于redis的单线程的用了命令之后只能有一个客户端对某一个key设置值在没有过期或删除key的时候是其他客户端是不能设置这个key的
>**面试官**好的那你如何控制Redis实现分布式锁有效时长呢
>
>**候选人**的确redis的setnx指令不好控制这个问题我们当时采用的redis的一个框架redisson实现的。
>
>在redisson中需要手动加锁并且可以控制锁的失效时间和等待时间当锁住的一个业务还没有执行完成的时候在redisson中引入了一个看门狗机制就是说每隔一段时间就检查当前业务是否还持有锁如果持有就增加加锁的持有时间当业务执行完成之后需要使用释放锁就可以了
>
>还有一个好处就是在高并发下一个业务有可能会执行很快先客户1持有锁的时候客户2来了以后并不会马上拒绝它会自旋不断尝试获取锁如果客户1释放之后客户2就可以马上持有锁性能也得到了提升。
>**面试官**好的redisson实现的分布式锁是可重入的吗
>
>**候选人**是可以重入的。这样做是为了避免死锁的产生。这个重入其实在内部就是判断是否是当前线程持有的锁如果是当前线程持有的锁就会计数如果释放锁就会在计算上减一。在存储数据的时候采用的hash结构大key可以按照自己的业务进行定制其中小key是当前线程的唯一标识value是当前线程重入的次数
>**面试官**redisson实现的分布式锁能解决主从一致性的问题吗
>
>**候选人**这个是不能的比如当线程1加锁成功后master节点数据会异步复制到slave节点此时当前持有Redis锁的master节点宕机slave节点被提升为新的master节点假如现在来了一个线程2再次加锁会在新的master节点上加锁成功这个时候就会出现两个节点同时持有一把锁的问题。
>
>我们可以利用redisson提供的红锁来解决这个问题它的主要作用是不能只在一个redis实例上创建锁应该是在多个redis实例上创建锁并且要求在大多数redis节点上都成功创建锁红锁中要求是redis的节点数量要过半。这样就能避免线程1加锁成功后master节点宕机导致线程2成功加锁到新的master节点上的问题了。
>
>但是,如果使用了红锁,因为需要同时在多个节点上都添加锁,性能就变的很低了,并且运维维护成本也非常高,所以,我们一般在项目中也不会直接使用红锁,并且官方也暂时废弃了这个红锁
>**面试官**:好的,如果业务非要保证数据的强一致性,这个该怎么解决呢?
>
>**候选人:**嗯~redis本身就是支持高可用的做到强一致性就非常影响性能所以如果有强一致性要求高的业务建议使用zookeeper实现的分布式锁它是可以保证强一致性的。
>**面试官**Redis集群有哪些方案, 知道嘛 ?
>
>**候选人**:嗯~~在Redis中提供的集群方案总共有三种主从复制、哨兵模式、Redis分片集群
>**面试官**:那你来介绍一下主从同步
>
>**候选人**是这样的单节点Redis的并发能力是有上限的要进一步提高Redis的并发能力可以搭建主从集群实现读写分离。一般都是一主多从主节点负责写数据从节点负责读数据主节点写入数据之后需要把数据同步到从节点中
>**面试官**:能说一下,主从同步数据的流程
>
>**候选人**:嗯~~,好!主从同步分为了两个阶段,一个是全量同步,一个是增量同步
>
>全量同步是指从节点第一次与主节点建立连接的时候使用全量同步,流程是这样的:
>
>第一从节点请求主节点同步数据其中从节点会携带自己的replication id和offset偏移量。
>
>第二主节点判断是否是第一次请求主要判断的依据就是主节点与从节点是否是同一个replication id如果不是就说明是第一次同步那主节点就会把自己的replication id和offset发送给从节点让从节点与主节点的信息保持一致。
>
>第三在同时主节点会执行bgsave生成rdb文件后发送给从节点去执行从节点先把自己的数据清空然后执行主节点发送过来的rdb文件这样就保持了一致
>
>当然如果在rdb生成执行期间依然有请求到了主节点而主节点会以命令的方式记录到缓冲区缓冲区是一个日志文件最后把这个日志文件发送给从节点这样就能保证主节点与从节点完全一致了后期再同步数据的时候都是依赖于这个日志文件这个就是全量同步
>
>增量同步指的是当从节点服务重启之后数据就不一致了所以这个时候从节点会请求主节点同步数据主节点还是判断不是第一次请求不是第一次就获取从节点的offset值然后主节点从命令日志中获取offset值之后的数据发送给从节点进行数据同步
>**面试官**怎么保证Redis的高并发高可用
>
>**候选人**首先可以搭建主从集群再加上使用redis中的哨兵模式哨兵模式可以实现主从集群的自动故障恢复里面就包含了对主从服务的监控、自动故障恢复、通知如果master故障Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主同时Sentinel也充当Redis客户端的服务发现来源当集群发生故障转移时会将最新信息推送给Redis的客户端所以一般项目都会采用哨兵的模式来保证redis的高并发高可用
>**面试官**你们使用redis是单点还是集群哪种集群
>
>**候选人**我们当时使用的是主从1主1从加哨兵。一般单节点不超过10G内存如果Redis内存不足则可以给不同服务分配独立的Redis主从节点。尽量不做分片集群。因为集群维护起来比较麻烦并且集群之间的心跳检测和数据通信会消耗大量的网络带宽也没有办法使用lua脚本和事务
>**面试官**redis集群脑裂该怎么解决呢
>
>**候选人**:嗯! 这个在项目很少见不过脑裂的问题是这样的我们现在用的是redis的哨兵模式集群的
>
>有的时候由于网络等原因可能会出现脑裂的情况就是说由于redis master节点和redis salve节点和sentinel处于不同的网络分区使得sentinel没有能够心跳感知到master所以通过选举的方式提升了一个salve为master这样就存在了两个master就像大脑分裂了一样这样会导致客户端还在old master那里写入数据新节点无法同步数据当网络恢复后sentinel会将old master降为salve这时再从新master同步数据这会导致old master中的大量数据丢失。
>
>关于解决的话我记得在redis的配置中可以设置第一可以设置最少的salve节点个数比如设置至少要有一个从节点才能同步数据第二个可以设置主从数据复制和同步的延迟时间达不到要求就拒绝请求就可以避免大量的数据丢失
>**面试官**redis的分片集群有什么作用
>
>**候选人**分片集群主要解决的是海量数据存储的问题集群中有多个master每个master保存不同数据并且还可以给每个master设置多个slave节点就可以继续增大集群的高并发能力。同时每个master之间通过ping监测彼此健康状态就类似于哨兵模式了。当客户端请求可以访问集群任意节点最终都会被转发到正确节点
>**面试官**Redis分片集群中数据是怎么存储和读取的
>
>**候选人**
>
>嗯~在redis集群中是这样的
>
>Redis 集群引入了哈希槽的概念,有 16384 个哈希槽,集群中每个主节点绑定了一定范围的哈希槽范围, key通过 CRC16 校验后对 16384 取模来决定放置哪个槽,通过槽找到对应的节点进行存储。
>
>取值的逻辑是一样的
>**面试官**Redis是单线程的但是为什么还那么快
>
>**候选人**
>
>嗯,这个有几个原因吧~~~
>
>1、完全基于内存的C语言编写
>
>2、采用单线程避免不必要的上下文切换可竞争条件
>
>3、使用多路I/O复用模型非阻塞IO
>
>例如bgsave 和 bgrewriteaof 都是在**后台**执行操作,不影响主线程的正常使用,不会产生阻塞
>**面试官**能解释一下I/O多路复用模型
>
>**候选人**:嗯~~I/O多路复用是指利用单个线程来同时监听多个Socket 并在某个Socket可读、可写时得到通知从而避免无效的等待充分利用CPU资源。目前的I/O多路复用都是采用的epoll模式实现它会在通知用户进程Socket就绪的同时把已就绪的Socket写入用户空间不需要挨个遍历Socket来判断是否就绪提升了性能。
>
>其中Redis的网络模型就是使用I/O多路复用结合事件的处理器来应对多个Socket请求比如提供了连接应答处理器、命令回复处理器命令请求处理器
>
>在Redis6.0之后,为了提升更好的性能,在命令回复处理器使用了多线程来处理回复事件,在命令请求处理器中,将命令的转换使用了多线程,增加命令转换速度,在命令执行的时候,依然是单线程

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Some files were not shown because too many files have changed in this diff Show More