diff --git a/kubernetes/k3s-3xui-pod.md b/kubernetes/k3s-3xui-pod.md new file mode 100644 index 0000000..4812ae5 --- /dev/null +++ b/kubernetes/k3s-3xui-pod.md @@ -0,0 +1,28 @@ +# Установка 3X-UI как под в K3s (Kubernetes) + +3X-UI — это симпатичный веб-интерфейс для управления VPN-серверами, такими как WireGuard, Shadowsocks, Xray, V2Ray +и тому подобное. Он позволяет настраивать и мониторить VPN-соединения и клиентов через браузер. Мы будем запускать +его как контейнер (под) внутри K3s кластера на Orange Pi 5. + +### Создание namespace (не обязательно) + +Для удобства организации рекомендую создать отдельное пространство имён (`namespace`) для 3X-UI. Это как папка для +ресурсов, чтобы они не смешивались с другими приложениями. + +Выполним в терминале: +```bash +sudo kubectl create namespace x-ui +``` + +Проверим, что пространство имён создано: +```bash +kubectl get namespaces +``` + +Увидим x-ui в списке: +```text +NAME STATUS AGE +... ... ... +... ... ... +x-ui Active 6s +``` \ No newline at end of file diff --git a/kubernetes/k3s-shadowsocks-client.md b/kubernetes/k3s-shadowsocks-client.md index b514730..e5d38e6 100644 --- a/kubernetes/k3s-shadowsocks-client.md +++ b/kubernetes/k3s-shadowsocks-client.md @@ -23,8 +23,8 @@ │ └── cclient-shadowsocks--izmir/ # Локация Измир │ ├── config.yaml │ └── deployment.yaml -├── ... -└── ... +├── … +└── … ``` Создаем файл `config.yaml` для первого Shadowsocks-клиента (Москва): @@ -61,7 +61,7 @@ data: - `data:` — данные конфигурации. - `config.json:` — имя файла, в который будет записан конфиг. - `|` — говорит, что дальше будет многострочный текст. - - `{...}` — Собственно JSON-конфигурация нашего Shadowsocks-клиента. + - `{…}` — Собственно JSON-конфигурация нашего Shadowsocks-клиента. - `server` и `server_port` — адрес и порт нашего VPS. - `local_address` и `local_port` — где будет SOCKS5 внутри кластера. - `password` и `method` — пароль и метод шифрования. Метод шифрования `chacha20-ietf-poly1305` -- используется, @@ -150,10 +150,10 @@ sudo k3s kubectl get pods -n kube-system Увидим что-то типа: ```text NAME READY STATUS RESTARTS AGE -... -... +… +… shadowsocks-client-moscow-54d64bf5f4-trb6p 1/1 Running 0 24m -... +… ``` Можно проверь логи: @@ -232,10 +232,10 @@ sudo k3s ctr images ls | grep shadowsocks Увидим что-то типа: ```text -... -docker.io/library/shadowsocks-with-tools:latest application/vnd.oci.image.manifest.v1+json sha256:... 22.5 MiB linux/arm64 io.cri-containerd.image=managed -... -... +… +docker.io/library/shadowsocks-with-tools:latest application/vnd.oci.image.manifest.v1+json sha256:… 22.5 MiB linux/arm64 io.cri-containerd.image=managed +… +… ``` Теперь нам нужно передать образ контейнера на другие ноды кластера. Как это сделать есть заметка "[Развертывание @@ -246,15 +246,15 @@ docker.io/library/shadowsocks-with-tools:latest application/vnd.oci.image.ma новый образ. Закомментируем строку `image: shadowsocks/shadowsocks-libev:latest` и вставим две строки после неё (обратите внимание на заметки): ```yaml -... +… spec: containers: - name: shadowsocks-client # image: shadowsocks/shadowsocks-libev:latest image: shadowsocks-with-tools # Без :latest, чтобы k3s не "ходил" за контейнером в реестр (например, DockerHub) imagePullPolicy: Never # Только локальный образ, не тянуть из реестра - ... -... + … +… ``` Уберём старый под из deployment и удалим сам под из k3s: @@ -276,9 +276,9 @@ sudo k3s kubectl get pods -n kube-system Увидим что-то типа: ```text NAME READY STATUS RESTARTS AGE -... +… shadowsocks-client-moscow-6cf7b956b8-mtsg4 1/1 Running 0 9s -... +… ``` #### Проверка работы Shadowsocks @@ -344,12 +344,12 @@ sudo k3s kubectl logs -n kube-system shadowsocks-client-moscow- Для этого нужно изменить _local_address_ в конфиге shadowsocks-клиента `config.yaml`: ```yaml -... +… "server_port": <ПОРТ>, # "local_address": "127.0.0.1", "local_address": "0.0.0.0", "local_port": 1081, -... +… ``` Применим конфиг: @@ -437,9 +437,9 @@ sudo k3s kubectl get service -n kube-system Увидим что-то типа: ```text NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -... +… ss-moscow-service ClusterIP 10.43.236.81 1081/TCP,1081/UDP 5m5s -... +… ``` Теперь другие поды могут обращаться к `ss-moscow-service.kube-system.svc.cluster.local:1081` как к SOCKS5-прокси. diff --git a/raspberry-and-orange-pi/k3s.md b/raspberry-and-orange-pi/k3s.md index ca829a1..bfad517 100644 --- a/raspberry-and-orange-pi/k3s.md +++ b/raspberry-and-orange-pi/k3s.md @@ -20,7 +20,7 @@ IoT-устройства, edge-серверы и т.п.). Для кластер контейнеры всё равно запускаются runtime’ом (это containerd в k3s). И Docker все равно еще нужен для создания образов, и если при установке k3s не указать `--docker` то k3s будет использовать его как runtime._ -Но, есть у k3s и минус для конкретно моего случая -- распределенная база **etcd**, в которой хранится состояния +Но, есть у k3s и минус для конкретно моего случая — распределенная база **etcd**, в которой хранится состояния кластера, нод и подов, в нем заменена SQLite. Это круто для маленьких компьютеров: экономно по памяти и другим ресурсам, и, что главное, никак не сказывается на производительности (пока узлов меньше 50-80), но означает, что в кластере k3s может быть только одна мастер-нода. Если мастер-нода упадет, её некому будет заменить и весь кластер умрет. @@ -29,7 +29,7 @@ IoT-устройства, edge-серверы и т.п.). Для кластер ### Важное предупреждение -k3s -- это не упрощенная мини-версия Kubernetes, здесь все компоненты упакованы в один бинарник, а значит намного +k3s — это не упрощенная мини-версия Kubernetes, здесь все компоненты упакованы в один бинарник, а значит намного проще не только добавлять узлы, но и удалять их. Так что если что-то пойдет не так с настройкой узла, просто удалите и начните заново. Удаление k3s с узла: ```bash @@ -51,14 +51,14 @@ curl -sfL https://get.k3s.io | sh -s - server --cluster-init --tls-san=192.168.1 ``` Здесь: -* `server` -- значение по умолчанию, устанавливает узел k3s в режиме *мастер* (control-plane). В этом режиме узел +* `server` — значение по умолчанию, устанавливает узел k3s в режиме *мастер* (control-plane). В этом режиме узел будет запускать все компоненты управления Kubernetes: API-сервер, контроллер-менеджер, планировщик (scheduler). - Такой узел отвечает за управление кластером и может также выполнять рабочие нагрузки (workloads), если - не настроены ограничения (taints). Если бы мы указали `agent` -- был бы установлен узел k3s в режиме *воркер*-узла. -* `--cluster-init` -- добавляет поддержку высокой доступности (HA -- High Availability) через встроенный `etcd`. Это + Такой узел отвечает за управление кластером и может также выполнять рабочие нагрузки (workloads), если + не настроены ограничения (taints). Если бы мы указали `agent` — был бы установлен узел k3s в режиме *воркер*-узла. +* `--cluster-init` — добавляет поддержку высокой доступности (HA — High Availability) через встроенный `etcd`. Это значит, что узел инициализирует новый кластер и готов к тому, чтобы другие мастер-узлы могли к нему подключиться (для создания HA-конфигурации). -* `--tls-san=192.168.1.27` -- добавляет IP 192.168.1.27 в сертификаты API-сервера, чтобы другие узлы и клиенты +* `--tls-san=192.168.1.27` — добавляет IP 192.168.1.27 в сертификаты API-сервера, чтобы другие узлы и клиенты могли обращаться к нему по этому адресу. Проверим, что все k3s запущен: @@ -70,9 +70,9 @@ sudo service k3s status ```text ● k3s.service - Lightweight Kubernetes Loaded: loaded (/etc/systemd/system/k3s.service; enabled; vendor preset: enabled) - Active: active (running) since ... -... -... + Active: active (running) since … +… +… ``` Посмотрим сколько нод в кластере: @@ -113,16 +113,16 @@ kube-system traefik-5d45fc8cc9-t5d58 1/1 Running 0 Представлены следующие поды: 1. `coredns` — это DNS-сервер для кластера. Он отвечает за разрешение имен внутри Kubernetes (например, чтобы поды могли обращаться друг к другу по именам сервисов вроде my-service.default.svc.cluster.local). -2. `helm-install-traefik-crd` -- это временный под (Job), который устанавливает Custom Resource Definitions (CRD) +2. `helm-install-traefik-crd` — это временный под (Job), который устанавливает Custom Resource Definitions (CRD) для *Traefik* — ingress-контроллера, встроенного в k3s. CRD нужны для управления ingress-ресурсами (маршрутизацией HTTP/HTTPS). Этот под — одноразовая задача (Job), а не постоянный сервис. Он запустился, выполнил работу (установил CRD) и завершился. Статус "*Completed*" значит, что он больше не работает. -3. `helm-install-traefik` -- ещё один Job, который устанавливает сам Traefik через Helm-чарт. Этот под развернул +3. `helm-install-traefik` — ещё один Job, который устанавливает сам Traefik через Helm-чарт. Этот под развернул основной Traefik-под и завершился. -4. `local-path-provisioner` -- компонент для автоматического создания локальных Persistent Volumes (PV) на узлах. Он +4. `local-path-provisioner` — компонент для автоматического создания локальных Persistent Volumes (PV) на узлах. Он позволяет подам запрашивать хранилище (например, через PersistentVolumeClaim) без сложной настройки NFS или внешних хранилищ. В k3s это встроено для простоты. -5. `metrics-server` -- собирает данные об использовании ресурсов (CPU, память) подов и узлов. Это нужно для команд +5. `metrics-server` — собирает данные об использовании ресурсов (CPU, память) подов и узлов. Это нужно для команд вроде `kubectl top` или для Horizontal Pod Autoscaler (HPA). Установку метрик можно отключить при запуске k3s флагом `--disable=metrics-server`. 6. `svclb-traefik` - это под для балансировки нагрузки (Service Load Balancer) для Traefik. В k3s нет встроенного @@ -131,14 +131,14 @@ kube-system traefik-5d45fc8cc9-t5d58 1/1 Running 0 * один для самой логики балансировки; * другой для мониторинга или дополнительной функциональности (например, *keepalived* или аналога) и это зависит от реализации в k3s. -7. `traefik` -- сам Traefik, ingress-контроллер, который обрабатывает HTTP/HTTPS трафик кластера и маршрутизирует +7. `traefik` — сам Traefik, ingress-контроллер, который обрабатывает HTTP/HTTPS трафик кластера и маршрутизирует его к соответствующим подам (с динамической конфигурацией нашим) и сервисам по правилам Ingress. Traefik в k3s установлен по умолчанию, но его можно отключить при запуске k3s флагом `--disable=traefik` (не будет ни *traefik*, ни *svclb*, ни связанных *Helm Jobs*). Обратите внимание, что, например, под `coredns` получил имя `coredns-ccb96694c-tfjwj`. Имена подов (Pod Names) в Kubernetes генерируются автоматически на основе правил, чтобы каждый под в кластере имел уникальное имя. -Структура имени -- `<имя-приложения>-<хеш-ревизии>-<случайный-суффикс>`. Впрочем, `<хеш-ревизии>` может отсутствовать, +Структура имени — `<имя-приложения>-<хеш-ревизии>-<случайный-суффикс>`. Впрочем, `<хеш-ревизии>` может отсутствовать, если под не имеет контроллера репликации (например, Job или CronJob). Можно проверить, что API нашего узла (кластера) отвечает: @@ -168,7 +168,7 @@ Unauthorized JSON-ответ от API. Что-то вроде: sudo cat /var/lib/rancher/k3s/server/node-token ``` -Вывод будет что-то вроде `K10...::server:longrandomstring`. Это и есть токен, который нужно будет использовать. +Вывод будет что-то вроде `K10…::server:longrandomstring`. Это и есть токен, который нужно будет использовать. Теперь на втором Orange Pi (например, с IP 192.168.1.28) можно запустить второй мастер-узел (вставим токен из предыдущего шага): @@ -176,9 +176,9 @@ sudo cat /var/lib/rancher/k3s/server/node-token curl -sfL https://get.k3s.io | sh -s - server --server https://192.168.1.27:6443 --token <ТОКЕН> --tls-san=192.168.1.28 ``` Здесь ключи: -* `--server https://192.168.1.27:6443` -- указывает на API мастер-узла, чтобы наш новый узел мог подключиться к кластеру. +* `--server https://192.168.1.27:6443` — указывает на API мастер-узла, чтобы наш новый узел мог подключиться к кластеру. * `--token` — токен аутентификации из предыдущего шага. -* `--tls-san=192.168.1.28` -- добавляет IP нашего второго мастера в сертификаты (для будущих подключений). +* `--tls-san=192.168.1.28` — добавляет IP нашего второго мастера в сертификаты (для будущих подключений). Проверим какие теперь ноды в кластере: ```bash @@ -210,7 +210,7 @@ kube-system svclb-traefik-4f8c2580-xzt5d 2/2 Running 0 kube-system traefik-5d45fc8cc9-t5d58 1/1 Running 0 2h 10.42.0.8 opi5plus-2 ``` -Как видим, у нас появился еще один `svclb-traefik` на второй ноде. Это под -- Service Load Balancer (SLB) для Traefik. +Как видим, у нас появился еще один `svclb-traefik` на второй ноде. Это под — Service Load Balancer (SLB) для Traefik. Он эмулирует облачный балансировщик нагрузки (типа AWS ELB), которого нет в локальном окружении вроде Orange Pi. SLB перенаправляет внешний трафик (например, на порты 80/443) к сервисам типа LoadBalancer внутри кластера. @@ -226,7 +226,7 @@ curl -sfL https://get.k3s.io | sh -s - agent --server https://192.168.1.10:6443 ``` Здесь ключ: -* `agent` -- устанавливает узел в режиме воркера (worker). Это значит, что узел будет выполнять рабочие нагрузки +* `agent` — устанавливает узел в режиме воркера (worker). Это значит, что узел будет выполнять рабочие нагрузки (поды), но не будет управлять кластером (без *control-plane*, *master* и на нем нет реплики *etcd*). Посмотрим на ноды (команда выполняется на одном из мастер-узлов): @@ -301,7 +301,7 @@ traefik LoadBalancer 10.43.164.48 192.168.1.26,192.168.1.27,192.16 им не нужен доступ к etcd в реальном времени. В чем может быть смысл иметь два мастера? Это обеспечивает репликацию данных (второй хранит копию etcd), но не -даёт отказоустойчивости -- когда один мастер упал, кластер становится неуправляемым (нет управления через kubectl), +даёт отказоустойчивости — когда один мастер упал, кластер становится неуправляемым (нет управления через kubectl), рабочие нагрузки (поды) могут продолжать работать, пока жив хотя бы один узел, но новые изменения (развертывание подов и обновления) невозможны. @@ -399,7 +399,7 @@ traefik-6c979cd89d-z6wwm 1/1 Running 0 2 ``` Хотя, в целом, кластер остается рабочим, и сам чинится при отключении и восстановлении узлов, но если отключается нода -на которой исполняется под с `coredns` -- то временно будет затруднен перезапуска и создание новых подов, а значит +на которой исполняется под с `coredns` — то временно будет затруднен перезапуска и создание новых подов, а значит и "переезд" подов с погашенного узла, до восстановления `coredns` тоже будет замедлен. Кроме того, если сценарий приложения(ий) развернутых внутри k3s предполагает переподключение с использованием имен подов или обнаружение подов, то это тоже перестанет работать. @@ -410,12 +410,12 @@ sudo k3s kubectl edit deployment coredns -n kube-system ``` Здесь: -* `kubectl edit` -- Открывает редактор (по умолчанию *vim*) для изменения ресурса Kubernetes напрямую в кластере. +* `kubectl edit` — Открывает редактор (по умолчанию *vim*) для изменения ресурса Kubernetes напрямую в кластере. Вместо создания локального YAML-файла и применения его через `kubectl apply`, мы сразу редактируем "живой" конфиг. -* `deployment coredns` -- Указывает, что редактируем объект типа *deployment* с именем `coredns`. Deployment — это +* `deployment coredns` — Указывает, что редактируем объект типа *deployment* с именем `coredns`. Deployment — это контроллер, который управляет набором подов (в данном случае coredns), обеспечивая их количество (реплики), перезапуск и обновления. -* `-n kube-system` -- Указывает пространство имён (namespace), где находится *coredns8. В k3s системные компоненты, +* `-n kube-system` — Указывает пространство имён (namespace), где находится *coredns8. В k3s системные компоненты, к которым относится *coredns(, обычно живут в kube-system. В открывшемся окне найдем строку `replicas: 1` и заменим её на `replicas: 2`. @@ -431,7 +431,7 @@ spec: NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-ccb96694c-n4qsp 0/1 ContainerCreating 0 5s opi5plus-1 coredns-ccb96694c-wzh96 1/1 Running 0 3h10m 10.42.1.8 opi5plus-3 -... +… ``` А затем: @@ -439,7 +439,7 @@ coredns-ccb96694c-wzh96 1/1 Running 0 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-ccb96694c-n4qsp 1/1 Running 0 15s 10.42.2.6 opi5plus-1 coredns-ccb96694c-wzh96 1/1 Running 0 3h10m 10.42.1.8 opi5plus-3 -... +… ``` **Как это будет работать?** Обе реплики `coredns` привязаны к сервису `kube-dns` в пространстве имён `kube-system`. @@ -455,10 +455,10 @@ sudo k3s kubectl get endpoints kube-dns -n kube-system гасили при экспериментах с устойчивостью кластера: ```text NAME ENDPOINTS AGE -kube-dns 10.42.1.8:53,10.42.2.6:53,10.42.1.8:53 + 3 more... 5d23h +kube-dns 10.42.1.8:53,10.42.2.6:53,10.42.1.8:53 + 3 more… 5d23h ``` -Каждый под `coredns` -- самостоятельный DNS-сервер. Они не взаимодействуют друг с другом и не обмениваются данными. Это +Каждый под `coredns` — самостоятельный DNS-сервер. Они не взаимодействуют друг с другом и не обмениваются данными. Это просто экземпляры одного и того же сервиса, работающие параллельно. Они независимы, получают данные из API Kubernetes и отвечают на запросы параллельно. В каждом поде кластера в качестве DNS настроен `kube-dns` (задаётся в файле `/etc/resolv.conf` внутри пода). Когда под отправляет DNS-запрос, его получит `kube-dns` и перенаправит запрос @@ -518,7 +518,7 @@ sudo apt install keepalived sudo nano /etc/keepalived/keepalived.conf ``` -На первом мастер-узле (хост -- `opi5plus-1`, IP -- `192.168.1.26`): +На первом мастер-узле (хост — `opi5plus-1`, IP — `192.168.1.26`): ```text vrrp_instance VI_1 { state MASTER # ЭТО ГЛАВНЫЙ ХОСТ. ПО УМОЛЧАНИЮ ТРАФИК С VIP БУДЕТ ПЕРЕНАПРАВЛЯТЬСЯ НА ЭТОТ ХОСТ @@ -537,7 +537,7 @@ vrrp_instance VI_1 { } ``` -На втором мастер-узле (хост -- `opi5plus-2`, IP -- `192.168.1.27`): +На втором мастер-узле (хост — `opi5plus-2`, IP — `192.168.1.27`): ```text vrrp_instance VI_1 { state BACKUP # ЭТО ВТОРОЙ ХОСТ. ОН БУДЕТ ПОЛУЧАТЬ ТРАФИК С VIP, ЕСЛИ ГЛАВНЫЙ ХОСТ УПАДЕТ @@ -556,7 +556,7 @@ vrrp_instance VI_1 { } ``` -И, наконец, на третьем мастер-узле (хост -- `opi5plus-3`, IP -- `192.168.1.28`): +И, наконец, на третьем мастер-узле (хост — `opi5plus-3`, IP — `192.168.1.28`): ```text vrrp_instance VI_1 { state BACKUP # ЭТО ТРЕТИЙ ХОСТ. ОН БУДЕТ ПОЛУЧАТЬ ТРАФИК С VIP, ЕСЛИ ГЛАВНЫЙ- И БЭКАП-ХОСТ УПАДЕТ @@ -588,15 +588,15 @@ ip addr show то увидим: ```text -... -... +… +… 2: enP4p65s0: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether c0:74:2b:fd:42:3c brd ff:ff:ff:ff:ff:ff inet 192.168.1.26/24 brd 192.168.1.255 scope global dynamic noprefixroute enP4p65s0 valid_lft 68779sec preferred_lft 68779sec inet 192.168.1.200/32 scope global enP4p65s0 valid_lft forever preferred_lft forever -... +… ``` Обратите внимание на виртуальный IP-адрес `192.168.1.200` находится в другой подсети (CIDR) и имеет маску `/32` (то есть с маской подсети `255.255.255.255`). Это "точечная" подсеть, содержащая только один адрес, не привязан к основной @@ -652,9 +652,9 @@ vps-sw-eye Ready 35m v1.31.6+k3s1 Таким образом, для управления удаленным узлом нужно чтобы он имел локальный IP-адрес в домашней сети, а не внешний. SSH-тоннель с помощью `autossh` и упаковкой UDP-трафика в TCP через `socat` не сработает (а я надеялся). Таким образом -"пробросить" Flannel для полноценного подключения удаленного k3s-узла -- VPN-туннель между каждой мастер-нодой на -удаленный узел. Это вполне рабочия вариант, если удаленные узлы -- полноценные и произвольные хосты. Но в моём -случае удаленный узел -- хост на 1 ядро и 1 ГБ ОЗУ. К тому же он на платформе x86_64, а не ARM, а значит ради одного +"пробросить" Flannel для полноценного подключения удаленного k3s-узла — VPN-туннель между каждой мастер-нодой на +удаленный узел. Это вполне рабочия вариант, если удаленные узлы — полноценные и произвольные хосты. Но в моём +случае удаленный узел — хост на 1 ядро и 1 ГБ ОЗУ. К тому же он на платформе x86_64, а не ARM, а значит ради одного узла не стоит заморачиваться с VPN. Другим вариантом является подключение внутри самих подов на удаленном узле к необходимым сервисам напрямую. Но таким diff --git a/raspberry-and-orange-pi/opi5plus-move-system-to-nvme-or-emmc.md b/raspberry-and-orange-pi/opi5plus-move-system-to-nvme-or-emmc.md index 54a1458..3fa0b8a 100644 --- a/raspberry-and-orange-pi/opi5plus-move-system-to-nvme-or-emmc.md +++ b/raspberry-and-orange-pi/opi5plus-move-system-to-nvme-or-emmc.md @@ -9,14 +9,14 @@ SSD NVMe, и для eMMC. Но, как и всякая магия, она мож ## Установка накопителей -Выключим Orange Pi 5 Plus и установим в него eMMC-носитель... +Выключим Orange Pi 5 Plus и установим в него eMMC-носитель… | Фото до и после установки eMMC. Внимание, устанавливайте до щелчка с обоих сторон! | |:-------------------------------------------------------------------------------------| | ![Orange Pi 5 Plus без eMMC](../images/orange-pi--photo--without-emmc.webp) | | ![Orange Pi 5 Plus c установленным eMMC](../images/orange-pi--photo--with-emmc.webp) | -...и/или SSD-накопитель NVMe +…и/или SSD-накопитель NVMe | Фото до и после установки NVMe. Более просто в установке. Для надёжности закрепить винтиком. | |:---------------------------------------------------------------------------------------------------| diff --git a/raspberry-and-orange-pi/opi5plus-rebuilding-linux-kernel-for-iscsi.md b/raspberry-and-orange-pi/opi5plus-rebuilding-linux-kernel-for-iscsi.md index 995e1c9..e95d97b 100644 --- a/raspberry-and-orange-pi/opi5plus-rebuilding-linux-kernel-for-iscsi.md +++ b/raspberry-and-orange-pi/opi5plus-rebuilding-linux-kernel-for-iscsi.md @@ -61,8 +61,8 @@ ls -al /tmp/boot-backup.tar.gz Теперь нам нужно скопировать его на какой-нибудь внешний хост (или носитель, но я буду копировать на хост другого компьютера). Если что-то пойдёт не так (например, после обновления ядра система не загрузится) можно будет восстановить -файлы из этого архива. Мой Orange Pi 5 Plus, на котором я буду компилировать ядро имеет хост -- `opi5plus-3` (замени -на свой хост), а имя пользователя от которого я работаю -- `opi` (замени на свой). На рабочем компьютере, с которого +файлы из этого архива. Мой Orange Pi 5 Plus, на котором я буду компилировать ядро имеет хост — `opi5plus-3` (замени +на свой хост), а имя пользователя от которого я работаю — `opi` (замени на свой). На рабочем компьютере, с которого я захожу по SSH на Orange, у меня есть папка `~/backup/` (`mkdir -p ~/backup`). Скачиваю в неё архив: ```bash scp opi@opi5plus-3.local:/tmp/boot-backup.tar.gz ~/backup/opi5plus-3-boot-backup.tar.gz @@ -93,38 +93,38 @@ drwxr-xr-x 3 root root 4096 ноя 21 09:55 dtb-6.1.43-rockchip-rk3588/ ``` Ключевые файлы: -* `Image` -- собственно ядро Linux (в данном случае версия 6.1.43 для Rockchip RK3588). При старте компьютера загрузчик +* `Image` — собственно ядро Linux (в данном случае версия 6.1.43 для Rockchip RK3588). При старте компьютера загрузчик U-Boot загрузит его в память и передаст ему управление. Без этого файла система не запустится. -* `vmlinuz-6.1.43-rockchip-rk3588` -- копия ядра (в системе уже есть резервная копия). -* `dtb/` -- Каталог файлами **Device Tree Blob** (`DTB`). Это бинарные файлы, описывающие аппаратное обеспечение устройства. +* `vmlinuz-6.1.43-rockchip-rk3588` — копия ядра (в системе уже есть резервная копия). +* `dtb/` — Каталог файлами **Device Tree Blob** (`DTB`). Это бинарные файлы, описывающие аппаратное обеспечение устройства. Для Orange Pi 5 Plus используется файл вроде `rk3588-orangepi-5-plus.dtb` (находится в подкаталоге `dtb/rockchip/`). DTB передаётся ядру, чтобы оно знало, как работать с процессором (количество ядер, частоты), памятью (RAM, её объём и адреса), периферией (UART, I2C, SPI, Ethernet, USB, GPIO, прерывания и тому подобное). На ARM-устройствах (в отличие от x86, где есть ACPI) нет стандартного способа обнаружения оборудования. DTB решает эту проблему, предоставляя ядру "карту" железа. U-Boot загружает DTB из `/boot/dtb/ `и передаёт его ядру при старте. Кстати, - в подкаталоге dtb/rockchip/ есть `overlay/` -- это дополнительные файлы, которые могут использоваться для добавления + в подкаталоге dtb/rockchip/ есть `overlay/` — это дополнительные файлы, которые могут использоваться для добавления и/или изменения функциональности устройства. Например, можно добавить поддержку новых периферийных устройств (камеру, дисплей и т.п.). -* `uInitrd` -- Начальный RAM-диск (initrd), адаптированный для U-Boot. Содержит модули и скрипты, необходимые для +* `uInitrd` — Начальный RAM-диск (initrd), адаптированный для U-Boot. Содержит модули и скрипты, необходимые для пред-загрузки (выбор накопителя, монтирование корневой файловой системы и т.п.). Если он повреждён или несовместим с ядром, загрузка может упасть на этапе инициализации. -* `orangepiEnv.txt` -- Конфигурационный файл для U-Boot. Здесь задаются параметры загрузки, такие как путь расположение - дерева DTB, UUID корневой файловой системы, тип файловой системы... Без правильных настроек в этом файле U-Boot не +* `orangepiEnv.txt` — Конфигурационный файл для U-Boot. Здесь задаются параметры загрузки, такие как путь расположение + дерева DTB, UUID корневой файловой системы, тип файловой системы… Без правильных настроек в этом файле U-Boot не найдёт нужные для загрузки файлы. -* `boot.scr` -- Скрипт загрузки для U-Boot. Содержит команды для загрузки ядра, initrd и DTB. U-Boot выполняет его +* `boot.scr` — Скрипт загрузки для U-Boot. Содержит команды для загрузки ядра, initrd и DTB. U-Boot выполняет его при старте системы. Этот файл создаётся из `boot.cmd` с помощью утилиты `mkimage`. Если он повреждён или отсутствует, U-Boot не сможет загрузить систему. -* `dtb-6.1.43-rockchip-rk3588/` -- Копия каталога `dtb/`, обычно появляется, когда ядро устанавливается или обновляется +* `dtb-6.1.43-rockchip-rk3588/` — Копия каталога `dtb/`, обычно появляется, когда ядро устанавливается или обновляется через пакетный менеджер (например, `apt`). Она привязана к конкретной версии ядра — в данном случае `6.1.43-rockchip-rk3588`, для того, чтобы: Хранить DTB-файлы, соответствующие этой версии ядра и избегать конфликты между DTB от разных версий ядра (если используется несколько ядер на одной системе). Менее критичные, но полезные файлы: -* `config-6.1.43-rockchip-rk3588` -- Конфигурация ядра, использованная при его сборке (он нам понадобится, чтобы +* `config-6.1.43-rockchip-rk3588` — Конфигурация ядра, использованная при его сборке (он нам понадобится, чтобы пересобрать ядро с iSCSI). -* `System.map-6.1.43-rockchip-rk3588` -- Карта меток (символов) ядра, полезна для отладки. -* `initrd.img-6.1.43-rockchip-rk3588` -- Обычный initrd, из которого генерируется uInitrd. -* `boot.bmp` и `logo.bmp` -- Изображения для экрана загрузки (не влияют на работу системы). +* `System.map-6.1.43-rockchip-rk3588` — Карта меток (символов) ядра, полезна для отладки. +* `initrd.img-6.1.43-rockchip-rk3588` — Обычный initrd, из которого генерируется uInitrd. +* `boot.bmp` и `logo.bmp` — Изображения для экрана загрузки (не влияют на работу системы). ## Устанавливать инструменты для сборки ядра @@ -136,13 +136,13 @@ sudo apt install -y build-essential bc flex bison libssl-dev libncurses-dev git Нам понадобятся следующие пакеты: -* `build-essential` -- Включает `gcc` (для ARM64, make и другие базовые инструменты компиляции. -* `bc` -- Утилита для точных математических вычислений в командной строке. Используется для вычислений в скриптах сборки ядра. -* `flex` и `bison` -- генератор лексических анализаторов и парсер. Нужны для обработки конфигурационных файлов ядра. -* `libssl-dev` -- Для поддержки криптографии в ядре и `OpenSSL`. -* `libncurses-dev` -- Библиотека для создания текстовых интерфейсов в терминале. Необходимо для работы интерфейса +* `build-essential` — Включает `gcc` (для ARM64, make и другие базовые инструменты компиляции. +* `bc` — Утилита для точных математических вычислений в командной строке. Используется для вычислений в скриптах сборки ядра. +* `flex` и `bison` — генератор лексических анализаторов и парсер. Нужны для обработки конфигурационных файлов ядра. +* `libssl-dev` — Для поддержки криптографии в ядре и `OpenSSL`. +* `libncurses-dev` — Библиотека для создания текстовых интерфейсов в терминале. Необходимо для работы интерфейса `menuconfig` при настройке параметров ядра. -* `git` -- Для клонирования исходного кода ядра из репозитория Xunlong. +* `git` — Для клонирования исходного кода ядра из репозитория Xunlong. > **Примечание:** Если вы хотите собрать ядро на x86-системе, установите кросс-компилятор `gcc-aarch64-linux-gnu` (`sudo apt install gcc-aarch64-linux-gnu`) и используйте его вместо обычного gcc в командах сборки. Он позволит собрать ядро для ARM64-архитектуры на x86-системе. @@ -314,10 +314,10 @@ sudo reboot Если вы все делали правильно, то такого быть не должно. Но, тем не менее, если загрузка не произошла, то это может выглядеть двумя способами: -* Система зависает на этапе загрузки: синенький огонек на Orange Pi не загорается и Ethernet тоже не мигает -- - _вы неправильно собрали ядро или испортили загрузчик_. -* Система, вроде как, грузится, но все никак... огоньки весело мигают, но не получается подключиться ни по SSH, ни - другим способом, пинги на IP-адрес не проходят -- _вы забыли подключить модули, накосячили с конфигом или с `.dtb`_. +* Система зависает на этапе загрузки: синенький огонек на Orange Pi не загорается и Ethernet тоже не мигает — + _вы неправильно собрали ядро или испортили загрузчик. +* Система, вроде как, грузится, но все никак… огоньки весело мигают, но не получается подключиться ни по SSH, ни + другим способом, пинги на IP-адрес не проходят — вы забыли подключить модули, накосячили с конфигом или с `.dtb`_. Чтобы починить, загружайтесь с MicroSD-карты (не забудьте отключить питание перед тем как вставить MicroSD-карту). Затем смонтируйте, в зависимости где у вас система, eMMC: @@ -327,7 +327,7 @@ mount /dev/mmcblk2p1 /mnt/emmc cd /mnt/emmc ``` -...или NVMe: +…или NVMe: ```bash mkdir -p /mnt/nvme mount /dev/nvme0n1p1 /mnt/nvme