docker-compose安装高可用Eureka集群
构建Eureka注册中心镜像
eureka项目来自于我之前写的一篇博客,博客地址: springcloud篇-(高可用注册中心Eureka集群实现)
1.修改原项目中的application.yml配置
server:
port: 8761
eureka:
auth:
enable: ${EUREKA_AUTH_ENABLE:false} #将认证相关的配置,通过这种方式来设置,方便在docker中通过环境变量来改变这些参数
username: ${EUREKA_AUTH_USERNAME:root}
password: ${EUREKA_AUTH_PASSWORD:123456}
server:
eviction-interval-timer-in-ms: 60000 #驱逐下线服务的间隔时间
enable-self-preservation: ${EUREKA_ENABLE_SELF_PRESERVATION:false} #关闭eureka服务自我保护机制,使eviction-interval-timer-in-ms配置生效
instance:
health-check-url-path: /actuator/health #健康检查地址
prefer-ip-address: true #显示ip地址
hostname: ${EUREKA_HOSTNAME:localhost}
client:
fetch-registry: false #注册中心不需要拉取服务
register-with-eureka: false #使用高可用集群搭建,设置为false即可
service-url:
defaultZone: ${EUREKA_SERVER_LIST:http://localhost:8761/eureka} #注册中心地址
spring:
application:
name: eureka-server
2.将项目打包上传到centos
3.编写Dockerfile文件
cat > Dockerfile <<EOF
FROM adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.9_11
# dockerfile维护人员
MAINTAINER lhstack@foxmail.com
#定义标签
LABEL version=0.0.1
LABEL gitee="https://gitee.com/myprofile"
# jvm参数
ENV JVM_OPTS "-Xmx128m -Xms128m -Xmn32m -Xss512k -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\$WORKDIR/error -Duser.timezone=Asia/Shanghai"
# 项目参数
ENV JAVA_OPTS ""
ENV WORKDIR "/opt/eureka"
#挂载error目录
VOLUME /opt/eureka/error
# 配置时区
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \\
&& apk update \\
&& apk add --no-cache tzdata \\
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 设置时区
ENV TZ Asia/Shanghai
# 设置工作目录
WORKDIR \$WORKDIR
# 将tomcat拷贝到工作目录
ADD *.jar app.jar
# 暴露端口
EXPOSE 8761
# 启动eureka
CMD java \$JVM_OPTS \$JAVA_OPTS -jar app.jar
EOF
4.构建eureka镜像
docker build -t eureka:0.0.1-alpine .
5.运行镜像
docker run --rm -ti -p 8761:8761 eureka:0.0.1-alpine
通过浏览器访问
搭建集群
1.编写eureka集群的环境变量
mkdir env
cat > env/eureka.env <<EOF
EUREKA_AUTH_ENABLE=true
EUREKA_AUTH_USERNAME=admin
EUREKA_AUTH_PASSWORD=123456
EUREKA_HOSTNAME=\${hostname}
EUREKA_SERVER_LIST="http://admin:123456@eureka-1:8761/eureka,http://admin:123456@eureka-2:8761/eureka,http://admin:123456@eureka-3:8761/eureka"
EOF
2.编写docker-compose.yaml文件
cat > docker-compose.yaml <<EOF
version: '3'
services:
eureka-1:
image: eureka:0.0.1-alpine
build: .
ports:
- 8761:8761
container_name: eureka-1
env_file:
- ./env/eureka.env
hostname: eureka-1
networks:
- eureka
eureka-2:
image: eureka:0.0.1-alpine
ports:
- 8762:8761
container_name: eureka-2
env_file:
- ./env/eureka.env
hostname: eureka-2
networks:
- eureka
eureka-3:
image: eureka:0.0.1-alpine
ports:
- 8763:8761
container_name: eureka-3
env_file:
- ./env/eureka.env
hostname: eureka-3
networks:
- eureka
networks:
eureka:
driver: bridge
ipam:
driver: default
config:
- subnet: "10.10.0.0/16"
EOF
3.执行docker-compose并通过浏览器访问对应端口的eureka应用
第一个
第二个
第三个
可以看到,上面指向的eureka高可用集群开发的那篇博客里面,集群页面是没有Ds Replicas的,是因为那篇博客里面的hostname都是localhost,所以eureka无法区分出来副本,实际上是不影响的
通过nginx实现负载均衡
1.生成nginx配置
mkdir conf
cat > ./conf/eureka.conf <<EOF
upstream eureka-cluster{
server eureka-1:8761 weight=1;
server eureka-2:8761 weight=1;
server eureka-3:8761 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP \$remote_addr; # 将客户端真实ip存放到X-Real-IP这个header里面,由于这里是没有使用host模式启动nginx,获取的会是宿主机的ip
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; # 每经过一个反向代理,就会把反向代理IP存放在X-Forwarded-For里
proxy_pass http://eureka-cluster;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
EOF
2.修改docker-compose.yaml,添加nginx进去
cat > docker-compose.yaml <<EOF
version: '3'
services:
eureka-lb:
image: nginx:alpine
container_name: eureka-lb
ports:
- 8080:80
volumes:
- ./conf:/etc/nginx/conf.d
depends_on:
- eureka-1
- eureka-2
- eureka-3
networks:
- eureka
eureka-1:
image: eureka:0.0.1-alpine
build: .
container_name: eureka-1
env_file:
- ./env/eureka.env
hostname: eureka-1
networks:
- eureka
eureka-2:
image: eureka:0.0.1-alpine
container_name: eureka-2
env_file:
- ./env/eureka.env
hostname: eureka-2
networks:
- eureka
eureka-3:
image: eureka:0.0.1-alpine
container_name: eureka-3
env_file:
- ./env/eureka.env
hostname: eureka-3
networks:
- eureka
networks:
eureka:
driver: bridge
ipam:
driver: default
config:
- subnet: "10.10.0.0/16"
EOF
3.通过浏览器访问
配置nginx ssl支持
1.下载cfssl证书生成工具
wget -O /usr/local/sbin/certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 && chmod +x /usr/local/sbin/certinfo
wget -O /usr/local/sbin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 && chmod +x /usr/local/sbin/cfssl
wget -O /usr/local/sbin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 && chmod +x /usr/local/sbin/cfssljson
2.生成证书
mkdir ssl && cd ssl
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"eureka": {
"expiry": "876000h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
}
}
}
}
EOF
cat > ca-csr.json <<EOF
{
"CN": "www.eureka.com.cn",
"hosts": [
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
EOF
#生成ca根证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
cat > server-csr.json <<EOF
{
"CN": "www.eureka.com.cn",
"hosts": [
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
EOF
#生成服务端证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=eureka server-csr.json | cfssljson -bare server
cd ..
3.修改nginx的配置文件
cat > ./conf/eureka.conf <<EOF
upstream eureka-cluster{
server eureka-1:8761 weight=1;
server eureka-2:8761 weight=1;
server eureka-3:8761 weight=1;
}
server {
listen 443 ssl http2 default_server;
server_name www.eureka.com.cn [::]:443 ssl http2 default_server;
ssl_certificate /opt/ssl/eureka/server.pem; # pem文件的路径
ssl_certificate_key /opt/ssl/eureka/server-key.pem; # key文件的路径
ssl_session_timeout 5m; #缓存有效期
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #加密算法
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #安全链接可选的加密协议
ssl_prefer_server_ciphers on; #使用服务器端的首选算法
location / {
proxy_set_header X-Real-IP \$remote_addr; # 将客户端真实ip存放到X-Real-IP这个header里面,由于这里是没有使用host模式启动nginx,获取的会是宿主机的ip
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; # 每经过一个反向代理,就会把反向代理IP存放在X-Forwarded-For里
proxy_pass http://eureka-cluster;
}
}
EOF
4.修改docker-compose.yml
cat > docker-compose.yaml <<EOF
version: '3'
services:
eureka-lb:
image: nginx:alpine
container_name: eureka-lb
ports:
- 8443:443
volumes:
- ./conf:/etc/nginx/conf.d
- ./ssl:/opt/ssl/eureka
depends_on:
- eureka-1
- eureka-2
- eureka-3
networks:
- eureka
eureka-1:
image: eureka:0.0.1-alpine
build: .
container_name: eureka-1
env_file:
- ./env/eureka.env
hostname: eureka-1
networks:
- eureka
eureka-2:
image: eureka:0.0.1-alpine
container_name: eureka-2
env_file:
- ./env/eureka.env
hostname: eureka-2
networks:
- eureka
eureka-3:
image: eureka:0.0.1-alpine
container_name: eureka-3
env_file:
- ./env/eureka.env
hostname: eureka-3
networks:
- eureka
networks:
eureka:
driver: bridge
ipam:
driver: default
config:
- subnet: "10.10.0.0/16"
EOF
5.通过浏览器访问
注意:查看eureka启动日志,确认启动成功之后再访问
注册product和consumer测试是否可用
1.因为eureka注册中心使用ssl进行代理,所以客户端注册的时候,需要配置证书信息
# 如果centos上面没有keytool工具,请用windows的,这里ca.pem就是nginx里面ssl目录下面的ca.pem文件
keytool -import -noprompt -file ca.pem -keystore truststore.jks -storepass 123456
# openssl在centos上是默认安装了的,这里我们导出server.pem相关文件格式为p12,pass:这里设置密码
openssl pkcs12 -export -in server.pem -inkey server-key.pem -out keystore.p12 -passout pass:123456
# 将p12格式证书导出成jks
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -srcstorepass 123456 -deststorepass 123456
2.配置域名映射,因为客户端这边配置了证书之后,会验证域名,我们上面生成的证书文件域名为www.eureka.com.cn
,因此我们添加一行域名映射
3.打开之前的product和consumer两个项目,分别将生成的keystore.jks和truststore.jks复制到resources目录下面,并且修改application.yaml文件内容为
Product
spring:
application:
name: Product
eureka:
instance:
prefer-ip-address: true
health-check-url-path: /actuator/health
client:
register-with-eureka: true
fetch-registry: false #生产端不需要拉取服务
service-url:
defaultZone: https://admin:123456@www.eureka.com.cn:8443/eureka #新的注册中心地址
tls: #证书相关
enabled: true
key-store: classpath:keystore.jks
key-store-password: 123456
key-password: 123456
trust-store-password: 123456
trust-store: classpath:truststore.jks
server:
port: 9090
Consumer
spring:
application:
name: Consumer
eureka:
instance:
prefer-ip-address: true
health-check-url-path: /actuator/health
client:
register-with-eureka: true
fetch-registry: true #消费端需要发现服务
service-url:
defaultZone: https://admin:123456@www.eureka.com.cn:8443/eureka #注册中心地址
tls:
enabled: true
key-store: classpath:keystore.jks
key-store-password: 123456
key-password: 123456
trust-store-password: 123456
trust-store: classpath:truststore.jks
server:
port: 8080
4.分别启动product和consumer,并查看注册中心是否存在实例
因为eureka-server注册中心副本默认同步时间设置的是30s,所以服务注册上去之后,所有节点不是马上就会有最新的注册实例
5.访问Consumer,查看是否能调用生产者暴露的服务