рдХреБрдмреЗрд░рдиреЗрдЯреНрд╕ рдореЗрдЬрдмрд╛рдиреЛрдВ рдХреЗ рдмреАрдЪ рдкрд┐рдВрдЧ рдХреА рдирд┐рдЧрд░рд╛рдиреА рд╣рдорд╛рд░рд╛ рдиреБрд╕реНрдЦрд╛ рд╣реИ



рдХреБрдмреЗрд░рдиреЗрдЯ рдХреНрд▓рд╕реНрдЯрд░ рдореЗрдВ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдирд┐рджрд╛рди рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдЕрдХреНрд╕рд░ рдзреНрдпрд╛рди рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдХрднреА-рдХрднреА рдХреНрд▓рд╕реНрдЯрд░ рдиреЛрдбреНрд╕ рдореЗрдВ рд╕реЗ рдПрдХ * рдФрд░, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдпрд╣ рджреБрд░реНрд▓рдн рдФрд░ рдЕрдЬреАрдм рд╣реИред рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдПрдХ рдРрд╕реЗ рдЙрдкрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рддрдХ рдкрд┐рдВрдЧ рдХрд░реЗ рдФрд░ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдп рдХреЗ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗред рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЧреНрд░рд╛рдлрд╛рдирд╛ рдореЗрдВ рдЧреНрд░рд╛рдл рдЦреАрдВрдЪрдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЕрд╕рдлрд▓ рдиреЛрдб рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рд╕реНрдерд╛рдиреАрдп рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ (рдФрд░, рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рд╕рднреА рдкреЙрдбреНрд╕ рдХреЛ рд╣рдЯрд╛ рджреЗрдВ, рдФрд░ рдлрд┐рд░ рд╕рдВрдмрдВрдзрд┐рдд рдХрд╛рд░реНрдп ** рдХрд░реЗрдВ) ...

* "рдмреВрдВрджрд╛ рдмрд╛рдВрджреА" рд╕реЗ рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рдиреЛрдб NotReady рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЕрдЪрд╛рдирдХ рдХрд╛рдо рдкрд░ рд▓реМрдЯ рд╕рдХрддрд╛ рд╣реИред рдпрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд▓реА рдореЗрдВ рдпрд╛рддрд╛рдпрд╛рдд рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдкрдбрд╝реЛрд╕реА рдиреЛрдбреНрд╕ рдкрд░ рдлрд▓реА рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪ рд╕рдХрддрд╛ рд╣реИред

** рдРрд╕реА рд╕реНрдерд┐рддрд┐рдпрд╛рдБ рдХреНрдпреЛрдВ рдкреИрджрд╛ рд╣реЛрддреА рд╣реИрдВ? рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдбреЗрдЯрд╛ рд╕реЗрдВрдЯрд░ рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдкрд░ рдиреЗрдЯрд╡рд░реНрдХ рдХреА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Hetzner рдореЗрдВ рдПрдХ рдмрд╛рд░ рд╣рдордиреЗ vswitch рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдПрдХ рдЕрджреНрднреБрдд рдХреНрд╖рдг рдореЗрдВ рдЗрд╕ vswitch рдкреЛрд░реНрдЯ рдкрд░ рдкрд╣реБрдВрдЪрдирд╛ рдмрдВрдж рд╣реЛ рдЧрдпрд╛: рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдиреЛрдб рд╕реНрдерд╛рдиреАрдп рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдкреНрд░рд╛рдкреНрдп рдерд╛ред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдХреБрдмреЗрд░рдиреЗрдЯреНрд╕ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреА рд╕реЗрд╡рд╛ рдХреЛ рд╕реАрдзреЗ рд▓реЙрдиреНрдЪ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддрд╛рдХрд┐ рдкреВрд░реА рддреИрдирд╛рддреА рд╣реЗрд▓рдо-рдЪрд╛рд░реНрдЯ рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣реЛред (рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рддреЗ рд╣реБрдП - рдпрджрд┐ рдПрдХ рд╣реА Ansible рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рд╡рд╛рддрд╛рд╡рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рднреВрдорд┐рдХрд╛рдПрдБ рд▓рд┐рдЦрдиреА рд╣реЛрдВрдЧреА: AWS, GCE, рдирдВрдЧреЗ рдзрд╛рддреБ ...) рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдереЛрдбрд╝реА рдЦреЛрдЬ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдХреБрдЫ рднреА рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рдорд┐рд▓рд╛ред рдЗрд╕рд▓рд┐рдП, рдЙрдиреНрд╣реЛрдВрдиреЗ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдмрдирд╛рдпрд╛ред

рд▓рд┐рдкрд┐ рдФрд░ рд╡рд┐рдиреНрдпрд╛рд╕


рддреЛ, рд╣рдорд╛рд░реЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдореБрдЦреНрдп рдШрдЯрдХ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ рдЬреЛ .status.addresses рдлрд╝реАрд▓реНрдб рдХреЗ рдХрд┐рд╕реА рднреА рдиреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИ рдФрд░, рдпрджрд┐ рдХрд┐рд╕реА рдиреЛрдб рдиреЗ рдЗрд╕ рдлрд╝реАрд▓реНрдб рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ рд╣реИ (рдпрд╛рдиреА рдПрдХ рдирдпрд╛ рдиреЛрдб рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ), рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЪрд╛рд░реНрдЯ рдкрд░ рд╣реЗрд▓реНрдо рдорд╛рди рднреЗрдЬрддрд╛ рд╣реИред configMap рдХреЗ рд░реВрдк рдореЗрдВ рдиреЛрдбреНрд╕ рдХреА рдпрд╣ рд╕реВрдЪреА:

 --- apiVersion: v1 kind: ConfigMap metadata: name: node-ping-config namespace: kube-prometheus data: nodes.json: > {{ .Values.nodePing.nodes | toJson }} 

рдкрд╛рдпрдерди рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реА:
 #!/usr/bin/env python3 import subprocess import prometheus_client import re import statistics import os import json import glob import better_exchook import datetime better_exchook.install() FPING_CMDLINE = "/usr/sbin/fping -p 1000 -A -C 30 -B 1 -q -r 1".split(" ") FPING_REGEX = re.compile(r"^(\S*)\s*: (.*)$", re.MULTILINE) CONFIG_PATH = "/config/nodes.json" registry = prometheus_client.CollectorRegistry() prometheus_exceptions_counter = \ prometheus_client.Counter('kube_node_ping_exceptions', 'Total number of exceptions', [], registry=registry) prom_metrics = {"sent": prometheus_client.Counter('kube_node_ping_packets_sent_total', 'ICMP packets sent', ['destination_node', 'destination_node_ip_address'], registry=registry), "received": prometheus_client.Counter( 'kube_node_ping_packets_received_total', 'ICMP packets received', ['destination_node', 'destination_node_ip_address'], registry=registry), "rtt": prometheus_client.Counter( 'kube_node_ping_rtt_milliseconds_total', 'round-trip time', ['destination_node', 'destination_node_ip_address'], registry=registry), "min": prometheus_client.Gauge('kube_node_ping_rtt_min', 'minimum round-trip time', ['destination_node', 'destination_node_ip_address'], registry=registry), "max": prometheus_client.Gauge('kube_node_ping_rtt_max', 'maximum round-trip time', ['destination_node', 'destination_node_ip_address'], registry=registry), "mdev": prometheus_client.Gauge('kube_node_ping_rtt_mdev', 'mean deviation of round-trip times', ['destination_node', 'destination_node_ip_address'], registry=registry)} def validate_envs(): envs = {"MY_NODE_NAME": os.getenv("MY_NODE_NAME"), "PROMETHEUS_TEXTFILE_DIR": os.getenv("PROMETHEUS_TEXTFILE_DIR"), "PROMETHEUS_TEXTFILE_PREFIX": os.getenv("PROMETHEUS_TEXTFILE_PREFIX")} for k, v in envs.items(): if not v: raise ValueError("{} environment variable is empty".format(k)) return envs @prometheus_exceptions_counter.count_exceptions() def compute_results(results): computed = {} matches = FPING_REGEX.finditer(results) for match in matches: ip = match.group(1) ping_results = match.group(2) if "duplicate" in ping_results: continue splitted = ping_results.split(" ") if len(splitted) != 30: raise ValueError("ping returned wrong number of results: \"{}\"".format(splitted)) positive_results = [float(x) for x in splitted if x != "-"] if len(positive_results) > 0: computed[ip] = {"sent": 30, "received": len(positive_results), "rtt": sum(positive_results), "max": max(positive_results), "min": min(positive_results), "mdev": statistics.pstdev(positive_results)} else: computed[ip] = {"sent": 30, "received": len(positive_results), "rtt": 0, "max": 0, "min": 0, "mdev": 0} if not len(computed): raise ValueError("regex match\"{}\" found nothing in fping output \"{}\"".format(FPING_REGEX, results)) return computed @prometheus_exceptions_counter.count_exceptions() def call_fping(ips): cmdline = FPING_CMDLINE + ips process = subprocess.run(cmdline, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) if process.returncode == 3: raise ValueError("invalid arguments: {}".format(cmdline)) if process.returncode == 4: raise OSError("fping reported syscall error: {}".format(process.stderr)) return process.stdout envs = validate_envs() files = glob.glob(envs["PROMETHEUS_TEXTFILE_DIR"] + "*") for f in files: os.remove(f) labeled_prom_metrics = [] while True: with open("/config/nodes.json", "r") as f: config = json.loads(f.read()) if labeled_prom_metrics: for node in config: if (node["name"], node["ipAddress"]) not in [(metric["node_name"], metric["ip"]) for metric in labeled_prom_metrics]: for k, v in prom_metrics.items(): v.remove(node["name"], node["ipAddress"]) labeled_prom_metrics = [] for node in config: metrics = {"node_name": node["name"], "ip": node["ipAddress"], "prom_metrics": {}} for k, v in prom_metrics.items(): metrics["prom_metrics"][k] = v.labels(node["name"], node["ipAddress"]) labeled_prom_metrics.append(metrics) out = call_fping([prom_metric["ip"] for prom_metric in labeled_prom_metrics]) computed = compute_results(out) for dimension in labeled_prom_metrics: result = computed[dimension["ip"]] dimension["prom_metrics"]["sent"].inc(computed[dimension["ip"]]["sent"]) dimension["prom_metrics"]["received"].inc(computed[dimension["ip"]]["received"]) dimension["prom_metrics"]["rtt"].inc(computed[dimension["ip"]]["rtt"]) dimension["prom_metrics"]["min"].set(computed[dimension["ip"]]["min"]) dimension["prom_metrics"]["max"].set(computed[dimension["ip"]]["max"]) dimension["prom_metrics"]["mdev"].set(computed[dimension["ip"]]["mdev"]) prometheus_client.write_to_textfile( envs["PROMETHEUS_TEXTFILE_DIR"] + envs["PROMETHEUS_TEXTFILE_PREFIX"] + envs["MY_NODE_NAME"] + ".prom", registry) 

рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рдкрд░ рдЪрд▓рддрд╛ рд╣реИ рдФрд░ рд╕рднреА рджреВрд╕рд░реЗ рдХреБрдмреЗрд░рдиреЗрдЯ рдХреНрд▓рд╕реНрдЯрд░ рдЗрдВрд╕реНрдЯреЗрдВрд╕реЗрд╕ рдХреЛ 2 рдмрд╛рд░ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб ICMP рдкреИрдХреЗрдЯ рднреЗрдЬрддрд╛ рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдЯреЗрдХреНрд╕реНрдЯ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд▓рд┐рдЦреЗ рдЬрд╛рддреЗ рд╣реИрдВред

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдбреЙрдХрд░ рдЫрд╡рд┐ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИ:

 FROM python:3.6-alpine3.8 COPY rootfs / WORKDIR /app RUN pip3 install --upgrade pip && pip3 install -r requirements.txt && apk add --no-cache fping ENTRYPOINT ["python3", "/app/node-ping.py"] 

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ ServiceAccount рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рднреВрдорд┐рдХрд╛, рдЬреЛ рдХреЗрд╡рд▓ рдиреЛрдбреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ (рддрд╛рдХрд┐ рдЙрдирдХреЗ рдкрддреЗ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП):

 --- apiVersion: v1 kind: ServiceAccount metadata: name: node-ping namespace: kube-prometheus --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: kube-prometheus:node-ping rules: - apiGroups: [""] resources: ["nodes"] verbs: ["list"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: kube-prometheus:kube-node-ping subjects: - kind: ServiceAccount name: node-ping namespace: kube-prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kube-prometheus:node-ping 

рдЕрдВрдд рдореЗрдВ, рдЖрдкрдХреЛ DaemonSet рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреЛ рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рд╕рднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рдЪрд▓рддреА рд╣реИ:

 --- apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: node-ping namespace: kube-prometheus labels: tier: monitoring app: node-ping version: v1 spec: updateStrategy: type: RollingUpdate template: metadata: labels: name: node-ping spec: terminationGracePeriodSeconds: 0 tolerations: - operator: "Exists" serviceAccountName: node-ping priorityClassName: cluster-low containers: - resources: requests: cpu: 0.10 image: private-registry.flant.com/node-ping/node-ping-exporter:v1 imagePullPolicy: Always name: node-ping env: - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: PROMETHEUS_TEXTFILE_DIR value: /node-exporter-textfile/ - name: PROMETHEUS_TEXTFILE_PREFIX value: node-ping_ volumeMounts: - name: textfile mountPath: /node-exporter-textfile - name: config mountPath: /config volumes: - name: textfile hostPath: path: /var/run/node-exporter-textfile - name: config configMap: name: node-ping-config imagePullSecrets: - name: antiopa-registry 

рд╢рдмреНрджреЛрдВ рдореЗрдВ рд╕рд╛рд░рд╛рдВрд╢ рд╕реНрдЯреНрд░реЛрдХ:

  • рдкрд╛рдпрдерди рд▓рд┐рдкрд┐ рдкрд░рд┐рдгрд╛рдо - рдЕрд░реНрдерд╛рдд рд╣реЛрд╕реНрдЯ рдорд╢реАрди рдкрд░ /var/run/node-exporter-textfile textfile рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд░рдЦреА рдЧрдИ рдкрд╛рда рдлрд╝рд╛рдЗрд▓реЗрдВ DaemonSet рдиреЛрдб-рдирд┐рд░реНрдпрд╛рддрдХ рдореЗрдВ рдорд┐рд▓рддреА рд╣реИрдВред рдЗрд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рддрд░реНрдХ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ --collector.textfile.directory /host/textfile , рдЬрд╣рд╛рдВ /host/textfile рд╣реЛрд╕реНрдЯрдкреЗ /var/run/node-exporter-textfile on /var/run/node-exporter-textfile export /var/run/node-exporter-textfile ред (рдЖрдк рдиреЛрдб-рдирд┐рд░реНрдпрд╛рддрдХ рдореЗрдВ рдЯреЗрдХреНрд╕реНрдЯрдлрд╛рдЗрд▓ рдХрд▓реЗрдХреНрдЯрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдпрд╣рд╛рдВ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред)
  • рдирддреАрдЬрддрди, рдиреЛрдб-рдирд┐рд░реНрдпрд╛рддрдХ рдЗрди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ, рдФрд░ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдиреЛрдб-рдирд┐рд░реНрдпрд╛рддрдХ рд╕реЗ рд╕рднреА рдбреЗрдЯрд╛ рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИред

рдХреНрдпрд╛ рд╣реБрдЖ рдерд╛?


рдЕрдм - рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдкрд░рд┐рдгрд╛рдо рдХреЗ рд▓рд┐рдПред рдЬрдм рдЗрд╕ рддрд░рд╣ рдХреЗ рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдмрдирд╛рдП рдЧрдП рдереЗ, рддреЛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рджреГрд╢реНрдп рд░реЗрдЦрд╛рдВрдХрди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдиреЛрдбреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ (рдЪрдпрдирдХрд░реНрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдмреНрд▓реЙрдХ рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рдкрд┐рдВрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЬрд┐рд╕ рдкрд░ ред рдпрд╣ рдЧреНрд░рд╛рдлрд╛рдирд╛ рдбреИрд╢рдмреЛрд░реНрдб рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЕрд╡рдзрд┐ рдХреЗ рд▓рд┐рдП рдЪрдпрдирд┐рдд рдиреЛрдбреНрд╕ рдХреЗ рдмреАрдЪ рдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕рд╛рд░рд╛рдВрд╢ рддрд╛рд▓рд┐рдХрд╛ рд╣реИ :



рдФрд░ рдпрд╣рд╛рдБ рдЪрдпрдирд┐рдд рдиреЛрдбреНрд╕ рдкрд░ рд╕рд╛рдорд╛рдиреНрдп рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде рдЧреНрд░рд╛рдл рд╣реИрдВ :



рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓рд╛рдЗрдиреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рднреА рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрд░реЛрдд рдиреЛрдб рдЪрдпрдирдХрд░реНрддрд╛ рд╕реЗ рдПрдХ рдЕрд▓рдЧ рдиреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреНрд░рд╛рдл рд╣реИ:



рдпрджрд┐ рдЖрдк рдЗрд╕ рддрд░рд╣ рдХреА рд░реЗрдЦрд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдХ рд╡рд┐рд╢реЗрд╖ рдиреЛрдб рд╕реЗ рдЙрди рд╕рднреА рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд╛рдирдХрд╛рд░реА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЧрдВрддрд╡реНрдп рдиреЛрдбреНрд╕ рдЪрдпрдирдХрд░реНрддрд╛ рдореЗрдВ рдЪреБрдирд╛ рдЧрдпрд╛ рдерд╛:



рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рд░реЗрдЦрд╛рдВрдХрди рдореЗрдВ рд╣реИ:



рдЕрдВрдд рдореЗрдВ, рдкреЛрд╖рд┐рдд рдЧреНрд░рд╛рдл рдиреЛрдбреНрд╕ рдХреЗ рдмреАрдЪ рдЦрд░рд╛рдм рдкрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛?





рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВ - рдпрд╣ рдХрд╛рд░рдгреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред

рдкреБрдирд╢реНрдЪ


рд╣рдорд╛рд░реЗ рдмреНрд▓реЙрдЧ рдореЗрдВ рднреА рдкрдврд╝реЗрдВ:

Source: https://habr.com/ru/post/hi442798/


All Articles