Jenkins+Gitlab+Nginx发布与回退基于tag的项目(解决重复构建)
环境拓扑:?Jenkins -192.168.1.30
?Gitlab -192.168.1.31
?LB -192.168.1.32
?Nginx1 -192.168.1.33
?Nginx2 -192.168.1.34
一、Jenkins集成Gitlab并实现自动发布项目- Jenkins为什么要集成Gitlab
?因为我们需要依托jenkins将gitlab上的项目获取至本地,为后续网站的的代码发布工作做好准备。
- Jenkins如何集成Gitlab
?由于enkins只是一个调度平台,所有需要安装与gitlab相关的插件即可完成集成。
1.开发提交代码至Gitlab?-准备好项目代码上传至服务器
--永久关闭防火墙和Selinux[root@Jenkins/Gitlab/LB/Web1/Web2 ~]# systemctl disable firewalld[root@Jenkins/Gitlab/LB/Web1/Web2 ~]# systemctl stop firewalld[root@Jenkins/Gitlab/LB/Web1/Web2 ~]# setenforce 0[root@Jenkins/Gitlab/LB/Web1/Web2 ~]# sed -i 's/enforcing/disabled/' /etc/selinux/config[root@Jenkins/Gitlab/LB/Web1/Web2 ~]# getenforce[root@Gitlab ~]# ll-rw-r--r-- 1 root root 1091072 3月 7 03:47 nongye-demo.tar[root@Gitlab ~]# tar -xf nongye-demo.tar[root@Gitlab ~]# lsgitlab-12-0-stable-zh gitlab-ce-12.0.3-ce.0.el7.x86_64.rpm nongye-demogitlab-12-0-stable-zh.tar.gz my-web nongye-demo.tar[root@Gitlab ~]# cd nongye-demo[root@Gitlab nongye-demo]# lscss fonts images index.html js
?-创建并配置项目
-按照Gitlab指示关联本地与远程仓库并推送代码到项目
[root@Gitlab nongye-demo]# git init初始化空的 Git 版本库于 /root/nongye-demo/.git/[root@Gitlab nongye-demo]# git remote add origin git@gitlab.fzmyw.com:devops/nongye-demo.git[root@Gitlab nongye-demo]# git remote -vorigin git@gitlab.fzmyw.com:devops/nongye-demo.git (fetch)origin git@gitlab.fzmyw.com:devops/nongye-demo.git (push)[root@Gitlab nongye-demo]# git add .[root@Gitlab nongye-demo]# git commit -m "第一次提交nongye-demo代码"[master(根提交) c8c49d3] 第一次提交nongye-demo代码 33 files changed, 11782 insertions(+) create mode 100755 css/bootstrap.css create mode 100755 css/style.css create mode 100755 css/swipebox.css create mode 100755 fonts/glyphicons-halflings-regular.woff create mode 100755 fonts/glyphicons-halflings-regular.woff2 create mode 100755 images/banner.jpg create mode 100755 images/g1.jpg create mode 100755 images/g2.jpg create mode 100755 images/g3.jpg create mode 100755 images/g4.jpg create mode 100755 images/g5.jpg create mode 100755 images/g6.jpg create mode 100755 images/g7.jpg create mode 100755 images/g8.jpg create mode 100755 images/icons.png create mode 100755 images/icons.svg create mode 100755 images/img1.jpg create mode 100755 images/move-up.png create mode 100755 images/slid.jpg create mode 100755 images/social-icons.png create mode 100755 images/t1.jpg create mode 100755 images/t2.jpg create mode 100755 images/t3.jpg create mode 100755 images/t4.jpg create mode 100755 index.html create mode 100755 js/bars.js create mode 100755 js/bootstrap.js create mode 100755 js/easing.js create mode 100755 js/easyResponsiveTabs.js create mode 100755 js/jquery-1.11.1.min.js create mode 100755 js/jquery.swipebox.min.js create mode 100755 js/move-top.js create mode 100755 js/responsiveslides.min.js[root@Gitlab nongye-demo]# git push origin -u masterCounting objects: 39, done.Compressing objects: 100% (39/39), done.Writing objects: 100% (39/39), 721.53 KiB | 0 bytes/s, done.Total 39 (delta 1), reused 0 (delta 0)To git@gitlab.fzmyw.com:devops/nongye-demo.git * [new branch] master -> master分支 master 设置为跟踪来自 origin 的远程分支 master。
2.Jenkins安装Gitlab所需插件
3.Jenkins创建freestyle项目,然后配置Gitlab仓库项目对应地址。
-配置Jenkins对Gitlab域名解析
[root@Jenkins ~]# echo 192.168.1.31 gitlab.fzmyw.com >> /etc/hosts
-Jenkins主机安装Git命令
[root@Jenkins ~]# yum -y install git4.Jenkins与Gitlab集成实践
-将Jenkins服务器的公钥放到Gitlab服务器上,实现Linux上免密克隆项目(Jenkins项目要免密拉取Gitlab代码还需要配置Jenkins凭证)
[root@Jenkins ~]# ssh-keygen -t rsaGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:SHA256:IlC1Xs6j1H0dz6o8qREJWvMOrxkzy0W1e4bD6vFkqQI root@JenkinsThe key's randomart image is:+---[RSA 2048]----+| ... || . . || . . = . . || . . B = o o + || . = S * o . o|| oEo * + + . || ..+ * O.+ || ..O Xo= || =o=.+. |+----[SHA256]-----+[root@Jenkins ~]# ls /root/.ssh/id_rsa id_rsa.pub known_hosts[root@Jenkins ~]# cat /root/.ssh/id_rsa.pubssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDRiweSF/50lxX7GKzyqq0FcT3i9GeMt2kaJXYZmKbKVk6qqqkQ7BUo1K65uiAUW2Bt70QBsbrciMzEDTnbspdaeAMd9pRPIeUsFIVG77cchAz2pvrokQolrWYF4cVMdeIyoOxhCHZzxrsPbrDFUWjcQYtl82/+ASbF6+3VFSUmjw68h1hhWAg0S/gJ9jhxC9lEDRs9/g1SB74G65JTf8wLMJgYFvMY1snsAbKgPcSUG20n/ErvPR+u9ZyB39Ri32dhqQcwWneyTxP/LzIRN/v9QPNjwICc9jkfbgFhmQ7SSlLgcyf2OnyjbY4uo38UGE8S0TYAtUrIWzLp/WFKfzXP root@Jenkins
-将Jenkins服务器的私钥配置成一个Jenkins凭据,实现Jenkins项目免密拉取Gitlab代码
?因为上面我们已经将Jenkins的公钥配置到了Gitlab的root用户SSH密钥配置中,现在Jenkins上的项目要去Gitlab拉取代码,需要再将Jenkins本机的私钥内容添加到Jenkins凭据中并在项目Git连接配置栏指定该私钥,即可完成认证(公钥-私钥)并免密连接拉取代码!
[root@Jenkins ~]# cat /root/.ssh/id_rsa-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEA0YsHkhf+dJcV+xis8qqtBXE94vRnjLdpGiV2GZimylZOqqqpEOwVKNSuubogFFtgbe9EAbG63IjMxA0527KXWngDHfaUTyHlLBSFRu+3HIQM9qb66JEKJa1mBeHFTHXiMqDsYQh2c8a7D26wxVFo3EGLZfNv/gEmxevt1RUlJo8OvIdYYVgINEv4CfY4cQvZRA0bPf4NUge+BuuSU3/MCzCYGBbzGNbJ7AGyoD3ElBttJ/xK7z0frvWcgd/UYt9nYakHMFp3sk8T/y8yETf7/UDzY8CAnPY5H24BYZkO0kpS4HMn9jp8o22OLqN/FBhPEtE2ALVKyFsy6f1hSn81zwIDAQABAoIBACB1kO6omNomrVkAMYpFthepuxR1F7VMlBNgyjKc2vls9TKqzRW5/G0exRIwKtf8b6uX7Mj2ZyPSbSXRhqzptVhmTtVNZRv8/Csf4qVibNMWAYwTwbpU/WVovu0aVB3MBQYit3swfGji2AdD9k4alkvIO3fHhgmq0/7E1Uq0w9R8/KaaLNstHi0EYBSqUzFnNPTkw7Jtc+hMaXwhkiwdIhnwImrCV9M5Gte4lIYIpHmcKJ9o8/ie6f+/amicujQpPiThtm/TwKdXZKtwU0IN3HaR6RKy1IPOhx9sYltwdWN8YEGkyM//zP7ETVrIuUhJ2iHSoECNivV0I/xKOu2YgwECgYEA+vnikyY9ciD215p+vYByFeciAfS+g3BSK3GWHxNF3UipDlyg3/BXIqhQFknRR/uAIwcc6DfcOhd6KUKKSfXoLbvqhfMHDD4ftTIr8006mvQpn3sG49VnEWRaC+sWLBPyOPTpp5fZ76wHyCkjVKlUhQAZxainkxZ70kRGeBz+OZECgYEA1bzSrbHgDKQc6ovZumRV0fxyPtQ2tE1tTpXcp47rgNalfIvvDMObvj3B2BXwwr4c8rAQUlYR8/LU9y41ZOF7GdIhEaRbRnVk7il7guQ9Kg1eWNYRL0XEim4hBtEEyAPl01z8bXyfKfOIKoIEzcu4Or/iwl6QjdxCZHgq7WslyV8CgYBxwKC5ITPobphy0EtxiK4szz3StSNEX7xehHUOUKXxzeUR5VnlJgHYa4EhGQQKJCvHtImdlvPyQIHWAZq8OwCo+esqGySun9mvPrY86FwPr2rOJezRhv/YGivWCw9ZmxDGT/s3QtQ8lTRRvJOO49CzF4CW3gJV4HLuspNeDYYMgQKBgQDAF5fw63BFbClg0pe34P0QYCX9OZSAryWR/zX0kYounLrWGJ2bhyGt9KsGnZFoNJynsHy6wwgXiyLDlBAAvnV4W1XFGUW/KTqwoS+UD7S42pL0nE+NgNKG5ztfePMnH/mp4GQtslcJyQmTyo6utmy4wEP4FC0ukcpJqYZLIoUvWQKBgQCDZUIuwJok/KLrFosAB4CyDA7VtbbRCPmTN7F2tULsZlg3advoTOJ45XjTamMUxS9aB5FXM0OfjQYW2uEE+dtFksNyDr0xZdbdnirowdtUsIcvIhD8L14DlrKuJznwrioaee2Y7gWMGBuvAMMRfPRnflLdu4I7XiLoqorSGMUzPg==-----END RSA PRIVATE KEY-----
-只测试Jenkins项目拉取Gitlab代码,暂时不做其他配置
[root@Jenkins ~]# ls /var/lib/jenkins/workspace/ #查看Jenkins工作目录freestyle-nongye freestyle-nongye@tmp [root@Jenkins ~]# ll #项目代码都在下面总用量 214052-rw-r--r-- 1 root root 77080368 3月 8 10:53 jenkins-2.176-1.1.noarch.rpm-rw-r--r--. 1 root root 71679711 3月 6 02:53 jenkins-2.283-1.1.noarch.rpm-rw-r--r-- 1 root root 70422599 3月 8 10:53 jenkins-2.60.3-1.1.noarch.rpm[root@Jenkins ~]# ll /var/lib/jenkins/workspace/freestyle-nongye总用量 416drwxr-xr-x 2 jenkins jenkins 64 3月 8 23:03 cssdrwxr-xr-x 2 jenkins jenkins 89 3月 8 23:03 fonts-rw-r--r-- 1 jenkins jenkins 34700 3月 8 23:03 g1.jpg-rw-r--r-- 1 jenkins jenkins 33354 3月 8 23:03 g2.jpg-rw-r--r-- 1 jenkins jenkins 28677 3月 8 23:03 g3-1646724756761.jpg-rw-r--r-- 1 jenkins jenkins 28677 3月 8 23:03 g3.jpg-rw-r--r-- 1 jenkins jenkins 55980 3月 8 23:03 g4.jpg-rw-r--r-- 1 jenkins jenkins 30487 3月 8 23:03 g5-1646724774424.jpg-rw-r--r-- 1 jenkins jenkins 30487 3月 8 23:03 g5-1646724779175.jpg-rw-r--r-- 1 jenkins jenkins 30487 3月 8 23:03 g5.jpgdrwxr-xr-x 2 jenkins jenkins 301 3月 8 23:03 images-rwxr-xr-x 1 jenkins jenkins 32046 3月 8 23:03 index.htmldrwxr-xr-x 2 jenkins jenkins 195 3月 8 23:03 js-rw-r--r-- 1 jenkins jenkins 142 3月 8 23:03 README.md-rw-r--r-- 1 jenkins jenkins 90503 3月 8 23:03 slid.jpg5.Jenkins实现项目自动化发布
1.手动搭建Nginx集群架构
-后端集群(LB、Web1、Web2)都需安装Nginx
?Nginx的安装与平滑升级(详):…
-LB负载均衡主机
[root@LB ~]# /usr/local/nginx/sbin/nginx -Vnginx version: nginx/1.16.1built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module[root@LB ~]# vim /usr/local/nginx/conf/nginx.conf... #gzip on; upstream html { #负载均衡配置 server 192.168.1.33:80; server 192.168.1.34:80;} server { listen 80; server_name html.fzmyw.com; #域名(测试域名,需要配置好域名解析) #charset koi8-r; #access_log logs/host.access.log main; location / { #root html; #index index.html index.htm; proxy_pass ; #负载均衡转发配置 proxy_set_header Host $http_host; }...[root@LB ~]# /usr/local/nginx/sbin/nginx -t #验证nginx配置文件有无错误nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful[root@LB ~]# /usr/local/nginx/sbin/nginx -s reload #平滑重启nginx
-Nginx1主机
[root@Web1 ~]# /usr/local/nginx/sbin/nginx -Vnginx version: nginx/1.16.1built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module[root@Web1 ~]# vim /usr/local/nginx/conf/nginx.conf... #gzip on; server { listen 80; server_name html.fzmyw.com; #域名(测试域名,需要配置好域名解析) #charset koi8-r; #access_log logs/host.access.log main; location / { root html/code/web; #项目网站代码存放路径(除了nginx自带的html目录下,其他路径必须是写绝对路径) index index.html index.htm; }...[root@Web1 ~]# /usr/local/nginx/sbin/nginx -t[root@Web1 ~]# /usr/local/nginx/sbin/nginx -s reload [root@Web1 html]# pwd/usr/local/nginx/html[root@Web1 html]# mkdir -p code/web[root@Web1 html]# ls code/web
-Nginx2主机
[root@Web2 ~]# /usr/local/nginx/sbin/nginx -Vnginx version: nginx/1.16.1built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module[root@Web2 ~]# vim /usr/local/nginx/conf/nginx.conf... #gzip on; server { listen 80; server_name html.fzmyw.com; #域名(测试域名,需要配置好域名解析) #charset koi8-r; #access_log logs/host.access.log main; location / { root html/code/web; #项目网站代码存放路径(除了nginx自带的html目录下,其他路径必须是写绝对路径) index index.html index.htm; }...[root@Web2 ~]# /usr/local/nginx/sbin/nginx -t[root@Web2 ~]# /usr/local/nginx/sbin/nginx -s reload[root@Web2 html]# pwd/usr/local/nginx/html[root@Web2 html]# mkdir -p code/web[root@Web2 html]# ls code/web6.手动编写Shell上线脚本,由Jenkins调用,拉取Gitlab代码并推送至Web服务器组实现项目上线
-配置Jenkins主机与后端Web集群组免密钥连接
[root@Jenkins ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.33[root@Jenkins ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.34
-编写上线脚本
[root@Jenkins ~]# mkdir shell[root@Jenkins ~]# vim shell/html_depoly.sh#!/sbin/bin/bashDATE=$(date +%Y-%m-%d-%H-%M-%S) #定义时间戳变量WEB="192.168.1.33 192.168.1.34" #定义后端集群组CODE="/usr/local/nginx/html/code" #定义后端项目代码存放路径Sdir="/opt" #定义项目tar包中转路径#思路:#1.Jenkins将Gitlab代码拉取至工作目录后,需先将项目代码打包get_code() { tar -czf $Sdir/web-${DATE}.tar.gz -C $WORKSPACE . #最后的WORKSPACE变量是直接调用的Jenkins的环境变量(即Jenkins中当前项目的工作目录),在添加执行Shell处可查看可调用的环境变量}#2.再scp将打好包的项目代码拷贝至Web后端集群项目文件夹中scp_web_server() {for i in ${WEB}do scp $Sdir/web-${DATE}.tar.gz root@$i:$Sdir #将打包好的项目tar包发送至后端集群组/opt目录 ssh root@$i "mkdir -p $CODE/web-${DATE} && \ #在后端集群项目代码存放路径创建当前项目时间戳目录,方便后期回滚(使用时删掉注释) tar -xf $Sdir/web-${DATE}.tar.gz -C $CODE/web-${DATE} #将带时间戳的项目包解压至后端集群组代码存放目录下 rm -rf $CODE/web && \ #删除当前的在运行的项目代码文件夹(或者移走备份) ln -s $CODE/web-${DATE} $CODE/web" #将新的项目代码文件夹设置软链接到后端集群项目代码读取目录done}deploy() { get_code scp_web_server #将两个函数定义在一起} deploy #执行函数
-修改Jenkins启动用户为root(避免各种权限问题)
[root@Jenkins ~]# vim /etc/sysconfig/jenkins...#JENKINS_USER="jenkins"JENKINS_USER="root" #修改启动Jenkins用户为root...[root@Jenkins ~]# systemctl restart jenkins[root@Jenkins shell]# ps -aux |grep jenkinsroot 44189 58.4 12.6 2688564 259068 ? Ssl 01:30 0:38 /etc/alternatives/java -Dcom.sun.akuma.Daemon=daemonized -Djava.awt.headless=true -DJENKINS_HOME=/var/lib/jenkins -jar /usr/lib/jenkins/jenkins.war --logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war --daemon --httpPort=8080 --debug=5 --handlerCountMax=100 --handlerCountMaxIdle=20root 44352 0.0 0.0 112720 980 pts/1 R+ 01:31 0:00 grep --color=auto jenkins
-配置Jenkins构建发布脚本
-Jenkins立即构建项目,实现上线
Windows访问时需配置域名解析
查看后端集群服务器上代码目录
?可以看到当前项目运行代码目录web软链接到了下面最新的web-2022-03-09-06-23-19代码目录。
[root@Web1 code]# pwd/usr/local/nginx/html/code[root@Web1 code]# ll总用量 0lrwxrwxrwx 1 root root 50 3月 9 16:01 web -> /usr/local/nginx/html/code/web-2022-03-09-06-23-19 #可以看到当前项目运行代码目录软链接到了下面最新的一个代码目录drwxr-xr-x 7 997 995 271 3月 9 04:54 web-2022-03-09-05-58-31drwxr-xr-x 7 997 995 271 3月 9 04:54 web-2022-03-09-06-23-19问题:项目需要回退版本怎么办?二、Jenkins实现项目tag版本方式发布
- 为什么要让项目支持tag版本方式上线?
?由于之前上线方式是直接获取最新代码,那么会造成后期回退变的困难。那如果采用ag方式,比如第一次上线v1.1、第二次上线v1.2、如果上线v1.2出现问题,那么我们可以快速回退至上一个版本v1.1。
- 实现tag版本上线方式思路
1.开发如果需要发布新版本,必须将当前的版本打上一个标签。2.Jenkins需要让其脚本支持传参,比如用户传递v1.1则拉取项目的v1.1标签的代码。1.首先安装Git Parameter插件,然后配置Jenkins参数化构建,让用户在构建时可以选择对应的tag版本。 2.修改代码,开发将提交至Gitlab上的代码打上不同的tag版本标签[root@Gitlab ~]# cd nongye-demo #进入开发之前克隆下来的项目代码目录[root@Gitlab nongye-demo]# lscss g2.jpg g4.jpg g5.jpg jsfonts g3-1646724756761.jpg g5-1646724774424.jpg images README.mdg1.jpg g3.jpg g5-1646724779175.jpg index.html slid.jpg[root@Gitlab nongye-demo]# git pull origin master #更新一下本地仓库代码(实际环境中可能会有其他人共同开发代码,已经提交过新代码,所以需要将远程仓库最新代码更新到本地仓库)来自 gitlab.fzmyw.com:devops/nongye-demo * branch master -> FETCH_HEADAlready up-to-date.[root@Gitlab nongye-demo]# git tag -a "v1.0" -m "v1.0版本代码提交为新的tag" #给当前本地仓库最新的完整代码打一个tag标签为v1.0版本[root@Gitlab nongye-demo]# git tag #查看当前所有的tag标签v1.0 [root@Gitlab nongye-demo]# git push origin v1.0 #将打好的tag标签版本推送至远程仓库的tag中Counting objects: 1, done.Writing objects: 100% (1/1), 158 bytes | 0 bytes/s, done.Total 1 (delta 0), reused 0 (delta 0)To git@gitlab.fzmyw.com:devops/nongye-demo.git * [new tag] v1.0 -> v1.0
-再修改代码,将不同的版本代码提交至Gitlab并打上不同的tag版本标签
[root@Gitlab nongye-demo]# vim index.html #修改代码为v2.0... <div class="container"> <div class="header-left"> <h1><a href="index.html">v2.0</a></h1> </div> <div class="header-right">...[root@Gitlab nongye-demo]# git add .[root@Gitlab nongye-demo]# git commit -m "v2.0"[master 253e97c] v2.0 1 file changed, 1 insertion(+), 1 deletion(-)[root@Gitlab nongye-demo]# git push origin masterCounting objects: 5, done.Compressing objects: 100% (3/3), done.Writing objects: 100% (3/3), 278 bytes | 0 bytes/s, done.Total 3 (delta 2), reused 0 (delta 0)To git@gitlab.fzmyw.com:devops/nongye-demo.git c81b043..253e97c master -> master[root@Gitlab nongye-demo]# git tag -a "v2.0" -m "v2.0版本代码提交为新的tag"[root@Gitlab nongye-demo]# git tagv1.0v2.0[root@Gitlab nongye-demo]# git push origin v2.0Counting objects: 1, done.Writing objects: 100% (1/1), 183 bytes | 0 bytes/s, done.Total 1 (delta 0), reused 0 (delta 0)To git@gitlab.fzmyw.com:devops/nongye-demo.git * [new tag] v2.0 -> v2.0 3.修改支持Gitlab项目tag版本传参的上线脚本
?脚本中的传递tag版本参数的变量$git_version是在Jenkins项目配置中Git Parameter那里设置的变量。
[root@Jenkins ~]# cd shell/[root@Jenkins shell]# cp html_depoly.sh html_depoly_tag.sh[root@Jenkins shell]# vim html_depoly_tag.sh#!/sbin/bin/bashDATE=$(date +%Y-%m-%d-%H-%M-%S)WEB="192.168.1.33 192.168.1.34"CODE="/usr/local/nginx/html/code"Sdir="/opt"Name=${DATE}-${git_version} #git_version是在Jenkins项目配置中Git Parameter那里设置的变量名字,将时间戳变量跟tag版本变量组合成一个,看着精简一点#思路:#1.Jenkins将Gitlab代码拉取至工作目录后,需先进入Jenkins工作目录将项目代码打包get_code() { #tar -cf $Sdir/web-${DATE}-${git_version}.tar.gz -C $WORKSPACE . #这里的WORKSPACE变量是直接调用的Jenkins的环境变量(即Jenkins中当前项目的工作目录),在执行Shell处可查看可调用的环境变量 tar -cf $Sdir/web-${Name}.tar.gz -C $WORKSPACE . #这里的$Name变量是将时间戳变量跟tag版本变量组合成一个,可以让打包好的项目名带上时间戳跟tag版本号}#2.再scp将打好包的项目代码拷贝至Web后端集群项目文件夹中scp_web_server() {for i in ${WEB}do scp $Sdir/web-${Name}.tar.gz root@$i:$Sdir ssh root@$i "mkdir -p $CODE/web-${Name} && \ tar -xf $Sdir/web-${Name}.tar.gz -C $CODE/web-${Name} rm -rf $CODE/web && \ ln -s $CODE/web-${Name} $CODE/web"done}deploy() { get_code scp_web_server} deploy4.实战Jenkins构建不同的tag版本项目发布
Jenkins项目进行参数化构建,在构建时选择新的tag版本部署并查看项目是否更新为修改后的新版本。
[root@Web1 code]# pwd/usr/local/nginx/html/code[root@Web1 code]# ll #查看后端服务器web1的项目文件夹,可以看到新部署的v2.0版本总用量 0lrwxrwxrwx 1 root root 55 3月 10 00:32 web -> /usr/local/nginx/html/code/web-2022-03-09-15-30-16-v2.0drwxr-xr-x 7 997 995 271 3月 10 00:03 web-2022-03-09-06-23-19drwxr-xr-x 7 997 995 271 3月 9 15:28 web-2022-03-09-15-30-16-v2.0三、Jenkins实现项目tag版本的回退1.修改支持Gitlab项目tag版本传参的回退脚本
[root@Jenkins shell]# cp html_depoly_tag.sh html_depoly_tag_rollback.sh[root@Jenkins shell]# vim html_depoly_tag_rollback.sh#!/sbin/bin/bashDATE=$(date +%Y-%m-%d-%H-%M-%S)WEB="192.168.1.33 192.168.1.34"CODE="/usr/local/nginx/html/code"Sdir="/opt"Name=${DATE}-${git_version} #git_version是在Jenkins项目配置中Git Parameter那里设置的变量名字,将时间戳变>量跟tag版本变量组合成一个,看着精简一点#思路:#1.Jenkins将Gitlab代码拉取至工作目录后,需先进入Jenkins工作目录将项目代码打包get_code() { #tar -cf $Sdir/web-${DATE}-${git_version}.tar.gz -C $WORKSPACE . #这里的WORKSPACE变量是直接调用的Jenkins的环境变量(即Jenkins中当前项目的工作目录),在执行Shell处可查看可调用的环境变量 tar -cf $Sdir/web-${Name}.tar.gz -C $WORKSPACE .}#2.再scp将打好包的项目代码拷贝至Web后端集群项目文件夹中scp_web_server() {for i in ${WEB}do scp $Sdir/web-${Name}.tar.gz root@$i:$Sdir ssh root@$i "mkdir -p $CODE/web-${Name} && \ tar -xf $Sdir/web-${Name}.tar.gz -C $CODE/web-${Name} rm -rf $CODE/web && \ ln -s $CODE/web-${Name} $CODE/web"done}deploy() { get_code scp_web_server}rollback() {back_file=$(ssh root@192.168.1.33 "find ${CODE} -maxdepth 1 -type d -name "web-*-${git_version}"")#由于后端集群部署回退时间戳、版本一致,所以这里就只需要到一台上查找我们在Jenkins构建时选择的git_version变量的值,即tag版本相对应的项目版本文件夹,即可回退至该版本 for i in ${WEB}do ssh root@$i "rm -rf $CODE/web && \ ln -s ${back_file} $CODE/web" #将上面查找到的回退版本项目文件夹设置为当前运行项目软链接done}#根据Jenkins项目中配置的选项参数变量deploy_env的值来判断执行哪一个脚本函数(部署脚本还是回退脚本)if [ $deploy_env == "deploy" ]; then deployelif [ $deploy_env == "rollback" ]; then rollbackfi
2.Jenkins添加参数化构建选项参数变量,支持选择部署或回退
问题:Jenkins中项目存在重复构建的问题?(点击构建项目多少次就会重复拷贝项目多少次,回退就没有意义)
四、Jenkins环境变量解决项目能重复发布问题GIT_COMMIT:Jenkins本次构建提交的哈希值
GIT_PREVIOUS_SUCCESSFUL_COMMIT:Jenkins上次在这个分支上成功构建的提交的哈希值。
注意:?GIT_PREVIOUS_SUCCESSFUL_COMMIT环境变量因为是记录的项目在这个分支上,上一次成功构建时提交的哈希值,所以这个哈希值是记录在构建历史里面的,如果将构建立历史删除,那么那一条构建成功记录的哈希值也会被删除!
1.修改支持判断重复构建的脚本(加入Jenkins环境变量判断)#!/sbin/bin/bashDATE=$(date +%Y-%m-%d-%H-%M-%S)WEB="192.168.1.33 192.168.1.34"CODE="/usr/local/nginx/html/code"Sdir="/opt"Name=${DATE}-${git_version} #git_version是在Jenkins项目配置中Git Parameter那里设置的变量名字,将时间戳变>量跟tag版本变量组合成一个,看着精简一点#思路:#1.Jenkins将Gitlab代码拉取至工作目录后,需先进入Jenkins工作目录将项目代码打包get_code() { #tar -cf $Sdir/web-${DATE}-${git_version}.tar.gz -C $WORKSPACE . #这里的WORKSPACE变量是直接调用的Jenkins的环境变量(即Jenkins中当前项目的工作目录),在执行Shell处可查看可调用的环境变量 tar -cf $Sdir/web-${Name}.tar.gz -C $WORKSPACE .}#2.再scp将打好包的项目代码拷贝至Web后端集群项目文件夹中scp_web_server() {for i in ${WEB}do scp $Sdir/web-${Name}.tar.gz root@$i:$Sdir ssh root@$i "mkdir -p $CODE/web-${Name} && \ tar -xf $Sdir/web-${Name}.tar.gz -C $CODE/web-${Name} rm -rf $CODE/web && \ ln -s $CODE/web-${Name} $CODE/web"done}deploy() { get_code scp_web_server}rollback() {back_file=$(ssh root@192.168.1.33 "find ${CODE} -maxdepth 1 -type d -name "web-*-${git_version}"")#由于后端集群部署回退时间一致,所以这里就只需要到一台上查找我们在Jenkins构建时选择的git_version变量的值,即tag版本相对应的项目版本文件夹 for i in ${WEB}do ssh root@$i "rm -rf $CODE/web && \ ln -s ${back_file} $CODE/web"done}#根据Jenkins项目中配置的选项参数变量deploy_env的值来判断执行哪一个脚本函数(部署脚本还是回退脚本)if [ $deploy_env == "deploy" ]; then#加入Jenkins中两个环境变量GIT_COMMIT、GIT_PREVIOUS_SUCCESSFUL_COMMIT来判断本次构建的项目哈希值是否已有成功构建存在的哈希值,存在及退出并提示,否则就部署! if [ "$GIT_COMMIT" == "$GIT_PREVIOUS_SUCCESSFUL_COMMIT" ];then echo "你已经部署过该${git_version}版本" exit 1 else deploy fielif [ $deploy_env == "rollback" ]; then rollbackfi
2.Jenkins构建时选择之前已经部署成功的tag版本项目进行重复构建
?可以看到tag为v2.0版本的项目之前已经成功构建过,所以现在再选择构建tag为v2.0版本的项目时,哈希值会重复,则根据脚本判断后无法继续构建,即可以避免重复构建问题! 3.Jenkins构建选择从未被构建过的tag版本项目进行构建
经济学人全球早报:上海电气总裁黄瓯逝世,字节跳动瓜瓜龙裁员50%,交个朋友回应锤子破产
上海电气执行董事兼总裁黄瓯8月5日不幸逝世
上海电气公告,公司执行董事兼总裁黄瓯于2021年8月5日不幸逝世。多位接近上海电气的人士透露,黄瓯于8月5日上午跳楼自尽。但各路记者未能从上海电气新闻中心证实这一消息。就在上周7月27日,上海电气公告,公司董事长兼首席执行官、法定代表人郑建华涉嫌严重违纪违法,目前正接受上海市纪委监委纪律审查和监察调查。随后在7月29日,公司董事会同意免去郑建华公司第五届董事会董事长、战略委员会主席及委员、首席执行官职务。
字节教育转型:瓜瓜龙体验课教辅裁员50%以上 你拍一、GOGOKID将被放弃
字节跳动旗下教育品牌大力教育正在进行新一轮调整:向3-8岁孩子提供AI动画课程的瓜瓜龙开始裁撤辅导老师,计划在8月底前裁撤50%以上的体验课辅导老师;向3-12岁孩子提供思维动画课程的你拍一、以及面向4-12岁孩子的外教英语一对一业务GOGOKID也已经下架了应用,接下来将停止运营。
交个朋友直播间回应锤子公司被申请破产:与债权方达成和解,流程已撤回
8月5日下午,就罗永浩锤子公司被申请破产一事,交个朋友直播间向新浪科技回应称,这个是锤子科技手机债务相关的案件,我们已经在6月4日和债权方达成了和解并按照和解协议陆续进行债务处理中。债权方申请公司破产的流程已经撤回,由于法院系统延迟的问题,现在才更新出来。罗永浩老师仍在积极努力挣钱,按计划积极替公司偿还债务,请大家放心!
北京:原家庭住房套数超限购 离婚3年内不得买房
北京市住房和城乡建设委员会发布《关于进一步完善商品住房限购政策的公告》,《公告》明确:自8月5日起,夫妻离异的,原家庭在离异前拥有住房套数不符合本市商品住房限购政策规定的,自离异之日起3年内,任何一方均不得在本市购买商品住房。相关负责人表示,在《公告》发布前提交离婚申请,尚未正式办理离婚登记的,离婚后仍然按照原先的政策执行。
上海小学期末不再考英语 禁止全区范围的学科统考统测
上海市教委印发《上海市中小学2021学年度课程计划及其说明》的通知,根据市教委有关文件的要求,小学生学业评价严格实行等第制;小学阶段不进行期中考试或考查;小学一、二年级可进行期末考查(一年级不得进行书面考查);三、四、五年级期末考试仅限语文、数学两门学科,其他学科只进行考查,考查形式可灵活多样,严格执行等第制。严禁对小学一至三年级进行全学区、全区范围的任何形式的学科统考统测(包括学业质量监测)。严禁对四至八年级进行全区范围的学科统考统测;区若要进行学业质量监测,每学年不超过1次,且只能随机抽样监测,随机抽取的学生比例不超过本年级的30%。严禁学校组织中小学生参加任何形式、任何范围的联考或月考。
成都完善购房政策:加强赠与管理、优化购房资格复核顺位
成都市正式出台《关于加强赠与管理和优化购房资格复核顺位相关事宜的通知》。第一,若受赠人具备购房资格,则赠与行为属于一次交易,视为发生过住房转让,赠与的住房计入受赠人家庭住房总套数审核购房资格。第二,若受赠人不具备购房资格,则赠与的住房自产权登记之日起5年内,仍计入赠与人家庭住房总套数审核购房资格。
永州多地发文指定爱尔眼科为学生视力建档,宁远县:合作文件已废止
近日,武汉抗疫医生艾芬在微博发文称,湖南省永州市宁远县教育局与卫健局联合发文指定宁远爱尔眼科作为当地学生视力建档医疗单位,并且有家长称“没有爱尔视力检查单,开学不能报名”,引发关注。涉事的宁远县爱尔眼科医院回应称系虚假消息。宁远县教育局则回应称,联合下发文件已于今年7月废止,宁远县纪委已介入调查。从永州眼科行业人士李良(化名)处获取的多份文件显示,不止是宁远县,还有永州市下辖零陵区、祁阳县亦下发过类似文件。
重磅!腾讯、阿里“互通”迎来重大进展
据媒体报道,脉脉平台上有一位认证为网易云音乐项目经理的用户表示,他认识的一位阿里巴巴内部人士向其证实淘宝88VIP或将于9月接入QQ音乐,进一步加大关联。此前就有网传消息称,未来阿里巴巴将在淘宝与天猫中引入微信支付,而腾讯将允许用户将阿里巴巴的电商消息分享。但双方都没有对传言作出正面回应。
饿了么成立外卖骑手基金,为骑手家庭提供帮扶
饿了么联合中华慈善总会成立“蓝骑士基金”,一年投入超千万帮扶骑手家庭。若骑手配偶、子女、父母遇到重大疾病,将提供每年2万元—5万元的帮扶金;低保户骑士的子女在教育阶段全程可申请助学金,额度为600元/学年/人—5000元/学年/人。
百度Apollo全新一代自动驾驶小巴阿波龙Ⅱ发布 将落地广州黄埔
8月5日,百度Apollo发布了新一代自动驾驶小巴——阿波龙II,新车拥有比肩Robotaxi的自动驾驶能力和更高级的智能座舱体验。未来百度Apollo将致力于把阿波龙II打造成为智能时代移动空间,面向公共出行、移动警务、健康管理等场景提供定制化的智能移动服务。
比亚迪股份:7月新能源汽车销量为50492辆 同比增长234.38%
比亚迪股份港股公告,7月新能源汽车销量为50492辆,同比增长234.38%,上年同期为15100辆;本年累计为20.51万辆,累计同比增长170.62%。
摩托罗拉发布edge系列双新机,2399元起售
摩托罗拉发布edge系列双新机,包括摩托罗拉edge s pro和摩托罗拉edge轻奢版。据官方介绍,两款新品均配备一亿像素主摄,传感器尺寸为1/1.52英寸,支持九合一2.1μm超大像素等。售价方面,摩托罗拉edge s pro 2399元起售,摩托罗拉edge轻奢版2599元起售。
乘联会崔东树:2021年1-6月中国新能源乘用车占世界份额47%
乘联会秘书长崔东树表示,中国新能源乘用车2019年的世界份额达到51%。但2020年受到政策环境与疫情等的影响,中国新能源车市场世界地位下降到41%,欧洲超越态势明显。2021年1-6月世界新能源乘用车销量235万台,中国新能源乘用车世界份额47%,表现优秀。
快看拟未来3年投入10亿元扶持原创漫画
快看创始人&CEO陈安妮在北京宣布,推出“双十亿”创作扶持计划,将在未来3年投入10亿元扶持原创漫画,另外投入10亿元携手合作方参与漫剧制作。作为“国漫第一平台”,快看2021年初正式进军全球市场,半年来已打开欧美日韩市场,覆盖近200个国家,目前用户数超2亿。
“星火·链网”底层区块链平台(BIF-Core)正式发布
日前,“首届全球数字经济大会”核心论坛——“数字基建与生态发展论坛”成功举办。论坛上,中国信通院工业互联网与物联网研究所副所长罗松介绍了“星火·链网”的最新进展,并正式发布了“星火·链网”底层区块链系统(BIF-Core),这标志着“星火·链网”的主链正式启动运行并开始向全球进行服务。
科兴将提交德尔塔毒株疫苗紧急使用申请
国内最早进入附条件上市的两家新冠灭活疫苗公司,科兴和中生也已开展对德尔塔变异株的疫苗研发。“科兴近期还将向各国药监局提交针对Gamma株的克尔来福?和Delta株的克尔来福?的临床研究及紧急使用申请。“今日,科兴控股生物技术有限公司董事长尹卫东透露。据悉,中生对于贝塔变变异株的灭活疫苗研发正在进行中,目前处于动物实验阶段。针对德尔塔变异株的灭活疫苗也在开发中。在其他技术路线上,针对变异株的重组蛋白疫苗、mRNA疫苗研发也都在进行中。
我国成功发射中星2E卫星
北京时间2021年8月6日0时30分,我国在西昌卫星发射中心用长征三号乙运载火箭,成功将中星2E卫星发射升空,卫星顺利进入预定轨道,发射任务获得圆满成功。此次任务是长征系列运载火箭的第383次飞行。
壕气!王楠夫妇要给奥运会乒乓球冠亚军送7套房
近期,前乒乓球奥运冠军王楠给东京奥运会乒乓球冠亚军送房的话题一举冲上微博热搜,引发广大网友的关注和热议。王楠的丈夫郭斌在微博上发文回应支持,并称一人一套合院。这意味着,王楠夫妇将送出7套房子。“合院”系王楠夫妇等及雅居乐集团合作开发的某地产项目中的户型。据悉,该户型一套总房款至少500万元。
560万粉UP主“机智的党妹”道歉:下架所有视频 退网反思
7月初,UP主“机智的党妹”发布了一段她在旅顺博物馆前跳舞的内容,瞬间引发网友质疑。8月5日晚,翻车一个月后,“机智的党妹”突然发长文道歉,称自己将删除全网账号,下架过往视频,正式退网。此前其在B站粉丝超过600万,如今还剩560万粉丝。
美国汽车制造商:拜登计划2030年零排放汽车销量占新车总销量50%
美国白宫与通用汽车、福特汽车和Stellantis发布联合声明表示,拜登将于当地时间8月5日签署一项行政令,设定了到2030年零排放汽车销量占新车总销量50%的目标,并提出新的汽车排放规定以在2026年之前减少污染。美国汽车制造商警告说,这将需要数十亿美元的政府资金。拜登该目标中的零排放汽车包括电池电动汽车、燃料电池汽车和带有汽油引擎的插电式混合动力汽车在内。
高通宣布以每股37美元现金竞购自动驾驶技术公司Veoneer
高通在一份声明中称,这项拟议中的收购,与高通的增长和多元化战略是一致的。它将强化高通将先进技术带入汽车行业的承诺,并代表着高通数字底盘解决方案(digital chassis solutions)的自然延伸。
小米葡萄牙商店开始接受比特币等加密货币支付
8月5日周四,据区块链与加密货币行业资讯网站U.Today报道,小米葡萄牙商店开始接受世界前三大数字货币和其他加密货币作为支付手段,推动比特币自8月2日以来首次重返4万美元。小米葡萄牙商店在社交媒体的官方网页上称,从现在开始,葡萄牙Mi Store的购物体验将变得更加包容和全面,用户可以使用比特币、以太坊、泰达币(Tether)、达世币(Dash)和瑞士加密货币支付服务供应商Utrust开发的原生代币Token Utrust来买小米产品。
AMD副总裁称赞苹果M1芯片,单线程性能强大,能效远超x86 CPU
AMD副总裁David McAfee近日接受了《印度快报》采访。他在采访中称赞了苹果自研的 ARM 架构M1芯片,并表示该芯片推出时震惊了业界,提供了出乎意料的性能。David McAfee表示苹果M1芯片的单核性能可以与AMD最新的Zen 3架构处理器相媲美。此外,M1芯片最大的创新是能效比特别高,目前的任何x86处理器在能效方面都不能和M1芯片相提并论。因此,M1芯片的发布对于业界是个很好的激励。
空客据称将在7月份交付约50架飞机
据彭博消息,一位知情人士透露,空客公司7月交付了大约50架飞机,根据该数字测算,空客今年以来截至目前的总交付量达到近350架。对此,公司拒绝发表评论。空客在疫情期间专注于维持喷气式飞机交付的战略已经取得成效,首席执行官纪尧姆·福里表示,订单量可望在今年晚些时候实现回升。
维珍银河:预计9月份将举行下一轮前往太空的火箭发射
维珍银河2021年Q2每股亏损0.39美元,市场预期亏损0.31美元,去年同期亏损0.3美元。公司正在恢复太空旅行“机票”的销售,起步价为每座45万美元;预计9月份将举行下一轮前往太空的火箭发射。
Astra计划在8月27日进行首次示范性的商业轨道发射
Astra5日披露了其首次商业轨道发射的发射窗口为8月27日,内容是为美国太空部队进行示范任务。Astra与美国空军签订的合同还包括第二次发射,时间定在今年晚些时候,该发射的确切时间表尚未最后确定。Astra公司的火箭将为太空部队携带的载荷将是为该机构的太空测试计划飞行的测试航天器。这次发射将从阿拉斯加科迪亚克的阿斯特拉太空港进行,公司以前就在那里进行过测试任务。
报告:2050年前实现净零排放 需在30年内年均新增可再生能源14亿千瓦
彭博近日发布2021年《新能源市场长期展望》,该报告指出,为了在2050年前实现净零排放目标,全球需要最高173万亿美元的能源转型投资。并且在接下来的30年里,平均每年需要新增大约14亿千瓦的可再生能源。
对书中“错误形象”不满?马斯克:已安排人给我写新的传记
8月5日,特斯拉CEO马斯克在社交平台表示,如果你对特斯拉、SpaceX和我的事情感到好奇,沃尔特?艾萨克森正在写一本传记。马斯克曾表示,艾萨克森已经跟随他好几天了,为这本书收集材料。此前,《华尔街日报》记者蒂姆?希金斯 (Tim Higgins) 在《权力游戏:马斯克、特斯拉和世纪赌注》披露了许多关于马斯克于他公司中不为人知的内幕。而马斯克对书中的许多内容并不认同。
鸿海砸25.2亿元新台币买旺宏六英寸晶圆厂,主攻电动车用SiC前进第三代半导体
鸿海与旺宏今(5)日共同举办签约仪式,鸿海将以25.2亿元新台币购买旺宏位在竹科的六英寸晶圆厂房及设备,交易产权转移预计今年底前完成,未来将主攻SiC功率元件,特别电动车用组件,并辅以硅晶圆的产品,像是微机电系统MEMS等,领先业界前进第三代半导体。
英特格高雄厂动土,2022年投产并创造200个工作机会
国际半导体材料大厂英特格在去年底宣布投资新台币60亿元,扩大在中国台湾地区布局;如今其全台湾地区最大制程中心的路科高雄厂日前也正式动土,预计于2022年底完工,并将提供200个工作机会。英特格台湾地区总经理谢俊安表示,英特格位于高雄路竹科学园区的新厂总占地约60,000平方公尺,楼板面积约37,000平方米,目前已开始进行建设,预计将于2022年底开始向客户交付样品,并逐步完成全面生产,将提供200个高端工作机会。
吉利与罗姆达成战略合作 携手发力碳化硅
8月3日,半导体制造商罗姆半导体官网宣布与汽车制造商吉利汽车集团缔结了以碳化硅为核心的战略合作伙伴关系。吉利将利用罗姆以碳化硅为核心的先进功率解决方案,开发高效电控系统和车载充电系统,以延长电动汽车的续航里程,降低电池成本并缩短充电时间。作为双方的首批合作成果,采用了罗姆碳化硅的电控系统已被应用于目前吉利正在开发的纯电动平台。
汽车芯片短缺加剧 南北丰田部分产线停产
始于去年底的汽车芯片短缺并没有随着时间推移而缓解,一汽丰田和广汽丰田因芯片短缺,各有部分产线暂停生产。不过两家公司均没有透露芯片短缺导致了哪些车型的减产,以及损失的具体产量。
中手游拟6.42亿港元向台湾大宇收购佳典及Mighty Leader100%股权。
上海电力拟224亿日元收购山口岩国项目公司100%股权 。
中国电信公告称,本次发行的初步询价工作已经完成,确定的发行价格为4.53元/股,对应的2020年摊薄后市盈率为20.18倍。预计发行人募集资金总额为470.94亿元,预计募集资金净额为467.12亿元。网下申购时间为8月9日(T日)的9:30-15:00,申购代码为“601728”。
立昂技术参股公司元道通信首次公开发行股票申请获通过。
证监会终止蓝箭电子、固安信通科创板发行注册。
证监会公告,陕西美邦药业集团股份有限公司首发获通过。
创业板上市委:亨迪药业、鑫甬生物首发8月12日上会。
上海凯宝参股公司谊众药业在科创板首次公开发行股票注册申请获批。
北京极智嘉科技计划最早今年在美国或上海进行IPO,募资5亿美元,目前公司更偏好在美国进行上市。
美股三大指数集体收涨,纳指、标普500指数创收盘新高,邮轮股、航空股、抗疫概念股表现强势。其中,道指收涨0.78%,纳指收涨0.78%,标普500指数收涨0.60%。美股经纪商Robinhood收盘跌28%。热门中概股多数下跌,网易跌超5%,滴滴跌超4%。
欧洲主要股指收盘涨跌不一,德国DAX30指数上涨0.34%,报15745.35点;英国富时100指数下跌0.02%,报7122.30点;法国CAC40指数上涨0.52%,报6781.19点。
国内商品期货夜盘收盘涨跌不一,能源化工品多数下跌;黑色系普遍走低;农产品表现分化。
问:风力发电行业市场规模?
前瞻产业研究员、分析师答:
感谢您的提问!
近年来,在国家重视并大力支持风电行业的背景下,我国风电装机容量呈现出加速增长的态势,2020年全国新增装机容量7167万千瓦,同比增长81.8%;累计装机容量为28153万千瓦,同比增长24.1%。
图表1:2015-2020年中国新增和累计风电装机容量(单位:万千瓦
更多数据请参考前瞻产业研究院《中国风电行业市场前瞻与投资战略规划分析报告》,同时前瞻产业研究院还提供产业大数据、产业规划、产业申报、产业园区规划、产业招商引资等解决方案。
更多深度行业分析尽在【前瞻经济学人APP】,还可以与500+经济学家/资深行业研究院交流互动。
日志分析平台Elasisearch+Filebeat+Redis+Logstash+Kibana部署
ELK日志分析平台? ELK日志分析系统是Logstash、Elastcsearch、Kibana开源软件的集合,对外是作为一个日志管理系统的开源方案,它可以从任何来源、任何格式进行日志搜索、分析与可视化展示。
1.ELK日志分析系统组成
? elasticsearch (es) :通过搭建群集;存储日志数据,索引日志数据。
? logstash :收集日志,收集到了后给es存储。
? kibana :视图形式展现日志信息,更加人性化。
2.日志处理步骤
? 将日志进行集中化管理。
? 将日志格式化(Logstash)并输出到Elasticsearch。
? 对格式化后的数据进行索引和存储(Elasticsearch)。
? 前端数据的展示(Kibana)。
1.Elasticsearch的概述
? 提供了一个分布式多用户能力的全文搜索引擎。
2.Elasticsearch核心概念
? 2.1接近实时(NRT)
? elasticsearch是一个接近实时的搜索平台,这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒)。
? 2.2集群(cluster)
? 一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。其中一个节点为主节点,这个主节点是可以通过选举产生的,并提供跨节点的联合索引和搜索的功能。集群有一个唯一性标示的名字,默认是elasticsearch,集群名字很重要,每个节点是基于集群名字加入到其集群中的。因此,确保在不同环境中使用不同的集群名字。
? —个集群可以只有一个节点。强烈建议在配置elasticsearch时,配置成集群模式。
? es具有集群机制,节点通过集群名称加入到集群中,同时在集群中的节点会有一个自己的唯一身份标识(自己的名称)。
? 2.3节点(node)
? 节点就是一台单一的服务器,是集群的一部分,存储数据并参与集群的索引和搜索功能。像集群一样,节点也是通过名字来标识,默认是在节点启动时随机分配的字符名。当然,你可以自己定义。该名字也很重要,在集群中用于识别服务器对应的节点。
? 节点可以通过指定集群名字来加入到集群中。默认情况,每个节点被设置成加入到elasticsearch集群。如果启动了多个节点,假设能自动发现对方,他们将会自动组建一个名为elasticsearch的集群。
? 2.4索引 (type)
? 在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类!分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。
? 类型相对于关系型数据库的表 ——》索引(库)-》类型(表)-》文档(记录)
? 2.5文档(document)
? 一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation))格式来表示,而JSON是一个到处存在的互联网数据交互格式。
? 在一个index/type里面,只要你想,你可以存储任意多的文档。注意,虽然一个文档在物理上位于一个索引中,实际上一个文档必须在一个索引内被索引和分配一个类型。文档相对于关系型数据库的列。
? 2.6分片和副本(shards & replicas)
? 在实际情况下,索引存储的数据可能超过单个节点的硬件限制。如一个10亿文档需1TB空间可能不适合存储在单个节点的磁盘上或者从单个节点搜索请求太慢了。为了解决这个问题,elasticsearch提供将索引分成多个分片的功能。当在创建索引时,可以定义想要分片的数量。每一个分片就是一个全功能的独立的索引,可以位于集群中任何节点上。
分片的两个最主要原因:
a.水平分割扩展,增大存储量b.分布式并行跨分片操作,提高性能和吞吐量? 分布式分片的机制和搜索请求的文档如何汇总完全是有elasticsearch控制的,这些对用户而言是透明的。
? 网络问题等等其它问题可以在任何时候不期而至,为了健壮性,强烈建议要有一个故障切换机制,无论何种故障以防止分片或者节点不可用。为此,elasticsearch让我们将索引分片复制一份或多份,称之为分片副本或副本。
副本也有两个最主要原因:
a.高可用性,以应对分片或者节点故障。出于这个原因,分片副本要在不同的节点上。b.能增大吞吐量,搜索可以并行在所有副本上执行。二、Filebeat? Filebeat 是一个轻量级的传送器,用于转发和集中日志数据。Filebeat 作为代理安装在您的服务器上,监控您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash以进行索引。
? Filebeat 的工作原理如下:当您启动 Filebeat 时,它会启动一个或多个输入,这些输入会在您为日志数据指定的位置中查找。对于 Filebeat 找到的每个日志,Filebeat 都会启动一个收割机。每个收割机读取新内容的单个日志,并将新日志数据发送到 libbeat,后者聚合事件并将聚合数据发送到您为 Filebeat 配置的输出。
三、Redis1.Redis简介
? Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。Redis支持数据的备份,即master-slave模式的数据备份。2.Redis优势
性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。3.Redis与其他key-value存储有什么不同?
? Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
? Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
四、Logstash1.Logstash介绍
—款强大的数据处理工具可实现数据传输、格式处理、格式化输出数据输入(从业务输入)、数据加工(如过滤、改写等)以及数据输出(输出到Elasticsearch群集)2.Logstash的主要组件
shipper:日志收集者,负责监控本地日志文件的变化,及时把日志文件的最新内容收集起来。通常,远程代理端(agent)只需要运行这个组件即可indexer:日志存储者,负责接收日志并写入到本地文件broker:日志hub,负责连接多个shipper和多个indexersearch and storage:允许对事件进行搜索和存储web interface:基于wWeb的展示界面五、Kibana1.Kibana介绍
一个针对Elasticsearch的开源分析及可视化平台搜索、查看存储在Elasticsearch索引中的数据通过各种图表进行高级数据分析及展示2.Kibana主要功能
Elasticsearch无缝之集成整合数据,复杂数据分析让更多团队成员受益接口灵活,分享更容易配置简单,可视化多数据源简单数据导出环境介绍:192.168.1.21?2核4G ? es-master21 ? ?filebeat、redis、logstash、elasticsearch、elasticsearch-head、kibana
192.168.1.22?1核2G? es-node22 ? ?elasticsearch
192.168.1.23?1核2G ? es-node23 ? ? elasticsearch
注意:
?Linux内核:3.10.0-862.el7.x86_64(不低于3.10.0)。
?ELK+Filebeat软件版本均为7.10.1,redis为最新latest,插件为elasticsearch-head:5版本。
?首先 logstash 具有日志采集、过滤、筛选等功能,功能完善但同时体量也会比较大,消耗系统资源自然也多。filebeat作为一个轻量级日志采集工具,虽然没有过滤筛选功能,但是仅仅部署在应用服务器作为我们采集日志的工具可以是说最好的选择。但我们有些时候可能又需要logstash的过滤筛选功能,所以我们在采集日志时用filebeat,然后交给logstash过滤筛选。
?其次,logstash的吞吐量是有限的,一旦短时间内filebeat传过来的日志过多会产生堆积和堵塞,对日志的采集也会受到影响,所以在filebeat与logstash中间又加了一层kafka消息队列来缓存或者说解耦,当然redis也是可以的。这样当众多filebeat节点采集大量日志直接放到kafka/redis中,logstash慢慢的进行消费,两边互不干扰。
说明:
? WEB服务日志代表收集的对象,由Filebeat收集日志后发送至Redis消息队列,然后Logstash将Redis中的数据拿出来由ElasticSearch收集处理并由Kibana进行可视化显示。(在生产中可以将各个功能单点进行扩展,例如将Redis和Logstash集群化。)
1.修改主机名
[root@localhost ~]# echo es-master21 > /etc/hostname //永久修改主机名(重启生效),临时修改可以直接hostname es-master21,重新打开远程终端即可[root@localhost ~]# echo es-node22 > /etc/hostname[root@localhost ~]# echo es-node23 > /etc/hostname
2.关闭防火墙及selinux
[root@es-master21/es-node22/23 ~]# systemctl stop firewalld && systemctl disable firewalld[root@es-master21/es-node22/23 ~]# setenforce 0 //临时关闭[root@es-master21/es-node22/23 ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config //永久关闭
3.配置主机名解析
[root@es-master21/es-node22/23 ~]# cat >> /etc/hosts << EOF> 192.168.1.21 es-master21> 192.168.1.22 es-node22> 192.168.1.23 es-node23> EOF[root@es-master21/es-node22/23 ~]# cat /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1 localhost localhost.localdomain localhost6 localhost6.localdomain6192.168.1.21 es-master21192.168.1.22 es-node22192.168.1.23 es-node23
4.系统参数优化
[root@es-master21 ~]# cat >> /etc/security/limits.conf << EOF> * soft nofile 65536> * hard nofile 131072> * soft nproc 2048> * hard nproc 4096> EOF[root@es-master21 ~]# for i in {22..23}> do> scp /etc/security/limits.conf root@192.168.1.$i:/etc/security/> done-----------------------------------------[root@es-master21 ~]# vim /etc/sysctl.confvm.max_map_count=655360[root@es-master21 ~]# for i in {22..23}> do> scp /etc/sysctl.conf root@192.168.1.$i:/etc/> done[root@es-node22/23 ~]# cat /etc/sysctl.conf //优化内核,对es支持vm.max_map_count=655360[root@es-node22/23 ~]# sysctl -p //使配置生效vm.max_map_count = 655360-----------------------------------------[root@es-master21 ~]# vim /etc/security/limits.d/20-nproc.conf //设置普通用户最大打开进程数为65535(默认root用户打开进程数不限制,普通用户最大打开进程数4096)* soft nproc 65535* hard nproc 65535root soft nproc unlimited[root@es-master21 ~]# for i in {22..23}> do> scp /etc/security/limits.d/20-nproc.conf root@192.168.1.$i:/etc/security/limits.d/> done[root@es-node22/23 ~]# cat /etc/security/limits.d/20-nproc.conf* soft nproc 65535* hard nproc 65535root soft nproc unlimited[root@es-master21 ~]# ulimit -u //查询用户最大可用的进程数65535
5.安装docker和docker compose
? 一文搞懂Docker与Docker Engine的安装
? 一文学会配置Docker 国内镜像加速器
? 一文学会Docker Compose安装
#查看docker安装后版本[root@es-master21/es-node22/23 ~]# docker versionClient: Docker Engine - Community Version: 20.10.11 API version: 1.41 Go version: go1.16.9 Git commit: dea9396 Built: Thu Nov 18 00:38:53 2021 OS/Arch: linux/amd64 Context: default......#配置镜像加速器与修改docker默认存储路径[root@es-master21/es-node22/23 ~]# cat /etc/docker/daemon.json{"registry-mirrors": [""],"graph": "/mnt/data" //修改docker默认存储路径}[root@es-master21/es-node22/23 ~]# docker info......Docker Root Dir: /mnt/data //docker存储路径已修改 Debug Mode: false Registry: Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Registry Mirrors: //镜像加速器地址 Live Restore Enabled: false#安装docker compose[root@es-master21/es-node22/23 ~]# curl -L `uname -s`-`uname -m` > /usr/local/bin/docker-compose[root@es-master21/es-node22/23 ~]# chmod +x /usr/local/bin/docker-compose[root@es-master21/es-node22/23 ~]# docker-compose versiondocker-compose version 1.25.4, build 8d51620adocker-py version: 4.1.0CPython version: 3.7.5OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019
----->这此以上的环境配置安装步骤所有主机都需要做!!!
6.下载各个服务的镜像
[root@es-master21/es-node22/23 ~]# docker pull elasticsearch:7.10.1[root@es-master21 ~]# docker pull kibana:7.10.1[root@es-master21 ~]# docker pull redis:latest[root@es-master21 ~]# docker pull mobz/elasticsearch-head:5[root@es-master21 ~]# docker pull logstash:7.10.1[root@es-master21 ~]# docker pull store/elastic/filebeat:7.10.1二、搭建Elasisearch集群
1.宿主机es-master21操作
[root@es-master21 ~]# mkdir -p /mnt/elasticsearch/data[root@es-master21 ~]# cd /mnt/[root@es-master21 mnt]# vim docker-compose.yml (使用时删除配置文件中所有的#注释信息,否则可能格式报错)version: '2.2' services: elasticsearch: #服务名称 image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1 #使用的镜像及版本 container_name: elasticsearch #容器名称 restart: always #失败自动重启策略 environment: - cluster.name=myes-cluster #集群名称,相同名称为一个集群,三个es节点必须一致。 - node.name=es01 #节点名称,集群模式下每个节点名称唯一 - network.publish_host=192.168.1.21 #用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP。 - discovery.seed_hosts=192.168.1.21,192.168.1.22,192.168.1.23 #写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点。 - cluster.initial_master_nodes=192.168.1.21,192.168.1.22,192.168.1.23 #初始化一个新的集群时需要此配置来选举master - bootstrap.memory_lock=true #内存交换的选项,官网建议设置为true。 ulimits: #栈内存的上限 memlock: soft: -1 #不限制 hard: -1 #不限制 volumes: - /mnt/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml #将容器中es的配置文件映射到本地 - /mnt/elasticsearch/data:/usr/share/elasticsearch/data #将es容器内存放数据路径映射到本地 ports: - 9200:9200 #http端口,可以直接浏览器访问。 - 9300:9300 #es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。 elasticsearch-head: #elasticsearch可视化插件 image: mobz/elasticsearch-head:5 container_name: elasticsearch-head restart: always ports: - 9100:9100 #http端口,可以直接浏览器访问。----->编写elasticsearch.yml文件<----- ||[root@es-master21 ~]# cd /mnt/elasticsearch[root@es-master21 elasticsearch]# vim elasticsearch.ymlcluster.name: "myes-cluster" #es集群名称,相同名称为一个集群,三个es节点必须一致network.host: 0.0.0.0 #设置服务绑定的IP地址,0.0.0.0表示所有地址http.cors.enabled: true #是否支持跨域http.cors.allow-origin: "*" #表示支持所有域名[root@es-master21 mnt]# docker-compose -f docker-compose.yml up -d #启动elasticsearch集群节点[root@es-master21 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcpelasticsearch-head /bin/sh -c grunt server Up 0.0.0.0:9100->9100/tcp,:::9100->9100/tcp
2.宿主机es-node22操作
[root@es-node22 ~]# mkdir -p /mnt/elasticsearch/data[root@es-node22 ~]# cd /mnt/[root@es-node22 mnt]# vim docker-compose.ymlversion: '2.2'services: elasticsearch: #服务名称 image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1 #使用的镜像及版本 container_name: elasticsearsh #容器名称 restart: always #失败自动重启策略 environment: - cluster.name=myes-cluster #集群名称,相同名称为一个集群,三个es节点必须一致 - node.name=es02 #节点名称。集群模式下每个节点名称唯一 - network.publish_host=192.168.1.22 #用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP。 - discovery.seed_hosts=192.168.1.21,192.168.1.22,192.168.1.23 #写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点 - cluster.initial_master_nodes=192.168.1.21,192.168.1.22,192.168.1.23 #初始化一个新的集群时需要此配置来选举master - bootstrap.memory_lock=true #内存交换的选项,官网建议为true。 ulimits: #栈内存的上限 memlock: soft: -1 #不限制 hard: -1 #不限制 volumes: - /mnt/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml #将容器中es的配置文件映射到本地 - /mnt/elasticsearch/data:/usr/share/elasticsearch/data #将es容器内存放数据路径映射到本地 ports: - 9200:9200 #http端口,可以直接浏览器访问 - 9300:9300 #es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。----->编写elasticsearch.yml文件<----- ||[root@es-node22 ~]# cd /mnt/elasticsearch[root@es-node22 elasticsearch]# vim elasticsearch.ymlcluster.name: "myes-cluster" #es集群名称,相同名称为一个集群,三个es节点必须一致。network.host: 0.0.0.0 #设置服务绑定的IP地址,0.0.0.0表示所有地址http.cors.enabled: true #是否支持跨域http.cors.allow-origin: "*" #表示支持所有域名[root@es-node22 mnt]# docker-compose -f docker-compose.yml up -d #启动elasticsearch集群节点[root@es-node22 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcp
3.宿主机es-node23操作
[root@es-node23 ~]# mkdir -p /mnt/elasticsearch/data[root@es-node23 ~]# cd /mnt/[root@es-node23 mnt]# vim docker-compose.ymlversion: '2.2'services: elasticsearch: #服务名称 image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1 #使用的镜像及版本 container_name: elasticsearsh #容器名称 restart: always #失败自动重启策略 environment: - cluster.name=myes-cluster #集群名称,相同名称为一个集群,三个es节点必须一致 - node.name=es03 #节点名称。集群模式下每个节点名称唯一 - network.publish_host=192.168.1.23 #用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP。 - discovery.seed_hosts=192.168.1.21,192.168.1.22,192.168.1.23 #写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点 - cluster.initial_master_nodes=192.168.1.21,192.168.1.22,192.168.1.23 #初始化一个新的集群时需要此配置来选举master - bootstrap.memory_lock=true #内存交换的选项,官网建议为true hostname: elasticsearch #服务hostname ulimits: #栈内存的上限 memlock: soft: -1 #不限制 hard: -1 #不限制 volumes: - /mnt/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml #将容器中es的配置文件映射到本地 - /mnt/elasticsearch/data:/usr/share/elasticsearch/data #将es容器内存放数据路径映射到本地 ports: - 9200:9200 #http端口,可以直接浏览器访问。 - 9300:9300 #es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。----->编写elasticsearch.yml文件<----- ||[root@es-node23 ~]# cd /mnt/elasticsearch[root@es-node23 elasticsearch]# vim elasticsearch.ymlcluster.name: "myes-cluster" #es集群名称,相同名称为一个集群,三个es节点必须一致network.host: 0.0.0.0 #设置服务绑定的IP地址,0.0.0.0表示所有地址http.cors.enabled: true #是否支持跨域http.cors.allow-origin: "*" #表示支持所有域名[root@es-node23 mnt]# docker-compose -f docker-compose.yml up -d #启动elasticsearch集群节点(执行此命令要在docker-compose.yml文件路径下执行)[root@es-node23 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcp`访问Elasticsearch集群` 三、搭建Filebeat
宿主机es-master21操作
注意:
? Filebeat要采集的日志目录必须挂载至Filebeat容器中,不然可能无法正常采集。
---Nginx日志---[root@es-master21 ~]# ll -h /var/log/nginx/总用量 69M-rwxr-xr-x. 1 root root 68M 12月 13 15:15 access.log-rwxr-xr-x. 1 root root 1.8M 12月 7 23:09 error.log[root@es-master21 ~]# mkdir -p /mnt/filebeat/[root@es-master21 ~]# cd /mnt/[root@es-master21 mnt]# vim docker-compose.yml ...... ...... filebeat: image: store/elastic/filebeat:7.10.1 #镜像依然选择与elk的版本一致 container_name: filebeat restart: always volumes: - /var/log/nginx/:/var/log/nginx #filebeat需要采集的nginx日志目录(必须要挂载至容器中) - /mnt/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro #filebeat的配置文件 - /etc/localtime:/etc/localtime----->编写filebeat.yml文件<----- ||[root@es-master21 mnt]# cd filebeat/[root@es-master21 filebeat]# vim filebeat.yml (使用时删除文件中带#的配置项,不然yml文件格式不对) filebeat.inputs: #inputs为复数,表名type可以有多个#- type: log #输入类型# access:# enabled: true #启用这个type配置# max_bytes: 20480 #单条日志的大小限制,建议限制(默认为10M,queue.mem.events * max_bytes 将是占有内存的一部分)# paths:# - /var/log/nginx/access.log #监控nginx的access日志,建议采集日志时先采集单一nginx的access日志。# close_rename: true #重命名后,文件将不会继续被采集信息# tail_files: true #配置为true时,filebeat将从新文件的最后位置开始读取,如果配合日志轮循使用,新文件的第一行将被跳过# fields: #额外的字段(表示在filebeat收集Nginx的日志中多增加一个字段source,其值是nginx-access-21,用来在logstash的output输出到elasticsearch中判断日志的来源,从而建立相应的索引,也方便后期再Kibana中查看筛选数据,结尾有图) # source: nginx-access-21 - type: log access: enabled: true paths: - /var/log/nginx/error.log fields: source: nginx-error-21 #额外的字段(表示在filebeat收集Nginx的日志中多增加一个字段source,其值是nginx-error-21,用来在logstash的output输出到elasticsearch中判断日志的来源,从而建立相应的索引,也方便后期再Kibana中查看筛选数据,结尾有图)setup.ilm.enabled: falseoutput.redis: #输出到redis hosts: ["192.168.1.21:6379"] #redis地址及端口 password: "123456" #redis密码 db: 0 #redis的库 key: "nginx_log" #定义输入到redis的key名[root@es-node22 mnt]# docker-compose -f docker-compose.yml up -d[root@es-master21 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcpelasticsearch-head /bin/sh -c grunt server Up 0.0.0.0:9100->9100/tcp,:::9100->9100/tcpfilebeat /usr/local/bin/docker-entr ... Up
注意:
? 不同的应用日志使用不同的redis的key值,使用output.redis中的keys值,官方例子:
output.redis: hosts: ["localhost"] key: "default_list" keys: - key: "error_list" #如果“message”字段包含error,则发送到error_list when.contains: message: "error" - key: "debug_list" #如果“message”字段包含debug,则发送到debug_list when.contains: message: "DEBUG" - key: "%{[fields.list]}"
? 说明:默认的key值是default_list,keys的值是动态分配创建的,当redis接收到的日志中message字段的值包含有error字段,则创建key为error_list,当包含有DEBUG字段,则创建key为debug_list。 ? 问题的解决方法是在每个应用的输出日志中新增一个能够区分这个日志的值,然后再在keys中设置,这样一来就能够把不同应用的日志输出到不同的redis的key中。
四、搭建Redis宿主机es-master21操作
[root@es-master21 ~]# mkdir -p /mnt/redis/data[root@es-master21 ~]# mkdir -p /mnt/redis/conf[root@es-master21 ~]# mkdir -p /mnt/redis/log[root@es-master21 ~]# cd /mnt/[root@es-master21 mnt]# vim docker-compose.yml............ redis: image: redis restart: always container_name: redis environment: - TZ=Asia/Shanghai ports: - 6379:6379 volumes: - /mnt/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf - /mnt/redis/data/:/data - /mnt/redis/log/redis.log:/var/log/redis/redis.log command: ["redis-server","/usr/local/etc/redis/redis.conf"]----->编写redis.conf文件<----- ||[root@es-master21 mnt]# vim redis/conf/redis.confbind 0.0.0.0port 6379requirepass 123456save ""pidfile /var/run/redis/redis.pid#logfile /var/log/redis/redis.log[root@es-master21 mnt]# docker-compose -f docker-compose.yml up -d[root@es-master21 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcpelasticsearch-head /bin/sh -c grunt server Up 0.0.0.0:9100->9100/tcp,:::9100->9100/tcpfilebeat /usr/local/bin/docker-entr ... Uplogstash /usr/local/bin/docker-entr ... Up 0.0.0.0:5044->5044/tcp,:::5044->5044/tcp, 9600/tcpredis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp,:::6379->6379/tcp查看Redis中由Filebeat采集后写进来的nginx日志数据
[root@es-master21 mnt]# docker exec -it redis bashroot@d5a4be90c7f6:/# redis-cli -h 192.168.1.21192.168.1.21:6379> AUTH 123456OK192.168.1.21:6379> SELECT 0OK192.168.1.21:6379> KEYS * #创建的key为nginx_log1) "nginx_log"192.168.1.21:6379> LLEN nginx_log(integer) 7167 #可以看到redis的nginx_log中有7167条数据未被消费五、搭建Logstash
宿主机es-master21操作
[root@es-master21 ~]# mkdir -p /mnt/logstash/data[root@es-master21 ~]# mkdir -p /mnt/logstash/config[root@es-master21 ~]# cd /mnt/[root@es-master21 mnt]# vim docker-compose.yml............ logstash: image: docker.elastic.co/logstash/logstash:7.10.1 container_name: logstash hostname: logstash restart: always environment: TZ: "Asia/Shanghai" ports: - 5044:5044 volumes: - /mnt/logstash/config/logstash.conf:/usr/share/logstash/conf.d/logstash.conf - /mnt/logstash/logstash.yml:/usr/share/logstash/config/logstash.yml - /mnt/logstash/data:/usr/share/logstash/data - /etc/localtime:/etc/localtime depends_on: - elasticsearch #依赖es服务,必须先启动es才会启动logstash----->编写logstash.yml与logstash.conf文件<----- ||[root@es-master21 mnt]# cd logstash/[root@es-master21 logstash]# vim logstash.ymlhttp.host: "0.0.0.0"path.config: /usr/share/logstash/conf.d/*.confpath.logs: /var/log/logstashxpack.monitoring.enabled: true #默认情况下logstash禁用监控,设置为true以启用X-Pack监控。xpack.monitoring.elasticsearch.hosts: ["192.168.1.21:9200","192.168.1.22:9200","192.168.1.23:9200"] #为es服务器列表以及端口号,用于将数据存储到es#pipeline.batch.size: 3000 #指发送到Elasticsearch的批量请求的大小,值越大,处理则通常更高效,但增加了内存开销#pipeline.batch.delay: 200 #指调整Logstash管道的延迟,过了该时间则logstash开始执行过滤器和输出[root@es-master21 logstash]# vim config/logstash.conf (使用时删除文件中带#的配置项,不然yml文件格式不对)input { redis { port => "6379" host => "192.168.1.21" password => "123456" data_type => "list" db => "0" key => "nginx_log" }}output { elasticsearch { hosts => [":9200",":9200",":9200"] } stdout { codec => rubydebug }}[root@es-node22 mnt]# docker-compose -f docker-compose.yml up -d[root@es-master21 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcpelasticsearch-head /bin/sh -c grunt server Up 0.0.0.0:9100->9100/tcp,:::9100->9100/tcpfilebeat /usr/local/bin/docker-entr ... Uplogstash /usr/local/bin/docker-entr ... Up 0.0.0.0:5044->5044/tcp,:::5044->5044/tcp, 9600/tcp查看Logstash日志,输出从Redis消费并处理的日志数据
[root@es-master21 mnt]# docker-compose logs -f logstash......logstash | "message" => "2021/10/23 01:06:00 [alert] 27214#0: *357982 write() to \"/usr/local/nginx/logs/access.log\" client: 209.14.12.185, server: localhost, request: \"GET /config/getuser?index=0 HTTP/1.1\", host: \"39.98.155.11:80\""logstash | }logstash | {logstash | "log" => {logstash | "file" => {logstash | "path" => "/var/log/nginx/error.log"logstash | },logstash | "offset" => 1863165logstash | },logstash | "@timestamp" => 2021-12-27T09:22:37.192Z,logstash | "host" => {logstash | "name" => "7fddb131a96b"logstash | },logstash | "fields" => {logstash | "source" => "nginx-error-21"logstash | },logstash | "@version" => "1",logstash | "input" => {logstash | "type" => "log"logstash | },logstash | "ecs" => {logstash | "version" => "1.6.0"logstash | },logstash | "agent" => {logstash | "hostname" => "7fddb131a96b",logstash | "version" => "7.10.1",logstash | "name" => "7fddb131a96b",logstash | "id" => "95b7e319-228c-4eed-b9c8-26fad0c59d3b",logstash | "type" => "filebeat",logstash | "ephemeral_id" => "76ec6bc4-39e9-4364-94fb-20f0a7f49122"logstash | },logstash | "message" => "2021/10/23 01:29:28 [alert] 27216#0: *357983 write() to \"/usr/local/nginx/logs/access.log\" failed (28: No space left on device) while logging request, client: 83.25.20.34, server: localhost, request: \"GET / HTTP/1.1\", host: \"39.98.155.11\""logstash | }logstash | {logstash | "log" => {logstash | "file" => {logstash | "path" => "/var/log/nginx/error.log"logstash | },logstash | "offset" => 1863404logstash | },logstash | "@timestamp" => 2021-12-27T09:22:37.192Z,logstash | "fields" => {logstash | "source" => "nginx-error-21"logstash | },logstash | "host" => {logstash | "name" => "7fddb131a96b"logstash | },logstash | "@version" => "1",logstash | "input" => {logstash | "type" => "log"logstash | },logstash | "ecs" => {logstash | "version" => "1.6.0"logstash | },logstash | "agent" => {logstash | "hostname" => "7fddb131a96b",logstash | "version" => "7.10.1",logstash | "name" => "7fddb131a96b",logstash | "id" => "95b7e319-228c-4eed-b9c8-26fad0c59d3b",logstash | "type" => "filebeat",logstash | "ephemeral_id" => "76ec6bc4-39e9-4364-94fb-20f0a7f49122"logstash | },logstash | "message" => "2021/10/23 01:36:39 [alert] 27214#0: *357985 write() to \"/usr/local/nginx/logs/access.log\" client: 119.108.53.121, server: localhost, request: \"GET / HTTP/1.1\", host: \"saas.weizujikeji.com\""查看Elasticsearch集群中是否有日志数据写入 六、搭建Kibana
宿主机es-master21操作
[root@es-master21 ~]# mkdir -p /mnt/kibana/config[root@es-master21 ~]# mkdir -p /mnt/kibana/data[root@es-master21 ~]# mkdir -p /mnt/kibana/plugins[root@es-master21 ~]# cd /mnt/[root@es-node23 mnt]# vim docker-compose.yml ...... ...... kibana: image: kibana:7.10.1 container_name: kibana environment: - elasticsearch.hosts=:9200 - TZ=Asia/Shanghai hostname: kibana depends_on: - elasticsearch #依赖es服务,必须先启动es才会启动kibana restart: always ports: - 5601:5601 volumes: - /mnt/kibana/config:/usr/share/kibana/config - /mnt/kibana/data:/usr/share/kibana/data - /mnt/kibana/plugins:/usr/share/kibana/plugins----->编写kibana.yml文件<----- ||[root@es-node23 mnt]# cd kibana/[root@es-node23 kibana]# vim config/kibana.ymlserver.name: kibana #Kibana实例对外展示的名称server.host: "0.0.0.0" #指定后端服务器的主机地址,0.0.0.0代表全部地址elasticsearch.hosts: [":9200",":9200",":9200"] #设置连接的es节点monitoring.ui.container.elasticsearch.enabled: truei18n.locale: "zh-CN" #kibana6.7以后支持配置中文汉化[root@es-master21 mnt]# docker-compose -f docker-compose.yml up -d[root@es-master21 mnt]# docker-compose ps Name Command State Ports---------------------------------------------------------------------------------------------------------elasticsearch /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 0.0.0.0:9300->9300/tcp,:::9300->9300/tcpelasticsearch-head /bin/sh -c grunt server Up 0.0.0.0:9100->9100/tcp,:::9100->9100/tcpfilebeat /usr/local/bin/docker-entr ... Upkibana /usr/local/bin/dumb-init - ... Up 0.0.0.0:5601->5601/tcp,:::5601->5601/tcplogstash /usr/local/bin/docker-entr ... Up 0.0.0.0:5044->5044/tcp,:::5044->5044/tcp, 9600/tcpredis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp,:::6379->6379/tcp访问Kibana并创建索引模式,展示ES中的Nginx日志数据 如果您喜欢本文,就请动动您的发财手为本文点赞评论转发,让我们一起学习更多运维相关知识,最后请记得关注我。