В этой статье используется лицензионное соглашение «Signature 4.0 International (CC BY 4.0)», добро пожаловать на перепечатку или изменение для использования, но вам необходимо указать источник.Атрибуция 4.0 Международная (CC BY 4.0)
Автор этой статьи: Су Ян
Создано: 08 сентября 2019 г. Статистические слова: 15348 слов Время чтения: 31 минута на чтение Ссылка на эту статью:Поиск teay.com/2019/09/08/…
Создайте свою среду K8s с помощью MicroK8s
В прошлом году я написалПросто создайте кластер Kubernetes, в то время использовался официальный набор инструментов: Kubeadm, это решение все еще слишком сложно для студентов, которые просто хотят его попробовать. Вот простой инструмент: MicroK8s.
Официальное название этого инструмента — «Kubernetes без эксплуатации и обслуживания, обслуживающий рабочие станции и Интернет вещей».
Официальный сайтДокумент здесь кратко знакомит с тем, как его установить и использовать, но студенты из материкового Китая, которые не учли сетевых проблем в процессе установки, в этой статье расскажут об этой ситуации.
написать впереди
официальныйранееОбъявите, что он будет использоваться следующимContainerd
заменятьdocker
:
The upcoming release of v1.14 Kubernetes will mark the MicroK8s switch to Containerd and enhanced security. As this is a big step forward we would like to give you a heads up and offer you a preview of what is coming. Give it a test drive with:
snap install microk8s --classic --channel=1.13/edge/secure-containerd
You can read more in our blog 117, and the respective pill request 13 Please, let us know 5 how we can make this transition smoother for you. Thanks
В сообществе уже есть пользователиПроконсультируйтесь / Тукао, Рассмотрите возможность уменьшения изменений здесь.Пока мы будем использовать docker в качестве пакета контейнера 1.13.Новую версию оставим на следующую "броску".
Установите MicroK8S с помощью SNAP
snapЭто более «продвинутое» решение для управления пакетами, предоставленное компанией **canonical**, которое впервые было применено к Ubuntu Phone.
Установить K8s с помощью оснастки очень просто, как показано ниже, одна команда решает проблему:
snap install microk8s --classic --channel=1.13/stable
Но если эта команда не выполняется на зарубежном хосте, она должна столкнуться с проблемами медленной установки.
snap install microk8s --classic --channel=1.13/stable
Download snap "microk8s" (581) from channel "1.13/stable" 0% 25.9kB/s 2h32m
Чтобы решить эту проблему, мы можем только временно добавить агента в оснастку, чтобы решить проблему.Snap не будет читать системные переменные среды, а только читать файлы переменных приложения.
Используйте следующие команды, чтобы легко изменить переменные среды оснастки, но редактор по умолчанию — ** nano **, который очень сложен в использовании.
systemctl edit snapd.service
Здесь мы можем сначала обновить редактор до нашего знакомого **vim**:
sudo update-alternatives --install "$(which editor)" editor "$(which vim)" 15
sudo update-alternatives --config editor
Интерактивный терминал требует, чтобы мы вручную вводили числа, а затем нажимали ввод, чтобы подтвердить выбор:
There are 5 choices for the alternative editor (providing /usr/bin/editor).
Selection Path Priority Status
------------------------------------------------------------
* 0 /bin/nano 40 auto mode
1 /bin/ed -100 manual mode
2 /bin/nano 40 manual mode
3 /usr/bin/vim 15 manual mode
4 /usr/bin/vim.basic 30 manual mode
5 /usr/bin/vim.tiny 15 manual mode
Press <enter> to keep the current choice[*], or type selection number: 5
update-alternatives: using /usr/bin/vim.tiny to provide /usr/bin/editor (editor) in manual mode
Выполните приведенную выше команду, чтобы снова отредактировать переменную среды и добавить конфигурацию прокси:
[Service]
Environment="HTTP_PROXY=http://10.11.12.123:10240"
Environment="HTTPS_PROXY=http://10.11.12.123:10240"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.0.0/24,*.domain.ltd"
Выполните установку еще раз, и процесс установки взлетит:
snap install microk8s --classic --channel=1.13/stable
Download snap "microk8s" (581) from channel "1.13/stable" 31% 14.6MB/s 11.2s
Если скорость не изменится, рассмотрите возможность перезагрузки службы моментальных снимков.
systemctl daemon-reload && systemctl restart snapd
Если вышеуказанная операция прошла успешно, вы увидите журнал, подобный следующему:
snap install microk8s --classic --channel=1.13/stable
microk8s (1.13/stable) v1.13.6 from Canonical✓ installed
Выполните команду списка, вы увидите установленные инструменты текущей оснастки:
snap list
Name Version Rev Tracking Publisher Notes
core 16-2.40 7396 stable canonical✓ core
microk8s v1.13.6 581 1.13 canonical✓ classic
ДоЧтобы установить K8s самостоятельно, вам нужно сначала установить докер, а при мгновенной установке все это есть по умолчанию.
microk8s.docker version
Client:
Version: 18.09.2
API version: 1.39
Go version: go1.10.4
Git commit: 6247962
Built: Tue Feb 26 23:56:24 2019
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: 18.09.2
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: 6247962
Built: Tue Feb 12 22:47:29 2019
OS/Arch: linux/amd64
Experimental: false
Получить образы зависимостей Kubernetes
Чтобы использовать Kubernetes, помимо установки MicroK8s, вам также необходимо получить образы инструментов, от которых он зависит. Однако получение образа все же требует немного усилий, в первую очередь1.13
Версия кода MicroK8s:
git clone --single-branch --branch=1.13 https://github.com/ubuntu/microk8s.git
Затем получите список объявленных в нем образов контейнеров:
grep -ir 'image:' * | awk '{print $3 $4}' | uniq
Из-за необузданности официального кода мы получим зеркальные имена странной формы:
localhost:32000/my-busybox
elasticsearch:6.5.1
alpine:3.6
docker.elastic.co/kibana/kibana-oss:6.3.2
time="2016-02-04T07:53:57.505612354Z"level=error
cdkbot/registry-$ARCH:2.6
...
...
quay.io/prometheus/prometheus
quay.io/coreos/kube-rbac-proxy:v0.4.0
k8s.gcr.io/metrics-server-$ARCH:v0.2.1
cdkbot/addon-resizer-$ARCH:1.8.1
cdkbot/microbot-$ARCH
"k8s.gcr.io/cuda-vector-add:v0.1"
nginx:latest
istio/examples-bookinfo-details-v1:1.8.0
busybox
busybox:1.28.4
В соответствии с конкретными потребностями целевого сервера, который мы хотим развернуть, замените$ARCH
переменная, удалите бессмысленное имя изображения, и отсортированный список выглядит следующим образом:
k8s.gcr.io/fluentd-elasticsearch:v2.2.0
elasticsearch:6.5.1
alpine:3.6
docker.elastic.co/kibana/kibana-oss:6.3.2
cdkbot/registry-amd64:2.6
gcr.io/google_containers/defaultbackend-amd64:1.4
quay.io/kubernetes-ingress-controller/nginx-ingress-controller-amd64:0.22.0
jaegertracing/jaeger-operator:1.8.1
gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.7
gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.7
gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.7
k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
k8s.gcr.io/heapster-influxdb-amd64:v1.3.3
k8s.gcr.io/heapster-grafana-amd64:v4.4.3
k8s.gcr.io/heapster-amd64:v1.5.2
cdkbot/addon-resizer-amd64:1.8.1
cdkbot/hostpath-provisioner-amd64:latest
quay.io/coreos/k8s-prometheus-adapter-amd64:v0.3.0
grafana/grafana:5.2.4
quay.io/coreos/kube-rbac-proxy:v0.4.0
quay.io/coreos/kube-state-metrics:v1.4.0
quay.io/coreos/addon-resizer:1.0
quay.io/prometheus/prometheus
quay.io/coreos/prometheus-operator:v0.25.0
quay.io/prometheus/alertmanager
quay.io/prometheus/node-exporter:v0.16.0
quay.io/coreos/kube-rbac-proxy:v0.4.0
k8s.gcr.io/metrics-server-amd64:v0.2.1
cdkbot/addon-resizer-amd64:1.8.1
nvidia/k8s-device-plugin:1.11
cdkbot/microbot-amd64
k8s.gcr.io/cuda-vector-add:v0.1
nginx:latest
istio/examples-bookinfo-details-v1:1.8.0
istio/examples-bookinfo-ratings-v1:1.8.0
istio/examples-bookinfo-reviews-v1:1.8.0
istio/examples-bookinfo-reviews-v2:1.8.0
istio/examples-bookinfo-reviews-v3:1.8.0
istio/examples-bookinfo-productpage-v1:1.8.0
busybox
busybox:1.28.4
Сохраните приведенный выше список какpackage-list.txtИспользуйте следующий сценарий на облачном сервере с бесперебойной сетью, чтобы сохранить образ инструмента, зависящего от K8s, в автономном режиме:
PACKAGES=`cat ./package-list.txt`;
for package in $PACKAGES; do docker pull "$package"; done
docker images | tail -n +2 | grep -v "<none>" | awk '{printf("%s:%s\n", $1, $2)}' | while read IMAGE; do
for package in $PACKAGES;
do
if [[ $package != *[':']* ]];then package="$package:latest"; fi
if [ $IMAGE == $package ];then
echo "[find image] $IMAGE"
filename="$(echo $IMAGE| tr ':' '-' | tr '/' '-').tar"
echo "[save as] $filename"
docker save ${IMAGE} -o $filename
fi
done
done
Перенести образ на сервер для развертывания можно разными способами, вот самое простое решение:scp
PACKAGES=`cat ./package-list.txt`;
for package in $PACKAGES;
do
if [[ $package != *[':']* ]];then package="$package:latest";fi
filename="$(echo $package| tr ':' '-' | tr '/' '-').tar"
# 根据自己实际场景修改地址
scp "mirror-server:~/images/$filename" .
scp "./$filename" "deploy-server:"
done
Если вы идете хорошо, вы увидите следующий журнал:
k8s.gcr.io-fluentd-elasticsearch-v2.2.0.tar 100% 140MB 18.6MB/s 00:07
elasticsearch-6.5.1.tar 100% 748MB 19.4MB/s 00:38
alpine-3.6.tar 100% 4192KB 15.1MB/s 00:00
docker.elastic.co-kibana-kibana-oss-6.3.2.tar 100% 614MB 22.8MB/s 00:26
cdkbot-registry-amd64-2.6.tar 100% 144MB 16.1MB/s 00:08
gcr.io-google_containers-defaultbackend-amd64-1.4.tar 100% 4742KB 13.3MB/s 00:00
...
...
Наконец, целевой сервер используетdocker load
команда для импорта изображения.
ls *.tar | xargs -I {} microk8s.docker load -i {}
Далее можно официально установить K8s.
Официально начните установку Kubernetes
Настройка различных компонентов с помощью MicroK8s выполняется одной командой:
microk8s.enable dashboard dns ingress istio registry storage
Полный список компонентов можно найти черезmicrok8s.enable --help
Приходите посмотреть:
microk8s.enable --help
Usage: microk8s.enable ADDON...
Enable one or more ADDON included with microk8s
Example: microk8s.enable dns storage
Available addons:
dashboard
dns
fluentd
gpu
ingress
istio
jaeger
metrics-server
prometheus
registry
storage
воплощать в жизньenable
Если все пойдет хорошо, вы увидите журналы, похожие на следующие:
logentry.config.istio.io/accesslog created
logentry.config.istio.io/tcpaccesslog created
rule.config.istio.io/stdio created
rule.config.istio.io/stdiotcp created
...
...
Istio is starting
Enabling the private registry
Enabling default storage class
deployment.extensions/hostpath-provisioner created
storageclass.storage.k8s.io/microk8s-hostpath created
Storage will be available soon
Applying registry manifest
namespace/container-registry created
persistentvolumeclaim/registry-claim created
deployment.extensions/registry created
service/registry created
The registry is enabled
Enabling default storage class
deployment.extensions/hostpath-provisioner unchanged
storageclass.storage.k8s.io/microk8s-hostpath unchanged
Storage will be available soon
использоватьmicrok8s.status
Проверьте состояние отдельных компонентов:
microk8s is running
addons:
jaeger: disabled
fluentd: disabled
gpu: disabled
storage: enabled
registry: enabled
ingress: enabled
dns: enabled
metrics-server: disabled
prometheus: disabled
istio: enabled
dashboard: enabled
Но компоненты готовы, это не значит, что K8s уже установлен, пользуйтесьmicrok8s.inspect
Проверьте результаты установки и развертывания:
Inspecting services
Service snap.microk8s.daemon-containerd is running
Service snap.microk8s.daemon-docker is running
Service snap.microk8s.daemon-apiserver is running
Service snap.microk8s.daemon-proxy is running
Service snap.microk8s.daemon-kubelet is running
Service snap.microk8s.daemon-scheduler is running
Service snap.microk8s.daemon-controller-manager is running
Service snap.microk8s.daemon-etcd is running
Copy service arguments to the final report tarball
Inspecting AppArmor configuration
Gathering system info
Copy network configuration to the final report tarball
Copy processes list to the final report tarball
Copy snap list to the final report tarball
Inspect kubernetes cluster
WARNING: IPtables FORWARD policy is DROP. Consider enabling traffic forwarding with: sudo iptables -P FORWARD ACCEPT
Решение простое, используйтеufw
Просто добавьте несколько правил:
sudo ufw allow in on cbr0 && sudo ufw allow out on cbr0
sudo ufw default allow routed
sudo iptables -P FORWARD ACCEPT
использовать сноваmicrok8s.inspect
Командный осмотр, найдетWARNINGисчез.
Но действительно ли установлен Kubernetes? Следуйте следующему разделу, чтобы найти ответ.
Решить, что Kubernetes не может нормально запуститься
После успешного завершения вышеуказанной операции используйтеmicrok8s.kubectl get pods
Просмотр текущих статусов Cubernetes Pods, если вы видитеContainerCreating
, то Kubernetes требует дополнительной «работы по исправлению».
NAME READY STATUS RESTARTS AGE
default-http-backend-855bc7bc45-t4st8 0/1 ContainerCreating 0 16m
nginx-ingress-microk8s-controller-kgjtl 0/1 ContainerCreating 0 16m
использоватьmicrok8s.kubectl get pods --all-namespaces
Проверьте подробный статус, и, если ничего другого, вы увидите вывод журнала, подобный следующему:
NAMESPACE NAME READY STATUS RESTARTS AGE
container-registry registry-7fc4594d64-rrgs9 0/1 Pending 0 15m
default default-http-backend-855bc7bc45-t4st8 0/1 ContainerCreating 0 16m
default nginx-ingress-microk8s-controller-kgjtl 0/1 ContainerCreating 0 16m
...
...
Первая задача - решить этуPendingгосударственный контейнер. использоватьmicrok8s.kubectl describe pod
Вы можете быстро просмотреть подробный статус текущего рассматриваемого модуля:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 22m default-scheduler Successfully assigned default/default-http-backend-855bc7bc45-t4st8 to ubuntu-basic-18-04
Warning FailedCreatePodSandBox 21m kubelet, ubuntu-basic-18-04 Failed create pod sandbox: rpc error: code = Unknown desc = failed pulling image "k8s.gcr.io/pause:3.1": Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Warning FailedCreatePodSandBox 43s (x45 over 21m) kubelet, ubuntu-basic-18-04 Failed create pod sandbox: rpc error: code = Unknown desc = failed pulling image "k8s.gcr.io/pause:3.1": Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Ссылаясь на вывод журнала, можно обнаружить, что в составленном ранее списке зависимых зеркал все еще есть «рыба, которая проскользнула через сеть»: MicroK8s также содержит зеркала, полученные из удаленной настройки, которые не прописаны в программе.
В этом случае мы можем сделать это, только давdocker
Добавьте прокси для решения проблемы (или делайте это по одному вручную).
Отредактируйте файл конфигурации переменных среды Docker, используемый MicroK8s.vi /var/snap/microk8s/current/args/dockerd-env
, добавить в него конфигурацию прокси, например:
HTTPS_PROXY=http://10.11.12.123:10555
HTTPS_PROXY=http://10.11.12.123:10555
NO_PROXY=127.0.0.1
Затем перезапустите докер:
sudo systemctl restart snap.microk8s.daemon-docker.service
После того, как все это настроено, выполните следующие команды, чтобы перезагрузить MicroK8s, и попробуйте снова установить различные компоненты:
microk8s.reset
microk8s.enable dashboard dns ingress istio registry storage
После завершения команды снова выполните ее через некоторое времяmicrok8s.kubectl get pods
Вы обнаружите, что статус всех модулей — «Работает»:
NAME READY STATUS RESTARTS AGE
default-http-backend-855bc7bc45-w62jd 1/1 Running 0 46s
nginx-ingress-microk8s-controller-m9lc2 1/1 Running 0 46s
использоватьmicrok8s.kubectl get pods --all-namespaces
Приступайте к проверке:
NAMESPACE NAME READY STATUS RESTARTS AGE
container-registry registry-7fc4594d64-whjnl 1/1 Running 0 2m
default default-http-backend-855bc7bc45-w62jd 1/1 Running 0 2m
default nginx-ingress-microk8s-controller-m9lc2 1/1 Running 0 2m
istio-system grafana-59b8896965-xtc27 1/1 Running 0 2m
istio-system istio-citadel-856f994c58-fbc7c 1/1 Running 0 2m
istio-system istio-cleanup-secrets-9q8tw 0/1 Completed 0 2m
istio-system istio-egressgateway-5649fcf57-cbqlv 1/1 Running 0 2m
istio-system istio-galley-7665f65c9c-l7grc 1/1 Running 0 2m
istio-system istio-grafana-post-install-sl6mb 0/1 Completed 0 2m
istio-system istio-ingressgateway-6755b9bbf6-hvnld 1/1 Running 0 2m
istio-system istio-pilot-698959c67b-zts2v 2/2 Running 0 2m
istio-system istio-policy-6fcb6d655f-mx68m 2/2 Running 0 2m
istio-system istio-security-post-install-5d7bb 0/1 Completed 0 2m
istio-system istio-sidecar-injector-768c79f7bf-qvcjd 1/1 Running 0 2m
istio-system istio-telemetry-664d896cf5-jz22s 2/2 Running 0 2m
istio-system istio-tracing-6b994895fd-z8jn9 1/1 Running 0 2m
istio-system prometheus-76b7745b64-fqvn9 1/1 Running 0 2m
istio-system servicegraph-5c4485945b-spf77 1/1 Running 0 2m
kube-system heapster-v1.5.2-64874f6bc6-8ghnr 4/4 Running 0 2m
kube-system hostpath-provisioner-599db8d5fb-kxtjw 1/1 Running 0 2m
kube-system kube-dns-6ccd496668-98mvt 3/3 Running 0 2m
kube-system kubernetes-dashboard-654cfb4879-vzgk5 1/1 Running 0 2m
kube-system monitoring-influxdb-grafana-v4-6679c46745-68vn7 2/2 Running 0 2m
Если вы видите результаты, подобные приведенным выше, Kubernetes действительно готов.
Создание приложений быстро
После того, как охрана закончилась, надо попробовать поиграть и посмотреть.Конечно, нет возможности торопливо положить ручку за кулисы под показ толпы.
использоватьkubectl
Создайте развертывание на основе существующего контейнера:
microk8s.kubectl create deployment microbot --image=dontrebootme/microbot:v1
Так как используется самая совершенная система оркестрации, было бы жаль не испытать автоматическое расширение:
microk8s.kubectl scale deployment microbot --replicas=2
Откройте сервис и создайте переадресацию трафика:
microk8s.kubectl expose deployment microbot --type=NodePort --port=80 --name=microbot-service
использоватьget
Команда для проверки статуса службы:
microk8s.kubectl get all
Если все пойдет хорошо, вы увидите что-то вроде следующего лога:
NAME READY STATUS RESTARTS AGE
pod/default-http-backend-855bc7bc45-w62jd 1/1 Running 0 64m
pod/microbot-7c7594fb4-dxgg7 1/1 Running 0 13m
pod/microbot-7c7594fb4-v9ztg 1/1 Running 0 13m
pod/nginx-ingress-microk8s-controller-m9lc2 1/1 Running 0 64m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/default-http-backend ClusterIP 10.152.183.13 <none> 80/TCP 64m
service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 68m
service/microbot-service NodePort 10.152.183.15 <none> 80:31354/TCP 13m
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/nginx-ingress-microk8s-controller 1 1 1 1 1 <none> 64m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/default-http-backend 1/1 1 1 64m
deployment.apps/microbot 2/2 2 2 13m
NAME DESIRED CURRENT READY AGE
replicaset.apps/default-http-backend-855bc7bc45 1 1 1 64m
replicaset.apps/microbot-7c7594fb4 2 2 2 13m
Вы можете видеть, что адрес службы, который мы только что создали,10.11.12.234:31354
. Используя браузер для доступа, вы можете видеть, что приложение работает.
В соответствии с зеленой концепцией защиты окружающей среды «кто производит и убирает», в дополнение к «безмозглому» творчеству, нам также необходимо научиться управлять (разрушать), использоватьdelete
Командование, сначала уничтожить развертывание:
microk8s.kubectl delete deployment microbot
После выполнения вывод журнала будет следующим:
deployment.extensions "microbot" deleted
Прежде чем уничтожить сервис, нам нужно использоватьget
Сначала команда получает имена всех сервисов:
microk8s.kubectl get services microbot-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
microbot-service NodePort 10.152.183.15 <none> 80:31354/TCP 24m
После получения имени службы оно все еще используетсяdelete
Команда для удаления ненужных ресурсов:
microk8s.kubectl delete service microbot-service
Результат выполнения следующий:
service "microbot-service" deleted
Просмотр приборной панели
Предполагается, что некоторые учащиеся все же захотят получить представление о статусе Dashboard.
в состоянии пройтиmicrok8s.config
Команда, сначала получите IP-адрес текущего прослушивающего сервера:
microk8s.config
apiVersion: v1
clusters:
- cluster:
server: http://10.11.12.234:8080
name: microk8s-cluster
contexts:
- context:
cluster: microk8s-cluster
user: admin
name: microk8s
current-context: microk8s
kind: Config
preferences: {}
users:
- name: admin
user:
username: admin
Вы можете видеть, что текущий IP-адрес службы прослушивания10.11.12.234
,использоватьproxy
Команда для включения переадресации трафика:
microk8s.kubectl proxy --accept-hosts=.* --address=0.0.0.0
Затем посетите следующий адрес, вы можете увидеть панель инструментов, с которой мы знакомы:
http://10.11.12.234:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login
разное
После полной установки общее дисковое пространство, подключенное к системе, приближается к 8G, поэтому, если вы планируете использовать его постоянно, вы можете заранее спланировать дисковое пространство, например, см.Миграция хранилищ контейнеров DockerПеренесите адрес пакета образа Docker, который будет расширяться в будущем.
df -h
Filesystem Size Used Avail Use% Mounted on
udev 7.8G 0 7.8G 0% /dev
tmpfs 1.6G 1.7M 1.6G 1% /run
/dev/sda2 79G 16G 59G 21% /
Наконец
Эта статья была написана месяц назад.Поскольку решение «Докер» все еще используется, своевременность в теории все еще надежна.Если у вас возникнут какие-либо проблемы, добро пожаловать на обсуждение и общение.
Наблюдая за тем, как в черновом ящике накапливается все больше и больше интересного контента, возможно, пришло время рассмотреть модель «соавторства».
-Эоф
Теперь у меня есть небольшая расстраивающая группа, которая собрала некоторые, как бросая небольшой партнер.
Без рекламы мы будем вместе болтать о софте, HomeLab и вопросах программирования, а также время от времени будем делиться технической информацией о салоне в группе.
Друзья, которые любят бросать, могут отсканировать код, чтобы добавить друзей. (Пожалуйста, укажите источник и цель, иначе не пройдет проверку)