mod: Перенос контейнера Docker в k3s....

This commit is contained in:
Sergei Erjemin 2025-04-28 10:54:10 +03:00
parent 9f713ba93a
commit 1abefba930
2 changed files with 162 additions and 143 deletions

View File

@ -15,7 +15,7 @@
* [Подключение менеджера сертификатов (cert-manager) Let's Encrypt](kubernetes/k3s-lets-encrypt-cert-manager.md) к k3s * [Подключение менеджера сертификатов (cert-manager) Let's Encrypt](kubernetes/k3s-lets-encrypt-cert-manager.md) к k3s
* [Под с 3X-UI](kubernetes/k3s-3xui-pod.md) в k3s * [Под с 3X-UI](kubernetes/k3s-3xui-pod.md) в k3s
* [Проксирование внешнего хоста через Traefik (Ingress-контроллер)](kubernetes/k3s-proxy.md) * [Проксирование внешнего хоста через Traefik (Ingress-контроллер)](kubernetes/k3s-proxy.md)
* [Перенос контейнера Docker в k3s](kubernetes/k3s-migrating-container-from-docker-to-kubernetes.md) * [Перенос контейнера Docker в k3s](kubernetes/k3s-migrating-container-from-docker-to-kubernetes.md) (на примере Gitea)
## Python ## Python
* [Устранение проблем при установке Python-коннектора mysqlclient (MySQL/MariaDB)](python/python-mysql.md) * [Устранение проблем при установке Python-коннектора mysqlclient (MySQL/MariaDB)](python/python-mysql.md)

View File

@ -44,9 +44,9 @@ docker stop docker stop gitea-new
``` ```
### Архивируем данные gitea ### Архивируем данные gitea
Находясь на хосте в Docker, cоздадим архив с данными gitea: Находясь на хосте в Docker, создадим архив с данными gitea:
```bash ```bash
tar -czf /home/orangepi/gitea-data.tar.gz -C /home/orangepi/docker-data/gitea-new . с
``` ```
Проверим, что архив создался: Проверим, что архив создался:
@ -82,7 +82,7 @@ ls -alh ~/gitea-data.tar.gz
Создадим пространство имен для gitea в k3s (чтобы все было аккуратно): Создадим пространство имен для gitea в k3s (чтобы все было аккуратно):
```bash ```bash
sudo kubectl create namespace gitea kubectl create namespace gitea
``` ```
Создаем папку для хранения манифестов gitea: Создаем папку для хранения манифестов gitea:
@ -99,7 +99,7 @@ mkdir -p ~/k3s/gitea
Создадим манифест для PersistentVolumeClaim (PVC) и PersistentVolume (PV): Создадим манифест для PersistentVolumeClaim (PVC) и PersistentVolume (PV):
```bash ```bash
nano ~/k3s/gitea/longhorn-pvc.yaml nano ~/k3s/gitea/gitea-pvc.yaml
``` ```
Вставляем в него следующее содержимое: Вставляем в него следующее содержимое:
@ -115,17 +115,17 @@ spec:
storageClassName: longhorn # Используем Longhorn как класс хранения storageClassName: longhorn # Используем Longhorn как класс хранения
resources: resources:
requests: requests:
storage: 10Gi # Размер под данные Gitea 10 Гб (максимальный объем) storage: 8Gi # Размер под данные Gitea 10 Гб (максимальный объем)
``` ```
Применим манифест: Применим манифест:
```bash ```bash
sudo kubectl apply -f ~/k3s/gitea/longhorn-pvc.yaml kubectl apply -f ~/k3s/gitea/gitea-pvc.yaml
``` ```
Проверим, что PVC создан и доступен: Проверим, что PVC создан и доступен:
```bash ```bash
sudo kubectl get pvc -n gitea -o wide kubectl get pvc -n gitea -o wide
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -151,20 +151,21 @@ spec:
containers: containers:
- name: init-data - name: init-data
image: alpine:latest image: alpine:latest
command: ["/bin/sh", "-c", "tar -xzf /mnt/gitea-data.tar.gz -C /data && chmod -R 777 /data && ls -la /data && sleep 3600"] command: ["/bin/sh", "-c", "tar -xzf /mnt/gitea-data.tar.gz -C /data && chown -R root:root /data && chmod -R 777 /data && ls -la /data && sleep 14400"]
# Для каталога `/data` заданы такие "злые" права из-за системных хуков, которые запускает Gitea. Точечно найти и дать права -- не получилось.
volumeMounts: volumeMounts:
- name: gitea-data - name: gitea-data
mountPath: /data mountPath: /data
- name: tmp-data - name: tmp-data
mountPath: /mnt mountPath: /mnt/gitea-data.tar.gz
volumes: volumes:
- name: gitea-data - name: gitea-data
persistentVolumeClaim: persistentVolumeClaim:
claimName: gitea-pvc claimName: gitea-pvc
- name: tmp-data - name: tmp-data
hostPath: hostPath:
path: /home/<USER-NAME> path: /home/<USER-NAME>/gitea-data.tar.gz
type: Directory # Указываем, что это папка type: File # Указываем, что это файл
restartPolicy: Never restartPolicy: Never
``` ```
@ -188,12 +189,12 @@ spec:
Применим манифест: Применим манифест:
```bash ```bash
sudo kubectl apply -f ~/k3s/gitea/gitea-init-data.yaml kubectl apply -f ~/k3s/gitea/gitea-init-data.yaml
``` ```
Проверим, что под создан и работает: Проверим, что под создан и работает:
```bash ```bash
sudo kubectl get pod -n gitea -o wide kubectl get pod -n gitea -o wide
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -204,7 +205,7 @@ gitea-init-data 1/1 Running 0 4m 10.42.2.64 opi5plus-1 <
Проверим логи пода: Проверим логи пода:
```bash ```bash
sudo kubectl logs -n gitea gitea-init-data kubectl logs -n gitea gitea-init-data
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -221,7 +222,7 @@ drwxrwxrwx 2 root root 4096 Apr 17 13:01 ssh
Как видим, данные благополучно распаковались в `/data` внутри пода, и это Longhorn PVC `gitea-pvc`. Можно также "зайти" Как видим, данные благополучно распаковались в `/data` внутри пода, и это Longhorn PVC `gitea-pvc`. Можно также "зайти"
в под и посмотреть, что там внутри: в под и посмотреть, что там внутри:
```bash ```bash
sudo kubectl exec -it -n gitea gitea-init-data -- /bin/sh kubectl exec -it -n gitea gitea-init-data -- /bin/sh
``` ```
Внутри пода дать команду, например: Внутри пода дать команду, например:
@ -250,13 +251,13 @@ SSD быстрее (если интересно, то вот [заметка о
и потому если контейнер с Gitea будет работать на SSD, то он будет работать быстрее. Как настроить предпочтение узлов и потому если контейнер с Gitea будет работать на SSD, то он будет работать быстрее. Как настроить предпочтение узлов
описано в [заметке о аффинити](k3s-affinate.md), поэтому кратко: присваиваем узлам метки, например `disk=ssd`: описано в [заметке о аффинити](k3s-affinate.md), поэтому кратко: присваиваем узлам метки, например `disk=ssd`:
```bash ```bash
sudo kubectl label nodes opi5plus-1 disk=ssd kubectl label nodes opi5plus-1 disk=ssd
sudo kubectl label nodes opi5plus-3 disk=ssd kubectl label nodes opi5plus-3 disk=ssd
``` ```
Проверяем, что метки добавлены: Проверяем, что метки добавлены:
```bash ```bash
sudo kubectl get nodes --show-labels | grep "disk=ssd" kubectl get nodes --show-labels | grep "disk=ssd"
``` ```
Будут показаны только узлы с меткой `disk=ssd`. У каждого узда очень много меток. Будут показаны только узлы с меткой `disk=ssd`. У каждого узда очень много меток.
@ -333,12 +334,12 @@ spec:
Применим манифест: Применим манифест:
```bash ```bash
sudo kubectl apply -f ~/k3s/gitea/gitea-deployment.yaml kubectl apply -f ~/k3s/gitea/gitea-deployment.yaml
``` ```
Проверим, что под создан и работает: Проверим, что под создан и работает:
```bash ```bash
sudo kubectl get pod -n gitea -o wide kubectl get pod -n gitea -o wide
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -356,7 +357,7 @@ gitea-init-data 0/1 Completed 0 2h 10.42.2.64 opi5p
Проверим логи пода `gitea`: Проверим логи пода `gitea`:
```bash ```bash
sudo kubectl logs -n gitea deployment/gitea kubectl logs -n gitea deployment/gitea
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -388,7 +389,7 @@ Server listening on 0.0.0.0 port 22.
Можно устроить более глубокую проверку, зайдя внутр пода и посмотреть как там всё устроено: Можно устроить более глубокую проверку, зайдя внутр пода и посмотреть как там всё устроено:
```bash ```bash
sudo kubectl exec -n gitea -it deployment/gitea -- /bin/bash kubectl exec -n gitea -it deployment/gitea -- /bin/bash
``` ```
Внутри пода проверим, что PVC `gitea-pvc` подключен и данные gitea и база на месте: Внутри пода проверим, что PVC `gitea-pvc` подключен и данные gitea и база на месте:
@ -445,81 +446,94 @@ exit
## Создание сервиса и IngressRoute для доступа к Gitea снаружи ## Создание сервиса и IngressRoute для доступа к Gitea снаружи
Добавим в предыдущий файл (или создадим новый манифест `~/k3s/gitea/gitea-service.yaml`) сервис для доступа к Gitea
снаружи кластера. Вставляем в него следующее содержимое:
```bash
nano ~/k3s/gitea/gitea-service.yaml
```
Вставляем в него следующее содержимое:
```yaml ```yaml
---
# Манифест для создания сервиса (Service)
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: gitea name: gitea # имя сервиса `gitea`
namespace: gitea namespace: gitea # в пространстве имен `gitea`
spec: spec:
selector: selector:
app: gitea app: gitea # выбираем поды с меткой `app: gitea`
ports: ports: # определяем порты, которые будут открыты в сервисе
- name: http - name: http # имя порта 'http'
port: 80 port: 80 # порт 80 (внешний)
targetPort: 3000 targetPort: 3000 # порт 3000 (внутренний, в контейнере)
protocol: TCP protocol: TCP # протокол TCP
#- name: ssh - name: ssh # имя порта 'http'
# port: 22 port: 22 # порт 22 (внешний)
# targetPort: 22 targetPort: 22 # порт 22 (внутренний, в контейнере)
# protocol: TCP protocol: TCP # протокол TCP
type: ClusterIP # тип сервиса -- ClusterIP (только внутри кластера)
``` ```
Объяснение:
selector: app: gitea — находит поды из Deployment gitea. Объяснение:
port: 80 — внешний порт сервиса (Traefik будет слать трафик сюда). * `selector: app: gitea` — находит поды из Deployment gitea.
targetPort: 3000 — порт контейнера Gitea. * `port: 80` — внешний порт сервиса (Traefik будет слать трафик сюда).
* `targetPort: 3000` — порт контейнера внутри пода Gitea.
Применим манифест: Применим манифест:
```bash ```bash
sudo kubectl apply -f ~/k3s/gitea/gitea-service.yaml kubectl apply -f ~/k3s/gitea/gitea-service.yaml
``` ```
sudo kubectl get svc -n gitea -o wide Проверим, что сервис создан:
```bash
kubectl get svc -n gitea -o wide
```
Увидим что-то вроде:
```text
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
gitea ClusterIP 10.43.211.8 <none> 80/TCP 115s app=gitea gitea ClusterIP 10.43.211.8 <none> 80/TCP 115s app=gitea
nano ~/k3s/gitea/https-redirect-middleware.yaml
```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: https-redirect
namespace: gitea
spec:
redirectScheme:
scheme: https
permanent: true
``` ```
Объяснение: Можно проверить, что под отвечает c IP-адреса сервиса (укажите IP-адрес сервиса):
```bash
curl -v http://10.43.211.8:80
```
redirectScheme: scheme: https — перенаправляет запросы на HTTPS. ## Создадим манифест для Middleware (перенаправление HTTP на HTTPS внутри Traefik):
permanent: true — возвращает 301 (постоянный редирект) для SEO и кэширования.
Размещаем в gitea, чтобы не затрагивать другие сервисы. Добавим в предыдущий файл (или создадим новый манифест `~/k3s/gitea/https-redirect-middleware.yaml`):
```yaml
---
# Манифест для Middleware (редирект HTTP → HTTPS внутри Traefik)
apiVersion: traefik.io/v1alpha1 # версия Traefik v34.2.1+up34.2.0 (Traefik v3.3.6)
# apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: https-redirect # Имя Middleware `https-redirect`
namespace: gitea # Размещаем в пространстве имен gitea, чтобы не затрагивать другие сервисы.
spec:
redirectScheme: # Схема редиректа
scheme: https # Перенаправлять на HTTPS
permanent: true # Постоянный редирект (HTTP 301) для SEO и кэширования
```
Что тут происходит:
* `redirectScheme: scheme: https` — перенаправляет запросы на HTTPS.
* `permanent: true` — возвращает 301 (постоянный редирект) для SEO и кэширования.
* Размещаем в gitea, чтобы не затрагивать другие сервисы.
Применить: Применить:
```bash ```bash
sudo kubectl apply -f ~/k3s/gitea/https-redirect-middleware.yaml kubectl apply -f ~/k3s/gitea/https-redirect-middleware.yaml
``` ```
### Подключаем сертификат Let's Encrypt ### Подключаем сертификат Let's Encrypt
У нас уже настроена выдача сертификатов Lets Encrypt в подах cert-managerб cert-manager-cainjector и У нас уже настроена выдача сертификатов Lets Encrypt в подах `cert-manager`, `cert-manager-cainjector` и
cert-manager-webhook, в пронстве имен cert-manager. Это нестандартный способ (см. [заметку о cert-manager](k3s-cert-manager.md)). `cert-manager-webhook`, в баронстве имен `cert-manager`. Это нестандартный способ
(см. [заметку о cert-manager](k3s-lets-encrypt-cert-manager.md)).
Проверим, что cert-manager работает: Проверим, что cert-manager работает:
```bash ```bash
sudo kubectl get pods -n cert-manager kubectl get pods -n cert-manager
``` ```
Увидим что-то вроде: Увидим что-то вроде:
```text ```text
@ -533,7 +547,7 @@ cert-manager-webhook-544c988c49-zxdxc 1/1 Running 0 19d
Проверим наличие ClusterIssuer: Проверим наличие ClusterIssuer:
```bash ```bash
sudo kubectl get clusterissuer -A -o wide kubectl get clusterissuer -A -o wide
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -544,7 +558,7 @@ letsencrypt-prod True The ACME account was registered with the ACME server
Проверим, что работает и Let's Encrypt знает о нас: Проверим, что работает и Let's Encrypt знает о нас:
```bash ```bash
sudo kubectl describe clusterissuer letsencrypt-prod kubectl describe clusterissuer letsencrypt-prod
``` ```
Увидим что-то вроде: Увидим что-то вроде:
@ -573,14 +587,8 @@ Events: <none>
Важно чтобы `Status: Conditions: Ready:` был `True`. Важно чтобы `Status: Conditions: Ready:` был `True`.
Добавим в предыдущий файл (или создадим новый манифест `~/k3s/gitea/gitea-certificate.yaml`) для получения сертификата
Let's Encrypt:
Создадим манифест для получения сертификата Let's Encrypt:
```bash
nano ~/k3s/gitea/gitea-certificate.yaml
```
и вставим в него следующее содержимое:
```yaml ```yaml
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
@ -596,67 +604,23 @@ spec:
kind: ClusterIssuer kind: ClusterIssuer
``` ```
secretName: gitea-tls: Сертификат сохраняется в Secret gitea-tls в gitea. Что тут происходит:
dnsNames: Домен git.cube2.ru. * `secretName: gitea-tls` -- Сертификат сохраняется в Secret с именем `gitea-tls` в пространстве имен `gitea`.
issuerRef: Ссылается на ClusterIssuer letsencrypt-prod. * `dnsNames` -- домен git.cube2.ru.
* `issuerRef` -- эмитент отвечающий за выдачу сертификата. В данном случае это `letsencrypt-prod`, который мы
создали ранее.
Применим манифест: Пока не будем применять манифест, так как это сразу создаст запрос к Lets Encrypt на получение сертификата, а у нас
```bash пока нет IngressRoute, который сможет обеспечить подтверждение владение доменом через _HTTP-01 challenge_
sudo kubectl apply -f ~/k3s/gitea/gitea-certificate.yaml (запрашивающий сертификат размещает специальный временный файл в папке `/.well-known/acme-challenge/` на web-сервере,
``` который доступен по HTTP, и Lets Encrypt проверяет его наличие для подтверждения владения доменом).
Проверим, что секрет создан:
```bash
sudo kubectl get secret -n gitea gitea-tls -o wide
```
Увидим что-то вроде:
```text
NAME TYPE DATA AGE
gitea-tls kubernetes.io/tls 2 46s
```
Проверим, что сертификат выдан:
```bash
sudo kubectl describe certificate -n gitea gitea-tls
```
Увидим что-то вроде:
```text
Name: gitea-tls
Namespace: gitea
...
...
...
Spec:
Dns Names:
тут-будет-ваш-домен
...
...
Status:
Conditions:
Last Transition Time: тут-будет-дата-время-выдачи-сертификата
Message: Certificate is up to date and has not expired
Observed Generation: 1
Reason: Ready
Status: True
Type: Ready
Not After: тут-будет-дата-время-окончания-действия-сертификата
Not Before: тут-будет-дата-время-начала-действия-сертификата
Renewal Time: тут-будет-дата-время-ближайшего-обновления-сертификата
Revision: 1
Events:
...
...
```
Ожидается `Status: True` в `Conditions`, свежие даты в `Not After` и `Not Before` и сообщение `Certificate is
up to date and has not expired` в `Message`.
У Lets Encrypt есть лимиты по количеству запросов на получение сертификатов (пять запросов в неделю), и исчерпать
лимит довольно неприятно. Как минимум полутора суток не получится запросить и получить новый сертификат. Поэтому
и не надо сейчас применять манифест.
## Создание IngressRoute для доступа к Gitea ## Создание IngressRoute для доступа к Gitea
Создать IngressRoute для HTTPS
Настроим IngressRoute для маршрутизации git.cube2.ru через HTTPS с Lets Encrypt и редиректом HTTP. Настроим IngressRoute для маршрутизации git.cube2.ru через HTTPS с Lets Encrypt и редиректом HTTP.
```bash ```bash
nano ~/k3s/gitea/gitea-ingressroute.yaml nano ~/k3s/gitea/gitea-ingressroute.yaml
@ -710,12 +674,67 @@ spec:
* `tls: certResolver: gitea-tls` — включает Lets Encrypt для автоматического получения сертификата через * `tls: certResolver: gitea-tls` — включает Lets Encrypt для автоматического получения сертификата через
cert-manager в секрет gitea-tls. Трафик идёт в тот же Service gitea. cert-manager в секрет gitea-tls. Трафик идёт в тот же Service gitea.
Применим манифест: Применим манифест для IngressRoute и сертификата Lets Encrypt:
```bash ```bash
sudo kubectl apply -f ~/k3s/gitea/gitea-ingressroute.yaml kubectl apply -f ~/k3s/gitea/gitea-ingressroute.yaml
kubectl apply -f ~/k3s/gitea/gitea-certificate.yaml
```
Все долно работать.
#### Проверим, что IngressRoute создан
#### Проверим, что сертификат Lets Encrypt создан
Проверим секрет:
```bash
kubectl get secret -n gitea gitea-tls -o wide
``` ```
Все долно работать. Проверим, что IngressRoute создан: Увидим что-то вроде:
```text
NAME TYPE DATA AGE
gitea-tls kubernetes.io/tls 2 46s
```
Проверим, что сертификат выдан:
```bash
sudo kubectl describe certificate -n gitea gitea-tls
```
Увидим что-то вроде:
```text
Name: gitea-tls
Namespace: gitea
...
...
...
Spec:
Dns Names:
тут-будет-ваш-домен
...
...
Status:
Conditions:
Last Transition Time: тут-будет-дата-время-выдачи-сертификата
Message: Certificate is up to date and has not expired
Observed Generation: 1
Reason: Ready
Status: True
Type: Ready
Not After: тут-будет-дата-время-окончания-действия-сертификата
Not Before: тут-будет-дата-время-начала-действия-сертификата
Renewal Time: тут-будет-дата-время-ближайшего-обновления-сертификата
Revision: 1
Events:
...
...
```
Ожидается `Status: True` в `Conditions`, свежие даты в `Not After` и `Not Before` и сообщение `Certificate is
up to date and has not expired` в `Message`.
## Подключение SSH к Gitea (опционально) ## Подключение SSH к Gitea (опционально)
@ -747,7 +766,7 @@ kubectl apply -f ~/k3s/gitea/gitea-service.yaml
Теперь Traefik сможет маршрутизировать SSH-трафик. Проверим, что сервис обновился: Теперь Traefik сможет маршрутизировать SSH-трафик. Проверим, что сервис обновился:
```bash ```bash
sudo kubectl get svc -n gitea -o wide kubectl get svc -n gitea -o wide
``` ```
Увидим что теперь в сервисе gitea есть порт 22: Увидим что теперь в сервисе gitea есть порт 22:
@ -778,13 +797,13 @@ spec:
Применим изменения и перезапустим Traefik чтобы изменения вступили в силу: Применим изменения и перезапустим Traefik чтобы изменения вступили в силу:
```bash ```bash
sudo kubectl apply -f ~/k3s/traefik/traefik-config.yaml kubectl apply -f ~/k3s/traefik/traefik-config.yaml
sudo kubectl rollout restart deployment -n kube-system traefik kubectl rollout restart deployment -n kube-system traefik
``` ```
Проверим, что Traefik перезапустился: Проверим, что Traefik перезапустился:
```bash ```bash
sudo kubectl get pod -n kube-system -o wide kubectl get pod -n kube-system -o wide
``` ```
Увидим что-то вроде (время жизни пода Traefik небольшое, так как он недавно перезапустился): Увидим что-то вроде (время жизни пода Traefik небольшое, так как он недавно перезапустился):