通过Docker部署Elasticsearch时开启SSL/TLS加密通讯

前言

在生产环境中部署docker需要开启加密通讯, 这样可以保障ES各个组件直接通讯的安全性

环境

说明: 本部署基于Windows的linux版docker, 如果是在linux docker下部署, 仅需要安装docker-ce与docker-compose

项目 说明
宿主机系统 Windows 10
虚拟机系统 Boot2Docker 18.09.1
docker 18.09.0
docker-compose 1.23.2
ES容器IP 192.168.28.60
git 2.20.1-64-bit

涉及的文件

新建一个空目录, 名为”deploy-ssl-es-docker”, 将以下文件放在此目录的根目录下.

  • instances.yml:

    此文件配合elasticsearch-certgen工具使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    instances:
    - name: es01
    dns:
    # es容器的dns名
    - es01
    - localhost
    ip:
    # 使用IP访问时此处要改成调用容器的IP
    # 不一定是容器自身的IP, 而是各个服务进行调用的IP
    # 否则证书认证将无法通过
    # 可填多个IP
    - 127.0.0.1

    - name: es02
    dns:
    - es02
    - localhost
    ip:
    # 使用IP访问时此处要改成调用容器的IP
    # 不一定是容器自身的IP, 而是各个服务进行调用的IP
    # 否则证书认证将无法通过
    # 可填多个IP
    - 127.0.0.1
  • .env:

    1
    2
    3
    4
    # es容器内的证书存储位置
    CERTS_DIR=/usr/share/elasticsearch/config/certificates
    # elastic用户的密码, 这里需要修改后再进行下面的操作
    ELASTIC_PASSWORD=PleaseChangeMe
  • create-certs.yml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    version: '2.2'

    services:
    create_certs:
    container_name: create_certs
    image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
    command: >
    bash -c '
    if [[ ! -d config/certificates/certs ]]; then
    mkdir config/certificates/certs;
    fi;
    if [[ ! -f /local/certs/bundle.zip ]]; then
    bin/elasticsearch-certgen --silent --in config/certificates/instances.yml --out config/certificates/certs/bundle.zip;
    # 将新生成的证书文件放到"config/certificates/certs"
    unzip config/certificates/certs/bundle.zip -d config/certificates/certs;
    fi;
    chgrp -R 0 config/certificates/certs
    '
    user: ${UID:-1000}
    working_dir: /usr/share/elasticsearch
    volumes: ['.:/usr/share/elasticsearch/config/certificates']
  • docker-compose.yml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    version: '2.2'

    services:
    es01:
    container_name: es01
    image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
    # 生产环境建议设置ulimits
    ulimits:
    memlock:
    soft: -1
    hard: -1
    nofile:
    soft: 65536
    hard: 65536
    nproc:
    soft: 65536
    hard: 65536
    environment:
    - node.name=es01
    # 生产环境建议开启
    - bootstrap.memory_lock=true
    - discovery.zen.minimum_master_nodes=2
    - ELASTIC_PASSWORD=$ELASTIC_PASSWORD
    - 'ES_JAVA_OPTS=-Xms512m -Xmx512m'
    - xpack.license.self_generated.type=trial
    - xpack.security.enabled=true
    - xpack.security.http.ssl.enabled=true
    - xpack.security.transport.ssl.enabled=true
    - xpack.security.transport.ssl.verification_mode=certificate
    - xpack.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
    - xpack.ssl.certificate=$CERTS_DIR/es01/es01.crt
    - xpack.ssl.key=$CERTS_DIR/es01/es01.key
    volumes: ['esdata_01:/usr/share/elasticsearch/data', './certs:$CERTS_DIR']
    ports:
    - 9200:9200
    healthcheck:
    test: curl --cacert $CERTS_DIR/ca/ca.crt -s https://localhost:9200 >/dev/null; if [[ $$? == 52 ]]; then echo 0; else echo 1; fi
    interval: 30s
    timeout: 10s
    retries: 5

    es02:
    container_name: es02
    image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
    # 生产环境建议设置ulimits
    ulimits:
    memlock:
    soft: -1
    hard: -1
    nofile:
    soft: 65536
    hard: 65536
    nproc:
    soft: 65536
    hard: 65536
    environment:
    - node.name=es02
    # 生产环境建议开启
    - bootstrap.memory_lock=true
    - discovery.zen.minimum_master_nodes=2
    # elastic用户的密码, 需要在".env"文件中修改
    - ELASTIC_PASSWORD=$ELASTIC_PASSWORD
    - discovery.zen.ping.unicast.hosts=es01
    - 'ES_JAVA_OPTS=-Xms512m -Xmx512m'
    # xpack的授权模式, 提供basic和trial
    # ref: https://www.elastic.co/guide/en/elasticsearch/reference/master/license-settings.html
    - xpack.license.self_generated.type=trial
    - xpack.security.enabled=true
    - xpack.security.http.ssl.enabled=true
    - xpack.security.transport.ssl.enabled=true
    # 提供full, certificate, 和none三种选项, 由于是自签名所以设置成certificate
    # ref: https://www.elastic.co/guide/en/elasticsearch/reference/current/security-settings.html#ssl-tls-settings
    - xpack.security.transport.ssl.verification_mode=certificate
    - xpack.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
    - xpack.ssl.certificate=$CERTS_DIR/es02/es02.crt
    - xpack.ssl.key=$CERTS_DIR/es02/es02.key
    volumes: ['esdata_02:/usr/share/elasticsearch/data', './certs:$CERTS_DIR']

    wait_until_ready:
    image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
    command: /usr/bin/true
    depends_on: { 'es01': { 'condition': 'service_healthy' } }

    volumes: { 'esdata_01': { 'driver': 'local' }, 'esdata_02': { 'driver': 'local' } }

部署

如果是在Windows下运行, 建议以下命令使用git bash执行

命令行进入”deploy-ssl-es-docker”目录并执行以下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

# winpty docker-machine ssh # 如果是Windows git bash下执行, 需要去掉此行注释

sudo /bin/bash -c 'cat >> /etc/sysctl.conf <<EOF
vm.max_map_count=262144
EOF'
sudo sysctl -p

# exit # 如果是Windows git bash下执行, 需要去掉此行注释

# 创建证书
docker-compose -f create-certs.yml up

# 启动容器
docker-compose up -d

测试运行状态

启动服务后等2-3分钟执行以下命令查看服务是否正常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

# 请将'192.168.28.60'换成环境中真实的容器IP, 如果返回不正常可以使用"docker logs es01"查看日志分析问题
curl --cacert certs/ca/ca.crt -u elastic:PleaseChangeMe https://192.168.28.60:9200

# 返回信息:
# {
# "name" : "es01",
# "cluster_name" : "docker-cluster",
# "cluster_uuid" : "NJHOMNVnTfSn-EBIfIzaVg",
# "version" : {
# "number" : "6.5.4",
# "build_flavor" : "default",
# "build_type" : "tar"
# "build_hash" : "d2ef93d",
# "build_date" : "2018-12-17T21:17:40.758843Z",
# "build_snapshot" : false,
# "lucene_version" : "7.5.0",
# "minimum_wire_compatibility_version" : "5.6.0",
# "minimum_index_compatibility_version" : "5.0.0"
# },
# "tagline" : "You Know, for Search"
# }

常见问题

如果容器起不来发现日志报错信息如下:

1
2
ERROR: [1] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

这代表docker下的宿主机需要设置”vm.max_map_count”参数
请在docker宿主机下执行以下命令:

1
2
3
4
5
6
7
8
9
#!/bin/bash


# winpty docker-machine ssh # 如果是Windows git bash下执行, 需要去掉此行注释

sudo /bin/bash -c 'cat >> /etc/sysctl.conf <<EOF
vm.max_map_count=262144
EOF'
sudo sysctl -p

Git项目

https://github.com/x22x22/deploy-ssl-es-docker

参考

Install Elasticsearch with Dockeredit
Encrypting communications in an Elasticsearch Docker Container

显示 Gitment 评论