无法在AKS中获得Postgres权限或PVC

时间:2020-02-12 16:22:28

标签: postgresql azure docker kubernetes azure-kubernetes

这些几乎是我按照顺序执行的步骤。基本上是文档概述的内容:

https://docs.microsoft.com/en-us/azure/aks/azure-files-dynamic-pv

  1. azure-storage-claim.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: test-app-sc
provisioner: kubernetes.io/azure-file
mountOptions:
  - dir_mode=0777
  - file_mode=0777
  - uid=1000
  - gid=1000
  - mfsymlinks
  - nobrl
  - cache=none
parameters:
  skuName: Standard_LRS
  location: westus
  1. azure-storage.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-app-storage
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: test-app-sc
  resources:
    requests:
      storage: 15Gi

PVC现在已设置。

根据Postgres图像文档更改了mountPath:

PGDATA

此可选变量可用于为数据库文件定义另一个位置,例如子目录。默认值为/ var / lib / postgresql / data,但是如果您使用的数据量是文件系统挂载点(例如GCE永久磁盘),则Postgres initdb建议使用一个子目录(例如/ var / lib / postgresql / data / pgdata)创建为包含数据。

这是非Docker特定的环境变量。由于该变量由postgres服务器二进制文件使用(请参见PostgreSQL文档),因此入口点脚本会将其考虑在内。

基于此,我的postgres.yaml设置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: postgres
  template:
    metadata:
      labels:
        component: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:11-alpine
          ports:
            - containerPort: 5432
          env: 
            - name: POSTGRES_DB
              valueFrom:
                secretKeyRef:
                  name: test-app-secrets
                  key: PGDATABASE
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: test-app-secrets
                  key: PGUSER
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: test-app-secrets
                  key: PGPASSWORD
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
            - name: PGDATA
              value: /var/lib/postgresql-data
          volumeMounts:
            - name: test-app-storage
              mountPath: /var/lib/postgresql-data
              subPath: postgres-storage
      volumes:
        - name: test-app-storage
          persistentVolumeClaim:
            claimName: test-app-storage
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: postgres
  ports:
    - port: 1423
      targetPort: 5432

您收到错误:

chmod: changing permissions of '/var/lib/postgresql-data': Operation not permitted

因此将其中一个作为Dockerfile:

FROM postgres:11-alpine
EXPOSE 5432
RUN /bin/bash -c 'chmod 777 /var/lib/postgresql-data'

FROM postgres:11-alpine
EXPOSE 5432

这并不重要,通过执行以下任何操作,您仍然会收到相同类型的错误:

            ...
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
          volumeMounts:
            - name: test-app-storage
              mountPath: /var/lib/postgresql-data
              subPath: postgres-storage
      volumes:
        - name: test-app-storage
          persistentVolumeClaim:
            claimName: test-app-storage
     ...

导致以下错误:

The files belonging to this database system will be owned by user "postgres". This user must also own the server process.
The database cluster will be initialized with locale "en_US.utf8". The default database encoding has accordingly been set to "UTF8". The default text search configuration will be set to "english".

Data page checksums are disabled.

initdb: error: directory "/var/lib/postgresql-data" exists but is not empty If you want to create a new database system, either remove or empty the directory "/var/lib/postgresql-data" or run initdb with an argument other than "/var/lib/postgresql-data".

尝试一下:

            ...
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
          volumeMounts:
            - name: test-app-storage
              mountPath: /var/lib/postgresql-data
              subPath: postgres-storage
      volumes:
        - name: test-app-storage
          persistentVolumeClaim:
            claimName: test-app-storage
     ...

结果如下:

chmod: changing permissions of '/var/lib/postgresql-data': Operation not permitted

尝试一下:

            ...
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
              value: "-D /var/lib/postgresql/data/pgdata"
          volumeMounts:
            - name: test-app-storage
              mountPath: /var/lib/postgresql/data/pgdata
              subPath: postgres-storage
      volumes:
        - name: test-app-storage
          persistentVolumeClaim:
            claimName: test-app-storage
     ...

结果如下:

The files belonging to this database system will be owned by user "postgres". This user must also own the server process.
The database cluster will be initialized with locale "en_US.utf8". The default database encoding has accordingly been set to "UTF8". The default text search configuration will be set to "english".

Data page checksums are disabled.

initdb: error: could not change permissions of directory "/var/lib/postgresql/data/pgdata": Operation not permitted fixing permissions on existing directory /var/lib/postgresql/data/pgdata ...

So nothing seems to work that I've tried and following the documentation where I can.

有人建议像这样摆脱卷挂:

            ...
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
            - name: PGDATA
              value: /var/lib/postgresql/data/pgdata
      volumes:
        - name: test-app-storage
          persistentVolumeClaim:
            claimName: test-app-storage
     ...

哪个,嘿,这确实有效!但是不会持久保留数据,因为它仅使用Pod存储,因此毫无意义:

enter image description here

当在Postgres中创建表,销毁Pod并重新部署它时,当然可以肯定,该表不再存在。

很有可能我做错了事,但是我一直在遵循文档,而且看起来应该可以。

哪里出了问题?

编辑:豆荚中的权限

显然,当PGDATAmountPath是同一目录时,会发生权限问题。例如:

  ...
  - name: PGDATA
    value: /var/lib/postgresql-data
volumeMounts:
  - name: test-app-storage
    mountPath: /var/lib/postgresql-data
    subPath: postgres-storage
...

or

  ...
  # if PGDATA is not specified it defaults to /var/lib/postgresql/data
  # - name: PGDATA
  #   value: /var/lib/postgresql-data
volumeMounts:
  - name: test-app-storage
    mountPath: /var/lib/postgresql/data
    subPath: postgres-storage
...

类似这样的地方(它们不匹配)会创建Pod,但会使用我显然不想要的Pod存储:

  # Thus /var/lib/postgresql/data
  # - name: PGDATA
  #   value: /var/lib/postgresql-data
volumeMounts:
  - name: test-app-storage
    mountPath: /var/lib/postgresql-data
    subPath: postgres-storage

权限ls -l如下:

$ ls -l

drwxr-xr-x 1 root     root     4096 Feb  2 06:06 apt
drwxr-xr-x 1 root     root     4096 Feb  2 06:07 dpkg
drwxr-xr-x 2 root     root     4096 Feb  2 06:06 exim4
drwxr-xr-x 2 root     root     4096 Aug 28  2018 logrotate
drwxr-xr-x 2 root     root     4096 Nov 10 12:17 misc
drwxr-xr-x 2 root     root     4096 Jan 30 00:00 pam
drwxr-xr-x 1 postgres postgres 4096 Feb  2 06:07 postgresql
drwxrwxrwx 2     1000     1000    0 Jan 31 21:46 postgresql-data
drwxr-xr-x 1 root     root     4096 Jan 30 00:00 systemd
drwxr-xr-x 3 root     root     4096 Feb  2 06:07 ucf

$ ls -l postgresql && ls -l postgresql/data && ls -l postgresql-data
total 4
drwx------ 19 postgres postgres 4096 Feb  5 23:28 data
total 124
drwx------ 6 postgres postgres  4096 Feb  5 23:28 base
drwx------ 2 postgres postgres  4096 Feb  5 23:29 global
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_commit_ts
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_dynshmem
-rw------- 1 postgres postgres  4281 Feb  5 23:28 pg_hba.conf
-rw------- 1 postgres postgres  1636 Feb  5 23:28 pg_ident.conf
drwx------ 4 postgres postgres  4096 Feb  5 23:33 pg_logical
drwx------ 4 postgres postgres  4096 Feb  5 23:28 pg_multixact
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_notify
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_replslot
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_serial
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_snapshots
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_stat
drwx------ 2 postgres postgres  4096 Feb  5 23:51 pg_stat_tmp
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_subtrans
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_tblspc
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_twophase
-rw------- 1 postgres postgres     3 Feb  5 23:28 PG_VERSION
drwx------ 3 postgres postgres  4096 Feb  5 23:28 pg_wal
drwx------ 2 postgres postgres  4096 Feb  5 23:28 pg_xact
-rw------- 1 postgres postgres    88 Feb  5 23:28 postgresql.auto.conf
-rw------- 1 postgres postgres 26588 Feb  5 23:28 postgresql.conf
-rw------- 1 postgres postgres    36 Feb  5 23:28 postmaster.opts
-rw------- 1 postgres postgres    94 Feb  5 23:28 postmaster.pid
total 0

创建数据文件的权限为postgres。但是,这样做不会将其映射到Azure文件和PVC。它只是留下而被豆荚摧毁。

我认为正在发生的事情是mountPath使用root,而PGDATA使用postgres,而mountPath正试图使用​​postgres? ??

真的,不确定,如何解决仍然迷路。

EDIT2

请回答以下答案:

https://stackoverflow.com/a/51203031/3123109

因此向我添加了以下内容:

- name: postgres
  image: postgres
  command: 
  - /bin/chown
  - -R
  - "1000"
  - /var/lib/postgresql/data

但这会产生一个新错误:

The selected container has not logged any messages yet.

我猜是进步。

4 个答案:

答案 0 :(得分:1)

我认为您的问题可能是由于您试图将子路径用作部署对象的一部分

请在没有此行的情况下重试您的第一个配置:

subPath:postgres-storage

应该导致这个 volumeMounts: -名称:postgres-storage mountPath:/ var / lib / postgresql / data / pgdata

让我知道是否有帮助。

更新:使用永久存储时,PostgreSQL的docker映像需要特别注意

https://hub.docker.com/_/postgres

要注意的主要警告是,postgres并不关心它运行的UID(只要/ var / lib / postgresql / data的所有者匹配),但是initdb确实在乎(并且需要用户存在于其中) / etc / passwd):

解决这个问题的三种最简单方法:

  1. 使用Debian变体(不是Alpine变体),从而允许映像使用nss_wrapper库为您“伪造” / etc / passwd内容(有关更多详细信息,请参阅docker-library / postgres#448)

  2. 从主机上以只读方式绑定安装/ etc / passwd(如果您想要的UID是主机上的有效用户):

$ docker run -it --rm --user“ $ {id -u):$(id -g)” -v / etc / passwd:/ etc / passwd:ro -e POSTGRES_PASSWORD = mysecretpassword postgres 属于该数据库系统的文件将由用户“ jsmith”拥有

  1. 与最终运行时分开初始化目标目录(中间有一个chown):

$泊坞窗卷创建pgdata $ docker run -it --rm -v pgdata:/ var / lib / postgresql / data -e POSTGRES_PASSWORD = mysecretpassword postgres 属于该数据库系统的文件将由用户“ postgres”拥有。 (一旦成功完成初始化并等待连接,请停止它) $ docker run -it --rm -v pgdata:/ var / lib / postgresql / data bash chown -R 1000:1000 / var / lib / postgresql / data $ docker run -it --rm --user 1000:1000 -v pgdata:/ var / lib / postgresql / data postgres 日志:数据库系统于世界标准时间2017年1月20日00:03:23关闭 日志:现在启用了MultiXact成员环绕保护 日志:自动真空启动器已启动 日志:数据库系统已准备就绪,可以接受连接

一种解决方案是利用bitnami制作的helm图表,它们使用init容器制定了复杂的持久性存储配置的默认设置,并且还支持修复所需的/ dev / shm配置

还请注意,容器的默认/ dev / shm大小为64MB。如果共享内存已用完,您将遇到错误:无法调整共享内存段的大小。 。 。 : 设备上没有剩余空间。例如,您将要传递--shm-size = 256MB到docker run,或者通过docker-compose

这是图表使用的初始化容器的示例。

https://github.com/helm/charts/blob/master/stable/postgresql/templates/statefulset.yaml#L74-L115

建议使用头盔安装Postgres图表(使用statefuset),而不要尝试使用部署对象来部署数据库。 (通常,您希望将部署对象用于无状态应用程序。)

答案 1 :(得分:0)

最后,解决方案是改用 Azure 磁盘。也许这已得到修复,您可以从 2020 年初开始使用 Azure 文件,但自从使用 Azure 磁盘后我就没有尝试过。

我的 .yaml 配置如下所示:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: file-storage
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: azurefile
  resources:
    requests:
      storage: 25Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-storage
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: default
  resources:
    requests:
      storage: 25Gi
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: postgres
  template:
    metadata:
      labels:
        component: postgres

    spec:
      containers:
        - name: postgres
          image: postgres:11-alpine
          ports:
            - containerPort: 5432
          env: 
            - name: POSTGRES_DB
              valueFrom:
                secretKeyRef:
                  name: app-prod-secrets
                  key: PGDATABASE
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: app-prod-secrets
                  key: PGUSER
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-prod-secrets
                  key: PGPASSWORD
            - name: POSTGRES_INITDB_ARGS
              value: "-A md5"
            - name: PGDATA
              value: /var/postgresql/data
          volumeMounts:
            - name: postgres-storage
              mountPath: /var/postgresql
      volumes:
        - name: postgres-storage
          persistentVolumeClaim:
            claimName: postgres-storage
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    component: postgres
  ports:
    - port: 5432
      targetPort: 5432

答案 2 :(得分:0)

之所以可以使用azure-disk,而不能使用azure-file,是因为azure-file是基于SMB协议的,而azure-disk不是[1]。

正如 GitHub.com 上的 andyzhangx 所述 [2]:

<块引用>

SMB 挂载选项(包括 dir 权限)无法更改,这是由 SMB proto 设计的,而对于磁盘(ext4,xfs),可以在挂载后更改 dir 权限

也许 [3] 中使用的方法也是一个解决方案,但我现在也将坚持使用 azure-disk 来处理我的(Bitnami)Postgresql PVC。

答案 3 :(得分:0)

回答你所有的问题。我在 AKS 中使用 PVC 声明使 postgres pod 工作

  1. https://github.com/docker-library/postgres/tree/5c0e796bb660f0ae42ae8bf084470f13417b8d63/12/buster 复制 docker 和 docker-entrypoint.sh 文件,我这么说的原因是我们需要修改 uid 和 gid 与 deployment.yaml 中定义的匹配,如下所示。我在这里使用 1025 。 安全上下文: runAsNonRoot: 假 以用户身份运行:1025 fsGroup:1025

  2. 更改docker文件中的2行

    groupadd -r postgres --gid=1025;
    useradd -r -g postgres --uid=1025--home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \

  3. 然后在docker文件中添加一个额外的命令 -> COPY docker-entrypoint.sh /usr/local/bin/

运行 chmod +x /usr/local/bin/docker-entrypoint.sh

  1. 创建基础镜像并推送到 Azure 容器注册表

  2. deployment.yaml 和 storage.yaml 如下

apiVersion:apps/v1

kind: Deployment
metadata:
  name: kinetic-postgres-alpha
  namespace: chatbot-dev
  annotations:
    buildNumber: 2020.04.15.1
    contributors: "Rakesh Sekar"
    azure-project: "Process"
    azure-repository: "IT-Robotics-Chatbot_Common"
    cmdb-app-name: "Robotics Chatbot"  # 
    docs: https://wiki.prodapt.com/
    description: |
      Chatbot Postgres Deployment
  labels:
    svc: kinetic-postgres-alpha
spec:
  replicas: 1
  selector:
    matchLabels:
      svc: kinetic-postgres-alpha
  template:
    metadata:
      labels:
        svc: kinetic-postgres-alpha
      annotations:
        buildNumber: 2020.04.15.1
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 10
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: svc
                  operator: In
                  values:
                  - kinetic-postgres-alpha       
              topologyKey: "kubernetes.io/hostname"   
      containers:
      - name: kinetic-postgres-alpha
        image: winacr01.azurecr.io/robotics/chatbot_botpress_postgres_baseimage:12
        imagePullPolicy: Always
        ports:
        - containerPort: 5432
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
          requests:
            cpu: 750m
            memory: 1024Mi
        env:
        - name: TZ
          value: UTC       
        - name: POSTGRES_DB
          value: botpress
        - name: POSTGRES_USER
          value: appadmin
        - name: POSTGRES_PASSWORD
          value: Admin4Chatbot
        - name: spring_profiles_active
          value: dev
        - name: APP_NAME
          value: kinetic-postgres-alpha
        - name: PGDATA
          value: /var/lib/postgresql/data/pgdata
        - name: NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: SERVICE
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        volumeMounts:
          - mountPath: /var/lib/postgresql/data
            subPath: pgdata
            name: postgredb
      volumes:
        - name: postgredb
          persistentVolumeClaim:
            claimName: kinetic-postgres-pvc
      securityContext:
        runAsNonRoot: false
        runAsUser: 1025
        fsGroup: 1025
      nodeSelector:
        agentpool: robotics
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: kinetic-postgres-pvc
  namespace: chatbot-dev
  labels:
    svc: kinetic-postgres-pvc
spec:
  storageClassName: managed-premium-retain
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  1. 为什么在更改 postgres 的 uid 和 gid 以匹配您作为 postgres 用户本身运行 AKS kubernetes pod 的 deployment.yaml 时有效。

这样可以避免错误,例如:

chmod:更改“var/lib/postgresql/data”的权限:权限被拒绝

chmod:更改“var/lib/postgresql/data/pgdata”的权限:权限被拒绝

  1. 如果您使用默认的 pgdata /var/lib/postgresql/data,为什么 Persistent 卷将无法工作,它会被挂载为 pod 存储,以使这项工作定义自定义 pgdata 并按如下方式挂载

     - name: PGDATA
       value: /var/lib/postgresql/data/pgdata
     - name: NAMESPACE
       valueFrom:
         fieldRef:
           fieldPath: metadata.namespace
     - name: SERVICE
       valueFrom:
         fieldRef:
           fieldPath: metadata.name
     volumeMounts:
       - mountPath: /var/lib/postgresql/data
         subPath: pgdata
         name: postgredb
    

我花了 2 周的时间才弄清楚这一点,希望它可以帮助像我一样尝试过的每个人。