Прошло чуть больше 2 месяцев с момента релиза первой версии универсального чарта, и мы рады представить чарт версии 2.0. В этой статье расскажу что нового, и рассмотрим на примере, как это работает.

Список обновлений

Мапы вместо списков сущностей

В первой версии для определния сущностей Job, CronJob, serviceMonitors и HelmHooks использовались списки, но практика показала, что использование мап, где имя сущности является ключом в мапе - удобнее. В первую очередь, это предоставляет возможность слияния мапов из разных файлов, возможность точечной модификации используя --set и т.д.

Используя следующие параметры в values:

cronJobs:
  mailing:
    schedule: "00 05 * * *"
    containers:
    - command: send-mail
      volumeMounts:
      - mountPath: /app/issues-mailing.conf
        name: config
        subPath: issues-mailing.conf
    volumes:
    - name: config
      type: secret
      originalName: app-config
    restartPolicy: OnFailure

и флаг --set cronJobs.mailing.schedule="*/5 * * * *" получаем в результате:

---
# Source: universal-chart/templates/cronjob.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: mailing
  namespace: "test"
  labels:
    app.kubernetes.io/name: test
    app.kubernetes.io/instance: test
    helm.sh/chart: universal-chart-2.0.0
    app.kubernetes.io/managed-by: Helm
  annotations:    
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
          annotations:
        spec:
          affinity:
            nodeAffinity:
              {}
            podAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - podAffinityTerm:
                  labelSelector:
                    matchLabels:
                      app.kubernetes.io/name: test
                      app.kubernetes.io/instance: test
                  namespaces:
                  - "test"
                  topologyKey: kubernetes.io/hostname
                weight: 1
            podAntiAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - podAffinityTerm:
                  labelSelector:
                    matchLabels:
                      app.kubernetes.io/name: test
                      app.kubernetes.io/instance: test
                  namespaces:
                  - "test"
                  topologyKey: kubernetes.io/hostname
                weight: 1
          imagePullSecrets:
          - name: registry.org
          - name: registry.org-rw
          containers:
          - name: mailing
            image: registry.org/my-app:latest
            imagePullPolicy: IfNotPresent
            command: ["send-mail"]                        
            volumeMounts:
            - mountPath: /app/issues-mailing.conf
              name: config
              subPath: issues-mailing.conf
          volumes:          
          - name: config
            secret:
              secretName: app-config 
          restartPolicy: OnFailure

HorizontalPodAutoscaler

Добавлена возможность настроить автомасштабирование используя HPA. Рассмотрим на примере.

Используя следующие параметры в values:

hpas:
  default-for-app:
    scaleTargetRef:
      name: app
    targetCPU: 60
    targetMemory: 70
  advanced-for-app2:
    apiVersion: autoscaling/v2
    labels:
      foo: bar
    annotations:
      bar.io/bar: foo
    minReplicas: 1
    maxReplicas: 5
    scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: app2
    metrics:
    - type: Pods
      pods:
        metric:
          name: packets-per-second
        target:
          type: AverageValue
          averageValue: 2k
    - type: Object
      object:
        metric:
          name: requests-per-second
        describedObject:
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          name: main-route
        target:
          type: Value
          value: 10k
    - type: External
      external:
        metric:
          name: queue_messages_ready
          selector:
            matchLabels:
              queue: "worker_tasks"
        target:
          type: AverageValue
          averageValue: 25

получаем в результате:

---
# Source: universal-chart/templates/hpa.yaml
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2
metadata:
  name: advanced-for-app2
  namespace: "test"
  labels:
    app.kubernetes.io/name: test
    app.kubernetes.io/instance: test
    helm.sh/chart: universal-chart-2.0.0
    app.kubernetes.io/managed-by: Helm
    foo: bar
  annotations:
    bar.io/bar: foo
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app2
  minReplicas: 1
  maxReplicas: 5
  metrics:
    - pods:
        metric:
          name: packets-per-second
        target:
          averageValue: 2k
          type: AverageValue
      type: Pods
    - object:
        describedObject:
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          name: main-route
        metric:
          name: requests-per-second
        target:
          type: Value
          value: 10k
      type: Object
    - external:
        metric:
          name: queue_messages_ready
          selector:
            matchLabels:
              queue: worker_tasks
        target:
          averageValue: 25
          type: AverageValue
      type: External
---
# Source: universal-chart/templates/hpa.yaml
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: default-for-app
  namespace: "test"
  labels:
    app.kubernetes.io/name: test
    app.kubernetes.io/instance: test
    helm.sh/chart: universal-chart-2.0.0
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app
  minReplicas: 2
  maxReplicas: 3
  metrics:
    - type: Resource
      resource:
        name: cpu
        targetAverageUtilization: 60
    - type: Resource
      resource:
        name: memory
        targetAverageUtilization: 70

PodDisruptionBudget

Добавлена возможность настроить квоту неработающих подов, с использованием PDB. Рассмотрим на примере.

Используя следующие values:

pdbs:
  nginx:
    labels:
      app: nginx
    minAvailable: 1
    extraSelectorLabels:
      app: nginx
  app2:
    labels:
      bar: foo
    maxUnavailable: 1
    extraSelectorLabels:
      bar: foo

получаем в результате:

---
# Source: universal-chart/templates/pdb.yaml
kind: PodDisruptionBudget
apiVersion: policy/v1beta1
metadata:
  name: app2
  namespace: "test"
  labels:
    app.kubernetes.io/name: test
    app.kubernetes.io/instance: test
    helm.sh/chart: universal-chart-2.0.0
    app.kubernetes.io/managed-by: Helm
    bar: foo
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: test
      app.kubernetes.io/instance: test
      bar: foo
---
# Source: universal-chart/templates/pdb.yaml
kind: PodDisruptionBudget
apiVersion: policy/v1beta1
metadata:
  name: nginx
  namespace: "test"
  labels:
    app.kubernetes.io/name: test
    app.kubernetes.io/instance: test
    helm.sh/chart: universal-chart-2.0.0
    app.kubernetes.io/managed-by: Helm
    app: nginx
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: test
      app.kubernetes.io/instance: test
      app: nginx

За HPA и PDB благодарим @evg_krsk.

Как и ранее, будем рады услышать ваши мысли и увидеть предложения по улучшению на GitHub. А так-же ждём в нашем телеграм-канале, где мы публикуем новости о DevOps (и не только) - DevOps FM.

Комментарии (3)


  1. onegreyonewhite
    10.06.2022 13:26
    +1

    Выглядит достойно для тех, кто любит минимизировать ручной труд. А как универсальный чарт работает в качестве сабчарта?

    Единственное чего я не понял, так это GPLv3. Потому что использование в коммерческих целях практически не возможно легально (к слову об субчартах) да и мало кто захочет с GPL связываться в принципе. Ну и для вас профита не понимаю. Можете объяснить?


    1. r_andreev Автор
      10.06.2022 13:52

      1. По поводу сабчарта . Если речь идёт об использовании в чарте "зонтике", да без проблем можно использовать, собирая необходимый вам набор приложений, включая несколько универсальных для разных прилож.

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


      1. onegreyonewhite
        10.06.2022 14:29
        +1

        1. Звучит отлично. Если не считать п.2

        2. Вы как-то упрощаете. В субчартах уже нельзя использовать, для реализации внутренних услуг тоже в очень редких случаях подойдёт. Вообще советую разобраться с лицензией, потому что для вас она тоже вносит ограничения (либо контрибьютить вам должны с MIT). Вы зря минусите, лучше бы текст почитали. В РФ сейчас он конечно мало смысла имеет, хотя тут от судьи зависит. Не просто так LGPL придумали.