要在生产环境建一套Elasticsearch 8.0,单节点搭配Kibana,确实是困难重重,新版本需要TLS验证了

现在这个时间节点,2025年9月2日,Elasticsearch最新版本是9.0,后撤2个版本是8.18.6

那就用这个版本了,然后根据官方的文档会把人搞糊涂的。

正确的方法如下:

一、建立自签的证书

其实可以用ACME的证书,但是没有人会三个月就去重启一下ES的容器,更新证书吧!

那只能选择自建CA,自签一个证书了!

因为有2个pod,es和kibana,所以要签两张证书,签证书随便用ES的一个版本就可以:

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.4.1-linux-x86_64.tar.gz

tar -zxf elasticsearch-8.4.1-linux-x86_64.tar.gz

cd elasticsearch-8.4.1/
./bin/elasticsearch-certutil ca --pem

# 得到CA证书,放在当前目录ca目录下
unzip elastic-stack-ca.zip

# 生成签发配置文件
cat << EOF >instances.yml 
instances:
   - name: es01
     dns:
       - es01
       - localhost
     ip:
       - 127.0.0.1
   - name: kibana
     dns:
       - kibana
       - localhost
     ip:
       - 127.0.0.1
EOF

# 签发2个pod的证书
./bin/elasticsearch-certutil cert --ca-cert ca/ca.crt --ca-key ca/ca.key --pem --in instances.yml
 
# 得到2张证书和key
unzip certificate-bundle.zip
# 生成两个目录,es01和kibana

# 准备好证书目录
mkdir -p /data/elasticsearch/certs
mv ca es01 kibana /data/elasticsearch/certs

# 准备好持久化卷
mkdir -p /data/elasticsearch/kibanadata
mkdir -p /data/elasticsearch/esdata01
二、配置docker-compose.yaml

8.18.6版本的docker-compose.yaml文件,位于:/data/elasticsearch/docker-compose.yaml

# docker-compose.yaml
services:
  es01:
    container_name: es
    # The Docker image to use for this service
    image: docker.elastic.co/elasticsearch/elasticsearch:8.18.6
    # The volumes to mount into this service
    volumes:
      - ./certs:/usr/share/elasticsearch/config/certs
      - ./esdata01:/usr/share/elasticsearch/data
    # The ports to expose from this service
    ports:
      - 9200:9200
    # The environment variables to set inside the container
    environment:
      - node.name=es01
      - cluster.name=lancode-cluster
      - discovery.type=single-node
      - ELASTIC_PASSWORD=aaaaaaaaaaaa
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms10g -Xmx10g"
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=true
      - xpack.security.http.ssl.key=certs/es01/es01.key
      - xpack.security.http.ssl.certificate=certs/es01/es01.crt
      - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.http.ssl.verification_mode=certificate
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.key=certs/es01/es01.key
      - xpack.security.transport.ssl.certificate=certs/es01/es01.crt
      - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.license.self_generated.type=basic
    # The memory limit for this service 12g = 1024*1024*1024*12
    mem_limit: 12884901888
    # The ulimits to set for this service
    ulimits:
      memlock:
        soft: -1
        hard: -1
    # The healthcheck to determine the health of this service
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120
  # The kibana service represents a Kibana instance
  kibana:
    # This service depends on the es01 service
    depends_on:
      es01:
        condition: service_healthy
    container_name: kibana
    # The Docker image to use for this service
    image: docker.elastic.co/kibana/kibana:8.18.6
    # The volumes to mount into this service
    volumes:
      - ./certs:/usr/share/kibana/config/certs
      - ./kibanadata:/usr/share/kibana/data
    # The ports to expose from this service
    ports:
      - 5601:5601
    # The environment variables to set inside the container
    environment:
      - SERVERNAME=kibana
      - ELASTICSEARCH_HOSTS=https://es01:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=bbbbbbbbbbbbbbb
      - ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
      - xpack.security.audit.enabled=true
      - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=cccccccccccccccccccccc
    # The memory limit for this service 2g = 1024*1024*1024*2
    mem_limit: 2147483648
    # The healthcheck to determine the health of this service
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

注意上面的计算:

  • 内存,系统是16G,2G保留,2G给kibana,12G给es,java启动参数给10g
  • ELASTIC_PASSWORD=aaaaaaaaaaaa 这里的pass是指ES的独立用户elastic
  • ELASTICSEARCH_PASSWORD=bbbbbbbbbbbbbb 这里的pass是指需要单独给kibana开的一个es用户kibana_system

最后登录kibana的密码是elastic用户的密码aaaaaaaaa

这里差点被绕糊涂了,ES升级后需要启用https,然后也多加了用户。kibana需要单独用一个用户kibana_system去连接es,而es呢,也有一个独立的用户elastic进行管理。登录kibanna呢,实际是要用elastic这个用户登录。Faint!!

三、启动
docker compose up -d

# 启动后必然报错,因为里面只有elastic这个用户,没有kibana_system用户
# 进入容器
docker exec -it es /bin/bash

# 生成密码
curl  -X POST --cacert config/certs/ca/ca.crt -u "elastic:aaaaaaaa" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d '{"password": "bbbbbbbb"}'

# 或者这样也行
docker-compose exec -T es bin/elasticsearch-reset-password --batch --user kibana_system
Password for the [kibana_system] user successfully reset.
New value: bbbbbbbb

然后就ok了,登录的时候用elastic的密码,不要用kibana_system!

image-20250902171625026

四、题外

最鬼畜的地方就是kibana

里面设置的两个配置项ELASTICSEARCH_USERNAMEELASTICSEARCH_PASSWORD还有ELASTICSEARCH_HOSTS, 居然是环境变量

进入容器里看到的kibana.yaml,倒数第二行elasticsearch.hosts 根本就是错的,误导群众,这里是环境变量优先,根本没有用到kibana.yaml中的配置!!!一定要注意。

image-20250902172211327

五、后记

无语啊无语,弄了自签证书,结果同事反映连接报证书错误

算了,给个不要证书的配置docker-compose.yaml

services:
  es01:
    container_name: es
    # The Docker image to use for this service
    image: docker.elastic.co/elasticsearch/elasticsearch:8.18.6
    # The volumes to mount into this service
    volumes:
      - ./certs:/usr/share/elasticsearch/config/certs
      - ./esdata01:/usr/share/elasticsearch/data
    # The ports to expose from this service
    ports:
      - 9200:9200
    # The environment variables to set inside the container
    environment:
      - node.name=es01
      - cluster.name=lancode-cluster
      - discovery.type=single-node
      - ELASTIC_PASSWORD=aaaaaaaaaaaa
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms10g -Xmx10g"
      - xpack.security.enabled=false
      - xpack.license.self_generated.type=basic
    # The memory limit for this service 12g = 1024*1024*1024*12
    mem_limit: 12884901888
    # The ulimits to set for this service
    ulimits:
      memlock:
        soft: -1
        hard: -1
    # The healthcheck to determine the health of this service
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s -I http://localhost:9200 | grep -q 'HTTP/1.1 200 OK'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120
  # The kibana service represents a Kibana instance
  kibana:
    # This service depends on the es01 service
    depends_on:
      es01:
        condition: service_healthy
    container_name: kibana
    # The Docker image to use for this service
    image: docker.elastic.co/kibana/kibana:8.18.6
    # The volumes to mount into this service
    volumes:
      - ./certs:/usr/share/kibana/config/certs
      - ./kibanadata:/usr/share/kibana/data
    # The ports to expose from this service
    ports:
      - 5601:5601
    # The environment variables to set inside the container
    environment:
      - SERVERNAME=kibana
      - ELASTICSEARCH_HOSTS=http://es01:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=bbbbbbbbbbbbbbb
      - xpack.security.enabled=false
      - xpack.security.audit.enabled=true
      - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=cccccccccccccccccccccc
    # The memory limit for this service 2g = 1024*1024*1024*2
    mem_limit: 2147483648
    # The healthcheck to determine the health of this service
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

区别在于 xpack.security.enabled=false和healthcheck