cat mindflow.txt > /dev/null – Telegram
cat mindflow.txt > /dev/null
180 subscribers
14 photos
87 links
Поток сознания о программировании, технологиях, жизни и вообще
Download Telegram
Минутка занимательного языкове́дения

Знание латинских (и в чуть меньшей степени - греческих) префиксов - рулит! В частности, при изучении английского языка. Мой любимый пример - prefix + duce, где duce - это производное от (опять же) латинского ducere - вести (to lead).

- produce - производить (pro - это что-то вроде вперед)
- introduce - вводить (intro - это что-то вроде внутрь)
- reduce - сводить [в плане уменьшать] (re - это назад, со временем reduce эволюционировало от простого "возвращать", до "возвращать то, что осталось", т.е. в меньшей степени)
- deduce - делать вывод, выводить [теорему] (de - это вниз, то есть проводить, прослеживать связь до самого низа)
- induce - побуждать (in - внутрь, т.е. приводить кого-то к чему-то)
- conduce - проводить, способствовать (con - вместе, т.е. идти самому вместе с ведомым, вести).

Что самое интересное, связь, похоже, можно прослеживать и дальше. Так, conduct - это производное от conduce - проводить. А кондуктор - это проводник. А если добавить еще один латинский префикс semi-, то получится semiconductor, он же - полупроводник.

Другие полезные примеры:

prefix + voke, где voke - это что-то вроде "звать"

- invoke - призывать
- evoke - вызывать (эмоции, воспоминания)
- provoke - вызывать (на конфронтацию)

prefix + clude, где clude - это что-то вроде "закрывать"

- include - включать
- exclude - исключать
- conclude - заключать, т.е. сводить факты вместе
- preclude - предотвращать

prefix + ject, где ject - это "бросать"

- inject - вводить
- eject - выбрасывать (e- то же, что ex-)
- reject - отбрасывать

А также ingress/egress/progress/egress/congress, revolve/convolve/evolve/involve, и т.д. и т.п... Быстрое гугление привело вот к такой ссылке с достаточно хорошим списком префиксов https://www.englishhints.com/latin-prefixes.html.
Статья Haste Makes Waste вообще о финансах, но начинается она с очень интересного исследования из мира биологии. Ученые брали две одинаковые группы мальков и помещали одну - в слишком холодную, а другую - в слишком теплую воду. В результате, мальки из холодной группы росли немного медленнее среднего для такого вида рыб, а мальки из теплой группы - немного быстрее. Затем мальков из обоих групп помещали в стандартную для них среду и со временем скорость их роста уравнивалась. Но на этом эксперимент не заканчивается! Оказывается, рыбы из холодной группы в итоге жили на 30% дольше среднего, а рыбы из теплой - на 15% меньше. А объясняется такая разница в продолжительности жизни тем, что ускоренный рост на ранних этапах формирования организма отнимает ресурсы у других не менее важных процессов - поддержки и восстановления существующих систем. И наоборот - замедленный рост позволяет больше ресурсов направить на поддержку и восстановление органов. Это все здорово и интересно, но причем здесь software development, спросите вы? А при том, что вероятно эти выводы можно экстраполировать на разработку сложных систем, особенно - разработку с нуля. Если допустить, что у нас есть две примерно одинаковые группы разработчиков делающих два примерно одинаковых проекта, и одна их групп топит за скорость поставки фич (экономя на рефакторинге, тестах, code style, observability, CI/CD и прочих вторичных вещах), а вторая - за качество процессов, то вероятно на первых порах первая группа будет продвигаться в продуктовой разработке намного быстрее, а вторая - намного медленнее среднего по больнице темпа. Но как показывает эксперимент с мальками, при помещении их в одинаковую среду со временем скорость роста уравнивалась в обоих группах. В случае разработки же зачастую определяющих фактором является степень сложности и успешность управление ей. Так как умственные ресурсы разработчиков в обоих группах конечны, а менеджмент всегда топит за скорость заработки фич, то рано или поздно оба проекта окажутся в нормальной среде с примерно одинаковым балансом фиче-делания и рефакторинга & co. Но моя гипотеза состоит в том, что проект первой группы загнется под весом неконтролируемой сложности намного раньше, чем проект из второй группы. В то время, как выработанные медленной группой на начальных этапах подходы и практики позволят второму проекту гармонично расти без саморазрушения из-за детских травм. Т.е. в долгосрочной перспективе неторопливый старт выигрывает. Если конечно у проекта планируется долгая жизнь, но это уже совсем другая история... 😉
TIL (not really): Network Service Mesh - это никакой не service mesh, в традиционном, если уже можно так говорить, его понимании. Istio, linkerd, consul - это оригинальные service mesh-и, оперирурющие на уровнях L4/L7. А Network Service Mesh - это какой-то новый зверь, пытающийся идеологию service mesh притащить на уровни L2/L3 сети. Похоже это нужно всяким telcos и ISP, или в продвинутых ынтерпрайз сетях. Самая адекватная информация по проекту на его же сайте, а пятиминутный поиск в Google показывает, что большинство статей в Интернет об NSM - сплошная вода.
Немного занимательных аналогий из мира Kubernetes
...для тех, кто программировал сервера еще до контейнеров

Container - процесс (или несколько связанных процессов).

Pod - "виртуальная машина" как группа процессов (т.е. контейнеров) разделяющих общие ресурсы (disk, RAM, CPU, network, etc) доступная по некоторому IP адресу. Такие "машины" недолговечны, при перезапуске создается новая идентичная машина с новым IP адресом.

Service - логическая группа "виртуальных машин" с постоянным адресом (IP и DNS). В до-kubernetes эре сервисом бы мог считаться виртуальный server какого-нибудь Nginx reverse proxy (или VirtualHost в Apache сервере) прячущий за своим upstream группу виртуалок переменной численности.

Node - в до-kubernetes эре - это железный сервер, на котором запущена куча виртуалок. А теперь это (зачастую, хоть и не всегда) виртуальная машина, на которой запущена куча pod-ов. Т.е. ушли на один уровень виртуализации глубже.

Service discovery - модное название для задачи нахождения по имени (или IP адресу) сервиса IP адреса конкретной машины из группы машин этого сервиса.

Load balancing - сделай свою service discovery так, чтобы ни один из IP адресов машин сервиса не оказался перегружен запросами.

Service proxy - это как reverse proxy, только тонко размазанный по стороне клиента. Клиенты общаются с конкретными машинами сервисов через service proxy. Service proxy работают локально и распределенно. Условно говоря, сколько клиентов, столько и service proxy-ей. Как и reverse proxy, технология решает задачу service discovery и load balancing.

Kube-proxy - процесс, который превращает каждую ноду кластера в L3/L4 service proxy. Что-то вроде envoy, но на уровне операционной системы (iptables или IPVS). Для каждого контейнера нода, на которой он запущен, является его service proxy.
Это свершилось! Kubernetes отказывается от поддержки Docker в качестве container runtime.

И это на самом деле здорово. Docker - это огромная экосистема с прицелом на удобство использования контейнеров именно человеками (а после покупки их Mirantis'ом и отказа от дальнейшей разработки swarm'а, developer experience стало по факту их единственным фокусом). Kubernetes'у же от container runtime'а нужно буквально три команды - запусти контейнер, покажи статус контейнера, да пошли ему сигнал (утрирую конечно). Поэтому по факту использовать полноценный dockerd смысла очень было мало. Но так уж исторически сложилось... К счастью, еще в далеком 2016 требования Kubernetes'а к container runtime формализовали в виде Container Runtime Interface (CRI); и containerd (то, что на самом деле запускает контейнеры позади dockerd) быстренько добавил поддержку CRI, а RedHat запилили свой аналог - cri-o. Но вот код Kubernetes до сих пор был вынужден поддерживать и милый сердцу CRI и legacy интеграцию с Docker'ом. И вот, настала пора большой чистки.

Fear not, с точки зрения разработчиков ничего не поменялось. Все благополучно продолжат писать свои Dockerfile'ы и запускать контейнеры на любимых маках в старом добром Docker. Стандартизация - сила!
Сказ о том, как в Kubernetes'е работа с сетью устроена

Kubernetes - это не только ц̶е̶н̶н̶ы̶й̶ ̶м̶е̶х̶ про запуск контейнеров, но и про управление сетью. Правда, если вы хотите узнать как работа с этой самой сетью организована, это может оказаться задачкой не из легких. Но у меня есть рецепт! Не факт, что рабочий, но все равно поделюсь.

На мой взгляд, удобно различать следующие "уровни" ответственности:

1. Container networking в рамках одного сервера (ноды). По факту о том, как сделать так, чтобы каждый Pod видел отдельный изолированный network stack и чтобы Pod'ы, расположенные на одной ноде могли общаться между собой "по-сети". В основном решается средствами Linux по виртуализации сети (network namespaces, veth, Linux bridge, вот это все).

2. Pod to Pod networking между разными нодами. Kubernetes классно придумал, что все Pod'ы должны быть адресуемыми по их IP и чтобы никакого "видимого" NAT'а (а если точнее - sNAT'а). Т.е. получатель пакетов от Pod'а видит в source IP тот же самый адрес, что и сам отправитель видит при условном ip addr show на своей стороне. Только вот Kubernetes забыл придумать, как это все организовать. Ну точнее не забыл, а справедливо решил, что сеть у каждого п̶р̶е̶д̶п̶р̶и̶я̶т̶и̶я̶ enterprise устроена на свой манер и поэтому пусть каждый по-своему и добивается нужной адресации. Тут на помощь приходят всякие проекты по виртуализации сети вроде flannel, calico, weave net и т.п.

3. Уровень Service'ов. Kubernetes из коробки предоставляет возможность объединять Pod'ы в логические группы, суть - микросервисы. Но что еще более приятно, задачи service discovery и load balancing решаются тоже из коробки, спасибо kube-proxy.

4. Уровень х̶а̶й̶п̶а̶ service mesh. Несмотря на то, что Service'ы все такие классные прямо из коробки, остается еще очень много нерешенных проблем, общих для каждого из приложений, которые также было бы здорово решить на уровен инфраструктуры. А именно - retry & timeouts, request tracing и прочая observability, mTLS и прочая security, и т.п. И оказывается, что уровень Service'ов вполне себе расширяемый, чему Linkerd и Istio яркое подтверждение.

5. Уровень Ingress. Уровни с 1 по 4 - это в основном о том, как трафик гонять внутри кластеров. А вот заводить трафик из внешнего мира внутрь кластера помогает Ingres. По факту это условный Nginx, который по динамически обновляемым правилам умеет (только) HTTP(S) запросы отправлять нужному Service'у.

Собственно, все. Дальше берем, и по каждому уровню проводим свое собственное расследование. Ах да, чуть не забыл. Работать с сетью в Linux из кода - то еще удовольствие. И поэтому добрые люди написали стандартизованные обертки (CNI) вокруг всяких сетевых комманд вроде iptables. Вот здесь можно посмотерть полный список.
Я тут как-то уже писал про Cloud Native Landscape. Это такая крутая интерактивная визуализация всех CNCF проектов. В какой-то момент я даже поверил, что эта визуализация придает некоторый смысл зонтику CNCF. Но потом передумал и продолжил ломать голову над тем, почему вдруг мы получили такой взрывной рост каких-то cloud-native проектов (да, мутный термин). И тут недавно мне напомнили одну вещь про... микросервисы! Ни для кого не секрет, что на самом деле микросервисы пытаются решать организационные проблемы, а не технические. Типа как код и зоны ответственности поделить между командами и сделать так, чтобы никто не толкался. Конечно, разрезать все на микросервисы! Фишка в том, что это похоже создает целый пласт новых технических проблем. Большие монолиты были дофига сложными, писать код в shared environment было тоже сложно. А теперь вдруг сервисы стали маленькими и никто, кроме твоих товарещей по команде твой код не ломает! То есть жизнь стала вроде как проще. Но похоже есть в природе закон сохранения сложности. И вся эта сложность написания кода для монолита переползла на уровень инфраструктуры. И теперь мы должны думать, как эффетивный RPC уровень замутить, как HTTP запросы трейсить, как логи собирать с сотен контейнеров, service mesh всякие мутить и т.п. Так что похоже, что именно эти технические проблемы, появившиеся из-за перехода на микросервисы, и решают CNCF проекты.

https://iximiuz.com/en/posts/making-sense-out-of-cloud-native-buzz/
TIL: Оказывается, у понятия Cloud Native есть официальное определение! Да еще и переведенное на много-много языков! Вот вариант на русском:

Нативные облачные (Cloud native) технологии позволяют организациям создавать и запускать масштабируемые приложения в современных динамических средах, таких как публичные, частные и гибридные облака. Контейнеры, сервисные сита (service meshes), микросервисы, неизменяемая инфраструктура и декларативные API являются примером такого подхода.

Эти техники позволяют слабосвязанным системам быть устойчивыми, управляемыми и под постоянным контролем. В сочетании с надежной автоматизацией они позволяют инженерам часто и предсказуемо вносить значительные изменения с минимальными усилиями.

Cloud Native Computing Foundation ставит целью адаптировать эту парадигму, развивая и поддерживая экосистему проектов, с открытым исходным кодом, независимую от их поставщиков. Мы демократизируем современные модели, чтобы сделать эти инновации доступными для всех.


https://github.com/cncf/toc/blob/master/DEFINITION.md
Восхищаюсь людьми, которые имеют смелость разворачивать не-managed Kubernetes кластеры для своего production. Со стороны мне всегда казалось, что в этом cloud native зоопарке слишком много moving parts чтобы спасть спокойно. Не столько с технической точки зрения (это наоборот весело, как LEGO собираешь), сколько с точки зрения безопасности. Без выделенной (большой и опытной) команды для поддержки инфраструктуры, обычным dev командам путь только в облака - EKS или GKE, а лучше Fargate или Cloud Run.

Иначе получится что-то вроде этого:

https://twitter.com/iximiuz/status/1358392288708349952
Что-то я давно сюда ничего не писал... Отчасти потому, что последний месяц был по уши в работе над серией статей про Computer Networking для самых маленьких (с картинками).

https://iximiuz.com/en/posts/computer-networking-101/
Для тех, кто поленится открывать статью - небольшое preview.