在kubernetes上部署的身份验证mongo

fcg9iug3  于 2022-12-03  发布在  Kubernetes
关注(0)|答案(5)|浏览(407)

我尝试在kubernetes集群上使用身份验证配置mongo

kind: StatefulSet
metadata:
  name: mongo
spec:
  serviceName: "mongo"
  replicas: 1
template:
  metadata:
    labels:
      app: mongo
  spec:
    containers:
    - name: mongodb
      image: mongo:4.0.0
      env:
      - name: MONGO_INITDB_ROOT_USERNAME
        value: "admin"
      - name: MONGO_INITDB_ROOT_PASSWORD
# Get password from secret
        value: "abc123changeme"
      command:
      - mongod
      - --auth
      - --replSet
      - rs0
      - --bind_ip
      - 0.0.0.0
      ports:
      - containerPort: 27017
        name: web
      volumeMounts:
      - name: mongo-ps
        mountPath: /data/db
    volumes:
    - name: mongo-ps
      persistentVolumeClaim:
        claimName: mongodb-pvc

当我尝试使用用户名“admin”和密码“abc123changeme”进行身份验证时,我收到了"Authentication failed."
我如何配置mongo管理员的用户名和密码(我想从secret获得密码)?
谢谢

vdzxcuhz

vdzxcuhz1#

环境变量不起作用的原因是MONGO_INITDB环境变量由docker-entrypoint.sh映像(https://github.com/docker-library/mongo/tree/master/4.0)中的www.example.com脚本使用,但是当您在kubernetes文件中定义'command:'时,您会覆盖该入口点(请参见注解https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
请看下面的YML,它是根据我在网上找到的一些例子改编的。

  1. cvallance/mongo-k8s-sidecar查找任何与POD标签匹配的mongo示例,而不考虑名称空间,因此它将尝试与集群中的任何旧示例挂钩。这让我花了几个小时的时间来挠头,因为我从示例中删除了environment=标签,因为我们使用名称空间来隔离我们的环境...回顾起来很愚蠢,也很明显...开始时非常混乱(由于串扰,mongo日志会抛出各种身份验证错误和服务关闭类型错误)
    1.我是ClusterRoleBindings的新手,花了一段时间才意识到它们是集群级别的,我知道这似乎是显而易见的(尽管需要提供一个命名空间以使kubectl接受它),但这会导致我的命名空间在每个命名空间之间被覆盖,因此请确保为每个环境创建唯一的名称,以避免在一个命名空间中的部署扰乱另一个命名空间,因为ClusterRoleBinding会在以下情况下被覆盖:在群集中不唯一
  2. MONGODB_DATABASE需要设置为'admin'才能进行身份验证。
    1.我按照this example来配置依赖于sleep 5的身份验证,希望在尝试创建adminUser之前守护进程已经启动并运行。我发现这段时间不够长,所以一开始就升级了,因为创建adminUser失败显然会导致连接被拒绝的问题。后来我改变了sleep,用while循环和mongo的ping来测试守护进程,这更简单。
    1.如果你在一个container(例如lxc,cgroups,Docker等)中运行mongod,而这个container不能访问系统中所有可用的RAM,你必须将--wiredTigerCacheSizeGB设置为一个小于容器中可用RAM数量的值。确切的数量取决于容器中运行的其他进程。
  3. You need at least 3 nodes in a Mongo cluster !
    下面的YML应该会启动并在kubernetes中配置一个mongo副本集,并启用永久存储和身份验证。如果您连接到pod...
kubectl exec -ti mongo-db-0 --namespace somenamespace /bin/bash

mongo shell安装在映像中,所以你应该能够连接到replicaset与...

mongo mongodb://mongoadmin:adminpassword@mongo-db/admin?replicaSet=rs0

然后看到您得到rs 0:PRIMARY〉或rs 0:SECONDARY,这表明这两个pod在一个mongo replicateset中。使用rs.conf()从PRIMARY中验证这一点。

#Create a Secret to hold the MONGO_INITDB_ROOT_USERNAME/PASSWORD
#so we can enable authentication
apiVersion: v1
data:
     #echo -n "mongoadmin" | base64
    init.userid: bW9uZ29hZG1pbg==
    #echo -n "adminpassword" | base64
    init.password: YWRtaW5wYXNzd29yZA==
kind: Secret
metadata:
  name: mongo-init-credentials
  namespace: somenamespace
type: Opaque
---
# Create a secret to hold a keyfile used to authenticate between replicaset members
# this seems to need to be base64 encoded twice (might not be the case if this
# was an actual file reference as per the examples, but we're using a simple key
# here
apiVersion: v1
data:
  #echo -n "CHANGEMECHANGEMECHANGEME" | base64 | base64
  mongodb-keyfile: UTBoQlRrZEZUVVZEU0VGT1IwVk5SVU5JUVU1SFJVMUYK
kind: Secret
metadata:
  name: mongo-key
  namespace: somenamespace
type: Opaque
---
# Create a service account for Mongo and give it Pod List role
# note this is a ClusterROleBinding - the Mongo Pod will be able
# to list all pods present in the cluster regardless of namespace
# (and this is exactly what it does...see below)
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mongo-serviceaccount
  namespace: somenamespace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mongo-somenamespace-serviceaccount-view
  namespace: somenamespace
subjects:
- kind: ServiceAccount
  name: mongo-serviceaccount
  namespace: somenamespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: pod-viewer
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-viewer
  namespace: somenamespace
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["list"]
---
#Create a Storage Class for Google Container Engine
#Note fstype: xfs isn't supported by GCE yet and the
#Pod startup will hang if you try to specify it.
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  namespace: somenamespace
  name: mongodb-ssd-storage
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
allowVolumeExpansion: true
---
#Headless Service for StatefulSets
apiVersion: v1
kind: Service
metadata:
  namespace: somenamespace
  name: mongo-db
  labels:
    name: mongo-db
spec:
 ports:
 - port: 27017
   targetPort: 27017
 clusterIP: None
 selector:
   app: mongo
---
# Now the fun part
#
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  namespace: somenamespace
  name: mongo-db
spec:
  serviceName: mongo-db
  replicas: 3
  template:
    metadata:
      labels:
        # Labels MUST match MONGO_SIDECAR_POD_LABELS
        # and MUST differentiate between other mongo
        # instances in the CLUSTER not just the namespace
        # as the sidecar will search the entire cluster
        # for something to configure
        app: mongo
        environment: somenamespace
    spec:
      #Run the Pod using the service account
      serviceAccountName: mongo-serviceaccount
      terminationGracePeriodSeconds: 10
      #Prevent a Mongo Replica running on the same node as another (avoid single point of failure)
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - mongo
            topologyKey: "kubernetes.io/hostname"
      containers:
        - name: mongo
          image: mongo:4.0.12
          command:
            #Authentication adapted from https://gist.github.com/thilinapiy/0c5abc2c0c28efe1bbe2165b0d8dc115
            #in order to pass the new admin user id and password in
          - /bin/sh
          - -c
          - >
            if [ -f /data/db/admin-user.lock ]; then
              echo "KUBERNETES LOG $HOSTNAME- Starting Mongo Daemon with runtime settings (clusterAuthMode)"
              #ensure wiredTigerCacheSize is set within the size of the containers memory limit
              mongod --wiredTigerCacheSizeGB 0.5 --replSet rs0 --bind_ip 0.0.0.0 --smallfiles --noprealloc --clusterAuthMode keyFile --keyFile /etc/secrets-volume/mongodb-keyfile --setParameter authenticationMechanisms=SCRAM-SHA-1;
            else
              echo "KUBERNETES LOG $HOSTNAME- Starting Mongo Daemon with setup setting (authMode)"
              mongod --auth;
            fi;
          lifecycle:
              postStart:
                exec:
                  command:
                  - /bin/sh
                  - -c
                  - >
                    if [ ! -f /data/db/admin-user.lock ]; then
                      echo "KUBERNETES LOG $HOSTNAME- no Admin-user.lock file found yet"
                      #replaced simple sleep, with ping and test.
                      while (! mongo --eval "db.adminCommand('ping')"); do sleep 10; echo "KUBERNETES LOG $HOSTNAME - waiting another 10 seconds for mongo to start" >> /data/db/configlog.txt; done;
                      touch /data/db/admin-user.lock
                      if [ "$HOSTNAME" = "mongo-db-0" ]; then
                        echo "KUBERNETES LOG $HOSTNAME- creating admin user ${MONGODB_USERNAME}"
                        mongo --eval "db = db.getSiblingDB('admin'); db.createUser({ user: '${MONGODB_USERNAME}', pwd: '${MONGODB_PASSWORD}', roles: [{ role: 'root', db: 'admin' }]});" >> /data/db/config.log
                      fi;
                      echo "KUBERNETES LOG $HOSTNAME-shutting mongod down for final restart"
                      mongod --shutdown;
                    fi;
          env:
            - name: MONGODB_USERNAME
              valueFrom:
                secretKeyRef:
                  name: mongo-init-credentials
                  key: init.userid
            - name: MONGODB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mongo-init-credentials
                  key: init.password
          ports:
            - containerPort: 27017
          livenessProbe:
            exec:
              command:
              - mongo
              - --eval
              - "db.adminCommand('ping')"
            initialDelaySeconds: 5
            periodSeconds: 60
            timeoutSeconds: 10
          readinessProbe:
            exec:
              command:
              - mongo
              - --eval
              - "db.adminCommand('ping')"
            initialDelaySeconds: 5
            periodSeconds: 60
            timeoutSeconds: 10
          resources:
            requests:
              memory: "350Mi"
              cpu: 0.05
            limits:
              memory: "1Gi"
              cpu: 0.1
          volumeMounts:
            - name: mongo-key
              mountPath: "/etc/secrets-volume"
              readOnly: true
            - name: mongo-persistent-storage
              mountPath: /data/db
        - name: mongo-sidecar
          image: cvallance/mongo-k8s-sidecar
          env:
            # Sidecar searches for any POD in the CLUSTER with these labels
            # not just the namespace..so we need to ensure the POD is labelled
            # to differentiate it from other PODS in different namespaces
            - name: MONGO_SIDECAR_POD_LABELS
              value: "app=mongo,environment=somenamespace"
            - name: MONGODB_USERNAME
              valueFrom:
                secretKeyRef:
                  name: mongo-init-credentials
                  key: init.userid
            - name: MONGODB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mongo-init-credentials
                  key: init.password
            #don't be fooled by this..it's not your DB that
            #needs specifying, it's the admin DB as that
            #is what you authenticate against with mongo.
            - name: MONGODB_DATABASE
              value: admin
      volumes:
      - name: mongo-key
        secret:
          defaultMode: 0400
          secretName: mongo-key
  volumeClaimTemplates:
  - metadata:
      name: mongo-persistent-storage
      annotations:
        volume.beta.kubernetes.io/storage-class: "mongodb-ssd-storage"
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
yizd12fk

yizd12fk2#

假设您创建了一个密码:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

下面是从kubernetes yaml文件中的secret获取值的代码片段:

env:
      - name: MONGO_INITDB_ROOT_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
g0czyy6m

g0czyy6m3#

我发现此问题与www.example.com中的错误有关docker-entrypoint.sh,并且在节点上检测到numactl时会发生此问题。
尝试以下简化代码(它将numactl排除在外):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongo-deployment
  labels:
    app: mongo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      labels:
        app: mongo
    spec:
      containers:
      - name: mongo
        image: mongo:4.0.0
        command:
        - /bin/bash
        - -c
        # mv is not needed for later versions e.g. 3.4.19 and 4.1.7
        - mv /usr/bin/numactl /usr/bin/numactl1 && source docker-entrypoint.sh mongod
        env:
        - name: MONGO_INITDB_ROOT_USERNAME
          value: "xxxxx"
        - name: MONGO_INITDB_ROOT_PASSWORD
          value: "xxxxx"
        ports:
        - containerPort: 27017

我提出了一个问题:https://github.com/docker-library/mongo/issues/330
希望它会在某个时候被修复,所以不需要黑客:o)

hs1rzwqc

hs1rzwqc4#

添加以下内容为我解决了问题:

- name: ME_CONFIG_MONGODB_ENABLE_ADMIN
  value: "true"

看起来默认设置为**“false”**。
如果使用的是Kubernetes,则可以使用以下命令检查失败原因:

kubernetes logs <pod name>
8ljdwjyq

8ljdwjyq5#

这就是对我有效的方法;

kind: StatefulSet
metadata:
  name: mongo
spec:
  serviceName: "mongo"
  replicas: 1
template:
  metadata:
    labels:
      app: mongo
  spec:
    containers:
    - name: my-mongodb-pod
      image: mongo:4.4.3
      env:
        - name: MONGO_INITDB_ROOT_USERNAME
          value: "someMongoUser"
        - name: MONGO_INITDB_ROOT_PASSWORD
          value: "somePassword"
        - name: MONGO_REPLICA_SET
          value: "myReplicaSet"
        - name: MONGO_PORT
          value: "27017"
      # Note, to disable non-auth in mongodb is kind of complicated[4]
      # Note, the `_getEnv` function is internal and undocumented[3].
      #
      # 1. https://gist.github.com/thilinapiy/0c5abc2c0c28efe1bbe2165b0d8dc115
      # 2. https://stackoverflow.com/a/54726708/2768067
      # 3. https://stackoverflow.com/a/67037065/2768067
      # 4. https://www.mongodb.com/features/mongodb-authentication
      command:
        - /bin/sh
        - -c
        - >
          set -x # print command been ran
          set -e # fail if any command fails

          env;
          ps auxwww;

          printf "\n\t mongod:: start in the background \n\n";
          mongod \
            --port="${MONGO_PORT}" \
            --bind_ip_all \
            --replSet="${MONGO_REPLICA_SET}" \
            --quiet > /tmp/mongo.log.json 2>&1 &

          sleep 9;
          ps auxwww;

          printf "\n\t mongod: set master \n\n";
          mongo --port "${MONGO_PORT}" --eval '
            rs.initiate({});
            sleep(3000);';

          printf "\n\t mongod: add user \n\n";
          mongo --port "${MONGO_PORT}" --eval '
            db.getSiblingDB("admin").createUser({
              user: _getEnv("MONGO_INITDB_ROOT_USERNAME"), 
              pwd: _getEnv("MONGO_INITDB_ROOT_PASSWORD"), 
              roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
            });';

          printf "\n\t mongod: shutdown \n\n";
          mongod --shutdown;
          sleep 3;
          ps auxwww;

          printf "\n\t mongod: restart with authentication \n\n";
          mongod \
            --auth \
            --port="${MONGO_PORT}" \
            --bind_ip_all \
            --replSet="${MONGO_REPLICA_SET}" \
            --verbose=v

相关问题