首页 文章 精选 留言 我的

精选列表

搜索[Agent体系],共10000篇文章
优秀的个人博客,低调大师

Python 完美诠释"高内聚"概念的 IO 流 API 体系结构

1. 前言 第一次接触 Python 语言的 IO API 时,是惊艳的。相比较其它语言所提供的 IO 流 API 。 无论是站在使用者的角度还是站在底层设计者的角度,都可以称得上无与伦比。 很多人在学习 JAVA 语言中的 IO 流 API 时,几乎是崩溃的。其 API 太多、API 之间的关系过于复杂。类的层次结构需要花费很多时间才能搞明白。API 设计者未免有炫技之嫌。 而 Python 的 IO 流操作,才真正应了哪句话:人生苦短,我学 python 。 以 open( ) 函数 为操作起点,便捷、快速地完成所有操作,绝对算得上轻量级设计的典范,且高度诠释了“高内聚”概念。使用起来颇有“四两拨千金”的轻松。 通过了解 open( ) 函数的参数设计,其开闭设计思想可谓使用到了极致。 2. open( ) 函数 2.1 函数原型 def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True): …… 2.2 函数功能 打开一个指定位置的文件并返回 IO 流对象。 2.3 函数参数 Tip: open( ) 函数的参数看起来虽然有点多,在使用时,很多参数都可以采用默认设置,它会提供最优的工作方案。 file 参数: 指定文件位置。可以是一个字符串描述的文件路径,也可以是一个文件描述符(int 类型)。 Tip: 当使用字符串描述时,可以是绝对路径,也可以是相对路径。 绝对路径: 以绝对位置作为路径的起点。 不同的操作系统中会有差异性,windows 以逻辑盘符为绝对起点,Liunx 以 "/" 根目录为绝对起点。 file=open("d:/guoke.txt") Tip: 上述代码运行时,需要保证在系统的 d 盘下有一个名字 "guoke.txt" 的文件。 相对路径: 所谓相对路径指以某一个已经存在的路径(或叫参照目录、当前目录)做起点。 默认情况下,相对路径以当前项目目录作为参照目录。可以使用 os 模块 中的 getcwd( ) 方法获取当前参照目录的信息。 import os print(os.getcwd()) # 本代码的测试项目放在 d:\myc 下;项目名称:filedmeo # 输出结果 # D:\myc\filedmeo 如下代码需要保证在项目目录中存在 " guoke.txt " file = open("guoke.txt") # 执行时, python 解释器会自动拼接一个完整路径 D:\myc\filedmeo\guoke.txt 参照目录 可以是不固定的,而是可变的。 改变相对路径的参考目录: import os # 把 d 盘作为当前目录 os.chdir("d:/") print(os.getcwd()) file = open("guoke.txt") # python 解释器会从 d 盘根目录下查找 guoke.txt 文件 描述符: 使用 open( ) 函数打开一个文件后,python 解释器系统会为此文件指定一个唯一的数字标识符。可以用此描述符作为 open( ) 参数。 file = open("guo_ke.txt") # fileno() 获取文件的描述符 file1 = open(file.fileno()) Tip: 用户文件的描述符从 3 开始。0,1,2 是系统保留文件描述符。 0:表示标准输入(键盘)设备描述符。 file = open(0) print("请输入一个数字:") res = file.readline() print("回显:", res) ''' 输出结果 请输入一个数字: 88 回显: 88 ''' 1:表示标准输出设备(显示器)描述符。 file = open(1, "w") file.write("you are welcome!") #类似于 print("you are welcome!") 的功能 2:表示标准错误输出设备(显示器)描述符。 file = open(2, "w") file.write("you are welcome!") #输出文字会以红色亮显 mode: 文件操作模式。默认为 "r" ,表示只读模式。 模式关键字 描述 异常 'r' 以只读方式打开文件 文件不存时,会抛出 FileNotFoundError 异常 ‘r+’ 以可读、可写方式打开文件 文件不存时,会抛出 FileNotFoundError 异常 ‘w’ 以可写方式打开文件 文件不存在时,创建一个字节 0 的空文件 ‘w+’ 以可写、可读方式打开文件(清空原内容) 文件不存在时,创建一个字节 0 的空文件 ‘a’ 以追加方式打开文件 文件不存在时,创建一个字节 0 的空文件 ‘a+’ 以可追加、可读方式打开文件 文件不存在时,创建一个字节 0 的空文件 ‘t’ 以文本文件格式打开文件 默认 ‘b’ 以二进制格式打开文件 ‘x’ 创建空文件并且可写 文件存在时,抛出 FileExistsError 异常 只要在模式组合中有 'r' 关键字,则文件必须提前存在: file = open("guo_ke.txt") file = open("guo_ke.txt", 'r') file = open("guo_ke.txt", 'rt') file = open("guo_ke.txt", 'r+t') 只要在模式组合中有 ‘w’ 关键字,则文件可以不必预先存在,如果存在,则原文件中内容会被清空。 # 可写 file = open("guo_ke.txt", 'w') # 可写、可读 file = open("guo_ke.txt", 'w+') 只要在模式组合中有 ‘a’ 关键字,则文件可以不必预先存在,如果存在,原文件中内空不会被清空 # 追加写 file = open("guo_ke.txt", 'a') # 追加写、且可读 file = open("guo_ke.txt", 'a+') buffering: 设置缓冲策略。可取值为 0、1、>1 。 0: 在二进制模式下关闭缓冲。 **1:**在文本模式下使用行缓冲。 行缓冲:以行数据为单位进行缓存。 >1 的整数: 指定缓冲区的大小(以字节为单位)。 如果没有指定 buffering 参数,则会提供默认缓冲策略: 二进制文件使用固定大小的缓冲块。 在许多系统上,缓冲区的长度通常为 4096 或 8192 字节。 "Interactive" 文本文件( isatty() 返回 True 的文件)使用行缓冲。其他文本文件使用和二进制文件相同的缓冲策略。 isatty( ) 方法检测文件是否连接到一个终端设备。 encoding: 指定解码或编码文件时使用的编码名称。 只能用于文本文件。默认使用平台编码。 errors: 指定如何处理编码和解码时抛出的错误。可选项如下: strict: 如果存在编码错误,则引发 ValueError 异常。 默认值 None 具有相同的效果。 ignore: 忽略错误。有可能会数据丢失。 replace: 会将替换标记(例如 '?' )插入有错误数据的地方。 newline: 在读或写文本内容时如何处理换行符号。可取值 None,' ','\n','\r' 和 '\r\n'。 OS 不同,换行符的描述也有差异。Unix 的行结束 '\n'、Windows 中为 '\r\n' 从流中读数据时,如果 newline 为 None,则启用平台约定换行模式。 写入流时,如果 newline 为 None,则写入的任何 '\n' 字符都将转换为系统默认行分隔符 。如果 newline 是 ' ' 或 '\n',则直接写入。如果 newline 是任何其他合法值,则写入的任何 '\n' 字符将被转换为给定的字符串。 closefd: file = open("guo_ke.txt",closefd=False) ''' 输出结果 Traceback (most recent call last): File "D:/myc/filedmeo/文件嵌套.py", line 1, in <module> file = open("guo_ke.txt",closefd=False) ValueError: Cannot use closefd=False with file name ''' 如果通过一个字符串路径描述打开文件, closefd 必须为 True (默认值),否则将引发错误。 file = open("guo_ke.txt", ) # 通过 file 文件的描述符打开文件 file1 = open(file.fileno(), closefd=False) file1.close() print("先打开文件:", file.closed) print("后打开文件:", file1.closed) ''' 输出结果 先打开文件: False 后打开文件: True ''' 当 open file1 文件时设置为 closefd=False ,则当 file1 文件关闭后,file 文件将保持打开状态。 opener:可理解为 open( ) 函数是一个高级封装对象,本质是通过 opener 参数接入了一个真正的具有底层文件操作能力的接口。 import os def opener(path, flags): return os.open(path, flags) # 调用 opener('guo_ke.txt','r') 时的参数来自于 open() 的第一个和第二个 with open('guo_ke.txt', 'r', opener=opener) as f: print(f.read()) 默认 opener 参数引用的就是 os.open( ) 方法。 3. 读写操作 调用 open( ) 函数后会返回一个 IO 流对象。IO 流对象中提供了常规的与读写相关的属性和方法。 class IO(Generic[AnyStr]): #返回文件的读写模式 @abstractproperty def mode(self) -> str: pass #返回文件的名称 @abstractproperty def name(self) -> str: pass #关闭文件 @abstractmethod def close(self) -> None: pass #判断文件是否关闭 @abstractproperty def closed(self) -> bool: pass #返回文件描述符号,每打开一个文件,python 会分配一个唯一的数字描述符号 @abstractmethod def fileno(self) -> int: pass #刷新缓存中的内容 @abstractmethod def flush(self) -> None: pass #是否连接到一个终端设备 @abstractmethod def isatty(self) -> bool: pass # 参数 n 为 -1 或不传递时,一次性读取文件中的所有内容,如果文件内容过多,可分多次读取 # 读取到文件末尾时,返回一个空字符串 ('') @abstractmethod def read(self, n: int = -1) -> AnyStr: pass # 文件是否可读 @abstractmethod def readable(self) -> bool: pass # 从文件中读取一行;换行符(\n)留在字符串的末尾 # 返回一个空的字符串时,表示已经到达了文件末尾 # 空行使用 '\n' 表示 @abstractmethod def readline(self, limit: int = -1) -> AnyStr: pass # 读取所有行并存储到列表中 # 也可以使用 list(f) @abstractmethod def readlines(self, hint: int = -1) -> List[AnyStr]: pass # 移动读写光标,改变文件的读写位置 # 通过向一个参考点添加 offset 来计算位置;参考点由 whence 参数指定。 # whence 的 0 值表示从文件开头起算,1 表示使用当前文件位置,2 表示使用文件末尾作为参考点。 # whence 如果省略则默认值为 0,即使用文件开头作为参考点。 @abstractmethod def seek(self, offset: int, whence: int = 0) -> int: pass # 是否可以移动光标 @abstractmethod def seekable(self) -> bool: pass # 返回文件的当前位置 @abstractmethod def tell(self) -> int: pass # 清除内容 @abstractmethod def truncate(self, size: int = None) -> int: pass # 是否可写 @abstractmethod def writable(self) -> bool: pass # 向文件写入内容 @abstractmethod def write(self, s: AnyStr) -> int: pass #向文件写入一行数据 @abstractmethod def writelines(self, lines: List[AnyStr]) -> None: pass 调用 open( ) 函数中使用文本模式时返回的是 TextIO 对象,相比较父类,多了几个特定于文本操作的属性。 class TextIO(IO[str]): # 缓存信息 @abstractproperty def buffer(self) -> BinaryIO: pass # 设置编码 @abstractproperty def encoding(self) -> str: pass # 设备错误处理方案 @abstractproperty def errors(self) -> Optional[str]: pass # 设置行缓存 @abstractproperty def line_buffering(self) -> bool: pass # 换行符的设置方案 @abstractproperty def newlines(self) -> Any: pass 3.1 文本文件读操作 基本操作 file = open("guo_ke.txt", mode='r') print("读写模式:", file.mode) print("文件名:", file.name) print("文件是否关闭:", file.closed) print("文件描述符号:", file.fileno()) print("文件是否可读", file.readable()) print("是否是标准输入流:", file.isatty()) print("文件是否可写:", file.writable()) print("缓存方案", file.buffer) print("文件默认编码:", file.encoding) print("编程错误处理方案", file.errors) print("是否设置行缓存", file.line_buffering) print("换行符的设置方案", file.newlines) ''' 输出结果 读写模式: r 文件名: guo_ke.txt 文件是否关闭: False 文件描述符号: 3 文件是否可读 True 是否是标准输入流: False 文件是否可写: False 缓存方案 <_io.BufferedReader name='guo_ke.txt'> 文件默认编码: cp936 编程错误处理方案 strict 是否设置行缓存 False 换行符的设置方案 None ''' cp936 指的是系统的第 936 号编码方案,即 GBK 编码。 多样化的读方法: 无论是读还是写时,需要理解一个文件指针(光标)的概念,也可理解为文件位置。读或写时,只能从当前位置向前移动。 提前准备好一个文本文件,在文件中写入如下内容 You hide in my heart deeply. Happiness! There is only you and I together time... With you just I don't want to give anyone the chance. Honey, can you marry me, I'll marry you! Don't know love you count is a close reason? read( ) 方法的使用 file = open("guo_ke.txt", "r") print("----------读取所有内容--------------") res = file.read() print(res) print("----------读取部分内容--------------") # 重新回到文件头 file.seek(0) res = file.read(100) print(res) # 关闭文件资源 file.close() ''' 输出结果 ----------读取所有内容-------------- You hide in my heart deeply. Happiness! There is only you and I together time... With you just I don't want to give anyone the chance. Honey, can you marry me, I'll marry you! Don't know love you count is a close reason? ----------读取部分内容-------------- You hide in my heart deeply. Happiness! There is only you and I together time... With you just I don ''' 这里有一个细节要注意: 第一次读取完所有文件内容后,读取位置已经移到了文件尾部。继续读取时是不能读到数据的。 可通过 seek( ) 方法,把光标移到文件头部。 readline( ) 方法的使用 file = open("guo_ke.txt", "r") print("---------读取一行--------") res = file.readline() print("数据长度:", len(res)) print(res) print("-----------限制内容-------------") res = file.readline(10) print("数据长度:", len(res)) print(res) print("-----------以行为单位读取所有数据-------------") #回到文件头部位置 file.seek(0) while True: res = file.readline() print(res) if res == "": break file.close() ''' 输出结果 ---------读取一行-------- 数据长度: 29 You hide in my heart deeply. -----------限制内容------------- 数据长度: 10 Happiness! -----------以行为单位读取所有数据------------- You hide in my heart deeply. Happiness! There is only you and I together time... With you just I don't want to give anyone the chance. Honey, can you marry me, I'll marry you! Don't know love you count is a close reason? ''' 一行一行读取所有内容时,输出时会在行与行之间产生一个空行。原因是行结束符号 'n' 会被当成一个空行输出。 readline( ) 还有一个兄弟 readlines() 。把数据以行为单位一次性存储一个列表中. file = open("guo_ke.txt", "r") print("-----------把文件中数据以行为单位存储在列表中---------") res = file.readlines() print(res) file.close() ''' 输出结果 -----------把文件中数据以行为单位存储在列表中--------- ['You hide in my heart deeply.\n', 'Happiness! There is only you and I together time...\n', "With you just I don't want to give anyone the chance.\n", "Honey, can you marry me, I'll marry you!\n", "Don't know love you count is a close reason?"] ''' 注意使用数据时换行符号的影响。 读取所有行也可以使用 ist(f) 方式。 file = open("guo_ke.txt", "r") print(list(file)) 文件对象支持以行为单位进行迭代操作。 file = open("guo_ke.txt", "r") print("-----------迭代方式输出文件内容---------") for f in file: print(f) file.close() 3.2 文本文件写操作 如果使用 "w" 模式进行写操作时,会丢失原来数据。如果不希望这样的事情 发生,可使用 "a" 模式对文写操作。 file = open("guo_ke_0.txt", "w") file.write("this is a test") # 添加新行 file.write("\n") file.write("who are you?") # 把列表中数据一次写入文件 lst = ["food\n", "fish\n", "cat\n"] file.write("\n") file.writelines(lst) file.close() 3.3 编码的问题 对文件同时做读写操作时,请务必保证编码的一致性。 如下面的代码就会出现 UnicodeDecodeError 异常。 file = open("guo_ke_1.txt", mode="w", encoding="utf-8") file.write("你好!果壳……") file.close() file_ = open("guo_ke_1.txt", mode="r", encoding="gbk") res = file_.read() print(res) ''' 输出结果 Traceback (most recent call last): File "D:/myc/filedmeo/乱码问题.py", line 6, in <module> res = file_.read() UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 16: illegal multibyte sequence ''' 3.4 二进制文本件操作 调用 open( ) 函数时使用 mode='rb' 返回的是 BinaryIO 对象。此对象提供了对二进制文件的读写,对二进制文件的读写操作和文本的没有什么太多区别。 文本文件与二进制文本的操作使用一个参数就能灵活切换。 class BinaryIO(IO[bytes]): @abstractmethod def write(self, s: Union[bytes, bytearray]) -> int: pass 4. 总结 open( ) 函数是一个神奇的存在。无论是对文本文件还是二进进制文件,无论是读还是写,它都能工作的很好。不得不佩服 python 设计者的简洁设计理念。 像通过文件描述符打开文件,使用 opener 参数自定义底层实现,都可称得上神来之笔。 另使用文件后一定要关闭,除了可以直接调用 close( ) 方法外,还可能使用 with 语句,此语法结构能自动调用 close(). with open("guo_ke.txt") as f: pass

优秀的个人博客,低调大师

k8s监控体系搭建prometheus+grafana+alertmanager无坑版

2 --> 提前准备 1.已经安装了k8s集群 2.已经安装了storgeclass(可以参考k8s存储管理 https://blog.51cto.com/luoguoling/2966225) 一.安装prometheus 1.0 提前设置namespace apiVersion: v1 kind: Namespace metadata: name: ops 1.1 prometheus配置文件 prometheus-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: ops data: prometheus.yml: | rule_files: - /etc/config/rules/*.rules scrape_configs: - job_name: prometheus static_configs: - targets: - localhost:9090 - job_name: kubernetes-apiservers kubernetes_sd_configs: - role: endpoints relabel_configs: - action: keep regex: default;kubernetes;https source_labels: - __meta_kubernetes_namespace - __meta_kubernetes_service_name - __meta_kubernetes_endpoint_port_name scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - job_name: kubernetes-nodes-kubelet kubernetes_sd_configs: - role: node # 发现集群中的节点 relabel_configs: # 将标签(.*)作为新标签名,原有值不变 - action: labelmap regex: __meta_kubernetes_node_label_(.+) scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - job_name: kubernetes-nodes-cadvisor kubernetes_sd_configs: - role: node relabel_configs: # 将标签(.*)作为新标签名,原有值不变 - action: labelmap regex: __meta_kubernetes_node_label_(.+) # 实际访问指标接口 https://NodeIP:10250/metrics/cadvisor,这里替换默认指标URL路径 - target_label: __metrics_path__ replacement: /metrics/cadvisor scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - job_name: kubernetes-service-endpoints kubernetes_sd_configs: - role: endpoints # 从Service列表中的Endpoint发现Pod为目标 relabel_configs: # Service没配置注解prometheus.io/scrape的不采集 - action: keep regex: true source_labels: - __meta_kubernetes_service_annotation_prometheus_io_scrape # 重命名采集目标协议 - action: replace regex: (https?) source_labels: - __meta_kubernetes_service_annotation_prometheus_io_scheme target_label: __scheme__ # 重命名采集目标指标URL路径 - action: replace regex: (.+) source_labels: - __meta_kubernetes_service_annotation_prometheus_io_path target_label: __metrics_path__ # 重命名采集目标地址 - action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 source_labels: - __address__ - __meta_kubernetes_service_annotation_prometheus_io_port target_label: __address__ # 将K8s标签(.*)作为新标签名,原有值不变 - action: labelmap regex: __meta_kubernetes_service_label_(.+) # 生成命名空间标签 - action: replace source_labels: - __meta_kubernetes_namespace target_label: kubernetes_namespace # 生成Service名称标签 - action: replace source_labels: - __meta_kubernetes_service_name target_label: kubernetes_name - job_name: kubernetes-pods kubernetes_sd_configs: - role: pod # 发现所有Pod为目标 # 重命名采集目标协议 relabel_configs: - action: keep regex: true source_labels: - __meta_kubernetes_pod_annotation_prometheus_io_scrape # 重命名采集目标指标URL路径 - action: replace regex: (.+) source_labels: - __meta_kubernetes_pod_annotation_prometheus_io_path target_label: __metrics_path__ # 重命名采集目标地址 - action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 source_labels: - __address__ - __meta_kubernetes_pod_annotation_prometheus_io_port target_label: __address__ # 将K8s标签(.*)作为新标签名,原有值不变 - action: labelmap regex: __meta_kubernetes_pod_label_(.+) # 生成命名空间标签 - action: replace source_labels: - __meta_kubernetes_namespace target_label: kubernetes_namespace # 生成Service名称标签 - action: replace source_labels: - __meta_kubernetes_pod_name target_label: kubernetes_pod_name alerting: alertmanagers: - static_configs: - targets: ["alertmanager:80"] 1.2 prometheus部署文件 prometheus-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: prometheus namespace: ops labels: k8s-app: prometheus spec: replicas: 1 selector: matchLabels: k8s-app: prometheus template: metadata: labels: k8s-app: prometheus spec: serviceAccountName: prometheus initContainers: - name: "init-chown-data" image: "busybox:latest" # imagePullPolicy: "IfNotPresent" command: ["chown", "-R", "65534:65534", "/data"] volumeMounts: - name: prometheus-data mountPath: /data subPath: "" containers: - name: prometheus-server-configmap-reload image: "jimmidyson/configmap-reload:v0.1" # imagePullPolicy: "IfNotPresent" args: - --volume-dir=/etc/config - --webhook-url=http://localhost:9090/-/reload volumeMounts: - name: config-volume mountPath: /etc/config readOnly: true - mountPath: /etc/localtime name: timezone resources: limits: cpu: 10m memory: 100Mi requests: cpu: 10m memory: 100Mi - name: prometheus-server image: "prom/prometheus:v2.20.0" # imagePullPolicy: "IfNotPresent" args: - --config.file=/etc/config/prometheus.yml - --storage.tsdb.path=/data - --web.console.libraries=/etc/prometheus/console_libraries - --web.console.templates=/etc/prometheus/consoles - --web.enable-lifecycle ports: - containerPort: 9090 readinessProbe: httpGet: path: /-/ready port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 livenessProbe: httpGet: path: /-/healthy port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 resources: limits: cpu: 500m memory: 800Mi requests: cpu: 200m memory: 400Mi volumeMounts: - name: config-volume mountPath: /etc/config - name: prometheus-data mountPath: /data subPath: "" - name: prometheus-rules mountPath: /etc/config/rules - mountPath: /etc/localtime name: timezone volumes: - name: config-volume configMap: name: prometheus-config - name: prometheus-rules configMap: name: prometheus-rules - name: prometheus-data persistentVolumeClaim: claimName: prometheus - name: timezone hostPath: path: /usr/share/zoneinfo/Asia/Shanghai --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: prometheus namespace: ops spec: storageClassName: "managed-nfs-storage" accessModes: - ReadWriteMany resources: requests: storage: 10Gi --- apiVersion: v1 kind: Service metadata: name: prometheus namespace: ops spec: type: NodePort ports: - name: http port: 9090 protocol: TCP targetPort: 9090 nodePort: 30089 selector: k8s-app: prometheus --- apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: ops --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: - "" resources: - nodes - nodes/metrics - services - endpoints - pods verbs: - get - list - watch - apiGroups: - "" resources: - configmaps verbs: - get - nonResourceURLs: - "/metrics" verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: ops 1.3 prometheus配置报警规则 prometheus-rules.yaml apiVersion: v1 kind: ConfigMap metadata: name: prometheus-rules namespace: ops data: general.rules: | groups: - name: general.rules rules: - alert: InstanceDown expr: up == 0 for: 1m labels: severity: error annotations: summary: "Instance {{ $labels.instance }} 停止工作" description: "{{ $labels.instance }} job {{ $labels.job }} 已经停止5分钟以上." node.rules: | groups: - name: node.rules rules: - alert: NodeFilesystemUsage expr: | 100 - (node_filesystem_free{fstype=~"ext4|xfs"} / node_filesystem_size{fstype=~"ext4|xfs"} * 100) > 80 for: 1m labels: severity: warning annotations: summary: "Instance {{ $labels.instance }} : {{ $labels.mountpoint }} 分区使用率过高" description: "{{ $labels.instance }}: {{ $labels.mountpoint }} 分区使用大于80% (当前值: {{ $value }})" - alert: NodeMemoryUsage expr: | 100 - (node_memory_MemFree+node_memory_Cached+node_memory_Buffers) / node_memory_MemTotal * 100 > 20 for: 1m labels: severity: warning annotations: summary: "Instance {{ $labels.instance }} 内存使用率过高" description: "{{ $labels.instance }}内存使用大于80% (当前值: {{ $value }})" - alert: NodeCPUUsage expr: | 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) > 60 for: 1m labels: severity: warning annotations: summary: "Instance {{ $labels.instance }} CPU使用率过高" description: "{{ $labels.instance }}CPU使用大于60% (当前值: {{ $value }})" - alert: KubeNodeNotReady expr: | kube_node_status_condition{condition="Ready",status="true"} == 0 for: 1m labels: severity: error annotations: message: '{{ $labels.node }} 已经有10多分钟没有准备好了.' pod.rules: | groups: - name: pod.rules rules: - alert: PodCPUUsage expr: | sum(rate(container_cpu_usage_seconds_total{image!=""}[1m]) * 100) by (pod_name, namespace) > 5 for: 5m labels: severity: warning annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod_name }} CPU使用大于80% (当前值: {{ $value }})" - alert: PodMemoryUsage expr: | sum(container_memory_rss{image!=""}) by(pod_name, namespace) / sum(container_spec_memory_limit_bytes{image!=""}) by(pod_name, namespace) * 100 != +inf > 80 for: 5m labels: severity: error annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod_name }} 内存使用大于80% (当前值: {{ $value }})" - alert: PodNetworkReceive expr: | sum(rate(container_network_receive_bytes_total{image!="",name=~"^k8s_.*"}[5m]) /1000) by (pod_name,namespace) > 30000 for: 5m labels: severity: warning annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod_name }} 入口流量大于30MB/s (当前值: {{ $value }}K/s)" - alert: PodNetworkTransmit expr: | sum(rate(container_network_transmit_bytes_total{image!="",name=~"^k8s_.*"}[5m]) /1000) by (pod_name,namespace) > 30000 for: 5m labels: severity: warning annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod_name }} 出口流量大于30MB/s (当前值: {{ $value }}/K/s)" - alert: PodRestart expr: | sum(changes(kube_pod_container_status_restarts_total[1m])) by (pod,namespace) > 0 for: 1m labels: severity: warning annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod }} Pod重启 (当前值: {{ $value }})" - alert: PodFailed expr: | sum(kube_pod_status_phase{phase="Failed"}) by (pod,namespace) > 0 for: 5s labels: severity: error annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod }} Pod状态Failed (当前值: {{ $value }})" - alert: PodPending expr: | sum(kube_pod_status_phase{phase="Pending"}) by (pod,namespace) > 0 for: 1m labels: severity: error annotations: summary: "命名空间: {{ $labels.namespace }} | Pod名称: {{ $labels.pod }} Pod状态Pending (当前值: {{ $value }})" e 二.alertmanager搭建 2.1 alertmanager配置文件alertmanger-configmap.yaml 注:邮箱需要自己去网易邮箱申请并且取得授权管理密码 apiVersion: v1 kind: ConfigMap metadata: name: alertmanager-config namespace: ops data: alertmanager.yml: |- global: # 在没有报警的情况下声明为已解决的时间 resolve_timeout: 5m # 配置邮件发送信息 smtp_smarthost: 'smtp.163.com:465' smtp_from: 'xxx@163.com' smtp_auth_username: 'xxx@163.com' smtp_auth_password: 'GMZFNPIWGYEPMGDK' smtp_hello: '163.com' smtp_require_tls: false # 所有报警信息进入后的根路由,用来设置报警的分发策略 route: # 这里的标签列表是接收到报警信息后的重新分组标签,例如,接收到的报警信息里面有许多具有 cluster=A 和 alertname=LatncyHigh 这样的标签的报警信息将会批量被聚合到一个分组里面 group_by: ['alertname', 'cluster'] # 当一个新的报警分组被创建后,需要等待至少group_wait时间来初始化通知,这种方式可以确保您能有足够的时间为同一分组来获取多个警报,然后一起触发这个报警信息。 group_wait: 30s # 当第一个报警发送后,等待'group_interval'时间来发送新的一组报警信息。 group_interval: 5m # 如果一个报警信息已经发送成功了,等待'repeat_interval'时间来重新发送他们 repeat_interval: 5m # 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器 receiver: default # 上面所有的属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。 routes: - receiver: email group_wait: 10s match: team: node receivers: - name: 'default' email_configs: - to: 'xxx@xx.com' send_resolved: true - name: 'email' email_configs: - to: 'xxx@qq.com' send_resolved: true 2.2 alertmanager template文件alertmanager-template.yaml #自定义告警模板 apiVersion: v1 kind: ConfigMap metadata: name: alertmanager-template-volume namespace: ops data: email.tmpl: | {{ define "email.html" }} {{ range .Alerts }} <pre> ========start========== 告警程序: prometheus_alert_email 告警级别: {{ .Labels.severity }} 级别 告警类型: {{ .Labels.alertname }} 故障主机: {{ .Labels.instance }} 告警主题: {{ .Annotations.summary }} 告警详情: {{ .Annotations.description }} 处理方法: {{ .Annotations.console }} 触发时间: {{ .StartsAt.Format "2006-01-02 15:04:05" }} ========end========== </pre> {{ end }} {{ end }} 2.3alertmanager部署文件alertmanager-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: alertmanager namespace: ops spec: replicas: 1 selector: matchLabels: k8s-app: alertmanager version: v0.14.0 template: metadata: labels: k8s-app: alertmanager version: v0.14.0 spec: containers: - name: prometheus-alertmanager image: "prom/alertmanager:v0.14.0" imagePullPolicy: "IfNotPresent" args: - --config.file=/etc/config/alertmanager.yml - --storage.path=/data - --web.external-url=/ ports: - containerPort: 9093 readinessProbe: httpGet: path: /#/status port: 9093 initialDelaySeconds: 30 timeoutSeconds: 30 volumeMounts: - name: config-volume mountPath: /etc/config #自定义告警模板 - name: config-template-volume mountPath: /etc/config/template - name: storage-volume mountPath: "/data" subPath: "" - mountPath: /etc/localtime name: timezone resources: limits: cpu: 10m memory: 200Mi requests: cpu: 10m memory: 100Mi - name: prometheus-alertmanager-configmap-reload image: "jimmidyson/configmap-reload:v0.1" imagePullPolicy: "IfNotPresent" args: - --volume-dir=/etc/config - --webhook-url=http://localhost:9093/-/reload volumeMounts: - name: config-volume mountPath: /etc/config readOnly: true resources: limits: cpu: 10m memory: 200Mi requests: cpu: 10m memory: 100Mi volumes: - name: config-volume configMap: name: alertmanager-config - name: config-template-volume configMap: name: alertmanager-template-volume - name: storage-volume persistentVolumeClaim: claimName: alertmanager - name: timezone hostPath: path: /usr/share/zoneinfo/Asia/Shanghai --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: alertmanager namespace: ops spec: storageClassName: managed-nfs-storage accessModes: - ReadWriteOnce resources: requests: storage: "2Gi" --- apiVersion: v1 kind: Service metadata: name: alertmanager namespace: ops labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "Alertmanager" spec: type: "NodePort" ports: - name: http port: 80 protocol: TCP targetPort: 9093 nodePort: 30093 selector: k8s-app: alertmanager 三 安装监控界面grafana 3.1 grafana部署文件 apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: ops spec: replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: containers: - name: grafana image: grafana/grafana:7.1.0 ports: - containerPort: 3000 protocol: TCP resources: limits: cpu: 100m memory: 256Mi requests: cpu: 100m memory: 256Mi volumeMounts: - name: grafana-data mountPath: /var/lib/grafana subPath: grafana - mountPath: /etc/localtime name: timezone securityContext: fsGroup: 472 runAsUser: 472 volumes: - name: grafana-data persistentVolumeClaim: claimName: grafana - name: timezone hostPath: path: /usr/share/zoneinfo/Asia/Shanghai --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: grafana namespace: ops spec: storageClassName: "managed-nfs-storage" accessModes: - ReadWriteMany resources: requests: storage: 5Gi --- apiVersion: v1 kind: Service metadata: name: grafana namespace: ops spec: type: NodePort ports: - port : 80 targetPort: 3000 nodePort: 30030 selector: app: grafana 3.2 数据源和监控模板 数据源填写配置prometheus.ops:9090 模板可以下载下面3个 k8s工作节点监控 k8s集群资源监控 k8s资源对象状态监控 k8s监控模板 提取码: aexi 操作结果展示 1.prometheus效果 4.2 alertmanager显示效果 4.3报警结果 4.4 grafana监控图部分图 文章参考了https://i4t.com/4197.html

优秀的个人博客,低调大师

数据中台的OneModel体系与经典维度建模理论有何关系?

作者:柯根 更多内容详见数据中台官网 https://dp.alibaba.com维度建模经典理论维度建模是数据仓库建设中的一种数据建模方法,将数据结构化的逻辑设计方法,它将客观世界划分为度量和上下文,Kimball最先提出这一概念。其最简单的描述就是,按照事实表,维度表来构建数据仓库,数据集市。这种方法的最被人广泛知晓的名字就是星型模式。实体关系模型(E-R)建模通常用于为单位的所有进程创建一个复杂的模型。这种方法已被证实在创建高效的联机事务处理 (OLTP) 系统方面很有效。相反,维度建模针对零散的业务进程创建个别的模型。例如,销售信息可以创建为一个模型,库存可以创建为另一个模型,而客户帐户也可以创建为另一个模型。每个模型捕获事实数据表中的事实,以及那些事实在链接到事实数据表的维度表中的特性。由这些排列产生的架构称为星型模式或

优秀的个人博客,低调大师

基于MaxCompute/Dataworks实现数据仓库管理与全链路数据体系

前言 就这样,大数据领域蓬勃发展了好几年,有很多伙伴执迷于技术,成为了分布式计算与存储的领域专家。也有很多伙伴执迷于数据,成为了行业的数据研发专家。当然还有很多小伙伴,热衷于工具系统开发,成为了数据技术专家。那么我们回过头来考虑,什么是大数据,什么又是数据仓库,什么又是数据技术。大数据其实是个非常笼统的感念,它是由数据仓库演化而来的数据与技术方法论,那么我们先说一下数据仓库的由来: 早在多年以前在Hadoop、Spark、Storm、Kafka等系列分布式计算与存储、消息中间件还没有成熟的时候,数据仓库主要基于Oracle的数仓建设,即便是现在比较流行的大数据产品,如阿里巴巴MaxCompute,仍然使用的是关系理论描述数据之间的关系,只是基于其数据存取的特点在关系数据模型的范式上有了不同的选择而已。但随着时间的推移,传统数据

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册