为了真实近似模拟线上,下面的配置都是一个服务一个docker-compose.yml文件。
consul
version: '3.3'
services:
consul:
image: consul
container_name: consul_server
network_mode: bridge
ports:
- 8300:8300
- 8301:8301
- 8301:8301/udp
- 8302:8302
- 8302:8302/udp
- 8400:8400
- 8500:8500
- 53:53/udp
command: consul agent -data-dir=/tmp/consul -server -bootstrap -domain=zhenhe.li -client=0.0.0.0
2018-04-22 23:06 做出更改:
1.镜像image由原来的progrium/consul 修改为官方的consul, 原因是原来的镜像中consul版本过低没有新特性。官方目前是1.0.7
2.参数变更为 consul agent 开头,同时新版本中要求参数要加入 -client=x.x.x.x 否则默认127.0.0.1 不允许外部ip 访问
新特性包含critical服务定时清除,允许Tags定义覆盖,增加Meta属性(非常有用,在后面的 template 中使用):
请求示例:
{
"ID": "redis1",
"Name": "redis",
"Tags": [
"primary",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000,
"Meta": {
"redis_version": "4.0"
},
"EnableTagOverride": false,
"Check": {
"DeregisterCriticalServiceAfter": "90m",
"HTTP": "http://localhost:5000/health",
"Interval": "10s"
}
}
响应示例:
{
"redis1": {
"ID": "redis1",
"Service": "redis",
"Tags": ["primary", "v1"],
"Address": "127.0.0.1",
"Meta": {
"redis_version": "4.0"
},
"Port": 8000,
"EnableTagOverride": false,
"CreateIndex": 0,
"ModifyIndex": 0
}
}
registrator
version: '3.3'
services:
registrator:
image: gliderlabs/registrator
container_name: docker_consul_registrator
network_mode: bridge
external_links:
- consul_server:consul
volumes:
- /var/run/docker.sock:/tmp/docker.sock
command: consul://consul:8500
上述配置文件中。 network_mode 使用的bridge ,这其中也踩过坑。网上有很多示例是host, 意思是docker 可以与宿主机共有一网套络,就是说进入容器执行ifconfig与宿主机看到的可能是一样的,暴露的端口也占用宿主机端口。后来反复测试发现在mac os中,network_mode=host 这个配置不能达到上述要求。最终在一篇讨论看到结论:Should docker run –net=host work?
讨论中说network_mode=host在linux中可以正常运行,有时间我验证一下。
nginx+consul-template, 这个网上或docker hub上有别人已经做好了,但是模板ctmpl文件都是根据自己的环境编写的,有可能不符合自己的要求,所以这一步还是要自己去pull nginx镜像,加入最新版consul-template,然后commit, push到hub上或自己的仓库中使用。
之所以要用自己的镜像,一个非常重要的原因是consul-template版本还是变更非常快的,它要随着consul版本的变更而变更Struct,用来解析最新的nodes, services等等json结构。 举例,我们本例中会用到的Meta属性就是目前网上现有的consul-template-nginx镜像中包含的consul-template所不能解析的。
自己基于官方nginx 镜像加入最新版的 consul-template,加入自己的ctmpl 模板文件
自定义consul-template-nginx
Dockerfile
FROM nginx
MAINTAINER LiZhenhe <zhenhe.li@vcg.com>
RUN apt-get update && \
apt-get install --no-install-recommends --no-install-suggests -y unzip && \
rm -r /var/lib/apt/lists/*
ENV CONSUL_TEMPLATE_VERSION 0.19.4
ADD https://releases.hashicorp.com/consul-template/${CONSUL_TEMPLATE_VERSION}/consul-template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip /tmp/consul-template.zip
RUN unzip /tmp/consul-template.zip -d /usr/bin && \
chmod +x /usr/bin/consul-template && \
rm /tmp/consul-template.zip
RUN mkdir /etc/ctmpl
COPY ctmpl /etc/ctmpl
WORKDIR /etc/ctmpl
ENTRYPOINT ["/usr/bin/consul-template"]
ctmpl模板文件, 内容还需要改造。这个模板来自网上,稍后,我基于这个模板加入Meta进行多域名解析的改造,适应我们现在线上环境的需求
{{range services}}
upstream {{.Name}} {
least_conn;{{range service .Name}}
server {{.Address}}:{{.Port}};{{end}}
}
{{end}}
server {
listen 80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
{{range services}}
location {{.Name}} {
proxy_read_timeout 180;
proxy_pass http://{{.Name}}/{{.Name}};
}
{{end}}
}
线上使用Tags,但不严谨, 应该使用Meta最为严谨安全
{{range services}}
{{$name := .Name}}
{{$service := service .Name}}
{{$tags := .Tags}}
upstream {{$name}} {
zone upstream-{{$name}} 64k;
{{range $service}}
server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
{{else}}
server 127.0.0.1:65535;
{{end}}
}
server {
listen 80;
listen 443;
charset utf-8;
server_name {{range $tags }} {{.}} {{else}}localhost{{end}};
access_log /var/log/nginx/{{$name}}.log;
location / {
proxy_pass http://{{$name}};
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 1000m;
proxy_buffering off;
}
}
{{end}}
注意这个ctmpl文件要与上面的Dockerfile放在同上目录下。
执行docker build -t="zhenheli/consul-template-nginx" -f Dockfile .来构建镜像
consul-template-nginx
version: '3'
services:
consul-template:
container_name: consul-template-nginx
image: zhenheli/consul-template-nginx
network_mode: bridge
external_links:
- consul_server:consul
command: -consul-addr=consul:8500 -wait=5s -template="/etc/ctmpl/ctmpl:/etc/nginx/conf.d/app.conf:nginx -s reload"
ports:
- 80:80
最终由于spring-cloud-consul-client版本过低也无法提供nodeMeta, 退回到使用tags, 不过为了安全起见, 制定了一个规则,
以vcg_domain:开头的才看作是要获取的域名的tag,具体实现如下:
{{range services}} {{$name := .Name}} {{$service := service .Name}} {{$tags := .Tags}}
upstream {{$name}} {
zone upstream-{{$name}} 64k;
{{range $service}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
{{else}}server 127.0.0.1:65535;{{end}}
}
server {
listen 80;
listen 443;
charset utf-8;
access_log /var/log/nginx/{{.Name}}.log;
server_name {{range $tag := .Tags}} {{if $tag|contains "vcg_domain:"}} {{$tag|replaceAll "vcg_domain:" ""}}{{else}}localhost{{end}}{{else}}localhost{{end}};
location / {
proxy_pass http://{{.Name}};
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 1000m;
proxy_buffering off;
}
} {{end}}
未完。更新日期:2018年04年24日 13:12
----------------------------------------
原创作品,版权归zhenhe.li@vcg.com所有,转载请标记出处。