mod: Перенос контейнера Docker в k3s..
This commit is contained in:
parent
dc04658e70
commit
138bb728fc
@ -8,17 +8,73 @@ Let's Encrypt. Мне показалось, что зависимость от
|
||||
[перекомпилировать ядро](../raspberry-and-orange-pi/opi5plus-rebuilding-linux-kernel-for-iscsi.md)
|
||||
).
|
||||
|
||||
Я решил задокументировать процесс переноса контейнера из Docker в k3s, тем более Gitea был не единственный контейнер,
|
||||
который нужно было перенести. Возможно мой опыт вам тоже пригодится.
|
||||
|
||||
Я решил задокументировать процесс переноса контейнера из Docker в k3s, тем более Gitea не единственный контейнер,
|
||||
который мне нужно было перенести. Возможно мой опыт вам тоже пригодится.
|
||||
|
||||
## Перенос данных Docker-контейнера Gitea на узел k3s
|
||||
|
||||
Останавливаем докер
|
||||
На старом хосте Gitea работал в контейнере через docker-compose. Вот её `docker-compose.yaml`:
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
restart: always
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "2222:22"
|
||||
volumes:
|
||||
- /home/orangepi/docker-data/gitea-new:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
```
|
||||
|
||||
Архивируем данные gitea
|
||||
Как видим, в контейнере Gitea (с именем `gitea-new`) в качестве базы используется SQLite. Файл базы, конфиги
|
||||
и остальные данные хранятся в каталоге `/data` контейнера, смонтированного во внешний том (volume)
|
||||
`/home/orangepi/docker-data/gitea-new`. Нам нужно будет перенести все эти данные в кластер k3s, в блочное
|
||||
хранилище Longhorn. Для этого создадим архив с данными gitea и перенесем его на один из узлов k3s.
|
||||
|
||||
Переносим данные на узел k3s (в моем случае это opi5plus-1) по SCP:
|
||||
Чтобы забрать данные из контейнера, нужно остановить его (на хосте с Docker):
|
||||
```bash
|
||||
docker stop docker stop gitea-new
|
||||
```
|
||||
### Архивируем данные gitea
|
||||
|
||||
Находясь на хосте в Docker, cоздадим архив с данными gitea:
|
||||
```bash
|
||||
tar -czf /home/orangepi/gitea-data.tar.gz -C /home/orangepi/docker-data/gitea-new .
|
||||
```
|
||||
|
||||
Проверим, что архив создался:
|
||||
```bash
|
||||
ls -alh /home/orangepi/gitea-data.tar.gz
|
||||
```
|
||||
|
||||
Увидим что-то вроде:
|
||||
```text
|
||||
-rw-r--r-- 1 orangepi orangepi 147M Apr 16 18:10 /home/orangepi/gitea-data.tar.gz
|
||||
```
|
||||
|
||||
### Перенесём данные на узел k3s по SCP:
|
||||
|
||||
Находясь на хосте с Docker, перенесем архив с данными gitea на узел k3s (в моем случае это `opi5plus-1`):
|
||||
```bash
|
||||
scp /home/orangepi/gitea-data.tar.gz opi@opi5plus-1:/home/opi/
|
||||
```
|
||||
|
||||
Перейдем на узел `opi5plus-1` k3s и проверим, что архив с данными gitea там есть:
|
||||
```bash
|
||||
ls -alh ~/gitea-data.tar.gz
|
||||
```
|
||||
|
||||
Увидим что-то вроде:
|
||||
```text
|
||||
-rw-r--r-- 1 opi opi 147M Apr 16 18:12 /home/opi/gitea-data.tar.gz
|
||||
```
|
||||
|
||||
|
||||
## Подготовка узла k3s
|
||||
@ -243,11 +299,11 @@ spec:
|
||||
containers: # определяем контейнеры, которые будут запущены в поде
|
||||
- name: gitea # имя контейнера `gitea`
|
||||
image: gitea/gitea:latest # образ
|
||||
env: # переменные окружения
|
||||
- name: USER_UID # идентификатор пользователя
|
||||
value: "1000"
|
||||
- name: USER_GID # идентификатор группы
|
||||
value: "1000"
|
||||
# env: # переменные окружения
|
||||
# - name: USER_UID # идентификатор пользователя
|
||||
# value: "1000"
|
||||
# - name: USER_GID # идентификатор группы
|
||||
# value: "1000"
|
||||
ports: # определяем порты, которые будут открыты в контейнере
|
||||
- containerPort: 3000 # порт 3000
|
||||
name: http # будет именоваться 'http' (используется в Gitea для веб-интерфейса)
|
||||
@ -408,9 +464,11 @@ spec:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 3000
|
||||
protocol: TCP
|
||||
#- name: ssh
|
||||
# port: 22
|
||||
# targetPort: 222
|
||||
# targetPort: 22
|
||||
# protocol: TCP
|
||||
```
|
||||
Объяснение:
|
||||
|
||||
@ -453,7 +511,7 @@ permanent: true — возвращает 301 (постоянный редире
|
||||
sudo kubectl apply -f ~/k3s/gitea/https-redirect-middleware.yaml
|
||||
```
|
||||
|
||||
|
||||
### Подключаем сертификат Let's Encrypt
|
||||
|
||||
У нас уже настроена выдача сертификатов Let’s Encrypt в подах cert-managerб cert-manager-cainjector и
|
||||
cert-manager-webhook, в пронстве имен cert-manager. Это нестандартный способ (см. [заметку о cert-manager](k3s-cert-manager.md)).
|
||||
@ -595,7 +653,7 @@ Events:
|
||||
up to date and has not expired` в `Message`.
|
||||
|
||||
|
||||
|
||||
## Создание IngressRoute для доступа к Gitea
|
||||
|
||||
Создать IngressRoute для HTTPS
|
||||
Настроим IngressRoute для маршрутизации git.cube2.ru через HTTPS с Let’s Encrypt и редиректом HTTP.
|
||||
@ -613,7 +671,7 @@ spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`git.cube2.ru`)
|
||||
- match: Host("git.cube2.ru")
|
||||
kind: Rule
|
||||
services:
|
||||
- name: gitea
|
||||
@ -630,7 +688,7 @@ spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`git.cube2.ru`)
|
||||
- match: Host("git.cube2.ru")
|
||||
kind: Rule
|
||||
services:
|
||||
- name: gitea
|
||||
@ -641,29 +699,270 @@ spec:
|
||||
# certResolver: letsencrypt
|
||||
```
|
||||
Объяснение:
|
||||
|
||||
Первая IngressRoute (gitea-http):
|
||||
entryPoints: web — слушает порт 80 (HTTP).
|
||||
match: Host(git.cube2.ru) — обрабатывает запросы к git.cube2.ru.
|
||||
services: gitea — направляет трафик в Service gitea (порт 80 → 3000).
|
||||
middlewares: https-redirect — редирект на HTTPS.
|
||||
Вторая IngressRoute (gitea-https):
|
||||
entryPoints: websecure — слушает порт 443 (HTTPS).
|
||||
tls: certResolver: letsencrypt — включает Let’s Encrypt для автоматического получения сертификата.
|
||||
Трафик идёт в тот же Service gitea.
|
||||
* Первая IngressRoute (`gitea-http`):
|
||||
* `entryPoints: web` — слушает порт 80 (HTTP).
|
||||
* `match: Host("git.cube2.ru")` — обрабатывает запросы к git.cube2.ru.
|
||||
* `services: gitea` — направляет трафик в Service gitea (порт 80 → 3000).
|
||||
* `middlewares: https-redirect` — редирект на HTTPS.
|
||||
* Вторая IngressRoute (gitea-https):
|
||||
* `entryPoints: websecure` — слушает порт 443 (HTTPS).
|
||||
* `tls: certResolver: gitea-tls` — включает Let’s Encrypt для автоматического получения сертификата через
|
||||
cert-manager в секрет gitea-tls. Трафик идёт в тот же Service gitea.
|
||||
|
||||
Применим манифест:
|
||||
```bash
|
||||
sudo kubectl apply -f ~/k3s/gitea/gitea-ingressroute.yaml
|
||||
```
|
||||
|
||||
Все долно работать. Проверим, что IngressRoute создан:
|
||||
|
||||
## Подключение SSH к Gitea (опционально)
|
||||
|
||||
Кроме http-доступа и идентификации по логину, паролю и токенами, к к Gitea можно подключаться по SSH ([git://]). Выше
|
||||
мы не настраивали SSH, так как Gitea я использовал как демонстрацию переноса Docker-контейнера в под K3s.
|
||||
|
||||
Порт 22 (SSH) на узлах K3s уже занят, поэтому нам нужно перенастроить его на другой порт. Например, 2222.
|
||||
|
||||
Для настройки SSH нужно:
|
||||
- Обновить Service для Gitea, чтобы он включал порт 22 (SSH).
|
||||
- Настроить Traefik для порта 2222
|
||||
- Добавить IngressRouteTCP для Gitea (маршрутизация порта 22 изнутри пода а 2222 порт снаружи).
|
||||
- Изменить Traefik Service для доступа по порту 2222
|
||||
|
||||
### Обновим Service для Gitea
|
||||
|
||||
Можно удалить временный под:
|
||||
Вносим изменения в `~/k3s/gitea/gitea-service.yaml`, добавив в конце (этот блок был закомментирован):
|
||||
```yaml
|
||||
- port: 22 # SSH, добавить
|
||||
targetPort: 22
|
||||
protocol: TCP
|
||||
name: ssh
|
||||
```
|
||||
|
||||
Применим изменения:
|
||||
```bash
|
||||
kubectl apply -f ~/k3s/gitea/gitea-service.yaml
|
||||
````
|
||||
|
||||
Теперь Traefik сможет маршрутизировать SSH-трафик. Проверим, что сервис обновился:
|
||||
```bash
|
||||
sudo kubectl get svc -n gitea -o wide
|
||||
```
|
||||
|
||||
Увидим что теперь в сервисе gitea есть порт 22:
|
||||
```text
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
|
||||
gitea ClusterIP 10.43.211.8 <none> 80/TCP,22/TCP 5h app=gitea
|
||||
```
|
||||
|
||||
### Настроим Traefik для порта 2222
|
||||
|
||||
Traefik должен слушать порт 2222. У меня Traefik настроен через `Helm values` в `HelmChartConfig`, через дополнительные
|
||||
параметры `additionalArguments` . Чтобы Traefik начал слушать порт 2222, добавим новый entryPoint с именем `ssh` в
|
||||
`~/k3s/traefik/traefik-config.yaml`. Добавим в конец файла: `- --entrypoints.ssh.address=:2222`. Полностью манифест
|
||||
у меня выглядит так:
|
||||
```yaml
|
||||
aapiVersion: helm.cattle.io/v1
|
||||
kind: HelmChartConfig
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: kube-system
|
||||
spec:
|
||||
valuesContent: |-
|
||||
additionalArguments:
|
||||
- --entrypoints.web-custom.address=:2055 # Слушаем HTTP на 2055 (для web-панели 3x-ui)
|
||||
- --entrypoints.ssh.address=:2222 # Слушаем TCP на 2222 (для SSH)
|
||||
- --log.level=DEBUG
|
||||
```
|
||||
|
||||
Применим изменения и перезапустим Traefik чтобы изменения вступили в силу:
|
||||
```bash
|
||||
sudo kubectl apply -f ~/k3s/traefik/traefik-config.yaml
|
||||
sudo kubectl rollout restart deployment -n kube-system traefik
|
||||
```
|
||||
|
||||
Проверим, что Traefik перезапустился:
|
||||
```bash
|
||||
sudo kubectl get pod -n kube-system -o wide
|
||||
```
|
||||
|
||||
Увидим что-то вроде (время жизни пода Traefik небольшое, так как он недавно перезапустился):
|
||||
```text
|
||||
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
|
||||
...
|
||||
...
|
||||
traefik-6b96fd9d85-8txb9 1/1 Running 0 119s 10.42.0.93 opi5plus-2 <none> <none>
|
||||
...
|
||||
```
|
||||
|
||||
### Добавим IngressRouteTCP для Gitea
|
||||
|
||||
Чтобы маршрутизировать трафик с порта 2222 на Service Gitea (порт 22), создадим манифест IngressRouteTCP:
|
||||
```bash
|
||||
nano ~/k3s/gitea/gitea-ingressroute-tcp.yaml
|
||||
```
|
||||
|
||||
И вставим в него следующее содержимое:
|
||||
```yaml
|
||||
# IngressRouteTCP для маршрутизации SSH через Traefik
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRouteTCP
|
||||
metadata:
|
||||
name: gitea-ssh
|
||||
namespace: gitea
|
||||
spec:
|
||||
entryPoints:
|
||||
- ssh # Соответствует entryPoint в Traefik
|
||||
routes:
|
||||
- match: HostSNI(`*`) # Для TCP без SNI
|
||||
services:
|
||||
- name: gitea
|
||||
port: 22 # Порт Service
|
||||
```
|
||||
|
||||
Применим манифест:
|
||||
```bash
|
||||
sudo kubectl apply -f ~/k3s/gitea/gitea-ingressroute-tcp.yaml
|
||||
```
|
||||
|
||||
Проверим, что IngressRouteTCP создан:
|
||||
```bash
|
||||
sudo kubectl get ingressroutetcp -n gitea
|
||||
```
|
||||
|
||||
Увидим что-то вроде:
|
||||
```text
|
||||
NAME AGE
|
||||
gitea-ssh 16s
|
||||
```
|
||||
### Изменим Traefik Service для доступа к SSH по порту 2222 через балансировщик
|
||||
|
||||
Если у вас уже есть манифест Traefik Service (например `~/k3s/traefik/traefik-service.yaml`), то нужно добавить в него
|
||||
обработку порта:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: kube-system
|
||||
...
|
||||
...
|
||||
spec:
|
||||
ports:
|
||||
...
|
||||
...
|
||||
...
|
||||
- name: ssh # Имя порта (должно соответствовать имени в IngressRouteTCP и entryPoint)
|
||||
port: 2222 # Внешний порт
|
||||
targetPort: 2222 # Порт Traefik
|
||||
protocol: TCP # Протокол
|
||||
```
|
||||
|
||||
И, само собой, применить манифест:
|
||||
```bash
|
||||
sudo kubectl apply -f ~/k3s/traefik/traefik-service.yaml
|
||||
```
|
||||
|
||||
Если у вас нет манифеста Traefik Service, то можно отредактировать его непосредственно в кластере через `kubectl edit`
|
||||
(будьте готовы редактировать в **vim**):
|
||||
```bash
|
||||
sudo kubectl edit svc -n kube-system traefik -o yaml
|
||||
```
|
||||
|
||||
Важно: значение `nodePort` для SSH не нужно указывать, так как оно будет сгенерировано автоматически сразу после
|
||||
сохранения и выхода из редактора (из vim выходите через `<esc:>wq`).
|
||||
|
||||
Проверим, что Service обновился:
|
||||
```bash
|
||||
sudo kubectl get svc -n kube-system traefik
|
||||
```
|
||||
|
||||
Увидим что-то вроде (орт 2222 добавился в Service Traefik):
|
||||
```text
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
traefik LoadBalancer 10.43.164.48 192.168.1.26,192.168.1.27,192.168.1.28 80:32171/TCP,443:30329/TCP,9000:31317/TCP,2055:31675/TCP,2222:31963/TCP 6d
|
||||
```
|
||||
|
||||
Проверим, что порт 2222 доступен на VIP-адресе keepalived (не забудьте заменить `<VIP>` на ваш Virtual IP):
|
||||
```bash
|
||||
nc -zv <VIP> 2222
|
||||
```
|
||||
|
||||
Увидим, что порт 2222 доступен:
|
||||
```text
|
||||
Connection to <VIP> port 2222 [tcp/rockwell-csp2] succeeded!
|
||||
```
|
||||
|
||||
SSH в Gitea по порту 2222 должен работать. Проверим, что SSH доступен. Создадим SSH-ключ:
|
||||
```bash
|
||||
ssh-keygen -t ed25519 -C "ваше-имя-в-gitea-или-что-угодно"
|
||||
```
|
||||
|
||||
Возьмём публичный SSH-ключ `cat ~/.ssh/id_ed25519.pub` и добавим через web-интерфейс Gitea (_Settings → SSH / GPG Keys_
|
||||
или _Настройки → SSH / GPG ключи_). После добавления ключа, можно подключиться к Gitea по SSH:
|
||||
```bash
|
||||
ssh -p 2222 git@<VIP>
|
||||
```
|
||||
|
||||
Увидим что-то вроде:
|
||||
```text
|
||||
PTY allocation request failed on channel 0
|
||||
Hi there, ваше-имя-в-gitea-или-что-угодно! You've successfully authenticated with the key named Apple Mac Mini M4, but Gitea does not provide shell access.
|
||||
If this is unexpected, please log in with password and setup Gitea under another user.
|
||||
Connection to <VIP> closed.
|
||||
```
|
||||
|
||||
**ВСЕ!!** Можно настроить переадресацию внешнего 22 порта на домашнем роутере на 2222 порт VIP-адреса, и работать
|
||||
со всеми репозиториями Gitea по SSH как обычно. Для большинства роутеров при обращении по доменому имени gitea тоже
|
||||
будет работать по 22 порту.
|
||||
|
||||
## Удаление временного пода и архива
|
||||
|
||||
Можно удалить временный под, который мы использовали для переноса данных gitea в блочное хранилище Longhorn PVC:
|
||||
```bash
|
||||
sudo kubectl delete pod gitea-init-data -n gitea
|
||||
```
|
||||
|
||||
И удалить временный архив с данными gitea которые мы перенесли из Docker-контейнера и положили в корень домашнего
|
||||
каталога. Теперь данные gitea уже в Longhorn PVC и арихив не нужен:
|
||||
```bash
|
||||
sudo rm ~/gitea-data.tar.gz
|
||||
```
|
||||
|
||||
## Выводы
|
||||
|
||||
### Плюсы
|
||||
|
||||
Размещение Gitea в K3s с Longhorn и Traefik повысит отказоустойчивость и доступность. Выход из строя любого узла
|
||||
не приведёт к потере данных, так как Longhorn хранит данные в репликах на других узлах, а Traefik обеспечивает
|
||||
автоматическую маршрутизацию трафика.
|
||||
|
||||
### Минусы
|
||||
|
||||
Сложность и число абстракций при доступе клиентов в Gitea возросло, и Gitea стала работать на 50-100 миллисекунд
|
||||
медленнее (в зависимости от нагрузки на узлы). Если посмотреть метрики:
|
||||
```bash
|
||||
time curl -s -o /dev/null https://git.cube2.ru
|
||||
```
|
||||
|
||||
Увидим что-то вроде:
|
||||
```text
|
||||
real 0m0.233s
|
||||
user 0m0.124s
|
||||
sys 0m0.015s
|
||||
```
|
||||
|
||||
Где **233 мс** — суммарное время запроса (включая DNS, соединение, TLS и ответ Gitea). Для моей локальной
|
||||
сети (1 Гбит/с) стало медленнее, чем ожидалось (~50-100 мс для Docker с Nginx). Но для цепочки K3s с Traefik, Longhorn
|
||||
и keepalived — это разумно.
|
||||
|
||||
#### Основные компоненты задержки:
|
||||
|
||||
| Причина | Docker + Nginx | K3s + Traefik + Longhorn + Keepalived |
|
||||
|-----------------------------|-------------------|-------------------------------------------------|
|
||||
| DNS | 20-50 мс. | 20-50 мс. |
|
||||
| Web-сервер + TLS | Nginx — 20-40 мс. | Traefik — 30-50 мс. |
|
||||
| Маршрутизация | 10 мс. | IngressRoute + Service + Keepalived — 20-60 мс. |
|
||||
| Доступ к базе данных SQLite | 10 мс. | Longhorn PVC — 20-50 мс. |
|
||||
| | | |
|
||||
| **Итого:** | **60-110 мс** | **90-210 мс** |
|
||||
|
Loading…
x
Reference in New Issue
Block a user