YAML
Pod
定义一个Pod
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx
spec: # 必选,用于定义容器的详细信息
initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
- command:
- sh
- -c
- echo "I am InitContainer for init some configuration"
image: busybox
imagePullPolicy: IfNotPresent
name: init-container
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: nginx:latest # 必选,容器所用的镜像的地址
imagePullPolicy: Always # 可选,镜像拉取策略
command: # 可选,容器启动执行的命令
- nginx
- -g
- "daemon off;"
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
volumeMounts: # 可选,存储卷配置,可以配置多个
- name: webroot # 存储卷名称
mountPath: /usr/share/nginx/html # 挂载目录
readOnly: true # 只读
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
resources: # 可选,资源限制和资源请求限制
limits: # 最大限制设置
cpu: 1000m
memory: 1024Mi
requests: # 启动所需的资源
cpu: 100m
memory: 512Mi
# startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
path: / # 检查路径
port: 80 # 监控端口
livenessProbe: # 可选,健康检查
#exec: # 执行容器命令检测方式
#command:
#- cat
#- /health
#httpGet: # httpGet检测方式
# path: /_health # 检查路径
# port: 8080
# httpHeaders: # 检查的请求头
# - name: end-user
# value: Jason
tcpSocket: # 端口检测方式
port: 80
initialDelaySeconds: 60 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 5 # 检测间隔
successThreshold: 1 # 检查成功为2次表示就绪
failureThreshold: 2 # 检测失败1次表示未就绪
lifecycle:
postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
exec:
command:
- sh
- -c
- 'mkdir /data/ '
preStop:
httpGet:
path: /
port: 80
# exec:
# command:
# - sh
# - -c
# - sleep 9
restartPolicy: Always # 可选,默认为Always
#nodeSelector: # 可选,指定Node节点
# region: subnet7
imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个
- name: default-dockercfg-86258
hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口
volumes: # 共享存储卷列表
- name: webroot # 名称,与上述对应
emptyDir: {} # 挂载目录
#hostPath: # 挂载本机目录
# path: /etc/hosts
Deployment
apiVersion: extensions/v1beta1 # 指定api版本,此值必须在kubectl api-versions中
kind: Deployment # 指定创建资源的角色/类型
metadata: # 资源的元数据/属性
name: demo # 资源的名字,在同一个namespace中必须唯一
namespace: default # 部署在哪个namespace中
labels: # 设定资源的标签
app: nginx
version: v1
spec: # 资源规范字段
progressDeadlineSeconds: 60 #k8s 在升级过程中有可能由于各种原因升级卡住(这个时候还没有明确的升级失败),比如在拉取被墙的镜像,权限不够等错误。那么这个时候就需要有个 deadline ,在 deadline 之内如果还卡着,那么就上报这个情况,这个时候这个 Deployment 状态就被标记为 False,并且注明原因。但是它并不会阻止 Deployment 继续进行卡住后面的操作。完全由用户进行控制。
replicas: 1 # 声明副本数目
revisionHistoryLimit: 3 # 保留历史版本
selector: # 选择器
matchLabels: # 匹配标签
app: nginx
version: v1
strategy: # 策略
rollingUpdate: # 滚动更新
maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
maxUnavailable: 30% # 示在更新过程中能够进入不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
type: RollingUpdate # 滚动更新策略
template: # 模版
metadata: # 资源的元数据/属性
annotations: # 自定义注解列表
sidecar.istio.io/inject: "false" # 自定义注解名字
labels: # 设定资源的标签
app: nginx
version: v1
spec: # 资源规范字段
containers:
- name: nginx# 容器的名字
image: nginx:1.17.0 # 容器使用的镜像地址
imagePullPolicy: IfNotPresent # 每次Pod启动拉取镜像策略,三个选择 Always、Never、IfNotPresent
# Always,每次都检查;
# Never,每次都不检查(不管本地是否有);
# IfNotPresent,如果本地有就不检查,如果没有就拉取(手动测试时,已经打好镜像存在docker容器中时,使用存在不检查级别, 默认为每次都检查,然后会进行拉取新镜像,因镜像仓库不存在,导致部署失败)
terminationMessagePolicy: File #退出信息会从文件中读取,可以修改为:FallbackToLogsOnError,从日志中来读取。
terminationMessagePath: #表示容器的异常终止消息的路径,默认在 /dev/termination-log 下。当容器退出时,可以通过容器的状态看到退出信息
volumeMounts: #文件挂载目录,容器内配置
- mountPath: /data/ #容器内要挂载的目录
name: share #定义的名字,需要与下面vloume对应
resources: # 资源管理
limits: # 最大使用
cpu: 300m # CPU,1核心 = 1000m
memory: 500Mi # 内存,1G = 1000Mi
requests: # 容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
cpu: 100m
memory: 100Mi
livenessProbe: # pod 内部健康检查的设置
httpGet: # 通过httpget检查健康,返回200-399之间,则认为容器正常
path: /healthCheck # URI地址
port: 8080 # 端口
scheme: HTTP # 协议
# host: 127.0.0.1 # 主机地址
initialDelaySeconds: 30 # 表明第一次检测在容器启动后多长时间后开始
timeoutSeconds: 5 # 检测的超时时间
periodSeconds: 30 # 检查间隔时间
successThreshold: 1 # 成功门槛
failureThreshold: 5 # 失败门槛,连接失败5次,pod杀掉,重启一个新的pod
readinessProbe: # Pod 准备服务健康检查设置
httpGet:
path: /healthCheck
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 5
#也可以用这种方法
#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
# command:
# - cat
# - /tmp/health
#也可以用这种方法
#tcpSocket: # 通过tcpSocket检查健康
# port: number
ports:
- name: http # 名称
containerPort: 8080 # 容器开发对外的端口
protocol: TCP # 协议
imagePullSecrets: # 镜像仓库拉取密钥
- name: harbor-certification
terminationGracePeriodSeconds: 30 #可以定义优雅关闭的宽限期,即在收到停止请求后,有多少时间来进行资源释放或者做其它操作,如果到了最大时间还没有停止,会被强制结束。
volumes: #挂载目录在本机的路径
- name: share #对应上面的名字
hostPath:
path: /data #挂载本机的路径
affinity: # 亲和性调试
nodeAffinity: # 节点亲和力
requiredDuringSchedulingIgnoredDuringExecution: # pod 必须部署到满足条件的节点上
nodeSelectorTerms: # 节点满足任何一个条件就可以
- matchExpressions: # 有多个选项,则只有同时满足这些逻辑选项的节点才能运行 pod
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64
Job
apiVersion: batch/v1 # 版本号
kind: Job # 类型
metadata: # 元数据
name: # rs名称
namespace: # 所属命名空间
labels: #标签
controller: job
spec: # 详情描述
completions: 1 # 指定job需要成功运⾏Pods的次数。默认值: 1
parallelism: 1 # 指定job在任⼀时刻应该并发运⾏Pods的数量。默认值: 1
activeDeadlineSeconds: 30 # 指定job可运⾏的时间期限,超过时间还未结束,系统将会尝试进⾏终⽌。
backoffLimit: 6 # 指定job失败后进⾏重试的次数。默认是6
manualSelector: true # 是否可以使⽤selector选择器选择pod,默认是false
selector: # 选择器,通过它指定该控制器管理哪些pod
matchLabels: # Labels匹配规则
app: counter-pod
matchExpressions: # Expressions匹配规则
- {key: app, operator: In, values: [counter-pod]}
template: # 模板,当副本数量不⾜时,会根据下⾯的模板创建pod副本
metadata:
labels:
app: counter-pod
spec:
restartPolicy: Never # 重启策略只能设置为Never或者OnFailure
containers:
- name: counter
image: busybox:1.30
command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 2;done"]
stafulset
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: nginx-ss
spec:
selector:
matchLabels:
app: nginx #必须匹配 .spec.template.metadata.labels
serviceName: "nginx" #声明它属于哪个Headless Service.
replicas: 3 #副本数
template:
metadata:
labels:
app: nginx # 必须配置 .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: www.my.com/web/nginx:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: nginx-pvc
mountPath: /usr/share/nginx/html
volumeClaimTemplates: #可看作pvc的模板
- metadata:
name: nginx-pvc
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nginx-nfs-storage" #存储类名,改为集群中已存在的
resources:
requests:
storage: 1Gi
Service
apiVersion: v1 # 指定api版本,此值必须在kubectl api-versions中
kind: Service # 指定创建资源的角色/类型
metadata: # 资源的元数据/属性
name: demo # 资源的名字,在同一个namespace中必须唯一
namespace: default # 部署在哪个namespace中
labels: # 设定资源的标签
app: demo
spec: # 资源规范字段
externalTrafficPolicy: Cluster #有2个值可以设置:Cluster或者Local
#Cluster表示:流量可以转发到其他节点上的Pod。这个是默认模式,Kube-proxy不管容器实例在哪,公平转发。
#Local表示:流量只发给本机的Pod。只转发给本机的容器,绝不跨节点转发。
type: ClusterIP # ClusterIP 类型
ports:
- port: 8080 # service 端口
targetPort: 80 # 容器暴露的端口
protocol: TCP # 协议
name: http # 端口名称
selector: # 选择器
app: demo
无头服务
把标签去了,然后加上ep指定ip和端口
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
kind: Endpoints
apiVersion: v1
metadata:
name: my-service
subsets:
- addresses:
- ip: 1.2.3.4
ports:
- port: 9376
多端口Service
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: myapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
NodePort
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30000
selector:
k8s-app: kubernetes-dashboard
apiVersion: v1
kind: Service
metadata:
name: kube-node-service
labels:
name: kube-node-service
spec:
type: NodePort #这里代表是NodePort类型的
ports:
- port: 8080 #这里的端口和clusterIP对应,即ip:8080,供内部访问。
targetPort: 8080 #端口一定要和container暴露出来的端口对应
protocol: TCP
nodePort: 32143 # 所有的节点都会开放此端口,此端口供外部调用。
selector:
app: web
ExternalName
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
Ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-http
namespace: default
spec:
rules: #用于定义当前Ingress资源的转发规则列表;由rules定义规则,或没有匹配到规则时,所有的流量会转发到由backend定义的默认后端。
- host: www.zhangtest.com
http:
paths:
- path: /
backend: #默认的后端用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,必须要定义backend或rules两者之一,该字段用于让负载均衡器指定一个全局默认的后端。
serviceName: myapp-clusterip1
servicePort: 80
- host: blog.zhangtest.com
http:
paths:
- path: /
backend:
serviceName: myapp-clusterip2
servicePort: 80
#TLS配置,目前仅支持通过默认端口443提供服务,如果要配置指定的列表成员指向不同的主机,则需要通过SNI TLS扩展机制来支持该功能。
# backend对象的定义由2个必要的字段组成:serviceName和servicePort,分别用于指定流量转发的后端目标Service资源名称和端口。
# rules对象由一系列的配置的Ingress资源的host规则组成,这些host规则用于将一个主机上的某个URL映射到相关后端Service对象,其定义格式如下:
spec:
rules:
- hosts: <string>
http:
paths:
- path:
backend:
serviceName: <string>
servicePort: <string>
创建一个Ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: simple-fanout-example
annotations:
kubernetes.io/ingress.class: "nginx" # 不同的controller,ingress.class可能不一致
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
serviceName: service1
servicePort: 4200
- path: /bar
pathType: ImplementationSpecific
backend:
serviceName: service2
servicePort: 8080
Ingress v1
apiVersion: networking.k8s.io/v1 # 1.19+
kind: Ingress
metadata:
name: simple-fanout-example
spec:
ingressClassName: nginx
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
service
name: service1
port:
number: 4200
单域名
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: simple-fanout-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: service1
servicePort: 4200
- path: /bar
backend:
serviceName: service2
servicePort: 8080
多域名
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
TLS
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-https-test
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: https-test.com
http:
paths:
- backend:
serviceName: nginx-svc
servicePort: 80
tls:
- secretName: nginx-test-tls
Ingress进阶使用
1、Ingress Nginx域名重定向 Redirect
当一个服务需要更换域名时,并不能对其直接更改,需要一个过渡的过程。在这个过程中,雷要将旧域名的访问跳转到新域名,此时可以使用Redirect功能。待旧域名无访问时、再停止旧域名在Nginx作为代理服务器时,Redirect可用于域名的重定向,比如访问old.com被重定向到new.com,Ingress可以更简单地实现Redirect功能。比如把nginx.redirectcom作为旧域名baidu.cvm作为新域名进行演示:
vim redirect.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
name: nginx-redirect
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx.redirect.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
可以看到配置重定向功能只需要填加一个annotations即可,key为nginx.ingress.kubernetes.io/permanent-redirect,值为目标URL: https://www.baidu.com。
接下来同样的方式将nginx.redirect.com解析到Cotrollr 所在节点,在浏览器访问或者使用curl访问,即可看到重定向信息。
使用curl访问域名nginxredirect.com,可以看到301(请求被重定向的返回值):
2、Ingress Nginx前后端分离 Rewrite
现在大部分应用都是前后端分离的架构,也就是前端用某个域名的根路径进行访问,后端接采用/api进行访问,用来区分前端和后端。或者同时具有很多个后端,需要使用/api-a到A服务pib到B服务,但是由于A和B服务可能并没有/api-a和/api-b的路径,因此需要将/api-x重写为“/”才可以正常到A或者B服务,否则将会出现404的报错。
此时可以通过Rewrite功能达到这种效果,首先创建一个应用模拟后端服务:
![image-20230315095517048](C:\Users\ROG Gaming\AppData\Roaming\Typora\typora-user-images\image-20230315095517048.png)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: backend-api
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx.test.com
http:
paths:
- backend:
service:
name: backend-api
port:
number: 80
path: /api-a(/|$)(.*)
pathType: ImplementationSpecific
需要添加一个key为nginx.ingress.kubernetes.io/rewrite-target,并且value是S2,此访问/api-a就会被重写为“/”,访问/api-a/xxx会被重写为/xxx。再次访问nginxtestcom/api-a即可问到后端服务
3、Ingress Nginx错误代码重定向
如果访问一些不存在的路径或域名,就会抛出404的异常页面。对于生产境,这个提示并不友好,会暴露Nginx的版本号,我们可以利用Ngnx的错误代码重定向功配些错误代码(比如404、403、503)重定向到一个固定的页面。
主要演示当访问链接返回值为404、503等错误时,如何自动跳转到自定义的页面。读者如果用Helm安装的Ingress Conroler,推荐直接修改values.yaml,之后执行helm upgrade即可(如果是静态文件安装,需要更改 ingres-nginx的 ConfigMap文件);首先需要开启defaultBackend,修改values.yaml
![image-20230315100118839](C:\Users\ROG Gaming\AppData\Roaming\Typora\typora-user-images\image-20230315100118839.png)
4、Ingress开启加密
vim ingress-ssl.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
creationTimestamp: null
name: nginx-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx.test.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- nginx.test.com
secretName: ca-secret
可以看到Ingress添加TLS配置也非常简单,只需要在spcc下添加一个ls字段即可
hosts: 证书所授权的域名列表,
secretName: 证书的Secret名字
接下来更新该Ingress就好。
5、Ingress Nginx 匹配请求头
开发一个网页或者应用时,往往会适配计算机端和手机端,通常会将移动客户端访问的页面定向到移动端的服务上,读者也有可能经常见到m.xxx.com此类的域名,基本都属于移动端服务。
Nginx可以通过一个请求的请求头判断客户端来源,并将其路由到指定的服务上。将演示把来自移动端的访问重定向到移动端服务,计算机端访问保持默认即可。
![image-20230315100600147](C:\Users\ROG Gaming\AppData\Roaming\Typora\typora-user-images\image-20230315100600147.png)
vim laptop-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
set $agentflag 0;
if ($http_user_agent ~* "(Android|iPhone|Windows Phone|UC|Kindle)" ){
set $agentflag 1;
}
if ( $agentflag = 1 ) {
return 301 http://m.test.com;
}
name: laptop
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: test.com
http:
paths:
- backend:
service:
name: laptop
port:
number: 80
path: /
pathType: ImplementationSpecific
之后在浏览器更改访问方式为iphone,可以验证
6、ingress Nginx基本认证
有些网站可能需要通过密码来访何,对于这类网站可以使用Nginx的basic-iut设置密码访问购万法如下,由于需要使用hpasswd工具,因此需要安装httpd;
yum -y install httpd
htpasswd -c auth(证书文件名) too(用户名)
cat auth
foo:$apr1$okma2fx3$haTJ.rrmi4pr3teazmjesI
#创建secret
kubectl create secret secretname basic=auth --from-file=auth
vim ingress-with-auth.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-type: basic
name: ingress-with-auth
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: auth.test.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
7、Ingress Nginx 黑/白名单
有些网页可能只需要指定用户访问,比如公司的ERP只能公司内部访问,此时可以使用白名单限制访问的IP。有些网页不允许某些IP访问,比如一些有异常流量的IP,此时可以使用黑名单禁该IP访问。
7.1 配置黑名单
配置黑名单禁止某一个或某一段IP,需要在Nginx Ingress的ConigMap中配置,比如将192.168.10.130(多个配置使用逗号分隔)添加至黑名单:
# vim values .yaml
config:
block-cidrs:192.168.10.130
#更新nginx-ingress
# helm upgrade ingress-nginx -n ingress-nginx
7.2 配置白名单
白名单表示只允许某个P访问,直接在YAML文件中配置即可(也可以通过ConfieMap配置);如只允许192.168.10.128访间,只需要添加一个nginx.ingress.kubernetes.io/whitelist-source-range注释即可:
vim auth-whitelist.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.10.128
name: ingress-with-auth
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: auth.test.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
8、Ingress Nginx 速率限制
有时候可能需要限制速率以降低后端压力,或者限制单个IP每秒的访问速率防止攻击,此财以使用Nginx的ratelimit进行配置
首先没有加速率限制,使用ab进行访问,Failed为0:
# ab -c 10 -n 100 http://auth.test.com/ | grep requests
Complete requests: 100
Failed requests: 0
添加速率限制,限制只能有一个连接,只需要添加nginx.ingress.kubernetes.io/limit-connections
为1即可:
vim auth-rate-limit.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/limit-connections: "1"
name: ingress-with-auth
namespace: study-ingress
spec:
ingressClassName: nginx
rules:
- host: auth.test.com
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: ImplementationSpecific
再次使用ab测试,Failed为67:
# ab -c 10 -n 100 http;//auth.teat.com/ grep requeatsi
Complete requests; 100
Failed requests: 67
还有很多其他方面的限制,常用的配置如下:
#限制每秒的连接,单个IP
nginx.ingress.kubernetes.io/limit-rps
#限制每分钟的连接,单个IP
nginx.ingress.kubernetes.io/limit-rpm
#限制客户端每秒传输的字节数,单位为KB,需要开启proxy-buffering
nginx,ingress.kubernetes.io/limit-rate
#速率限制白名单
nginx.ingress.kubernetes.io/limit-whitelist
9、使用Nginx 实现灰度/金丝雀发布
Nginx可以实现一些简单的灰度、蓝绿发布,当某个服务需要在上线之前进行一些逻辑测试时,可以使用此功能。
假设我们有两个命名空间,一个是正在使用的生产环境Production,另一个是用于灰度测试的Canary。在发布应用时,可以将应用先发布至Canary,然后切一部分流量到Canary,之后慢慢将流量全部切换到上面即可。
首先创建模拟生产(Production)环境的命名空间和服务:
# kubectl create ns production
namespace/production created
# kubectl create deploy canary-v1~image=registry.cn-beijing.aliyuncs.com/dotbalo/canary:vl -n production
# kubectl expose deploy canary-vl --port 8080 -n production
# kubectl create ingress canary-vl --rule=canary.com/*=canary-vl:8080 -n production
接下来创建v2版本,充当灰度环境:
# kubectl create ns canarynamespace/canary created
创建v2版本的应用和Service:
# kubectl create deploy canary-v2 --image=registry.cn-beijing.aliyuncs. com/dotbalo/canary:v2 -n canary
# kubectl expose deploy canary-v2 --port 8080 -n canary
待程序启动完成后,通过Service访问该服务,会返回Canary v2:
# kubectl get svc -n canary
# cur1 192.168.181.120:8080
<h1>Canaryv2</hl>
接下来通过Ingress控制流量
Canary 版本切入部分流量
创建v2版本的Ingress时,需要添加两个注释:一个是nginxingress.kubernetes.io/canary,表明是灰度环境;另一个是nginxingresskubernetes.io/canary-weight,表明分配多少流量到该环境,本示为10%:
vim canary-v2.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
name: canary-v2
namespace: canary
spec:
ingressClassName: nginx
rules:
- host: canary.com
http:
paths:
- backend:
service:
name: canary-v2
port:
number: 8080
path: /
pathType: ImplementationSpecific
使用ruby脚本进行测试,此脚本会输出v1和v2的访问次数比值:
# vim test-canary.rb
counts = Hash.new(0)
100.times do
output = 'curl -s canary.com | grep 'Canary' | awk '(print $2)' | awk -F"<" '{print $1}''
counts[output.strip.split.last] +=1
end
puts counts
安装Ruby并测试:
# yum install ruby -y
# ruby test-canary.rb
["v1"=>90,"v2"=>10)
# ruby test-canary.rb
["vl"=>92,"v2"=>8}
# ruby test-canary.rb
["v1"=>91,"v2"=>9}
可以看到比例差不多是1:9,接下来可以更改权重,再次测试.
ConfigMap
valueFrom
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: env-valuefrom
name: env-valuefrom
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: env-valuefrom
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
app: env-valuefrom
spec:
containers:
- command:
- sh
- -c
- env
env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
key: special.how
name: special-config
image: busybox
imagePullPolicy: IfNotPresent
name: env-valuefrom
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 10m
memory: 10Mi
dnsPolicy: ClusterFirst
restartPolicy: Never
envFrom
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: env-valuefrom
name: env-valuefrom
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: env-valuefrom
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
app: env-valuefrom
spec:
containers:
- command:
- sh
- -c
- env
env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
envFrom:
- configMapRef:
name: game-config-env-file
prefix: fromCm_
image: busybox
imagePullPolicy: IfNotPresent
name: env-valuefrom
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 10m
memory: 10Mi
dnsPolicy: ClusterFirst
restartPolicy: Never
文件挂载
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Provide the name of the ConfigMap containing the files you want
# to add to the container
name: special-config
restartPolicy: Never
自定义文件名
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: special.how
path: keys
restartPolicy: Never
指定文件权限
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: busybox
command: [ "/bin/sh","-c","ls -l /etc/config/..data/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: special.how
path: keys
defaultMode: 0666
restartPolicy: Never
Secret
挂载Secret
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret: # configMap换成secret
secretName: mysecret # configMap类型为name
自定义文件名挂载
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
Secret作为环境变量
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
imagePullSecrets
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
# 多个Secret
- name: myregistrykey2
- name: myregistrykeyx
Ingress TLS
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-https-test
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: https-test.com
http:
paths:
- backend:
serviceName: nginx-svc
servicePort: 80
tls:
- secretName: nginx-test-tls
StorageClass
简易模板
allowVolumeExpansion: true
#PersistentVolume 可以配置为可扩展。将此功能设置为 true 时,允许用户通过编辑相应的 PVC 对象来调整卷大小。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
parameters:
fsType: ext4
staleReplicaTimeout: "30"
provisioner: driver.longhorn.io
reclaimPolicy: Retain
volumeBindingMode: Immediate
部署rbd-provisioner
CEPH——RBD
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/rbd #提供者,storageclass需要有一个供应者,用来确定我们使用什么样的存储来创建pv。provisioner既可以是内部供应程序,也可以由外部供应商提供,外部供应商需要额外的配置。
parameters: #参数
monitors: 10.16.153.105:6789 #Ceph monitor,逗号分隔。该参数是必需的。可以是多个
adminId: kube #Ceph 客户端 ID,用于在池 ceph 池中创建映像。默认是 “admin”。
adminSecretName: ceph-secret #adminId 的 Secret 名称。该参数是必需的。 提供的 secret 必须有值为 “kubernetes.io/rbd” 的 type 参数。
adminSecretNamespace: kube-system #adminSecret 的命名空间。默认是 “default”。
pool: kube # Ceph RBD 池. 默认是 “rbd”。
userId: kube #Ceph 客户端 ID,用于映射 RBD 镜像。默认与 adminId 相同。
userSecretName: ceph-secret-user
userSecretNamespace: default #userSecretName 的命名空间。
fsType: ext4 #Kubernetes支持的fsType。默认:“ext4”。
imageFormat: "2" #Ceph RBD镜像格式,“1” 或者 “2”。默认值是 “1”。
imageFeatures: "layering" #这个参数是可选的,只能在你将 imageFormat 设置为 “2” 才使用。目前支持的功能只是 layering(就是分层镜像)。默认是 “",没有功能打开。
reclaimPolicy: Retain #回收策略
volumeBindingMode: Immediate #Immediate表示立即绑定userSecretName:用于映射 RBD 镜像的 userId 的Ceph Secret的名字。 它必须与PVC存在于相同的namespace 中。该参数是必需的。提供的 secret必须具有值为 “kubernetes.io/rbd” 的 type参数,例如以这样的方式创建:
kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \
--from-literal=key='QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==' \
--namespace=kube-system
NFS
参考链接:K8S学习之storageclass_daydayup9527的博客-CSDN博客_k8s storageclass
创建NFS-Provisioner
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate #---设置升级策略为删除再创建(默认为滚动更新)
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
#---由于quay.io仓库国内被墙,所以替换成七牛云的仓库
image: quay-mirror.qiniu.com/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: nfs-client #--- nfs-provisioner的名称,以后设置的storageclass要和这个保持一致
- name: NFS_SERVER
value: 192.168.2.11 #---NFS服务器地址,和 valumes 保持一致
- name: NFS_PATH
value: /nfs/data #---NFS服务器目录,和 valumes 保持一致
volumes:
- name: nfs-client-root
nfs:
server: 192.168.2.11 #---NFS服务器地址
path: /nfs/data #---NFS服务器目录
资源限制
常见限制
#resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: resource-test
labels:
app: resourcequota
spec:
hard:
pods: 50
requests.cpu: 0.5
requests.memory: 512Mi
limits.cpu: 5
limits.memory: 16Gi
configmaps: 20
requests.storage: 40Gi
persistentvolumeclaims: 20
replicationcontrollers: 20
secrets: 20
services: 50
services.loadbalancers: "2"
services.nodeports: "10"
# quota-objects.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota-demo
spec:
hard:
persistentvolumeclaims: "1"
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-quota-demo
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
#再新建PVC会提示错误
限制范围(request,limit)
示例1:配置默认的requests和limits
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-mem-limit-range
spec:
limits:
- default:
cpu: 1
memory: 512Mi
defaultRequest:
cpu: 0.5
memory: 256Mi
type: Container
---
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo
spec:
containers:
- name: default-cpu-demo-ctr
image: nginx
示例2:配置requests和limits的范围
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-min-max-demo-lr
spec:
limits:
- max:
cpu: "800m"
memory: 1Gi
min:
cpu: "200m"
memory: 500Mi
type: Container
#超过或者低于default都会报错
---
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-2
spec:
containers:
- name: constraints-mem-demo-2-ctr
image: nginx
resources:
limits:
memory: "1.5Gi"
requests:
memory: "800Mi"
---
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-3
spec:
containers:
- name: constraints-mem-demo-3-ctr
image: nginx
resources:
limits:
memory: "800Mi"
requests:
memory: "100Mi"
示例3:限制申请存储空间的大小
apiVersion: v1
kind: LimitRange
metadata:
name: storagelimits
spec:
limits:
- type: PersistentVolumeClaim
max:
storage: 2Gi
min:
storage: 1Gi
QOS
示例1:实现QoS为Guaranteed的Pod
guaranteed,优先级最高,最不容易被驱逐,要求是request和limit必须一致
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
示例2:实现QoS为Burstable的Pod
优先级居中,要求设置request或者limit其中一个,剩下的按照default来,request低于limit
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
示例3:实现QoS为BestEffort的Pod
优先级最低,最先被驱逐或者kill,没设置request和limit
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
RBAC
role,rolebinding主要对应的是命名空间,clusterrole,clusterrolebindings主要对应整个集群,可以绑定user,group,serviceaccounts
pod-exec-cr.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-exec
rules:
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- list
- apiGroups:
- ""
resources:
- pods/exec #之前提到的子资源
verbs:
- create
ns-readonly.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-readonly
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- metrics.k8s.io
resources:
- pods
verbs:
- get
- list
- watch
扩展:deletecollection
在云平台开发、中间件容器化时,经常会遇到批量删除k8s资源对象的需求,deletecollection就是批量对象
可以根据abel批量删除pv,pvc,pod等等。
DeleteCollection方法第一个参数是删除选项,第二个参数是删除条件,包括label Selector、field Selector等
存储扩展
可以设置共享型存储,多个pod,共用一个pv,需要创建sc,之后pvc指向共享型sc,多个pod指定一个PVC即可。
PVC扩容可以直接edit,可能要十分钟。
1.19以上可以创建snapshotclass对指定PVC进行快照,创建完成以后可以restore恢复
pvc-restore.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc-restore
spec:
storageClassName: rook-ceph-block
dataSource:
name: rbd-pvc-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
restore-check-snapshot-rbd.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: check-snapshot-restore
spec:
selector:
matchLabels:
app: check
strategy:
type: Recreate
template:
metadata:
labels:
app: check
spec:
containers:
- image: alpine:3.8
name: check
command:
- sh
- -c
- sleep 36000
volumeMounts:
- name: check-mysql-persistent-storage
mountPath: /mnt
volumes:
- name: check-mysql-persistent-storage
persistentVolumeClaim:
claimName: rbd-pvc-restore
PVC也支持克隆
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc-clone
spec:
storageClassName: rook-ceph-block
dataSource:
name: mysql-pv-claim
kind: PersistentVolumeClaim
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
helm与operator
helm与operator
helm适合部署简单的无状态的,不需要额外功能的服务,只要把相关模板文件放在chart包的templates目录就行。
helm需要有自己单独的客户端工具。
helm主要是通过values.yaml来控制常用参数,比如副本数,sc名字等
operator需要自己写一个控制器,控制器可以解析自己定义的crd,然后生成对应的资源文件加载到k8s中,可以实现备份回滚等功能,当然,也需要有一定的开发能力。
operator可以一键扩容 更改crd的yaml,然后replace一下就好。
EFK
efk,fluentd功能有限,比如他只能收集程序输出到控制台的日志,不能收集非控制台日志,往往很多不遵循云原生的程序会输出很多日志文件,这些容器内的日志文件,无法收集。
filebeat是非常轻量级的日志采集工具,一般以sidecar的形式配置在pod中。甚至可以部署在容器中,来采集非控制台日志。当然 也可以部署在集群中采集控制台日志。
新贵loki-stack,grafana开源的,水平扩展,高可用,多租户的日志聚合系统。适合小公司。
可以通过标签添加到日志流,他不会对日志进行全文检索,仅仅索引相关日志的元数据,更简单,更节省成本,虽然没有别的灵活。
他可以很方便部署在k8s中,并且对pod日志进行收集,采集的时候就会把集群的元数据添加到日志中,这样就很方便通过元数据,比如标签,namespace等字段在grafana上搜索。
Loki有自己的语法,和Prometheus类似。
支持正则,=~(模糊匹配)等等。同时支持过滤字段,只包含xxx,大于20ms等等
Prometheus
概述
Prometheus 主要通过 Pull 的方式来抓取目标服务暴露出来的监控接口,因此需要配置对应的抓取任务来请求监控数据并写入到 Prometheus 提供的存储中,目前 Prometheus 服务提供了如下几个任务的配置:
原生 Job 配置:提供 Prometheus 原生抓取 Job 的配置。
Pod Monitor:在 K8S 生态下,基于 Prometheus Operator 来抓取 Pod 上对应的监控数据。
Service Monitor:在 K8S 生态下,基于 Prometheus Operator 来抓取 Service 对应 Endpoints 上的监控数据。
云原生与非云原生
云原生应用:找到本身提供的Metrics接口,然后配置一个Scrvice指向该应用的Pod,最后创建一个ScrviceMonitor指定该应用的Service即可完成监控数据的采集。
非云原生应用:需要找到合适该应用的Exporter,之后Exporter链接至该应用并采集相关数据,然后配置一个Service指向该Exporter的Pod,最后创建一个ServiceMonitor指定该Exporter的Sorvice即可完成监控数据的采集。
原生 Job 配置
# 抓取任务名称,同时会在对应抓取的指标中加了一个 label(job=job_name)
job_name: <job_name>
# 抓取任务时间间隔
[ scrape_interval: <duration> | default = <global_config.scrape_interval> ]
# 抓取请求超时时间
[ scrape_timeout: <duration> | default = <global_config.scrape_timeout> ]
# 抓取任务请求 URI 路径
[ metrics_path: <path> | default = /metrics ]
# 解决当抓取的 label 与后端 Prometheus 添加 label 冲突时的处理。
# true: 保留抓取到的 label,忽略与后端 Prometheus 冲突的 label;
# false: 对冲突的 label,把抓取的 label 前加上 exported_<original-label>,添加后端 Prometheus 增加的 label;
[ honor_labels: <boolean> | default = false ]
# 是否使用抓取到 target 上产生的时间。
# true: 如果 target 中有时间,使用 target 上的时间;
# false: 直接忽略 target 上的时间;
[ honor_timestamps: <boolean> | default = true ]
# 抓取协议: http 或者 https
[ scheme: <scheme> | default = http ]
# 抓取请求对应 URL 参数
params:
[ <string>: [<string>, ...] ]
# 通过 basic auth 设置抓取请求头中 `Authorization` 的值,password/password_file 互斥,优先取 password_file 里面的值。
basic_auth:
[ username: <string> ]
[ password: <secret> ]
[ password_file: <string> ]
# 通过 bearer token 设置抓取请求头中 `Authorization` bearer_token/bearer_token_file 互斥,优先取 bearer_token 里面的值。
[ bearer_token: <secret> ]
# 通过 bearer token 设置抓取请求头中 `Authorization` bearer_token/bearer_token_file 互斥,优先取 bearer_token 里面的值。
[ bearer_token_file: <filename> ]
# 抓取连接是否通过 TLS 安全通道,配置对应的 TLS 参数
tls_config:
[ <tls_config> ]
# 通过代理服务来抓取 target 上的指标,填写对应的代理服务地址。
[ proxy_url: <string> ]
# 通过静态配置来指定 target,详见下面的说明。
static_configs:
[ - <static_config> ... ]
# CVM 服务发现配置,详见下面的说明。
cvm_sd_configs:
[ - <cvm_sd_config> ... ]
# 在抓取数据之后,把 target 上对应的 label 通过 relabel 的机制进行改写,按顺序执行多个 relabel 规则。
# relabel_config 详见下面说明。
relabel_configs:
[ - <relabel_config> ... ]
# 数据抓取完成写入之前,通过 relabel 机制进行改写 label 对应的值,按顺序执行多个 relabel 规则。
# relabel_config 详见下面说明。
metric_relabel_configs:
[ - <relabel_config> ... ]
# 一次抓取数据点限制,0:不作限制,默认为 0
[ sample_limit: <int> | default = 0 ]
# 一次抓取 Target 限制,0:不作限制,默认为 0
[ target_limit: <int> | default = 0 ]
honorLabels: 如果目标标签和服务器标签冲突,是否保留目标标签interval:监控数据抓取的时间间隔
path: Metrics接口路径
port: Metrics端口
scheme: Metrics接口的协议。
namespaceSelector: 监控目标Service所在的命名空间,selector:监控目标Service的标签
Pod Monitor
相应配置项说明如下:
# Prometheus Operator CRD 版本
apiVersion: monitoring.coreos.com/v1
# 对应 K8S 的资源类型,这里面 Pod Monitor
kind: PodMonitor
# 对应 K8S 的 Metadata,这里只用关心 name,如果没有指定 jobLabel,对应抓取指标 label 中 job 的值为 <namespace>/<name>
metadata:
name: redis-exporter # 填写一个唯一名称
namespace: cm-prometheus # namespace不固定,除kube-system下的任意namespace都可以
labels:
prom_id: prom-xxx
# 描述抓取目标 Pod 的选取及抓取任务的配置
spec:
# 填写对应 Pod 的 label,pod monitor 会取对应的值作为 job label 的值。
# 如果查看的是 Pod Yaml,取 pod.metadata.labels 中的值。
# 如果查看的是 Deployment/Daemonset/Statefulset,取 spec.template.metadata.labels。
[ jobLabel: string ]
# 把对应 Pod 上的 Label 添加到 Target 的 Label 中
[ podTargetLabels: []string ]
# 一次抓取数据点限制,0:不作限制,默认为 0
[ sampleLimit: uint64 ]
# 一次抓取 Target 限制,0:不作限制,默认为 0
[ targetLimit: uint64 ]
# 配置需要抓取暴露的 Prometheus HTTP 接口,可以配置多个 Endpoint
podMetricsEndpoints:
[ - <endpoint_config> ... ] # 详见下面 endpoint 说明
# 选择要监控 Pod 所在的 namespace,不填为选取所有 namespace
[ namespaceSelector: ]
# 是否选取所有 namespace
[ any: bool ]
# 需要选取 namespace 列表
[ matchNames: []string ]
# 填写要监控 Pod 的 Label 值,以定位目标 Pod [K8S metav1.LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#labelselector-v1-meta)
selector:
[ matchExpressions: array ]
[ example: - {key: tier, operator: In, values: [cache]} ]
[ matchLabels: object ]
[ example: k8s-app: redis-exporter ]
例子
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: redis-exporter # 填写一个唯一名称
namespace: cm-prometheus # namespace不固定,除kube-system下的任意namespace都可以
labels:
prom_id: prom-xxx
spec:
podMetricsEndpoints:
- interval: 30s
port: metric-port # 填写pod yaml中Prometheus Exporter对应的Port的Name
path: /metrics # 填写Prometheus Exporter对应的Path的值,不填默认/metrics
relabelings:
- action: replace
sourceLabels:
- instance
regex: (.*)
targetLabel: instance
replacement: 'crs-xxxxxx' # 调整成对应的 Redis 实例 ID
- action: replace
sourceLabels:
- instance
regex: (.*)
targetLabel: ip
replacement: '1.x.x.x' # 调整成对应的 Redis 实例 IP
namespaceSelector: # 选择要监控pod所在的namespace
matchNames:
- redis-test
selector: # 填写要监控pod的Label值,以定位目标pod
matchLabels:
k8s-app: redis-exporter
Service Monitor
如果体验过容器化或者二进制的方式安装Promethcus,就会注意到Prometheus有一个配置文件,用于配置需要监控哪些数据,或者配置一些告警策略。这个配置文件的维护非常麻烦,特别是监控项非常多的情况下,很容易出现配置错误,而在Kubemtcs上部署Promethcus,可以不用维护这个配置文件,而是通过一个叫ServiceMonitor的资源来自动发现监控目标并动态生成配置。
相应配置项说明如下:
# Prometheus Operator CRD 版本
apiVersion: monitoring.coreos.com/v1
# 对应 K8S 的资源类型,这里面 Service Monitor
kind: ServiceMonitor
# 对应 K8S 的 Metadata,这里只用关心 name,如果没有指定 jobLabel,对应抓取指标 label 中 job 的值为 Service 的名称。
metadata:
name: redis-exporter # 填写一个唯一名称
namespace: cm-prometheus # namespace不固定,除kube-system下的任意namespace
labels:
prom_id: prom-xxx
# 描述抓取目标 Pod 的选取及抓取任务的配置
spec:
# 填写对应 Pod 的 label(metadata/labels),service monitor 会取对应的值作为 job label 的值
[ jobLabel: string ]
# 把对应 service 上的 Label 添加到 Target 的 Label 中
[ targetLabels: []string ]
# 把对应 Pod 上的 Label 添加到 Target 的 Label 中
[ podTargetLabels: []string ]
# 一次抓取数据点限制,0:不作限制,默认为 0
[ sampleLimit: uint64 ]
# 一次抓取 Target 限制,0:不作限制,默认为 0
[ targetLimit: uint64 ]
# 配置需要抓取暴露的 Prometheus HTTP 接口,可以配置多个 Endpoint
endpoints:
[ - <endpoint_config> ... ] # 详见下面 endpoint 说明
# 选择要监控 Pod 所在的 namespace,不填为选取所有 namespace
[ namespaceSelector: ]
# 是否选取所有 namespace
[ any: bool ]
# 需要选取 namespace 列表
[ matchNames: []string ]
# 填写要监控 Pod 的 Label 值,以定位目标 Pod [K8S metav1.LabelSelector](https://v1-17.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#labelselector-v1-meta)
selector:
[ matchExpressions: array ]
[ example: - {key: tier, operator: In, values: [cache]} ]
[ matchLabels: object ]
[ example: k8s-app: redis-exporter ]
例子
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: go-demo # 填写一个唯一名称
namespace: cm-prometheus # namespace不固定,除 kube-system 下的任意namespace
labels:
prom_id: prom-xxx
spec:
endpoints:
- interval: 30s
# 填写service yaml中Prometheus Exporter对应的Port的Name
port: 8080-8080-tcp
# 填写Prometheus Exporter对应的Path的值,不填默认/metrics
path: /metrics
relabelings:
# ** 必须要有一个 label 为 application,这里假设 k8s 有一个 label 为 app,
# 我们通过 relabel 的 replace 动作把它替换成了 application
- action: replace
sourceLabels: [__meta_kubernetes_pod_label_app]
targetLabel: application
# 选择要监控service所在的namespace
namespaceSelector:
matchNames:
- golang-demo
# 填写要监控service的Label值,以定位目标service
selector:
matchLabels:
app: golang-app-demo
endpoint_config 配置
相应配置项说明如下:
# 对应 port 的名称,这里需要注意不是对应的端口,默认:80,对应的取值如下:
# ServiceMonitor: 对应 Service>spec/ports/name;
# PodMonitor: 说明如下:
# 如果查看的是 Pod Yaml,取 pod.spec.containers.ports.name 中的值。
# 如果查看的是 Deployment/Daemonset/Statefulset,取 spec.template.spec.containers.ports.name。
[ port: string | default = 80]
# 抓取任务请求 URI 路径
[ path: string | default = /metrics ]
# 抓取协议: http 或者 https
[ scheme: string | default = http]
# 抓取请求对应 URL 参数
[ params: map[string][]string]
# 抓取任务间隔的时间
[ interval: string | default = 30s ]
# 抓取任务超时
[ scrapeTimeout: string | default = 30s]
# 抓取连接是否通过 TLS 安全通道,配置对应的 TLS 参数
[ tlsConfig: TLSConfig ]
# 通过对应的文件读取 bearer token 对应的值,放到抓取任务的 header 中
[ bearerTokenFile: string ]
# 通过对应的 K8S secret key 读取对应的 bearer token,注意 secret namespace 需要和 PodMonitor/ServiceMonitor 相同
[ bearerTokenSecret: string ]
# 解决当抓取的 label 与后端 Prometheus 添加 label 冲突时的处理。
# true: 保留抓取到的 label,忽略与后端 Prometheus 冲突的 label;
# false: 对冲突的 label,把抓取的 label 前加上 exported_<original-label>,添加后端 Prometheus 增加的 label;
[ honorLabels: bool | default = false ]
# 是否使用抓取到 target 上产生的时间。
# true: 如果 target 中有时间,使用 target 上的时间;
# false: 直接忽略 target 上的时间;
[ honorTimestamps: bool | default = true ]
# basic auth 的认证信息,username/password 填写对应 K8S secret key 的值,注意 secret namespace 需要和 PodMonitor/ServiceMonitor 相同。
[ basicAuth: BasicAuth ]
# 通过代理服务来抓取 target 上的指标,填写对应的代理服务地址。
[ proxyUrl: string ]
# 在抓取数据之后,把 target 上对应的 label 通过 relabel 的机制进行改写,按顺序执行多个 relabel 规则。
# relabel_config 详见下面说明。
relabelings:
[ - <relabel_config> ...]
# 数据抓取完成写入之前,通过 relabel 机制进行改写 label 对应的值,按顺序执行多个 relabel 规则。
# relabel_config 详见下面说明。
metricRelabelings:
[ - <relabel_config> ...]
relabel_config 配置
相应配置项说明如下:
# 从原始 labels 中取哪些 label 的值进行 relabel,取出来的值通过 separator 中的定义进行字符拼接。# 如果是 PodMonitor/ServiceMonitor 对应的配置项为 sourceLabels 。[ source_labels: '[' <labelname> [, ...] ']' ]# 定义需要 relabel 的 label 值拼接的字符,默认为 ';'。
[ separator: <string> | default = ; ]
# action 为 replace/hashmod 时,通过 target_label 来指定对应 label name。# 如果是 PodMonitor/ServiceMonitor 对应的配置项为 targetLabel 。
[ target_label: <labelname> ]
# 需要对 source labels 对应值进行正则匹配的表达式。
[ regex: <regex> | default = (.*) ]
# action 为 hashmod 时用到,根据 source label 对应值 md5 取模值。
[ modulus: <int> ]
# action 为 replace 的时候,通过 replacement 来定义当 regex 匹配之后需要替换的表达式,可以结合 regex 正规则表达式替换。
[ replacement: <string> | default = $1 ]
# 基于 regex 匹配到的值进行相关的操作,对应的 action 如下,默认为 replace:# replace: 如果 regex 匹配到,通过 replacement 中定义的值替换相应的值,并通过 target_label 设值并添加相应的 label # keep: 如果 regex 没有匹配到,丢弃# drop: 如果 regex 匹配到,丢弃# hashmod: 通过 moduels 指定的值把 source label 对应的 md5 值取模,添加一个新的 label,label name 通过 target_label 指定# labelmap: 如果 regex 匹配到,使用 replacement 替换对就的 label name# labeldrop: 如果 regex 匹配到,删除对应的 label# labelkeep: 如果 regex 没有匹配到,删除对应的 label[ action: <relabel_action> | default = replace ]
ServiceMonitor、Endpoint和Exporter的关系
在Prometheus监控系统中,ServiceMonitor、Endpoint和Exporter是三个关键组件,它们之间的关系如下:
- Exporter:Exporter是一个独立的进程或服务,用于收集指标并将其暴露为HTTP端点。例如,Node Exporter用于收集服务器相关的指标,而MySQL Exporter用于收集数据库相关的指标。
- Endpoint:Endpoint是Exporter提供指标的网络地址和端口。在访问时,Prometheus会向该地址发送HTTP请求,并从响应中获取指标数据。
- ServiceMonitor:ServiceMonitor定义了一组具有相同标签(Label)的Endpoint,并由Prometheus定期轮询这些Endpoint以获取指标数据。ServiceMonitor的标签通常与Kubernetes服务标签匹配,因此可以轻松地监控Kubernetes集群中的服务。
总之,Exporter负责采集指标,Endpoint提供指标的网络地址和端口,而ServiceMonitor定义了一组具有相同标签的Endpoint并定期轮询这些Endpoint以获取指标数据。这些组成部分共同构成了Prometheus监控体系中的重要组成部分。
无法发现监控目标
通过ServiceMonitor监控应用时,如果监控没有找到目标主机的排查步骤瓶骤大致如下:
确认ServiceMonitor是否成功创建。
确认Prometheus是否生成了相关配置
确认存在ServiceMonitor匹配的Service。
确认通过Service能够访问程序的Metrics接口。
确认Service的端口和Scheme、ServiceMonitor一致
添加etcd与mysql监控
vim etcd-svc.yaml
apiVersion: v1
kind: Endpoints
metadata:
labels:
app: etcd-prom
name: etcd-prom
namespace: kube-system
subsets:
- addresses:
- ip: YOUR_ETCD_IP01
- ip: YOUR_ETCD_IP02
- ip: YOUR_ETCD_IP03
ports:
- name: https-metrics
port: 2379 # etcd端口
protocol: TCP
apiVersion: v1
kind: Service
metadata:
labels:
app: etcd-prom
name: etcd-prom
namespace: kube-system
spec:
ports:
- name: https-metrics
port: 2379
protocol: TCP
targetPort: 2379
type: ClusterIP
servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: etcd
namespace: monitoring
labels:
app: etcd
spec:
jobLabel: k8s-app
endpoints:
- interval: 30s
port: https-metrics # 这个port对应 Service.spec.ports.name
scheme: https
tlsConfig:
caFile: /etc/prometheus/secrets/etcd-ssl/etcd-ca.pem #证书路径
certFile: /etc/prometheus/secrets/etcd-ssl/etcd.pem
keyFile: /etc/prometheus/secrets/etcd-ssl/etcd-key.pem
insecureSkipVerify: true # 关闭证书校验
selector:
matchLabels:
app: etcd-prom # 跟Service的lables保持一致
namespaceSelector:
matchNames:
- kube-system
mysql-exporter.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-exporter
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
k8s-app: mysql-exporter
template:
metadata:
labels:
k8s-app: mysql-exporter
spec:
containers:
- name: mysql-exporter
image: registry.cn-beijing.aliyuncs.com/dotbalo/mysqld-exporter
env:
- name: DATA_SOURCE_NAME
value: "exporter:exporter@(mysql.default:3306)/"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9104
---
apiVersion: v1
kind: Service
metadata:
name: mysql-exporter
namespace: monitoring
labels:
k8s-app: mysql-exporter
spec:
type: ClusterIP
selector:
k8s-app: mysql-exporter
ports:
- name: api
port: 9104
protocol: TCP
mysql-sm.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mysql-exporter
namespace: monitoring
labels:
k8s-app: mysql-exporter
namespace: monitoring
spec:
jobLabel: k8s-app
endpoints:
- port: api
interval: 30s
scheme: http
selector:
matchLabels:
k8s-app: mysql-exporter
namespaceSelector:
matchNames:
- monitoring
黑盒监控
对MySQL或者Etcd的监控都是监控应用本身,也就是程序内部的一些指标,这类监控关注的是原因,一般为出现问题的根本,此类监控称为白盒监控。
还有一类监控关注的是现象,也就是正在发生的告警,比如某个网站突然慢了,或者打不开了。此类告警是站在用户的角度看到的东西,比较关注现象,表示正在发生的问题,这类监控称为黑盒监控。白盒监控可以通过Exporter采集数据,黑盒监控也可以通过Exporter采集数据,新版本的Prometheus Stack已经默认安装了Blackbox Exporter,可以用其采集某个域名、接口或者TCP连接的
状态、是否可用等。
可以通过以下命令查看:新版Prometheus Stack已经默认安装了Blackbox Exporter,
kubectl get po -n monitoring -l app,kubernetes,io/name=blackbox-exporter
同时也会创建一个Service,可以通过该Service访问Blackbox Exporter并传递一些参数:
kubectl get svc -n monitoring -l app.kubernetes.io/name=blackbox-exporter
静态配置
之前配置监控目标时,用的都是ServiceMonitor,但是ServiceMonitor可能会有一些限制。比如,如果没有安装Prometheus Operator,可能就无法使用ServiceMonitor,另外并不是所有的监控都能使用ServiceMonitor进行配置,或者使用ServiceMonitor配置显得过于烦琐
黑盒监控使用ServiceMonitor就显得过于复杂,使用传统的配置方式,直接将target传递给Blackbox Exporter即可。虽然本书使用的是Operator安装Prometheus,但是它也是支持静态配置的,比如可以用Prometheus监控windows
Prometheus语法
此时得到的结果为监柜目标主机磕盘可尼率大于60%的主机,如果将大于60改为小于20.就是负所有磁盘可用率小于20%的主机,此时是不是就应该产生告警?所以说将PromQL的语法稍加工即为我们想要的告警条件
除了以上判断语往外,Prometheus支持如下判断:
==:相等
!=:不相等
>:大于
<:小于
>=:大专等手。
<=:小于等于。
上述法只是做了一个简单的判断,比如只过滤了磁盘可用率大于60%的指标,如果想要过游其他范围也是支持的、比如圈盘可用率大于30%小于等于60%的主机:
30 < ({noda filesyatem avail_bytesfmountpoint="/} / node_filesyetem eize bytes {mountpoint-"/"})*100 = 60
在语句的前面加上“30<”,后面加上“<=”60。也可以用and进行联合查询
(node_filesyatem availbytes(mountpoint="/”] / nodefilesyatem size bytescountpoint-"/myy,ts“100 > 30 and (node filesysten avadl bytes(mountpointe"/") /lodn tilenyaten 3ize bytes(mountpoint-"/") ) * 100 <=60
除了and外,也支持or和unlcss:
and:并且
or:或者。
unlcss:排除。
Prometheus函数
我们可以继续使用topk函数,找到统计结果中次数多的几个结果。比如找到排名前5的数据
topk(5, sum(http geqoest_total) by (statuscode, handler))
PromQL开箱即用的函数有很多,比如取最后3个数据:
grafana(3, sum(http request_total) by (statuscode, handler))
找出统计结果中最小的数据:
min (node_filesystem avail bytes(mountpoint="/“})
最大的数据:
max(node filesystem avail bytes(mountpoint="/"))
平均值:
avg(node filesystem avail bytes(mountpoint="/))
四舍五入,向上取最接近的整数,比如2.79一3:
ceil(node filesystem files free(mountpoint="/"} / 1024 / 1024)
向下取整数,比如2.79-2:
floor(node filesystem files free(mountpoint="/") / 1024 / 1024)
对结果进行正向排序:
sort(sum(http request total) by (handler, statuscode))
对结果进行逆向排序:
sort desc(sum(http request total) by (handler, gtatusaode))
predict linear函数可以用于预测分析和预测性告警,比如可以根据一天的数据预测4个磁盘分区的空间会不会小于0:
predict_linear(node_filesystem files free(mountpoint="/") [1d] , 4*3600) < 0
除了上述函数,还有几个比较重要的函数,比如increase、 rate、irate。其中increase用开段时间范围内数据的增长,rate和irate用于计算增长率。比如查询某个请求在1小时内增长了多少
increase(http_request_total(handler="/api/datasources/proxy/:id/*",method="get",namespace='monitoring",service="grafana",statuscode="200”}[1h]
将1小时增长的数量除以该时间即为增长率:
increase(http_request_total(handler="/api/datasources/proxy/:id",method="get”,espace="monitoring",service="grafana",statuscode="200")[1h]) / 3600
当然,increase也可以用于磁盘、CPU、内存等指标,读者可以发挥一下自己的想象。相ncrease,rate可以直接计算出某个指标在给定时间范围内的增长率,比如还是计算1小时的增长率可以用rate函数进行计算:
rate(http_request_total(handler="/api/datasources/proxy/:id/",method="gat",namesfce="monitoring”,service="grafana",statuscode="200"}[1h])
在使用rate和increase时,难免会遇到一个问题,就是常说的“长尾效应”,也就是某个招标直处于一个数值,这个增长率即为0,此时会出现误判。比如某个主机的避盘空间已经在昨天达了100%,此时查询1小时的增长率,由于没有变化,因此无法计算在这个时间窗口的平均增长就意味着无法反映此问题。
PromQL针对“长尾效应”提供了一个更加灵敏的函数: irate,同样用于计算区间向量的增长速率,但是irate计算的是瞬时增长率,即irate是通过区间向量中最后两个样本数据来计算区间向量的增长率的,这种方式可以适当避免一些指标的“长尾效应”
虽然irate较rate提供了更高的灵敏度,但是如果需要分析长期趋势,或者在配置告警规则时,irate过高的灵敏度会造成干扰,针对长期趋势分析和告警规则,更推荐使用rate函数。
Alter报警规则
Alertmanagcr的配置主要分为5大块:
Global: 全局配置,主要进行一些通用的配置,比如邮伴通如的账号、密码、SMTP服务器微信告警等。Global块配置下的配置选项在参配置文伴肉的所有配置项下可见,但是文件内其他位置的子配置可以覆盖Global配置。
Tomplatcs:用于放置自定义模板的位置
Route: 告警路由配置,用于告警信息的分组路由,可以将不同分组的告警发送给不同的收件人,比如将数据库告警发送给DBA,服务器告警发送给OPS.
Inhibit_rules: 告警抑制、主要用于减少告警的次数,防止“告警轰炸”。比如某个宿球宕机,可能会引起容器重建、漂移、服务不可用等一系列问题,如果每个异常均有告帮会一次性发送很多告警,造成告警轰炸,并且也会干扰定位问题的思路,所以可以使用警抑制,屏蔽由宿主机宏机引来的其他问题,只发送宿主机宕机的消息即可。
Rcccivers; 告警收件人配置、每个receiver都有一个名字,经过route分组并且路由后需定一个reccivcr,就是在此位置配置的。
了解完Alcrtmanagr主要的配置块后,接下来对Alertmanager比较重要的Route单独讲解,其配置会在实践中进行补充。
从配置文件可以看出,路由配置块的项级配置由route开始,它是整个路由的人口,称作根路由,每一条告警进来后,都先进入rouse,之后根据告警自身的标签Aroutcgroup_by配置的字段进行分组。比如可以根据job、csr或看其他自定义的标签称进行分组,分组后进入子路由(通过rouwe.routes限置子路由),遇一步通行更加细粒度的划分比如job名称包含mysql的发送给DBA组。
除了group by route;外。Route还有以下常用的配置:
receiver:告警的通知目标。需爱和rcceivers配置中的namc进行匹配。需要注意的是,rowlo.rouics下也可以有ncciver配置,优先级高于routc,rcccivcr配置的默认接收人,当告警没有匹配到子路由时,会使用route.reccivcr进行通知,比如上述配置中的Dcfault.
group_by:分组配置,值奏型为列表。比如配置成[job,severity],代表告警信息包含job和scvcrity标签的会进行分组,且标签的kcy和value都相同才会被分到一组。continue: 决定匹配到第一个路由后,是否继续后续匹配。默认为false,即匹配到第一个子
match:一对一匹配规则,比如match配置的为job:mysql,那么具有job=mysql的告警会进节点后停止继续匹配。
match_rc:和match类似,只不过match_re是正则匹配。
matchcrs:这是Alcrtmanager 0.22版本新添加的一个配置项,用于替换match和match re,如入该路由。果读者用0.22以上版本的Alertmanager,可以尝试使用该参数。Matchers设计理念参考了Prometheus和OpenMetircs,可以写成这样:
匹配foo等于bar且dings不等于bums:
matchers:
- foo = bar
- dings != bums
匹配foo等于bar和baz,且dings不等于bums:
matchers:["foo = bar,baz","dings != bums"]
匹配foo等于bar且dings不等于bums的另一种写法,和PromQL类似:
matchers:[ ' { foo="bar",dings!="bums"} ' ]
group_wait: 告警通知等待,值类型为字符串。若一组新的告警产生,则会等group_wait后再发送通知,该功能主要用于当告警在很短时间内接连产生时,在group_wait内合并为单一的告警后再发送,防止告警过多,默认值为30s。
group_interval: 同一组告警通知后,如果有新的告警添加到该组中,再次发送告警通知的时间,默认值为5m。
repeat_interval:如果一条告警通知已成功发送,且在间隔repeat interval后,该告警仍然术被设置为resolved,则会再次发送该告警通知,默认值为4h。
以上即为Alertmanager常用的路由配置,可以看到Alertmanager的路由和匹配规则非常灵活通过不同的路由嵌套和匹配规则可以达到不同的通知效果。
安装初始容易产生的告警
KubeSchedulerDown和KubeControllerManagerDown:可以参考15.3.3节的ServiceMonitor进行(加上schedule和controller的监控)
Watchdog:并非是一个异常的告警,而是Promethcus集群的状态监控,它表示Prometheus解决。集群的状态是正常的,可以将此告警关闭.
CPUThrottlingHigh: 谊告警反映的是最近5分钟超过25%的CPU执行周期受到限制的容器一般是limit没置得低或者未设置引起的。可以将此告警关闭,或者合理配置容器的resources
NodeClockNotSynchronising: 该告警是由于主机和时间服务器无法连接导致的,读者可能参数。并没有此告警,该告警可以直接关闭,也可以通过配置NTP服务器来解决。
PrometheusRule配置
meladata.labels: PromctheusRule有两个比较重要的标签,即prometheus和role,这两个标签必须在PrometheusRule中配置,且值必须分别为K8s和alert-rules,这样才能让Promcthcus发现该配置。可以通过kubectl get prometheus -n monitoring k8s -oyaml查看ruleSclector的配置
spec.groups:相当于对PromethcusRulc进行分组,可以配置多个,本示例只配置了一个名为blackbox-cxporter的纽。nulcs; 该组下的告警策略可以配置多个,本例只配置了一个延迟的告警.
description:用来对告警进行描述,{{ $labels.instance }}用来取出告警规则中的标签的值用来区分是哪个实例出了问题,具体的标签可以通过PromQL查询显示,{{ Svalue }}即为expr表达式的结果
expr:此处的表达式为sum(probe http_duration _seconds{job=~"blackbox"}) by (instance)>1。意味着只要探测延迟大于1秒,就会触发告警。由于probe_http_duration seconds探测细分为connect、 proccssing、resolve、 tls、transfer, 因此需要根据instance进行汇总。
labels:告警规则的标签,本例添加了一个额外的标签type: blackbox,可以用于告警的路由,Severity为告警的级别,可以根据不同的告警设置不同的级别。
小结:
Prometheus在生产环境中的常用配置,实现了业务的监控和告警,并且使用徽信和邮件进行了告警的通知,如果是其他通知方式,可以参考官方文档和其他资料,逻辑都是类似的.另外,关于云原生和非云原生应用的监控,其监控流程类似,只是非云原生应用需要单独的Exporter进行数据采集。
具体的监控和告警流程可以划分为如下几个步骤(非云原生应用):
找到对应服务的Exporter (如果是自有业务,可能需要自行暴露数据)。
如果是Kubernetes集群外部服务,可能需要创建单独的Service指向该服务,直接使用服务IP也可以。
创建Exporter并配置被监控端的IP或Service.
创建Exporter的Service用于被Prometheus发现并注册。
创建的ServiceMonitor将被监控资源注册至Prometheus (也可以使用静态配置)配置服务的告警策略
配置服务的告警路由,将告警发送给指定的人。
对于云原生应用:如果是Kubernetes集群外部服务,可能需要创建单独的Service指向该服务创建的ServiceMonitor将被监控资源注册至Promthous (也可以使用静态配置)。
配置服务的告警策略
配置服务的告警路由,将告警发送给指定的人。