Added k3s page.

Signed-off-by: Pavel Kirilin <win10@list.ru>
This commit is contained in:
2021-12-09 15:38:19 +04:00
parent f25752b927
commit 68dcb8da74
16 changed files with 1345 additions and 88 deletions

View File

@ -1,7 +1,7 @@
---
title: Разделение докера на среды.
description: Как работать с несколькими docker-compose.
position: 3
position: 2
category: DevOps
---

View File

@ -1,7 +1,7 @@
---
title: Makefiles для чайников.
description: Автоматизируем по старинке.
position: 1
position: 3
category: 'DevOps'
---

View File

@ -246,25 +246,31 @@ $ wemake-python-styleguide --dev
Теперь добавим конфигурационных файлов в корень проекта.
Это мои конфигурации, которые я настроил под себя, можешь менять их как хочешь.
`.mypy.ini` для настройки валидации типов.
```ini{}[.mypy.ini]
[mypy]
strict = True
ignore_missing_imports=True
allow_subclassing_any=True
allow_untyped_calls=True
pretty=True
show_error_codes=True
implicit_reexport=True
allow_untyped_decorators=True
```
`.isort.cfg` для конфигурации сортировки импортов.
```ini{}[.isort.cfg]
[isort]
Для конфигурации сортировки импортов и проверки типов добавим следющее
в наш основной файл проекта.
Обычно я добавляю эти секции сразу после секции `[tool.poetry.dev-dependencies]`.
```toml{}[pyproject.toml]
...
[tool.mypy]
strict = true
ignore_missing_imports = true
allow_subclassing_any = true
allow_untyped_calls = true
pretty = true
show_error_codes = true
implicit_reexport = true
allow_untyped_decorators = true
warn_return_any = false
[tool.isort]
profile = "black"
multi_line_output = 3
include_trailing_comma = true
use_parentheses = true
...
```
`.flake8` - конфигурация линтинга. Тут довольно много. Это игнорирование ненужных кодов ошибок, которые не особо-то и ошибки.
@ -416,13 +422,6 @@ repos:
entry: yesqa
language: system
types: [ python ]
- id: pytest
name: pytest
entry: pytest
language: system
pass_filenames: false
types: [ python ]
```
И не забываем про `.gitignore`. Его можно найти [тут](https://github.com/github/gitignore/blob/master/Python.gitignore).

View File

@ -0,0 +1,753 @@
---
title: Начало работы с kubernetes
description: Как там это всё разворачивать в двух словах.
category: DevOps
position: 4
---
# Проблема в изучении кубернетес
Многие люди, кто задавались вопросом как начать работать с
кубернетесом сталкивались с тем, что документация крайне
большая сложная и нет нормального описания как
завернуть маленький проект из одного проекта в свой кластер или
как развернуть свой кластер без боли.
А всё потому что вся документация нацелена на большие
production-ready системы с большим rps и тому подобным.
В данной статье я попробую исправить это вселенское
недопонимание используя k3s, свой комплюктер и немного знаний по кодингу.
<div align="center">
![Intro image](/images/k3s_start/kube_intro.jpg)
</div>
# Что такое кубернетес и почему это лучше докера
Многие ребята, кто хорошо знаком с докером и его
возможностями могут задаваться таким вопросом.
Для тех кто в танке, напомню, что докер
имеет вариант запуска в режиме кластера.
Этот функционал называется docker swarm.
В целом, swarm отдалённо напоминает kubernetes,
так как в этом режиме докер, худо-бедно но умеет
автоскейлится и запускаться в кластере,
но это всё равно немного не то.
<b-message type="is-info" has-icon>
Также замечу, что кубер активно развивается и поддерживается.
огромным количество компаний. А вот docker swarm уже по-немногу
умирает и документация по нему не то чтобы супер хороша.
</b-message>
По большей части кубернетес это система,
которая будет управлять вашими приложениями,
следить за их состоянием и помогать вам в их
конфигурации. Кубер умеет очень много, поэтому
все интересные способности я в этой статье не смогу осветить,
но самую базу попробую рассказать.
# Из чего состоит кубернетес
Так как я в этой статье хотел затронуть
совсем базовые и практические вещи, то рассматривать
мы будем только крайне полезные компоненты.
- Container
- Pod
- Deployment
- Service
- Ingress
- Namespace
- Secret
- ConfigMap
А теперь рассмотрим немного поподробнее.
## Container
Контейнеры не то чтобы часть специфичная для кубернетес.
С контейнерами вы можете быть знакомы из кучи систем.
В контексте кубера они не обладают никакими дополнительными
свойствами. Это ровно то же, что и контейнеры `containerd`
или те, с которыми вы возились с докером. Ничего нового.
Собираются контейнеры для кубернетеса ровно тем же образом,
что и для докера.
<b-message type="is-warning" has-icon>
Важная ремарка. Кубер начиная с 2021 кубернетес не поддерживает
докер как бэкенд. Теперь кубер будет общаться с
containerd напрямую. Это значит, что теперь перед использованием
контейнеров собранных на локальной машине надо будет импортировать их
в `containerd` используя `ctr image import`.
Как импортировать образы почитать можно в [этой статье](https://cwienczek.com/2020/06/import-images-to-k3s-without-docker-registry/).
</b-message>
## Pod
<div align="center">
<img alt="Pods" style="width: 100%" src="/images/k3s_start/pods.svg">
</div>
Поды - это логически связанные группы контейнеров.
Это самая базовая еденица кубернетеса.
В поде находится от одного до множества контейнеров.
Интересная особенность пода в том, что все контейнеры
делят один сетевой адресс. Другими словами,
если у вас один из контейнеров открыл порт `3000`,
то другие контейнеры из пода эти порты использовать не смогут.
То есть, если вы хотите логически связанные приложения
поместить в под, то они могут ходить друг к другу через лупбек
адреса. Такие как `localhost` или `127.0.0.1`.
## Deployment
Поды это круто, но есть одно но. Данные объекты неизменяемые
и сам под скейлить вручную занятие сомнительное.
Конечно, никто не мешает создать вам вручную [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)
и самому крутить там нужные значения. Но в среднем
вам с этим возиться не очень то хочется.
<br>
Deployment нужна именно для описания подов и создания
некоторых ресурсов, нужных для скейлинга.
Также с помощью деплойментов можно делать откаты приложения через
механиз роллбеков. Я это рассматривать не буду. Тут только база.
## Service
Сервис - это ресурс, с помощью которого поды могут общаться
между собой. По факту сервис описывает, какие порты пода
открыты и перенаправляет трафик на них.
Представьте себе под, который просто проксирует весь трафик с одного
порта на какой-нибудь порт пода. Это и есть Service.
<div align="center">
![Service overview](/images/k3s_start/service%20overview.png)
</div>
Выглядит сервис примерно так как показано на кртинке выше.
Он направляет весь входной трафик с указанного порта на
порты подов.
Также сервис выступает как балансировщик.
<b-message type="is-info" has-icon>
Если вы хотите сделать запрос от одного пода до дргого внутри кластера, то
вам придётся использовать сервис.
<br>
Если вы попробуете сделать запрос напрямую по IP пода, то у вас, конечно же,
получится, но это довольно странная идея из-за того, что при пересоздании
пода у него может обновится IP внутри кластера. Поэтому лучше использовать сервисы. Также они потребуются для ингресса.
</b-message>
## Ingress
Ингрессы это сервис описывающий куда пускать трафик,
который поступает снаружи кластера.
<div align="center">
![Ingress overview](/images/k3s_start/ingress-overview.png)
</div>
Принцип работы ингресса следующий:
Вы указываете хост ингресса и различные регексы пути.
В зависимости от входящего запроса ингресс выбирает в какой сервис
направить его и в какой порт.
Настройка ингресса достаточно гибкая и я не думаю,
что вы можете столкнуться с какими либо проблемами.
## Namespace
Неймспейсы это логические разделители уровня доступа.
Я предпочитаю использовать разные неймспейсы под различные логические группы приложений.
Например, в моём кластере есть отдельные неймспейсы для каждого приложения.
Скажем, у меня есть проект, в котором есть база данных и веб сервер.
Я держу их в одном неймспейсе, который называется также, как и приложени.
А вот телеграм боты -- приложения достаточно лёгкие.
Поэтому у меня есть неймспейс со всеми телеграм ботами.
Эта штука позволяет просто лучше организовать свой кубернетес кластер.
Также неймспейсы очень полезны для ограничивания возможностей
конкретного пользователя.
Например, вы можете создать правило, которое будет разрешать пользователю
смотреть на поды в каком-то неймспейсе, но при этом ему нельзя будет
что либо изменять.
## Secret и ConfigMap
Данные ресурсы нужны только чтобы хранить
внутри кластера какую-нибудь информацию.
Например вы можете сохранить в ConfigMap
переменные среды и потом использовать их в подах в одном неймспейсе.
В секреты обычно кидают сертификаты или какие-нибудь ключи.
Но так как секреты не особо секретные принято использовать [Vault](https://www.vaultproject.io/docs/platform/k8s). Но так как эта статья затрагивает только
основы рассматривать развертку и настройку Vault мы не будем, ну и также HashiCorp
всё довольно подробно расписали сами.
# Как развернуть k8s у себя
Для локального кубера есть пара вариантов.
- k3s (Недоступен под Windows)
- minikube
На первый взгляд minikube может показаться лучшим вариантом.
И он действительно хорош тем, что его легко почистить после
своих экспериментов. Однако, там есть проблемы с ингрессами.
По факту они не работают и там надо окольными путями получать
адреса приложения.
<br>
k3s - это легковесная production-ready реализация k8s. Ingress у него работают
отлично, поэтому я буду использовать его.
<br>
Я не буду зацикливаться на установке `minikube`, так как
он прост в установке и первоначальной настройке. Почитать подробнее можно в
[официальном гайде от minikube](https://minikube.sigs.k8s.io/docs/start/).
С `k3s` всё немного посложнее, но тоже достаточно просто, если немного разобраться. Первоначальная установка описана в [официальной доке k3s](https://rancher.com/docs/k3s/latest/en/installation/install-options/).
## Подключение кластера
После установки в домашней дериктории должен был быть
сгенерирован файл `.kube/config`. Этот файл содержит данные для
подключения к различным кластерам. `minikube` Сам добавляет
ключи для подключения к .kube/config. `K3S` не изменяет
никаким образом `.kube/config`, поэтому надо будет это сделать вручную.
Для того, чтобы это сделать сначала разберёмся как выглядит конфиг.
```yaml{}[.kube/config]
apiVersion: v1
kind: Config
preferences: {}
# Массив кластеров.
# Каждый элемент -- данные для подключения
# Тут также есть названия для каждого кластера.
clusters:
- name: hyper
cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.1.55:6443
- name: k3s-local
cluster:
certificate-authority-data: DATA+OMITTED
server: https://127.0.0.1:6443
# Массив данных пользователя.
# Тут указаны пользователи с
# различными сертификатами.
# Обычно для разных серверов у вас будут
# Различные данные для входа.
users:
- name: hyper-s3rius
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: k3s-user
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
# Массив контекстов.
# Контекст - это связующее звено
# между кластероами и пользователями.
contexts:
- context:
cluster: hyper
user: hyper-s3rius
name: hyper
- context:
cluster: k3s-local
user: k3s-user
name: k3s
# Текущий контекст указывает какой
# контекст использовать по умолчанию.
current-context: "k3s"
```
Для работы с кубером из командной строки
можно использовать `kubectl`. Чтобы сменить контекст в любой команде вы
можете передать параметр `--context $CONTEXT_NAME`, где `$CONTEXT_NAME` это название контекста.
Чтобы достать данные для подключения к `k3s` надо посмотреть его конфиг
и скопировать данные. Либо выставить переменную среды, которая будет
указывать конфиг k3s. Конфиг подключения `k3s` лежит в файле `/etc/rancher/k3s/k3s.yaml`.
Можете выполнить команду, которая будет просить kubectl использовать указанный конфиг:
`export KUBE_CONFIG=/etc/rancher/k3s/k3s.yaml`
<br>
Либо скопируйте нужные данные для подключения себе в `.kube/config`.
После настройки выполните команду и проверьте что вам вернулось
что-то подобное. Это значит, что никаких ресурсов пока в
кластере нет. Это мы исправим позже. Пока что можно сказать,
что подключение прошло успешно.
```bash
$ kubectl --context "my-context" get pods
No resources found in default namespace.
```
Если же у вас выпадает ошибка, например такая.
```
The connection to the server localhost:8080 was refused - did you specify the right host or port?
```
То либо запустите кластер
```
sudo systemctl start k3s.service
```
Либо у вас неверные данные для входа.
### Мониторинг кластера
Для просматривания управления кластером используется cli утилита `kubectl`.
Но для того, чтобы с ней работать нужно получше понять что вообще в кластере есть.
Для этого я советую использовать [Lens](https://k8slens.dev/). Это крайне
удобный интерфейс для управления своим кластером.
Также там есть очень клёвая настрока, которая сама включит мониторинг
потребления памяти и процессора для всех подов и кластера в общем.
На локальной машине это не очень много смысла имеет,
а вот в проде было бы очень полезно.
Выглядит Lens примерно так:
<div align="center" style="margin-top:15px;">
![Lens example](/images/k3s_start/lens-example.png)
</div>
Для изучения **крайне настоятельно рекомендую** настроить Lens.
# Ваше первое приложение в кластере.
### Сервер
Давайте создадим своё первое приложение.
Для этого я буду использовать [express.js](https://expressjs.com/), так как он крайне популярен и прост.
Для этого сначала напишем сам сервер. Я буду использовать yarn, но можете и npm,
сути не поменяет.
Создайте какую-нибудь папку, где вы будете эксперементировать, откройте в ней ваш любимый тектовый редактор и просто копируйте файлы ниже.
```json{}[package.json]
{
"name": "req_counter",
"version": "1.0.0",
// Указан модуль,
// чтобы использовать нормальны импорты,
// а не require.
"type": "module",
"license": "MIT",
"scripts": {
// Скрипт старта сервера.
"server": "node index.js"
},
// Зависимости проекта.
"dependencies": {
"express": "^4.17.1"
}
}
```
И само приложение
```js{}[index.js]
import express from "express";
import { hostname } from "os";
import { argv, exit } from "process";
// Серверное приложение.
const app = express();
// Глобальный счётчик входящих запросов.
let requests = 0;
// Обработка входящего запроса.
app.get("*", (req, res) => {
// Увеличиваем глобальный счётчик запросов.
requests += 1;
// Логгируем входящий запрос.
console.log(`${req.method} ${req.url}`);
// Возвращаем информацию о текущем хосте и количестве запросов.
res.json({
requests: requests,
hostname: hostname(),
});
});
// Аргументы командной строки.
// Напрмиер yarn run server 127.0.0.1 8000
const args = argv.slice(2);
// Если передано неверное количество аргументов.
if (args.length != 2) {
console.error("Usage: yarn run server {host} {port}");
exit(1);
}
// Простейший "парсинг" аргументов командной строки.
const host = args[0];
const port = args[1];
// Старт сервера.
app.listen(port, host, () => {
console.log(`Server listening at http://${host}:${port}`);
});
```
Это всё. Сервер готов.
<hr>
Протестируем запуск сервера выполнив команду ниже и открыв в
своём любимом браузере http://localhost:8080.
```
yarn run server 0.0.0.0 8080
```
У меня всё работает и успешно отдаётся нужная информация.
```json
{
"requests": 1,
"hostname": "s3rius-pc"
}
```
### Docker образ
Теперь создадим докер образ приложения.
Добавим `.dockerignore`, чтобы игнорировать ненужные файлы во время сборки образа.
```gitignore{}[.dockerignore]
node_modules/
```
И добавим в проект `Dockerfile` для описания самого процесса сборки.
```dockerfile{}[Dockerfile]
FROM node:17-alpine
WORKDIR /app
COPY . /app/
RUN yarn install
CMD [ "yarn", "run", "server", "0.0.0.0", "8000"]
```
Давайте соберём и запустим проект в контейнере.
```bash
docker build --tag="s3rius/req-counter-express:latest" .
docker run --rm -it -p 3400:8000 "s3rius/req-counter-express:latest"
```
Можете проверить, что приложение работает успешно, открыв в браузере http://localhost:3400.
У меня в ответ пришло то же сообщение. Только, как можно заметить,
`hostname` поменялся. На самом деле контейнеры используют свои hostname
отличные от `hostname` локальной машины.
```json
{
"requests": 10,
"hostname": "8f23adadc640"
}
```
Вариантов как положить это приложение в K8S несколько.
- Вы можете запушить собранное приложение в [Docker HUB](https://hub.docker.com/) и использовать его.
- Можете использовать мой образ `s3rius/req-counter-express:latest`
- Импортировать собранный образ как tar файл и импортировать его в containerd напрямую.
Как это сделать почитать можно в [этой статье](https://cwienczek.com/2020/06/import-images-to-k3s-without-docker-registry/).
### Деплой в k8s
Создайте папку `kube` в папке проекта и теперь мы будем работать в ней.
Все ресурсы будут описаны yaml-файлами.
```yaml{}[kube/deployment.yml]
---
apiVersion: apps/v1
kind: Deployment
# метаданные самого деплоймента.
metadata:
name: req-counter-deployment
spec:
# Количество реплик пода.
replicas: 1
# Селектор, который выбирает
# какие поды принадлежат этому деплойменту.
selector:
matchLabels:
app: req-counter
# Шаблон пода,
# который будет использоваться при
# маштабировании.
template:
# Метаданные пода.
# тут обычно помещаются лейблы,
# с помощью которых деплоймент идентифицирует
# свои поды.
metadata:
labels:
app: req-counter
spec:
# Масссив контейнеров
containers:
# Название контейнера внутри пода.
- name: req-counter-app
# Образ приложения.
image: s3rius/req-counter-express:latest
# Ресурсы требуемые для работы приложения.
resources:
# Минимальное количество ресурсов,
# которое кластер гарантированно предоставит приложению.
# Также данные значения используются для того,
# чтобы выяснить на какой ноде запускать приложение.
requests:
memory: "50Mi"
cpu: "30m"
# Максимально возможные значения приложения.
# Если приложение выйдет за лимиты,
# то кубер убьёт приложение.
limits:
memory: "128Mi"
cpu: "100m"
# Порты на которых открыты приложения.
ports:
- containerPort: 8000
protocol: TCP
```
Теперь опишем сервис для управления трафиком.
```yaml{}[kube/service.yml]
---
apiVersion: v1
kind: Service
# Метадата сервиса.
metadata:
name: req-counter-service
spec:
# Селектор подов,
# которым будет пускаться трафик.
# Трафик может идти в любой под,
# который матчит данному селектору.
selector:
app: req-counter
# Порты для проксирования соединений.
ports:
# Порт сервиса
- port: 80
# Порт пода, куда будет идти трафик дальше.
targetPort: 8000
```
И в последнюю очередь опишем наш ингрес.
```yaml{}[kube/ingress.yml]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
# Метаданные ингресса.
metadata:
name: req-counter-ingress
labels:
name: req-counter-ingress
spec:
# Правила роутинга.
rules:
# Требуемый хост.
- host: req-counter.local
http:
paths:
# Тип пути Prefix значит,
# что все запросы, которые начинаются c
# ${path} будут матчится тут.
- pathType: Prefix
# Сам путь.
path: "/"
backend:
service:
# Название нашего сервиса.
name: req-counter-service
# Порт сервиса, куда перенаправлять входящий трафик.
port:
number: 80
```
Перед тем, как создать все описанные ресурсы создадим неймспейс.
```bash
$ kubectl --context k3s create namespace req-couter-ns
namespace/req-couter-ns created
```
После того, как неймспейс создан самое время сделать последний штрих.
<div align="center">
![Apply meme](/images/k3s_start/kubectl-apply.png)
</div>
```bash
$ kubectl --context k3s --namespace req-couter-ns apply -f ./kube/
deployment.apps/req-counter-deployment created
ingress.networking.k8s.io/req-counter-ingress created
service/req-counter-service created
```
Готово. Теперь вы можете зайти в lens, выбрать свой кластер из списка
и посмотреть как там поживает ваше приложение.
Также не забудьте указать неймспей, в который вы беплоиди приложение.
Выглядит это чудо примерно так:
<div align="center">
![Deployed app in lens](/images/k3s_start/lens-deployed.png)
</div>
Также можно использовать команду и вывести всё себе в терминал.
```
$ kubectl --context k3s --namespace req-couter-ns get all
NAME READY STATUS RESTARTS AGE
pod/req-counter-deployment-764476db97-dt2tc 1/1 Running 0 8m11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/req-counter-service ClusterIP 10.43.50.23 <none> 80/TCP 8m11s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/req-counter-deployment 1/1 1 1 8m11s
NAME DESIRED CURRENT READY AGE
replicaset.apps/req-counter-deployment-764476db97 1 1 1 8m11s
```
### Маштабирование
В рамках демонстрации давате поменяем значение
`replicas` в нашем файле деплоймента до `3`.
```yaml{}[kube/deployment.yml]
...
spec:
# Количество реплик пода.
replicas: 3
...
```
После изменения просто ещё раз вызовите команду apply.
```bash
$ kubectl --context k3s --namespace req-couter-ns apply -f ./kube/
deployment.apps/req-counter-deployment configured
ingress.networking.k8s.io/req-counter-ingress unchanged
service/req-counter-service unchanged
```
Как можно видеть изменился только наш `Deployment`.
Остальные ресурсы остались нетронутыми.
Давайте посмотрим на поды в нашем неймспейсе.
```
$ kubectl --context k3s --namespace req-couter-ns get pods
NAME READY STATUS RESTARTS AGE
req-counter-deployment-764476db97-dt2tc 1/1 Running 0 13m
req-counter-deployment-764476db97-tdjrb 1/1 Running 0 69s
req-counter-deployment-764476db97-x28fr 1/1 Running 0 69s
```
Как видно, всё правильно. Теперь у нас 3 пода
нашего приложения.
Теперь я пойду и выполню кучу запросов по адресу http://req-counter.local/
и получу балансировку между подами из коробки, без дополнительных
конфигураций.
Если у вас не получается найти адрес. Добавьте данный хост себе в
`/etc/hosts` на линуксе или в `C:\Windows\System32\drivers\etc\hosts` на windows,
дописав в конец файла следующее:
```
...
127.0.0.1 req-couter.local
```
И теперь вы можете открыть в браузере своё приложение и увидеть,
как кубернетес заботливо направляет трафик туда, куда вы хотите.
<div align="center">
![Making requests](/images/k3s_start/requests.gif)
</div>
### Как мне очистить мой кластер?
Всё очень просто.
Так как у нас имеются описния ресурсов, то мы
можем удалить всё сразу используя команду
```bash
$ kubectl --context k3s --namespace req-couter-ns delete -f ./kube/
deployment.apps "req-counter-deployment" deleted
ingress.networking.k8s.io "req-counter-ingress" deleted
service "req-counter-service" deleted
```
Таким образом k8s удалит все описанные ресурсы из вашего кластера.
До новых встреч.

View File

@ -7,7 +7,6 @@ category: DevOps
# Traefik - роутинг просто
Сегодня я бы хотел рассказать о такой клёвой штуке, как [Traefik](https://traefik.io/traefik/). Не так давно я перевёл все сервисы своего сервера на traefik и это буквально сделало жизнь проще. Сегодня я расскажу вам зачем он нужен, как его настроить, и покажу на примере, как именно он помогает. По факту, это nginx на стероидах, в плане конфигурации, потому что в traefik за тебя сделано гораздо больше.
# Что такое traefik
@ -33,6 +32,7 @@ Traefik - это система, которая позволяет настро
</div>
## Архитектура
В официальной документации зарисована следующая схема работы traefik:
<div align="center">
@ -43,21 +43,24 @@ Traefik - это система, которая позволяет настро
Как можно видеть по данному изображению, есть 5 основных составляющих traefik, а именно:
* entrypoints
* routers
* rules (часть routers)
* middlewares (чать routers)
* services
- entrypoints
- routers
- rules (часть routers)
- middlewares (чать routers)
- services
### Entrypoint
Являются основными слушателями входящих соединений. Через них проходит весь трафик. Если попробовать объяснить в двух словах: "Порт, на который должно прийти входящее соединение", - вполне себе неплохое объяснение. В данном туториале я создам 2 `entrypoint`, которые будут слушать на http и https.
### Routers, Rules и Middlewares
Роутер - связующее звено между `entrypoint` и сервисом, куда нужно направить трафик. Роутер хранит в себе информацию, куда направить входящий трафик, и
правила, по которым можно определить, пускать ли трафик дальше.
Rules - это и есть те самые правила, которые определяют, через какой роутер пустить трафик.
Допустим, у вас в конфиге есть следующие правила:
```
Host(`myapp.com`) && (PathPrefix(`/api`) || PathPrefix(`/memes`))
```
@ -75,7 +78,6 @@ Host(`myapp.com`) && (PathPrefix(`/api`) || PathPrefix(`/memes`))
Вы, конечно же, можете использовать локально установленную версию, всё будет работать, как часы.
</b-message>
Для нашего основного traefik на сервере мы создадим небольшой docker-compose.yml, файл конфига и папочку с сертификатами.
Структура будет следующая:
@ -101,12 +103,19 @@ services:
image: traefik:v2.4.8
container_name: traefik_main
command:
# Включает прослушивание докера на новые события и следит за лейблами контейнеров.
- --providers.docker=true
# Отключает автоматическое создание роутеров ко всем контейнерам на сервере.
- --providers.docker.exposedbydefault=false
# Сеть докера, по которой будет выполнятся подключение к контейнерам.
- --providers.docker.network=traefik-shared
# Папка с конфигурационным файлом.
- --providers.file.directory=/etc/traefik/dynamic
# Включает отслеживание изменений файла конфигурации.
- --providers.file.watch=true
# Создаёт entrypoint с названием http и слушает 80 порт.
- --entrypoints.http.address=:80
# Создаёт entrypoint с названием https и слушает 443 порт.
- --entrypoints.https.address=:443
ports:
# The HTTP port
@ -119,12 +128,16 @@ services:
environment:
MAIN_HOST: 192.168.1.89
volumes:
# So that Traefik can listen to the Docker events
# Обязательный вольюм. Так траефик может слушать
# события происходящие в демоне докера.
- /var/run/docker.sock:/var/run/docker.sock
# Вольюм с файлом конфигурации.
- ./config.toml:/etc/traefik/dynamic/traefik.toml
# Папка сертификатов.
- ./certs:/etc/certs/
networks:
# Сетка, внутри которой будут находится приложения.
traefik-shared:
name: traefik-shared
@ -132,16 +145,6 @@ networks:
Вот какие параметры я передаю в `traefik-cli`.
| Параметр | Что делает |
|-------------------------------------------------|----------------------------------------------------------------------------------|
| `providers.docker=true` | Включает прослушивание докера на новые события и следит за лейблами контейнеров. |
| `providers.docker.exposedbydefault=false` | Отключает автоматическое создание роутеров ко всем контейнерам на сервере. |
| `providers.docker.network=traefik-shared` | Сеть докера, по которой будет выполнятся подключение к контейнерам. |
| `providers.file.directory=/etc/traefik/dynamic` | Папка с конфигурационным файлом. |
| `providers.file.watch=true` | Включает отслеживание изменений файла конфигурации. |
| `entrypoints.http.address=:80` | Создаёт entrypoint с названием http и слушает 80 порт. |
| `entrypoints.https.address=:443` | Создаёт entrypoint с названием https и слушает 443 порт. |
Конечно, вы всегда можете глянуть `traefik --help` и подобрать себе желаемые параметры.
Также из docker-compose файла видно, что я создал докер сеть `traefik-shared`, которую в дальнейшем буду использовать на всех контейнерах, которым требуется свой домен.
@ -153,16 +156,19 @@ networks:
Для генерации локальных сертификатов я использую тулу [mkcert](https://github.com/FiloSottile/mkcert).
Для любого локального домена я делаю что-то типа:
```bash
mkcert "*.local"
mv _wildcard.local-key.pem local.key
mv _wildcard.local.pem local.pem
```
И помещаю это в папочку `certs` рядом с `docker-compose.yml`.
После того как я создал все нужные сертефикаты для всех доменов, их надо указать в файле `config.toml` в папочке traefik.
Вот пример:
```toml{}[config.toml]
[tls.options]
[tls.options.default]
@ -190,9 +196,11 @@ mv _wildcard.local.pem local.pem
После этого вы можете запускать traefik и наслаждаться доменами для ваших контейнеров.
# Запуск приложений
Теперь сконфигурируем приложение таким образом, чтобы к нему можно было обращаться через доменное имя.
Для примера возьмем мелкое приложение на nodejs со следующей структурой проекта:
```
.
├── docker-compose.yml
@ -260,10 +268,15 @@ services:
server:
build: .
labels:
# Включить поддержку роутинга через traefik.
- traefik.enable=true
# Поставить правило роутинга, если Host запроса равен test_node.local.
- traefik.http.routers.test_node.rule=Host(`test_node.local`)
# Слушать на entrypoint http (80 порт, это было объявлено в параметрах запуска traefik).
- traefik.http.routers.test_node.entrypoints=http
# Сервис, связанный с роутером test_node.
- traefik.http.routers.test_node.service=node_test
# Порт, куда направлять запросы в сервис node_test.
- traefik.http.services.node_test.loadbalancer.server.port=3000
command: runserver
networks:
@ -271,6 +284,7 @@ services:
networks:
# Докер сеть, в которой находится traefik.
traefik-shared:
name: traefik-shared
external: true
@ -282,14 +296,6 @@ networks:
Как вы видите, приложение слушает на порт `3000` и отвечает свим hostname и количеством обработанных запросов. А в docker-compose.yml, в отличие от обычного проекта, появились labels.
| Лейбл | Что делает |
|---------------------------------------------------------------|---------------------------------------------------------------------------------------|
| ``traefik.enable=true`` | Включить поддержку роутинга через traefik |
| ``traefik.http.routers.<router>.rule=Host(`test_node.local`)`` | Поставить правило роутинга, если Host запроса равен test_node.local |
| ``traefik.http.routers.<router>.entrypoints=http`` | Слушать на entrypoint http (80 порт, это было объявлено в параметрах запуска traefik) |
| ``traefik.http.routers.<router>.service=<service>`` | Сервис, связанный с роутером test_node |
| ``traefik.http.services.<service>.loadbalancer.server.port=3000`` | Порт, куда направлять запросы в сервис node_test |
<hr/>
<b-message type="is-danger" has-icon>
@ -301,13 +307,14 @@ networks:
Обратите внимание на косые кавычки при указании хоста! Это обязательно.
В объявлении labels могут быть использованы переменные среды. Например:
``traefik.http.routers.test_node.rule=Host(`${APP_HOST}`)``
`` traefik.http.routers.test_node.rule=Host(`${APP_HOST}`) ``
</b-message>
Также можно видеть, что я подключил контейнер к сети, которую мы указывали в контейнере traefik. Здесь она помечена как external.
Теперь мы можем спокойно запустить наш сервис. Для этого воспользуемся следующей командой:
```bash
docker-compose up --build --scale server=3
```
@ -328,6 +335,7 @@ $ curl -H "Host: test_node.local" "http://localhost"
Как вы видите, traefik балансирует между контейнерами за нас. И я считаю, что это - победа.
## Подключение TLS и сертификатов
Тут всё не намного сложнее. Давайте немного поменяем лейблы нашего контейнера.
```yaml
@ -347,6 +355,7 @@ services:
На данном этапе вам потребуется добавить свой хост в `/etc/hosts`, если вы используете нормальную систему. Но если вы всё же на windows, то вам потребуется добавить правило в `C:\Windows\System32\drivers\etc\hosts`.
И добавляем в конец файла запись:
```
127.0.0.1 test_node.local
```
@ -365,12 +374,12 @@ $ curl --insecure https://test_node.local
{"request_num":0,"host":"7417ac8fda92"}
```
## Добавление локальных сервисов не из докера
Все те флаги, которые мы указываем в labels, вы также можете указать в файле конфигурации рядом с docker-compose.yml, указав конкретный ip адрес.
Например:
```toml
[http.routers]
# Define a connection between requests and services
@ -387,8 +396,8 @@ $ curl --insecure https://test_node.local
url = "http://192.168.1.89:8100"
```
# Создание локального DNS
В данном пункте я бы хотел рассказать, как настроить свой DNS-сервер, чтобы ваши домены были доступны всем устройствам в локальной сети. Для этого я буду использовать dnsmasq. Пользователям винды он недоступен, поэтому советую развернуть маленький домашний сервер на линуксе.
Для этого установите `dnsmasq` и найдите и раскомментируйте, либо добавьте следующие строчки в файл `/etc/dnsmasq.conf`:
@ -406,6 +415,7 @@ address=/.<other_domain>/<your_local_ip>
Чтобы это узнать, посмотрите свой ip через роутер или выполните `ip addr`.
Вообще, `dnsmasq` парсит файл `/etc/hosts` и вы можете туда добавлять записи, типа:
```
192.168.1.1 mydomain.local
```
@ -413,6 +423,7 @@ address=/.<other_domain>/<your_local_ip>
Но так как я указал `address`, то это необязательно. `dnsmasq` и без явного указания поддоменов должен будет работать отлично.
Запустите `dnsmasq` в режиме сревиса:
```bash
sudo systemctl enable dnsmasq.service
sudo systemctl start dnsmasq.service
@ -457,5 +468,4 @@ services:
[![GIF](/images/traefik_imgs/traefik_web.png)](/images/traefik_imgs/traefik_web.png)
Разве это не круто?

View File

@ -1,9 +1,9 @@
<template>
<div class="page">
<b-navbar type="is-primary w-100">
<b-navbar type="is-primary w-100" :fixed-top="true">
<template #brand>
<NuxtLink to="/" class="navbar-item">
<img src="/icon.png" alt="Logo" /> S3rius' dev blog
<img src="/icon.png" alt="Logo" /> Dev blog
</NuxtLink>
</template>
<template #end>
@ -24,7 +24,7 @@
:key="category"
class="is-hidden-desktop"
>
<p class="navbar-item is-inactive divider">
<p class="navbar-item is-inactive category">
<span>{{ category }}</span>
</p>
<NuxtLink
@ -73,7 +73,8 @@ export default defineComponent({
const categories = ref([])
$content({ deep: true })
.only(['category', 'slug', 'title', 'position'])
.sortBy('createdAt', 'asc')
.sortBy('category', 'asc')
.sortBy('position', 'asc')
.fetch()
.then((pages) => {
let cats = new Map()
@ -94,12 +95,11 @@ export default defineComponent({
</script>
<style scoped lang="scss">
.divider {
.category {
width: 100%;
text-align: center;
border-bottom: 1px solid #000;
line-height: 0.1em;
margin: 10px 0 20px;
color: gray;
span {
background: #fff;

View File

@ -70,7 +70,7 @@ export default {
short_name: 'Dev blog',
lang: 'ru',
background_color: '#fafdff',
theme_color: '#fafdff',
theme_color: '#687cec',
},
icon: {
fileName: 'icon.png',

View File

@ -44,10 +44,16 @@ export default defineComponent({
]
if (doc.image) {
meta_data.push({
hid: 'og:description',
name: 'og:description',
hid: 'og:image',
name: 'og:image',
content: doc.image,
})
} else {
meta_data.push({
hid: 'og:image',
name: 'og:image',
content: 'https://s3rius.blog/logo.png',
})
}
meta.value = meta_data
})
@ -83,7 +89,7 @@ export default defineComponent({
font-weight: 300;
letter-spacing: -0.01em;
color: rgba(0, 0, 0, 0.54);
margin: 1em 0.5em;
margin: 1em 0;
}
h1 {
@ -139,5 +145,10 @@ export default defineComponent({
margin-bottom: 0.5em !important;
margin-left: 1.25em !important;
}
table {
display: inline-block;
overflow: auto;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

View File

@ -0,0 +1,484 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 668 277" style="enable-background:new 0 0 668 277;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#326DE6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st1{opacity:0.71;fill:#326CE6;}
.st2{opacity:0.45;fill:#FFFFFF;}
.st3{fill:#FFFFFF;stroke:#006DE9;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st4{fill:#006DE9;}
.st5{fill:#A0CAEA;}
.st6{fill:#FFFFFF;}
.st7{opacity:0.13;}
.st8{fill:url(#SVGID_1_);}
.st9{fill:url(#SVGID_2_);}
.st10{fill:#FFFFFF;stroke:#006DE9;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st11{fill:#FFFFFF;stroke:#006DE9;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st12{fill:#FFFFFF;stroke:#326DE6;stroke-width:3.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st13{fill:#326DE6;}
.st14{fill:none;stroke:#326DE6;stroke-width:2.4;stroke-miterlimit:10;}
.st15{fill:#A0CAE9;}
.st16{fill:#FFFFFF;stroke:#326DE6;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st17{fill:#FFFFFF;stroke:#326DE6;stroke-width:1.6;stroke-miterlimit:10;}
.st18{fill:none;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;}
.st19{fill:none;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.3749,1.5832;}
.st20{fill:none;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.4006,1.6004;}
.st21{fill:none;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.4,1.6;}
.st22{fill:none;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;}
.st23{fill:none;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.3975,1.5984;}
.st24{fill:none;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.395,1.5966;}
.st25{fill:none;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.3963,1.5976;}
.st26{opacity:0.1;fill:#EEF406;}
.st27{opacity:2.000000e-02;fill:#EEF406;}
.st28{opacity:0.1;fill:#06F7C9;}
.st29{fill:none;stroke:#006DE9;stroke-width:0.8;stroke-miterlimit:10;}
.st30{opacity:0.1;fill:url(#SVGID_3_);}
.st31{opacity:0.1;fill:url(#SVGID_4_);}
.st32{opacity:0.1;fill:url(#SVGID_5_);}
.st33{opacity:0.1;fill:url(#SVGID_6_);}
.st34{fill:none;stroke:#326DE6;stroke-width:1.2;stroke-miterlimit:10;}
.st35{opacity:0.1;fill:url(#SVGID_7_);}
.st36{opacity:0.1;fill:url(#SVGID_8_);}
.st37{opacity:0.1;fill:url(#SVGID_9_);}
.st38{opacity:0.1;fill:url(#SVGID_10_);}
.st39{fill:none;stroke:#326DE6;stroke-width:2;stroke-miterlimit:10;}
.st40{opacity:0.4;fill:none;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;}
.st41{fill:none;stroke:#EEF406;stroke-width:2.4596;stroke-miterlimit:10;}
.st42{fill:#011F38;}
.st43{opacity:0.4;}
.st44{opacity:0.1;}
.st45{fill:#326DE6;stroke:#EEF406;stroke-width:2;stroke-miterlimit:10;}
.st46{fill:none;stroke:#FFFFFF;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
.st47{fill:#06F7C9;stroke:#FFFFFF;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st48{fill:none;stroke:#011F38;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
.st49{fill:#326DE6;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;}
.st50{fill:#06F7C9;stroke:#011F38;stroke-width:0.8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st51{fill:#8115FF;stroke:#011F38;stroke-width:0.8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st52{opacity:0.3;}
.st53{opacity:0.2;fill:#6D6E71;}
.st54{fill:#EEF406;}
.st55{fill:#06F7C9;}
.st56{fill:#FFFFFF;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.4,1.6;}
.st57{fill:#FFFFFF;stroke:#EEF406;stroke-width:1.6;stroke-miterlimit:10;stroke-dasharray:2.4,1.6;}
.st58{fill:none;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.4938,1.6626;}
.st59{fill:none;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.0084,1.3389;}
.st60{fill:none;stroke:#06F7C9;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:2.724,1.816;}
.st61{fill:#011F38;stroke:#414042;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st62{fill:none;stroke:#011F38;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st63{fill:none;stroke:#011F38;stroke-width:0.2813;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
<symbol id="node_high_level" viewBox="-81 -93 162 186.1">
<polygon class="st0" points="-80,-46 -80,46 0,92 80,46 80,-46 0,-92 "/>
<g id="Isolation_Mode_3_">
</g>
</symbol>
<symbol id="node_x5F_empty" viewBox="-87.5 -100.6 175.1 201.1">
<use xlink:href="#node_high_level" width="162" height="186.1" id="XMLID_201_" x="-81" y="-93" transform="matrix(1.0808 0 0 1.0808 -3.292006e-05 -3.749943e-05)" style="overflow:visible;"/>
<g>
<polygon class="st1" points="76.8,-28.1 -14,-80.3 0,-88.3 76.7,-44.4 "/>
<polygon class="st2" points="76.8,-28.1 32.1,-53.8 38.8,-66.1 76.7,-44.4 "/>
</g>
</symbol>
<symbol id="node_x5F_new" viewBox="-87.6 -101 175.2 202">
<polygon class="st3" points="0,-100 -86.6,-50 -86.6,50 0,100 86.6,50 86.6,-50 "/>
<polygon class="st4" points="-86.6,-20.2 -86.6,-50 0,-100 25.8,-85.1 "/>
<polygon class="st5" points="-40.8,-70.7 -32.9,-57 15.7,-85.1 0,-94.3 "/>
<text transform="matrix(0.866 -0.5 -0.5 -0.866 -33.9256 -70.7388)" class="st6" style="font-family:'RobotoSlab-Regular'; font-size:11.3632px;">Docker</text>
<text transform="matrix(0.866 -0.5 -0.5 -0.866 -76.0668 -46.4087)" class="st6" style="font-family:'RobotoSlab-Regular'; font-size:11.3632px;">Kubelt</text>
</symbol>
<g id="CLUSTER">
</g>
<g id="master">
<g id="master_x5F_level1">
</g>
</g>
<g id="Node">
<g id="Node_x5F_level3_x5F_1">
<g id="Isolation_Mode">
</g>
</g>
</g>
<g id="service">
</g>
<g id="pods">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="122.1878" y1="127.5093" x2="204.1367" y2="127.5093">
<stop offset="0" style="stop-color:#326DE6"/>
<stop offset="1" style="stop-color:#10FFC6"/>
</linearGradient>
<circle style="opacity:0.1;fill:url(#SVGID_1_);" cx="163.2" cy="127.5" r="41"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="238.2856" y1="127.5093" x2="347.5509" y2="127.5093">
<stop offset="0" style="stop-color:#326DE6"/>
<stop offset="1" style="stop-color:#10FFC6"/>
</linearGradient>
<circle style="opacity:0.1;fill:url(#SVGID_2_);" cx="292.9" cy="127.5" r="54.6"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="390.5175" y1="77.3348" x2="517.7111" y2="179.9297">
<stop offset="0" style="stop-color:#326DE6"/>
<stop offset="1" style="stop-color:#10FFC6"/>
</linearGradient>
<circle class="st30" cx="452.7" cy="127.5" r="71"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="16.3336" y1="127.5093" x2="77.7953" y2="127.5093">
<stop offset="0" style="stop-color:#326DE6"/>
<stop offset="1" style="stop-color:#10FFC6"/>
</linearGradient>
<circle class="st31" cx="47.1" cy="127.5" r="30.7"/>
<circle class="st39" cx="163.2" cy="127.5" r="41"/>
<circle class="st39" cx="47.1" cy="127.5" r="30.7"/>
<circle class="st39" cx="292.9" cy="127.5" r="54.6"/>
<circle class="st39" cx="452.7" cy="127.5" r="71"/>
</g>
<g id="IP">
<g>
<path class="st42" d="M121.7,110.7l0.6-1.4l-6.6-3l-0.5,1.6l-0.4-0.2l0.5-2.4l7.3,3.3l0.7-1.4l0.5,0.2l-1.6,3.4L121.7,110.7z"/>
<path class="st42" d="M124.1,100.5c0.9,0.6,1.5,1.2,1.8,1.9c0.3,0.7,0.2,1.4-0.3,2.1c-0.4,0.7-1,1.1-1.8,1.2
c-0.8,0.1-1.6-0.2-2.5-0.7l-1.6-1c-0.9-0.6-1.5-1.2-1.8-1.9c-0.3-0.7-0.2-1.4,0.3-2.1c0.4-0.7,1-1.1,1.8-1.2
c0.8-0.1,1.6,0.2,2.5,0.7L124.1,100.5z M122,100c-0.7-0.5-1.4-0.7-2-0.6c-0.6,0-1,0.3-1.4,0.9c-0.3,0.5-0.4,1.1-0.2,1.6
c0.2,0.5,0.7,1,1.5,1.5l1.8,1.1c0.7,0.5,1.4,0.7,2,0.6c0.6,0,1-0.3,1.4-0.9c0.3-0.5,0.4-1.1,0.2-1.6c-0.2-0.5-0.7-1-1.5-1.5
L122,100z"/>
<path class="st42" d="M128.3,100.4l-0.5,0.6l-0.8-0.6l0.5-0.6L128.3,100.4z"/>
<path class="st42" d="M128.9,98.8l1-1.2l-5.3-4.8l-1,1.4l-0.4-0.3l1.2-2.1l5.9,5.3l1.1-1.1l0.4,0.3l-2.5,2.8L128.9,98.8z"/>
<path class="st42" d="M134.2,89.8c0.7,0.8,1.1,1.6,1.1,2.4c0,0.8-0.3,1.4-0.9,1.9c-0.6,0.5-1.3,0.7-2.1,0.6
c-0.7-0.1-1.5-0.6-2.2-1.5l-1.2-1.4c-0.7-0.8-1.1-1.6-1.1-2.4c0-0.8,0.3-1.4,0.9-1.9c0.6-0.5,1.3-0.7,2.1-0.6
c0.7,0.1,1.5,0.6,2.2,1.5L134.2,89.8z M132.4,88.7c-0.6-0.7-1.1-1.1-1.7-1.2c-0.6-0.1-1.1,0-1.6,0.4c-0.5,0.4-0.7,0.9-0.6,1.5
c0.1,0.6,0.4,1.2,0.9,1.9l1.4,1.6c0.6,0.7,1.1,1.1,1.7,1.2c0.6,0.1,1.1,0,1.6-0.4c0.5-0.4,0.7-0.9,0.6-1.5
c-0.1-0.6-0.4-1.2-0.9-1.9L132.4,88.7z"/>
<path class="st42" d="M138.3,91l-0.7,0.5l-0.5-0.8l0.7-0.5L138.3,91z"/>
<path class="st42" d="M139.3,89.7l1.3-0.8l-3.6-6.2l-1.3,1.1l-0.2-0.4l1.8-1.6l4,6.9l1.4-0.7l0.3,0.4l-3.3,1.9L139.3,89.7z"/>
<path class="st42" d="M147.2,82.7c0.4,1,0.5,1.9,0.3,2.6c-0.2,0.7-0.7,1.3-1.5,1.6c-0.8,0.3-1.5,0.3-2.1-0.1
c-0.7-0.4-1.2-1.1-1.6-2.1l-0.7-1.8c-0.4-1-0.5-1.9-0.3-2.6s0.7-1.3,1.4-1.6c0.8-0.3,1.5-0.3,2.1,0.1c0.7,0.4,1.2,1.1,1.6,2.1
L147.2,82.7z M145.8,81.1c-0.3-0.8-0.8-1.4-1.2-1.7c-0.5-0.3-1-0.3-1.6-0.1c-0.6,0.2-0.9,0.7-1.1,1.2c-0.1,0.6,0,1.2,0.3,2.1
l0.8,2c0.3,0.8,0.8,1.4,1.2,1.7c0.5,0.3,1,0.3,1.6,0.1c0.6-0.2,0.9-0.7,1.1-1.2c0.1-0.6,0-1.3-0.3-2.1L145.8,81.1z"/>
<path class="st42" d="M150.6,85.2l-0.8,0.2l-0.3-0.9l0.8-0.2L150.6,85.2z"/>
<path class="st42" d="M152,84.7l-0.1-0.5l2.1-3.6c0.4-0.7,0.7-1.2,0.8-1.6s0.2-0.8,0.1-1.2c-0.1-0.5-0.3-0.9-0.7-1.2
c-0.4-0.3-0.8-0.3-1.3-0.2c-0.6,0.1-1.1,0.4-1.3,0.8c-0.3,0.4-0.3,0.9-0.2,1.5l-0.6,0.1l0,0c-0.2-0.7,0-1.3,0.3-1.9
c0.4-0.6,1-0.9,1.8-1.1c0.7-0.1,1.3,0,1.8,0.3s0.8,0.8,1,1.5c0.1,0.5,0,1-0.2,1.5s-0.5,1.1-0.9,1.8l-1.8,3.1l0,0l3.7-0.7l-0.2-1.2
l0.6-0.1l0.3,1.8L152,84.7z"/>
</g>
<g>
<path class="st42" d="M15.9,114.8l0.6-1.4l-6.5-3.1l-0.5,1.6L9,111.7l0.6-2.4l7.2,3.4l0.7-1.3l0.5,0.2l-1.6,3.4L15.9,114.8z"/>
<path class="st42" d="M18.6,104.6c0.9,0.6,1.5,1.3,1.7,2c0.2,0.7,0.1,1.4-0.4,2.1c-0.5,0.7-1.1,1-1.8,1.1s-1.6-0.2-2.5-0.9
l-1.6-1.1c-0.9-0.6-1.5-1.3-1.7-2s-0.1-1.4,0.4-2.1c0.5-0.7,1.1-1,1.9-1.1c0.8,0,1.6,0.2,2.5,0.9L18.6,104.6z M16.6,104
c-0.7-0.5-1.4-0.7-1.9-0.7s-1,0.3-1.4,0.8c-0.4,0.5-0.4,1.1-0.2,1.6s0.7,1.1,1.4,1.6l1.7,1.2c0.7,0.5,1.4,0.7,1.9,0.7
s1.1-0.3,1.4-0.8c0.4-0.5,0.4-1.1,0.2-1.6c-0.2-0.5-0.7-1.1-1.4-1.6L16.6,104z"/>
<path class="st42" d="M22.8,104.9l-0.5,0.6l-0.7-0.6l0.5-0.6L22.8,104.9z"/>
<path class="st42" d="M23.5,103.4l1.1-1.1l-4.8-5.4l-1.1,1.3l-0.3-0.4l1.5-2l5.3,6l1.2-1l0.3,0.4l-2.8,2.5L23.5,103.4z"/>
<path class="st42" d="M30.1,95.2c0.6,0.9,0.8,1.8,0.7,2.5c-0.1,0.8-0.5,1.3-1.2,1.8c-0.7,0.4-1.4,0.5-2.1,0.3s-1.4-0.9-1.9-1.8
l-1-1.6c-0.6-0.9-0.8-1.8-0.7-2.5c0.1-0.8,0.5-1.3,1.2-1.8c0.7-0.4,1.4-0.5,2.1-0.3c0.7,0.3,1.4,0.9,1.9,1.8L30.1,95.2z
M28.4,93.8c-0.5-0.7-1-1.2-1.5-1.4c-0.5-0.2-1.1-0.2-1.6,0.2c-0.5,0.3-0.8,0.8-0.9,1.4c0,0.6,0.2,1.2,0.6,2l1.1,1.8
c0.5,0.7,1,1.2,1.5,1.4c0.5,0.2,1.1,0.2,1.6-0.2c0.5-0.3,0.8-0.8,0.9-1.4s-0.2-1.2-0.6-2L28.4,93.8z"/>
<path class="st42" d="M33.8,97.1l-0.7,0.3l-0.4-0.9l0.7-0.3L33.8,97.1z"/>
<path class="st42" d="M35.1,96l1.4-0.5l-2.2-6.8l-1.5,0.7l-0.2-0.5l2.1-1.2l2.4,7.6l1.5-0.4l0.2,0.5l-3.6,1.2L35.1,96z"/>
<path class="st42" d="M44.4,91.1c0.2,1.1,0.1,2-0.3,2.6c-0.4,0.7-1,1-1.8,1.2c-0.8,0.1-1.5-0.1-2.1-0.6s-0.9-1.3-1.1-2.4L38.8,90
c-0.2-1.1,0-2,0.3-2.6c0.4-0.7,1-1,1.8-1.2c0.8-0.1,1.5,0.1,2.1,0.6c0.6,0.5,0.9,1.3,1.1,2.4L44.4,91.1z M43.4,89.2
c-0.1-0.9-0.4-1.5-0.8-1.9s-0.9-0.6-1.5-0.5c-0.6,0.1-1.1,0.4-1.3,0.9c-0.3,0.5-0.3,1.2-0.2,2.1l0.3,2.1c0.1,0.9,0.4,1.5,0.8,1.9
c0.4,0.4,0.9,0.6,1.5,0.5c0.6-0.1,1.1-0.4,1.3-0.9s0.3-1.2,0.2-2.1L43.4,89.2z"/>
<path class="st42" d="M47,94.4l-0.8,0l0-1l0.8,0L47,94.4z"/>
<path class="st42" d="M48.6,93.9l1.5,0.1l0.7-7.2l-1.7,0.1l0-0.5l2.4-0.3L50.8,94l1.5,0.2l-0.1,0.5l-3.7-0.4L48.6,93.9z"/>
</g>
<g>
<path class="st42" d="M246.8,91.7l0.9-1.2l-5.5-4.6l-0.9,1.4l-0.4-0.3l1.1-2.2l6.1,5.1l1-1.1l0.4,0.3l-2.4,2.9L246.8,91.7z"/>
<path class="st42" d="M251.7,82.3c0.8,0.8,1.2,1.5,1.3,2.3c0.1,0.8-0.2,1.4-0.8,2c-0.6,0.6-1.3,0.8-2,0.7
c-0.8-0.1-1.5-0.5-2.3-1.3l-1.3-1.4c-0.8-0.8-1.2-1.5-1.3-2.3c-0.1-0.8,0.2-1.4,0.7-2c0.6-0.6,1.3-0.8,2-0.7
c0.8,0.1,1.5,0.5,2.3,1.3L251.7,82.3z M249.8,81.4c-0.6-0.6-1.2-1-1.8-1.1c-0.6-0.1-1.1,0.1-1.5,0.5c-0.4,0.4-0.6,1-0.5,1.5
c0.1,0.6,0.5,1.2,1.1,1.8l1.5,1.5c0.6,0.6,1.2,1,1.8,1.1c0.6,0.1,1.1-0.1,1.5-0.5c0.4-0.4,0.6-1,0.5-1.5s-0.5-1.2-1.1-1.8
L249.8,81.4z"/>
<path class="st42" d="M255.8,83.2l-0.6,0.5l-0.6-0.7l0.6-0.5L255.8,83.2z"/>
<path class="st42" d="M256.7,81.7l1.2-1l-4.3-5.8l-1.2,1.2l-0.3-0.4l1.6-1.8l4.8,6.4l1.3-0.9l0.3,0.4l-3,2.2L256.7,81.7z"/>
<path class="st42" d="M263.6,73.8c0.6,0.9,0.8,1.8,0.7,2.5c-0.1,0.7-0.5,1.3-1.2,1.8c-0.7,0.4-1.4,0.5-2.1,0.2
c-0.7-0.3-1.3-0.9-1.9-1.8l-1-1.6c-0.6-0.9-0.8-1.8-0.7-2.5c0.1-0.8,0.5-1.3,1.2-1.8c0.7-0.4,1.4-0.5,2.1-0.2
c0.7,0.3,1.4,0.9,1.9,1.8L263.6,73.8z M262,72.4c-0.5-0.7-0.9-1.2-1.5-1.5s-1.1-0.2-1.6,0.1c-0.5,0.3-0.8,0.8-0.9,1.4
c0,0.6,0.2,1.2,0.6,2l1.1,1.8c0.4,0.7,0.9,1.2,1.5,1.5c0.5,0.2,1.1,0.2,1.6-0.1c0.5-0.3,0.8-0.8,0.9-1.4c0-0.6-0.2-1.2-0.6-2
L262,72.4z"/>
<path class="st42" d="M267.4,75.6l-0.7,0.4l-0.4-0.9l0.7-0.4L267.4,75.6z"/>
<path class="st42" d="M268.6,74.4l1.4-0.7l-2.8-6.6l-1.5,0.9l-0.2-0.5l2-1.4l3.1,7.3l1.4-0.5l0.2,0.5l-3.5,1.5L268.6,74.4z"/>
<path class="st42" d="M277.3,68.3c0.3,1.1,0.4,1.9,0.1,2.6c-0.3,0.7-0.8,1.2-1.6,1.4c-0.8,0.2-1.5,0.2-2.1-0.3
c-0.6-0.4-1.1-1.2-1.4-2.2l-0.6-1.8c-0.3-1-0.4-1.9-0.1-2.6c0.3-0.7,0.8-1.2,1.6-1.4c0.8-0.2,1.5-0.2,2.1,0.3
c0.6,0.4,1.1,1.2,1.4,2.2L277.3,68.3z M276,66.6c-0.3-0.8-0.6-1.4-1.1-1.8s-1-0.4-1.6-0.2c-0.6,0.2-1,0.6-1.2,1.1
c-0.2,0.6-0.1,1.2,0.1,2.1l0.6,2c0.3,0.8,0.6,1.4,1.1,1.8c0.5,0.4,1,0.4,1.6,0.3c0.6-0.2,1-0.6,1.2-1.1s0.1-1.2-0.1-2.1L276,66.6z
"/>
<path class="st42" d="M280.5,71l-0.8,0.2l-0.2-0.9l0.8-0.2L280.5,71z"/>
<path class="st42" d="M282.9,65.8l0.8-0.1c0.6-0.1,1.1-0.3,1.3-0.7c0.3-0.4,0.4-0.8,0.3-1.3c-0.1-0.5-0.3-0.9-0.6-1.2
c-0.3-0.3-0.8-0.4-1.4-0.3c-0.5,0.1-1,0.3-1.3,0.7c-0.3,0.4-0.4,0.8-0.3,1.3l-0.6,0.1l0,0c-0.1-0.7,0-1.2,0.5-1.7
c0.4-0.5,1-0.8,1.7-0.9c0.8-0.1,1.4,0,1.9,0.4c0.5,0.3,0.8,0.9,0.9,1.6c0.1,0.4,0,0.8-0.2,1.2c-0.2,0.4-0.5,0.7-0.9,0.9
c0.5,0.1,1,0.3,1.3,0.6c0.3,0.3,0.5,0.7,0.6,1.2c0.1,0.7,0,1.4-0.5,1.9c-0.4,0.5-1,0.8-1.8,0.9c-0.7,0.1-1.4,0-2-0.4
c-0.6-0.3-0.9-0.9-1-1.6l0,0l0.6-0.1c0.1,0.5,0.3,0.9,0.8,1.2c0.4,0.3,0.9,0.4,1.5,0.3c0.6-0.1,1-0.3,1.3-0.7s0.4-0.8,0.3-1.4
c-0.1-0.6-0.3-1-0.7-1.2c-0.4-0.2-0.9-0.3-1.6-0.2l-0.8,0.1L282.9,65.8z"/>
</g>
<g>
<path class="st42" d="M397.1,77.6l1-1.2l-5.2-4.9l-1,1.4l-0.4-0.3l1.3-2.1l5.8,5.5l1.1-1.1l0.4,0.4l-2.6,2.7L397.1,77.6z"/>
<path class="st42" d="M402.5,68.5c0.7,0.8,1.1,1.6,1.2,2.4c0.1,0.8-0.2,1.4-0.8,2c-0.6,0.6-1.3,0.8-2,0.7s-1.5-0.6-2.2-1.4
l-1.3-1.4c-0.7-0.8-1.1-1.6-1.2-2.4s0.2-1.4,0.8-2c0.6-0.6,1.3-0.8,2-0.7c0.8,0.1,1.5,0.6,2.2,1.4L402.5,68.5z M400.6,67.4
c-0.6-0.6-1.2-1-1.7-1.2c-0.6-0.1-1.1,0-1.6,0.5c-0.5,0.4-0.7,0.9-0.6,1.5c0.1,0.6,0.4,1.2,1,1.8l1.4,1.6c0.6,0.6,1.2,1,1.7,1.2
c0.6,0.1,1.1,0,1.6-0.4c0.5-0.4,0.7-0.9,0.6-1.5c-0.1-0.6-0.4-1.2-1-1.8L400.6,67.4z"/>
<path class="st42" d="M406.5,69.5l-0.6,0.5l-0.6-0.7l0.6-0.5L406.5,69.5z"/>
<path class="st42" d="M407.5,68l1.2-1l-4.2-5.8l-1.2,1.2L403,62l1.6-1.8l4.7,6.4l1.3-0.8l0.3,0.4l-3,2.2L407.5,68z"/>
<path class="st42" d="M414.5,60c0.6,0.9,0.8,1.8,0.7,2.5c-0.1,0.8-0.5,1.3-1.2,1.8c-0.7,0.4-1.4,0.5-2.1,0.3
c-0.7-0.3-1.4-0.9-1.9-1.8l-1-1.6c-0.6-0.9-0.8-1.8-0.7-2.5c0.1-0.8,0.5-1.3,1.2-1.8c0.7-0.4,1.4-0.5,2.1-0.3
c0.7,0.3,1.4,0.9,1.9,1.8L414.5,60z M412.8,58.7c-0.5-0.7-1-1.2-1.5-1.5c-0.5-0.2-1.1-0.2-1.6,0.2c-0.5,0.3-0.8,0.8-0.9,1.4
c0,0.6,0.2,1.2,0.6,2l1.1,1.8c0.5,0.7,1,1.2,1.5,1.5c0.5,0.2,1.1,0.2,1.6-0.1c0.5-0.3,0.8-0.8,0.9-1.4s-0.2-1.2-0.6-2L412.8,58.7z
"/>
<path class="st42" d="M418.2,61.8l-0.7,0.4l-0.5-0.8l0.7-0.4L418.2,61.8z"/>
<path class="st42" d="M419.5,60.6l1.4-0.7l-3.1-6.5l-1.4,0.9l-0.2-0.4l1.9-1.5l3.4,7.2l1.4-0.6l0.2,0.5l-3.4,1.6L419.5,60.6z"/>
<path class="st42" d="M427.8,54.1c0.4,1,0.5,1.9,0.2,2.6s-0.7,1.2-1.5,1.5c-0.8,0.3-1.5,0.2-2.1-0.1c-0.7-0.4-1.2-1.1-1.6-2.1
l-0.7-1.8c-0.4-1-0.5-1.9-0.2-2.6c0.2-0.7,0.7-1.2,1.5-1.5c0.8-0.3,1.5-0.2,2.1,0.1c0.7,0.4,1.2,1.1,1.6,2.1L427.8,54.1z
M426.4,52.4c-0.3-0.8-0.7-1.4-1.2-1.7c-0.5-0.3-1-0.4-1.6-0.1c-0.6,0.2-1,0.6-1.1,1.2c-0.1,0.6-0.1,1.2,0.2,2.1l0.8,2
c0.3,0.8,0.7,1.4,1.2,1.7s1,0.4,1.6,0.2c0.6-0.2,1-0.6,1.1-1.2s0.1-1.3-0.3-2.1L426.4,52.4z"/>
<path class="st42" d="M431.2,56.5l-0.8,0.2l-0.3-0.9l0.8-0.2L431.2,56.5z"/>
<path class="st42" d="M436.3,52.3l1.3-0.3l0.1,0.6l-1.3,0.3l0.4,1.5l0.9-0.1l0.1,0.5l-2.5,0.6l-0.1-0.5l0.9-0.3l-0.4-1.5l-3.9,0.9
l-0.1-0.4l2.4-6.7l0.7-0.2L436.3,52.3z M432.6,53.2l3.1-0.7l-1.1-4.7l0,0l-0.1,0.7L432.6,53.2z"/>
</g>
</g>
<g id="deployments">
</g>
<g id="containers_x2F_volumes">
<g>
<g>
<polygon class="st50" points="138.1,120.8 148.6,114.7 159.2,120.8 148.6,126.9 "/>
<polygon class="st50" points="138.1,133 138.1,120.8 148.6,126.9 148.6,139.1 "/>
<polygon class="st50" points="148.6,139.1 148.6,126.9 159.2,120.8 159.2,133 "/>
</g>
<g>
<path class="st51" d="M188.2,132.2C188.2,132.2,188.2,132.2,188.2,132.2C188.2,132.1,188.2,132.1,188.2,132.2v-10.6h-21.1v10.6
c0,0,0,0,0,0c0,0,0,0,0,0v0.2h0c0.2,2.9,4.9,5.2,10.5,5.2c5.7,0,10.3-2.3,10.5-5.2h0V132.2z"/>
<ellipse class="st51" cx="177.7" cy="121.7" rx="10.6" ry="5.4"/>
</g>
</g>
<g>
<g>
<polygon class="st50" points="36.5,121.4 47.1,115.3 57.6,121.4 47.1,127.5 "/>
<polygon class="st50" points="36.5,133.6 36.5,121.4 47.1,127.5 47.1,139.7 "/>
<polygon class="st50" points="47.1,139.7 47.1,127.5 57.6,121.4 57.6,133.6 "/>
</g>
</g>
<g>
<g>
<polygon class="st50" points="282.4,108.7 292.9,102.6 303.5,108.7 292.9,114.8 "/>
<polygon class="st50" points="282.4,120.9 282.4,108.7 292.9,114.8 292.9,127 "/>
<polygon class="st50" points="292.9,127 292.9,114.8 303.5,108.7 303.5,120.9 "/>
</g>
<g>
<polygon class="st50" points="270.5,132 278.4,127.4 286.3,132 278.4,136.5 "/>
<polygon class="st50" points="270.5,141.1 270.5,132 278.4,136.5 278.4,145.7 "/>
<polygon class="st50" points="278.4,145.7 278.4,136.5 286.3,132 286.3,141.1 "/>
</g>
<g>
<path class="st51" d="M318,141.8C318,141.8,318,141.8,318,141.8C318,141.8,318,141.8,318,141.8v-10.6h-21.1v10.6c0,0,0,0,0,0
c0,0,0,0,0,0v0.2h0c0.2,2.9,4.9,5.2,10.5,5.2c5.7,0,10.3-2.3,10.5-5.2h0V141.8z"/>
<ellipse class="st51" cx="307.4" cy="131.3" rx="10.6" ry="5.4"/>
</g>
</g>
<g>
<g>
<path class="st51" d="M435.6,133.6C435.6,133.5,435.6,133.5,435.6,133.6C435.6,133.5,435.6,133.5,435.6,133.6v-10.6h-21.1v10.6
c0,0,0,0,0,0c0,0,0,0,0,0v0.2h0c0.2,2.9,4.9,5.2,10.5,5.2c5.7,0,10.3-2.3,10.5-5.2h0V133.6z"/>
<ellipse class="st51" cx="425.1" cy="123" rx="10.6" ry="5.4"/>
</g>
<g>
<path class="st51" d="M479,111.8C479,111.8,479,111.8,479,111.8C479,111.8,479,111.8,479,111.8v-10.6h-21.1v10.6c0,0,0,0,0,0
c0,0,0,0,0,0v0.2h0c0.2,2.9,4.9,5.2,10.5,5.2s10.3-2.3,10.5-5.2h0V111.8z"/>
<ellipse class="st51" cx="468.5" cy="101.3" rx="10.6" ry="5.4"/>
</g>
<g>
<polygon class="st50" points="443.4,122.2 454,116.1 464.6,122.2 454,128.3 "/>
<polygon class="st50" points="443.4,134.4 443.4,122.2 454,128.3 454,140.5 "/>
<polygon class="st50" points="454,140.5 454,128.3 464.6,122.2 464.6,134.4 "/>
</g>
<g>
<polygon class="st50" points="475.1,123.7 483,119.1 490.9,123.7 483,128.3 "/>
<polygon class="st50" points="475.1,132.8 475.1,123.7 483,128.3 483,137.4 "/>
<polygon class="st50" points="483,137.4 483,128.3 490.9,123.7 490.9,132.8 "/>
</g>
</g>
<g>
<g>
<polygon class="st50" points="442.6,146.8 437.3,143.8 432,146.8 437.3,149.9 "/>
<polygon class="st50" points="442.6,152.9 442.6,146.8 437.3,149.9 437.3,156 "/>
<polygon class="st50" points="437.3,156 437.3,149.9 432,146.8 432,152.9 "/>
</g>
</g>
</g>
<g id="labels_x2F_selectors">
</g>
<g id="description">
<g>
<path class="st42" d="M150.5,220.6c1.1,0,2,0.3,2.6,0.9s1,1.3,1,2.2c0,0.9-0.3,1.7-1,2.2c-0.6,0.6-1.5,0.8-2.6,0.8h-1.6v2.1l1,0.2
v1.2h-4v-1.2l1-0.2V222l-1-0.2v-1.2h1H150.5z M148.9,225.3h1.6c0.5,0,0.9-0.1,1.2-0.4c0.3-0.3,0.4-0.7,0.4-1.1
c0-0.5-0.1-0.8-0.4-1.2c-0.3-0.3-0.7-0.5-1.2-0.5h-1.6V225.3z"/>
<path class="st42" d="M154.7,226.6c0-1.1,0.3-1.9,0.9-2.6c0.6-0.7,1.4-1,2.5-1c1.1,0,1.9,0.3,2.5,1c0.6,0.7,0.9,1.6,0.9,2.6v0.1
c0,1.1-0.3,2-0.9,2.6c-0.6,0.7-1.4,1-2.5,1c-1.1,0-1.9-0.3-2.5-1c-0.6-0.7-0.9-1.6-0.9-2.6V226.6z M156.6,226.8
c0,0.7,0.1,1.2,0.3,1.6c0.2,0.4,0.6,0.6,1.1,0.6c0.5,0,0.9-0.2,1.1-0.6s0.3-0.9,0.3-1.6v-0.1c0-0.6-0.1-1.2-0.4-1.6
c-0.2-0.4-0.6-0.6-1.1-0.6c-0.5,0-0.9,0.2-1.1,0.6c-0.2,0.4-0.3,0.9-0.3,1.6V226.8z"/>
<path class="st42" d="M167,229.4c-0.2,0.3-0.5,0.6-0.8,0.8c-0.3,0.2-0.7,0.3-1.1,0.3c-0.9,0-1.6-0.3-2.1-1s-0.7-1.5-0.7-2.6v-0.1
c0-1.1,0.2-2,0.7-2.7c0.5-0.7,1.2-1,2.1-1c0.4,0,0.7,0.1,1,0.2c0.3,0.2,0.5,0.4,0.8,0.7v-2.6l-1-0.2v-1.2h1h1.9v9l0.9,0.2v1.2
h-2.6L167,229.4z M164.3,226.9c0,0.6,0.1,1.1,0.3,1.5s0.6,0.5,1,0.5c0.3,0,0.5-0.1,0.7-0.2s0.4-0.3,0.5-0.5v-3
c-0.1-0.2-0.3-0.4-0.5-0.5c-0.2-0.1-0.4-0.2-0.7-0.2c-0.5,0-0.8,0.2-1,0.6s-0.3,1-0.3,1.6V226.9z"/>
<path class="st42" d="M173.7,230.3V229l3.1-3.4c0.5-0.5,0.8-1,1-1.3c0.2-0.4,0.3-0.7,0.3-1c0-0.4-0.1-0.7-0.3-1
c-0.2-0.3-0.5-0.4-0.9-0.4c-0.4,0-0.8,0.2-1,0.5c-0.2,0.3-0.3,0.7-0.3,1.2h-1.9l0,0c0-0.9,0.3-1.6,0.9-2.2
c0.6-0.6,1.4-0.9,2.4-0.9c1,0,1.8,0.3,2.4,0.8s0.9,1.2,0.9,2.1c0,0.6-0.2,1.1-0.5,1.6c-0.3,0.5-0.9,1.1-1.6,1.9l-1.7,1.9l0,0h2.5
l0.1-1h1.5v2.4H173.7z"/>
</g>
<g>
<path class="st42" d="M35.2,220.6c1.1,0,2,0.3,2.6,0.9s1,1.3,1,2.2c0,0.9-0.3,1.7-1,2.2c-0.6,0.6-1.5,0.8-2.6,0.8h-1.6v2.1l1,0.2
v1.2h-4v-1.2l1-0.2V222l-1-0.2v-1.2h1H35.2z M33.5,225.3h1.6c0.5,0,0.9-0.1,1.2-0.4c0.3-0.3,0.4-0.7,0.4-1.1
c0-0.5-0.1-0.8-0.4-1.2c-0.3-0.3-0.7-0.5-1.2-0.5h-1.6V225.3z"/>
<path class="st42" d="M39.3,226.6c0-1.1,0.3-1.9,0.9-2.6c0.6-0.7,1.4-1,2.5-1c1.1,0,1.9,0.3,2.5,1c0.6,0.7,0.9,1.6,0.9,2.6v0.1
c0,1.1-0.3,2-0.9,2.6c-0.6,0.7-1.4,1-2.5,1c-1.1,0-1.9-0.3-2.5-1c-0.6-0.7-0.9-1.6-0.9-2.6V226.6z M41.3,226.8
c0,0.7,0.1,1.2,0.3,1.6c0.2,0.4,0.6,0.6,1.1,0.6c0.5,0,0.9-0.2,1.1-0.6s0.3-0.9,0.3-1.6v-0.1c0-0.6-0.1-1.2-0.4-1.6
c-0.2-0.4-0.6-0.6-1.1-0.6c-0.5,0-0.9,0.2-1.1,0.6c-0.2,0.4-0.3,0.9-0.3,1.6V226.8z"/>
<path class="st42" d="M51.6,229.4c-0.2,0.3-0.5,0.6-0.8,0.8c-0.3,0.2-0.7,0.3-1.1,0.3c-0.9,0-1.6-0.3-2.1-1s-0.7-1.5-0.7-2.6v-0.1
c0-1.1,0.2-2,0.7-2.7c0.5-0.7,1.2-1,2.1-1c0.4,0,0.7,0.1,1,0.2c0.3,0.2,0.5,0.4,0.8,0.7v-2.6l-1-0.2v-1.2h1h1.9v9l0.9,0.2v1.2
h-2.6L51.6,229.4z M48.9,226.9c0,0.6,0.1,1.1,0.3,1.5s0.6,0.5,1,0.5c0.3,0,0.5-0.1,0.7-0.2s0.4-0.3,0.5-0.5v-3
c-0.1-0.2-0.3-0.4-0.5-0.5c-0.2-0.1-0.4-0.2-0.7-0.2c-0.5,0-0.8,0.2-1,0.6s-0.3,1-0.3,1.6V226.9z"/>
<path class="st42" d="M58.4,229.1l1.6-0.2v-6.5h-1.7v-1.1l3.6-0.7v8.3l1.6,0.2v1.2h-5.2V229.1z"/>
</g>
<g>
<path class="st42" d="M280.3,220.6c1.1,0,2,0.3,2.6,0.9s1,1.3,1,2.2c0,0.9-0.3,1.7-1,2.2c-0.6,0.6-1.5,0.8-2.6,0.8h-1.6v2.1l1,0.2
v1.2h-4v-1.2l1-0.2V222l-1-0.2v-1.2h1H280.3z M278.7,225.3h1.6c0.5,0,0.9-0.1,1.2-0.4c0.3-0.3,0.4-0.7,0.4-1.1
c0-0.5-0.1-0.8-0.4-1.2c-0.3-0.3-0.7-0.5-1.2-0.5h-1.6V225.3z"/>
<path class="st42" d="M284.5,226.6c0-1.1,0.3-1.9,0.9-2.6c0.6-0.7,1.4-1,2.5-1c1.1,0,1.9,0.3,2.5,1c0.6,0.7,0.9,1.6,0.9,2.6v0.1
c0,1.1-0.3,2-0.9,2.6c-0.6,0.7-1.4,1-2.5,1c-1.1,0-1.9-0.3-2.5-1c-0.6-0.7-0.9-1.6-0.9-2.6V226.6z M286.4,226.8
c0,0.7,0.1,1.2,0.3,1.6c0.2,0.4,0.6,0.6,1.1,0.6c0.5,0,0.9-0.2,1.1-0.6s0.3-0.9,0.3-1.6v-0.1c0-0.6-0.1-1.2-0.4-1.6
c-0.2-0.4-0.6-0.6-1.1-0.6c-0.5,0-0.9,0.2-1.1,0.6c-0.2,0.4-0.3,0.9-0.3,1.6V226.8z"/>
<path class="st42" d="M296.8,229.4c-0.2,0.3-0.5,0.6-0.8,0.8c-0.3,0.2-0.7,0.3-1.1,0.3c-0.9,0-1.6-0.3-2.1-1s-0.7-1.5-0.7-2.6
v-0.1c0-1.1,0.2-2,0.7-2.7c0.5-0.7,1.2-1,2.1-1c0.4,0,0.7,0.1,1,0.2c0.3,0.2,0.5,0.4,0.8,0.7v-2.6l-1-0.2v-1.2h1h1.9v9l0.9,0.2
v1.2h-2.6L296.8,229.4z M294.1,226.9c0,0.6,0.1,1.1,0.3,1.5s0.6,0.5,1,0.5c0.3,0,0.5-0.1,0.7-0.2s0.4-0.3,0.5-0.5v-3
c-0.1-0.2-0.3-0.4-0.5-0.5c-0.2-0.1-0.4-0.2-0.7-0.2c-0.5,0-0.8,0.2-1,0.6s-0.3,1-0.3,1.6V226.9z"/>
<path class="st42" d="M305.6,224.6h1.1c0.5,0,0.8-0.1,1-0.4s0.3-0.6,0.3-1c0-0.4-0.1-0.7-0.3-0.9c-0.2-0.2-0.5-0.4-1-0.4
c-0.4,0-0.7,0.1-0.9,0.3c-0.2,0.2-0.4,0.5-0.4,0.8h-1.9l0,0c0-0.8,0.3-1.4,0.9-1.9c0.6-0.5,1.4-0.7,2.3-0.7c1,0,1.8,0.2,2.4,0.7
c0.6,0.5,0.9,1.2,0.9,2c0,0.4-0.1,0.8-0.4,1.2s-0.6,0.7-1.1,0.9c0.5,0.2,0.9,0.5,1.2,0.9s0.4,0.9,0.4,1.4c0,0.9-0.3,1.6-1,2.1
c-0.6,0.5-1.5,0.8-2.5,0.8c-0.9,0-1.7-0.2-2.3-0.7c-0.6-0.5-1-1.1-0.9-2l0,0h1.9c0,0.4,0.1,0.7,0.4,0.9s0.6,0.4,1,0.4
c0.4,0,0.8-0.1,1.1-0.4c0.3-0.2,0.4-0.6,0.4-1c0-0.5-0.1-0.9-0.4-1.1c-0.3-0.2-0.6-0.4-1.1-0.4h-1.1V224.6z"/>
</g>
<g>
<path class="st42" d="M440.2,220.6c1.1,0,2,0.3,2.6,0.9s1,1.3,1,2.2c0,0.9-0.3,1.7-1,2.2c-0.6,0.6-1.5,0.8-2.6,0.8h-1.6v2.1l1,0.2
v1.2h-4v-1.2l1-0.2V222l-1-0.2v-1.2h1H440.2z M438.6,225.3h1.6c0.5,0,0.9-0.1,1.2-0.4c0.3-0.3,0.4-0.7,0.4-1.1
c0-0.5-0.1-0.8-0.4-1.2c-0.3-0.3-0.7-0.5-1.2-0.5h-1.6V225.3z"/>
<path class="st42" d="M444.4,226.6c0-1.1,0.3-1.9,0.9-2.6c0.6-0.7,1.4-1,2.5-1c1.1,0,1.9,0.3,2.5,1c0.6,0.7,0.9,1.6,0.9,2.6v0.1
c0,1.1-0.3,2-0.9,2.6c-0.6,0.7-1.4,1-2.5,1c-1.1,0-1.9-0.3-2.5-1c-0.6-0.7-0.9-1.6-0.9-2.6V226.6z M446.3,226.8
c0,0.7,0.1,1.2,0.3,1.6c0.2,0.4,0.6,0.6,1.1,0.6c0.5,0,0.9-0.2,1.1-0.6s0.3-0.9,0.3-1.6v-0.1c0-0.6-0.1-1.2-0.4-1.6
c-0.2-0.4-0.6-0.6-1.1-0.6c-0.5,0-0.9,0.2-1.1,0.6c-0.2,0.4-0.3,0.9-0.3,1.6V226.8z"/>
<path class="st42" d="M456.7,229.4c-0.2,0.3-0.5,0.6-0.8,0.8c-0.3,0.2-0.7,0.3-1.1,0.3c-0.9,0-1.6-0.3-2.1-1s-0.7-1.5-0.7-2.6
v-0.1c0-1.1,0.2-2,0.7-2.7c0.5-0.7,1.2-1,2.1-1c0.4,0,0.7,0.1,1,0.2c0.3,0.2,0.5,0.4,0.8,0.7v-2.6l-1-0.2v-1.2h1h1.9v9l0.9,0.2
v1.2h-2.6L456.7,229.4z M454,226.9c0,0.6,0.1,1.1,0.3,1.5s0.6,0.5,1,0.5c0.3,0,0.5-0.1,0.7-0.2s0.4-0.3,0.5-0.5v-3
c-0.1-0.2-0.3-0.4-0.5-0.5c-0.2-0.1-0.4-0.2-0.7-0.2c-0.5,0-0.8,0.2-1,0.6s-0.3,1-0.3,1.6V226.9z"/>
<path class="st42" d="M469.2,226.7h1.1v1.3h-1.1v0.9l1,0.2v1.2h-4v-1.2l1-0.2V228h-3.9l-0.1-0.9l4-6.4h2V226.7z M465,226.7h2.2
v-3.5l0,0l-0.2,0.3L465,226.7z"/>
</g>
<g>
<path class="st42" d="M560.2,131.7c0.4,0,0.7-0.1,1-0.4s0.4-0.5,0.4-0.9h1l0,0c0,0.5-0.2,1-0.7,1.5s-1.1,0.6-1.8,0.6
c-0.9,0-1.6-0.3-2.1-0.9s-0.7-1.4-0.7-2.3v-0.2c0-0.9,0.2-1.7,0.7-2.3s1.2-0.9,2.1-0.9c0.5,0,1,0.1,1.4,0.3s0.7,0.4,1,0.7l0.1,1.4
h-0.9l-0.3-1c-0.1-0.1-0.3-0.2-0.5-0.3s-0.5-0.1-0.7-0.1c-0.6,0-1,0.2-1.3,0.7s-0.4,1-0.4,1.6v0.2c0,0.6,0.1,1.2,0.4,1.6
S559.6,131.7,560.2,131.7z"/>
<path class="st42" d="M563.8,129.2c0-0.9,0.3-1.7,0.8-2.3s1.2-0.9,2.1-0.9c0.9,0,1.6,0.3,2.1,0.9s0.8,1.4,0.8,2.3v0.1
c0,0.9-0.3,1.7-0.8,2.3s-1.2,0.9-2.1,0.9c-0.9,0-1.6-0.3-2.1-0.9s-0.8-1.4-0.8-2.3V129.2z M565,129.3c0,0.7,0.1,1.2,0.4,1.7
s0.7,0.7,1.3,0.7c0.5,0,1-0.2,1.2-0.7s0.4-1,0.4-1.7v-0.1c0-0.7-0.1-1.2-0.4-1.7s-0.7-0.7-1.3-0.7s-1,0.2-1.3,0.7s-0.4,1-0.4,1.7
V129.3z"/>
<path class="st42" d="M570.4,131.7l1-0.2V127l-1-0.2v-0.7h2l0.1,0.9c0.2-0.3,0.5-0.6,0.8-0.8s0.7-0.3,1.1-0.3
c0.7,0,1.2,0.2,1.6,0.6s0.6,1,0.6,1.9v3.1l1,0.2v0.7h-3.1v-0.7l1-0.2v-3.1c0-0.6-0.1-1-0.3-1.2s-0.6-0.4-1-0.4
c-0.3,0-0.6,0.1-0.9,0.2s-0.5,0.4-0.6,0.7v3.7l1,0.2v0.7h-3.1V131.7z"/>
<path class="st42" d="M580.3,124.6v1.5h1.2v0.9h-1.2v3.8c0,0.3,0.1,0.5,0.2,0.6s0.3,0.2,0.5,0.2c0.1,0,0.2,0,0.3,0s0.2,0,0.3-0.1
l0.2,0.8c-0.1,0.1-0.3,0.1-0.5,0.2s-0.4,0.1-0.6,0.1c-0.5,0-0.8-0.1-1.1-0.4s-0.4-0.7-0.4-1.3v-3.8h-1v-0.9h1v-1.5H580.3z"/>
<path class="st42" d="M586.8,132.4c0-0.2-0.1-0.3-0.1-0.5s0-0.3,0-0.4c-0.2,0.3-0.5,0.5-0.8,0.7s-0.7,0.3-1.1,0.3
c-0.7,0-1.2-0.2-1.5-0.5s-0.5-0.8-0.5-1.4c0-0.6,0.2-1.1,0.7-1.4s1.2-0.5,2-0.5h1.2v-0.7c0-0.4-0.1-0.7-0.4-0.9s-0.6-0.3-1-0.3
c-0.3,0-0.5,0-0.8,0.1s-0.4,0.2-0.5,0.3l-0.1,0.7H583v-1.2c0.3-0.2,0.6-0.4,1-0.6s0.9-0.2,1.3-0.2c0.7,0,1.3,0.2,1.7,0.6
s0.7,0.9,0.7,1.6v3.1c0,0.1,0,0.2,0,0.2s0,0.2,0,0.2l0.5,0.1v0.7H586.8z M585,131.6c0.4,0,0.7-0.1,1-0.3s0.5-0.4,0.7-0.7v-1h-1.2
c-0.5,0-0.8,0.1-1.1,0.3s-0.4,0.5-0.4,0.8c0,0.3,0.1,0.5,0.3,0.6S584.6,131.6,585,131.6z"/>
<path class="st42" d="M589.3,131.7l1-0.2V127l-1-0.2v-0.7h2.1v5.4l1,0.2v0.7h-3.1V131.7z M591.4,124.5h-1.2v-1.2h1.2V124.5z"/>
<path class="st42" d="M593.1,131.7l1-0.2V127l-1-0.2v-0.7h2l0.1,0.9c0.2-0.3,0.5-0.6,0.8-0.8s0.7-0.3,1.1-0.3
c0.7,0,1.2,0.2,1.6,0.6s0.6,1,0.6,1.9v3.1l1,0.2v0.7H597v-0.7l1-0.2v-3.1c0-0.6-0.1-1-0.3-1.2s-0.6-0.4-1-0.4
c-0.3,0-0.6,0.1-0.9,0.2s-0.5,0.4-0.6,0.7v3.7l1,0.2v0.7h-3.1V131.7z"/>
<path class="st42" d="M603.8,132.6c-0.9,0-1.6-0.3-2.1-0.9s-0.8-1.4-0.8-2.3v-0.3c0-0.9,0.3-1.7,0.8-2.3s1.2-0.9,1.9-0.9
c0.9,0,1.5,0.3,1.9,0.8s0.7,1.2,0.7,2.1v0.7h-4.1l0,0c0,0.6,0.2,1.1,0.5,1.5s0.7,0.6,1.2,0.6c0.4,0,0.7-0.1,1-0.2s0.5-0.3,0.8-0.5
l0.5,0.8c-0.2,0.2-0.5,0.4-0.9,0.6S604.3,132.6,603.8,132.6z M603.6,126.9c-0.4,0-0.7,0.2-1,0.5s-0.4,0.7-0.5,1.2l0,0h2.9v-0.2
c0-0.5-0.1-0.8-0.4-1.1S604.1,126.9,603.6,126.9z"/>
<path class="st42" d="M607.3,126.8v-0.7h2l0.1,0.9c0.2-0.3,0.4-0.6,0.7-0.8s0.6-0.3,0.9-0.3c0.1,0,0.2,0,0.3,0s0.2,0,0.2,0
l-0.2,1.1l-0.7,0c-0.3,0-0.6,0.1-0.8,0.2s-0.4,0.3-0.5,0.6v3.6l1,0.2v0.7h-3.1v-0.7l1-0.2V127L607.3,126.8z"/>
<path class="st42" d="M612.3,131.7l1-0.2V127l-1-0.2v-0.7h2.1v5.4l1,0.2v0.7h-3.1V131.7z M614.4,124.5h-1.2v-1.2h1.2V124.5z"/>
<path class="st42" d="M617.8,131.5h2.6l0.1-1h1v1.9h-5v-0.8l3.4-4.6h-2.3l-0.1,1h-1v-1.9h4.8v0.8L617.8,131.5z"/>
<path class="st42" d="M625.4,132.6c-0.9,0-1.6-0.3-2.1-0.9s-0.8-1.4-0.8-2.3v-0.3c0-0.9,0.3-1.7,0.8-2.3s1.2-0.9,1.9-0.9
c0.9,0,1.5,0.3,1.9,0.8s0.7,1.2,0.7,2.1v0.7h-4.1l0,0c0,0.6,0.2,1.1,0.5,1.5s0.7,0.6,1.2,0.6c0.4,0,0.7-0.1,1-0.2s0.5-0.3,0.8-0.5
l0.5,0.8c-0.2,0.2-0.5,0.4-0.9,0.6S625.9,132.6,625.4,132.6z M625.2,126.9c-0.4,0-0.7,0.2-1,0.5s-0.4,0.7-0.5,1.2l0,0h2.9v-0.2
c0-0.5-0.1-0.8-0.4-1.1S625.7,126.9,625.2,126.9z"/>
<path class="st42" d="M633.2,131.7c-0.2,0.3-0.5,0.5-0.8,0.7s-0.6,0.2-1,0.2c-0.8,0-1.4-0.3-1.8-0.8s-0.7-1.3-0.7-2.2v-0.1
c0-1,0.2-1.8,0.7-2.5s1-0.9,1.8-0.9c0.4,0,0.7,0.1,1,0.2s0.5,0.3,0.7,0.6v-2.6l-1-0.2v-0.7h1h1.2v8.2l1,0.2v0.7h-2L633.2,131.7z
M630.1,129.5c0,0.6,0.1,1.1,0.4,1.5s0.7,0.6,1.2,0.6c0.3,0,0.6-0.1,0.9-0.2s0.4-0.4,0.6-0.7v-2.9c-0.1-0.3-0.3-0.5-0.6-0.6
s-0.5-0.2-0.9-0.2c-0.6,0-1,0.2-1.2,0.7s-0.4,1.1-0.4,1.8V129.5z"/>
<path class="st42" d="M643.3,132.4c0-0.2-0.1-0.3-0.1-0.5s0-0.3,0-0.4c-0.2,0.3-0.5,0.5-0.8,0.7s-0.7,0.3-1.1,0.3
c-0.7,0-1.2-0.2-1.5-0.5s-0.5-0.8-0.5-1.4c0-0.6,0.2-1.1,0.7-1.4s1.2-0.5,2-0.5h1.2v-0.7c0-0.4-0.1-0.7-0.4-0.9s-0.6-0.3-1-0.3
c-0.3,0-0.5,0-0.8,0.1s-0.4,0.2-0.5,0.3l-0.1,0.7h-0.9v-1.2c0.3-0.2,0.6-0.4,1-0.6s0.9-0.2,1.3-0.2c0.7,0,1.3,0.2,1.7,0.6
s0.7,0.9,0.7,1.6v3.1c0,0.1,0,0.2,0,0.2s0,0.2,0,0.2l0.5,0.1v0.7H643.3z M641.4,131.6c0.4,0,0.7-0.1,1-0.3s0.5-0.4,0.7-0.7v-1
h-1.2c-0.5,0-0.8,0.1-1.1,0.3s-0.4,0.5-0.4,0.8c0,0.3,0.1,0.5,0.3,0.6S641.1,131.6,641.4,131.6z"/>
<path class="st42" d="M645.6,134.1l1-0.2v-7l-1-0.2v-0.7h1.9l0.1,0.8c0.2-0.3,0.5-0.5,0.8-0.7s0.7-0.2,1.1-0.2
c0.8,0,1.4,0.3,1.8,0.9s0.7,1.4,0.7,2.5v0.1c0,0.9-0.2,1.7-0.7,2.2s-1,0.8-1.8,0.8c-0.4,0-0.7-0.1-1-0.2s-0.5-0.3-0.8-0.6v2.2
l1,0.2v0.7h-3.1V134.1z M650.8,129.4c0-0.7-0.1-1.3-0.4-1.8s-0.7-0.7-1.3-0.7c-0.3,0-0.6,0.1-0.8,0.2s-0.4,0.4-0.6,0.6v3.1
c0.1,0.3,0.3,0.5,0.6,0.6s0.5,0.2,0.9,0.2c0.5,0,1-0.2,1.2-0.6s0.4-0.9,0.4-1.6V129.4z"/>
<path class="st42" d="M652.9,134.1l1-0.2v-7l-1-0.2v-0.7h1.9l0.1,0.8c0.2-0.3,0.5-0.5,0.8-0.7s0.7-0.2,1.1-0.2
c0.8,0,1.4,0.3,1.8,0.9s0.7,1.4,0.7,2.5v0.1c0,0.9-0.2,1.7-0.7,2.2s-1,0.8-1.8,0.8c-0.4,0-0.7-0.1-1-0.2s-0.5-0.3-0.8-0.6v2.2
l1,0.2v0.7h-3.1V134.1z M658.1,129.4c0-0.7-0.1-1.3-0.4-1.8s-0.7-0.7-1.3-0.7c-0.3,0-0.6,0.1-0.8,0.2s-0.4,0.4-0.6,0.6v3.1
c0.1,0.3,0.3,0.5,0.6,0.6s0.5,0.2,0.9,0.2c0.5,0,1-0.2,1.2-0.6s0.4-0.9,0.4-1.6V129.4z"/>
</g>
<line class="st61" x1="554.8" y1="130" x2="481.7" y2="130"/>
<g>
<path class="st42" d="M559.5,106.8l-0.8,0.1l1.3,3.6l0.1,0.5h0l0.1-0.5l1.3-3.6l-0.8-0.1V106h2.4v0.7l-0.5,0.1l-2.1,5.5h-0.9
l-2.2-5.5l-0.5-0.1V106h2.4V106.8z"/>
<path class="st42" d="M564,109.1c0-0.9,0.3-1.7,0.8-2.3s1.2-0.9,2.1-0.9c0.9,0,1.6,0.3,2.1,0.9s0.8,1.4,0.8,2.3v0.1
c0,0.9-0.3,1.7-0.8,2.3s-1.2,0.9-2.1,0.9c-0.9,0-1.6-0.3-2.1-0.9s-0.8-1.4-0.8-2.3V109.1z M565.1,109.3c0,0.7,0.1,1.2,0.4,1.7
s0.7,0.7,1.3,0.7c0.5,0,1-0.2,1.2-0.7s0.4-1,0.4-1.7v-0.1c0-0.7-0.1-1.2-0.4-1.7s-0.7-0.7-1.3-0.7s-1,0.2-1.3,0.7s-0.4,1-0.4,1.7
V109.3z"/>
<path class="st42" d="M570.4,104v-0.7h2.1v8.2l1,0.2v0.7h-3.1v-0.7l1-0.2v-7.3L570.4,104z"/>
<path class="st42" d="M578.9,111.4c-0.2,0.3-0.5,0.6-0.8,0.8s-0.7,0.3-1.1,0.3c-0.7,0-1.2-0.2-1.6-0.7s-0.6-1.1-0.6-2.1v-2.8
l-0.7-0.2V106h0.7h1.2v3.8c0,0.7,0.1,1.1,0.3,1.4s0.5,0.4,0.9,0.4c0.4,0,0.7-0.1,1-0.2s0.5-0.4,0.6-0.7v-3.7l-0.8-0.2V106h0.8h1.2
v5.4l0.7,0.2v0.7H579L578.9,111.4z"/>
<path class="st42" d="M581.4,111.6l1-0.2v-4.5l-1-0.2V106h2l0.1,0.8c0.2-0.3,0.5-0.5,0.8-0.7s0.7-0.2,1.1-0.2s0.8,0.1,1.1,0.3
s0.5,0.5,0.7,0.9c0.2-0.4,0.5-0.6,0.8-0.9s0.7-0.3,1.1-0.3c0.6,0,1.2,0.2,1.5,0.7s0.6,1.1,0.6,2v2.9l1,0.2v0.7h-3.1v-0.7l1-0.2
v-2.9c0-0.6-0.1-1.1-0.3-1.3s-0.5-0.4-1-0.4c-0.4,0-0.7,0.1-1,0.4s-0.4,0.6-0.4,1.1v3.1l1,0.2v0.7h-3.1v-0.7l1-0.2v-2.9
c0-0.6-0.1-1-0.3-1.3s-0.5-0.4-1-0.4c-0.4,0-0.6,0.1-0.9,0.2s-0.4,0.3-0.5,0.6v3.8l1,0.2v0.7h-3.1V111.6z"/>
<path class="st42" d="M595.8,112.5c-0.9,0-1.6-0.3-2.1-0.9s-0.8-1.4-0.8-2.3v-0.3c0-0.9,0.3-1.7,0.8-2.3s1.2-0.9,1.9-0.9
c0.9,0,1.5,0.3,1.9,0.8s0.7,1.2,0.7,2.1v0.7h-4.1l0,0c0,0.6,0.2,1.1,0.5,1.5s0.7,0.6,1.2,0.6c0.4,0,0.7-0.1,1-0.2s0.5-0.3,0.8-0.5
l0.5,0.8c-0.2,0.2-0.5,0.4-0.9,0.6S596.3,112.5,595.8,112.5z M595.6,106.8c-0.4,0-0.7,0.2-1,0.5s-0.4,0.7-0.5,1.2l0,0h2.9v-0.2
c0-0.5-0.1-0.8-0.4-1.1S596.1,106.8,595.6,106.8z"/>
</g>
<line class="st61" x1="554.8" y1="110" x2="468.4" y2="110"/>
<g>
<path class="st42" d="M557.2,46.7V46h3.1v0.7l-1,0.2v6.7l1,0.2v0.7h-3.1v-0.7l1-0.2v-6.7L557.2,46.7z"/>
<path class="st42" d="M565,46c0.9,0,1.6,0.2,2.1,0.7s0.8,1.1,0.8,1.9c0,0.8-0.3,1.4-0.8,1.9s-1.2,0.7-2.1,0.7h-1.8v2.5l1,0.2v0.7
h-3.1v-0.7l1-0.2v-6.7l-1-0.2V46h1H565z M563.2,50.2h1.8c0.6,0,1-0.2,1.3-0.5s0.4-0.7,0.4-1.2s-0.1-0.9-0.4-1.2s-0.7-0.5-1.3-0.5
h-1.8V50.2z"/>
<path class="st42" d="M576,54.5c0-0.2-0.1-0.3-0.1-0.5s0-0.3,0-0.4c-0.2,0.3-0.5,0.5-0.8,0.7s-0.7,0.3-1.1,0.3
c-0.7,0-1.2-0.2-1.5-0.5s-0.5-0.8-0.5-1.4c0-0.6,0.2-1.1,0.7-1.4s1.2-0.5,2-0.5h1.2v-0.7c0-0.4-0.1-0.7-0.4-0.9s-0.6-0.3-1-0.3
c-0.3,0-0.5,0-0.8,0.1s-0.4,0.2-0.5,0.3l-0.1,0.7h-0.9v-1.2c0.3-0.2,0.6-0.4,1-0.6s0.9-0.2,1.3-0.2c0.7,0,1.3,0.2,1.7,0.6
s0.7,0.9,0.7,1.6v3.1c0,0.1,0,0.2,0,0.2s0,0.2,0,0.2l0.5,0.1v0.7H576z M574.1,53.6c0.4,0,0.7-0.1,1-0.3s0.5-0.4,0.7-0.7v-1h-1.2
c-0.5,0-0.8,0.1-1.1,0.3s-0.4,0.5-0.4,0.8c0,0.3,0.1,0.5,0.3,0.6S573.8,53.6,574.1,53.6z"/>
<path class="st42" d="M582.7,53.7c-0.2,0.3-0.5,0.5-0.8,0.7s-0.6,0.2-1,0.2c-0.8,0-1.4-0.3-1.8-0.8s-0.7-1.3-0.7-2.2v-0.1
c0-1,0.2-1.8,0.7-2.5s1-0.9,1.8-0.9c0.4,0,0.7,0.1,1,0.2s0.5,0.3,0.7,0.6v-2.6l-1-0.2v-0.7h1h1.2v8.2l1,0.2v0.7h-2L582.7,53.7z
M579.6,51.6c0,0.6,0.1,1.1,0.4,1.5s0.7,0.6,1.2,0.6c0.3,0,0.6-0.1,0.9-0.2s0.4-0.4,0.6-0.7v-2.9c-0.1-0.3-0.3-0.5-0.6-0.6
s-0.5-0.2-0.9-0.2c-0.6,0-1,0.2-1.2,0.7s-0.4,1.1-0.4,1.8V51.6z"/>
<path class="st42" d="M589.9,53.7c-0.2,0.3-0.5,0.5-0.8,0.7s-0.6,0.2-1,0.2c-0.8,0-1.4-0.3-1.8-0.8s-0.7-1.3-0.7-2.2v-0.1
c0-1,0.2-1.8,0.7-2.5s1-0.9,1.8-0.9c0.4,0,0.7,0.1,1,0.2s0.5,0.3,0.7,0.6v-2.6l-1-0.2v-0.7h1h1.2v8.2l1,0.2v0.7h-2L589.9,53.7z
M586.8,51.6c0,0.6,0.1,1.1,0.4,1.5s0.7,0.6,1.2,0.6c0.3,0,0.6-0.1,0.9-0.2s0.4-0.4,0.6-0.7v-2.9c-0.1-0.3-0.3-0.5-0.6-0.6
s-0.5-0.2-0.9-0.2c-0.6,0-1,0.2-1.2,0.7s-0.4,1.1-0.4,1.8V51.6z"/>
<path class="st42" d="M592.9,48.9v-0.7h2l0.1,0.9c0.2-0.3,0.4-0.6,0.7-0.8s0.6-0.3,0.9-0.3c0.1,0,0.2,0,0.3,0s0.2,0,0.2,0
l-0.2,1.1l-0.7,0c-0.3,0-0.6,0.1-0.8,0.2s-0.4,0.3-0.5,0.6v3.6l1,0.2v0.7h-3.1v-0.7l1-0.2v-4.5L592.9,48.9z"/>
<path class="st42" d="M600.6,54.6c-0.9,0-1.6-0.3-2.1-0.9s-0.8-1.4-0.8-2.3v-0.3c0-0.9,0.3-1.7,0.8-2.3s1.2-0.9,1.9-0.9
c0.9,0,1.5,0.3,1.9,0.8s0.7,1.2,0.7,2.1v0.7h-4.1l0,0c0,0.6,0.2,1.1,0.5,1.5s0.7,0.6,1.2,0.6c0.4,0,0.7-0.1,1-0.2s0.5-0.3,0.8-0.5
l0.5,0.8c-0.2,0.2-0.5,0.4-0.9,0.6S601.1,54.6,600.6,54.6z M600.4,48.9c-0.4,0-0.7,0.2-1,0.5s-0.4,0.7-0.5,1.2l0,0h2.9v-0.2
c0-0.5-0.1-0.8-0.4-1.1S600.9,48.9,600.4,48.9z"/>
<path class="st42" d="M609,50.1h-0.9l-0.2-0.8c-0.1-0.1-0.3-0.2-0.5-0.3s-0.5-0.1-0.7-0.1c-0.4,0-0.7,0.1-0.9,0.3
s-0.3,0.4-0.3,0.7c0,0.2,0.1,0.4,0.3,0.6s0.5,0.3,1.1,0.4c0.8,0.2,1.4,0.4,1.8,0.7s0.6,0.7,0.6,1.2c0,0.6-0.2,1-0.7,1.4
s-1,0.5-1.8,0.5c-0.5,0-0.9-0.1-1.3-0.2s-0.7-0.3-1-0.5l0-1.4h0.9l0.2,0.8c0.1,0.1,0.3,0.2,0.5,0.3s0.5,0.1,0.7,0.1
c0.4,0,0.7-0.1,1-0.2s0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.6s-0.6-0.3-1.1-0.4c-0.8-0.2-1.3-0.4-1.7-0.7s-0.6-0.7-0.6-1.2
c0-0.5,0.2-1,0.7-1.3s1-0.5,1.7-0.5c0.5,0,0.9,0.1,1.3,0.2s0.7,0.3,1,0.5L609,50.1z"/>
<path class="st42" d="M615.1,50.1h-0.9l-0.2-0.8c-0.1-0.1-0.3-0.2-0.5-0.3s-0.5-0.1-0.7-0.1c-0.4,0-0.7,0.1-0.9,0.3
s-0.3,0.4-0.3,0.7c0,0.2,0.1,0.4,0.3,0.6s0.5,0.3,1.1,0.4c0.8,0.2,1.4,0.4,1.8,0.7s0.6,0.7,0.6,1.2c0,0.6-0.2,1-0.7,1.4
s-1,0.5-1.8,0.5c-0.5,0-0.9-0.1-1.3-0.2s-0.7-0.3-1-0.5l0-1.4h0.9l0.2,0.8c0.1,0.1,0.3,0.2,0.5,0.3s0.5,0.1,0.7,0.1
c0.4,0,0.7-0.1,1-0.2s0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.6s-0.6-0.3-1.1-0.4c-0.8-0.2-1.3-0.4-1.7-0.7s-0.6-0.7-0.6-1.2
c0-0.5,0.2-1,0.7-1.3s1-0.5,1.7-0.5c0.5,0,0.9,0.1,1.3,0.2s0.7,0.3,1,0.5L615.1,50.1z"/>
</g>
<line class="st61" x1="554.8" y1="52.1" x2="440.6" y2="52.1"/>
</g>
<g id="Layer_14">
</g>
</svg>

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB