如何利用Confd与Etcd对CoreOS中的服务进行动态重新配置

confd 0.20.0 监听etcd动态更新nginx配置文件,解决confd0.16.0连接etcd失败时程序终止的问题 confd0.20.0版本 ,etcd的指定key值发生变化时,nginx的配置文件更新,nginx重启的效果。解决confd0.16.0连接etcd失败时程序终止的问题 阅读详情

提供:ZStack云计算

系列教程

本教程为CoreOS上手指南系列九篇中的第七篇。

内容介绍

CoreOS允许大家在各集群成员上的Docker容器内轻松运行服务。作为基本流程,我们通常需要启动某服务的一个或多个实例,而后利用etcd加以注册。

在本篇教程中,我们将探讨confd工具,其专门用于观察分布式键-值存储中的内容变化。其运行于Docker容器之风,且可用于触发配置修改与服务重载。

先决条件与既定目标

为了完成本篇教程,大家应当对CoreOS及其各组件拥有基本了解。

如果对这方面内容不太熟悉,大家请首先参阅以下几篇教程:

另外,要了解更多与管理工具相关的内容,则请参阅:

其中“如何创建灵活服务”一文特别重要,因为其中涉及的服务将作为本篇教程内的前端服务。

在今天的文章中,我们将探讨如何利用Nginx创建新的应用容器。其将作为反向代理服务于各个Apache实例。该Nginx容器将利用confd进行配置,负责观察各sidekick服务所负责的服务注册表。

我们将继续使用本系列教程的三节点集群:

  • coreos-1
  • coreos-2
  • coreos-3

下面正式开始今天的内容。

配置后端Apache服务

我们首先从后端Apache服务开始。

登录至COreOS设备:

ssh -A core@ip_address
Apache容器设置

我们首先创建基本Apache容器。由于之前在其它教程中已经提到,因此这里只简要进行说明。

下面提取基础镜像并启动容器实例:

docker run -i -t ubuntu:14.04 /bin/bash

容器启动后,我们会面对一套bash会话。在这里,更新本地apt软件包目录并安装apahce2:

apt-get update
apt-get install apache2 -y

设置默认页面:

echo"<h1>Running from Docker on CoreOS</h1>" > /var/www/html/index.html

现在退出该容器:

exit

使用以下命令登录或创建Docker Hub账户:

docker login

这里需要提供用户名、密码以及邮箱地址。

接下来获取刚刚创建的实例的容器ID:

docker ps -l

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
1db0c9a40c0d        ubuntu:14.04        "/bin/bash"         2 minutes ago       Exited (0) 4 seconds ago                       jolly_pare

其中的高亮部分即为容器ID。将输出结果复制到我们自己的计算机上。

现在提交该容器ID、Docker Hub用户名称以及镜像名称。这里我们使用apahce作为名称:

docker commit 1db0c9a40c0duser_name/apache

将新镜像推送至Docker Hub:

docker push user_name/apache

现在即可在服务文件中使用此镜像了。

创建Apache服务模板单元文件

现在我们已经拥有了可用容器,接下来创建模板单元文件,保证fleet与systemd能够正确管理该服务。

在开始之前,首先设置一套目录结构:

cd ~
mkdir static templates instances

现在,我们可以在模板目录内构建自己的模板文件了:

vim templates/apache@.service

将以下内容粘贴至文件中。大家可以参阅创建灵活的fleet服务单元文件教程了解各选项的含义:

[Unit]Description=Apache web server service on port %i

# Requirements
Requires=etcd.serviceRequires=docker.serviceRequires=apache-discovery@%i.service

# Dependency ordering
After=etcd.serviceAfter=docker.serviceBefore=apache-discovery@%i.service[Service]
# Let processes take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill apache.%iExecStartPre=-/usr/bin/docker rm apache.%iExecStartPre=/usr/bin/docker pull user_name/apacheExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PRIVATE_IPV4}:%i:80 \user_name/apache /usr/sbin/apache2ctl -D FOREGROUND

# Stop
ExecStop=/usr/bin/docker stop apache.%i[X-Fleet]
# Don't schedule on the same machine as other Apache instances
Conflicts=apache@*.service

我们这里需要修改以使用专有接口替代公共接口。由于我们的各Apache实例都会通过Nginx反射代理发送流量,因此这部分调整是必不可少的。注意,在DigitalOcean上使用专有接口的话,我们使用的各服务器必须具备“private networking”标记。

另外,注意变更user_name以引用我们的Docker Hub用户名,从而正确提取Docker文件。

创建sidekick模板单元文件

现在,我们需要以同样的方式处理sidekick服务。稍后我们会对内容进行调整以符合自身环境的实际情况。

打开该模板文件:

vim templates/apache-discovery@.service

在文件中使用以下信息:

[Unit]Description=Apache web server on port %i etcd registration

# Requirements
Requires=etcd.serviceRequires=apache@%i.service

# Dependency ordering and binding
After=etcd.serviceAfter=apache@%i.serviceBindsTo=apache@%i.service[Service]

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c '\
  while true; do \
curl -f ${COREOS_PRIVATE_IPV4}:%i; \
if [ $? -eq 0 ]; then \
  etcdctl set /services/apache/${COREOS_PRIVATE_IPV4} \'${COREOS_PRIVATE_IPV4}:%i\' --ttl 30; \
else \
  etcdctl rm /services/apache/${COREOS_PRIVATE_IPV4}; \
fi; \
sleep 20; \
  done'

# Stop
ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PRIVATE_IPV4}[X-Fleet]
# Schedule on the same machine as the associated Apache service
MachineOf=apache@%i.service

以上配置与之前教程中的内容有所区别。我们利用etcdctl set命令调整了部分值。相较于发送JSON对象,这里我们设置了简单的IP地址加端口的组合。通过这种方式,我们能够直接读取该值以掌握前往此服务的必要连接信息。

我们还调整了相关信息以指定在其它文件中已经使用的专有接口。

进行服务实例化

现在为这些服务创建两个实例。

首先是创建符号链接。前往刚刚创建的~/instances目录,同时链接至服务运行所在的端口。我们希望让两项服务分别运行在端口7777与端口8888上:

cd ~/instances
ln -s ../templates/apache@.service apache@7777.service
ln -s ../templates/apache@.service apache@8888.service
ln -s ../templates/apache-discovery@.service apache-discovery@7777.service
ln -s ../templates/apache-discovery@.service apache-discovery@8888.service

现在,我们可以将~/instances目录发送至fleet以启动这些服务:

fleetctl start ~/instances/*

在实例启动后(可能需要几分钟),大家应该能够看到sidekicks生成的etcd条目:

etcdctl ls --recursive /

/coreos.com
/coreos.com/updateengine
/coreos.com/updateengine/rebootlock
/coreos.com/updateengine/rebootlock/semaphore
/services
/services/apache
/services/apache/10.132.249.206/services/apache/10.132.249.212

如果大家查询这些条目的值,则会看到其IP地址与端口编号:

etcdctl get /services/apache/10.132.249.206

10.132.249.206:8888

大家可以使用curl以检索该页面,并确保其正常起效。注意,我们必须配置该服务使用专有网络才能保证其在设备内正常运作:

curl 10.132.249.206:8888

<h1>Running from Docker on CoreOS</h1>

现在我们已经设置完成了自己的后端基础设施。我们的下一项目标是熟悉confd,从而在Nginx每次变更及重新配置时在etcd中查看/services/apache的位置。

创建Nginx容器

我们继续以Ubuntu 14.04为系统平台启动Nginx容器。

安装软件

使用以下命令启动一套新容器:

docker run -i -t ubuntu:14.04 /bin/bash

更新我们的本地apt软件包缓存并安装Nginx。我们还需要安装curl,因为基础镜像中并不包含:

apt-get update
apt-get install nginx curl -y

现在我们可以前往发布页面以获取GitHub上的confd。我们还需要找到其最新稳定版本的链接。目前该版本为v0.5.0,但具体链接可能有所变化。

现在重新回到Docker容器,使用复制到的URL以下载该应用。我们将其存放在/usr/local/bin目录内。我们需要将confd选定为输出文件:

cd /usr/local/bin
curl -L https://github.com/kelseyhightower/confd/releases/download/v0.5.0/confd-0.5.0<^>-linux-amd64 -o confd

现在将该文件设置为可执行,从而在容器内加以使用:

chmod +x confd

我们还需要创建confd所能支持的配置结构,在/etc目录下进行:

mkdir -p /etc/confd/{conf.d,templates}
创建Confd配置文件以读取Etcd值

现在我们的应用已经安装完成,接下来配置confd。具体方式可以是创建配置文件,或者使用模板资源文件。

confd中的配置文件用于设置该服务以检查特定etcd值,同时在检测到变更时执行初始化操作。配置文件使用TOML文件格式,其易于使用且非常直观。

首先在配置目录中创建nginx.toml文件:

vi /etc/confd/conf.d/nginx.toml

在文件中添加以下信息:

[template]

# The name of the template that will be used to render the application's configuration file
# Confd will look in `/etc/conf.d/templates` for these files by default
src = "nginx.tmpl"

# The location to place the rendered configuration file
dest = "/etc/nginx/sites-enabled/app.conf"

# The etcd keys or directory to watch.  This is where the information to fill in
# the template will come from.
keys = [ "/services/apache" ]

# File ownership and mode information
owner = "root"mode = "0644"

# These are the commands that will be used to check whether the rendered config is
# valid and to reload the actual service once the new config is in place
check_cmd = "/usr/sbin/nginx -t"reload_cmd = "/usr/sbin/service nginx reload"

下面解释其中的部分关键内容:

DirectiveRequired?TypeDescription

src Yes String为用于渲染该信息的模板。如果其处于/etc/confd/templates位置之外,则使用完整路径。

dest Yes String为已渲染配置文件所在的位置。

keys Yes Array of strings为模板使用以实现正确渲染的etcd键。如果该模板被设定为处理子键,则其亦可为目录。

owner No String为作为渲染配置文件持有者的用户名称。

group No String为持有渲染配置文件的组。

mode No String为用于设定渲染文件的octal权限模式。

check_cmd No String用于检查渲染配置文件的语法。

reload_cmd No String命令用于重载该应用的配置。

prefix No String为etcd层次结构中的一部分,位于keys指令中的keys之前,用于确保.toml文件更为灵活。

我们创建的这个文件中包含大量重要内容,用于指定confd实例的功能实现方式。我们的Nginx容器所使用的模板存储于/etc/confd/templates/nginx.conf.tmpl内,用于渲染将被放置在/etc/nginx/sites-enabled/app.conf处的配置文件。该文件将被赋予0644权限组,并归属于root用户。

此confd应用将查找/services/apache节点中的变更。当变更出现时,confd会查询此节点中的新信息,而后为Nginx渲染新的配置。另外,它还能够对已有文件进行语法错误检查并重载Nginx服务。

现在我们的模板资源文件已经创建完成。

创建Confd模板文件

我们将使用confd项目GitHub说明文档内提供的模板文件。

创建的这个文件将在之前完成的配置文件内加以引用。将此文件放在我们的模板目录内:

vi /etc/confd/templates/nginx.tmpl

在文件中,我们需要重新创建标准Nginx反向代理配置文件。这里我们会使用部分Go模板化语法,用于替换confd从etcd中提取到的信息。

首先利用upstream服务器配置该块。此部分用于定义Nginx能够作为请求发送目标的服务器池。其格式如下:

upstreampool_name {
serverserver_1_IP:port_num;
serverserver_2_IP:port_num;
serverserver_3_IP:port_num;
}

这样我们就能将请求发送至pool_name处,而Nginx则会选择定义服务器之一来处理请求内容。

我们的模板文件负责解析etcd以获取Apache Web服务器的IP地址与端口编号。因此相较于以状态化方式定义upstream服务器,我们可以在所渲染的文件中动态填充这些信息。具体方式请参阅Go模板中的动态内容介绍。

要完成这一目标,我们使用以下内容作为配置块:

upstream apache_pool {
{{ range getvs "/services/apache/*" }}
server {{ . }};
{{ end }}
}

下面解释其具体含义。我们打开的块负责定义名为apache_pool的上游服务器池。在其中,我们使用双大括号以指定Go代码。

在这些大括号中,我们指定所需值的来源etcd端点。我们使用range使列表具备可迭代性。

我们将etcd中/services/apache位置下的全部条目发送至range块。而后,我们在利用“{{}}”中的一个点(.)来插入当前迭代中的键值。在range循环中,我们借此填充服务器池。最后,我们使用{{end}}指令作为循环结尾。

注意:记得在循环内的server指令后加上分号。如果不添加,则会造成配置无法生效。

在服务器池设置完成后,我们可以使用代理将全部连接引导至该池。需要注意的是access_log,这里我们暂时使用自定义格式:

upstream apache_pool {
{{ range getvs "/services/apache/*" }}
server {{ . }};
{{ end }}
}

server {
listen80 default_server;
listen [::]:80 default_server ipv6only=on;

access_log /var/log/nginx/access.log upstreamlog;

location / {
    proxy_passhttp://apache_pool;
    proxy_redirectoff;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

这会响应全部端口80上的连接,并将其发送至apache_pool位置的服务器池。

另外,我们还需要移除默认Nginx配置文件,从而保证不会出现冲突。这里我们移除指向默认配置的符号链接:

rm /etc/nginx/sites-enabled/default

接下来,我们要配置模板文件内所引用的日志格式。这部分内容必须位于配置中的http部分,且可用于主配置文件。将该文件打开:

vi /etc/nginx/nginx.conf

添加log_format指令以定义希望记录的信息。其会记录进行访问的客户端以及请求被发送到的后端服务器。我们以如下规程实现数据记录:

. . .
http {
### Basic Settings##log_format upstreamlog '[$time_local] $remote_addr passed to: $upstream_addr: $request Upstream Response Time: $upstream_response_time Request time: $request_time';

sendfileon;
. . .

完成后保存并退出。

创建脚本以运行Confd

我们需要创建一套脚本,负责利用模板资源文件并在合适的时间段内调用confd。

此脚本必须肩负以下两项职责,从而保证我们的服务能够正常运作:

  • 必须根据当前后端基础设施状态对Nginx设置进行初始化,从而匹配容器启动操作。
  • 必须持续观察etcd注册表中的Apache服务器变更,从而根据后端服务器可用状态重新配置Nginx。

这里我们直接使用Marcel de Graaf的GitHub页面。这套脚本非常适合我们的实际需求,只需要根据实际场景做出一点调整。

首先将该脚本与我们的confd可执行文件放在一起。我们将其命名为confd-watch:

vi /usr/local/bin/confd-watch

我们仍然从bash标题头开始进行解释。而后设置部分bash选项以保证在出现故障时,该脚本会立即失效。其会返回最后一条失效或者成功运行的命令值。

#!/bin/bash
set -eo pipefail

下面我们希望设置部分变量。通过使用bash参数,我们可以设置默认值但同时保留一定的灵活性,从而在调用脚本时能够覆盖掉其中的硬编码值。基本上,这意味着独立设置各连接地址,而后将其归纳成组以获取完整的地址。

参数替代部分使用以下语法:

${var_name:-default_value}。如果存在var_name或者为非空,则将其值作为属性; 否则采用default_value默认值。

我们已经在默认情况下将etcd设定为使用默认值。这样我们的脚本能够正常起效,但同时亦可在必要时通过定制化方式调用该脚本:

#!/bin/bash
set -eo pipefail

export ETCD_PORT=${ETCD_PORT:-4001}export HOST_IP=${HOST_IP:-172.17.42.1}export ETCD=$HOST_IP:$ETCD_PORT

现在使用confd对Nginx配置文件的初始版本进行渲染,各相关值读取自etcd。我们还将使用一条until循环以持续尝试构建初始配置。

该循环结构将在etcd不可用的情况下立即生效,或者在Nginx容器先于后端服务器被启动的情况下被激活。这样etcd会反复尝试,直到其最终生成有效的初始配置。

我们调用的实际confd命令会在执行一次后退出。因此我们可以等待5秒钟,直到后端服务器完成注册后再行尝试。我们利用默认或提交的参数接入完整的ETCD变量,而后使用模板资源文件以定义需要执行的操作:

#!/bin/bash
set -eo pipefail

export ETCD_PORT=${ETCD_PORT:-4001}export HOST_IP=${HOST_IP:-172.17.42.1}export ETCD=$HOST_IP:$ETCD_PORTecho"[nginx] booting container. ETCD: $ETCD"# Try to make initial configuration every 5 seconds until successful
until confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; doecho"[nginx] waiting for confd to create initial nginx configuration"
sleep 5done

在初始配置设置完成后,脚本接下来需要以持续方式运行。我们要借此确保Nginx能够借此发现一切变更并保持更新。

这一次,我们设置连续轮询间隔,并将其无限期运行在后台进程内。我们提交同样的etcd连接信息与同样的模板资源文件,因为我们需要实际的目标与之前所提到的并无区别。

在将confd进程纳入后台后,我们可以使用现有配置文件启动Nginx了。由于此脚本将通过Docker的run命令接受调用,因此需要使其在前台运行在确保容器不会中途退出。要完成这一目标,我们可以追踪日志内容以访问全部记录到的信息:

#!/bin/bash
set -eo pipefail

export ETCD_PORT=${ETCD_PORT:-4001}export HOST_IP=${HOST_IP:-172.17.42.1}export ETCD=$HOST_IP:$ETCD_PORTecho"[nginx] booting container. ETCD: $ETCD."# Try to make initial configuration every 5 seconds until successful
until confd -onetime -node $ETCD -config-file /etc/confd/conf.d/nginx.toml; doecho"[nginx] waiting for confd to create initial nginx configuration."
sleep 5done# Put a continual polling `confd` process into the background to watch# for changes every 10 seconds
confd -interval 10 -node $ETCD -config-file /etc/confd/conf.d/nginx.toml &
echo"[nginx] confd is now monitoring etcd for changes..."# Start the Nginx service using the generated configecho"[nginx] starting nginx service..."
service nginx start

# Follow the logs to allow the script to continue running
tail -f /var/log/nginx/*.log

完成之后保存并退出。
最后,我们需要将此脚本设置为可执行:

chmod +x /usr/local/bin/confd-watch

退出该容器并返回主机系统:

exit
提交并推送容器

现在我们可以提交该容器并将其推送至Docker Hub,从而供全部设备进行获取。找到其容器ID:

docker ps -l

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
de4f30617499        ubuntu:14.04        "/bin/bash"         22 hours ago        Exited (0) About a minute ago                       stupefied_albattani

其中的高亮字符串即为我们需要的容器ID。使用此ID、Docker Hub用户名以及镜像名称提交该容器。这里我们将其命名为nginx_lb:

docker commit de4f30617499user_name/nginx_lb

如果需要,请登录Docker Hub账户:

docker login

现在已经可以进行镜像提交了:

docker push user_name/nginx_lb

构建Nginx Static单元文件

下面我们需要构建一个单元文件,其负责启动我们创建完成的容器。在这里,我们使用fleet以控制此流程。

由于此文件没有现成模板可用,因此我们将在此前创建的~/static目录中从头进行创建:

vim static/nginx_lb.service

下面从标准的[Unit]部分开始,描述该服务并定义其依赖性与顺序:

[Unit]Description=Nginx load balancer for web server backends

# Requirements
Requires=etcd.serviceRequires=docker.service

# Dependency ordering
After=etcd.serviceAfter=docker.service

接下来,我们定义文件中的[Serivce]部分。在这里我们将超时设置为0,同时将killmode设置为无。我们需要再次引入环境文件,从而访问此容器运行所在主机的公共与专有IP地址。

之后,我们将清理环境以确保该容器的早期版本不再存在。现在提取刚刚创建的容器以确保其处于最新版本。

最后,启动此容器。在此过程中,我们需要启动容器,根据remove与kill命令中的引用内容为其命名,而后为其提供运行所在主机的公共IP地址并映射至端口80。我们调用此前创建的confd-watch脚本作为run命令:

[Unit]Description=Nginx load balancer for web server backends

# Requirements
Requires=etcd.serviceRequires=docker.service

# Dependency ordering
After=etcd.serviceAfter=docker.service[Service]
# Let the process take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill nginx_lbExecStartPre=-/usr/bin/docker rm nginx_lbExecStartPre=/usr/bin/docker pull user_name/nginx_lbExecStart=/usr/bin/docker run --name nginx_lb -p ${COREOS_PUBLIC_IPV4}:80:80 \user_name/nginx_lb /usr/local/bin/confd-watch

现在我们需要理清停止命令与fleet调度方向。我们希望该容器只在主机不再运行其它负载均衡实例或者后端Apache服务器时才进行初始化。这样一来,我们就能更为高效地进行服务负载分散:

[Unit]Description=Nginx load balancer for web server backends

# Requirements
Requires=etcd.serviceRequires=docker.service

# Dependency ordering
After=etcd.serviceAfter=docker.service[Service]
# Let the process take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill nginx_lbExecStartPre=-/usr/bin/docker rm nginx_lbExecStartPre=/usr/bin/docker pull user_name/nginx_lbExecStart=/usr/bin/docker run --name nginx_lb -p ${COREOS_PUBLIC_IPV4}:80:80 \user_name/nginx_lb /usr/local/bin/confd-watch

# Stop
ExecStop=/usr/bin/docker stop nginx_lb[X-Fleet]Conflicts=nginx.serviceConflicts=apache@*.service

完成后保存并退出。

运行Nginx负载均衡

现在我们拥有此前完成的两套Apache实例。下面进行检查:

fleetctl list-units

UNIT                MACHINE             ACTIVE  SUB
apache-discovery@7777.service   197a1662.../10.132.249.206  active  running
apache-discovery@8888.service   04856ec4.../10.132.249.212  active  running
apache@7777.service     197a1662.../10.132.249.206  active  running
apache@8888.service     04856ec4.../10.132.249.212  active  running

大家也可以再次检查,确保其已经注册至etcd:

etcdctl ls --recursive /services/apache

/services/apache/10.132.249.206
/services/apache/10.132.249.212

我们现在可以启动Nginx服务了:

fleetctl start ~/static/nginx_lb.service

Unit nginx_lb.service launched on 96ec72cf.../10.132.248.177

整个启动过程可能需要耗费1分钟左右,具体取决于镜像的获取速度。启动完成后,如果使用fleetctl journal命令检查日志,则会看到来自confd的日志信息:

fleetctl journal nginx_lb.service

-- Logs begin at Mon 2014-09-15 14:54:05 UTC, end at Tue 2014-09-16 17:13:58 UTC. --
Sep 16 17:13:48 lala1 docker[15379]: 2014-09-16T17:13:48Z d7974a70e976 confd[14]: INFO Target config /etc/nginx/sites-enabled/app.conf out of sync
Sep 16 17:13:48 lala1 docker[15379]: 2014-09-16T17:13:48Z d7974a70e976 confd[14]: INFO Target config /etc/nginx/sites-enabled/app.conf has been updated
Sep 16 17:13:48 lala1 docker[15379]: [nginx] confd is monitoring etcd for changes...
Sep 16 17:13:48 lala1 docker[15379]: [nginx] starting nginx service...
Sep 16 17:13:48 lala1 docker[15379]: 2014-09-16T17:13:48Z d7974a70e976 confd[33]: INFO Target config /etc/nginx/sites-enabled/app.conf in sync
Sep 16 17:13:48 lala1 docker[15379]: ==> /var/log/nginx/access.log <==
Sep 16 17:13:48 lala1 docker[15379]: ==> /var/log/nginx/error.log <==
Sep 16 17:13:58 lala1 docker[15379]: 2014-09-16T17:13:58Z d7974a70e976 confd[33]: INFO /etc/nginx/sites-enabled/app.conf has md5sum a8517bfe0348e9215aa694f0b4b36c9b should be 33f42e3b7cc418f504237bea36c8a03e
Sep 16 17:13:58 lala1 docker[15379]: 2014-09-16T17:13:58Z d7974a70e976 confd[33]: INFO Target config /etc/nginx/sites-enabled/app.conf out of sync
Sep 16 17:13:58 lala1 docker[15379]: 2014-09-16T17:13:58Z d7974a70e976 confd[33]: INFO Target config /etc/nginx/sites-enabled/app.conf has been updated

可以看到,confd会从etcd中获取初始配置。其随后启动nginx。接下来的各行显示etcd条目已经被重新评估,同时生成新的配置文件。如果新生成的文件与原有文件的md5不符,则原有文件会被替换,服务也随之重载。

如此一来,我们的负载均衡服务最终将能够追踪Apache后端服务器。如果confd进行不断更新,则可能是因为我们的Apache实例刷新TTL的频率过高。这时,大家可以增加sidekick模板中的sleep与TTL值以解决这个问题。

要查看运行中的负载均衡机制,大家可以从运行Nginx服务的主机上查询/etc/environments文件。其中包含该主机的公共IP地址。如果大家希望进一步改善此配置,则可以考虑运行一项sidekick服务以将此信息注册至etcd:

fleetctl ssh nginx_lb cat /etc/environment

COREOS_PRIVATE_IPV4=10.132.248.177
COREOS_PUBLIC_IPV4=104.131.16.222

现在,如果我们通过浏览器前往公共IPv4,则会看到我们在Apache实例中配置的页面:

如果大家再次查看日志,应该会看到用于指定负责发送请求的后端服务器的相关信息:

fleetctl journal nginx_lb

. . .
Sep 16 18:04:38 lala1 docker[18079]: 2014-09-16T18:04:38Z 51c74658196c confd[28]: INFO Target config /etc/nginx/sites-enabled/app.conf in sync
Sep 16 18:04:48 lala1 docker[18079]: 2014-09-16T18:04:48Z 51c74658196c confd[28]: INFO Target config /etc/nginx/sites-enabled/app.conf in sync
Sep 16 18:04:48 lala1 docker[18079]: [16/Sep/2014:18:04:48 +0000] 108.29.37.206 passed to: 10.132.249.212:8888: GET / HTTP/1.1 Upstream Response Time: 0.003 Request time: 0.003

总结

可以看到,现在我们已经可以设置服务以检查etcd的配置细节。confd等工具能够持续提取各重要条目,从而极大简化这一实现流程。

在本示例当中,我们配置Nginx服务以使用etcd来生成其初始配置。我们也可以在后台设置以持续检查各项变更。这套体系与基于模板的动态配置相结合,将使我们实现后端服务器的不断更新。

本文来源自DigitalOcean Community。英文原文:How To Use Confd and Etcd to Dynamically Reconfigure Services in CoreOS By Justin Ellingwood

翻译:diradw

Docker生产环境服务发现与分布式配置实战:etcd与Consul深度选型指南 服务发现与分布式配置是微服务架构中容器化落地的核心基础设施,其本质是解决动态环境下服务寻址、健康感知与配置一致性问题。基于Raft共识算法的强一致KV存储(如etcd)和集成DNS/健康检查的全栈服务网格(如Consul),分别代表了‘可靠性优先’与‘开箱即用优先’两种技术路径。它们并非Docker插件,而是支撑容器编排的底层协调中枢,在金融、电商等高可用场景中直接影响系统韧性。本文聚焦Docker生态下etcd与Consul的真实部署逻辑、参数调优依据及避坑经验,覆盖集群拓扑设计、TLS加固、Watch机 阅读详情

相关推荐

etcd与Consul实战:服务发现与配置中心生产部署指南

服务发现和分布式配置中心是云原生架构的核心基础设施,解决微服务动态寻址与配置集中治理两大关键问题。其底层原理依赖强一致性或最终一致性的分布式键值存储,通过自动注册、健康检查、实时发现与安全注销形成闭环。技术价值在于支撑Kubernetes调度、Istio流量治理、Spring Cloud配置热更新等高可用场景。典型应用包括容器化环境下的服务自动感知、多环境配置灰度发布、敏感信息加密管理及故障自愈。本文聚焦etcd(Raft强一致)与Consul(全栈开箱即用)的选型逻辑、TLS安全加固、三节点高可用部署及线

weixin_30896511的博客 504

入门ETCD——配合confd实现配置管理

Confd是一个轻量级的配置管理工具。通过查询后端存储,结合配置模板引擎,保持本地配置最新,同时具备定期探测机制,配置变更自动reload。对应的后端存储可以是etcd,redis、zookeeper等。

qq_33816243的博客 1864

CoreOS下利用confd和Nginx实现负载均衡集群的示例教程

简介:本文提供了一个详细的教程,介绍如何使用CoreOS、etcd、confd和Nginx构建一个高效且可扩展的负载均衡集群。教程涵盖了从CoreOS和etcd的基础配置到通过confd动态更新配置以及利用Nginx实现流量分配的完整流程。读者将学习到如何部署Docker容器化的Web应用,并使用Shell脚本自动化整个部署过程。该示例包含源代码和配置文件,可以帮助用户逐步搭建和测试其负载均衡集群。

weixin_35019679的博客 891

confd动态配置文件详解

confd介绍 Confd是一个轻量级的配置管理工具。通过查询后端存储,结合配置模板引擎,保持本地配置最新,同时具备定期探测机制,配置变更自动reload。 对应的后端存储可以是etcd,redis、zookeeper等等 confd的部署 以下Linux系统为例。 下载confd的二进制文件,下载地址为:https://github.com/kelseyhightower/confd/relea...

爱死亡机器人 7113

手把手教你用STM32F303和LAN9252搭建EtherCAT从站(附IO/AD/DA完整代码)

本文详细介绍了如何使用STM32F303和LAN9252搭建EtherCAT从站,涵盖硬件选型、开发环境配置、协议栈移植及IO/AD/DA功能实现。通过实战指南和完整代码,帮助开发者快速掌握工业自动化中的实时通信技术,提升系统性能与可靠性。

weixin_26802933的博客 235

Pspice安装教程:Windows系统完整指南(含环境变量设置)

详细讲解在Windows系统中完成Pspice安装的全过程,涵盖安装步骤与关键的环境变量设置,帮助用户顺利运行仿真工具。适合初学者快速上手pspice安装教程中的核心环节。

weixin_42230607的博客 1180

Etcd+Confd 管理Nginx配置文件

背景 手写Nginx的upsteam麻烦并且容易出错,想通过类似Kong的Restfull的api形式操作upsteam节点。 架构图 etcd:分布式KV存储系统,一般用于共享配置和服务注册与发现。是CoreOS公司发起的一个开源项目。 ETCD存储格式类似于文件系统,以根"/"开始下面一级级目录,最后一个是Key,一个key对应一个Value。 etcd集群:使用Raft协议保证每个节点数据一致,由多个节点对外提供服务。这里只用单台。 confd:管理本地应用配置文件,使用etc.

叱咤少帅的博客 4618

wps js宏获取工作簿、工作表、单元格的值、链接转图片、单元格区域数据转二维数组、保存工作簿的常用Excel操作

wps js宏入门看这里,我写了常用的js操作Excel的方法:获取工作簿对象、获取工作表对象、获取单元格的值、链接转图片、生成条形码图片、单元格区域数据转二维数组方法、保存工作簿、弹出输入框、YesNo选择框,助你从VBA转战JS。

huaermeier的博客 3万+

confd_confd读书笔记

1.下载安装confd]# wgethttps://github.com/kelseyhightower/confd/releases/download/v0.15.0/confd-0.15.0-linux-amd64]# mkdir -p /opt/confd/bin]# mv confd-0.15.0-linux-amd64 /opt/confd/bin/confd]# chmod +x /o...

weixin_39881387的博客 278

Dify 深度进阶:从入门到精通AI应用构建

《Dify进阶指南:从基础到高阶的AI应用开发技巧》 本文深入探讨Dify平台的高级功能与应用开发技巧。首先强调核心概念的深化,包括提示词工程进阶、知识库高效管理和模型参数优化。重点介绍智能体应用的开发方法,如何让AI具备自主规划与执行能力。同时讲解工作流编排、前端集成等实用技术,并分享应用运营优化、成本控制等实践经验。文章还展望了Dify生态的发展趋势,为开发者提供从基础到进阶的完整学习路径,助力打造更智能高效的AI应用。

同名公众号:dify实验室 1953

2026中银杯区块链赛项备赛全攻略:从任务书拆解到高分技巧

区块链技术正从概念走向工程化落地,其核心价值在于通过分布式账本、智能合约与共识机制,构建可信、透明、可追溯的业务协作网络。在供应链溯源、存证、资产流转等场景中,区块链应用已从单一技术验证转向完整业务系统交付,这对开发者的综合能力提出了更高要求。对于职业院校技能大赛而言,选手不仅需要掌握联盟链底层搭建、Solidity合约开发、前后端应用联调等技术,还需具备规范交付与团队协作的工程素养。围绕2026年中银杯湖北省职业院校技能大赛区块链技术应用赛项,本文深入拆解任务书模块与评分逻辑,梳理底层链搭建、智能合约开发

weixin_27960253的博客 335

Paz服务发现机制:让你的微服务架构无缝协作的终极指南

Paz是一个基于Docker、CoreOS、Etcd和Fleet构建的开源PaaS平台,它的服务发现机制是微服务架构无缝协作的关键。这个免费的开源平台提供了完整的服务发现解决方案,让开发人员能够轻松管理分布式系统中的服务通信。 ## 什么是Paz服务发现?🎯 Paz服务发现机制是一种基于Etcd的分布式服务注册与发现系统。在微服务架构中,服务实例会动态地启动和停止,Paz通过自动化的服务发现

gitblog_00159的博客 821

【AI智能体】Codex + Seedance2.5 制作AI视频实战操作详解

【AI智能体】Codex + Seedance2.5 制作AI视频实战操作详解

congge_study的博客 3839

Paz核心功能解析:打造企业级容器部署与监控系统

Paz是一个开源的内部服务平台,提供类似PaaS的工作流,基于Docker、CoreOS、Etcd和Fleet构建。该平台通过直观的界面和强大的后端服务,帮助企业轻松实现容器化应用的部署、管理与监控,是现代DevOps环境中的理想选择。 ## 🚀 核心功能概览 Paz平台围绕五大核心组件构建,形成完整的容器服务生命周期管理体系: ### 1️⃣ 直观的Web前端界面 Paz提供了用户友好

gitblog_00714的博客 757

CANoe制作网关实现CAN(FD)报文故障注入(报文长度/timeout/信号错误/E2E)2

CANoe制作网关实现CAN报文故障注入(报文长度/timeout/信号错误/E2E) 2.新建CANoe工程 3.透传功能 4.故障注入panel面板 5.CAPL代码 5.1故障注入开始、停止、定时 5.2DLC故障注入 5.3 Timeout故障注入 5.4 信号故障注入

天赐好车的博客 3680

Challenge 6 - OSCP C

开放了161端口,直接snmpbulkwalk扫描得到账号密码试了那几个web端口,发现可以登录8083的vesta,但是需要用户名大写Jack接着登录之后里面可以创建计划任务,直接弄个反弹shell,一分钟回弹。得到shell后,运行linpeas.sh提供了几个可能的漏洞,挨个试一下。

羽的博客 4159

LTX-2.3-Multiple-Subject-Reference 完全解析:一款让多主体角色永不“变脸“的多参考视频生成 LoRA

📌 **LTX-2.3-Multiple-Subject-Reference** 是一款基于 Lightricks/LTX-2.3 视频基座训练的 **多主体参考(Multiple Subject Reference,简称 MSR)LoRA**:你只需提供 2~5 张参考图(人物、物体、场景),再配上一段文字描述,它就能生成角色身份、服装、道具全程"不变脸"的参考驱动视频,是当前多参考视频生成方

gitblog_00482的博客 383

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Paz vs 传统PaaS:为什么选择这款开源容器编排平台?终极指南

在当今快速发展的云原生时代,容器编排平台已成为现代应用部署的核心基础设施。Paz作为一款开源、自托管的**容器编排平台**,为开发者提供了与传统PaaS完全不同的部署体验。这款基于Docker、CoreOS、Etcd和Fleet构建的**开源PaaS解决方案**,让企业能够拥有自己的私有PaaS环境,同时享受开源带来的灵活性和控制权。 ## 🚀 Paz是什么?重新定义私有PaaS Paz是一

gitblog_07966的博客 844

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

163MusicLyrics:免费音乐歌词提取,批量获取网易云与QQ音乐的LRC/SRT歌词

想把网易云音乐或QQ音乐里的歌词存成 LRC 文件,又不想手动复制粘贴、逐行改格式?163MusicLyrics 是一款跨平台的音乐歌词提取工具:粘贴歌曲链接、点一下保存,就能拿到带时间轴的歌词文件,还覆盖批量歌词、LRC/SRT 转换和自动翻译。 [![163MusicLyrics音乐歌词提取主界面:搜索、歌词预览与输出格式设置](https://raw.gitcode.com/GitHub_

gitblog_00748的博客 829

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

ubantu18.04下Hadoop安装与伪分布式配置

1 下载   下载地址:http://mirror.bit.edu.cn/apache/hadoop/common/stable2/ 2 解压   将文件解压到 /usr/local/hadoop cd ~/下载   tar -zxf hadoop-2.9.1.tar.gz   sudo mv ./hadoop-2.9.1/ /usr/local/hadoop   cd...

chb4715的博客 253

Webpack3 环境配置篇 | React + Webpack3 后台管理项目搭建(1)

React + Webpack3 后台管理项目搭建(1)| webpack3 配置篇 最近的前端开发实践中,接触最多就是React后台管理的开发项目,多次对公司React项目配置进行优化升级,下面介绍的是基本的React + React-router4 + Webpack3 + less + Antd单页面应用程序的项目搭建方法。 目录 React + Webpack3 后台管理项目搭建(1...

赫拉莉的博客 1580

Erlangshen-DeBERTa-v2最佳实践:避免常见错误的7个技巧

Erlangshen-DeBERTa-v2-186M-Chinese-SentencePiece是一款高效的中文预训练模型,基于DeBERTa-v2架构优化,特别适用于中文自然语言处理任务。本文将分享7个实用技巧,帮助新手用户避免常见错误,充分发挥模型性能。 ## 1. 正确配置模型路径参数 使用模型时首先要确保路径参数配置正确。在[examples/inference.py](https:/

gitblog_00092的博客 546

【ETCD】ETCD——confd配置管理

本文介绍了如何使用confd+etcd实现Nginx配置的动态管理。主要内容包括:confd作为轻量级配置管理工具的工作原理和安装方法;通过创建Nginx模板文件和资源配置文件,实现基于etcd键值变化的配置自动更新;演示了如何通过修改etcd中的/nginx/root_dir键值来动态切换Nginx服务的版本(V1/V2)。该方案解决了多服务环境下配置文件管理复杂的问题,实现了配置的集中化管理、版本回溯和自动加载功能。实验验证表明,当etcd中的配置变更时,confd能够实时检测并更新Nginx配置,确保

weixin_73059729的博客 1100

Confd配置管理工具完全指南:从基础配置到高级用法

Confd是一款轻量级的配置管理工具,它能够动态地从键值存储后端(如etcd、Consul等)获取配置信息,并根据模板生成最终的配置文件。这种设计使得Confd成为现代云原生架构中不可或缺的配置管理组件。 ## 核心配置文件解析 Confd的主配置文件默认位于`/etc/confd/confd.toml`,采用TOML格式编写。TOML是一种易于阅读的配置文件格式,特别适合人类编写和机器解析。...

gitblog_00820的博客 738

confd的使用

1. confd的部署 以下Linux系统为例。 下载confd的二进制文件,下载地址为:https://github.com/kelseyhightower/confd/releases。例如: # Download the binary wget https://github.com/kelseyhightower/confd/releases/download/v0.16.0/co...

胡伟煌的博客 1万+

confd的安装与使用

一、概述 当系统变的复杂,配置项越来越多,一方面配置管理变得繁琐,另一方面配置修改后需要重新上线同样十分痛苦。这时候,需要有一套集中化配置管理系统,一方面提供统一的配置管理,另一方面提供配置变更的自动下发,及时生效。 说道统一配置管理系统,大家应该比较熟悉,常见的:zookeeper、etcd、consul、git等等。 上述的集中配置中心使用的时候,部署图大致是这样的: server...

菲宇运维 2万+
上一篇: 如何利用fleet单元文件为CoreOS集群创建高灵活性服务
下一篇: 如何利用CoreOS服务器对常见问题进行故障排查
普通网友
博客等级 码龄10年 769粉丝 269原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值