近期发现 prometheus 出现 discovery=file msg="Error adding file watcher" err="too many open files"
的告警。且更新prometheus json 文件后,不能及时的刷新,需要等待很久。
报错信息如下:
通过观察报错,字面意思是 open files
打开的太多了,于是检查 open files
的设定。
|
|
通过检查发现,open files
设定正确,但仍未解决问题。
通过查找资料发现,是因为fs.inotify.max_user_instances
默认值设定太小导致的。表示每一个real user ID
可创建的inotify instatnces
的数量上限,默认128
。
|
|
问题解决
参考:
https://blog.csdn.net/weiguang1017/article/details/54381439
https://groups.google.com/forum/#!topic/prometheus-users/OQzEYeggnpw
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/11/27/解决Prometheus too many open files问题/
]]>MinIO 是一个高性能的对象存储,原生支持 Kubernetes 部署的解决方案。 MinIO也提供了一个 Amazon Web Services S3 兼容 API 并支持所有核心 S3 功能。
部署Minio
授权
minio配置文件
minio-server启动配置文件
启动minio-server
配置haproxy
设置MinIO Client(mc)
登陆Minio Server的服务器
访问minio-Server Web
http://ip:9800/minio/login
账号密码为,在minio.env配置文件里设置的MINIO_ROOT_USER
和MINIO_ROOT_PASSWORD
的值
MinIO Console
→ Access
→ Create Policy
→ Write Policy
意思是,只能控制test bucket
Minio旧版本Binary下载地址:https://dl.min.io/server/minio/release/linux-amd64/archive/
官网:http://www.minio.org.cn/download.shtml#/linux
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/11/07/部署文件不切片的Minio-Server/
]]>版更后, Grafana 无法正常展示 Prometheus 资料。
稍微拉长 Grafana 时间轴,Grafana 会显示 query processing would load too many samples into memory in query execution.
报错信息。
因版更后, 可能因业务改变而导致prometheus metric
突增。但 Grafana 拉取的数据超过了 Prometheus 限制。 通过查找资源和翻阅 Prometheus GitHub 发现。由于PromQL语句可能会载入大量的 metrics 数据,导致 Prometheus 内存以及 CPU 消耗超标,为了保护 Prometheus 不会被复杂的 PromQL 查询吃掉过多的资源,Prometheus 作者在代码层面设置了限制。在 Prometheus 2.5.0 版本后,Prometheus 新增可以通过–query.max-samples参数来调整限制,满足更多的业务需求。
Prometheus 2.5.0 GitHub 特性说明:
地址:https://github.com/prometheus/prometheus/releases/tag/v2.5.0
Issue 地址:https://github.com/prometheus/prometheus/pull/4513
因 GS prometheus
在迁移时升级过 Prometheus
版本,故需要查阅对应版本的 Prometheus
源码来了解 Prometheus 默认限制大小。
Prometheus 源码地址:https://github.com/prometheus/prometheus/blob/v2.15.2/cmd/prometheus/main.go
通过 Prometheus 源码可知,Prometheus 默认的最大查询上限为:50000000
。因 GS Grafana 图查询次数超过 Prometheus 限制,所以,我们需要通过参数来调整上线大小。
参数说明:
经过沟通,目前使用的 Gs prometheus 启动参数为:
参考文档:
http://blog.kankanan.com/article/query-processing-would-load-too-many-samples-into-memory-in-query-execution.html
https://github.com/prometheus/prometheus/blob/v2.15.2/cmd/prometheus/main.go
https://github.com/prometheus/prometheus/releases/tag/v2.5.0
https://github.com/prometheus/prometheus/pull/4513
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/10/27/解决Grafana query processing would load too many samples into memory in query exec/
]]>sentinel是一个管理redis实例的工具,它可以实现对redis的监控、通知、自动故障转移。sentinel不断的检测redis实例是否可以正常工作,通过API向其他程序报告redis的状态,如果redis master不能工作,则会自动启动故障转移进程,将其中的一个slave提升为master,其他的slave重新设置新的master服务器。
Redis Sentinel是一个分布式架构,包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当发现节点不可达时,会对节点做下线标识.
如果被标识的是主节点,他还会选择和其他Sentinel节点进行“协商”,当大多数的Sentinel节点都认为主节点不可达时,他们会选举出一个Sentinel节点来完成自动故障转移工作,同时将这个变化通知给Redis应用方.
整个过程完全自动,不需要人工介入,所以可以很好解决Redis的高可用问题.
redis主从复制
Redis主从复制可将主节点数据同步给从节点,从节点此时有两个作用:
Redis Sentinel有以下几个功能:
环境:
Centos 7.9.2009
Redis version:5.0.13
分别有3个Sentinel节点,1个主节点,2个从节点组成一个Redis Sentinel
| hostname | ip | redis port | sentinel port |
| — | — | — | — |
| node1 | 10.21.248.7 | 16379 | 26379 |
| node2 | 10.21.248.179 | 16379 | 26379 |
| node3 | 10.21.108.47 | 16379 | 26379 |
|
|
|
|
Node1 Sentinel配置
注意:sentinel myid每个节点都要唯一
Node1 启动脚本
从节点需新增replicaof masterip 配置
Node2 Sentinel配置
注意:sentinel myid每个节点都要唯一
Node2 启动脚本
从节点需新增replicaof masterip 配置
Node3 Sentinel配置
注意:sentinel myid每个节点都要唯一
Node3 启动脚本
|
|
查看Redis Sentinel日志
任意登陆一个节点的Redis Sentinel,可查看Redis Sentinel状态
|
|
node2的sentinel日志
启动旧redis master,则自动以从节点的身份加入到redis sentinel
关机/重启命令略
node3 sentinel日志
启动旧redis master,则自动以从节点的身份加入到redis sentinel
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/08/27/Redis-Sentinel/
]]>NSQ是一个基于Go语言的分布式实时消息队列中间件,它基于MIT开源协议发布,由bitly公司开源出来的一款简单易用的消息中间件,它有以下特点:
NSQ由以下3种守护进程组成:
下载解压NSQ
supervisor部署
nsq1
nsq2
nsqlookup1
nsqlookup2
nsqadmin
启动服务
访问Nsqadmin
http://ip:port:4171
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/05/07/部署nsq/
]]>Centos 7.4
Docker version 18.09.0
|
|
拉取容器镜像
启动容器
查看容器状态
好干净哇…!
我们先准备一个测试页面
当我们遇到这个问题时,是Prometheus所在的宿主机时间不对,我们需要先同步时间
prometheus默认监控了自己的9100端口
编写prometheus.yml配置文件
这里使用的是自己封装的镜像,因官方镜像不支持通过API来重新加载Prometheus配置文件,试想一下,如果每次修改了配置文件,都需要重启Prometheus,是不是有点那啥..
正确添加Prometheus配置文件后,我们可以查看到监控的key.
这里也使用的是自己封装的镜像,原因同上。
添加Prometheus的DataSource
安装grafana常用插件,绘制图标。
grafana插件安装完成后需要重启服务
绘制完成后的Prometheus监控面板
这里监控2个,分别是密码文件修改监控和网站探测
url测试
|
|
定义value为0,正常;value为1,触发告警
这里出现重复告警,是因为测试环境只有一台,通过JOB看出Prometheus重复监控了
附件:
Grafana_templates.tar.gz
check_md5.zip
check_http.zip
check_code.zip
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/04/22/Prometheus监控docker/
]]>Grafana 是 Graphite 和 InfluxDB 仪表盘和图形编辑器。
Grafana 是开源的,功能齐全的度量仪表盘和图形编辑器,支持 Graphite,InfluxDB 和 OpenTSDB。
Grafana 主要特性:灵活丰富的图形化选项;可以混合多种风格;支持白天和夜间模式;多个数据源;Graphite 和 InfluxDB 查询编辑器等。
Prometheus采取到k8s集群的监控数据后,由于Prometheus自带的展示图形不太友好,故我们需要选择更加强大的图形展示工具。Prometheus的时区是UTC +0且不支持修改,而Grafana可以选择时区
Grafana官网:https://grafana.com/
|
|
|
|
访问 http://192.168.1.198:3000 打开Grafana WEB界面
添加数据源
Add Data Source添加数据源
这里是编辑 influxdb-datasource
执行kubectl get svc --all-namespaces -o wide | grep -i influxdb
可以获取influxdb的cluster-ip和Port
添加Grafana的Prometheus数据源
数据源Type选择Prometheus
执行kubectl get pod --all-namespaces -o wide | grep -i prometheus
可以获取Prometheus的ip
添加Dashboard
Grafana官方有个Prometheus模板,参考:https://grafana.com/dashboards/162 ,可以把它导入到Grafana
把下载的kubernetes-pod-monitoring_rev1.json 导入到Grafana
上传json文件并选择数据源
导入成功。下图为模板默认监控数据,具体需要根据实际情况修改
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2022/01/14/Grafana展示Prometheus数据/
]]>prometheus从根本上存储的所有数据都是时间序列: 具有时间戳的数据流只属于单个度量指标和该度量指标下的多个标签维度。除了存储时间序列数据外,Prometheus也可以利用查询表达式存储5分钟的返回结果中的时间序列数据。
Prometheus提供一个函数式的表达式语言,可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源, 以HTTP API的方式提供给外部系统使用。
在Prometheus的表达式语言中,任何表达式或者子表达式都可以归为四种类型:
container_cpu_usage_seconds_total
选择了具有container_cpu_usage_seconds_total
的时间序列 查询pod (nginx-deployment-d8d99448f-h6585)聚合一分钟之内的cpu 负载
|
|
等于
container_cpu_usage_seconds_total
:容器CPU每秒使用总和,是一个时间序列名称。 {}
:即时矢量选择器。允许在给定的时间戳(即时)中为每个时间序列和每个样本值选择一组时间序列:比如仅指定度量标准名称。这将产生包含具有此度量标准名称的所有时间序列的元素的即时矢量。即时矢量选择器参考 {image!="",container_name!="POD",pod_name="kubernetes-dashboard-666fbbf977-v9vsh"}
都是时间序列container_cpu_usage_seconds_total
的标签。其中image
是名称标签,container_name
是工作标签,pod_name
是组标签。 image!=""
:是时间序列container_cpu_usage_seconds_total
的名称标签,意思是image不为空。container_name!="POD"
意思同上,container_name不等于POD。pod_name="kubernetes-dashboard-666fbbf977-v9vsh"
意思同上,意思是pod_name等于kubernetes-dashboard-666fbbf977-v9vsh。匹配操作符参考 [1m]
:范围矢量选择器。在语法上,范围持续时间会附在矢量选择器末尾的[]
内,意思是为每个结果范围矢量元素提取多久的时间值。范围矢量选择器参考
我们可以通过Prometheus的UI界面查询到该containername的具体信息,如下:
随便输入一个时间序列值,Prometheus默认会列出当前K8s里所有的监控信息,然后ctrl+F搜索
![prometheus时间序列](https://note.youdao.com/yws/api/personal/file/F458416FAFC341B0BBDCD5D0C29DE7DE?method=download&shareKey=ab0ca193e6ec09a12f3cf779e2d43da3)
下面两个监控指标获取的监控目标相同
[]
来表示时间范围,持续时间用数字表示,后接下面单元之一:s
- seconds m
- minutes h
- hours d
- days w
- weeks y
- years 见上面例子,范围矢量选择器参考
以下表达式返回container_cpu_usage_seconds_total在一天前5分钟内的速率
4.1. 二元操作符
Prometheus的查询语言支持基本的逻辑运算和算术运算。对于两个瞬时向量, 匹配行为可以被改变
4.2. 算术二元运算符
+
加法 -
减法 *
乘法 /
除法 %
模 ^
幂等 二元运算操作符支持scalar/scalar(标量/标量)
、vector/scalar(向量/标量)
、和vector/vector(向量/向量)
之间的操作
在两个标量之间进行操作符运算,得到的结果也是标量
在向量和标量之间,这个操作符会作用于这个向量的每个样本值上。例如:如果一个时间序列瞬时向量除以2,操作结果也是一个新的瞬时向量,且度量指标名称不变, 它是原度量指标瞬时向量的每个样本值除以2
在两个向量之间,一个二元算术操作符作用在左边瞬时向量的每个样本值,且该样本值与操作符右边能匹配上的样本值计算,向量匹配。结果写入到一个没有度量指标名称的瞬时向量
4.3. 比较二元操作符
在Prometheus系统中,比较二元操作符有:
==
等于 !=
不等于 >
大于 <
小于 >=
大于等于 <=
小于等于 比较二元操作符被应用于scalar/scalar(标量/标量)
、vector/scalar(向量/标量)
,和vector/vector(向量/向量)
。比较操作符得到的结果是bool
布尔类型值,返回1
或者0
值。
在两个标量之间的比较运算,bool结果写入到另一个结果标量中。
瞬时向量和标量之间的比较运算,这个操作符会应用到某个当前时刻的每个时间序列数据上,如果一个时间序列数据值与这个标量比较结果是false,则这个时间序列数据被丢弃掉,如果是true, 则这个时间序列数据被保留在结果中。
在两个瞬时向量之间的比较运算,左边度量指标数据中的每个时间序列数据,与右边度量指标中的每个时间序列数据匹配,没有匹配上的,或者计算结果为false的,都被丢弃,不在结果中显示。否则将保留左边的度量指标和标签的样本数据写入瞬时向量。
4.4. 逻辑/集合二元操作符逻辑/集合
二元操作符只能作用在即时向量
, 包括:
and
交集 or
并集 unless
补集 vector1 and vector2
的逻辑/集合二元操作符,规则:vector1瞬时向量中的每个样本数据与vector2向量中的所有样本数据进行标签匹配,不匹配的,全部丢弃。运算结果是保留左边的度量指标名称和值。vector1 or vector2
的逻辑/集合二元操作符,规则: 保留vector1向量中的每一个元素,对于vector2向量元素,则不匹配vector1向量的任何元素,则追加到结果元素中。vector1 unless vector2
的逻辑/集合二元操作符,又称差积。规则:包含在vector1中的元素,但是该元素不在vector2向量所有元素列表中,则写入到结果集中。
vector1 [operate] vector2
。如果它们有相同的标签和值,则表示相匹配。ingoring
关键字是指,向量匹配时,可以忽略指定标签。on
关键字是指,在指定标签上进行匹配。格式如下所示:sum
(在维度上求和) max
(在维度上求最大值) min
(在维度上求最小值) avg
(在维度上求平均值) stddev
(求标准差) stdvar
(求方差) count
(统计向量元素的个数) count_values
(统计相同数据值的元素数量) bottomk
(样本值第k个最小值) topk
(样本值第k个最大值) quantile
(统计分位数) 这些操作符被用于聚合所有标签维度,或者通过without或者by子句来保留不同的维度。
parameter只能用于count_values
, quantile
, topk
和bottomk
。without
移除结果向量中的标签集合,其他标签被保留输出。by
关键字的作用正好相反,即使它们的标签值在向量的所有元素之间。keep_common
子句允许保留额外的标签(在元素之间相同,但不在by子句中的标签)
count_values
对每个唯一的样本值输出一个时间序列。每个时间序列都附加一个标签。这个标签的名字有聚合参数指定,同时这个标签值是唯一的样本值。每一个时间序列值是结果样本值出现的次数。topk
和bottomk
与其他输入样本子集聚合不同,返回的结果中包括原始标签。by和without仅仅用在输入向量的桶中。
例如: 如果度量指标名称http_requests_total包含由group, application, instance的标签组成的时间序列数据,我们可以通过以下方式计算去除instance标签的http请求总数:
如果我们对所有应用程序的http请求总数:
统计每个编译版本的二进制文件数量:
通过所有实例,获取http请求第5个最大值:
^
*
,/
,%
+
,-
==
,!=
,<=
,<
,>=
,>
and
,unless
or
参考:https://github.com/1046102779/prometheus/blob/master/prometheus/querying/operators.md
year(v=vector(time()) instant-vector)
。v是参数值,instant-vector
是参数类型。vector(time())
是默认值。 abs()
abs(v instant-vector)
返回输入向量的所有样本的绝对值 absent()
absent(v instant-vector)
,如果赋值给它的向量具有样本数据,则返回空向量;如果传递的瞬时向量参数没有样本数据,则返回不带度量指标名称且带有标签的样本值为1的结果
当监控度量指标时,如果获取到的样本数据是空的, 使用absent方法对告警是非常有用的。
|
|
ceil()
ceil(v instant-vector)
是一个向上舍入为最接近的整数
changes()
changes(v range-vector)
输入一个范围向量, 返回这个范围向量内每个样本数据值变化的次数。
clamp_max()
clamp_max(v instant-vector, max scalar)
数,输入一个瞬时向量和最大值,样本数据值若大于max,则改为max,否则不变.
clamp_min()
clamp_min(v instant-vector)
函数,输入一个瞬时向量和最大值,样本数据值小于min,则改为min。否则不变。
count_saclar()
count_scalar(v instant-vector)
函数, 输入一个瞬时向量,返回key:value="scalar"
: 样本个数。而count()
函数,输入一个瞬时向量,返回key:value=
向量:样本个数,其中结果中的向量允许通过by
条件分组
day_of_month()
day_of_month(v=vector(time()) instant-vector)
函数,返回被给定UTC时间所在月的第几天。返回值范围:1~31。
day_of_week()
day_of_week(v=vector(time()) instant-vector)
函数,返回被给定UTC时间所在周的第几天。返回值范围:0~6. 0表示星期天
days_in_month()
days_in_month(v=vector(time()) instant-vector)
函数,返回当月一共有多少天。返回值范围:28~31
delta()
delta(v range-vector)
函数,计算一个范围向量v的第一个元素和最后一个元素之间的差值。返回值:key:value=度量指标:差值
返回过去两小时的CPU温度差:
delta函数返回值类型只能是gauges
deriv()
deriv(v range-vector)
函数,计算一个范围向量v中各个时间序列二阶导数,使用简单线性回归
deriv二阶导数返回值类型只能是gauges
drop_common_labels()
drop_common_labels(instant-vector)
函数,输入一个瞬时向量,返回值是key:value=
度量指标:样本值,其中度量指标是去掉了具有相同标签
例如:
http_requests_total{code=”200”, host=”127.0.0.1:9090”, method=”get”} : 4,
http_requests_total{code=”200”, host=”127.0.0.1:9090”, method=”post”} : 5,
返回值: http_requests_total{method=”get”} : 4, http_requests_total{code=”200”, method=”post”} : 5
exp()
exp(v instant-vector)
函数,输入一个瞬时向量, 返回各个样本值的e指数值,即为e^N次方。特殊情况如下所示:Exp(+inf) = +Inf Exp(NaN) = NaN
floor()
floor(v instant-vector)
函数,与ceil()
函数相反。 4.3 为 4
histogram_quantile()
histogram_quatile(φ float, b instant-vector)
函数计算b向量的φ-直方图 (0 ≤ φ ≤ 1)
。参考中文文献
holt_winters()
holt_winters(v range-vector, sf scalar, tf scalar)
函数基于范围向量v,生成事件序列数据平滑值。平滑因子sf
越低, 对老数据越重要。趋势因子tf
越高,越多的数据趋势应该被重视。0< sf, tf <=1。 holt_winters
仅用于gauges
hour()
hour(v=vector(time()) instant-vector)
函数返回被给定UTC时间的当前第几个小时,时间范围:0~23
idelta()
idelta(v range-vector)
函数,输入一个范围向量,返回key: value = 度量指标: 每最后两个样本值差值
increase()
increase(v range-vector)
函数, 输入一个范围向量,返回:key:value =
度量指标:last值-first值,自动调整单调性,如:服务实例重启,则计数器重置。与delta()
不同之处在于delta是求差值,而increase返回最后一个减第一个值,可为正为负
返回过去5分钟,连续两个时间序列数据样本值的http请求增加值:
|
|
irate
irate(v range-vector)
函数, 输入:范围向量,输出:key: value =
度量指标: (last值-last前一个值)/时间戳差值
。它是基于最后两个数据点,自动调整单调性, 如:服务实例重启,则计数器重置
针对范围向量中的每个时间序列数据,返回两个最新数据点过去5分钟的HTTP请求速率:
|
|
irate
只能用于绘制快速移动的计数器。因为速率的简单更改可以重置FOR子句,利用警报和缓慢移动的计数器,完全由罕见的尖峰组成的图形很难阅读
label_replace()
对于v中的每个时间序列,label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)
将正则表达式与标签值src_label匹配。如果匹配,则返回时间序列,标签值dst_label被替换的扩展替换。$1替换为第一个匹配子组,$2替换为第二个等。如果正则表达式不匹配,则时间序列不会更改。
另一种更容易的理解是:label_replace
函数,输入:瞬时向量,输出:key: value =
度量指标: 值(要替换的内容:首先,针对src_label标签,对该标签值进行regex正则表达式匹配。如果不能匹配的度量指标,则不发生任何改变;否则,如果匹配,则把dst_label标签的标签纸替换为replacement 下面这个例子返回一个向量值a带有foo
标签: label_replace(up{job="api-server", serice="a:c"}, "foo", "$1", "service", "(.*):.*")
ln()
ln(v instance-vector)
计算瞬时向量v中所有样本数据的自然对数。特殊例子:ln(+Inf) = +Inf ln(0) = -Inf ln(x<0) = NaN ln(NaN) = NaN
log2()
log2(v instant-vector)
函数计算瞬时向量v中所有样本数据的二进制对数。
log10()
log10(v instant-vector)
函数计算瞬时向量v中所有样本数据的10进制对数。相当于ln()
minute()
minute(v=vector(time()) instant-vector)
函数返回给定UTC时间当前小时的第多少分钟。结果范围:0~59
month()
month(v=vector(time()) instant-vector)
函数返回给定UTC时间当前属于第几个月,结果范围:0~12
predict_linear()
predict_linear(v range-vector, t scalar)
预测函数,输入:范围向量和从现在起t秒后,输出:不带有度量指标,只有标签列表的结果值
rate()
rate(v range-vector)
函数, 输入:范围向量,输出:key: value = 不带有度量指标,且只有标签列表:(last值-first值)/时间差
rate(http_requests_total[5m])
rate()
函数返回值类型只能用counters,当用图表显示增长缓慢的样本数据时,这个函数是非常合适的
注意:当rate函数和聚合方式联合使用时,一般先使用rate函数,再使用聚合操作, 否则,当服务实例重启后,rate无法检测到counter重置
resets()
resets()
函数, 输入:一个范围向量,输出:key-value=没有度量指标,且有标签列表[在这个范围向量中每个度量指标被重置的次数]。在两个连续样本数据值下降,也可以理解为counter被重置resets(http_requests_total[5m])
。resets只能和counters一起使用
round()
round(v instant-vector, to_nearest 1= scalar)
函数,与ceil和floor函数类似,输入:瞬时向量,输出:指定整数级的四舍五入值, 如果不指定,则是1以内的四舍五入
scalar()
scalar(v instant-vector)
函数, 输入:瞬时向量,输出:key: value = “scalar”, 样本值[如果度量指标样本数量大于1或者等于0, 则样本值为NaN, 否则,样本值本身]
sort()
sort(v instant-vector)
函数,输入:瞬时向量,输出:key: value = 度量指标:样本值[升序排列]
sort_desc()
sort(v instant-vector
函数,输入:瞬时向量,输出:key: value = 度量指标:样本值[降序排列]
sqrt()
sqrt(v instant-vector)
函数,输入:瞬时向量,输出:key: value = 度量指标: 样本值的平方根
time()
time()
函数,返回从1970-01-01到现在的秒数,注意:它不是直接返回当前时间,而是时间戳
vector()
vector(s scalar)
函数,返回:key: value= {}
, 传入参数值
year()
year(v=vector(time()) instant-vector)
,返回年份
_over_time()
下面的函数列表允许传入一个范围向量,返回一个带有聚合的瞬时向量:
avg_over_time(range-vector)
: 范围向量内每个度量指标的平均值 min_over_time(range-vector)
: 范围向量内每个度量指标的最小值 max_over_time(range-vector)
: 范围向量内每个度量指标的最大值 sum_over_time(range-vector)
: 范围向量内每个度量指标的求和值 count_over_time(range-vector)
: 范围向量内每个度量指标的样本数据个数 quantile_over_time(scalar, range-vector)
: 范围向量内每个度量指标的样本数据值分位数,φ-quantile (0 ≤ φ ≤ 1)
stddev_over_time(range-vector)
: 范围向量内每个度量指标的总体标准偏差 stdvar_over_time(range-vector)
: 范围向量内每个度量指标的总体标准方差 参考:https://github.com/1046102779/prometheus/blob/master/prometheus/querying/functions.md
https://www.kancloud.cn/huyipow/prometheus/525003
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2021/06/02/Prometheus查询语法/
]]>现象:us地区 zabbix-proxy 在晚上高峰期时(21:00~24:00)容易发生 zabbix-server 无法连接 zabbix proxy。
问题原因:经检查,US 到 TW 之间通讯走国际链路会经过 PCCW 运营商,且保障到运营商和调整路由后效果不明显。
mtr 截图
因为 CDS 在 TW 有服务器,最后和 厂商 CDS 沟通后,采用 CDS 云互联解决问题,网络链路不会经过 PCCW 运营商。即 US CDS 机器与 TW CDS 机器建立 “大内网”,两者通过内网通讯,然后 TW CDS 转发 US zabbix proxy 流量到 TW zabbix-server。
解决过程:
最开始想到的是 通过 iptables SNAT 和 DNAT 实现路由转发。但可惜的是,失败了。
然后尝试使用 nginx 来转发 zabbix proxy 流量到 zabbix server,经过验证,由于 zabbix proxy 数据包过大,七层 nginx 反向代理无法完整转发流量,经多次尝试调整参数后,仍无法解决。失败了。
使用四层 haproxy 来代理 zabbix proxy 流量到 zabbix server。成功!。
使用 SNAT 和 DNAT ,代理服务器一直在发送大量 ARP 包,暂未解决问题。
这是之前配置的 SNAT 和 DNAT 规则,可能是姿势不对,未能解决问题。
在 zabbix proxy 上配置了路由到代理服务器,但zabbix-proxy 仍无法与 zabbix-server 建立通讯。
使用 nginx 代理时,可以发现 zabbix proxy 发送过来的 包很大,nginx 无法完整接收此数据包,才导致最后的失败。
使用 haproxy 代理
使用 haproxy 代理后,看到 zabbix proxy 已经可以正常发送数据到 zabbix-server。
haproxy 配置:
zabbix proxy 需要配置静态路由改变 zabbix proxy 到 zabbix server 的网络链路,即通过 代理服务器转发流量。
然后zabbix proxy的 zabbix server 配置改为 代理服务器 IP 地址。
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2021/03/17/代理转zabbix proxy/
]]>以前做报表从Mysql数据里面提取数据很简单,几条简单的SHELL脚本就可以实现该功能,因为是自己使用,所以对于格式无所谓,以前使用的都是.csv
格式,因为其是以逗号
区分的,方便脚本处理。这次不一样了,虽然这次接到需求也是从Mysql中导出数据,但是!!导出文件的格式必须是.XLSX
这是微软EXCEL软件自有的格式,包含特殊的文件头,所以之前的方法失效了,失效了… 折腾了好久,也请教了别人,终于,终于解决了这个需求。
环境:
Centos 7.2.1511
Python 2.7.5 -> 3.5
|
|
升级 Python 2.7.5 至 Python 3.5
不要动系统自带的Python,否则系统的某些功能都无法正常使用
如果报这个错,好像是 查询SQL
时超时了,在同级目录下会生成 __pycache__
文件夹,脚本换个目录(不要在含有__pycache__
这个目录的目录中执行 py脚本),然后删掉其父目录,再执行 py 脚本
Python脚本:
附件:
Python-3.5.4.tar.gz
select3.py
numpy-1.13.3-cp35-cp35m-manylinux1_x86_64.whl
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2020/10/16/Python-读取Mysql生成EXCEL(XLSX)/
]]>Horizontal Pod Autoscaling,简称HPA,是Kubernetes中实现POD水平自动伸缩的功能。
K8S集群可以通过Replication Controller的scale机制完成服务的扩容或缩容,实现具有伸缩性的服务。
K8S自动伸缩分为:
自动扩展主要分为两种:
HPA属于前者。它可以根据CPU使用率或应用自定义metrics自动扩展Pod数量(支持 replication controller、deployment 和 replica set)。
获取metrics的两种方式:
request
,否则HPA不会工作。 kube-controller-manager.service
中可以通过–horizontal-pod-autoscaler-sync-period
修改)查询metrics的资源使用情况。 HPA Controller会通过调整副本数量使得CPU使用率尽量向期望值靠近,而且不是完全相等。另官方考虑到自动扩展的决策可能需要一段时间才会生效:例如当pod所需要的CPU负荷过大,从而在创建一个新pod的过程中,系统的CPU使用量可能会同样在有一个攀升的过程。所以在每一次作出决策后的一段时间内,将不再进行扩展决策。对于扩容而言,这个时间段为3分钟,缩容为5分钟(可以通过--horizontal-pod-autoscaler-downscale-delay
,--horizontal-pod-autoscaler-upscale-delay
进行调整)。
角色 | IP | 操作系统版本 |
---|---|---|
master | 192.168.1.201 | centos 7.4 |
etcd1 | 192.168.1.201 | centos 7.4 |
etcd2 | 192.168.1.202 | centos 7.4 |
etcd3 | 192.168.1.203 | centos 7.4 |
node1 | 192.168.1.204 | centos 7.4 |
node2 | 192.168.1.205 | centos 7.4 |
环境 | 软件版本 |
---|---|
kubectl server | v1.9.2 |
kubectl client | v1.9.2 |
Go | go1.9.2 |
etcdctl | 3.2.15 |
etcd | 3.2.15 |
flanneld | v0.10.0 |
cfssl | 1.2.0 |
docker | 18.09.1-beta1 |
|
|
|
|
|
|
先准备一套K8S集群环境,环境部署略。
|
|
|
|
|
|
|
|
这时发现nginx-hpa获取不到当前的CPU情况(TARGETS)。等待几分钟后执行kubectl describe hpa
发现HPA报错信息如下:
大概意思是HPA无法通过API获取到metrics值。
解决办法:
在/etc/systemd/system/kube-controller-manager.service
配置文件中新增--horizontal-pod-autoscaler-use-rest-clients=false
配置参数。然后重启kube-controller-manager服务即可。
|
|
|
|
配置并重启完成kube-controller-manager服务后,执行kubectl delete -f nginx-hpa-cpu.yml
和kubectl apply -f nginx-hpa-cpu.yml
重新创建服务后,发现出现新的错误,信息如下:
意思是HPA无法连接heapster服务。于是检查heapster服务是否异常。
访问kube-dashboard发现POD是可以通过heapster获取到CPU内存的信息的。如下,说明heapster工作正常。
于是到node节点手动curl访问连接异常的URL。经测试在node1节点上访问正常。
于是到kube-master上访问测试,发现HPA无法访问到heapster。
接下来我们来测试下网络情况,发现kube-master无法Ping通heapster的POD地址。
测试发现是网络不通导致的。解决办法是在kube-master上安装flannel网络。
如果flannel网络的IP地址丢失,重启flannel网卡systemctl restart flanneld
即可解决。
再测试下kube-master到heapster POD的网络情况:
重新导入nginx-hpa-cpu.yml文件,然后等待几分钟…
OK,HPA连接heapster成功。
截至目前,HPA支持的API版本有三个。分别是autoscaling/v1
,autoscaling/v2beta1
,autoscaling/v2beta2
。其中autoscaling/v1
只支持CPU一种伸缩指标;在autoscaling/v2beta1
中增加支持custom metrics;在autoscaling/v2beta2
中增加支持external metrics。
详细说明参考:
官方说明,在k8s 1.11版本,HPA将不再从heapster上获取指标。
|
|
这里只针对CPU的HPA 压力测试。
压测命令
观察HPA当前负载和POD的情况
|
|
当负载飙升时,HPA会按照定义的规则开始创建新的POD副本(定义POD的CPU阈值为70%)。
继续压测,会发现POD副本数量继续增加(REPLICAS从3到5)。
当REPLICAS达到定义的上限时,即使当前CPU的压力仍然很大,REPLICAS也不会再增加了。
停止压测,当CPU负载降低时,HPA会自动减少POD的数量。
慢慢的,HPA会减少POD的数量,直到降低到最小POD数(MINPODS)。
通过kube-dashboard观察这个过程的变化。
通过HPA的日志信息查看到它伸缩的过程。
autoscaling/v2beta1
中增加支持custom metrics。
|
|
等待几分钟后…
观察发现前面10%是内存的使用百分比,后面0%是CPU的使用百分比。
|
|
autoscaling/v2beta2
测试发现目前k8s 1.9.2暂不支持这个API版本。
参考:
http://blog.51cto.com/ylw6006/2113848
https://blog.frognew.com/2017/01/kubernetes-pod-scale.html
https://k8smeetup.github.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
https://blog.csdn.net/qq_17016649/article/details/79297796
https://github.com/kubernetes/kubernetes/issues/57673
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2019/01/28/k8s集群水平扩展-HPA/
]]>Loki是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流编制一组标签,为 Prometheus和 Kubernetes用户做了相关优化。项目受 Prometheus 启发,类似于 Prometheus 的日志系统。
Loki初体验
与其他日志聚合系统相比, Loki具有下面的一些特性:
Loki 由以下3个部分组成:
环境 | 版本 |
---|---|
centos | v7.4 |
docker | v18.09.0 |
docker-compose | v1.23.2 |
grafana | v5.5.0 |
node-exporter | v0.17.0 |
prometheus | v2.5.0 |
clone loki源码
可以直接运行官方的docker-compose.yml文件,执行命令为:docker-compose -f docker-compose.yaml up -d
docker-compose.yml 文件如下,这里使用的 grafana 镜像为自己编译的,官方的镜像为:image: grafana/grafana:master
|
|
部署完成后,访问grafana:http://ip:3000,默认密码为`admin:admin`
Grafana v5.5.0+以上的版本才支持Loki
添加数据源Prometheus和Loki
根据系统标签来查看Loki日志
测试发现当promtail定义读取的日志路径为/var/log
时,即使日志路径为/var/log/grafana/grafana.log
也不能读取。
这里的job varlogs是在promtail的配置文件里定义的,promtail配置文件如下:
Loki也可以查看Prometheus的item
参考:
Grafana 日志聚合工具 Loki
Loki官网
Deploy Loki to Kubernetes
Configuring the Loki Datasource in Grafana
Loki API
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2019/01/20/Grafana日志聚合工具Loki/
]]>今天看到一篇文章介绍怎么用python来爬抖音的小视频和音乐。于是兴趣大增,先来试试能不能玩,哈哈。
先来看个效果图,嗯嗯…
环境:
python 3.7.1
centos 7.4
pip 10.0.1
|
|
|
|
有时候因为网络原因会安装失败,这时重新执行上面的命令即可,直到安装完成。
导入douyin模块
导入如果报错的话,可能douyin模块没有安装成功。
下面我们开始爬…爬抖音小视频和音乐咯
几分钟后…我们来看看爬的成果
可以看到视频配的音乐被存储成了 mp3 格式的文件,抖音视频存储成了 mp4 文件。
嗯…不错,哈哈。
作者说,能爬抖音上所有热门话题和音乐下的相关视频都爬取到,并且将爬到的视频下载下来,同时还要把视频所配的音乐也单独下载下来,不仅如此,所有视频的相关信息如发布人、点赞数、评论数、发布时间、发布人、发布地点等等信息都需要爬取下来,并存储到 MongoDB 数据库。
由于我这里没有mongodb所以,把这mongodb相关的配置给注释掉了。
作者github地址:https://github.com/Python3WebSpider/DouYin
====以下摘自作者====
本库依赖的其他库有:
数据结构定义
如果要做一个库的话,一个很重要的点就是对一些关键的信息进行结构化的定义,使用面向对象的思维对某些对象进行封装,抖音的爬取也不例外。
在抖音中,其实有很多种对象,比如视频、音乐、话题、用户、评论等等,它们之间通过某种关系联系在一起,例如视频中使用了某个配乐,那么视频和音乐就存在使用关系;比如用户发布了视频,那么用户和视频就存在发布关系,我们可以使用面向对象的思维对每个对象进行封装,比如视频的话,就可以定义成如下结构:
这里将一些关键的属性定义成 Video 类的一部分,包括 id 索引、desc 描述、author 发布人、music 配乐等等,其中 author 和 music 并不是简单的字符串的形式,它也是单独定义的数据结构,比如 author 就是 User 类型的对象,而 User 的定义又是如下结构:
所以说,通过属性之间的关联,我们就可以将不同的对象关联起来,这样显得逻辑架构清晰,而且我们也不用一个个单独维护字典来存储了,其实这就和 Scrapy 里面的 Item 的定义是类似的。
请求和重试
实现爬取的过程就不必多说了,这里面其实用到的就是最简单的抓包技巧,使用 Charles 直接进行抓包即可。抓包之后便可以观察到对应的接口请求,然后进行模拟即可。
所以问题就来了,难道我要一个接口写一个请求方法吗?另外还要配置 Headers、超时时间等等的内容,那岂不是太费劲了,所以,我们可以将请求的方法进行单独的封装,这里我定义了一个 fetch 方法:
这个方法留了一个必要参数,即 url,另外其他的配置我留成了 kwargs,也就是可以任意传递,传递之后,它会依次传递给 requests 的请求方法,然后这里还做了异常处理,如果成功请求,即可返回正常的请求结果。
定义了这个方法,在其他的调用方法里面我们只需要单独调用这个 fetch 方法即可,而不需要再去关心异常处理,返回类型了。
好,那么定义好了请求之后,如果出现了请求失败怎么办呢?按照常规的方法,我们可能就会在外面套一层方法,然后记录调用 fetch 方法请求失败的次数,然后重新调用 fetch 方法进行重试,但这里可以告诉大家一个更好用的库,叫做 retrying,使用它我们可以通过定义一个装饰器来完成重试的操作。
比如我可以使用 retry 装饰器这么装饰 fetch 方法:
这里使用了装饰器的四个参数:
这里 retry_on_exception 参数指定了一个方法,叫做 need_retry,方法定义如下:
这里判断了如果是 requests 的 ConnectionError 和 ReadTimeout 异常的话,就会抛出异常进行重试,否则不予重试。
所以,这样我们就实现了请求的封装和自动重试,是不是非常 Pythonic?
下载处理器的设计
为了下载视频,我们需要设计一个下载处理器来下载已经爬取到的视频链接,所以下载处理器的输入就是一批批的视频链接,下载器接收到这些链接,会将其进行下载处理,并将视频存储到对应的位置,另外也可以完成一些信息存储操作。
为了实现高速下载,这里我们可以使用 aiohttp 库来完成,另外异步下载我们也不能一下子下载太多,不然网络波动太大,所以我们可以设置 batch 式下载,可以避免同时大量的请求和网络拥塞,主要的下载函数如下:
这个 download 方法设计了多种数据接收类型,可以接收一个生成器,也可以接收单个或列表形式的视频对象数据,接着调用了 process_items 方法进行了异步下载,其方法实现如下:
这里使用了 asyncio 实现了异步处理,并通过对视频链接进行分批处理保证了流量的稳定性,另外还使用了 tqdm 实现了进度条的显示。
我们可以看到,真正的处理下载的方法是 process_item,这里面会调用视频下载、音频下载、数据库存储的一些组件来完成处理,由于我们使用了 asyncio 进行了异步处理,所以 process_item 也需要是一个支持异步处理的方法,定义如下:
这里我们可以看到,真正的处理逻辑都在一个个 handler 里面,我们将每个单独的功能进行了抽离,定义成了一个个 Handler,这样可以实现良好的解耦合,如果我们要增加和关闭某些功能,只需要配置不同的 Handler 即可,而不需要去改动代码,这也是设计模式的一个解耦思想,类似工厂模式。
Handler 的设计
刚才我们讲了,Handler 就负责一个个具体功能的实现,比如视频下载、音频下载、数据存储等等,所以我们可以将它们定义成不同的 Handler,而视频下载、音频下载又都是文件下载,所以又可以利用继承的思想设计一个文件下载的 Handler,定义如下:
这里我们还是使用了 aiohttp,因为在下载处理器中需要 Handler 支持异步操作,这里下载的时候就是直接请求了文件链接,然后判断了文件的类型,并完成了文件保存。
视频下载的 Handler 只需要继承当前的 FileHandler 即可:
这里其实就是加了类别判断,确保数据类型的一致性,当然音频下载也是一样的。
异步 MongoDB 存储
上面介绍了视频和音频处理的 Handler,另外还有一个存储的 Handler 没有介绍,那就是 MongoDB 存储,平常我们可能习惯使用 PyMongo 来完成存储,但这里我们为了加速,需要支持异步操作,所以这里有一个可以实现异步 MongoDB 存储的库,叫做 Motor,其实使用的方法差不太多,MongoDB 的连接对象不再是 PyMongo 的 MongoClient 了,而是 Motor 的 AsyncIOMotorClient,其他的配置基本类似。
在存储时使用的是 update_one 方法并开启了 upsert 参数,这样可以做到存在即更新,不存在即插入的功能,保证数据的不重复性。
整个 MongoDB 存储的 Handler 定义如下:
可以看到我们在类中定义了 AsyncIOMotorClient 对象,并暴露了 conn_uri 连接字符串和 db 数据库名称,可以在声明 MongoHandler 类的时候指定 MongoDB 的链接地址和数据库名。
同样的 process 方法,这里使用 await 修饰了 update_one 方法,完成了异步 MongoDB 存储。
好,以上便是 douyin 库的所有的关键部分介绍,这部分内容可以帮助大家理解这个库的核心部分实现,另外可能对设计模式、面向对象思维以及一些实用库的使用有一定的帮助。
参考:https://github.com/Python3WebSpider/DouYin
不到 10 行代码爬抖音
附件:
douyin.py
Python-3.7.1.tar.xz
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/11/06/Python十行代码爬抖音/
]]>Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。
编译安装python3.7.1并支持ssl 模块
环境:
python 3.7.1
centos 7.4
|
|
|
|
|
|
|
|
如果不安装libffi-devel,在编译时会报下面的错误
如果不安装openssl,在使用ssl模块时会报错
|
|
|
|
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/11/04/Python升级/
]]>在部署完k8s及使用prometheus监控后,发现一个问题啊,那就是能不能像zabbix一样,自己定义key啊,监控自己的服务,毕竟官方提供的key也不能完全覆盖。。
在查阅官网资料发现,prometheus是可以使用自定义key的。
官方git地址:https://github.com/prometheus/node_exporter
官方描述:
即通过官方提供的collector来实现自定义key功能。
具体的collector这里就不一一列出了,可参考这里
环境:
Prometheus version 2.2.0
node_exporter version 0.15.2
Centos 7.4
这里就以监控nginx页面的状态码为例了,使用的是textfile
这个collector
编写和zabbix类似的监控脚本并赋予其返回值
|
|
|
|
编写脚本生成key
|
|
zabbix_runner脚本会生成node_nginx_testpage_status.prom
文件,该文件记录当前监控指标的状态
启动node_exporter
--collector.textfile.directory
指定textfile
收集器读取文件的目录。根据官网说明,textfile
收集器会读取以.prom
结尾的文件 访问prometheus Dashboard
http://ip:9090
首先先确认prometheus与node_exporter建立连接
输入在node_nginx_testpage_status.prom
文件中生成的key
这样就完成了node_exporter自定义key
接下来把其放到定时任务中即可
|
|
附件:
zabbix_runner
node_nginx_testpage_status
node_exporter_key.sh
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/09/29/node-exporter自定义key/
]]>运算符的优先级:+
和-
优先级最低,*
,/
,//
,%
优先级较高,单目运算符+
和-
优先级更高,乘方的优先级最高
环境:
python 2.7
centos 7.5
|
|
+
)可以做字符串拼接 运算符 | 描述 | 示例 |
+ | 两个对象相加 | >>>print ‘abc’+’def’ abcdef >>>print 123+234 357 >>> |
- | 两个对象相减 | >>>print 123-456 -333 >>> |
* | 两个数相乘或返回一个重复若干次的序列 | >>>print 123*456 56088 >>>print ‘abc’*2 abcabc >>> |
/ | 两个数相除 | >>>print 2/3 0 >>>print 2/3.0 0.666666666667 >>>print 2.0/3 0.666666666667 >>> |
// | 整除,返回商的整数部分 | >>>print 3//2 1 >>>print 3//2.0 1.0 >>> |
% | 求余/取模,返回除法的余数 | >>>print 4%3 1 >>>print 4%3.0 1.0 >>>print 4%2.0 0.0 >>>print 4%2 0 >>> |
** | 求幂/次方 | >>>print 2**3 8 >>>print 2**3.0 8.0 >>> |
运算符 | 描述 | 实例 | 示例 |
= | 简单赋值运算符 | a = 5,b = 3,c = a - b | >>>a = 5 >>>b = 3 >>>c = a - b >>>print ‘c的值为:’,c c的值为:2 >>> |
+= | 加法赋值运算符 | a+= b 相当于 a = a+b | >>>a = 5 >>>b = 3 >>>a+= b >>>print ‘a的值为:’,a a的值为:8 >>> |
-= | 减法赋值运算符 | a -= b 相当于 a = a -b | >>>a = 5 >>>b = 3 >>>a -= b >>>print ‘a的值为:’,a a的值为:2 >>> |
*= | 乘法赋值运算符 | a *= b 相当于 a = ab | >>>a = 5 >>>b = 3 >>>a *= b >>>print ‘a的值为:’,a a的值为:15 >>> |
/= | 除法赋值运算符 | a /= b 相当于 a = a / b | >>>a = 5 >>>b = 3 >>>a /= b >>>print ‘a的值为:’,a a的值为:1 >>> |
//= | 取整除赋值运算符 | a //= b 相当于 a = a // b | >>>a = 5 >>>b = 3 >>>a //= b >>>print ‘a的值为:’,a a的值为:1 >>> |
%= | 取模赋值运算符 | a %= b 相当于 a = a % b | >>>a = 5 >>>b = 3 >>>a %= b >>>print ‘a的值为:’,a a的值为:2 >>> |
**= | 幂赋值运算符符 | a **= b 相当于 a = a^b | >>>a = 5 >>>b = 3 >>>a **= b >>>print ‘a的值为:’,a a的值为:125 >>> |
python 不支持C语言中的自增1和自减1运算符,因为+
和-
也是单目运算,python会将--n
解释为-(-n)
从而得到n,同样,++n
的结果也是n。
运算符 | 描述 | 示例 |
< | 小于,比较运算符返回1表示真,返回0表示假。 这分别与特殊的变量True和False等价 | >>>a=21 >>>b=10 >>>a>b True >>> |
<= | 小于或等于 | >>>a=21 >>>b=31 >>>a<=b True >>> |
> | 大于 | >>>a=21 >>>b=31 >>>a>b False >>> |
>= | 大于或等于 | >>>a=31 >>>b=21 >>>a>=b True >>> |
== | 等于 | >>>a=31 >>>b=21 >>>a==b False >>> |
!= | 不等于 | >>>a=31 >>>b=21 >>>a!=b True >>> |
is | 判断两个标识符是否引用自一个对象 | >>>x = [4,5,6] >>>y = [7,8,9] >>>x is y False >>> |
is not | 判断两个标识符是否引用自不同对象 | >>>x = [4,5,6] >>>y = [7,8,9] >>>x is not y True >>> |
Python中的任何一个对象都可以被测试“真”值。可以这样理解:Python中的任何一个对象都可以转换为一个布尔值,而这个“真”值测试就是获取一个对象对应的布尔值的过程。
Python中只有下面这些值对应的布尔值为False:
None
False
0
,如:0
,0.0
,0j
''
,()
,[]
{}
__bool__()
或__len__()
方法,且实例调用该方法时返回整数0或布尔值False 除此之外,所有的其它值对应的布尔值都是True, 因此许多类型的对象永远是True。”真”值测试可以被用在 if或while条件中,也可以作为布尔操作的操作数。
Python中的逻辑运算称为“布尔运算(Boolean Operations)”,操作符包括:and(与)、or(或)、not(非)。
运算符 | 逻辑表达式 | 描述 | 示例 |
and | x and y | 与运算,只有两个布尔值都为 True 时,计算结果才为 True | >>>x = True >>>y = False >>>x and y False >>> |
or | x or y | 或运算,只要有一个布尔值为 True,计算结果就是 True | >>>x = True >>>y = False >>>x or y True >>> |
not | not x | 非运算,把True变为False,或者把False变为True | >>>x = True >>>not x False >>> |
按位运算是指把数字转换为二进制来进行计算。
运算符 | 描述 | 实例 | 示例 |
& | 按位与,参与运算的两个值。 如果相应的二进制位都为1,则该位结果为1,否则为0 | a&b对应的二进制结果为 0000 1100,十进制为12 | >>>a=60 >>>b=13 >>>c=a & b >>>print c 12 >>> |
| | 按位或运算符, 只要对应的二个二进位有一个为1时,结果位就为1 | (a|b)输出结果61, 二进制解释: 0011 1101 | >>>a=60 >>>b=13 >>>c=a|b >>>print c 61 >>> |
^ | 按位异或运算符, 当两对应的二进位相异时,结果为1 | (a^b)输出结果49, 二进制解释: 0011 0001 | >>>a=60 >>>b=13 >>>c=a^b >>>print c 49 >>> |
~ | 按位取反运算符,对数据的每个二进制位取反, 即把1变为0,把0变为1。~x 类似于-x-1 | (~a)输出结果-61, 二进制解释:1100 0011, 在一个有符号二进制数的补码形式 | >>>a=60 >>>b=~a >>>print b -61 >>> |
<< | 左移动运算符,运算数的各二进位全部左移若干位, 由 << 右边的数字指定了移动的位数,高位丢弃,低位补0 | a << 2输出结果240, 二进制解释: 1111 0000 | >>>a=60 >>>b=a<<2< br="">>>>print b 240 >>>2<> |
>> | 右移动运算符, 把”>>”左边的运算数的各二进位全部右移若干位, >>右边的数字指定了移动的位数 | a>>2输出结果15, 二进制解释:0000 1111 | >>>a=60 >>>b=a>>2 >>>print b 15 >>> |
运算符 | 描述 | 实例 |
---|---|---|
in | 如果在指定的序列中找到值返回 True,否则返回 False | x 在 y 序列中 , 如果 x 在 y 序列中返回 True |
not in | 如果在指定的序列中没有找到值返回 True,否则返回 False | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True |
|
|
|
|
运算符 | 描述 |
---|---|
** |
指数(最高优先级) |
~ ,+ ,- |
按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* ,/ ,% ,// |
乘,除,取模和取整除 |
+ ,- |
加法减法 |
>> ,<< |
右移,左移运算符 |
& |
位’AND’ |
^ |
位运算符 |
<= ,< ,> ,>= |
比较运算符 |
<> ,== ,!= |
等于运算符 |
= ,%= ,/= ,//= ,-= ,+= ,*= ,**= |
赋值运算符 |
is is not |
身份运算符 |
in not in |
成员运算符 |
not and or |
逻辑运算符 |
指运算所需变量为一个的运算符,又叫一元运算符,其中有:
!
~
++
,–
-
(类型)
*
,&
sizeof
等 指对两个变量进行操作
[]
->
(向结构体成员运算符) _
*
/
%
+
-
==
!=
<
,>
,<=
,>=
&&
||
!
&
^
|
<<
>>
=
+=
-=
*=
/=
%=
>>=
(对变量进行位运算移位之后的结果再赋值给原来的变量) <<=
(同上)&=
,a = iand(a, b) is equivalent to a &= b
参考,参考 |=
,a|=2等价于a=a|2()
;a = ior(a, b) is equivalent to a |= b
。参考同上 ^=
;a = ixor(a, b) is equivalent to a ^= b
。参考同上 ,
三目运算符对三个变量进行操作,指的是计算机c语言的重要组成部分。条件运算符是唯一有3个操作数的运算符,所以有时又称为三元运算符。一般来说,三目运算符的结合性是右结合的。
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/08/04/Python运算符/
]]>到目前为止,也工作了好几年了吧。曾经某次听赵班长的公开课,听着听着发现,越听越懵…有种啥也不会的感觉..-_-!!!
但是呢,这些东西也确实是在工作中用到过,只是比较零碎。某些名词也确实很熟悉,但是呢,比如你现在问我里面具体的细节,我会用一脸懵逼来回应你,哈哈。
这些天抽空对着赵班长总结的表格,尝试在网上收集了些资料,整理出下面的文章。如果有不对的地方,欢迎大家指点。在整理这些东西的过程中,也是对我自己所掌握知识的一种回顾吧。让我们为了自己心中所想,一起努力吧!
整理运维知识体系之操作系统层
参考:https://www.unixhot.com/page/ops
运维架构层级 | 运维角度 | 内容描述/主要技术关键词 | 监控体系 | 自动化/DevOps | 云计算 |
操作系统层 | CPU | CPU运行级别、CPU管理(进程管理、taskset、intel VT-X)、使用率、上下文切换、运行队列、进程调度、系统调用 | mpstat、strace | 虚拟化 | 公有云弹性计算产品 |
内存 | 虚拟内存、SWAP换入换出、内存寻址、内存管理(Buffer Cache、HugePages、ksmd、EPT) | vmstat、free | |||
I/O(磁盘) | 缺页中断、IOPS(顺序IO、随机IO)、IO管理(IO调度算法、virtio)、VFS | iostat、iotop | |||
I/O(网络) | TCP/IP(三次握手、四次挥手、状态转换、TCP队列)、IO模型、Bonding、Bridge、网络管理(iftop、tcpdump) | iftop | |||
内核/Shell | 内核定制、内存参数优化、脚本编程(AWK、Sed、Shell、Python、PHP、Perl、Ruby、Lua) | 系统监控 |
taskset
|
|
|
|
CPU使用率
65%~70%
,system空间保持在30%
,空闲保持在0%~5%
。 参数 | 描述 |
---|---|
%us | 用户空间程序的cpu使用率(没有通过nice调度) |
%sy | 系统空间的cpu使用率,主要是内核程序 |
%ni | 用户空间且通过nice调度过的程序的cpu使用率 |
%id | 空闲cpu |
%wa | cpu运行时在等待io的时间 |
%hi | cpu处理硬中断的数量 |
%si | cpu处理软中断的数量 |
%st | 被虚拟机偷走的cpu |
参数 | 描述 |
---|---|
r | 运行队列(多少个进程真的分配到CPU)。当值超过CPU数目,就会出现CPU瓶颈。和CPU的负载有关系,一般负载超过3就比较高,超过5就很高,超过10就不正常,服务器状态很危险。top的负载类似每秒的运行队列,如果队列过大,表示CPU很繁忙,一般会造成CPU使用率很高。 |
b | 阻塞的进程 |
swpd | 虚拟内存使用的大小。如果大于0表示机器的物理内存不足 |
free | 空闲的物理内存大小 |
buff | 缓存(主要用于块设备) |
cache | 缓存(缓存文件) |
si | 每秒从磁盘读入虚拟内存的大小。如果大于0表示物理内存不够或内存泄漏 |
so | 每秒虚拟内存写入磁盘的大小。如果大于0表示物理内存不够或内存泄漏 |
bi | 块设备每秒写入的块数量,块设备指系统上所有的磁盘和其他设备,默认为1024byte |
bo | 块设备每秒读取的块数量,如果读取文件,bo会大于0。bi和bo一般都接近0,不然就是IO过于频繁 |
in | 每秒CPU的中断次数,包括时间中断 |
cs | 每秒上下文切换次数,在调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目。每次调用系统函数,代码就会进入内核空间,导致上下文切换,这个很耗资源。 |
us | 用户CPU使用率 |
sy | 系统CPU使用率,如果太高,表示系统调用时间长 |
id | 空闲CPU时间,一般来说,id + us + sy = 100 |
wt | 等待IO CPU时间 |
sar
sar命令语法和vmstat一样
命令 | 参数 | 描述 |
sar -q 1 5 | runq-sz | 运行队列的长度(等待运行的进程数) |
plist-sz | 进程列表中进程(processes)和线程(threads)的数量 | |
ldavg-1 | 最后1分钟的系统平均负载(System load average) | |
ldavg-5 | 过去5分钟的系统平均负载 | |
ldavg-15 | 过去15分钟的系统平均负载 |
mpstat
命令 | 参数 | 描述 |
mpstat 1 5 | %user | 处理用户进程所使用 CPU 的百分比 |
%nice | 使用 nice 命令对进程进行降级时 CPU 的百分比 | |
%system | 内核进程使用的 CPU 百分比 | |
%iowait | 等待进行 I/O 所使用的 CPU 时间百分比 | |
%irq | 用于处理系统中断的 CPU 百分比 | |
%soft | 软件中断的 CPU 百分比 | |
%idle | 显示 CPU 的空闲百分比 | |
%intr/s | 显示每秒 CPU 接收的中断总数 |
pidstat
命令 | 参数 | 描述 |
pidstat | %user | 处理用户进程所使用 CPU 的百分比 |
%system | 内核进程使用的 CPU 百分比 | |
%guest | 进程在虚拟机占用cpu的百分比 | |
%CPU | 进程占用cpu的百分比 | |
CPU | 处理进程的cpu编号 | |
Command | 当前进程对应的命令 | |
pidstat -r | PID | 进程标识符 |
Minflt/s | 任务每秒发生的次要错误,不需要从磁盘中加载页 | |
Majflt/s | 任务每秒发生的主要错误,需要从磁盘中加载页 | |
VSZ | 虚拟地址大小,虚拟内存的使用KB | |
RSS | 常驻集合大小,非交换区五里内存使用KB | |
Command | 当前进程对应的命令 | |
pidstat -d | PID | 进程id |
kB_rd/s | 每秒从磁盘读取的KB | |
kB_wr/s | 每秒写入磁盘KB | |
kB_ccwr/s | 任务取消的写入磁盘的KB。当任务截断脏的pagecache的时候会发生 | |
Command | 当前进程对应的命令 | |
pidstat -w -p PID | PID | 进程id |
Cswch/s | 每秒主动任务上下文切换数量 | |
Nvcswch/s | 每秒被动任务上下文切换数量 | |
Command | 当前进程对应的命令 | |
pidstat -t -p PID | TGID | 主线程号 |
TID | 线程id | %user | 处理用户进程所使用 CPU 的百分比 |
%system | 内核进程使用的 CPU 百分比 | |
%guest | 进程在虚拟机占用cpu的百分比 | |
%CPU | 进程占用cpu的百分比 | |
CPU | 处理进程的cpu编号 | |
Command | 当前进程对应的命令 | |
pidstat -T ALL -p PID | PID | 进程标识符 |
Usr-ms | 任务和子线程在用户级别使用的毫秒数 | |
System-ms | 任务和子线程在系统级别使用的毫秒数 | |
Guest-ms | 任务和子线程在虚拟机(running a virtual processor)使用的毫秒数 | |
Command | 当前进程对应的命令 |
上下文切换
文档参考
现在linux是大多基于抢占式,CPU给每个任务一定的服务时间,当时间片轮转的时候,需要把当前状态保存下来,同时加载下一个任务,这个过程叫做上下文切换。时间片轮转的方式,使得多个任务利用一个CPU执行成为可能,但是保存现场和加载现场,也带来了性能消耗。
对于抢占式操作系统,引起上下文切换的原因大致有几下几种:
监测Linux的应用的时候,当CPU的利用率非常高,但是系统的性能却上不去的时候,不妨监控一下线程/进程的切换,看看是不是context switching导致的overhead过高。常用命令:pidstat
,vmstat
运行队列
文档参考
65%~70%
,system空间保持在30%
,空闲保持在0%~5%
。 CPU调度发生的情况:
非抢占式(nonpreemptive)和抢占式(preemptive)调度。前者是指让程序一直运行着,直到它自己出异常;后者允许其他程序抢占现在正在运行的程序。
系统调用
文档参考1,文档参考2,文档参考3
当用户态的进程调用一个系统调用时,CPU从用户态切换到内核态并开始执行一个内核函数。Linux通过由向量为128(0x80)的编程异常实现CPU由用户态到内核态的转换。
SWAP换入换出
文档参考
内存页面分为用户页面和内核页面。
关于SWAP的设置,Oracle官方推荐:
RAM|Swap Space
—|—
Up to 512 MB|2 times the size of RAM
Between 1024 MB and 2048 MB|1.5 times the size of RAM
Between 2049 MB and 8192 MB|Equal to the size of RAM
More than 8192 MB|0.75 times the size of RAM
内存寻址
文档参考1,文档参考2
内存寻址是指CPU允许支持的内存大小。双通道内存技术其实是一种内存控制和管理技术,它依赖于芯片组的内存控制器发生作用,在理论上能够使两条同等规格内存所提供的带宽增长一倍。计算机管理内存的基本方式有两种:段式管理和页式管理。
内存管理
文档参考
内存管理是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。
Buffer Cache
文档参考
缓存区cache(磁盘缓存)和缓冲区buffer(内存缓存)都是临时存储区。不同点:
HugePages
文档参考
HugePages是linux内核的一个特性,使用hugepage可以用更大的内存页来取代传统的4K页面。优点有:
Kmsd
文档参考
KSM是内核中的一种内存共享机制。在2.6.36版本的内核中引入,它会合并某些相同的页面以减少页面冗余,在内核中有一个KSM守护进程 ksmd,它定期扫描用户向它注册的内存区,寻找相同的页面,从而用一个添加写保护的页面来代替, 当有进程尝试写入的时候,会自动分配一个新页面,这点就是典型的COW机制。
EPT
文档参考
在虚拟化环境下,intel CPU在处理器级别加入了对内存虚拟化的支持。即扩展页表EPT,而AMD也有类似的成为NPT。
缺页中断
文档参考
缺页中断是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。在这个时候,被内存映射的文件实际上成了一个分页交换文件。
IOPS
文档参考1,文档参考2
IOPS(Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位。
|
|
IO调度算法
CFQ(完全公平排队I/O调度程序)
特点:
工作原理:
NOOP(电梯式调度程序)
特点:
电梯算法饿死读请求的解释:
virtio
文档参考
一种 I/O 半虚拟化解决方案,是一套通用 I/O 设备虚拟化的程序,是对半虚拟化 Hypervisor 中的一组通用 I/O 设备的抽象。提供了一套上层应用与各 Hypervisor虚拟化设备(KVM,Xen,VMware等)之间的通信框架和编程接口,减少跨平台所带来的兼容性问题,大大提高驱动程序开发效率。
VFS
文档参考1,文档参考2
VFS(virtual File System),也称为虚拟文件系统交换层(Virtual Filesystem Switch)的作用就是采用标准的Unix系统调用读写位于不同物理介质上的不同文件系统,即为各类文件系统提供了一个统一的操作界面和应用编程接口。VFS是一个可以让open()
、read()
、write()
等系统调用不用关心底层的存储介质和文件系统类型就可以工作的粘合层。
iostat
命令 | 参数 | 描述 |
iostat -x | rrqm/s | 每秒这个设备相关的读取请求有多少被Merge了(当系统调用需要读取数据的时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge) |
wrqm/s | 每秒这个设备相关的写入请求有多少被Merge了 | |
r/s | 每秒读取的扇区数 | |
w/s | 每秒写入的扇区数 | |
rkB/s | 每秒读K字节数,是 rsect/s 的一半,因为每扇区大小为512字节。(需要计算) | |
wkB/s | 每秒写K字节数。是 wsect/s 的一半。(需要计算) | |
avgrq-sz | 平均每次设备I/O操作的数据大小(扇区)。delta(rsect+wsect)/delta(rio+wio) | |
avgqu-sz | 平均I/O队列长度。即 delta(aveq)/s/1000(因为aveq的单位为毫秒) | |
await | 平均每次设备I/O操作的等待时间(毫秒)。即 delta(ruse+wuse)/delta(rio+wio) | |
r_await | 发送给要服务的设备的读取请求的平均时间(毫秒)。这包括队列中请求所花费的时间和服务它们所花费的时间。 | |
w_await | 发送给要服务的设备的写入请求的平均时间(毫秒)。这包括队列中请求所花费的时间和服务它们所花费的时间。 | |
svctm | 平均每次设备I/O操作的服务时间(毫秒) | |
%util | 一秒中有百分之多少的时间用于 I/O 操作,即被io消耗的cpu百分比 |
iotop(yum安装)
TCP三次握手四次挥手
文档参考
最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
TCP状态变迁
文档参考
三次握手:
四次挥手:
为何TIME_WAIT需要等2MSL时间才能回到CLOSED状态:
如果网络不可靠,那么就无法保证最后客户端发送的ACK报文服务器端一定能够收到,因此处于LAST_ACK状态的服务器可能会因为超时而未收到ACK报文,而重新向客户端发送FIN报文,TIME_WAIT的作用就是用来客户端重新发送可能丢失的ACK报文。
TCP队列
文档参考
IO模型
文档参考
网卡Bonding模式
文档参考
Bridge
文档参考
计算机内部一般有系统总线来连接内部所有的硬件设备。一个典型的系统总线是PCI(Peripheral Component Interconnect)总线。其他类型的用得较多的总线还有ISA,EISA,MCA,SCSI,和USB。
一个计算机有多个不同类型的总线,这些总线由桥(bridge)链接起来。有以下两种高速总线处理到达或出自内存芯片的数据传输:
网络管理
iftop(yum安装)
tcpdump
文档参考
tcpdump -i lo
tcpdump -s0
tcpdump -n
内核定制
文档参考1,文档参考2,文档参考3
linux系统的启动流程:POST自检过程(BIOS) –>如果有多块磁盘,需要在BIOS上选择启动磁盘 –>引导MBR(bootloader引导程序) –> 加载initrd文件 –>执行进程init –>显示欢迎界面
Linux系统定制的目的和意义:
Linux内核参数优化
文档参考
sysctl -a
查看所有系统变量/proc/sys
下内核文件与配置文件sysctl.conf中变量存在着对应关系
|
|
参考值(具体根据系统硬件配置对应值)
|
|
脚本编程
系统监控
在工作中我使用的是Zabbix做系统监控,参考zabbix官网
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/07/27/运维知识体系之操作系统层/
]]>Jenkins持续集成工具,也玩了不少遍,但很少分享这类文档,今天抽空整理了下文档,和大家分享,哈哈
回想一下我们之前的发布流程:
有了jenkins以后,发布流程:
对于程序员而言,只要做两件事:
环境:
Centos 7.5
nexus 3.12.0
jenkins 2.128
maven 3.5.3
项目 | IP | 备注 |
---|---|---|
jenkins | 192.168.1.60 | 基于docker部署 |
maven | 192.168.1.60 | 和jenkins集成在一起 |
nexus3_oss | 192.168.1.61 | 基于docker部署 |
安装docker环境
docker-compose
jenkins
|
|
nexus3_oss
|
|
应用环境部署
|
|
|
|
|
|
打开nexus3_oss,访问http://192.168.1.61:8081
默认的账户密码为:admin
/admin123
Online - Remote Available
表示nexus仓库正在向nexus远端中央库下载公共依赖包Online - Ready to Connect
表示nexus仓库当前没有下载任务(向远端nexus中央库)
打开jenkins,访问http://192.168.1.60:8080
登录密码在日志中查找,在初始化jenkins时也会用到
jenkins安装maven Integration
插件,可以配置全局Maven Options
“系统管理” –“系统设置” –“Maven项目配置”-Xms1024m -Xmx1024m -XX:MaxPermSize=512m
登录jenkins后,点击“新建任务”,然后配置jenkins
在Git上添加相应的账户,Jenkins需要通过此账户从git上clone代码进行编译
Jenkins配置完成后,就可以编译项目了
在编译过程中,会遇到各种依赖问题,需要找开发童鞋沟通获取相应的依赖包
总结遇到的错误有(部分):
从Maven私服(nexus)正常下载依赖包
|
|
在编译时遇到依赖关系
|
|
与开发童鞋沟通获取相应的依赖包上传到nexus仓库
上传到nexus命令
需要先安装Maven和配置settings.xml(maven/conf/settings.xml
)
settings.xml文件配置 参考这里
通过报错可以看到,缺少json-lib-2.4-jdk15.jar这个依赖jar包,且json-lib-2.4-jdk15.jar这个依赖包存放的路径为:fakepath/json-lib/2.4/json-lib-2.4-jdk15.jar
手动上传到nexus仓库需要各个参数指定jar的文件名,如下:Dclassifier
字段有的jar依赖包没有就不需要指定该参数DgroupId
字段表示jar包的目录路径,如果有多级目录写法如上Durl
字段为上传到nexus仓库的路径deploymentRepo
字段为maven setting.xml里定义的nexus仓库的密码,具体见settings.xml文件
上传到nexus私服后,再去maven仓库目录删除对应出错的依赖jar包目录后,再次编译即可
编译时再遇到jar包依赖解决方法如上,找开发童鞋获取相应的jar依赖包并上传到nexus仓库。这个上传到nexus仓库开发写好pom.xml文件后应该可以自动上传的,而不需要我们手动上传到nexus仓库
如果不想通过jenkins来测试jar包是否存在依赖问题,可以配置好maven后并在该服务器上手动执行如下命令测试
附上一张jenkins编译失败的图片:
披荆斩棘,经过九九八十一难后,jenkins编译成功啦,结果如下
找到jenkins的$WORKSPACE 目录,进入到项目里面的可以看到编译成功后的jar包文件
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/07/04/部署jenkins项目/
]]>虽然zabbix已经玩了好多遍了,但每次重新部署时,还得到处找,今天抽空整理下文档,以后就可以直接复制粘贴了,哈哈
环境:
centos 7.4
zabbix 3.4.11
mysql 5.6
php 5.4
nginx 12.2
zabbix 3.4环境要求:
参考:zabbix requirements
|
|
|
|
如果能使用webtatic源的话,可以安装高版本的PHP。这里用不了webtatic的yum源。-_-!!!
|
|
这里也操作了mysql迁移DATA目录
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
如果点”next step”没有反应,需要检查下/var/lib/php/session
权限,如果没有这个目录就新建一个并授权777
附件:
epel-release-latest-7.noarch
mysql80-community-release-el7-1.noarch
webtatic-release
zabbix-3.4.11.tar.gz
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/06/30/部署Zabbix-3-4/
]]>本文是基于Ansible批量部署Jenkins环境
支持部署的环境:
环境 | ip |
---|---|
Jenkins | 192.168.1.201 |
Maven | 192.168.1.202 |
Nodejs | 192.168.1.203 |
Nexus3 | 192.168.1.206 |
工具 | 版本 | 备注 |
---|---|---|
centos | 7.4 | 7版本的系统对docker性能支持更好 |
Ansible | 2.5.2 | 因有些语法较新,需要ansible大于2.4 |
docker-ce | latest | - |
Jenkins | 2.128 | - |
Maven | 3.5.3 | - |
Nodejs | v8.11.2 | - |
Nexus3_oss | 3.12.0 | - |
|
|
工具包大小:
本工具测试环境为:centos 7.4
Author:Jack_wang
Blog:http://www.yfshare.vip
ssh-copy-id -i ~/.ssh/id_rsa.pub root@ip
注:ansible需要使用2.4以上的版本,因有些语法2.4以下不支持.
当前ansible版本为2.5.2。
|
|
注:这里安装ansible-2.5.2时,yum源里会缺少python-babel-0.9.6-8.el7.noarch.rpm包,可以在https://pkgs.org/download/python-b
abel这里下载.在当前目录也提供了该依赖包.
按要求修改hosts文件相关参数
操作步骤:
部署成功后,可执行下面命令查看结果:
Jenkins:访问http://ip:8080
Maven:
执行mvn -v
Nodejs:
执行node -v
nexus3:访问http://ip:8081
按要求修改hosts文件相关参数
操作步骤:
按要求修改hosts文件相关参数
操作步骤:
附件:
jenkins_ansible_2.128.tar.gz百度网盘,密码:dxng
本文出自”Jack Wang Blog”:http://www.yfshare.vip/2018/06/21/Ansible部署Jenkins环境/
]]>