OpenShift Access Mongodb Pod from another Pod

2019-07-24 17:04发布

问题:

I'm currentrly trying to deploy a mongodb pod on OpenShift and accessing this pod from another node.js application via mongoose. Now at first everything seems fine. I have created a route to the mongodb and when i open it in my browser I get

It looks like you are trying to access MongoDB over HTTP on the native driver port.

So far so good. But when I try opening a connection to the database from another pod it refuses the connection. I'm using the username and password provided by OpenShift and connect to

mongodb://[username]:[password]@[host]:[port]/[dbname]

unfortunately without luck. It seems that the database is just accepting connections from the localhost. However I could not find out how to change that. Would be great if someone had an idea.

Heres the Deployment Config

   apiVersion: v1
kind: DeploymentConfig
metadata:
  annotations:
    template.alpha.openshift.io/wait-for-ready: "true"
  creationTimestamp: null
  generation: 1
  labels:
    app: mongodb-persistent
    template: mongodb-persistent-template
  name: mongodb
spec:
  replicas: 1
  selector:
    name: mongodb
  strategy:
    activeDeadlineSeconds: 21600
    recreateParams:
      timeoutSeconds: 600
    resources: {}
    type: Recreate
  template:
    metadata:
      creationTimestamp: null
      labels:
        name: mongodb
    spec:
      containers:
      - env:
        - name: MONGODB_USER
          valueFrom:
            secretKeyRef:
              key: database-user
              name: mongodb
        - name: MONGODB_PASSWORD
          valueFrom:
            secretKeyRef:
              key: database-password
              name: mongodb
        - name: MONGODB_ADMIN_PASSWORD
          valueFrom:
            secretKeyRef:
              key: database-admin-password
              name: mongodb
        - name: MONGODB_DATABASE
          valueFrom:
            secretKeyRef:
              key: database-name
              name: mongodb
        image: registry.access.redhat.com/rhscl/mongodb-32-rhel7@sha256:82c79f0e54d5a23f96671373510159e4fac478e2aeef4181e61f25ac38c1ae1f
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 27017
          timeoutSeconds: 1
        name: mongodb
        ports:
        - containerPort: 27017
          protocol: TCP
        readinessProbe:
          exec:
            command:
            - /bin/sh
            - -i
            - -c
            - mongo 127.0.1:27017/$MONGODB_DATABASE -u $MONGODB_USER -p $MONGODB_PASSWORD
              --eval="quit()"
          failureThreshold: 3
          initialDelaySeconds: 3
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          limits:
            memory: 512Mi
        securityContext:
          capabilities: {}
          privileged: false
        terminationMessagePath: /dev/termination-log
        volumeMounts:
        - mountPath: /var/lib/mongodb/data
          name: mongodb-data
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: mongodb-data
        persistentVolumeClaim:
          claimName: mongodb
  test: false
  triggers:
  - imageChangeParams:
      automatic: true
      containerNames:
      - mongodb
      from:
        kind: ImageStreamTag
        name: mongodb:3.2
        namespace: openshift
    type: ImageChange
  - type: ConfigChange
status:
  availableReplicas: 0
  latestVersion: 0
  observedGeneration: 0
  replicas: 0
  unavailableReplicas: 0
  updatedReplicas: 0

The Service Config

apiVersion: v1
kind: Service
metadata:
  annotations:
    template.openshift.io/expose-uri: mongodb://{.spec.clusterIP}:{.spec.ports[?(.name=="mongo")].port}
  creationTimestamp: null
  labels:
    app: mongodb-persistent
    template: mongodb-persistent-template
  name: mongodb
spec:
  ports:
  - name: mongo
    port: 27017
    protocol: TCP
    targetPort: 27017
  selector:
    name: mongodb
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

and the pod

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/created-by: |
      {"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"some-name-space","name":"mongodb-3","uid":"xxxx-xxx-xxx-xxxxxx","apiVersion":"v1","resourceVersion":"244413593"}}
    kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu request for container
      mongodb'
    openshift.io/deployment-config.latest-version: "3"
    openshift.io/deployment-config.name: mongodb
    openshift.io/deployment.name: mongodb-3
    openshift.io/scc: nfs-scc
  creationTimestamp: null
  generateName: mongodb-3-
  labels:
    deployment: mongodb-3
    deploymentconfig: mongodb
    name: mongodb
  ownerReferences:
  - apiVersion: v1
    controller: true
    kind: ReplicationController
    name: mongodb-3
    uid: a694b832-5dd2-11e8-b2fc-40f2e91e2433
spec:
  containers:
  - env:
    - name: MONGODB_USER
      valueFrom:
        secretKeyRef:
          key: database-user
          name: mongodb
    - name: MONGODB_PASSWORD
      valueFrom:
        secretKeyRef:
          key: database-password
          name: mongodb
    - name: MONGODB_ADMIN_PASSWORD
      valueFrom:
        secretKeyRef:
          key: database-admin-password
          name: mongodb
    - name: MONGODB_DATABASE
      valueFrom:
        secretKeyRef:
          key: database-name
          name: mongodb
    image: registry.access.redhat.com/rhscl/mongodb-32-rhel7@sha256:82c79f0e54d5a23f96671373510159e4fac478e2aeef4181e61f25ac38c1ae1f
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 3
      initialDelaySeconds: 30
      periodSeconds: 10
      successThreshold: 1
      tcpSocket:
        port: 27017
      timeoutSeconds: 1
    name: mongodb
    ports:
    - containerPort: 27017
      protocol: TCP
    readinessProbe:
      exec:
        command:
        - /bin/sh
        - -i
        - -c
        - mongo 127.0.1:27017/$MONGODB_DATABASE -u $MONGODB_USER -p $MONGODB_PASSWORD
          --eval="quit()"
      failureThreshold: 3
      initialDelaySeconds: 3
      periodSeconds: 10
      successThreshold: 1
      timeoutSeconds: 1
    resources:
      limits:
        memory: 512Mi
      requests:
        cpu: 250m
        memory: 512Mi
    securityContext:
      capabilities:
        drop:
        - KILL
        - MKNOD
        - SETGID
        - SETUID
        - SYS_CHROOT
      privileged: false
      runAsUser: 1049930000
      seLinuxOptions:
        level: s0:c223,c212
    terminationMessagePath: /dev/termination-log
    volumeMounts:
    - mountPath: /var/lib/mongodb/data
      name: mongodb-data
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-rfvr5
      readOnly: true
  dnsPolicy: ClusterFirst
  imagePullSecrets:
  - name: default-dockercfg-3mpps
  nodeName: thenode.name.net
  nodeSelector:
    region: primary
  restartPolicy: Always
  securityContext:
    fsGroup: 1049930000
    seLinuxOptions:
      level: s0:c223,c212
    supplementalGroups:
    - 5555
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  volumes:
  - name: mongodb-data
    persistentVolumeClaim:
      claimName: mongodb
  - name: default-token-rfvr5
    secret:
      defaultMode: 420
      secretName: default-token-rfvr5
status:
  phase: Pending

回答1:

Ok that was a long search and finally I was able to solve it. My first mistake was, that routes are not suited to make a connection to a database as they only use the http-protocol.

Now there were 2 usecases left for me

  1. You're working on your local machine and want to test code that you later upload to OpenShift
  2. You deploy that code to OpenShift (has to be in the same project but is a different app than the database)

1. Local Machine

Since the route doesn't work port forwarding is used. I've read that before but didn't really understand what it meant (i thought the service itsself is forwading ports already).

When you are on your local machine you will do the following with the oc

oc port-forward <pod-name> <local-port>:<remote-port>

You'll get the info that the port is forwarded. Now the thing is, that in your app you will now connect to localhost (even on your local machine)

2. App running on OpenShift

After you will upload your code to OpenShift(In my case, just Add to project --> Node.js --> Add your repo), localhost will not be working any longer. What took a while for me to understand is that as long as you are in the same project you will have a lot of information in your environment variables. So just check the name of the service of your database (in my case mongodb) and you will find the host and port to use

Summary

Here's a little code example that works now, as well on the local machine as on OpenShift. I have already set up a persistand MongoDB on OpenShift called mongodb.

The code doesn't do much, but It will make a connection and tell you that it did, so you know it's working.

var mongoose = require('mongoose');

// Connect to Mongodb
var username = process.env.MONGO_DB_USERNAME || 'someUserName';
var password = process.env.MONGO_DB_PASSWORD || 'somePassword';

var host = process.env.MONGODB_SERVICE_HOST || '127.0.0.1';
var port = process.env.MONGODB_SERVICE_PORT || '27017';

var database = process.env.MONGO_DB_DATABASE || 'sampledb';
console.log('---DATABASE PARAMETERS---');
console.log('Host: ' + host);
console.log('Port: ' + port);
console.log('Username: ' + username);
console.log('Password: ' + password); 
console.log('Database: ' + database);



var connectionString = 'mongodb://' + username + ':' + password +'@' + host + ':' + port + '/' + database;
console.log('---CONNECTING TO---');
console.log(connectionString);
mongoose.connect(connectionString);

mongoose.connection.once('open', (data) => {
    console.log('Connection has been made');
    console.log(data);
});