This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
giganet:sflow [2021/07/21 13:03] rb created |
giganet:sflow [2021/08/03 13:28] (current) rb |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Схема мониторинга | + | ===== Общая схема мониторинга ===== |
| - | ==== Задействованные сервера ==== | + | < |
| + | switch sflow -> goflow2 -> kafka -> clickhouse | ||
| - | ==== Задействованные приложения ==== | + | </ |
| - | ==== Общая схема мониторинга ==== | + | - switch отправляет данные sflow на UDP порт 6343 |
| + | - goflow2 принимает поток данных, | ||
| + | - kafka просто получает данные, | ||
| + | - clickhouse | ||
| + | - kafka - таблица подключена на чтение в kafka, данные читаются только 1 раз | ||
| + | - kafka_to_raw - представление которое выбирает данные с kafka и добавляя нужные поля вставляет в raw | ||
| + | - raw - таблица с остаточными сырыми данными | ||
| + | |||
| + | ==== switch ==== | ||
| + | |||
| + | примеры конфигов для свитчей | ||
| + | |||
| + | < | ||
| + | sampling.1G = 8192 | ||
| + | sampling.10G = 8192 | ||
| + | sampling.40G = 16384 | ||
| + | sampling.100G = 32768 | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== goflow2 ==== | ||
| + | |||
| + | file / | ||
| + | |||
| + | < | ||
| + | GOFLOW2_ARGS=-format pb -format.protobuf.fixedlen=true -listen=sflow:// | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== kafka ==== | ||
| + | |||
| + | == Установка == | ||
| + | |||
| + | < | ||
| + | useradd kafka -m | ||
| + | passwd kafka | ||
| + | su -l kafka | ||
| + | cd | ||
| + | curl https:// | ||
| + | tar -xvzf kafka_2.13-2.8.0.tgz | ||
| + | ln -s / | ||
| + | |||
| + | </ | ||
| + | |||
| + | / | ||
| + | |||
| + | < | ||
| + | delete.topic.enable=true | ||
| + | |||
| + | </ | ||
| + | |||
| + | / | ||
| + | |||
| + | < | ||
| + | [Unit] | ||
| + | Requires=network.target remote-fs.target | ||
| + | After=network.target remote-fs.target | ||
| + | |||
| + | [Service] | ||
| + | Type=simple | ||
| + | User=kafka | ||
| + | ExecStart=/ | ||
| + | ExecStop=/ | ||
| + | Restart=on-abnormal | ||
| + | |||
| + | [Install] | ||
| + | WantedBy=multi-user.target | ||
| + | |||
| + | </ | ||
| + | |||
| + | / | ||
| + | |||
| + | < | ||
| + | [Unit] | ||
| + | Requires=zookeeper.service | ||
| + | After=zookeeper.service | ||
| + | |||
| + | [Service] | ||
| + | Type=simple | ||
| + | User=kafka | ||
| + | ExecStart=/ | ||
| + | ExecStop=/ | ||
| + | Restart=on-abnormal | ||
| + | |||
| + | [Install] | ||
| + | WantedBy=multi-user.target | ||
| + | |||
| + | </ | ||
| + | |||
| + | Запускаем сервисы | ||
| + | |||
| + | < | ||
| + | systemctl daemon-reload | ||
| + | systemctl start kafka | ||
| + | systemctl enable kafka | ||
| + | |||
| + | </ | ||
| + | |||
| + | Работаем с kafka | ||
| + | |||
| + | < | ||
| + | / | ||
| + | / | ||
| + | / | ||
| + | / | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== clickhouse ==== | ||
| + | |||
| + | === дополнительная информация | ||
| + | |||
| + | [[https:// | ||
| + | [[https:// | ||
| + | [[https:// | ||
| + | [[https:// | ||
| + | |||
| + | === таблица kafka === | ||
| + | < | ||
| + | |||
| + | CREATE TABLE traffic.kafka | ||
| + | ( | ||
| + | `TimeReceived` UInt64, | ||
| + | `SequenceNum` UInt64, | ||
| + | `SamplingRate` UInt64, | ||
| + | `FlowDirection` UInt32, | ||
| + | |||
| + | `SamplerAddress` FixedString(16), | ||
| + | |||
| + | `TimeFlowStart` UInt64, | ||
| + | `TimeFlowEnd` UInt64, | ||
| + | |||
| + | `Bytes` UInt64, | ||
| + | `Packets` UInt64, | ||
| + | |||
| + | `SrcAddr` FixedString(16), | ||
| + | `DstAddr` FixedString(16), | ||
| + | |||
| + | `EType` UInt32, | ||
| + | `Proto` UInt32, | ||
| + | |||
| + | `SrcPort` UInt32, | ||
| + | `DstPort` UInt32, | ||
| + | |||
| + | `InIf` UInt32, | ||
| + | `OutIf` UInt32, | ||
| + | |||
| + | `SrcMac` String, | ||
| + | `DstMac` String, | ||
| + | |||
| + | `SrcVlan` UInt32, | ||
| + | `DstVlan` UInt32, | ||
| + | `VlanId` UInt32, | ||
| + | |||
| + | `IngressVrfID` UInt32, | ||
| + | `EgressVrfID` UInt32, | ||
| + | |||
| + | `IPTos` UInt32, | ||
| + | `ForwardingStatus` UInt32, | ||
| + | `IPTTL` UInt32, | ||
| + | `TCPFlags` UInt32, | ||
| + | `IcmpType` UInt32, | ||
| + | `IcmpCode` UInt32, | ||
| + | `IPv6FlowLabel` UInt32, | ||
| + | |||
| + | `FragmentId` UInt32, | ||
| + | `FragmentOffset` UInt32, | ||
| + | `BiFlowDirection` UInt32, | ||
| + | |||
| + | `SrcAs` UInt32, | ||
| + | `DstAs` UInt32, | ||
| + | |||
| + | `NextHop` FixedString(16), | ||
| + | `NextHopAS` UInt32, | ||
| + | |||
| + | `SrcNet` UInt32, | ||
| + | `DstNet` UInt32, | ||
| + | |||
| + | `HasMPLS` UInt8, | ||
| + | `MPLSCount` UInt32, | ||
| + | `MPLS1TTL` UInt32, | ||
| + | `MPLS1Label` UInt32, | ||
| + | `MPLS2TTL` UInt32, | ||
| + | `MPLS2Label` UInt32, | ||
| + | `MPLS3TTL` UInt32, | ||
| + | `MPLS3Label` UInt32, | ||
| + | `MPLSLastTTL` UInt32, | ||
| + | `MPLSLastLabel` UInt32 | ||
| + | ) | ||
| + | ENGINE = Kafka | ||
| + | SETTINGS | ||
| + | kafka_broker_list = ' | ||
| + | kafka_topic_list = ' | ||
| + | kafka_group_name = ' | ||
| + | kafka_format = ' | ||
| + | kafka_schema = ' | ||
| + | kafka_num_consumers = 6 | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== таблица raw ==== | ||
| + | |||
| + | < | ||
| + | CREATE TABLE traffic.raw | ||
| + | ( | ||
| + | `Date` Date, | ||
| + | `Datetime` DateTime, | ||
| + | |||
| + | `SequenceNum` UInt64, | ||
| + | `SamplingRate` UInt64, | ||
| + | `FlowDirection` UInt32, | ||
| + | |||
| + | `SamplerAddress` String, | ||
| + | |||
| + | `TimeFlowStart` DateTime, | ||
| + | `TimeFlowEnd` DateTime, | ||
| + | |||
| + | `Bytes` UInt64, | ||
| + | `Packets` UInt64, | ||
| + | |||
| + | `SrcIp` String, | ||
| + | `DstIp` String, | ||
| + | |||
| + | `EType` UInt32, | ||
| + | `Proto` String, | ||
| + | |||
| + | `SrcPort` UInt32, | ||
| + | `DstPort` UInt32, | ||
| + | |||
| + | `InIf` UInt32, | ||
| + | `OutIf` UInt32, | ||
| + | |||
| + | `SrcMac` String, | ||
| + | `DstMac` String, | ||
| + | |||
| + | `SrcVlan` UInt32, | ||
| + | `DstVlan` UInt32, | ||
| + | `VlanId` UInt32, | ||
| + | |||
| + | `IngressVrfID` UInt32, | ||
| + | `EgressVrfID` UInt32, | ||
| + | |||
| + | `IPTos` UInt32, | ||
| + | `ForwardingStatus` UInt32, | ||
| + | `IPTTL` UInt32, | ||
| + | `TCPFlags` UInt32, | ||
| + | `IcmpType` UInt32, | ||
| + | `IcmpCode` UInt32, | ||
| + | `IPv6FlowLabel` UInt32, | ||
| + | |||
| + | `FragmentId` UInt32, | ||
| + | `FragmentOffset` UInt32, | ||
| + | `BiFlowDirection` UInt32, | ||
| + | |||
| + | `SrcGeo` UInt32, | ||
| + | `DstGeo` UInt32, | ||
| + | `SrcAs` UInt32, | ||
| + | `DstAs` UInt32, | ||
| + | |||
| + | `SrcCountry` String, | ||
| + | `DstCountry` String, | ||
| + | |||
| + | `NextHop` String, | ||
| + | `NextHopAS` UInt32, | ||
| + | |||
| + | `SrcNet` String, | ||
| + | `DstNet` String, | ||
| + | |||
| + | `HasMPLS` UInt8, | ||
| + | `MPLSCount` UInt32, | ||
| + | `MPLS1TTL` UInt32, | ||
| + | `MPLS1Label` UInt32, | ||
| + | `MPLS2TTL` UInt32, | ||
| + | `MPLS2Label` UInt32, | ||
| + | `MPLS3TTL` UInt32, | ||
| + | `MPLS3Label` UInt32, | ||
| + | `MPLSLastTTL` UInt32, | ||
| + | `MPLSLastLabel` UInt32) | ||
| + | ENGINE = MergeTree | ||
| + | PARTITION BY toYYYYMMDD(Date) | ||
| + | ORDER BY Datetime | ||
| + | TTL Date | ||
| + | SETTINGS index_granularity = 8192 | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== таблица kafka_to_raw ==== | ||
| + | |||
| + | < | ||
| + | CREATE MATERIALIZED VIEW traffic.kafka_to_raw TO traffic.raw | ||
| + | ( | ||
| + | `Date` Date, | ||
| + | `Datetime` DateTime, | ||
| + | |||
| + | `SequenceNum` UInt64, | ||
| + | `SamplingRate` UInt64, | ||
| + | `FlowDirection` UInt32, | ||
| + | |||
| + | `SamplerAddress` String, | ||
| + | |||
| + | `TimeFlowStart` DateTime, | ||
| + | `TimeFlowEnd` DateTime, | ||
| + | |||
| + | `Bytes` UInt64, | ||
| + | `Packets` UInt64, | ||
| + | |||
| + | `SrcIp` String, | ||
| + | `DstIp` String, | ||
| + | |||
| + | `EType` UInt32, | ||
| + | `Proto` String, | ||
| + | |||
| + | `SrcPort` UInt32, | ||
| + | `DstPort` UInt32, | ||
| + | |||
| + | `InIf` UInt32, | ||
| + | `OutIf` UInt32, | ||
| + | |||
| + | `SrcMac` String, | ||
| + | `DstMac` String, | ||
| + | |||
| + | `SrcVlan` UInt32, | ||
| + | `DstVlan` UInt32, | ||
| + | `VlanId` UInt32, | ||
| + | |||
| + | `IngressVrfID` UInt32, | ||
| + | `EgressVrfID` UInt32, | ||
| + | |||
| + | `IPTos` UInt32, | ||
| + | `ForwardingStatus` UInt32, | ||
| + | `IPTTL` UInt32, | ||
| + | `TCPFlags` UInt32, | ||
| + | `IcmpType` UInt32, | ||
| + | `IcmpCode` UInt32, | ||
| + | `IPv6FlowLabel` UInt32, | ||
| + | |||
| + | `FragmentId` UInt32, | ||
| + | `FragmentOffset` UInt32, | ||
| + | `BiFlowDirection` UInt32, | ||
| + | |||
| + | `SrcAs` UInt32, | ||
| + | `DstAs` UInt32, | ||
| + | |||
| + | `SrcCountry` String, | ||
| + | `DstCountry` String, | ||
| + | |||
| + | `NextHop` String, | ||
| + | `NextHopAS` UInt32, | ||
| + | |||
| + | `SrcNet` String, | ||
| + | `DstNet` String, | ||
| + | |||
| + | `HasMPLS` UInt8, | ||
| + | `MPLSCount` UInt32, | ||
| + | `MPLS1TTL` UInt32, | ||
| + | `MPLS1Label` UInt32, | ||
| + | `MPLS2TTL` UInt32, | ||
| + | `MPLS2Label` UInt32, | ||
| + | `MPLS3TTL` UInt32, | ||
| + | `MPLS3Label` UInt32, | ||
| + | `MPLSLastTTL` UInt32, | ||
| + | `MPLSLastLabel` UInt32 | ||
| + | ) AS | ||
| + | SELECT | ||
| + | toDate(TimeReceived) AS Date, | ||
| + | TimeReceived as Datetime, | ||
| + | IPv4NumToString(reinterpretAsUInt32(substring(reverse(SamplerAddress), | ||
| + | Bytes * SamplingRate as Bytes, | ||
| + | Packets * SamplingRate as Packets, | ||
| + | multiIf(EType = 0x0800, dictGetUInt32(' | ||
| + | EType = 0x86DD, dictGetUInt32(' | ||
| + | multiIf(EType = 0x0800, dictGetUInt32(' | ||
| + | EType = 0x86DD, dictGetUInt32(' | ||
| + | multiIf(EType = 0x0800, dictGetUInt32(' | ||
| + | EType = 0x86DD, dictGetUInt32(' | ||
| + | multiIf(EType = 0x0800, dictGetUInt32(' | ||
| + | EType = 0x86DD, dictGetUInt32(' | ||
| + | multiIf(EType = 0x0800, IPv4NumToString(reinterpretAsUInt32(substring(reverse(SrcAddr), | ||
| + | EType = 0x86DD, IPv6NumToString(SrcAddr), | ||
| + | multiIf(EType = 0x0800, IPv4NumToString(reinterpretAsUInt32(substring(reverse(DstAddr), | ||
| + | EType = 0x86DD, IPv6NumToString(DstAddr), | ||
| + | dictGet(' | ||
| + | MACNumToString(toUInt64(SrcMac)) AS SrcMac, | ||
| + | MACNumToString(toUInt64(DstMac)) AS DstMac, | ||
| + | dictGetString(' | ||
| + | dictGetString(' | ||
| + | |||
| + | SequenceNum, | ||
| + | SamplingRate, | ||
| + | FlowDirection, | ||
| + | TimeFlowStart, | ||
| + | TimeFlowEnd, | ||
| + | EType, | ||
| + | SrcPort, | ||
| + | DstPort, | ||
| + | InIf, | ||
| + | OutIf, | ||
| + | SrcVlan, | ||
| + | DstVlan, | ||
| + | VlanId, | ||
| + | IngressVrfID, | ||
| + | EgressVrfID, | ||
| + | IPTos, | ||
| + | ForwardingStatus, | ||
| + | IPTTL, | ||
| + | TCPFlags, | ||
| + | IcmpType, | ||
| + | IcmpCode, | ||
| + | IPv6FlowLabel, | ||
| + | FragmentId, | ||
| + | FragmentOffset, | ||
| + | BiFlowDirection, | ||
| + | NextHop, | ||
| + | NextHopAS, | ||
| + | SrcNet, | ||
| + | DstNet, | ||
| + | HasMPLS, | ||
| + | MPLSCount, | ||
| + | MPLS1TTL, | ||
| + | MPLS1Label, | ||
| + | MPLS2TTL, | ||
| + | MPLS2Label, | ||
| + | MPLS3TTL, | ||
| + | MPLS3Label, | ||
| + | MPLSLastTTL, | ||
| + | MPLSLastLabel | ||
| + | FROM traffic.kafka | ||
| + | |||
| + | </ | ||
| + | |||
| + | ==== Словари ==== | ||
| + | |||
| + | protocols - словарь для текстового представления протоколов | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.protocols ( | ||
| + | `proto` UInt8, | ||
| + | `name` String, | ||
| + | `description` String | ||
| + | ) | ||
| + | PRIMARY KEY proto | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(FLAT()) | ||
| + | |||
| + | </ | ||
| + | |||
| + | asnv4 - конвертация ipv4 к ASN | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.asnv4 | ||
| + | ( | ||
| + | `network` String, | ||
| + | `asn` UInt32, | ||
| + | `aso` String DEFAULT '??' | ||
| + | ) | ||
| + | PRIMARY KEY network | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(IP_TRIE()) | ||
| + | |||
| + | </ | ||
| + | |||
| + | asnv6 - конвертация ipv6 к ASN | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.asnv6 | ||
| + | ( | ||
| + | `network` String, | ||
| + | `asn` UInt32, | ||
| + | `aso` String DEFAULT '??' | ||
| + | ) | ||
| + | PRIMARY KEY network | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(IP_TRIE()) | ||
| + | |||
| + | </ | ||
| + | |||
| + | contryen | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.contryen | ||
| + | ( | ||
| + | `geoname_id` id, | ||
| + | `locale_code` String, | ||
| + | `continent_code` String, | ||
| + | `continent_name` String, | ||
| + | `country_iso_code` String, | ||
| + | `country_name` String, | ||
| + | `is_in_european_union` UInt8 | ||
| + | ) | ||
| + | PRIMARY KEY geoname_id | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(HASHED()) | ||
| + | |||
| + | </ | ||
| + | |||
| + | contryv4 | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.contryv4 | ||
| + | ( | ||
| + | `network` String, | ||
| + | `geoname_id` UInt32 DEFAULT 0, | ||
| + | `registered_country_geoname_id` UInt32 DEFAULT 0, | ||
| + | `represented_country_geoname_id` UInt32 DEFAULT 0, | ||
| + | `is_anonymous_proxy` UInt8 DEFAULT 0, | ||
| + | `is_satellite_provider` UInt8 DEFAULT 0 | ||
| + | ) | ||
| + | PRIMARY KEY network | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(IP_TRIE()) | ||
| + | |||
| + | </ | ||
| + | |||
| + | contryv6 | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.contryv6 | ||
| + | ( | ||
| + | `network` String, | ||
| + | `geoname_id` UInt32 DEFAULT 0, | ||
| + | `registered_country_geoname_id` UInt32 DEFAULT 0, | ||
| + | `represented_country_geoname_id` UInt32 DEFAULT 0, | ||
| + | `is_anonymous_proxy` UInt8 DEFAULT 0, | ||
| + | `is_satellite_provider` UInt8 DEFAULT 0 | ||
| + | ) | ||
| + | PRIMARY KEY network | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(IP_TRIE()) | ||
| + | |||
| + | </ | ||
| + | |||
| + | switches | ||
| + | |||
| + | < | ||
| + | CREATE DICTIONARY dictionaries.switches | ||
| + | ( | ||
| + | `ip` String, | ||
| + | `name` String | ||
| + | ) | ||
| + | PRIMARY KEY ip | ||
| + | SOURCE(FILE(PATH '/ | ||
| + | LIFETIME(MIN 0 MAX 3600) | ||
| + | LAYOUT(COMPLEX_KEY_HASHED()) | ||
| + | |||
| + | </ | ||