Study/Kubernetes

[Kubernetes]Elasticsearch, Kibana를 Docker로 띄우기 & Fluentd는 Pod로 띄우기

seomj 2023. 11. 4. 23:30

 

현재 프로젝트를 진행하며 서비스할 Web과 API Server의 log를 모니터링하기 위해 EFK는 구축하고자 했다.


EKF

Elasticsearch + Fluentd + Kibana

 

Fluentd: 로그 수집

Elasticsearch: 수집된 로그를 검색 및 분석하여 저장

Kibana: ES를 통해 데이터 시각화

 

https://peterica.tistory.com/210

 

 

환경 구성

AWS 위 bastion에 ES와 Kibana를 docker로 띄워서 구성한 다음, eks worker node에 fluentd를 daemonset으로 배포하여 log를 수집해 올 예정이다.

web과 api는 현재 node 위 pod로 배포되어 있는 상황이다.

추후 가능하다면 publice에 있는 bastion에서 private에 위치한 gitops로 es는 옮길 예정이다.

 

하지만 현재 상황에서는 각 노드에 로그만 가져올 수 있는 선까지만 구현했다.

 

 

AWS 환경 구성

TEST 환경을 구성하기 위해 bastion 하나와 EKS를 구성하여 진행했다.

그리고 아래에서 설명을 하겠지만 es를 돌릴 instance의 유형은 t3.large 정도는 되어야 괜찮다.

나는 t3.medium에서 하다가 컨테이너가 자꾸 죽어서 몇시간을 삽질했다...

 

docker를 미리 설치해두어야 한다.

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

 

그리고 해당 인스턴스 보안그룹에서 9200, 5601을 열어줘야 한다.

나는 현재 http로 구성을 했기에 9200만 열어줬다. 필요하다면 9200도 열어주어야 한다.

 

 

 

Elasticsearch docker로 띄우기

https로 통신을 하도록 되어 있는거 같은데 본인은 http로 구성했다.

 

es와 관련된 컨테이너들을 동일한 네트워크에 연결하여 통신할 수 있도록 하기 위해 network를 create했다.

$ docker network create elastic

 

image를 pull 하자.

$ docker pull docker.elastic.co/elasticsearch/elasticsearch:8.10.4

 

container를 실행시키자.

$ sudo docker run -d --name es01 --net elastic -p 9200:9200 -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.10.4

-d 옵션으로 백그라운드에서 동작하도록 설정하였다.

 

하지만 여기서 컨테이너 자꾸 죽는 현상이 발생했다.

이걸 해결하기 위해 2가지 조치를 취했다.

  • t3.medium에서 t3.large로 instance type 변경
  • vm.max_map_count를 262144로 설정
# 일시적 변경
$ sudo sysctl -w vm.max_map_count=262144

# 영구적 변경
$ vi /etc/sysctl.conf
vm.max_map_count=262144

$ sysctl vm.max_map_count
$ sudo docker restart es01

 

이 2가지를 진행하므로 해결할 수 있었다.

 

vm.max_map_count

https://www.gimsesu.me/elasticsearch-change-vm-max-map-count

기본 값은 Linux의 경우 65,530

es를 실행하기 위해서는 최소 262,144로 상향하는 것을 권장

 

이는 프로세스가 가질 수 있는 최대 메모리 맵 영역 수를 포함

변수로, /proc/sys/vm/max_map_count 파일을 가리킨다.

이 파일은 Linux kernel의 메모리 맵*영역의 최대 개수를 조작할 수 있다.

메모리 매핑 작업이 많이 일어나는 프로세스일수록 가상 메모리에서의 주소 공간인 가상 주소 공간을 많이 필요로 한다.

 

ES는 운영 체제를 이용하여 인덱스 파일들을 가상 메모리에 가상으로 매핑하고 파일 시스템 캐시를 생성한다. 덕분에 검색 요청이 들어오면 디스크에 접근할 필요 없이 캐시에 들어있는 데이터를 가져와 신속하게 응답한다.

그러나 Linux의 경우 응용 프로그램이 한번에 너무 많은 파일을 열거나 너무 많은 메모리를 매핑하는 것을 방지하는 제한이 있다. 이게 바로 vm.max_map_count이다.

 

 

이제 https가 아닌 http로 통신하기 위해 container 내부의 config를 수정하자.

exec로 접근은 가능하지만 내부에 vi, vim 등이 없어 파일을 수정하는 데 지장이 있다. 

나는 파일을 로컬에서 작성하여 컨테이너 내부로 넣어줬다. 

 

우선 파일을 먼저 확인하기 위해 컨테이너 내부로 진입하자.

여기서 확인해야 할 파일은 ~/config/elasticsearch.yml 이다.

$ sudo docker exec -it es01 /bin/bash

elasticsearch@c00a7b999cf1:~$ cat config/elasticsearch.yml
cluster.name: "docker-cluster"
network.host: 0.0.0.0

#----------------------- BEGIN SECURITY AUTO CONFIGURATION -----------------------
#
# The following settings, TLS certificates, and keys have been automatically
# generated to configure Elasticsearch security features on 30-10-2023 17:49:37
#
# --------------------------------------------------------------------------------

# Enable security features
xpack.security.enabled: true

xpack.security.enrollment.enabled: true

# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents
xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/http.p12

# Enable encryption and mutual authentication between cluster nodes
xpack.security.transport.ssl:
  enabled: true
  verification_mode: certificate
  keystore.path: certs/transport.p12
  truststore.path: certs/transport.p12
#----------------------- END SECURITY AUTO CONFIGURATION -------------------------
elasticsearch@c00a7b999cf1:~$ exit
exit

 

여기서 변경해야 할 값은 xpack.security.enabled 값으로 true에서 false로 변경해주면 된다.

https://www.elastic.co/guide/en/elasticsearch/reference/current/security-settings.html

ES 보안 기능을 활성화하는 값으로 false로 비활성화하자.

이는 보안에 대해 사용하지 않는 설정이므로 주의하여 사용할 필요가 있다.

 

 

해당 파일의 내용을 복사하여 로컬에서 수정한 뒤 컨테이너로 넣어주자.

$ vi es.yaml
$ sudo docker cp es.yaml es01:/usr/share/elasticsearch/config/elasticsearch.yml
Successfully copied 2.56kB to es01:/usr/share/elasticsearch/config/elasticsearch.yml
$ sudo docker restart es01
es01
$ sudo docker ps
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED          STATUS         PORTS                                                 NAMES
c00a7b999cf1   docker.elastic.co/elasticsearch/elasticsearch:8.10.4   "/bin/tini -- /usr/l…"   11 minutes ago   Up 4 seconds   0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 9300/tcp   es01
$ sudo docker exec -it es01 /bin/bash

elasticsearch@c00a7b999cf1:~$ cat config/elasticsearch.yml
cluster.name: "docker-cluster"
network.host: 0.0.0.0

#----------------------- BEGIN SECURITY AUTO CONFIGURATION -----------------------
#
# The following settings, TLS certificates, and keys have been automatically
# generated to configure Elasticsearch security features on 30-10-2023 17:49:37
#
# --------------------------------------------------------------------------------

# Enable security features
xpack.security.enabled: false

xpack.security.enrollment.enabled: true

# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents
xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/http.p12

# Enable encryption and mutual authentication between cluster nodes
xpack.security.transport.ssl:
  enabled: true
  verification_mode: certificate
  keystore.path: certs/transport.p12
  truststore.path: certs/transport.p12
#----------------------- END SECURITY AUTO CONFIGURATION -------------------------
elasticsearch@c00a7b999cf1:~$ exit
exit

ubuntu@ip-10-0-3-39:~/es$ curl localhost:9200
{
  "name" : "c00a7b999cf1",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "oREeGd4TSUSmYOYxgRXW0A",
  "version" : {
    "number" : "8.10.4",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "b4a62ac808e886ff032700c391f45f1408b2538c",
    "build_date" : "2023-10-11T22:04:35.506990650Z",
    "build_snapshot" : false,
    "lucene_version" : "9.7.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

 

이제 모든 설정이 끝났으니 curl을 통해 잘 작동하고 있는지 확인을 해보자.

$ sudo docker ps
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED         STATUS         PORTS
                            NAMES
a31b9e008050   docker.elastic.co/elasticsearch/elasticsearch:8.10.4   "/bin/tini -- /usr/l…"   5 minutes ago   Up 2 minutes   0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 9300/tcp   es01

$ curl localhost:9200
{
  "name" : "a31b9e008050",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "S6nLV9ZgRvWcXQyYk3iwrg",
  "version" : {
    "number" : "8.10.4",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "b4a62ac808e886ff032700c391f45f1408b2538c",
    "build_date" : "2023-10-11T22:04:35.506990650Z",
    "build_snapshot" : false,
    "lucene_version" : "9.7.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

 

 

Kibana docker로 띄우기

kibana는 바로 뜨더라..ㅎㅎ

$ sudo docker run -d --name kib01 --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.10.4

$ sudo docker ps
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED         STATUS         PORTS
                            NAMES
a89662b6265e   docker.elastic.co/kibana/kibana:8.10.4                 "/bin/tini -- /usr/l…"   5 seconds ago   Up 4 seconds   0.0.0.0:5601->5601/tcp, :::5601->5601/tcp             kib01
a31b9e008050   docker.elastic.co/elasticsearch/elasticsearch:8.10.4   "/bin/tini -- /usr/l…"   7 minutes ago   Up 4 minutes   0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 9300/tcp   es01

 

 

확인

elasticsearch

 

kibana

 

kibana에서 elasticsearch로 구성을 하기 위해 kibana container에서 bin/kibana-verification-code를 실행

kibana@a89662b6265e:~/bin$ ./kibana-verification-code
Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/8.10/production.html#openssl-legacy-provider
Your verification code is:  xxx xxx

xxx xxx에 번호가 뜨고 해당 번호를 web에 입력하면 끝!

 

 

Fluentd daemonset 띄우기

fluentd daemonset 으로 설치하기 위해 manifest.yaml 다운받자.

$ curl -LJ -o fluentd.yaml https://github.com/fluent/fluentd-kubernetes-daemonset/blob/master/fluentd-daemonset-elasticsearch-rbac.yaml?raw=true

 

 

다운받은 fluentd.yaml에서 FLUENT_ELASTICSEARCH_HOST의 value 값만 내 ip로 변경하면 된다.

      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
          - name:  FLUENT_ELASTICSEARCH_HOST
            value: "[elasticsearch 호스트 ip]"
          - name:  FLUENT_ELASTICSEARCH_PORT
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME
            value: "http"

 

 

이제 적용하자.

$ kubectl apply -f fluentd.yaml

 

 

확인

kibana에서 Management > Index Management

보면 logstash로 해서 데이터가 쌓이는 것을 확인할 수 있다.

 

Index Pattern에서 logstash-*로 설정한 후 dashboard에서 확인해보자.

nginx를 배포했다가 지우고 하면 log가 찍히는 것을 확인할 수 있다.

 

node에 기록되는 log 가져오기 까지는 성공!

 

그러나 내가 구현하고 싶은 pod의 log를 가져오기 위해서는 fluentd의 confing를 공부하여 원하는 대로 작성한 후 configmap을 함께 apply 해야한다. 추후 공부해보며 진행해보도록 하자.

 

 

 

참고

https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html

https://www.elastic.co/guide/en/kibana/current/docker.html

https://twofootdog.tistory.com/50