cloudflare_在天蓝色和cloudflare上使用水平分割DNS对无服务器mongodb副本集进行地形化...

cloudflare

Occasionally, some scenarios require non-orthodox deployments, whether it’s due to a temporary state of a system such as moving from an on-prem deployment to the cloud, or as convenient way of testing and validating a deployment with all of its moving parts.Such is the case of the example in this article, which deploys a MongoDB, a database that needs no introduction, replica set on Azure, but, and this is the not-so-orthodox area of this deployment, exposes it to the external world in addition to being available on an internal private virtual network.

有时,某些情况需要非正统部署,无论是由于系统的临时状态(例如从本地部署迁移到云),还是由于测试和验证部署及其所有移动部分的便捷方式而导致的。本文中的示例就是这种情况,该示例部署了一个MongoDB,一个不需要引入的数据库,在Azure上设置了副本,但这是该部署的不太传统的领域,将其暴露给了外部世界除了可以在内部专用虚拟网络上使用。

What’s non-orthodox about it? Well, usually a database is not exposed directly to the outside world, instead, there are one or more software layers, which also execute additional logic and just store and retrieve data.

这是什么非正统的? 好吧,通常数据库并不直接暴露给外界,而是有一个或多个软件层,它们也执行附加的逻辑并仅存储和检索数据。

问题 (The Problem)

If you’ve worked with MongoDB replica sets before, you should be familiar with the replica set connection string which includes multiple hosts:

如果您以前使用过MongoDB副本集,则应该熟悉包含多个主机的副本集连接字符串:

mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017,mongodb2.example.com:27017/?replicaSet=myRepl

This is where things get complicated, because if we need the hosts to be available from both the internal network and the external world, we need to use hosts names that can be resolved from both the internal network and the external world, and they have to be the same host names, as MongoDB replica sets are only aware of the host names that were used when they were joined to the replica set, so two different names per host won’t work.

这使事情变得复杂,因为如果我们需要内部网络和外部世界都可以使用主机,则需要使用可以从内部网络和外部世界都解析的主机名,并且它们必须是相同的主机名,因为MongoDB副本集仅知道将它们加入副本集时使用的主机名,因此每个主机两个不同的名称将不起作用。

解决方案—水平分割DNS (The Solution — Split Horizon DNS)

To solve the problem, something called a split-horizon DNS needs to be used, and although the name suggests something out-of-the-ordinary, it actually means using two DNS zones, one private internal and one public external, with the same name, such as example.com.

为了解决该问题,需要使用一种称为“水平分割DNS”的方法,尽管该名称暗示了一些不寻常的用法,但这实际上意味着使用两个DNS区域,一个是私有内部区域,一个是公共外部区域,并且使用相同的区域。名称,例如example.com

By doing so, we’ll be able to register a host named node1.example.com once with a private IP in the private internal zone and once with a public IP in the public external zone, making the MongoDB connection string shown above valid for both environments.

这样,我们将能够在私有内部区域中使用私有IP注册一次主机,并在公共外部区域中使用公共IP注册一次名为node1.example.com的主机,从而使上面显示的MongoDB连接字符串对两种环境。

这个例子 (The Example)

The complete Terraform based example, which deploys three MongoDB nodes, exposes them to the outside world using an Azure Firewall, registers the internal IP addresses to an Azure Private DNS and registers the public IP addresses to a public DNS zone on Cloudflare, can be found in this GitHub repository:

可以找到完整的基于Terraform的示例,该示例部署了三个MongoDB节点,使用Azure防火墙将其公开给外部世界,将内部IP地址注册到Azure私有DNS,并将公共IP地址注册到Cloudflare上的公共DNS区域。在此GitHub存储库中:

For brevity reasons, I won’t cover the entire example here, but only the sections that make the replica set and DNS zones work as required, starting with the bash script that is executed by each node on startup to join the replica set:

为简洁起见,在此我将不讨论整个示例,而仅使构成副本集和DNS区域的部分按要求工作,从启动时每个节点执行以加入副本集的bash脚本开始:

#!/bin/sh


until /usr/bin/mongo "mongodb://127.0.0.1:27017" --quiet --eval "db.getMongo()"; do
    sleep 1
done


/usr/bin/mongo "mongodb://127.0.0.1:27017" <<EOF
    rs.initiate({_id: "${replica_set}", members: [
        ${members}
    ], settings: {electionTimeoutMillis: 2000}});
EOF

You’ll notice that this is actually a template loaded by Terraform, which also populates the ${replica_set} and ${members} originating from the main entry point like so:

您会注意到,这实际上是Terraform加载的模板,它还会填充来自主入口点的${replica_set}${members} ,如下所示:

locals {
  deployment_name = "mongo"
  nodes_count     = 3
  location        = "eastus"
  zone_name       = "example.com"
  replica_set     = "mongo-set"
  nodes_list = {
    for index in range(1, local.nodes_count + 1) : index => "${local.deployment_name}${index}.${local.zone_name}"
  }
}

Once the script creates a node running on Azure Container Instances using the mongo-node module which is part of the example:

一旦脚本创建了使用mongo-node模块运行在Azure容器实例上mongo-node ,该示例就是一部分:

module "mongo_node" {
  source = "./modules/mongo-node"


  deployment_name      = "${local.deployment_name}"
  location             = local.location
  nodes_count          = local.nodes_count
  resource_group_name  = azurerm_resource_group.this.name
  network_profile_id   = azurerm_network_profile.this.id
  zone_name            = local.zone_name
  storage_account_name = azurerm_storage_account.this.name
  storage_primary_key  = azurerm_storage_account.this.primary_access_key
  replica_set          = local.replica_set
  nodes_list           = local.nodes_list
}

An internal private IP address is registered to the private DNS zone (as part of the module’s script):

内部私有IP地址已注册到私有DNS区域(作为模块脚本的一部分):

resource "azurerm_private_dns_a_record" "this" {
  count               = var.nodes_count
  name                = "${var.deployment_name}${count.index + 1}"
  zone_name           = var.zone_name
  resource_group_name = var.resource_group_name
  ttl                 = 300
  records             = [azurerm_container_group.this[count.index].ip_address]
}

For the public side of our deployment, an Azure Firewall and associated public addresses are created (one IP address per node) using the firewall module:

对于我们部署的公共方面,使用firewall模块创建了Azure防火墙和关联的公共地址(每个节点一个IP地址):

module "firewall" {
  source = "./modules/firewall"


  deployment_name     = "${local.deployment_name}3"
  resource_group_name = azurerm_resource_group.this.name
  location            = local.location
  pips_count          = local.nodes_count
  subnet_id           = azurerm_subnet.external.id
}

And SNAT and network rules on the above firewall, that will forward the traffic from the external IP addresses to the matching internal MongoDB nodes using the network-rule and nat-rule modules:

以及上述防火墙上的SNAT和网络规则,它将使用network-rulenat-rule模块将流量从外部IP地址转发到匹配的内部MongoDB节点:

module "netowork_rule" {
  source = "./modules/network-rule"


  deployment_name     = "${local.deployment_name}"
  resource_group_name = azurerm_resource_group.this.name
  firewall_name       = module.firewall.this_name
  port                = 27017
  ip_addresses        = module.firewall.this_pips
}


module "nat_rule" {
  source = "./modules/nat-rule"


  deployment_name      = "${local.deployment_name}"
  resource_group_name  = azurerm_resource_group.this.name
  firewall_name        = module.firewall.this_name
  port                 = 27017
  public_ip_addresses  = module.firewall.this_pips
  private_ip_addresses = module.mongo_node.this_ips
}

Lastly, public DNS records are created on Cloudflare using the IP addresses that were created with the firewall using the cloudflare-record module:

最后,使用使用cloudflare-record模块通过防火墙创建的IP地址在Cloudflare上创建公共DNS记录:

module "cloudflare_record" {
  source = "./modules/cloudflare-record"


  deployment_name = local.deployment_name
  zone_name       = local.zone_name
  pips            = module.firewall.this_pips
}

部署测试(Deployment Testing)

To test the deployment, a MongoDB connection string similar to the following will be required (ensure you set node names and replica set name to whatever values you used):

要测试部署,将需要类似于以下内容的MongoDB连接字符串(确保将节点名称和副本集名称设置为所使用的任何值):

mongodb://mongo1.example.com:27017,mongo2.example.com:27017,mongo3.example.com:27017/?replicaSet=mongo-set

And either use the mongo command line tool, or something like MongoDBCompass which is available here:

并且可以使用mongo命令行工具,也可以使用以下类似的MongoDBCompass之类的东西:

结论 (Conclusion)

As exposing databases to the external world is always risky, even when using a firewall, it is recommended to also restrict the rules even further by setting source IP addresses which can access the nodes and use transport layer encryption to protect the information passing between the consumers and the MongoDB nodes.

由于即使在使用防火墙的情况下,将数据库暴露在外部也总是存在风险,因此建议通过设置可以访问节点的源IP地址并使用传输层加密来保护使用者之间传递的信息,从而进一步限制规则。和MongoDB节点。

翻译自: https://medium.com/microsoftazure/terraforming-a-serverless-mongodb-replica-set-with-split-horizon-dns-on-azure-and-cloudflare-9687e37dacf1

cloudflare

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值