我有一个运行节点JS的基于容器的应用程序,而我的后端是mongoDB容器。
基本上,我打算做的是在kubernetes中运行它。
我已将其作为单独的容器部署在当前环境中,并且工作正常。我有一个mongoDB容器和一个节点JS容器。
连接两个我会做的
docker run -d --link=mongodb:mongodb -e MONGODB_URL='mongodb://mongodb:27017/user' -p 4000:4000 e922a127d049
我的connection.js运行如下,它将带MONGODB_URL并传递到我的节点JS容器中的process.env中。然后,我的connection.js将MONGODB_URL提取到mongoDbUrl中,如下所示。
const mongoClient = require('mongodb').MongoClient;
const mongoDbUrl = process.env.MONGODB_URL;
//console.log(process.env.MONGODB_URL)
let mongodb;
function connect(callback){
mongoClient.connect(mongoDbUrl, (err, db) => {
mongodb = db;
callback();
});
}
function get(){
return mongodb;
}
function close(){
mongodb.close();
}
module.exports = {
connect,
get,
close
};
要在k8s上部署,我已经为
编写了一个yaml文件。1)Web控制器 2)网络服务 3)mongoDB控制器 4)mongoDB服务
这是我当前的mongoDB控制器
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mongo-deployment
spec:
replicas: 1
template:
metadata:
labels:
name: mongo
spec:
containers:
- image: mongo:latest
name: mongo
ports:
- name: mongo
containerPort: 27017
hostPort: 27017
我的mongoDB服务
apiVersion: v1
kind: Service
metadata:
labels:
name: mongodb
name: mongodb
spec:
ports:
- port: 27017
targetPort: 27017
selector:
name: mongo
我的网络控制器
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: web
name: web-controller
spec:
replicas: 1
selector:
name: web
template:
metadata:
labels:
name: web
spec:
containers:
- image: leexha/node_demo:21
env:
- name: MONGODB_URL
value: "mongodb://mongodb:27017/user"
name: web
ports:
- containerPort: 4000
name: node-server
和我的网络服务
apiVersion: v1
kind: Service
metadata:
name: web
labels:
name: web
spec:
type: NodePort
ports:
- port: 4000
targetPort: 4000
protocol: TCP
selector:
name: web
我能够在本地kubernetes集群上部署所有服务和Pod。
但是,当我尝试通过Nodeport访问Web应用程序时,它告诉我mongoDB存在连接错误。
TypeError: Cannot read property 'collection' of null
at /app/app.js:24:17
at Layer.handle [as handle_request]
这是我的app.js节点JS代码
var bodyParser = require('body-parser')
, MongoClient = require('mongodb').MongoClient
, PORT = 4000
, instantMongoCrud = require('express-mongo-crud') // require the module
, express = require('express')
, app = express()
, path = require('path')
, options = { //specify options
host: `localhost:${PORT}`
}
, db = require('./connection')
// connection to database
db.connect(() => {
app.use(bodyParser.json()); // add body parser
app.use(bodyParser.urlencoded({ extended: true }));
//console.log('Hello ' + process.env.MONGODB_URL)
// get function
app.get('/', function(req, res) {
db.get().collection('users').find({}).toArray(function(err, data){
if (err)
console.log(err)
else
res.render('../views/pages/index.ejs',{data:data});
});
});
很明显,当我的节点JS应用程序无法读取mongoDB服务时,这是一个错误。
起初我以为我的MONGODB_URL没有设置在我的容器中。但是,当我使用
检查nodeJS容器时kubectl exec -it web-controller-r269f /bin/bash
并回显我的MONGODB_URL,它返回我正确的mongodb:// mongodb:27017 / user。
我很不确定自己在做什么错,因为我很确定自己已经按顺序完成了所有工作,并且我的Web部署正在与mongoDB服务进行通信。有什么帮助吗?抱歉,我仍在学习kubernetes,请原谅任何错误
答案 0 :(得分:1)
[编辑]
很抱歉,连接字符串mongodb://mongodb:27017
实际上可以工作。我尝试使用dns查询该名称,即使没有指定“ .default.svc ...”,它也能够解析为正确的IP地址。
root@web-controller-mlplb:/app# host mongodb
mongodb.default.svc.cluster.local has address 10.108.119.125
@Anshul Jindal是正确的,表明您有竞争条件,其中Web Pod先于数据库Pod加载。您可能正在kubectl apply -f .
尝试在包含这些yaml的文件夹中进行重置kubectl delete -f .
。然后kubectl apply
首先显示数据库,然后几秒钟后,kubectl apply
Web出现。您还可以在运行Pod之前,使用Init Containers检查mongo服务何时准备就绪。或者,您也可以在node.js应用程序中进行检查。
在Node.js中等待mongodb服务的示例
在connection.js文件中,您可以更改连接功能,使其在第一次失败时(即由于mongodb service / pod尚不可用),它将每3秒重试一次,直到可以连接为止。成立。这样,您甚至不必担心应用kubernetes清单的加载顺序,只需kubectl apply -f .
let RECONNECT_INTERVAL = 3000
function connect(callback){
mongoClient.connect(mongoDbUrl, (err, db) => {
if (err) {
console.log("attempting to reconnect to " + mongoDbUrl)
setTimeout(connect.bind(this, callback), RECONNECT_INTERVAL)
return
} else {
mongodb = db;
callback();
}
});
}