Оглавление
Как работает виртуальная машина?
Загрузка кода приложения на сервер
Виртуальный хостинг
на одном сервере находится много разных подобных проектов, для каждого из них отведено свое рабочее пространство. При этом у всех проектов общие ресурсы: процессор и оперативная память. Все проекты делят их между собой. Это достаточно безопасно и позволяет провайдеру изолировать данные пользователей друг от друга, но можно сказать, что пользователи хостинга конкурируют друг с другом за ресурсы. Такой хостинг — самый дешевый способ публикации приложения, но в то же время очень ограниченный. В нём нет никакой возможности настраивать операционную систему под себя, устанавливать необходимые программы. Есть только те программы, которые предоставляет хостинг.
Выделенный сервер
настоящий «железный» компьютер, который находится в стойке в дата-центре. К нему предоставляется полный администраторский доступ, поэтому можно устанавливать всё, что угодно. Самый дорогой способ публикации приложения.
Виртуальная машина (VPS)
предоставляется такая же операционная система, как в случае выделенного сервера, и полный администраторский доступ. То есть по факту это такой же независимый компьютер. Отличие лишь в том, что в данном случае на одном «железном» сервере размещается сразу несколько таких виртуальных «компьютеров».
Как работает виртуальная машина?
На «железном» сервере устанавливается специальное ПО — гипервизор.
Гипервизор
это программа, которая управляет физическими ресурсами вычислительной машины и распределяет эти ресурсы между несколькими различными операционными системами, позволяя запускать их одновременно. Гипервизор изолирует запущенные ОС (виртуальные машины) друг от друга так, чтобы каждая из них монопольно использовала выделенные ей ресурсы. Таким образом, виртуальные машины не могут влиять друг на друга, поэтому мы можем не беспокоиться за безопасность наших данных. Существует два типа гипервизоров: программные и аппаратные. Программные гипервизоры используют ОС «железного» сервера для разделения ресурсов. Аппаратные взаимодействуют с ресурсами напрямую.
Управление сервером
Для того чтобы управлять сервером (виртуальной машиной), нам нужно к ней подключиться. Для этого существует протокол SSH — сетевой протокол прикладного уровня, позволяющий производить удаленное управление операционной системой и передавать информацию. SSH расшифровывается как Secure Shell, т. е. безопасная оболочка.
SSH использует клиент-серверную модель. Это значит, что для подключения к виртуальной машине на ней должна быть запущена специальная программа, которая работает постоянно. Называется она sshd (OpenSSH Daemon) — программа демон для ssh. К счастью, эта программа по умолчанию установлена на всех операционных системах Linux, которыми мы с вами будем пользоваться.
Работает SSH поверх стека TCP/IP. Для подключения к машине нам потребуется ее IP-адрес, который должен быть публичным (не адресом внутри локальной сети).
Все данные, которые проходят по SSH-протоколу, шифруются, поэтому злоумышленник, получивший доступ к какому-либо узлу сети между нами и виртуальной машиной, не сможет расшифровать команды и данные, которые мы отправляем на эту машину. Для работы по протоколу SSH используется одноименная команда, которая доступна на всех ОС Linux, Mac OS и Windows (начиная с 10-й версии).
К серверам можно подключаться двумя способами: 🎯 Через логин и пароль пользователя на сервере. 🎯 **Без пароля,** через специальные ключи: **публичный** и **приватный**. Оба генерируются на компьютере пользователя. **Приватный** ключ всегда хранится у пользователя, им нельзя ни с кем делиться. **Публичный** же загружается на все машины, к которым мы хотим подключиться.
В Yandex Cloud при создании машины нельзя указать пароль пользователя. Поэтому подключение возможно только вторым способом. Инструкция по созданию ключей здесь. https://cloud.yandex.ru/docs/managed-kubernetes/operations/node-connect-ssh#creating-ssh-keys
DNS
DNS используется не только для получения адреса по доменному имени. Существует много типов DNS-записей, вот основные из них:
**А** — адрес веб-ресурса, который соответствует введенному имени домена. Как раз та самая запись, про которую шла речь выше. **MX** — адрес почтового сервера. **CNAME** — указание привязки аналога к собственному доменному имени. Чаще всего используется для прикрепления поддомена. Например, можно привязать веб-адрес [www.site.ru](http://www.site.ru/) к фактическому сайту для домена [site.ru](http://site.ru/). **NS** — адрес DNS-сервера, отвечающего за содержание прочих ресурсных записей. **TXT** — любая текстовая информация о домене. **SPF** — данные с указанием списка серверов, которым позволено отправлять письма от имени указанного домена. **SOA** — исходная запись зоны, в которой указаны сведения о сервере, содержащем образцовую информацию о доменном имени. Благодаря DNS мы можем дать нашей виртуальной машине человекопонятный адрес. Существует проект, который предоставляет DNS-записи бесплатно — [ссылка на него](https://www.freenom.com/ru/index.html?lang=ru).
Как работает DNS?
Настройка сервера
После того как мы подключились через SSH к нашей машине, нам нужно установить все необходимые зависимости, например Python или базу данных PostgreSQL.
Для этого в операционных системах существуют специальные программы, упрощающие установку — пакетные менеджеры (как менеджер pip у Python).
Пакетный менеджер: 🎯 устанавливает/обновляет/удаляет библиотеки и компоненты систем; 🎯 устанавливает зависимости этих компонентов; 🎯 следит за совместимостью пакетов друг с другом.
В разных операционных системах используются разные пакетные менеджеры, например:
Ubuntu/debian: apt
Redhat/CentOS: yum
Alpine: apk
MacOS: brew
Arch Linux: pacman
Windows 10: NuGet
Скрипты могут быть в пакете, если при установке/удалении файлов на машине требуется совершить еще какие-либо действия.
**Состав пакета**
- Метаинформация:
- имя
- версия
- релиз
- архитектура
- зависимости
- **...**
- Файлы
- Скрипты**:**
- pre-install
- post-install
- pre-remove
- post-remove
- ...
APT
В ОС Ubuntu используется пакетный менеджер apt. Вот пример команд:
- обновить БД пакетов:
`apt update`
- установить пакет Python:
`apt install python`
- удалить пакет:
`apt remove python`
- переустановить пакет:
`apt install --reinstall python`
Пример установки Python 3.10
sudo su
add-apt-repository ppa:deadsnakes/ppa
apt install python3.10
Установка БД PostgreSQL
apt install postgresql
# Создание пользователя и базы данных
sudo su postgres
createuser --interactive -P
createdb flask_app --owner flask_app_user
psql -U flask_app_user -h 127.0.0.1 flask_app
Загрузка кода приложения на сервер
Существует огромное количество способов доставки кода приложения на сервер. Мы рассмотрим основные:
🎯 копирование файлов через SSH;
🎯 копирование файлов через Git.
Git
- git push
- подключаемся к серверу
- делаем git pull
SSH
Для копирования файлов через SSH потребуется команда scp:
# Копирование одного файла:
scp test.txt malenko@51.250.22.196:test.txt
# Копирование директории:
scp -r dir/ malenko@51.250.22.196:.
Загрузка приложений в фоне
При запуске операционной системы открываются различные службы, которые необходимы для ее корректной работы. Например, демон для работы с сетью или же демон SSH. Также необходимо примонтировать существующие диски и большое количество других работ. Для этого в ОС есть система инициализации, одна из таких систем — это **systemd**. Она: - запускает процессы при старте системы; - использует cgroups, т. е. изолирует все запущенные процессы; - отслеживает состояние всех процессов; - может перезапускать сервисы в случае их падения; - журналирует события.
Управление происходит через команду systemctl.
Для того чтобы добавить какой-либо сервис в систему, необходимо создать так называемый **Unit** (юнит). Юнитом может быть: - service — демон (программа, работающая в фоне); - device — реагирование на подключение устройства; - target — группировка юнитов; - mount — точка монтирования файловой системы. В физическом представлении юнит — это особый файл, в котором описаны все необходимые настройки. Юниты добавляются: - в /usr/lib/systemd/system, когда программа устанавливается через пакетный менеджер; - /etc/systemd/system, сюда добавляет администратор **(то есть мы).**
Как выглядит юнит-файл?
# Пример юнит-файла для Flask-приложения
[Unit]
Description=Flask-app
After=network.target
[Service]
WorkingDirectory=/opt/app/flask-app/
ExecStart=/opt/app/env/bin/python -m flask run -h 0.0.0.0 -p 80
Environment="APP_SETTINGS=/etc/flask-app/config.py"
Restart=always
[Install]
WantedBy=multi-user.target
Секция Unit (юнит):
- **Description** — описание. - **After** — переременная, показывающая после инициализации каких юнитов надо запуститься (в нашем случае, например, после старта демона, работающего с сетью).
Секция Service:
- **Type** — тип сервиса. - **ExecStart** — команда для запуска. - **Restart** — переременная, показывающая, в каких случаях нужно «переподнять» сервис после его завершения. - **WorkingDirectory** — рабочая директория.
Секция Install:
WantedBy – переременная, показывающая, на каком уровне запуска стартует сервис.
После того, как мы описали свой юнит-файл, необходимо положить его в директорию `/etc/systemd/system`.
Например:
`/etc/systemd/system/flask-api.service`
Дальше, после добавления юнита, необходимо, чтобы systemd подтянул новую конфигурацию, для этого вводим команду
`systemctl daemon-reload`
И после всего «включаем» наш сервис. Для этого пишем в терминале:
systemctl start flask-api # название берется из названия unit-файла