Знакомство с Kubernetes. Часть 18: PodPresets

Oct 1, 2018 06:01 · 654 words · 4 minute read kubernetes

В этой статье рассмотрим использование PodPresets - объектов, с помощью которых можно добавлять определенную информацию в поды во время их создания. Информация может включать в себя секреты, тома и переменные окружения. Давайте разберемся!

Для указания подов (Pods), к которым должен применяться API ресурс PodPresets используются селекторы меток. Использование PodPresets позволяет значительно сократить размеры манифестов и избавиться от копипасты.

В Kubernetes существует контроллер (admission controller) PodPreset, который, если включен, применяет PodPresets к запросам на создание подов. При этом выполняются следующие действия:

  • проверяются все доступные PodPresets;
  • проверяется соответствие селекторов меток любого PodPreset меткам создаваемого контейнера;
  • делается попытка добавить информацию (настройки), определенную в PodPreset, в создаваемый под;
  • при ошибке добавления информации из PodPreset под создается без каких-либо вложенных ресурсов из PodPreset и записывается сообщение об ошибке;
  • при успешном добавлении информации из PodPreset в описание пода также добавляется аннотация (чтобы понимать, что под модифицирован с помощью PodPreset). Аннотации выглядят так podpreset.admission.kubernetes.io/podpreset-<pod-preset name>: "<resource version>".

Каждому поду (Pod) можно сопоставить ноль или более PodPreset; каждый PodPreset может быть применен к нулю или нескольким подам. При добавлении из PodPreset данных, содержащихся в Env, EnvFrom и VolumeMounts изменяется спецификация КАЖДОГО контейнера в поде; при добавлении данных, содержащихся в Volume, меняется спецификация пода.

Для использования PodPreset необходимо:

  • включить API settings.k8s.io/v1alpha1/podpreset. Например, добавлением параметра settings.k8s.io/v1alpha1=true к опции --runtime-config API-сервера;
  • включить контроллер PodPreset, например добавив значение PodPreset в параметр --enable-admission-plugins API-сервера;
  • создать объект PodPreset в соответствующем неймспейсе.

Рассмотрим конкретный пример. Создадим файл preset.yaml следующего содержимого:

apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-database
spec:
  selector:
    matchLabels:
      role: frontend
  env:
    - name: DB_PORT
      value: "6379"
  volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir: {}

Создадим данный объект в кластере Kubernetes:

kubectl create -f preset.yaml

Проверим наличие объекта:

kubectl get podpreset
NAME             AGE
allow-database   1m

Теперь при создании подов с меткой role: frontend к ним будет добавляться информация из данного PodPreset. Проверим данное утверждение - создаем файл pod.yaml с таким содержимым:

apiVersion: v1
kind: Pod
metadata:
  name: website
  labels:
    app: website
    role: frontend
spec:
  containers:
    - name: website
      image: nginx
      ports:
        - containerPort: 80

Создаем под:

kubectl create -f pod.yaml

Убедимся, что под создан и запущен:

kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
website   1/1       Running   0          4m

Получим подробное описание пода с помощью команды:

kubectl get pod website -o yaml

apiVersion: v1
kind: Pod
metadata:
  name: website
  labels:
    app: website
    role: frontend
  annotations:
    podpreset.admission.kubernetes.io/podpreset-allow-database: "resource version"
spec:
  containers:
    - name: website
      image: nginx
      volumeMounts:
        - mountPath: /cache
          name: cache-volume
      ports:
        - containerPort: 80
      env:
        - name: DB_PORT
          value: "6379"
  volumes:
    - name: cache-volume
      emptyDir: {}

Как и ожидалось, к поду была добавлена информация из PodPreset.

Более сложный пример (с использованием ConfigMap). Описание пода выглядит следующим образом:

apiVersion: v1
kind: Pod
metadata:
  name: website
  labels:
    app: website
    role: frontend
spec:
  containers:
    - name: website
      image: nginx
      ports:
        - containerPort: 80

Описание конфигмапа (ConfigMap) выглядит так:

apiVersion: v1
kind: ConfigMap
metadata:
  name: etcd-env-config
data:
  number_of_members: "1"
  initial_cluster_state: new
  initial_cluster_token: DUMMY_ETCD_INITIAL_CLUSTER_TOKEN
  discovery_token: DUMMY_ETCD_DISCOVERY_TOKEN
  discovery_url: http://etcd_discovery:2379
  etcdctl_peers: http://etcd:2379
  duplicate_key: FROM_CONFIG_MAP
  REPLACE_ME: "a value"

Содержимое файла с описанием PodPreset будет теперь таким:

apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-database
spec:
  selector:
    matchLabels:
      role: frontend
  env:
    - name: DB_PORT
      value: "6379"
    - name: duplicate_key
      value: FROM_ENV
    - name: expansion
      value: $(REPLACE_ME)
  envFrom:
    - configMapRef:
        name: etcd-env-config
  volumeMounts:
    - mountPath: /cache
      name: cache-volume
    - mountPath: /etc/app/config.json
      readOnly: true
      name: secret-volume
  volumes:
    - name: cache-volume
      emptyDir: {}
    - name: secret-volume
      secret:
         secretName: config-details

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

apiVersion: v1
kind: Pod
metadata:
  name: website
  labels:
    app: website
    role: frontend
  annotations:
    podpreset.admission.kubernetes.io/podpreset-allow-database: "resource version"
spec:
  containers:
    - name: website
      image: nginx
      volumeMounts:
        - mountPath: /cache
          name: cache-volume
        - mountPath: /etc/app/config.json
          readOnly: true
          name: secret-volume
      ports:
        - containerPort: 80
      env:
        - name: DB_PORT
          value: "6379"
        - name: duplicate_key
          value: FROM_ENV
        - name: expansion
          value: $(REPLACE_ME)
      envFrom:
        - configMapRef:
            name: etcd-env-config
  volumes:
    - name: cache-volume
      emptyDir: {}
    - name: secret-volume
      secret:
         secretName: config-details

Чуть больше информации об использовании PodPreset можно найти тут.

tweet Share