https://hub.helm.sh/charts/cetic/pgadmin

helm repo add cetic https://cetic.github.io/helm-charts
helm repo update
helm install cetic/pgadmin --name pgadmin --namespace pgadmin --set image.repository=dpage/pgadmin4:4.15 --set service.type=ClusterIP --set image.pullPolicy=IfNotPresent

PersistentVolume

apiVersion: v1
kind: PersistentVolume
metadata:
   name: pgadmin-pv
   namespace: pgadmin
   labels:
     app: pgadmin
spec:
  capacity:
    storage: 4Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: "/kubernetes_volumes/pgadmin-data"
    type: Directory
  persistentVolumeReclaimPolicy: Retain

Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt
  name: pgadmin-ingress
  namespace: pgadmin
spec:
  rules:
  - host: pgadmin.autosys.tk
    http:
      paths:
      - backend:
          serviceName: pgadmin
          servicePort: 80
        path: /
  tls:
  - hosts:
    - pgadmin.autosys.tk
    secretName:  pgadmin-autosys-tk-tls

Ошибки

После апгрейда docker-образа с версии 4.15 до 4.17 под не смог запуститься с ошибкой:

WARNING: Failed to set ACL on the directory containing the configuration database: [Errno 1] Operation not permitted: '/var/lib/pgadmin'
PermissionError: [Errno 1] Operation not permitted: '/var/lib/pgadmin/sessions'

Это произошло потому, что у пользователь, от имени которого исполняется pgadmin, не является владельцем директории, которая смонтирована как persistentVolume. Поэтому, когда контейнер запускается (но еще не упал с Error) нужно найти процесс pgadmin:

#ps -aux | grep pgadmin
5050     16492  0.0  0.1  24720 22892 ?        Ss   16:07   0:00 /usr/local/bin/python /usr/local/bin/gunicorn --timeout 86400 --bind [::]:80 -w 1 --threads 25 --access-logfile - run_pgadmin:app

И сделать owner'ом папки пользователя с указанным id. В хостовой системе, на которой исполняется контейнер, такого пользователя может и не быть. Главное, чтобы в ACL директории был прописан правильный id:

sudo chown 5050:5050 /kubernetes_volumes/pgadmin-data/ -R

Проблемы

Если нужно, чтобы при входе в PGAdmin сразу подключался сервер, то нужно сделать две вещи - заполнить файл с определениями серверов /pgadmin4/servers.json и заполнить файл pgpass, который хранит пароли для заданных серверов/бд/пользовтелей.
Если с заполнением файла /pgadmin4/servers.json всё более-менее понятно (за исключением того, что путь PassFile задается относительно директории пользователя, что само по себе нетривиально), то вот с файлом pgpass всё не очень просто.
В документации написано, что права на этот файл должны быть строго не шире, чем 0600, то есть права на чтение должен иметь только владелец файла.
Однако, если pgadmin работает в кластере kubernetes, содержимое файла pgpass монтируется из секрета а для пода задан securityContext, то defaultMod для файла смонтированного из секрета не применяется (так написано тут: https://github.com/kubernetes/kubernetes/issues/89153 и тут: https://github.com/kubernetes/kubernetes/issues/57923). В итоге - всё оказывается сложнее, но выход есть!
Итак, я использую чарт pgadmin в качестве сабчарта (наряду с чартом postgresql) и хочу, чтобы в конфиг PGAdmin автоматически попадали параметры развернутого postgresql.
Для этого мне понадобилось

  • Секрет с содержимым файла pgpass
    {{- if .Values.pgadmin4.enabled -}}
    apiVersion: v1
    kind: Secret
    metadata:
      name: pgpassfile
      labels:
    data:
      pgpassfile: {{ include "pgadmin4.pgpassfile" . | b64enc | quote }}
    {{- end}}

  • Содержимое файла pgpass формируется хелпером

    {{- define "pgadmin4.pgpassfile" -}}
    {{ .Values.global.postgresql.fullnameOverride }}:{{ .Values.global.postgresql.service.port }}:*:{{ .Values.global.postgresql.postgresqlUsername }}:{{ .Values.global.postgresql.postgresqlPassword }}
    {{ end }}

  • Хелпер для формирования файла /pgadmin4/servers.json (хелпер родительского чарта переопределяет хелпер сабчарта pgadmin4)

    {{/*
    Определение сервера для PGAdmin
    */}}
    {{- define "pgadmin.serverDefinitions" }}
    {
        "Servers": {
            "1": {
                "Name": "PostgeSql-{{ .Values.global.environment }}",
                "Group": "Servers",
                "Host": "{{ .Values.global.postgresql.fullnameOverride }}",
                "Port": "{{ .Values.global.postgresql.service.port }}",
                "MaintenanceDB": "{{ .Values.global.postgresql.postgresqlDatabase }}",
                "Username": "{{ .Values.global.postgresql.postgresqlUsername }}",
                "SSLMode": "prefer",
                "Comment": "Preconfigured PostgreSQL Server",
                "DBRestriction": "{{ .Values.global.postgresql.postgresqlDatabase }}",
                "PassFile": "/pgpass"
            }
        }
    }
    {{- end -}}

  • Проблему с правами на файл pgpass решаем с помощью init-контейнера, который монтирует секрет в файл, а затем - копирует этот файл в нужную папку и задает ему нужные права:

      extraSecretMounts:
      - name: pgpassfile
        secret: pgpassfile
        subPath: pgpassfile
        mountPath: "/pgpass"
        readOnly: true
      extraInitContainers: |
        - name: pgpass-permissions-init
          image: "docker.rdleas.ru/dpage/pgadmin4:4.29"
          command:
          - "/bin/ash"
          - "-c"
          - "/bin/mkdir -p /var/lib/pgadmin/storage/pgadmin && /bin/cp /pgpass /var/lib/pgadmin/storage/pgadmin/pgpass && /bin/chmod 0600 /var/lib/pgadmin/storage/pgadmin/pgpass"
          securityContext:
            runAsUser: 0
          volumeMounts:
          - mountPath: /pgpass
            name: pgpassfile
            readOnly: false
            subPath: pgpassfile
          - mountPath: /var/lib/pgadmin
            name: pgadmin-data

  • В файле values родительского чарта записи такие:

global:
  environment: dev
  postgresql: 
    fullnameOverride: postgresql
    postgresqlUsername: api-user
    postgresqlPassword: tvJk3XrqM3d7xX6b
    postgresqlDatabase: sbl-mobile-api
    service:
      port: 5432
...
postgresql:
  enabled: true
  fullnameOverride: postgresq
...
pgadmin4:
  serverDefinitions:
  #defined in _helpers.tpl - "pgadmin.serverDefinitions"
    enabled: true
  extraSecretMounts:
  - name: pgpassfile
    secret: pgpassfile
    subPath: pgpassfile
    mountPath: "/pgpass"
    readOnly: true
  extraInitContainers: |
    - name: pgpass-permissions-init
      image: "docker.rdleas.ru/dpage/pgadmin4:4.29"
      command:
      - "/bin/ash"
      - "-c"
      - "/bin/mkdir -p /var/lib/pgadmin/storage/pgadmin && /bin/cp /pgpass /var/lib/pgadmin/storage/pgadmin/pgpass && /bin/chmod 0600 /var/lib/pgadmin/storage/pgadmin/pgpass"
      securityContext:
        runAsUser: 0
      volumeMounts:
      - mountPath: /pgpass
        name: pgpassfile
        readOnly: false
        subPath: pgpassfile
      - mountPath: /var/lib/pgadmin
        name: pgadmin-data
  persistentVolume:
    enabled: false
  securityContext:
    runAsUser: 0
    runAsGroup: 0
    fsGroup: 0
Enter your comment. Wiki syntax is allowed:
 
  • devops/setup_pgadmin_on_kubernetes.txt
  • Last modified: 2021/02/10 21:16
  • by admin