Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Archive for the ‘Конспекти’ Category

Kubernetes з microk8s

leave a comment »

Kubernetes – це такий docker-compose на стероїдах, що дозволяє керувати кластером машин на яких запускаються контейнери. Infrastructure as a code, і всяке таке. Дивно що в цьому кібернетичному блозі про кібернетіс ще жодного разу не згадувалось, тому варто цю ситуацію виправити.

Інсталяція

Є різні способи поставити локально однонодовий кластер, minikube (з яким в мене не дуже вийшло), і microk8s, який на Ubuntu, і лінукси в яких є менеджер пакетів Snappy, ставиться так:

sudo snap install microk8s --classic

Це встановить кластер і CLI для керування кластером kubectl. Правда вона називатиметься microk8s.kubectl. Якщо ви не ставили kubectl окремо (можна через той же snap install) для керування кластером десь в хмарах, то можна зробити аліас, а якщо ставили – так можна переконфігурити її для роботи з локальним кластером:

microk8s.kubectl config view --raw > ~/.kube/config

Тоді можна наприклад отримати список нодів кластера:

$ kubectl get nodes
NAME                   STATUS    ROLES     AGE       VERSION
bunyk-latitude-e5470   Ready     <none>    3h        v1.14.0

Логічно що у випадку локальної інсталяції це буде лише один комп’ютер.

Щоб перемкнути kubectl на керування наприклад якимось кластером в хмарах Google, за умови що у вас встановлений gcloud, треба виконати:

gcloud container clusters get-credentials [CLUSTER_NAME]

Аддони й панель керування

Ще microk8s має команди для вмикання (enable) і вимикання (disable) аддонів:

microk8s.enable dns dashboard

dns потрібний для багатьох речей, тому його радять вмикати. dashboard – web UI, і InfluxDB з Grafana для моніторингу ресурсів. Щоб його побачити, треба викликати kubectl proxy і перейти за адресою: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login

Сторінка логіну

Там попросять залогінитись, щоб отримати JWT токен для логіну, треба виконати

kubectl -n kube-system get secret
# тоді в списку знайти ім'я що починається з kubernetes-dashboard-token-
# а тоді:
kubectl -n kube-system describe secret kubernetes-dashboard-token-c4bmp

Параметр -n означає простір імен, це щось на зразок директорії де лежать всі об’єкти кластера, наприклад секрети. Це також відображається в шляхах до API, як от /api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ для доступу до сервісу https:kubernetes-dashboard. За замовчуванням kubectl працює з простором імен default, але у випадку вище, нам треба kube-system.

Запуск контейнерів в Kubernetes

Тепер може спробуємо щось запустити? Для цього треба створити под (pod – англійське слово що позначає групу китів. Вони взагалі дивні слова мають для цього. Зграя сов – це parliament, круків – murder). Под – це група контейнерів зі спільною IP адресою, які запускаються а ноді.

Найпростіший спосіб створити под – майже такий самий як запустити контейнер:

kubectl run nginx --image=nginx
# kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
# deployment.apps/nginx created

Це говорить нам що команда створила deployment, але в майбутньому створюватиме лише поди, якщо не передати параметр --generator=run-pod/v1. Чому так пояснюють тут.

Що таке деплоймент? Нуууу, це важко пояснити, і це мене найбільше в Кубернетісі вибішує. Под – це набір конейнерів зі спільною IP адресою, набором портів, диском, і т.д. Под сам по собі запускати в kubernetes не рекомендують, бо після того як в нього трапиться якась аварія наприклад через закінчення пам’яті, його ніхто не перезапустить. Подом керує контролер, одним з яких є контролер що називається ReplicaSet, який задає кількість копій пода що мають бути запущені. І якщо одна з них з якихось причин здихає – запускається нова, щоб кількість завжди відповідала потрібній. Deployment – об’єкт що містить контролер ReplicaSet, і керує версіями імеджів контейнерів в подах цього контролера. Абстракцій як в TCP/IP…

Тим не менш, ми побачимо под в списку:

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7db9fccd9b-w6468   1/1     Running   1          44h

Щоб видалити деплоймент разом з подами дають команду:

kubectl delete deployments/nginx

Трохи складніший спосіб створити под – написати маніфест:

apiVersion: v1 
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - image: nginx
      name: nginx
      ports:
        - containerPort: 80
          name: http
          protocol: TCP

Якщо його записати в файл, наприклад nginx.yaml, то щоб запустити:

kubectl apply -f nginx.yaml 

Як подивитись що всередині пода? Можна прокинути порт, і тоді те що контейнери в поді віддають на якомусь порті буде доступно на порті localhost:

kubectl port-forward nginx 8088:80

Загальне правило для портів в Kubernetes (бо такі пари порт:порт зустрічаються часто) – зліва порти ззовні, справа – всередині. Якщо все працює, на http://localhost:8088 ви маєте побачити сторінку де пише “If you see this page, the nginx web server is successfully installed and working.”

Можна подивитись логи:

$ kubectl logs -f nginx
127.0.0.1 - - [31/Mar/2019:17:00:53 +0000] "GET /favicon.ico HTTP/1.1" 404 154 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"
127.0.0.1 - - [31/Mar/2019:17:01:56 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"

Як змінити те що под показує на головній? Створити якийсь html файл і закинути його командою:

kubectl cp index.html nginx:/usr/share/nginx/html/index.html

Хоча так не прийнято робити, і можна хіба що під час розробки. Краще додати файли в імедж за допомогою Dockerfile.

Запуск сайту

Але давайте вже зробимо щось серйозне на кілька контейнерів. Наприклад як в цій публікації було за допомогою docker compose, тільки за допомогою kubernetes: два контейнери, один з них nginx веб-сервер що віддає статичні файли для фронт-енду, інший – API на python що віддає дані графіків.

Таким чином файли backend.docker, dashboard.html і server.py можна скопіювати собі в проект без змін (звідси). nginx.docker напевне краще називати frontend.docker, і помістити туди лише файли фронт-енду:

FROM nginx

COPY dashboard.html /usr/share/nginx/html/index.html

Конфігурацію nginx ми змінювати не будемо, бо відповідальним за диспетчеризацію запитів між фронт-ендом і бекендом в нас буде штука що називається Ingress.

Тут, на відміну від docker-compose який сам наші контейнери може зібрати, їх треба створити вручну:

docker build -t frontend -f frontend.docker .
docker build -t backend -f backend.docker .

Покладемо конфіг для двох деплойментів у файл site.yaml і скажемо кластеру оновитись (kubectl apply -f site.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
spec:
  selector:
    matchLabels:
      tier: frontend
  replicas: 1
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: frontend
        image: frontend
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment
spec:
  selector:
    matchLabels:
      tier: backend
  replicas: 2 # більше подів для бекенду, бо йому самому може важко.
  template:
    metadata:
      labels:
        tier: backend
    spec:
      containers:
      - name: backend
        image: backend
        ports:
        - containerPort: 80

Один файл в Kubernetes може містити описи багатьох об’єктів, розділені рядком що містить “—“. Так простіше працювати, бо треба менше команд kubectl apply, чи kubectl delete.

Якщо kubectl get pods показує що наші поди мають статус ErrImagePull або ImagePullBackOff, це означає що kubernetes намагається взяти імеджі не з нашого комп’ютера, а з докерхабу.

Виявляється треба ще додати їх в реєстр microk8s. Для цього:

microk8s.enable registry

docker tag backend localhost:32000/backend
docker push localhost:32000/backend
docker tag frontend localhost:32000/frontend
docker push localhost:32000/frontend

Підозрюю що це можна було зробити простіше і швидше якщо зразу називати імеджі правильним тегом. Але майстерність приходить з досвідом. 🙂 В кінцевому результаті ви маєте мати три запущені поди, в двох деплойментах.

І що з того? Поки нічого, бо IP адреси цих подів динамічно міняються (коли їх перезапускають). Для того щоб мати постійний доступ потрібен сервіс, який проксює доступ до подів заданих мітками (labels). Мітки це пари ключ-значення які чіпляються до об’єктів в Kubernetes. Коли ми в описі пода писали:

labels: 
  tier: backend

То це ми йому якраз задавали мітки. Тепер по мітках ми можемо ці об’єкти отримувати:

bunyk@bunyk-thinkpad:~/projects/dockerizing$ kubectl get pods -l tier=frontend
NAME                                   READY   STATUS    RESTARTS   AGE
frontend-deployment-695cfcc94c-jl5hg   1/1     Running   0          3h6m
bunyk@bunyk-thinkpad:~/projects/dockerizing$ kubectl get pods -l tier=backend
NAME                                  READY   STATUS    RESTARTS   AGE
backend-deployment-669d885465-cfbrc   1/1     Running   0          3h6m
backend-deployment-669d885465-nh8lg   1/1     Running   0          3h6m

Так само сервіс має надає доступ з постійним IP до набору подів заданого мітками. Сервіси створюються так:

apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    tier: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  selector:
    tier: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

Сервіс має селектор що визначає за якими подами стежити, і відкриває порти. port – це який порт відкрити, targetPort – це до якого порта в поді приєднатись. За цим треба слідкувати, бо якщо не виконається одна з умов: порт на якому слухає сервер в контейнері == containerPort, containerPort == targetPort сервіса, port сервіса == порт до якого приєднується клієнт, то отримаємо помилку “Connection refused” чи подібну.

Після чергового kubectl apply -f site.yaml можна подивитись які сервіси отримуємо:

$ kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
backend      ClusterIP   10.152.183.69   <none>        80/TCP    110m
frontend     ClusterIP   10.152.183.63   <none>        80/TCP    30m
kubernetes   ClusterIP   10.152.183.1    <none>        443/TCP   8d
$ curl 10.152.183.69/data/1
[1.0997977838,0.6222197737,0.7265324166,1.0475918458,0.8271129655,0.6489646475,0.3625859258,0.7692987393,1.1331619921,1.4889188394]

Бачимо що сервіси які ми створюємо мають тип ClusterIP. Це тип за замовчуванням, і означає що він буде доступний лише з середини кластера. Нам доступний, бо ми ж сидимо на одній єдиній ноді кластера. Крім нього є ще NodePort, LoadBalancer і ExternalName, але розбиратись що це – ми не будемо, бо й без того голова вже пухне (чи у вас ні?).

Залишився ще Ingress. Це штука що дає доступ до сервісів кластера ззовні кластера. Конфігурується так:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: entrypoint
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - http:
      paths:
      - path: /api/(.*)
        backend:
          serviceName: backend
          servicePort: 80
      - path: /(.*)
        backend:
          serviceName: frontend
          servicePort: 80

Перед тим як її створювати, треба ще виконати microk8s.enable ingress.

Тут важливий параметр nginx.ingress.kubernetes.io/rewrite-target, який означає “передавати сервісу запит замінивши URL на той що вказано, підставивши групи з регулярного виразу в path“.

Після застосування цієї конфігурації, на localhost в нас завантажиться фронтенд, пошле через ingress запити до бекенду, і все навіть буде через HTTP 2.0.

Питайтесь якщо що не виходить чи не доходить, в мене теж багато з того що тут написано не виходило зразу, може я вже стикався з тими проблемами що у вас.

Advertisements

Written by bunyk

Квітень 7, 2019 at 00:21

Опубліковано в Кодерство, Конспекти

Tagged with

Python – калькулятор – 2. Sympy

leave a comment »

Намагаюсь тут вивчити матан для функцій багатьох змінних щоб зрозуміти як працюють штучні мережі. Для цього використовую Brilliant.org, такий собі гейміфікований сайт для вивчення математики. І враховуючи те що я там вже за 1200 задач зробив, гейміфікація таки працює.

Задачі там варіюються від “знайди x – ось він”, які можна розв’язувати однією рукою, поки іншою штовхаєш коляску парком. Наприклад:

Капітан Кортевеґ причалив біля пірсу, і його човен здійняв одиночну хвилю. Капітану стало цікаво, погнав за хвилею і на ходу виявив що висота води в залежності від часу і позиції в просторі h(x, t) описується рівнянням:

\frac{\partial h}{\partial t} + \frac{\partial^3 h}{\partial x^3} + 6h\frac{\partial h}{\partial x} = 0

Який найбільший порядок похідної в цьому рівнянні?

І ти такий думаєш: “Та ось він!”. Вписуєш відповідь на одну цифру, і переходиш до наступного завдання.

А потім капітан думає як розв’язувати те рівняння. І дають підказку, що розв’язок – це

h(x, t) = \frac{2}{\left(e^{\frac{1}{2}(x - ct)} + e^{-\frac{1}{2}(x - ct)}\right)^2}

Знайдіть значення c, яке задовольняє вищенаведене рівняння Кортевега – де Фріза.

І ти собі такий, ок, треба знайти кожну похідну, додати і прирівняти до нуля. Добре що дали розв’язок і треба знайти лише константу, бо дифрівняння я все ще не вмію розв’язувати, для того треба вміти інтегрувати. Але все одно без паперу не обійтись. Вдома списую пару листочків:
Прочитати решту цього запису »

Written by bunyk

Березень 3, 2019 at 11:10

Опубліковано в Інструменти, Конспекти

Tagged with ,

Як відсканувати книжку без сканера?

with 2 comments

Є класний додаток для андроїд від Microsoft – Office Lens. Він робить деякі зусилля щодо того аби криво (під якимось кутом) сфотографовані документи виглядали як відскановані. Це звісно важче для книжки, особливо якщо багато сторінок обдерті і не прямокутні, але часто виглядає краще ніж просто фото, і потім обрізати менше.

Знімки програми потім можна буде знайти на пристрої за шляхом /Pictures/Office Lens.

А зліпити їх до купи і перетворити в DJVU – за допомогою скрипта, який я запозичив звідси і трохи модифікував:

import os, glob, subprocess

#Change these to suit your situation=========================
IMGDIR="./" #directory of images to be converted
OUTDJVU = IMGDIR + 'OUT.djvu'

#Don't change these ==========================================
TMPDJVU = IMGDIR + 'TMP.djvu'


#convert jpg to djvu and collate to a single file   
if os.path.exists(OUTDJVU):
    os.remove(OUTDJVU)

for infile in sorted(glob.glob(os.path.join(IMGDIR, '*.jpg'))):
    print('Processing ' + infile)

    #convert jpg to a temp djvu file
    # cmd = 'c44 -decibel 48 ' + '"'+infile+'"' + ' "'+TMPDJVU+'"'
    subprocess.call(['c44', '-decibel', '48', infile, TMPDJVU])
    
    if os.path.exists(OUTDJVU):
        #Add the djvu file to the collated file
        cmd = ['djvm', '-i', OUTDJVU, TMPDJVU]
    else:
        # Create the collated file
        cmd = ['djvm', '-c', OUTDJVU, TMPDJVU]
    subprocess.call(cmd)

#Delete the temporary file
os.remove(TMPDJVU)

print('\nAll files converted and collated successfully')

В результаті можна отримати щось отаке: https://commons.wikimedia.org/wiki/File:%D0%A7%D0%B8%D1%82%D0%B0%D0%BD%D0%BA%D0%B0_%D0%B4%D0%BB%D1%8F_II._%D0%BA%D0%BB._%D1%88%D0%BA._%D1%81.djvu

Written by bunyk

Травень 9, 2018 at 22:53

Опубліковано в Кодерство, Конспекти

Звідки взялось танго?

with 4 comments

У вікіпедії я з командою пишемо статтю яка розповість про танго все в найдрібніших деталях. Поки що можна прочитати як воно виникло. Я знаю (бо бачу статистику переходів) що вам неохота багато читати, тому я викладу тут найцікавіші фрагменти з тої історії. Після чого поділюсь своїми пошуками того як танго з’явилось у Львові, і взагалі складнощами написання статтей на основі пошуку. Бо потрібна допомога, тому що я точно знаю що є люди які знають більше.

Але спершу про те що писало у вікіпедії іспанською. Якщо ви щось чули про те що танго з’явилось в борделях Буенос-Айреса, то вас майже правильно поінформували. Хоча звісно насправді все було ще гірше і ще цікавіше. Отож, справа була портових містах біля гирла річки Ла-Плата:
Прочитати решту цього запису »

Written by bunyk

Травень 7, 2016 at 01:58

Як дописувати до Вікіпедії?

with 6 comments

Мене іноді питають про найелементарніші речі, тому почну з найелементарнішого. Якщо вам щось не подобається у Вікіпедії, і ви знаєте як воно повинно було бути правильно – ось як це виправляється:

Шляхи до редагування Вікіпедії

Шляхи до редагування Вікіпедії

Хоча звісно не все так просто. Іноді ваші зміни можуть не прийняти, тоді варто піти на сторінку обговорення і обговорити всі питаня які виникають.

Також вам крім кнопки “[ред.]” дуже потрібні ще дві речі: сильна цікавість до чогось, і бажання розібратись, та бажання поділитись тим про що довідались з іншими. А далі – деяке знання розмітки, але це не настільки вже й обов’язково. Оформлення вас навчать, головне аби стаття відповідала правилам, тобто мала незалежні від вас джерела і не порушувала авторські права (копіпаст або переклад дозволяється лише з матеріалів під вільними ліцензіями). Тому писати Вікіпедію трохи складніше ніж скачувати реферати з інтернету. 😉 А написати вибрану статтю складніше ніж написати дипломну роботу. Тут трохи про те як пишуться вибрані. Коли сам напишу вибрану – може розповім як і це робилось.

А поки що, розглянемо наприклад як дописувалась стаття про компанію Fujikura, яка відповідає мінімальним вимогам до якості. Той самий підхід працює як і для розширення існуючих статтей, так і для створення нових. Про Fujikura я дізнався завдяки прес-релізу “Міністерства магії”:
Прочитати решту цього запису »

Written by bunyk

Травень 2, 2016 at 13:58

Опубліковано в Інструменти, Конспекти

Tagged with ,

Медитація для двох

with 10 comments

Спершу я розповім про те, як треба цілуватись. Щоб вам стало цікаво і ви прочитали. 😉

Марсіанський метод

Є такий фантастичний роман Хайнлайна (більш відомого за твором “Зоряний десант”, який було екранізовано), що називається “Чужинець на чужині“. От, і його я прочитав черед дуже дивний відгук в інтернеті, який якраз і вчив того як краще цілуватись. Книжка гарна, продовжує традицію Мауглі і Тарзана, тільки цього разу хлопчика виховали не звірі, а марсіани. І окрім теми яку ми розглядаємо, дає ще багато над чим подумати. Але повернемось до поцілунків:
Прочитати решту цього запису »

Written by bunyk

Жовтень 14, 2015 at 21:05

Опубліковано в Конспекти, Психософія

Tagged with ,

… І що ходити вмію забуваю. (Танго чекліст)

with 2 comments

Я потрохи освоююсь на рівні усвідомленої некомпетентності в танго. Мені навіть дозволяють танцювати ходити в парі.

І це дуже цікаво, бо виявляється більше проблем ніж коли я танцюю сам. Я спочатку скаржився що велосипед легше освоювати, бо там кожна помилка миттєво відображається на колінах, ліктях, чолі та інших місцях до яких може дотягнутись асфальт. Але тут теж, якщо бути уважним, можна помітити помилки. І на щастя, вони не настільки фатальні.

Аргентинське танго – це чотиринога істота з двома мозками і однією нервовою системою. І в танцюриста з’явлються додаткові синапси в руках і тулубі. Найбільше мені в ньому подобається те що там тебе справді мовчки уважно слухають. І навіть погоджуються, хоча ти говориш дурниці. Розмова відбувається без слів (точніше і зі словами і з реченнями, але замість звуків там рухи). Зміст приблизно такий:

– Ну що, пішли E2-E4?
– Гаразд.
Прочитати решту цього запису »

Written by bunyk

Червень 26, 2015 at 16:30

Опубліковано в Конспекти

Tagged with , , ,