Русский
Русский
English
Статистика
Реклама

Kuber

Перевод Минимально жизнеспособный Kubernetes

31.07.2020 20:21:00 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса DevOps практики и инструменты.





Если вы это читаете, вероятно, вы что-то слышали о Kubernetes (а если нет, то как вы здесь оказались?) Но что же на самом деле представляет собой Kubernetes? Это Оркестрация контейнеров промышленного уровня? Или Cloud-Native Operating System? Что вообще это значит?

Честно говоря, я не уверен на 100%. Но думаю интересно покопаться во внутренностях и посмотреть, что на самом деле происходит в Kubernetes под его многими слоями абстракций. Так что ради интереса, давайте посмотрим, как на самом деле выглядит минимальный кластер Kubernetes. (Это будет намного проще, чем Kubernetes The Hard Way.)

Я полагаю, что у вас есть базовые знания Kubernetes, Linux и контейнеров. Все, о чем мы здесь будем говорить предназначено только для исследования/изучения, не запускайте ничего из этого в продакшене!

Обзор


Kubernetes содержит много компонент. Согласно википедии, архитектура выглядит следующим образом:



Здесь показано, по крайней мере, восемь компонент, но большинство из них мы проигнорируем. Я хочу заявить, что минимальная вещь, которую можно обоснованно назвать Kubernetes, состоит из трех основных компонент:

  • kubelet
  • kube-apiserver (который зависит от etcd его базы данных)
  • среда выполнения контейнера (в данном случае Docker)


Давайте посмотрим, что о каждом из них говорится в документации (рус., англ.). Сначала kubelet:

Агент, работающий на каждом узле в кластере. Он следит за тем, чтобы контейнеры были запущены в поде.

Звучит достаточно просто. Что насчет среды выполнения контейнеров (container runtime)?

Среда выполнения контейнера это программа, предназначенная для выполнения контейнеров.

Очень информативно. Но если вы знакомы с Docker, то у вас должно быть общее представление о том, что он делает. (Детали разделения ответственностей между средой выполнения контейнеров и kubelet на самом деле довольно тонкие и здесь я не буду в них углубляться.)

И API-сервер?

Сервер API компонент Kubernetes панели управления, который представляет API Kubernetes. API-сервер это клиентская часть панели управления Kubernetes

Любому, кто когда-либо что-либо делал с Kubernetes, приходилось взаимодействовать с API либо напрямую, либо через kubectl. Это сердце того, что делает Kubernetes Kubernetesом мозг, превращающий горы YAML, который мы все знаем и любим (?), в работающую инфраструктуру. Кажется очевидным, что API должен присутствовать в нашей минимальной конфигурации.

Предварительные условия


  • Виртуальная или физическая машина Linux с root-доступом (я использую Ubuntu 18.04 на виртуальной машине).
  • И это все!


Скучная установка


На машину, которую мы будем использовать необходимо установить Docker. (Я не собираюсь подробно рассказывать как работает Docker и контейнеры; если вам интересно, есть замечательные статьи). Давайте просто установим его с помощью apt:

$ sudo apt install docker.io$ sudo systemctl start docker


После этого нам нужно получить бинарники Kubernetes. На самом деле для начального запуска нашего кластера нам нужен только kubelet, так как для запуска других серверных компонент мы сможем использовать kubelet. Для взаимодействия с нашим кластером после того как он заработает, мы также будем использовать kubectl.

$ curl -L https://dl.k8s.io/v1.18.5/kubernetes-server-linux-amd64.tar.gz > server.tar.gz$ tar xzvf server.tar.gz$ cp kubernetes/server/bin/kubelet .$ cp kubernetes/server/bin/kubectl .$ ./kubelet --versionKubernetes v1.18.5


Что произойдет, если мы просто запустим kubelet?

$ ./kubeletF0609 04:03:29.105194    4583 server.go:254] mkdir /var/lib/kubelet: permission denied


kubelet должен работать от root. Достаточно логично, так как ему надо управлять всем узлом. Давайте посмотрим на его параметры:

$ ./kubelet -h<слишком много строк, чтобы разместить здесь>$ ./kubelet -h | wc -l284


Ого, как много опций! К счастью, нам понадобится только пара из них. Вот один из параметров, который нам интересен:

--pod-manifest-path string


Путь к каталогу, содержащему файлы для статических подов, или путь к файлу с описанием статических подов. Файлы, начинающиеся с точек, игнорируются. (УСТАРЕЛО: этот параметр следует устанавливать в конфигурационном файле, передаваемом в Kubelet через опцию --config. Для дополнительной информации см. kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)

Этот параметр позволяет нам запускать статические поды поды, которые не управляются через Kubernetes API. Статические поды используются редко, но они очень удобны для быстрого поднятия кластера, а это именно то, что нам нужно. Мы проигнорируем это громкое предупреждение (опять же, не запускайте это в проде!) и посмотрим, сможем ли мы запустить под.

Сначала мы создадим каталог для статических подов и запустим kubelet:

$ mkdir pods$ sudo ./kubelet --pod-manifest-path=pods


Затем в другом терминале/окне tmux/еще где-то, мы создадим манифест пода:

$ cat <<EOF > pods/hello.yamlapiVersion: v1kind: Podmetadata:  name: hellospec:  containers:  - image: busybox    name: hello    command: ["echo", "hello world!"]EOF


kubelet начинает писать какие-то предупреждения и кажется, что ничего не происходит. Но это не так! Давайте посмотрим на Docker:

$ sudo docker ps -aCONTAINER ID        IMAGE                  COMMAND                 CREATED             STATUS                      PORTS               NAMES8c8a35e26663        busybox                "echo 'hello world!'"   36 seconds ago      Exited (0) 36 seconds ago                       k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_468f670c3c85f        k8s.gcr.io/pause:3.2   "/pause"                2 minutes ago       Up 2 minutes                                    k8s_POD_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_0$ sudo docker logs k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4hello world!


kubelet прочитал манифест пода и дал Dockerу команду запустить пару контейнеров в соответствии с нашей спецификацией. (Если вам интересно узнать про контейнер pause, то это хакерство Kubernetes подробности смотрите в этом блоге.) Kubelet запустит наш контейнер busybox с указанной командой и будет перезапускать его бесконечно, пока статический под не будет удален.

Поздравьте себя. Мы только что придумали один из самых запутанных способов вывода текста в терминал!

Запускаем etcd


Нашей конечной целью является запуск Kubernetes API, но для этого нам сначала нужно запустить etcd. Давайте запустим минимальный кластер etcd, поместив его настройки в каталог pods (например, pods/etcd.yaml):

apiVersion: v1kind: Podmetadata:  name: etcd  namespace: kube-systemspec:  containers:  - name: etcd    command:    - etcd    - --data-dir=/var/lib/etcd    image: k8s.gcr.io/etcd:3.4.3-0    volumeMounts:    - mountPath: /var/lib/etcd      name: etcd-data  hostNetwork: true  volumes:  - hostPath:      path: /var/lib/etcd      type: DirectoryOrCreate    name: etcd-data


Если вы когда-либо работали с Kubernetes, то подобные YAML-файлы должны быть вам знакомы. Здесь стоит отметить только два момента:

Мы смонтировали папку хоста /var/lib/etcd в под, чтобы данные etcd сохранялись после перезапуска (если этого не сделать, то состояние кластера будет стираться при каждом перезапуске пода, что будет нехорошо даже для минимальной установки Kubernetes).
Мы установили hostNetwork: true. Этот параметр, что неудивительно, настраивает etcd для использования сети хоста вместо внутренней сети пода (это облегчит API-серверу поиск кластера etcd).

Простая проверка показывает, что etcd действительно запущен на localhost и сохраняет данные на диск:

$ curl localhost:2379/version{"etcdserver":"3.4.3","etcdcluster":"3.4.0"}$ sudo tree /var/lib/etcd//var/lib/etcd/ member     snap        db     wal         0.tmp         0000000000000000-0000000000000000.wal


Запуск API-сервера


Запустить API-сервер Kubernetes еще проще. Единственный параметр, который надо передать, --etcd-servers, делает то, что вы ожидаете:

apiVersion: v1kind: Podmetadata:  name: kube-apiserver  namespace: kube-systemspec:  containers:  - name: kube-apiserver    command:    - kube-apiserver    - --etcd-servers=http://127.0.0.1:2379    image: k8s.gcr.io/kube-apiserver:v1.18.5  hostNetwork: true


Поместите этот YAML-файл в каталог pods, и API-сервер запустится. Проверка с помощью curl показывает, что Kubernetes API прослушивает порт 8080 с полностью открытым доступом аутентификация не требуется!

$ curl localhost:8080/healthzok$ curl localhost:8080/api/v1/pods{  "kind": "PodList",  "apiVersion": "v1",  "metadata": {    "selfLink": "/api/v1/pods",    "resourceVersion": "59"  },  "items": []}


(Опять же, не запускайте это в продакшене! Я был немного удивлен, что настройка по умолчанию настолько небезопасна. Но я предполагаю, что это сделано для облегчения разработки и тестирования.)
И, приятный сюрприз, kubectl работает из коробки без каких-либо дополнительных настроек!

$ ./kubectl versionClient Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}$ ./kubectl get podNo resources found in default namespace.


Проблема


Но если копнуть немного глубже, то кажется, что что-то идет не так:

$ ./kubectl get pod -n kube-systemNo resources found in kube-system namespace.


Статические поды, которые мы создали, пропали! На самом деле, наш kubelet-узел вообще не обнаруживается:

$ ./kubectl get nodesNo resources found in default namespace.


В чем же дело? Если вы помните, то несколько абзацев назад мы запускали kubelet с чрезвычайно простым набором параметров командной строки, поэтому kubelet не знает, как связаться с сервером API и уведомлять его о своем состоянии. Изучив документацию, мы находим соответствующий флаг:

--kubeconfig string

Путь к файлу kubeconfig, в котором указано как подключаться к серверу API. Наличие --kubeconfig включает режим API-сервера, отсутствие --kubeconfig включает автономный режим.

Все это время, сами того не зная, мы запускали kubelet в автономном режиме. (Если бы мы были педантичны, то можно было считать автономный режим kubelet как минимально жизнеспособный Kubernetes, но это было бы очень скучно). Чтобы заработала настоящая конфигурация, нам нужно передать файл kubeconfig в kubelet, чтобы он знал, как общаться с API-сервером. К счастью, это довольно просто (так как у нас нет проблем с аутентификацией или сертификатами):

apiVersion: v1kind: Configclusters:- cluster:    server: http://127.0.0.1:8080  name: mink8scontexts:- context:    cluster: mink8s  name: mink8scurrent-context: mink8s


Сохраните это как kubeconfig.yaml, убейте процесс kubelet и перезапустите с необходимыми параметрами:

$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml


(Кстати, если вы попытаетесь обратиться к API через curl, когда kubelet не работает, то вы обнаружите, что он все еще работает! Kubelet не является родителем своих подов, подобно Dockerу, он больше похож на управляющего демона. Контейнеры, управляемые kubelet, будут работать, пока kubelet не остановит их.)

Через несколько минут kubectl должен показать нам поды и узлы, как мы и ожидаем:

$ ./kubectl get pods -ANAMESPACE     NAME                    READY   STATUS             RESTARTS   AGEdefault       hello-mink8s            0/1     CrashLoopBackOff   261        21hkube-system   etcd-mink8s             1/1     Running            0          21hkube-system   kube-apiserver-mink8s   1/1     Running            0          21h$ ./kubectl get nodes -owideNAME     STATUS   ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIMEmink8s   Ready    <none>   21h   v1.18.5   10.70.10.228   <none>        Ubuntu 18.04.4 LTS   4.15.0-109-generic   docker://19.3.6


Давайте на этот раз поздравим себя по-настоящему (я знаю, что уже поздравлял) у нас получился минимальный кластер Kubernetes, работающий с полнофункциональным API!

Запускаем под


Теперь посмотрим на что способен API. Начнем с пода nginx:

apiVersion: v1kind: Podmetadata:  name: nginxspec:  containers:  - image: nginx    name: nginx


Здесь мы получим довольно интересную ошибку:

$ ./kubectl apply -f nginx.yamlError from server (Forbidden): error when creating "nginx.yaml": pods "nginx" isforbidden: error looking up service account default/default: serviceaccount"default" not found$ ./kubectl get serviceaccountsNo resources found in default namespace.


Здесь мы видим насколько ужасающе неполна наша среда Kubernetes у нас нет учетных записей для служб. Давайте попробуем еще раз, создав учетную запись службы вручную, и посмотрим, что произойдет:

$ cat <<EOS | ./kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata:  name: default  namespace: defaultEOSserviceaccount/default created$ ./kubectl apply -f nginx.yamlError from server (ServerTimeout): error when creating "nginx.yaml": No APItoken found for service account "default", retry after the token isautomatically created and added to the service account


Даже когда мы создали учетную запись службы вручную, токен аутентификации не создается. Продолжая экспериментировать с нашим минималистичным кластером, мы обнаружим, что большинство полезных вещей, которые обычно происходят автоматически, будут отсутствовать. Сервер Kubernetes API довольно минималистичен, большая часть тяжелых автоматических настроек происходит в различных контроллерах и фоновых заданиях, которые еще не выполняются.

Мы можем обойти эту проблему, установив опцию automountServiceAccountToken для учетной записи службы (так как нам все равно не придется ее использовать):

$ cat <<EOS | ./kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata:  name: default  namespace: defaultautomountServiceAccountToken: falseEOSserviceaccount/default configured$ ./kubectl apply -f nginx.yamlpod/nginx created$ ./kubectl get podsNAME    READY   STATUS    RESTARTS   AGEnginx   0/1     Pending   0          13m


Наконец, под появился! Но на самом деле он не запустится, так как у нас нет планировщика (scheduler) еще одного важного компонента Kubernetes. Опять же, мы видим, что API Kubernetes на удивление глупый когда вы создаете под в API, он его регистрирует, но не пытается выяснить, на каком узле его запускать.

На самом деле для запуска пода планировщик не нужен. Можно вручную добавить узел в манифест в параметре nodeName:

apiVersion: v1kind: Podmetadata:  name: nginxspec:  containers:  - image: nginx    name: nginx  nodeName: mink8s

(Замените mink8s на название узла.) После delete и apply мы видим, что nginx запустился и слушает внутренний IP-адрес:

$ ./kubectl delete pod nginxpod "nginx" deleted$ ./kubectl apply -f nginx.yamlpod/nginx created$ ./kubectl get pods -owideNAME    READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATESnginx   1/1     Running   0          30s   172.17.0.2   mink8s   <none>           <none>$ curl -s 172.17.0.2 | head -4<!DOCTYPE html><html><head><title>Welcome to nginx!</title>


Чтобы убедиться, что сеть между подами работает корректно, мы можем запустить curl из другого пода:

$ cat <<EOS | ./kubectl apply -f -apiVersion: v1kind: Podmetadata:  name: curlspec:  containers:  - image: curlimages/curl    name: curl    command: ["curl", "172.17.0.2"]  nodeName: mink8sEOSpod/curl created$ ./kubectl logs curl | head -6  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed<!DOCTYPE html><html><head><title>Welcome to nginx!</title>


Довольно интересно покопаться в этом окружении и посмотреть, что работает, а что нет. Я обнаружил, что ConfigMap и Secret работают так, как и ожидается, а Service и Deployment нет.

Успех!


Этот пост становится большим, поэтому я собираюсь объявить о победе и заявить, что это жизнеспособная конфигурация, которую можно назвать Kubernetes". Резюмируя: четыре бинарных файла, пять параметров командной строки и всего лишь 45 строк YAML (не так много по стандартам Kubernetes) и у нас работает немало вещей:

  • Поды управляются с помощью обычного Kubernetes API (с несколькими хаками)
  • Можно загружать публичные образы контейнеров и управлять ими
  • Поды остаются живыми и автоматически перезапускаются
  • Сеть между подами в рамках одного узла работает довольно хорошо
  • ConfigMap, Secret и простейшее монтирование хранилищ работает как положено


Но большая часть из того, что делает Kubernetes по-настоящему полезным, все еще отсутствует, например:

  • Планировщик подов
  • Аутентификация / авторизация
  • Несколько узлов
  • Сеть сервисов
  • Кластерный внутренний DNS
  • Контроллеры для учетных записей служб, развертываний, интеграции с облачными провайдерами и большинство других плюшек, которые приносит Kubernetes


Так что же мы на самом деле получили? Kubernetes API, работающий сам по себе, на самом деле, является всего лишь платформой для автоматизации контейнеров. Он не делает много это работа для различных контроллеров и операторов, использующих API, но он обеспечивает консистентную среду для автоматизации.

Узнать подробнее о курсе на бесплатном вебинаре.



Читать еще:


Подробнее..

Перевод Эфемерные тома с отслеживанием емкости хранилища EmptyDir на стероидах

07.09.2020 18:22:46 | Автор: admin

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

Например сервисы для кэширования ограничены по оперативной памяти, но также могут перемещать данные, которые редко используются, в хранилище, работающее медленнее, чем оперативная память, с небольшим влиянием на общую производительность. Другим приложениям нужно знать, что в файлах могут быть некоторые входные данные только для чтения, например настройки или секретные ключи.

В Kubernetes уже есть несколько типов эфемерных томов, но их функциональность ограничена тем, что реализовано в K8s.

Эфемерные тома CSI позволили расширять Kubernetes с помощью драйверов CSI для обеспечения поддержки легковесных локальных томов. Этим способом возможно применять произвольные структуры: настройки, секреты, данные для идентификации, переменные и так далее. CSI драйверы должны быть доработаны для поддержки этой функции Kubernetes, поскольку предполагается, что обычные стандартизированные драйверы не будут работать - но предполагается, что такие тома можно использовать на любом узле, выбранном для пода.

Это может стать проблемой для томов со значительным потреблением ресурсов узла или для хранилища, доступного только на некоторых узлах. Поэтому в Kubernetes 1.19 представлены две новые фунции томов для альфа-тестирования, концептуально похожих на тома EmptyDir:

  • эфемерные тома общего назначения;

  • отслеживание емкости хранилища CSI.

Преимущества нового подхода:

  • хранилище может быть локальным, либо подключаемым по сети;

  • тома могут иметь заданный размер, который не может быть превышен приложением;

  • работает с любыми драйверами CSI, поддерживающими предоставление постоянных томов и (для поддержки отслеживания емкости) реализующими вызов GetCapacity;

  • тома могут иметь некоторые начальные данные, зависящие от драйвера и параметров;

  • все типовые операции с томом (создание снимка состояния, изменение размера и т.п.) поддерживаются;

  • тома можно использовать с любым контроллером приложений, принимающим спецификацию модуля или тома;

  • планировщик Kubernetes сам выбирает подходящие узлы, поэтому больше не нужно обеспечивать и настраивать расширения планировщика и изменять webhooks.

Варианты применения

Таким образом эфемерные тома общего назначения подходят для следующих вариантов применения:

Постоянная память в качестве замены оперативной памяти для memcached

Последние выпуски memcached добавили поддержку использования постоянной памяти (Intel Optane и т.п., прим. переводчика) вместо обычной оперативной памяти. При развертывании memcached через контроллер приложений можно с помощью эфемерных томов общего назначения сделать запрос на выделение тома заданного размера из PMEM с помощью CSI драйвера, например PMEM-CSI.

Локальное хранилище LVM в качестве рабочего пространства

Приложения, работающие с данными, размер которых превышает размер оперативной памяти, могут запрашивать локальное хранилище с размером или метриками производительности, которые не могут обеспечить обычные тома EmptyDir от Kubernetes. К примеру, для этой цели был написан TopoLVM.

Доступ только для чтения для томов с данными

Выделение тома может привести к созданию заполненного тома при:

Эти тома могут быть смонтированы в режиме только для чтения.

Как это работает

Эфемерные тома общего назначения

Ключевой особенностью эфемерных томов общего назначения является новый источник тома, EphemeralVolumeSource, содержащий все поля для создания запроса к тому (исторически это называется запрос на постоянный том, PVC). Новый контроллер в kube-controller-manager просматривает поды, создающие такой источник тома, а затем создает PVC для этих подов. Для CSI драйвера этот запрос выглядит так же, как и остальные, поэтому здесь не нужно особенной поддержки.

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

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

Для того, чтобы быть уверенным в том, что том удаляется вместе с подом, контроллер делает под владельцем запроса на том. Когда под удаляется - отрабатывает штатный механизм уборки мусора, который удаляет как запрос, так и том.

Запросам ставится в соответствие драйвер хранилища через обычный механизм класса хранилища. Хотя классы с немедленным и поздним связыванием (они же WaitForFirstConsumer) поддерживаются, для эфемерных томов имеет смысл использовать WaitForFirstConsumer, тогда планировщик может учесть как использование узла, так и доступность хранилища при выборе узла. Здесь же появляется новая функция.

Отслеживание емкости хранилища

Обычно планировщик не имеет данных о том, где CSI драйвер создаст том. Также у планировщика нет возможности связаться с драйвером напрямую для запроса этой информации. Поэтому планировщик опрашивает узлы до тех пор, пока не найдет тот, на котором тома могут быть доступными (позднее связывание), либо полностью оставит выбор места за драйвером (немедленное связывание).

Новый API CSIStorageCapacity, находящийся в стадии alpha, позволяет хранение нужных данных в etcd, так что они доступны планировщику. В отличие от поддержки эфемерных томов общего назначения при развертывании драйвера нужно включить отслеживание емкости хранилища: external-provisioner должен опубликовать информацию о емкости, получаемую от драйвера через обычный GetCapacity.

Если планировщику надо выбрать узел для пода с непривязанным томом, использующим позднее связывание, а драйвер при развертывании активировал эту функцию устанавливая флаг CSIDriver.storageCapacity, то будут автоматически отброшены узлы, у которых нету достаточно емкости хранилища. Это работает как для эфемерных общего назначения, так и постоянных томов, но не для эфемерных томов CSI, поскольку их параметры не могут быть считаны Kubernetes.

Как обычно, тома с немедленными связыванием создаются перед планированием подов, а их размещение выбирается драйвером хранилища, поэтому при настройке external-provisioner по-умолчанию пропускаются классы хранения с немедленным связыванием, поскольку эти данные все равно не будут использоваться.

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

N.B. Более подробную информацию вы сможете получить, а также безопасно потренироваться на кошках стенде, а в случае совсем уж непонятной ситуации получить квалифицированную помощь техподдержки на интенсивах - Kubernetes База пройдёт 28-30 сентября, а для более продвинутых специалистов Kubernetes Мега 1416 октября.

Безопасность

CSIStorageCapacity

Объекты CSIStorageCapacity находятся в пространствах имен, при раскатке каждого драйвера CSI в своем пространстве имен рекомендуется ограничить права RBAC для CSIStorageCapacity в этом пространстве, поскольку очевидно, откуда приходят данные. В любом случае Kubernetes не проверяет это, а обычно драйверы ставятся в одном пространстве имен, так что в конечном итоге ожидается, что драйвера будут работать и не будут публиковать неверные данные (и тут мне карта поперла, прим. переводчика по мотивам бородатого анекдота)

Эфемерные тома общего назначения

Если пользователи имеют права для создания пода (напрямую или опосредованно) - они также смогут создать эфемерные тома общего назначения даже если у них нет прав на создание запроса на том. А все потому, что проверки прав RBAC применяются к контроллеру, который создает PVC, а не к пользователю. Это основное изменение, которое нужно добавить к учетной записи, перед включением этой функции в кластерах, если ненадежные пользователи не должны иметь права на создание томов.

Пример

Отдельная ветка в PMEM-CSI содержит все нужные изменения для запуска кластера Kubernetes 1.19 внутри виртуальных машин QEMU со всеми фунциями, находящимися на alpha стадии. Код драйвера не изменялся, поменялось только развертывание.

На подходящей машине (Linux, обычный пользователь может использовать Docker, смотрите тут детали) эти команды поднимут кластер и установят драйвер PMEM-CSI:

git clone --branch=kubernetes-1-19-blog-post https://github.com/intel/pmem-csi.gitcd pmem-csiexport TEST_KUBERNETES_VERSION=1.19 TEST_FEATURE_GATES=CSIStorageCapacity=true,GenericEphemeralVolume=true TEST_PMEM_REGISTRY=intelmake start &amp;&amp; echo &amp;&amp; test/setup-deployment.sh

После того, как все отработает, вывод будет содержать инструкции для использования:

The test cluster is ready. Log in with [...]/pmem-csi/_work/pmem-govm/ssh.0, runkubectl once logged in.  Alternatively, use kubectl directly with thefollowing env variable:   KUBECONFIG=[...]/pmem-csi/_work/pmem-govm/kube.configsecret/pmem-csi-registry-secrets createdsecret/pmem-csi-node-secrets createdserviceaccount/pmem-csi-controller created...To try out the pmem-csi driver ephemeral volumes:   cat deploy/kubernetes-1.19/pmem-app-ephemeral.yaml |   [...]/pmem-csi/_work/pmem-govm/ssh.0 kubectl create -f -

Объекты CSIStorageCapacity не подразумевают чтение людьми, так что надо некая обработка. С помощью фильтров шаблона на Golang будут показаны классы хранилищ, в этом примере будут отображены имя, топология и емкость:

$ kubectl get \        -o go-template='{{range .items}}{{if eq .storageClassName "pmem-csi-sc-late-binding"}}{{.metadata.name}} {{.nodeTopology.matchLabels}} {{.capacity}}{{end}}{{end}}' \        csistoragecapacitiescsisc-2js6n map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker2] 30716Micsisc-sqdnt map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker1] 30716Micsisc-ws4bv map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker3] 30716Mi

Отдельный объект имеет такое содержимое:

$ kubectl describe csistoragecapacities/csisc-6cw8jName:         csisc-sqdntNamespace:    defaultLabels:       <none>Annotations:  <none>API Version:  storage.k8s.io/v1alpha1Capacity:     30716MiKind:         CSIStorageCapacityMetadata:  Creation Timestamp:  2020-08-11T15:41:03Z  Generate Name:       csisc-  Managed Fields:    ...  Owner References:    API Version:     apps/v1    Controller:      true    Kind:            StatefulSet    Name:            pmem-csi-controller    UID:             590237f9-1eb4-4208-b37b-5f7eab4597d1  Resource Version:  2994  Self Link:         /apis/storage.k8s.io/v1alpha1/namespaces/default/csistoragecapacities/csisc-sqdnt  UID:               da36215b-3b9d-404a-a4c7-3f1c3502ab13Node Topology:  Match Labels:    pmem-csi.intel.com/node:  pmem-csi-pmem-govm-worker1Storage Class Name:           pmem-csi-sc-late-bindingEvents:                       <none>

Давайте попробуем создать демонстрационное приложение с одним эфемерным томом общего назначения. Содержимое файла pmem-app-ephemeral.yaml:

# This example Pod definition demonstrates# how to use generic ephemeral inline volumes# with a PMEM-CSI storage class.kind: PodapiVersion: v1metadata:  name: my-csi-app-inline-volumespec:  containers:    - name: my-frontend      image: intel/pmem-csi-driver-test:v0.7.14      command: [ "sleep", "100000" ]      volumeMounts:      - mountPath: "/data"        name: my-csi-volume  volumes:  - name: my-csi-volume    ephemeral:      volumeClaimTemplate:        spec:          accessModes:          - ReadWriteOnce          resources:            requests:              storage: 4Gi          storageClassName: pmem-csi-sc-late-binding

После создания, как показано в инструкции выше, у нас появился дополнительный под и PVC:

$ kubectl get pods/my-csi-app-inline-volume -o wideNAME                       READY   STATUS    RESTARTS   AGE     IP          NODE                         NOMINATED NODE   READINESS GATESmy-csi-app-inline-volume   1/1     Running   0          6m58s   10.36.0.2   pmem-csi-pmem-govm-worker1   <none>           <none>$ kubectl get pvc/my-csi-app-inline-volume-my-csi-volumeNAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS               AGEmy-csi-app-inline-volume-my-csi-volume   Bound    pvc-c11eb7ab-a4fa-46fe-b515-b366be908823   4Gi        RWO            pmem-csi-sc-late-binding   9m21s

Владелец PVC - под:

$ kubectl get -o yaml pvc/my-csi-app-inline-volume-my-csi-volumeapiVersion: v1kind: PersistentVolumeClaimmetadata:  annotations:    pv.kubernetes.io/bind-completed: "yes"    pv.kubernetes.io/bound-by-controller: "yes"    volume.beta.kubernetes.io/storage-provisioner: pmem-csi.intel.com    volume.kubernetes.io/selected-node: pmem-csi-pmem-govm-worker1  creationTimestamp: "2020-08-11T15:44:57Z"  finalizers:  - kubernetes.io/pvc-protection  managedFields:    ...  name: my-csi-app-inline-volume-my-csi-volume  namespace: default  ownerReferences:  - apiVersion: v1    blockOwnerDeletion: true    controller: true    kind: Pod    name: my-csi-app-inline-volume    uid: 75c925bf-ca8e-441a-ac67-f190b7a2265f...

Ожидаемо обновилась информация для pmem-csi-pmem-govm-worker1:

csisc-2js6n map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker2] 30716Micsisc-sqdnt map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker1] 26620Micsisc-ws4bv map[pmem-csi.intel.com/node:pmem-csi-pmem-govm-worker3] 30716Mi

Если другому приложению надо будет больше, чем 26620Mi, планировщик не будет брать в расчет pmem-csi-pmem-govm-worker1 при любом раскладе.

Что дальше?

Обе функции все еще в разработке. Было открыто несколько заявок при alpha-тестировании. По ссылкам с предложениями по улучшениям ведется документирование работы, которую надо сделать, чтобы перейти в стадию beta, а также какие альтернативы были уже рассмотрены и отклонены:

Подробнее..

Микросервисы на монолите

15.12.2020 12:20:26 | Автор: admin

Всем привет!

Скажу сразу, эта статья не про очередное переписывание монолита на микросервисы, а о применении микросервисных практик в рамках существующего проекта с использованием интересных, как мне кажется, подходов. Наверное, уже нет смысла объяснять, почему многие проекты активно используют микросервисную архитектуру. Сегодня в IT возможности таких инструментов как Docker, Kubernetes, Service Mesh и прочих сильно меняют наше представление об архитектуре современного приложения, вынуждая пересматривать подходы и переписывать целые проекты на микросервисы. Но так ли это необходимо для всех частей проекта?

В нашем проекте есть несколько систем, которые писались в те времена, когда преимущества микросервисного подхода были не столь очевидны, а инструментов, позволяющих использовать такой подход, было очень мало, и переписывать системы полностью просто нецелесообразно. Для адаптации к новой архитектуре мы решили в части задач использовать асинхронный подход, а также перейти к хранению части данных на общих сервисах. Само приложение при этом осталось на Django (API для SPA). При переходе на k8s деплой приложения был разбит на несколько команд: HTTP-часть (API), Celery-воркеры и RabbitMQ-консьюмеры. Причем было именно три развёртывания, то есть все воркеры, как и консьюмеры, крутились в одном контейнере. Быстрое и простое решение. Но этого оказалось недостаточно, так как это решение не обеспечивало нужный уровень надежности.

Начнем с RabbitMQ-консьюмеров. Основная проблема была в том, что внутри контейнера стартовал воркер, который запускал много потоков на каждый консьюмер, и пока их было пару штук, всё было хорошо, но сейчас их уже десятки. Решение нашли простое: каждый консьюмер вывели в отдельную команду manage.py и деплоим отдельно. Таким образом, у нас несколько десятков k8s-развёртываний на одном образе, с разными параметрами запуска. Ресурсы мы тоже выставляем для каждого консьюмера отдельно, и реальное потребление у консьюмеров достаточно невысокое. В результате для одного репозитория у нас десятки реальных отдельных сервисов в k8s, которые можно масштабировать, и при этом разработчикам намного удобнее работать только с одним репозиторием. То же самое и для развёртываний Сelery.

Если решение с воркерами достаточно простое и очевидное, то с HTTP-частью было немного сложнее. В нашей системе внешний межсервисный API и внутренний для фронтенда были в одном развёртывании с большим лимитом ресурсов и большим количеством инстансов.

Вроде бы рабочее решение? Да, но ДомКлик большой сложный механизм с сотнями сервисов, и иногда выход одного стороннего (вне конкретной системы) сервиса, который используется в одном единственном API-методе, может привести к пробке на сервере uwsgi. К чему это приводит, надеюсь, объяснять не нужно, всё встает или тормозит. В такие моменты должен приходить Кэп и говорить что-то вроде: Нужно было делать отдельные микросервисы и тогда упал бы только тот, что связан с отказавшим внешним сервисом. Но у нас-то монолит.

В Kubernetes есть такой сервис, как Ingress Controller, его основная задача распределять нагрузку между репликами. Но он, по сути, nginx, а значит Ingress Controller можно использовать для того, чтобы роутить запросы на разные сервисы.

Примерно вот так выглядит схема:

Проанализировав наш API, мы разбили его на несколько групп:

  • Внешний API (методы для других сервисов).

  • Внутренний API (методы для фронтенда).

  • Некритичные API-методы, которые зависимы от внешних сервисов, но не влияют на работу системы (статистика, счетчики и т. п.)

Таким образом можно легко создавать новые сервисы. Управлять ресурсами для каждого из них, масштабировать те методы, которые несут большую нагрузку, и получать другие преимущества. Если один из методов перестанет отвечать из-за каких-то внешних причин, то его можно изолировать в отдельное развёртывание и снизить нагрузку на другие части системы.

В конечном итоге наша система, имея один репозиторий и Django под капотом, раздроблена благодаря Kubernetes на 42 сервиса, 5 из которых делят HTTP-трафик, а остальные 37 консьюмеры и Celery-задачи. И в таком виде она может быть актуальна еще пару лет, несмотря на использование относительно старого стека технологий.

Подробнее..

8 Kubernetes-инсайтов, шпаргалка по Curl и онлайн-курс Разработка облачных приложений с микросервисными архитектурами

28.01.2021 20:21:55 | Автор: admin

Мы приготовили для вас много новых инсайтов, записей важных вебинаров, книжек и шпаргалок. Прокачивайте скилы, читайте, смотрите, думайте, применяйте на практике! Станьте частью DevNation!

Начни новое:

Скачать:

  • Шпаргалка по команде Curl
    Примеры использования и синтаксис curl, включая ее использование для запроса API.

  • Шпаргалка по базовым вещам Podman

  • Debezium на OpenShift
    Debezium это распределенная опенсорсная платформа для отслеживания изменений в данных. Благодаря ее надежности и скорости ваши приложения смогут реагировать быстрее и никогда не пропустят события, даже если что-то пойдет на так. Наша шпаргалка поможет с развертыванием, созданием, запуском и обновление DebeziumConnector на OpenShift.
    Загрузить шпаргалку

Чем заняться на досуге:

Мероприятия:

  • 28 января, DevNation: The Show
    Еженедельный часовой чат в прямом эфире. Как обычно, в программе свежие новости и интерактивная игра для участников.

  • DevNation Deep Dive: Kubernetes
    Поспешите, поезд Kubernetes уже отправляется узнайте, как применять, развертывать и использовать Kubernetes для решения задач, с которые вы сталкиваетесь в облаке .

Смотри в записи:

  • Вебинар DevNation Tech Talk Сборка kubectl-плагина с помощью Quarkus
    Разбираем, как с нуля спроектировать kubectl-плагин и собрать его, используя Quarkus. Также рассмотрим удобную работу с Kubernetes-кластером с использованием нативной компиляции для получения сверхбыстрых бинарников и расширений для Kubernetes-клиента.

  • jconf.dev
    Бесплатная виртуальная Java-конференция прямо у вас на экране: четыре техно-трека с нашими комьюнити-экспертами по Java и облаку, 28 углубленных сессий и два потрясающих основных доклада.

  • AnsibleFest
    Два дня интереснейших докладов, демонстраций и практических занятий. Отличная возможность узнать, как разработчики, администраторы и ЛПР в сфере ИТ отвечают на вызовы перемен с помощью гибких технологий автоматизации с открытым кодом, которые позволяют перейти от того, что есть, к тому, что нужно.

  • J4K Conference
    Новая виртуальная конференция по Kubernetes, Java и облаку: 17 сессий с сотрудниками Red Hat, включая доклад Марка Литтла (Mark Little), главного человека в Red Hat по связующему ПО.

По-русски:

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru