部署基于etcd的coredns集群

简介: 部署基于etcd的coredns集群

前言

现需要为公司搭建私有DNS,私有服务器都使用私有DNS的地址,便于访问内部自定义的域名。采用CoreDNS + ETCD方案部署,coredns和etcd都以三实例运行,etcd为集群模式,使用nginx做coredns的udp负载均衡,避免单机性能问题。另使用prometheus监控coredns和etcd。

本文中的etcd、coredns、prometheus都以二进制方式运行,也可以用docker容器。

环境信息

IP 系统版本 应用 备注
192.168.0.10 CentOS 7.9 x86_64 Nginx 1.21 udp负载均衡
192.168.0.11 CentOS 7.9 x86_64 coredns v1.10.0, etcd v3.5.4
192.168.0.12 CentOS 7.9 x86_64 coredns v1.10.0, etcd v3.5.4
192.168.0.13 CentOS 7.9 x86_64 coredns v1.10.0, etcd v3.5.4
192.168.0.14 CentOS 7.9 x86_64 prometheus

大致架构如下图

image.png

步骤

1. 部署etcd

  1. 官方下载etcd的二进制压缩包,将解压后目录内的二进制文件放到/usr/local/bin
  2. 找个空目录,执行启动脚本。注意修改每个etcd服务器的IP。脚本里面用python自动获取本机ip,然后根据ip启动对应的etcd。(PS:其实脚本里面的启动函数写重复了,只需要写一个然后传参就行了。)
#!/bin/bash
set -u
script_dir=$(cd $(dirname $0) && pwd)
# 注意修改IP
etcd1IP='192.168.0.11'
etcd2IP='192.168.0.12'
etcd3IP='192.168.0.13'
etcdClusterToken='etcd-cluster-1'
function getLocalIP(){
    # 通过python获取本机IP, 如果新的linux发行版默认没有python2, 注意更改为python3
    cat > /tmp/getLocalIP.py <<EOF
#!/usr/bin/env python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 53))
print(s.getsockname()[0])
EOF
    IP=$(python /tmp/getLocalIP.py)
}
function start() {
    nohup etcd --name $1 \
        --listen-client-urls http://$2:2379 \
        --advertise-client-urls http://$2:2379 \
        --listen-peer-urls http://$2:2380 \
        --initial-advertise-peer-urls http://$2:2380 \
        --initial-cluster-token ${etcdClusterToken} \
        --initial-cluster="etcd1=http://${etcd1IP}:2380,etcd2=http://${etcd2IP}:2380,etcd3=http://${etcd3IP}:2380" \
        --initial-cluster-state 'new' \
        --enable-pprof \
        --logger 'zap' \
        --log-outputs=stderr \
        --data-dir="${script_dir}/data" > ${script_dir}/logs/app.log 2>&1 &
}
function main() {
    mkdir -p ./{data,logs}
    getLocalIP
    case $IP in
        $etcd1IP)
            start etcd1 ${IP}
            ;;
        $etcd2IP)
            start etcd2 ${IP}
            ;;
        $etcd3IP)
            start etcd3 ${IP}
            ;;
        *)
            echo "Unknown Node ip"
    esac
}
main
  1. 测试集群是否正常
# 如果正常则全部显示successfully
etcdctl --endpoints http://192.168.0.11:2379,http://192.168.0.12:2379,http://192.168.0.13:2379 endpoint health

2. 部署coredns

  1. 从官方github仓库下载二进制包,个人一般会把coredns的二进制文件放到coredns/bin目录下
  2. 编写配置文件coredns.conf/Corefile。注意修改本机IP和etcd实例的host
.:53 {
    # 绑定本机IP
    bind 192.168.0.11
    etcd {
        path /coredns
        endpoint http://192.168.0.11:2379 http://192.168.0.12:2379 http://192.168.0.13:2379
        fallthrough
    }
    # 最后所有的都转发到系统配置的上游dns服务器去解析
    forward . /home/apps/coredns/conf/forwards
    # 缓存时间ttl
    cache 1800
    # 自动加载配置文件的间隔时间
    reload 6s
    # 输出日志
    #log
    # 输出错误
    errors
    # 监控
    prometheus 192.168.0.11:19097
}

其中forwards内容如下:

nameserver 223.6.6.6
nameserver 223.5.5.5
  1. 通过脚本启动coredns
#!/bin/bash
# description: 启动CoreDNS
set -u
scriptDir=$(cd $(dirname $0) && pwd)
baseDir=$(cd ${scriptDir}/.. && pwd)
pidFile=${baseDir}/logs/app.pid
function prepare(){
    # 检查当前用户是否为root
    if [[ $(whoami) != "root" ]]; then
        echo "please use root privilege"
        exit 1
    fi
    # 检查是否存在配置文件, 无则报错退出
    if [[ ! -f ${baseDir}/conf/Corefile ]]; then
        echo "${baseDir}/conf/Corefile not found"
        exit 1
    fi
    
    # 检测是否存在日志目录, 无则创建
    if [[ ! -d ${baseDir}/logs ]]; then
        mkdir -p ${baseDir}/logs
    fi
    
    # 检查进程是否已存在, 存在则退出
    ps -ef | grep -v grep | grep ${scriptDir}/coredns > /dev/null
    if [[ $? -eq 0 ]]; then
        echo "coredns is running"
        exit 1
    fi
}
function startApp(){
    nohup ${scriptDir}/coredns --conf ${baseDir}/conf/Corefile \
        -pidfile ${pidFile} > ${baseDir}/logs/start.log 2>&1 &
}
function check(){
    # 检查是否正常启动
    for i in $(seq 2); do
        echo "checking coredns whether is running or not ..."
        sleep 1
    done
    ps -ef | grep -v grep | grep ${scriptDir}/coredns > /dev/null
    if [[ $? -eq 0 ]]; then
        echo "coredns is running"
    fi
}
function main(){
    prepare
    startApp
    check
}
main

3. nginx配置udp负载均衡

PS:强调一点,nginx早就支持tcp和udp的四层网络代理转发了,别再听信一些老掉牙的教程说nginx只支持http的七层网络代理转发。

nginx在stream域的配置udp的网络转发,以下为示例

stream {
    upstream coredns {
        server 192.168.0.11:53;
        server 192.168.0.12:53;
        server 192.168.0.13:53;
    }
    server {
        listen 53 udp;
        proxy_pass coredns;
    }
}

4. 测试dns是否可用

  1. 通过etcdctl添加一条dns解析记录。这里将zhangsan.com解析到192.168.0.10
etcdctl --endpoints http://192.168.0.11:2379,http://192.168.0.12:2379,http://192.168.0.13:2379 put /coredns/com/zhangsan/x1 '{"host":"192.168.0.10", "ttl": 60}'
  1. 使用nslookup工具测试。如果提示没有命令,centos 可安装bind-utils,ubuntu可安装dns-utils
nslookup zhangsan.com 192.168.0.10
  1. 如果上条命令正常返回解析结果,说明coredns集群搭建完成,后面新增服务器只需要将dns配置为nginx的地址即可。

5. 配置prometheus监控

prometheus的安装和使用略过,以下仅为etcd和coredns的监控配置示例,使用的是基于文件的服务发现。

- job_name: "etcd"
    file_sd_configs:
    - files: ['/home/apps/prometheus/sd_configs/etcd/*.yaml']
      refresh_interval:  10s
  - job_name: "coredns"
    file_sd_configs:
    - files: ['/home/apps/prometheus/sd_configs/coredns/*.yaml']
      refresh_interval:  10s

sd_configs/etcd/nodes.yaml内容如下:

- targets: ['192.168.0.11:2379']
  labels:
    instance: 192.168.0.11
- targets: ['192.168.0.12:2379']
  labels:
    instance: 192.168.0.12
- targets: ['192.168.0.13:2379']
  labels:
    instance: 192.168.0.13

sd_configs/coredns/nodes.yaml内容如下:

- targets: ['192.168.0.11:19097']
  labels:
    instance: 192.168.0.11
- targets: ['192.168.0.12:19097']
  labels:
    instance: 192.168.0.12
- targets: ['192.168.0.13:19097']
  labels:
    instance: 192.168.0.13

之后去grafana官网找个合适的dashboard进行import即可。

相关文章
|
存储 缓存 文件存储
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
32698 79
如何保证分布式文件系统的数据一致性
|
前端开发 容器
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局(上)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局
17752 20
|
设计模式 存储 监控
设计模式(C++版)
看懂UML类图和时序图30分钟学会UML类图设计原则单一职责原则定义:单一职责原则,所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。bad case:IPhone类承担了协议管理(Dial、HangUp)、数据传送(Chat)。good case:里式替换原则定义:里氏代换原则(Liskov 
36683 19
设计模式(C++版)
|
存储 编译器 C语言
抽丝剥茧C语言(初阶 下)(下)
抽丝剥茧C语言(初阶 下)
|
机器学习/深度学习 人工智能 自然语言处理
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
24758 14
|
机器学习/深度学习 弹性计算 监控
重生之---我测阿里云U1实例(通用算力型)
阿里云产品全线降价的一力作,2023年4月阿里云推出新款通用算力型ECS云服务器Universal实例,该款服务器的真实表现如何?让我先测为敬!
36661 15
重生之---我测阿里云U1实例(通用算力型)
|
SQL 存储 弹性计算
Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
|
存储 算法 Java
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务
随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。
29838 52

热门文章

最新文章

下一篇
开通oss服务