Ресурсы в Kubernetes. Часть 1: Память (Memory)

Чтобы Kubernetes смог максимально эффективно использовать доступную инфраструктуру и корректно выделить ресурсы, необходимые для работы вашего приложения, вам следует указать требования в ресурсам каждого контейнера. В данный момент есть возможность задавать два типа требований (requests и limits) для двух типов ресурсов — памяти (memory) и процессора (CPU). В данной статье рассмотрим requests и limits применительно к памяти — давайте разберемся!




При описании пода (Pods) для каждого из его контейнеров могут быть заданы требования к ресурсам в следующем формате:




...
resources:
  limits:
    cpu: "2"
    memory: 2Gi
  requests:
    cpu: "2"
    memory: 2Gi
...




Тип требований requests используется в Kubernetes планировщиком для корректного размещения и запуска подов в существующей инфраструктуре, как бы говоря “запусти контейнеры данного пода там, где есть достаточное количество запрощенных ресурсов”. Limits — жесткое ограничение ресурсов, доступных контейнеру и среде его выполнения (тут и далее имеется в виду Docker container runtime). Превышение указанных лимитов (limits) ресурсов зачастую приводит к троттлингу или остановке (termination) контейнера.




Если значение requests для контейнера не указано, то по умолчанию будет использоваться значение установленное в limits. Если же не указано значение limits, то по умолчанию это значение будет равно 0 (если верить документации — неограниченно. На самом деле ограничивается ресурсами узла, на котором запускается под).




Возникает вопрос, стоит ли указывать значения limits больше, чем requests? Если ваше приложение стабильно использует предсказуемый объем оперативной памяти, то устанавливать разные значения параметров requests и limits для памяти нет смысла. В случае с CPU, разница между заданными значениями requests и limits может не устанавливаться (при условии, что эти же ресурсы не используются другими контейнерами и их не нужно “делить”).




Если вы новичок в Kubernetes, для начала лучше всего использовать значения limits точно такие же как и requests — это обеспечит так называемый “гарантированный класс качества сервиса” (Guaranteed QoS class, об этих классах чуть ниже). С другой стороны, класс Burstable QoS потенциально позволяет более эффективно использовать ресурсы инфраструктуры, правда, за счет большей непредсказуемости — например, рост CPU-latency может повлиять на остальные поды/контейнеры, запущенные на том же рабочем узле (ноде).




В Kubernetes QoS классы используются в соответствии с наличием и конфигурацией requests и limits (детальное описание):




  • если для всех контейнеров пода установлены отличные от 0 requests и limits для всех типов ресурсов, и эти значения равны, то под будет принадлежать к классу Guaranteed;



  • если для одного или нескольких контейнера пода установлены отличные от 0 requests и limits для одного или всех типов ресурсов и эти значения не равны, то под будет принадлежать к классу Burstable;



  • если для всех контейнеров пода не установлены значения requests и limits для всех типов ресурсов, то поду будет присвоен класс Best-Effort.




Поды класса Best-Effort обладают наименьшим приоритетом. Они могут использовать любое количество свободной памяти, доступное на рабочем узле, но будут остановлены в первую очередь, если система испытывает недостаток памяти (under memory pressure). Поды класса Burstable обычно имеют некоторое гарантированное количество ресурсов (благодаря requests), но могут использовать больше ресурсов (если такие доступны). Если система испытывает недостаток памяти (и остановка подов с классом Best-Effort не помогла), то поды данного класса, которые превысили значение заданное в requests будут остановлены. Класс Guaranteed обладает максимальным приоритетом, и поды данного класса будут остановлены только если они используют больше ресурсов, чем установлено в limits.




Итак, что же означает память (memory) в данном контексте? В нашем случае, это общее значение размера страниц памяти (Resident set size, RSS) и использования кэша страниц (page cache) контейнерами.




Примечание. В “чистом” docker’е в это значение также входит своп (swap), который предусмотрительно отключен в Kubernetes.




RSS — размер страниц памяти, выделенных процессу операционной системой и в настоящее время находящихся в ОЗУ. Например, для Java процесса это heap (куча), non-heap (стек) память, оff-heap (она же native memory) и т. д.




Кэш страниц — иногда также называемый дисковый кэшем, используется для кеширования блоков с HDD/SSD. Все операции ввода/вывода обычно происходят через этот кэш (из соображений производительности). Чем больше данных читает/записывает ваше приложение на диск, тем больший объем памяти необходим для кэша страниц. Ядро будет использовать доступную память для кэша страниц, но будет освобождать ее, если память понадобится в другом месте/процессе — таким образом производительность вашего приложения может снижаться при недостаточном объеме оперативной памяти.




Исходя из документации docker, можно сказать, что размер кэша страниц, используемых контейнером, может сильно отличаться в зависимости от того, могут ли некоторые файлы “поделены” между несколькими контейнерами, запущенными на одном рабочем узле (достигается благодаря overlayfs storage driver).




Значения параметров requests и limits измеряются в байтах, однако можно использовать и суффиксы. К примеру, настройка памяти JVM Xmx1g (1024³ bytes) будет соответствовать 1Gi в спецификации контейнера.




Ограничения по памяти (limits) с точки зрения Kubernetes считаются “несжимаемыми” (non-compressible), следовательно при превышении этих ограничений троттлинг невозможен — ядро будет агрессивно очищать кэш страниц (для освобождения ресурсов / достижения желаемого состояния рабочего узла) и контейнеры к конце концов могут быть остановлены (прерваны) хорошо известным Linux Out of Memory (OOM) Killer.




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




На этом все, в следующей статье рассмотрим requests и limits применительно к использованию процессора (CPU).



2023-01-03T00:07:01
DevOps

Pidgin: все о приложении для обмена мгновенными сообщениями в 2023 году

Pidgin: все о приложении для обмена мгновенными сообщениями в 2023 году

Pidgin: все о приложении для обмена мгновенными сообщениями в 2023 году

Продолжая наши Серия постов 2022 года, куда мы обращаемся дистрибутивы и приложения GNU/Linux, чей последний раз мы исследовали это было Много лет назад, у нас сегодня пиджин. Который хорошо известен и используется приложение для обмена мгновенными сообщениями.

Также с начала года получил новое обновление, для которого мы считаем идеальным обновить на благо всех, что предлагает текущие и новые приложение для обмена мгновенными сообщениями «Пиджин, в 2023 году».



Читать

Kubernetes — установить Cosnul

Consul — это децентрализованный отказоустойчивый discovery-сервис от компании HashiCorp (которая разрабатывает такие продукты как Vagrant, TerraForm, Otto, Atlas и другие).




Consul является децентрализованным сервисом, то есть Consul agent устанавливается на каждый хост и является полноправным участником кластера. Таким образом, сервисам не нужно знать адрес discovery в нашей сети, все запросы к discovery выполняются на локальный адрес 127.0.0.1.




В этом руководстве вы развернете центр обработки данных Consul с официальным чартом Helm.
Вам не нужно обновлять какие-либо значения в чарте Хелма для базовой установки.
Однако вы можете создать файл значений с параметрами, чтобы разрешить доступ к пользовательскому интерфейсу Consul.
Предупреждение о безопасности. Это руководство не для производственного использования. По умолчанию на диаграмме будет установлена небезопасная конфигурация Consul. Пожалуйста, обратитесь к документации Kubernetes, чтобы определить, как вы можете обеспечить безопасность Consul на Kubernetes в производстве. Кроме того, настоятельно рекомендуется использовать правильно защищенный кластер Kubernetes или убедиться, что вы понимаете и включаете рекомендуемые функции безопасности.
Для успешного выполнения этого руководства у вас должен быть существующий кластер Kubernetes и локально настроенные Helm и kubectl.




Разворачиваем Consul




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




По умолчанию в чарте будут установлены три сервера Consul и клиент на всех узлах Kubernetes.




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




Скачать Helm чарт




Во-первых, вам нужно будет клонировать официальный Helm чарт из репозитория Gashub от HashiCorp.




$ git clone https://github.com/hashicorp/consul-helm.git




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




Ознакомьтесь с документацией по чартам Helm, чтобы узнать больше информации.




Установка Consul через Helm




Чтобы развернуть Consul, вы должны быть в том же каталоге, что и чарт.




$ cd consul-helm




Теперь вы можете развернуть Консул с помощью установки helm.




Это позволит развернуть три сервера и агента на всех узлах Kubernetes.




Процесс должен быть быстрым, менее 5 минут.




$ helm install .



NAME:   mollified-robin LAST DEPLOYED: Mon Feb 25 15:57:18 2019 NAMESPACE: default STATUS: DEPLOYED

NAME                             READY  STATUS             RESTARTS  AGE

mollified-robin-consul-25r6z     0/1    ContainerCreating  0         0s

mollified-robin-consul-4p6hr     0/1    ContainerCreating  0         0s

mollified-robin-consul-n82j6     0/1    ContainerCreating  0         0s

mollified-robin-consul-server-0  0/1    Pending            0         0s

mollified-robin-consul-server-1  0/1    Pending            0         0s

mollified-robin-consul-server-2  0/1    Pending            0         0s




Вывод, показщанный выше был уменьшен для удобства чтения.




Однако вы можете видеть, что в этом кластере Kubernetes с тремя узлами есть три сервера Consul и три клиента Consul.




Доступ к Consul UI




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




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




Создайте файл значений




Сначала создайте файл значений, который можно передать в командной строке при обновлении.




# values.yaml

global:

  datacenter: hashidc1

syncCatalog:

  enabled: true

ui:

  service:

    type: 'LoadBalancer'

server:

  affinity: |

    podAntiAffinity:

      requiredDuringSchedulingIgnoredDuringExecution:

        - labelSelector:

            matchLabels:

              app: {{ template "consul.name" . }}

              release: "{{ .Release.Name }}"

              component: server

        topologyKey: kubernetes.io/hostname




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




Параметры синхронизации каталога позволят вам увидеть сервисы Kubernetes в пользовательском интерфейсе Consul.




Инициируйте обновление




Наконец, инициируйте обновление с помощью helm upgrade и флага -f, который передается в ваш новый файл значений.




Этот процесс также должен быть быстрым, менее минуты.




$ helm upgrade consul -f values.yaml




Теперь вы можете использовать kubectl get services для определения внешнего IP-адреса вашего пользовательского интерфейса Consul.




$ kubectl get services

NAME                            TYPE           CLUSTER-IP     EXTERNAL-IP             PORT(S)        AGE

consul                          ExternalName   <none>         consul.service.consul   <none>         11d

kubernetes                      ClusterIP      122.16.14.1    <none>                  443/TCP        137d

mollified-robin-consul-dns      ClusterIP      122.16.14.25   <none>                  53/TCP,53/UDP  13d

mollified-robin-consul-server   ClusterIP      None           <none>                  8500/TCP       13d

mollified-robin-consul-ui       LoadBalancer   122.16.31.395  36.276.67.195           8




Кроме того, вы можете использовать kubectl get pods для просмотра нового процесса синхронизации.




Процесс синхронизации каталога по умолчанию синхронизирует службы Consul и Kubernetes в обоих направлениях.




$ kubectl get pods

NAME                                                 READY   STATUS      RESTARTS   AGE

mollified-robin-consul-d8mnp                          1/1     Running     0         15d

mollified-robin-consul-p4m89                          1/1     Running     0         15d

mollified-robin-consul-qclqc                          1/1     Running     0         15d

mollified-robin-consul-server-0                       1/1     Running     0         15d

mollified-robin-consul-server-1                       1/1     Running     0         15d

mollified-robin-consul-server-2                       1/1     Running     0         15d

mollified-robin-consul-sync-catalog-f75cd5846-wjfdk   1/1     Running     0




Служба должна была добавитьcя по имени развертывания consul-ui.





Обратите внимание, вам не нужно указывать порт при доступе к панели мониторинга.




Доступ к Consul




Помимо доступа к Consul с помощью пользовательского интерфейса, вы можете управлять Consul с помощью HTTP API или напрямую подключаясь к поду с помощью kubectl.




Kubectl




Для доступа к каталогу pod и data вы можете запустить kodectl в pod для запуска сеанса оболочки.




$ kubectl exec -it mollified-robin-consul-server-0 /bin/sh




Это позволит вам перемещаться по файловой системе и запускать консольные команды CLI на поде.




Например, вы можете просмотреть Consul members.




$ consul members

Node                                   Address           Status  Type    Build  Protocol  DC        Segment

mollified-robin-consul-server-0        172.20.2.18:8301  alive   server  1.4.2  2         hashidc1  <all>

mollified-robin-consul-server-1        172.20.0.21:8301  alive   server  1.4.2  2         hashidc1  <all>

mollified-robin-consul-server-2        172.20.1.18:8301  alive   server  1.4.2  2         hashidc1  <all>

gke-tier-2-cluster-default-pool-leri5  172.20.1.17:8301  alive   client  1.4.2  2         hashidc1  <default>

gke-tier-2-cluster-default-pool-gnv4   172.20.2.17:8301  alive   client  1.4.2  2         hashidc1  <default>

gke-tier-2-cluster-default-pool-zrr0   172.20.0.20:8301  alive   client  1.4.2




Consul HTTP API




Вы можете использовать Consul HTTP API , связавшись с локальным агентом, работающим на узле Kubernetes.




Вы можете прочитать документацию, если хотите узнать больше об использовании Consul HTTP API с Kubernetes.




Источник: https://sidmid.ru/kubernetes-установить-cosnul/



2023-01-02T06:18:22
DevOps

Kubernetes — запуск kafka

kubectl create ns kafka




git clone https://github.com/confluentinc/cp-helm-charts.git




cd cp-helm-charts/
helm dependency update charts/cp-kafka/




[root@prod-vsrv-kubemaster1 cp-helm-charts]# vim charts/cp-zookeeper/values.yaml




persistence:

  enabled: true

  ## Size for Data dir, where ZooKeeper will store the in-memory database snapshots.

  dataDirSize: 5Gi

  dataDirStorageClass: "nfs-storageclass"



  ## Size for data log dir, which is a dedicated log device to be used, and helps avoid competition between logging and snaphots.

  dataLogDirSize: 5Gi

  dataLogDirStorageClass: "nfs-storageclass"





[root@prod-vsrv-kubemaster1 cp-helm-charts]# vim charts/cp-kafka/values.yaml




persistence:

  enabled: true

  size: 1Gi

  storageClass: "nfs-storageclass"




helm install confluent ./charts/cp-kafka/ —values ./charts/cp-kafka/values.yaml -n kafka




zookeeper доступ по адресу:




confluent-cp-zookeeper.kafka.svc.test.local:2181




поставим теперь kafka-manager:




helm repo add stable https://kubernetes-charts.storage.googleapis.com




helm pull stable/kafka-manager




tar -xvf kafka-manager-2.3.5.tgz




rm -rf kafka-manager-2.3.5.tgz




[root@prod-vsrv-kubemaster1 cp-helm-charts]# vim kafka-manager/values.yaml




zkHosts: "confluent-cp-zookeeper.kafka.svc.test.local:2181"





basicAuth:

  enabled: true

  username: "admin"

  ## Defaults to a random 10-character alphanumeric string if not set

  ##

  password: "admin"







ingress:

  enabled: true

  annotations: {}

    # kubernetes.io/ingress.class: nginx

    # kubernetes.io/tls-acme: "true"

  path: /

  hosts:

    - kafka.prod.test.local







[root@prod-vsrv-kubemaster1 cp-helm-charts]# helm install kafka-manager kafka-manager/ —values kafka-manager/values.yaml -n kafka




далее настраиваем в панельке кластер, в качестве адреса для zookeeper указываем:
confluent-cp-zookeeper.kafka.svc.test.local:2181













проверим работу. Для этого создадим под откуда будем подключаться:




cat test-pod.yaml




apiVersion: v1

kind: Pod

metadata:

  name: kafka-client

  namespace: kafka

spec:

  containers:

  - name: kafka-client

    image: confluentinc/cp-enterprise-kafka:6.0.1

    command:

      - sh

      - -c

      - "exec tail -f /dev/null"





Запускаем:
kubectl apply -f test-pod.yaml




Подключаемся:
kubectl exec -it kafka-client -n kafka /bin/bash




Смотрим список топиков:




[appuser@kafka-client ~]$ kafka-topics —bootstrap-server confluent-cp-kafka-headless:9092 —list
__consumer_offsets
_confluent-metrics
test-ropic




создаём producer и вкидываем через него несколько проверочных строк:




[appuser@kafka-client ~]$ kafka-console-producer —broker-list confluent-cp-kafka-0.confluent-cp-kafka-headless.kafka:9092 —topic test-ropic
>sdfsf
>sdfsf
>rtert
>hyhy




Читаем эти сообщения с помощью consumer




[appuser@kafka-client ~]$ kafka-console-consumer —bootstrap-server confluent-cp-kafka-0.confluent-cp-kafka-headless.kafka:9092 —topic test-ropic —from-beginning
sdfsf
sdfsf
rtert
hyhy




Создаём topic:
[appuser@kafka-client ~]$ kafka-topics —bootstrap-server confluent-cp-kafka-headless:9092 —topic NEW-TEST-TOPIC —create —partitions 1 —replication-factor 1 —if-not-exists
Created topic NEW-TEST-TOPIC.




проверяем:
[appuser@kafka-client ~]$ kafka-topics —bootstrap-server confluent-cp-kafka-headless:9092 —list
NEW-TEST-TOPIC
__consumer_offsets
_confluent-metrics
new-test-topic




Удаляем:
[appuser@kafka-client ~]$ kafka-topics —bootstrap-server confluent-cp-kafka-headless:9092 —topic NEW-TEST-TOPIC —delete —if-exists




Проверяем:
[appuser@kafka-client ~]$ kafka-topics —bootstrap-server confluent-cp-kafka-headless:9092 —list
__consumer_offsets
_confluent-metrics
new-test-topic




Источник: https://sidmid.ru/kubernetes-запуск-kafka/



2023-01-02T06:16:04
DevOps

Kubernetes — пример использования RBAC

Начиная с Kubernetes 1.6, политики RBAC включаются по умолчанию. Политики RBAC имеют жизненно важное значение для правильного управления вашим кластером, поскольку они позволяют вам указывать, какие типы действий разрешены для конкретного пользователя и его роли в вашей организации.




Примеры включают:




  • Защиту кластера путем разрешения привилегированные действий (например, доступ к секретам) только администраторам.



  • Включение принудительной аутентификации пользователей в вашем кластере.



  • Ограничение создания ресурсов (т.к. контейнеры, постоянные диски, развертывания) для конкретных пространств имен. Вы также можете использовать квоты, чтобы гарантировать, что использование ресурсов ограничено и находится под контролем.



  • Разрешение пользователям просматривать ресурсы только в своем авторизованном пространстве имен, что позволяет изолировать ресурсы внутри вашей организации (например, между отделами или департаментами).




В следствие того, что в последних версиях Kubernetes RBAC включен по умолчанию, вы, возможно, уже обнаружили специфические ошибки при настройке решений по сетевой виртуализации (например, flunneld) или деплое Helm в вашем кластере. Обычно такие ошибки выглядят следующим образом:




the server does not allow access to the requested resource




ща рассмотрим как правильно работать с RBAC, чтобы вы могли решать такого рода проблемы.




API объекты RBAC




Одной из основных функций Kubernetes является то, что все его ресурсы представляют собой моделируемые API объекты, которые позволяют выполнять с ними операции CRUD (Create, Read, Update, Delete). Примерами ресурсов являются:




  • Pods



  • Deployments



  • Namespaces



  • Secrets



  • Replicasets



  • PersistentVolumes



  • ConfigMaps



  • Nodes




Примеры возможных операций над этими ресурсами:




  • create



  • get



  • delete



  • list



  • update



  • edit



  • watch



  • exec




Высокоуровневые ресурсы связаны с группами API (например, Pod относится к core группе API, а Deployments относятся к группе API apps). Дополнительные сведения обо всех доступных ресурсах, операциях и группах API см. в официальном справочнике API Kubernetes.




Для управления RBAC в Kubernetes, помимо ресурсов и операций, нам нужны следующие элементы:




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



  • Roles и ClusterRoles. Оба состоят из правил. Разница между Role и ClusterRole – это область применимости: в Role правила применимы к одному пространству имен, тогда как ClusterRole правила распространяются на весь кластер, поэтому правила применяются к нескольким пространствам имен. ClusterRoles также могут определять правила для ресурсов уровня кластера (например, узлы). Roles и ClusterRoles мапятся на API ресурсы внутри нашего кластера.



  • Subjects. Субъекты соответствуют объектам, которые пытаются выполнить операции в кластере. Существует три типа субъектов:



  • User Accounts (учетные записи пользователей): глобальны и предназначены для людей или процессов, живущих вне кластера. В кластере Kubernetes нет связанного с этим субъектом объекта API ресурса.



  • Service Accounts (учетные записи служб). Этот вид учетной записи предназначен для внутрикластерных процессов, запущенных в Pod-ах вашего кластера, которым необходимо получить доступ к API кластера.



  • Groups (группы). Группы используется для ссылки на сразу несколько учетных записей.Некоторые группы, такие как cluster-admin (объясняется в последующих разделах), создаются по умолчанию.



  • RoleBindings (связи ролей) и ClusterRoleBindings (связи кластерных ролей): как видно из названия сущностей, они связывают субъекты с ролями (т.е. операциями, которые может выполнять конкретный пользователь). Что касается их разницы с ClusterRoles, разница заключается в области применимости: RoleBinding применяет правила внутри одного пространства имен, тогда как ClusterRoleBinding применяет их во всех пространствах имен кластера.




Вы можете найти примеры каждого элемента API в официальной документации Kubernetes.




Создание пользователя с ограничениями по пространству имен




В этом примере мы создадим следующую учетную запись пользователя:




  • Имя пользователя: user1



  • Группа: deparment1




Мы добавим необходимые политики RBAC, чтобы этот пользователь мог полностью управлять развертываниями (т.е. использовать команду kubectl run) только внутри пространства имен office. В конце мы проверим созданные политики, чтобы убедиться, что они работают так, как мы их определили.




Создание пространства имен




Выполните команду kubectl create для создания пространства имен office. Команду необходимо запустить от пользователя Kubernetes admin:




[root@kub-master-1 ~]# kubectl create namespace office




Создание пользователя




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




  • Создайте закрытый ключ для своего пользователя. В этом примере мы назовем файл user1.key[root@kub-master-1 ~]# openssl genrsa -out user1.key 2048



  • Создайте запрос сертификата user1.csr, используя только что созданный вами закрытый ключ (user1.key). Убедитесь, что вы указали свое имя пользователя и группу в разделе -subj(CN для имени пользователя и O для группы). Как упоминалось ранее, мы будем использовать имя user1 и deparment1 в качестве группы:




[root@kub-master-1 ~]# openssl req -new -key user1.key -out user1.csr -subj «/CN=user1/O=deparment1»




  • Найдите свой центр сертификации кластера Kubernetes (CA). Он будет отвечать за утверждение запроса и получение необходимого сертификата для доступа к API кластера. Обычно он располагается в директории /etc/kubernetes/pki/. В случае Minikube это будет ~/.minikube/. Убедитесь, что файлы ca.crt и ca.key существуют в соответствующей директории.




[root@kub-master-1 ~]# ll /etc/kubernetes/pki/

total 156

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 admin-kub-master-1-key.pem

-rw-------. 1 kube kube-cert 1399 Mar  8 18:58 admin-kub-master-1.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 admin-kub-master-2-key.pem

-rw-------. 1 kube kube-cert 1399 Mar  8 18:58 admin-kub-master-2.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 admin-kub-master-3-key.pem

-rw-------. 1 kube kube-cert 1399 Mar  8 18:58 admin-kub-master-3.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 apiserver-key.pem

-rw-------. 1 kube kube-cert 2444 Mar  8 18:58 apiserver.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 ca-key.pem

-rw-------. 1 kube kube-cert 1090 Mar  8 18:58 ca.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 front-proxy-ca-key.pem

-rw-------. 1 kube kube-cert 1111 Mar  8 18:58 front-proxy-ca.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 front-proxy-client-key.pem

-rw-------. 1 kube kube-cert 1367 Mar  8 18:58 front-proxy-client.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 kube-controller-manager-key.pem

-rw-------. 1 kube kube-cert 1375 Mar  8 18:58 kube-controller-manager.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 kube-proxy-kub-master-1-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 kube-proxy-kub-master-1.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 kube-proxy-kub-master-2-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 kube-proxy-kub-master-2.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 kube-proxy-kub-master-3-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 kube-proxy-kub-master-3.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 kube-proxy-kub-worker-1-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 kube-proxy-kub-worker-1.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 kube-proxy-kub-worker-2-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 kube-proxy-kub-worker-2.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 kube-scheduler-key.pem

-rw-------. 1 kube kube-cert 1363 Mar  8 18:58 kube-scheduler.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 node-kub-master-1-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 node-kub-master-1.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 node-kub-master-2-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 node-kub-master-2.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 node-kub-master-3-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 node-kub-master-3.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 node-kub-worker-1-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 node-kub-worker-1.pem

-rw-------. 1 kube kube-cert 1679 Mar  8 18:58 node-kub-worker-2-key.pem

-rw-------. 1 kube kube-cert 1273 Mar  8 18:58 node-kub-worker-2.pem

-rw-------. 1 kube kube-cert 1675 Mar  8 18:58 service-account-key.pem





  • Создайте сертификат user1.crt, одобрив запрос на подпись сертификата, user1.csr, сделанный ранее. Убедитесь, что вы заменили CA_LOCATION в примере команды ниже на местоположение вашего актуального CA кластера. Сертификат будет действителен в течение 500 дней:




$ openssl x509 -req -in user1.csr -CA CA_LOCATION/ca.crt -CAkey CA_LOCATION/ca.key -CAcreateserial -out user1.crt -days 500




в моём случае это команда:




[root@kub-master-1 ~]# openssl x509 -req -in user1.csr -CA /etc/kubernetes/pki/ca.pem -CAkey /etc/kubernetes/pki/ca-key.pem -CAcreateserial -out user1.crt -days 500
и её вывод:




Signature ok

subject=/CN=user1/O=deparment1

Getting CA Private Key




  • Сохраните как user1.crt, так и user1.key где-нибудь в безопасном месте (например, в директории ~/.kube/certs/):
    $ mkdir ~/.kube/certs
    $ cp user1.crt ~/.kube/certs
    $ cp user1.key ~/.kube/certs



  • добавьте новый контекст с новыми учетными данными для вашего кластера Kubernetes.
    [root@kub-master-1 ~]# kubectl config set-credentials user1 —client-certificate=$HOME/.kube/certs/user1.crt —client-key=$HOME/.kube/certs/user1.keyСмотрим имя кластера:
    [root@kub-master-1 ~]# kubectl config view -o jsonpath='{«Cluster nametServern»}{range .clusters[*]}{.name}{«t»}{.cluster.server}{«n»}{end}’



  • добавьте новый контекст с новыми учетными данными для вашего кластера Kubernetes.
    [root@kub-master-1 ~]# kubectl config set-credentials user1 —client-certificate=$HOME/.kube/certs/user1.crt —client-key=$HOME/.kube/certs/user1.keyСмотрим имя кластера:
    [root@kub-master-1 ~]# kubectl config view -o jsonpath='{«Cluster nametServern»}{range .clusters[*]}{.name}{«t»}{.cluster.server}{«n»}{end}’



  • [root@kub-master-1 ~]# kubectl config set-context user1-context —cluster=cluster.local —namespace=office —user=user1




добавим теперь пользователя  под которым будем работать:




[root@kub-master-1 ~]# adduser test
[root@kub-master-1 ~]# mkdir -p /home/test/.kube/certs
[root@kub-master-1 ~]# cp /root/.kube/certs/user1.* /home/test/.kube/certs/




смотрим файл:
[root@kub-master-1 ~]# cat /root/.kube/config




нас интересует:




certificate-authority-data
и
server




и создаём файл следующего вида:




[root@kub-master-1 ~]# cat /home/test/.kube/config




apiVersion: v1

clusters:

- cluster:

    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrVENDQWVHZ0F3SUJBZ0lKQUl0L0JPdHQrWUhVTUEwR0NTcUdTSWIzRFFFQkN3VUFNQkl4RURBT0JnTlYKQkFNTUIydDFZbVV0WTJFd0lCY05NakV3TXpBNE1USTFPREE1V2hnUE1qRXlNVEF5TVRJeE1qVTRNRGxhTUJJeApFREFPQmdOVkJBTU1CMnQxWW1VdFkyRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCCkFRQ2FRZk9nbzdpZ3oyV0QyWEd1dzNSd2x6VUhxcjRFT2k1d0wwaWZvVnBaWXBzZk9ORlE0ME90akVEQUVsUXYKSW5YeW1iVEdQN0w0QUFIZlNFZWRULysyUFh4NmV6VDV3WlozbGg5WWt1UmhHcWZUamtsVXN6LzVoOVpNekhzNgpwWWVyNzVJQUZyRXlxSDFtR2pwM0FjaUZmNUU1TmFvczJXQ21HWklPbmdqTmVUMElXdHFGQjNVTzNMSTkxS0JJCi9tNWRPZTh6elJjVWxBODltTTFhTzBBSTZEYWNUbXRiVllDcklwVW01cE45UHFWSjVZNGorTXQvSlpISTlnRisKMUsvUW5hb0owVm5udkl0T0dJbzhaSlZ5ellTVTlNZlltcmE0RkhvYmQzaGsrN1RBZ3lNRWJlOERLdUlpRENzKwozOVhEaXByL0FaRHVnYnZuOVJYV0M5WnhBZ01CQUFHalVEQk9NQjBHQTFVZERnUVdCQlJaUUtYWFdJTlpCSkJzCkZERTlpTTYydHJuSDhUQWZCZ05WSFNNRUdEQVdnQlJaUUtYWFdJTlpCSkJzRkRFOWlNNjJ0cm5IOFRBTUJnTlYKSFJNRUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBQVgrakdVT3k4R1lEKzh6M244SFV6V25XeAp0RWRrdEJEakxVcjB2anovN0lVRDU0R0MrRm5FY0ZybXZMVHhkYWNNNXNEQmo2MHhscjh2dG9mbDFzekJxMjVVCnFUWTRveDZ1VzUreGlBU1hqNFhHeEZtUG8rUzVGUi9EZjA3clBJZ3QzWWdEYkZHUUw5aHh4UXdKMDdVR3JKa08KM0QyNjYzUDJ4WTBndGdyYzY0UG5EWDBuZ1VxSzJ0akxsKy9qU1c1MHdnWURvbUlYNjlyWUxyMElzOWpYZmk0OQpFK3ljb2ZURElSeUFWT2U2QTBXbmQ2MFhlMEZPdUdqUVZHcWRKeVhBeVhrOW1FK1lNRk9kS09PZjMxNmtYeW90ClppNmE3bnZtYjhFSWpXZWFpd1JwQzNGOEgrdHRFYzFmSVdvNkoralJZTlFjME5BaFhZbFRwRmp6blA0TAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==

    server: https://192.168.1.201:6443

  name: cluster.local

contexts:

- context:

    cluster: cluster.local

    namespace: office

    user: user1

  name: user1-context

kind: Config

preferences: {}

users:

- name: user1

  user:

    client-certificate: certs/user1.crt

    client-key: certs/user1.key




не забываем указать certificate-authority-data и server




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




[test@kub-master-1 ~]$ kubectl get pod -n my-site
The connection to the server localhost:8080 was refused — did you specify the right host or port?
данная ошибка логична потому что мы не указали context




[test@kub-master-1 ~]$ kubectl —context=user1-context get pods -n my-site
Error from server (Forbidden): pods is forbidden: User «user1» cannot list resource «pods» in API group «» in the namespace «my-site»




а вот эта как рас та ошибка что и должна прилетать Forbidden




Создание роли для управления развертываниями




Создайте файл role-deployment-manager.yaml с приведенным ниже содержимым. В этом yaml-файле мы создаем правило, которое позволяет пользователю выполнять несколько операций с Deployments, Pods и ReplicaSets (необходимых для создания Deployment), которые принадлежат к core (выделены “” в yaml-файле) extensions группам API:




[root@kub-master-1 ~]# cat role-deployment-manager.yaml




apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  namespace: office

  name: deployment-manager

rules:

- apiGroups: ["", "extensions", "apps"]

  resources: ["deployments", "replicasets", "pods"]

  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # вы таже можете использовать ["*"] вместо списка




[root@kub-master-1 ~]# kubectl create -f role-deployment-manager.yaml




Установление связи пользователь-роль




Создайте файл rolebinding-deployment-manager.yaml так, как показано ниже. В этом файле мы привязываем Role deployment-manager к субъекту User Account user1 внутри пространства имен office:




[root@kub-master-1 ~]# cat rolebinding-deployment-manager.yaml




apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

  name: deployment-manager-binding

  namespace: office

subjects:

- kind: User

  name: user1

  apiGroup: ""

roleRef:

  kind: Role

  name: deployment-manager

  apiGroup: ""




[root@kub-master-1 ~]# kubectl create -f rolebinding-deployment-manager.yaml




Тестирование политик RBAC




Теперь вы можете выполнять следующие команды без каких-либо проблем:




[test@kub-master-1 ~]$ kubectl —context=user1-context get pods -n office
No resources found in office namespace.




запустим тестовое приложение и проверим что нам доступно из под нашего пользователя:




[test@kub-master-1 ~]$ kubectl —context=user1-context get all -n office




NAME                                        READY   STATUS    RESTARTS   AGE

pod/my-deployment-apache-859486bd8c-8ccxd   1/1     Running   0          96s



NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE

deployment.apps/my-deployment-apache   1/1     1            1           96s



NAME                                              DESIRED   CURRENT   READY   AGE

replicaset.apps/my-deployment-apache-859486bd8c   1         1         1       96s

Error from server (Forbidden): replicationcontrollers is forbidden: User "user1" cannot list resource "replicationcontrollers" in API group "" in the namespace "office"

Error from server (Forbidden): services is forbidden: User "user1" cannot list resource "services" in API group "" in the namespace "office"

Error from server (Forbidden): daemonsets.apps is forbidden: User "user1" cannot list resource "daemonsets" in API group "apps" in the namespace "office"

Error from server (Forbidden): statefulsets.apps is forbidden: User "user1" cannot list resource "statefulsets" in API group "apps" in the namespace "office"

Error from server (Forbidden): horizontalpodautoscalers.autoscaling is forbidden: User "user1" cannot list resource "horizontalpodautoscalers" in API group "autoscaling" in the namespace "office"

Error from server (Forbidden): jobs.batch is forbidden: User "user1" cannot list resource "jobs" in API group "batch" in the namespace "office"

Error from server (Forbidden): cronjobs.batch is forbidden: User "user1" cannot list resource "cronjobs" in API group "batch" in the namespace "office"





как видим нам доступны только следующие сущности:
deployments  replicasets   pods




как рас их мы и перечислили в конфиге  role-deployment-manager.yaml  для нашего namespace office




проверим удаление:




YAML




[test@kub-master-1 ~]$ kubectl --context=user1-context delete pod my-deployment-apache-859486bd8c-8ccxd -n office

pod "my-deployment-apache-859486bd8c-8ccxd" deleted




как видим всё ок.




Источник: https://sidmid.ru/kubernetes-пример-использования-rbac/



2023-01-02T06:12:18
DevOps

Использование PostStart хука при запуске пода в Kubernetes-кластере

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




Для каждого контейнера в поде хуки определяются отдельно. Существуют два типа хуков — PostStart и PreStop. Первый является асинхронным и выполняется сразу же при создании контейнера, однако нет никакой гарантии, что данный хук будет выполнен до запуска инструкции ENTRYPOINT контейнера. Стоит отметить, что если выполнение PostStart хука занимает очень много времени (или зависает), то контейнер не может перейти в состояние Running.




Хук PreStop, как видно из его названия, выполняется перед тем как контейнер будет остановлен (terminated) — будь то API-запрос или другое событие (например, неудачная liveness probe, “выдавливание” пода с узла кластера, перебор используемых ресурсов). Этот вызов синхронный, а это значит, что он обязательно должен быть завершен до того, как будет отправлен сигнал остановки контейнера.




Для хуков в жизненном цикле контейнеров предусмотрено два варианта обработчиков (handlers):




  • Exec — выполняет определенную команду (скрипт) в пространстве имен контейнера. Ресурсы, которые используются данной командой также учитываются в используемых ресурсах контейнера (важно при определении памяти и CPU);



  • HTTP — выполняет HTTP-запрос на определенный эндпоинт контейнера.




Если какой-то из хуков PostStart или PreStop завершается с ошибкой, то контейнер также будет остановлен. Логи хуков недоступны при выполнении команды kubectl logs <pod_name>, но если по какой-то причине они выполнились неудачно, то происходит событие FailedPostStartHook или FailedPreStopHook соответственно. Эти события можно увидеть выполнив команду kubectl describe pod <pod_name>.




Итак, мы вполне можем использовать PostStart хук для вставки данных в Redis при старте контейнера.




Идея состоит в следующем: с помощью ConfigMap мы добавим файл(ы) внутрь контейнера, причем названием ключа в редисе будет имя, а значением — содержимое этого файла. Далее, используя PostStart хук, мы “обработаем” каждый из файлов и вставим соответствующие данные в БД Redis.




Манифест, содержащий в себе все необходимые объекты Kubernetes, будет выглядеть так:




apiVersion: v1

kind: Service

metadata:

  name: ads-redis-test

  namespace: default

spec:

  selector:

    app: ads-redis-test

  ports:

  - name: redis

    port: 6379

  clusterIP: None

---

apiVersion: v1

kind: ConfigMap

metadata:

  name: ads-redis-test

  namespace: default

data:

  flow-rules-key: |

    [{

      "resource": "loopme.grpc.ssp.v0.AdsTxtRecordService/GetAdsTxtRelationships",

      "count": 100.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v0.PublisherAccountService/GetPublisherById",

      "count": 5.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v1.PublisherAccountService/GetPublisherById",

      "count": 5.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v0.BundleLegacyService/GetBundleByKey",

      "count": 20.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.lsm.ssp.v0.BundleService/GetBundleById",

      "count": 20.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.lsm.ssp.v0.BundleService/QueryBundle",

      "count": 20.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v0.AppLegacyService/GetAppById",

      "count": 10.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v0.AppLegacyService/GetAppIdByKey",

      "count": 10.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v0.AppLegacyService/GetAppIdByContainerKey",

      "count": 16.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "loopme.grpc.ssp.v0.AppLegacyService/GetAppByContainerKey",

      "count": 10.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "ExchangeThrottleRateService/GetThrottleRatesByKeys",

      "count": 20.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "dsp-fetcher",

      "count": 25.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "exchange-fetcher",

      "count": 300.0,

      "grade": "THREAD",

      "limit-app": "default"

    },{

      "resource": "kafka_dmp_ads_requests_info",

      "count": 500.0,

      "grade": "QPS",

      "limit-app": "default"

    }]    

  degrade-rules-key: |

    [{

      "resource": "analytics.AnalyticsApiService/AnalyzeCall",

      "count": 10.0,

      "grade": "EXCEPTION_COUNT",

      "time-window": 10,

      "min-request-amount": 100,

      "stat-interval-ms": 20000,

      "slow-ratio-threshold": 0.6

    },{

      "resource": "analytics.AnalyticsApiService/AnalyzeCall",

      "count": 10.0,

      "grade": "EXCEPTION_RATIO",

      "time-window": 10,

      "min-request-amount": 100,

      "stat-interval-ms": 20000,

      "slow-ratio-threshold": 0.6

    }]    

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: ads-redis-test

  namespace: default

spec:

  replicas: 1

  selector:

    matchLabels:

      app: ads-redis-test

  template:

    metadata:

      labels:

        app: ads-redis-test

    spec:

      containers:

      - name: redis

        image: redis:6.0.9

        ports:

        - name: redis

          containerPort: 6379

        resources:

          limits:

            cpu: "0.5"

            memory: 1Gi

          requests:

            cpu: "0.5"

            memory: 1Gi

        lifecycle:

          postStart:

            exec:

              command: ["/bin/bash", "-c", "cd /script/ && for FILE in *key; do cat ${FILE} | redis-cli -n 2 -x set ${FILE}; done"]

        livenessProbe:

          exec:

            command:

            - sh

            - -c

            - redis-cli -h $(hostname) ping

          initialDelaySeconds: 5

          periodSeconds: 3

        readinessProbe:

          exec:

            command:

            - sh

            - -c

            - redis-cli -h $(hostname) ping

          initialDelaySeconds: 5

          timeoutSeconds: 3

        volumeMounts:

        - mountPath: /script

          name: script

      volumes:

      - name: script

        configMap:

          name: ads-redis-test




Вся “магия” заключается в команде, которая определена в postStart хуке:




command: ["/bin/bash", "-c", "cd /script/ && for FILE in *key; do cat ${FILE} | redis-cli -n 2 -x set ${FILE}; done"]




Здесь для каждого файла в каталоге /script, который заканчивается на key выполняется следующее:




  • с помощью команды cat выводится содержимое файла в STDOUT;



  • через конвейер | передаются следующей команде — консольной утилите redis-cli (здесь в STDIN попадает содержимое STDOUT из предыдущего шага);



  • redis-cli выполняет вставку данных во вторую БД (ключ -n 2) с помощью команды SET.




Примечание Именем ключа будет значение переменной ${FILE} (имя файла), а значением — данные из STDIN (об этом заботится ключ -x).




Источник: https://sidmid.ru/использование-poststart-хука-при-запуске-пода/



2023-01-02T06:04:30
DevOps