Kubernetes - запуск EFK

Thank you for reading this post, don't forget to subscribe!

Мой рабо­чий вари­ант (ILM не рабо­та­ет) - печаль беда

 

Запуск EFK-сте­ка с посто­ян­ны­ми локаль­ны­ми тома­ми Elasticsearch в Kubernetus. Так же здесь запус­ка­ет­ся ingress для Kibana, что поз­во­лит обра­щать­ся к сер­ви­су извне.

cat elasticsearch_pv.yaml

[codesyntax lang="php"]

[/codesyntax]

 

cat pvc-local.yaml

[codesyntax lang="php"]

[/codesyntax]

 

cat elasticsearch_statefulset.yaml

[codesyntax lang="php"]

[/codesyntax]

 

cat elasticsearch_svc.yaml

[codesyntax lang="php"]

[/codesyntax]

cat fluentd-daemonset.yaml

[codesyntax lang="php"]

[/codesyntax]

cat kibana.yaml

[codesyntax lang="php"]

[/codesyntax]

cat kibana_ingress.yaml

[codesyntax lang="php"]

[/codesyntax]

================================================

EFK - с томами на nfs шаре

 

Elasticsearch — рас­пре­де­лен­ный и мас­шта­би­ру­е­мый меха­низм поис­ка в реаль­ном вре­ме­ни, под­дер­жи­ва­ю­щий пол­но­тек­сто­вый и струк­ту­ри­ро­ван­ный поиск, а так­же ана­ли­ти­ку. Он обыч­но исполь­зу­ет­ся для индек­са­ции боль­ших жур­на­лов и поис­ка в них дан­ных, но так­же его мож­но исполь­зо­вать и для поис­ка во мно­гих раз­лич­ных видах документов.

Elasticsearch обыч­но раз­вер­ты­ва­ет­ся вме­сте с Kibana, мощ­ным интер­фей­сом визу­а­ли­за­ции дан­ных, кото­рый высту­па­ет как панель управ­ле­ния Elasticsearch. Kibana поз­во­ля­ет про­смат­ри­вать дан­ные жур­на­лов Elasticsearch через веб-интер­фейс и созда­вать инфор­ма­ци­он­ные пане­ли и запро­сы для быст­ро­го полу­че­ния отве­тов на вопро­сы и ана­ли­ти­че­ских дан­ных по вашим при­ло­же­ни­ям Kubernetes.

мы исполь­зу­ем Fluentd для сбо­ра дан­ных жур­на­ла и их пре­об­ра­зо­ва­ния и отправ­ки на сер­вер Elasticsearch. Fluentd — попу­ляр­ный сбор­щик дан­ных с откры­тым исход­ным кодом, кото­рый мы настро­им на узлах Kubernetes для отсле­жи­ва­ния фай­лов жур­на­ла кон­тей­не­ров, филь­тра­ции и пре­об­ра­зо­ва­ния дан­ных жур­на­ла и их достав­ки в кла­стер Elasticsearch, где они будут индек­си­ро­вать­ся и храниться.

Для нача­ла мы настро­им и запу­стим мас­шта­би­ру­е­мый кла­стер Elasticsearch, а затем созда­дим служ­бу и раз­вер­ты­ва­ние Kibana в Kubernetes. В заклю­че­ние мы настро­им Fluentd как DaemonSet, кото­рый будет запус­кать­ся на каж­дом рабо­чем узле Kubernetes.

 

Узна­ём имя кластера(потом понадобится)

Шаг 1 — Создание пространства имен

Преж­де чем раз­во­ра­чи­вать кла­стер Elasticsearch, мы созда­дим про­стран­ство имен, куда уста­но­вим весь инстру­мен­та­рий веде­ния жур­на­лов. Kubernetes поз­во­ля­ет отде­лять объ­ек­ты, рабо­та­ю­щие в кла­сте­ре, с помо­щью вир­ту­аль­но­го абстра­ги­ро­ва­ния кла­сте­ров через про­стран­ства имен. В этом обу­ча­ю­щем моду­ле мы созда­дим про­стран­ство имен efk, куда уста­но­вим ком­по­нен­ты ком­плек­са EFK. Это про­стран­ство имен так­же поз­во­лит нам быст­ро очи­щать и уда­лять ком­плекс жур­на­лов без поте­ри функ­ци­о­наль­но­сти кла­сте­ра Kubernetes.

Для нача­ла иссле­дуй­те суще­ству­ю­щие про­стран­ства имен в вашем кла­сте­ре с помо­щью коман­ды kubectl:

Про­стран­ство имен default содер­жит объ­ек­ты, кото­рые созда­ют­ся без ука­за­ния про­стран­ства имен. Про­стран­ство имен kube-system содер­жит объ­ек­ты, создан­ные и исполь­зу­е­мые систе­мой Kubernetes, в том чис­ле kube-dnskube-proxy и kubernetes-dashboard. Это про­стран­ство имен луч­ше регу­ляр­но очи­щать и не засо­рять его рабо­чи­ми зада­ча­ми при­ло­же­ний и инструментария.

Про­стран­ство имен kube-public — это еще одно авто­ма­ти­че­ски созда­ва­е­мое про­стран­ство имен, кото­рое мож­но исполь­зо­вать для хра­не­ния объ­ек­тов, кото­рые вы хоти­те сде­лать доступ­ны­ми и чита­е­мы­ми во всем кла­сте­ре, в том чис­ле для поль­зо­ва­те­лей, кото­рые не про­шли аутентификацию.

Для созда­ния про­стран­ства имен efk открой­те файл namespace.yml

[codesyntax lang="php"]

[/codesyntax]

Затем сохра­ни­те и закрой­те файл.

Здесь мы зада­дим вид объ­ек­та Kubernetes как объ­ект Namespace. Что­бы узнать боль­ше об объ­ек­тах Namespace, озна­комь­тесь с крат­ким обзо­ром про­странств имен в офи­ци­аль­ной доку­мен­та­ции по Kubernetes. Так­же мы зада­дим вер­сию Kubernetes API, исполь­зу­е­мую для созда­ния объ­ек­та (v1), и при­сво­им ему имя efk

Шаг 2 — Создание набора Elasticsearch StatefulSet

Мы созда­ли про­стран­ство имен для наше­го ком­плек­са веде­ния жур­на­лов, и теперь можем начать раз­вер­ты­ва­ние его ком­по­нен­тов. Вна­ча­ле мы раз­вер­нем кла­стер Elasticsearch из 3 узлов.

мы будем исполь­зо­вать 3 пода Elasticsearch, что­бы избе­жать про­бле­мы «раз­де­ле­ния моз­га», кото­рая встре­ча­ет­ся в слож­ных кла­сте­рах с мно­же­ством узлов и высо­ким уров­нем доступ­но­сти. Такое «раз­де­ле­ние моз­га» про­ис­хо­дит, когда несколь­ко узлов не могут свя­зы­вать­ся с дру­ги­ми узла­ми, и в свя­зи с этим выби­ра­ет­ся несколь­ко отдель­ных основ­ных узлов. В слу­чае с 3 узла­ми, если один узел вре­мен­но отклю­ча­ет­ся от кла­сте­ра, осталь­ные два узла могут выбрать новый основ­ной узел, и кла­стер будет про­дол­жать рабо­ту, пока послед­ний узел будет пытать­ся сно­ва при­со­еди­нить­ся к нему. Допол­ни­тель­ную инфор­ма­цию мож­но най­ти в доку­мен­тах «Новая эпо­ха коор­ди­на­ции кла­сте­ров в Elasticsearch» и «Кон­фи­гу­ра­ции голо­со­ва­ния».

Создание службы без главного узла

Для нача­ла мы созда­дим служ­бу Kubernetes без глав­но­го узла с име­нем elasticsearch, кото­рая будет опре­де­лять домен DNS для 3 подов. Служ­ба без глав­но­го узла не выпол­ня­ет балан­си­ров­ку нагруз­ки и не име­ет ста­ти­че­ско­го IP-адре­са. Допол­ни­тель­ную инфор­ма­цию о служ­бах без глав­но­го узла мож­но най­ти в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

Открой­те файл с име­нем elasticsearch_service.yaml

[codesyntax lang="php"]

[/codesyntax]

 

Затем сохра­ни­те и закрой­те файл.

Мы опре­де­ля­ем службу с име­нем elasticsearch в про­стран­стве имен efk и при­сва­и­ва­ем ей ярлык app: elasticsearch. Затем мы зада­ем для .spec.selector зна­че­ние app: elasticsearch, что­бы служ­ба выби­ра­ла поды с ярлы­ком app: elasticsearch. Когда мы при­вя­зы­ва­ем Elasticsearch StatefulSet к этой служ­бе, служ­ба воз­вра­ща­ет запи­си DNS A, кото­рые ука­зы­ва­ют на поды Elasticsearch с ярлыком app: elasticsearch.

Затем мы зада­ем пара­метр clusterIP: None, кото­рый дела­ет эту служ­бу служ­бой без глав­но­го узла. В заклю­че­ние мы опре­де­ля­ем пор­ты 9200 и 9300, кото­рые исполь­зу­ют­ся для вза­и­мо­дей­ствия с REST API и для свя­зи меж­ду узла­ми соответственно.

Мы настро­и­ли служ­бу без глав­но­го узла и ста­биль­ный домен  .elasticsearch.efk.svc.minikube для наших подов. Теперь мы можем создать набор StatefulSet.

Создание набора StatefulSet

Набор Kubernetes StatefulSet поз­во­ля­ет назна­чать подам ста­биль­ный иден­ти­фи­ка­тор и предо­став­лять им ста­биль­ное и посто­ян­ное хра­ни­ли­ще. Elasticsearch тре­бу­ет­ся ста­биль­ное хра­ни­ли­ще, что­бы его дан­ные сохра­ня­лись при пере­за­пус­ке и изме­не­нии пла­ни­ров­ки подов. Допол­ни­тель­ную инфор­ма­цию о рабо­чей зада­че StatefulSet мож­но най­ти на стра­ни­це Statefulsets в доку­мен­та­ции по Kubernetes.

смот­рим имя наше­го провиженера(provisioner)

Открой­те файл с име­нем elasticsearch_statefulset.yaml

[codesyntax lang="php"]

[/codesyntax]

 

рас­смот­рим каж­дый блок в отдельности:

[codesyntax lang="php"]

[/codesyntax]

 

.

В этом бло­ке мы опре­де­ля­ем объ­ект StatefulSet под назва­ни­ем es-cluster в про­стран­стве имен efk. Затем мы свя­зы­ва­ем его с ранее создан­ной служ­бой elasticsearch, исполь­зуя поле serviceName. За счет это­го каж­дый под набо­ра StatefulSet будет досту­пен по сле­ду­ю­ще­му адре­су DNSes-cluster-[0,1,2].elasticsearch.efk.svc.minikube, где [0,1,2] соот­вет­ству­ет назна­чен­но­му номе­ру пода в виде обыч­но­го цело­го числа.

Мы зада­ли 3 копии (пода) и уста­но­ви­ли для селек­то­ра matchLabels зна­че­ние app: elasticseach, кото­рое мы так­же отра­зим в раз­де­ле .spec.template.metadata. Поля .spec.selector.matchLabels и .spec.template.metadata.labels долж­ны совпадать.

Теперь мы можем перей­ти к спе­ци­фи­ка­ции объекта.

[codesyntax lang="php"]

[/codesyntax]

 

Здесь мы опре­де­ля­ем поды в набо­ре StatefulSet. Мы при­сво­им кон­тей­не­рам имя elasticsearch и выбе­рем образ Docker docker.elastic.co/elasticsearch/elasticsearch:7.2.0. Сей­час вы може­те изме­нить мет­ку обра­за, что­бы она соот­вет­ство­ва­ла ваше­му соб­ствен­но­му обра­зу Elasticsearch или дру­гой вер­сии образа.

Мы исполь­зу­ем поле resources, что­бы ука­зать, что кон­тей­не­ру тре­бу­ет­ся все­го гаран­ти­ро­вать все­го деся­тую часть ресур­сов vCPU с воз­мож­но­стью уве­ли­че­ния загруз­ки до 1 vCPU (что огра­ни­чи­ва­ет исполь­зо­ва­ние ресур­сов подом при пер­во­на­чаль­ной обра­бот­ке боль­шо­го объ­е­ма дан­ных или при пико­вой нагруз­ке). Вам сле­ду­ет изме­нить эти зна­че­ния в зави­си­мо­сти от ожи­да­е­мой нагруз­ки и доступ­ных ресур­сов. Допол­ни­тель­ную инфор­ма­цию о запро­сах ресур­сов и огра­ни­че­ни­ях мож­но най­ти в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

Мы откро­ем и назо­вем пор­ты 9200 и 9300 для REST API и свя­зи меж­ду узла­ми соот­вет­ствен­но. Мы зада­дим volumeMount с име­нем data, кото­рый будет мон­ти­ро­вать посто­ян­ный том с име­нем data в кон­тей­нер по пути /usr/share/elasticsearch/data. Мы опре­де­лим VolumeClaims для набо­ра StatefulSet в дру­гом бло­ке YAML позднее.

В заклю­че­ние мы зада­дим в кон­тей­не­ре несколь­ко пере­мен­ных среды:

  • cluster.name: имя кла­сте­ра Elasticsearch, efk
  • node.name: имя узла, кото­рое мы уста­нав­ли­ва­ем как зна­че­ние поля .metadata.name с помо­щью valueFrom. Оно раз­ре­ша­ет­ся как es-cluster-[0,1,2] в зави­си­мо­сти от назна­чен­но­го узлу поряд­ко­во­го номера.
  • discovery.seed_hosts: это поле исполь­зу­ет спи­сок потен­ци­аль­ных глав­ных узлов в кла­сте­ре, ини­ци­и­ру­ю­щем про­цесс обна­ру­же­ния узлов. Посколь­ку в этом обу­ча­ю­щем моду­ле мы уже настро­и­ли служ­бу без глав­но­го узла, наши поды име­ют доме­ны в фор­ме es-cluster-[0,1,2].elasticsearch.efk.svc.minikube, так что мы зада­дим соот­вет­ству­ю­щее зна­че­ние для этой пере­мен­ной. Исполь­зуя раз­ре­ше­ние DNS в локаль­ном про­стран­стве имен Kubernetes мы можем сокра­тить это до es-cluster-[0,1,2].elasticsearch. Допол­ни­тель­ную инфор­ма­цию об обна­ру­же­нии Elasticsearch мож­но най­ти в офи­ци­аль­ной доку­мен­та­ции по Elasticsearch.
  • cluster.initial_master_nodes: в этом поле так­же зада­ет­ся спи­сок потен­ци­аль­ных глав­ных узлов, кото­рые будут участ­во­вать в про­цес­се выбо­ра глав­но­го узла. Обра­ти­те вни­ма­ние, что для это­го поля узлы нуж­но ука­зы­вать по име­ни node.name, а не по име­нам хостов.
  • ES_JAVA_OPTS: здесь мы зада­ем зна­че­ние -Xms512m -Xmx512m, кото­рое пред­пи­сы­ва­ет JVM исполь­зо­вать мини­маль­ный и мак­си­маль­ный раз­мер выде­ле­ния памя­ти 512 МБ. Вам сле­ду­ет настро­ить эти пара­мет­ры в зави­си­мо­сти от доступ­но­сти ресур­сов и потреб­но­стей ваше­го кла­сте­ра. Допол­ни­тель­ную инфор­ма­цию мож­но най­ти в раз­де­ле «Настрой­ка раз­ме­ра выде­ля­е­мой памя­ти».

Сле­ду­ю­щий блок, кото­рый мы будем встав­лять, выгля­дит сле­ду­ю­щим образом:

[codesyntax lang="php"]

[/codesyntax]

 

В этом бло­ке мы опре­де­ля­ем несколь­ко кон­тей­не­ров ини­ци­а­ли­за­ции, кото­рые запус­ка­ют­ся до глав­но­го кон­тей­не­ра при­ло­же­ния elasticsearch. Каж­дый из этих кон­тей­не­ров ини­ци­а­ли­за­ции выпол­ня­ет­ся до кон­ца в задан­ном поряд­ке. Допол­ни­тель­ную инфор­ма­цию о кон­тей­не­рах ини­ци­а­ли­за­ции мож­но най­ти в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

Пер­вый такой кон­тей­нер с име­нем fix-permissions запус­ка­ет коман­ду chown для сме­ны вла­дель­ца и груп­пы ката­ло­га дан­ных Elasticsearch на 1000:1000, UID поль­з­до­ва­те­ля Elasticsearch. По умол­ча­нию Kubernetes мон­ти­ру­ет ката­лог дан­ных как root, что дела­ет его недо­ступ­ным для Elasticsearch. Допол­ни­тель­ную инфор­ма­цию об этом шаге мож­но най­ти в доку­мен­та­ции по Elasticsearch «Заме­ча­ния по исполь­зо­ва­нию в про­из­вод­стве и зна­че­ния по умол­ча­нию».

Вто­рой кон­тей­нер с име­нем increase-vm-max-map запус­ка­ет коман­ду для уве­ли­че­ния пре­дель­но­го коли­че­ства mmap в опе­ра­ци­он­ной систе­ме, кото­рое по умол­ча­нию может быть слиш­ком низ­ким, в резуль­та­те чего могут воз­ни­кать ошиб­ки памя­ти. Допол­ни­тель­ную инфор­ма­цию об этом шаге мож­но най­ти в офи­ци­аль­ной доку­мен­та­ции по Elasticsearch.

Сле­ду­ю­щим запус­ка­ет­ся кон­тей­нер ини­ци­а­ли­за­ции increase-fd-ulimit, кото­рый запус­ка­ет коман­ду ulimit для уве­ли­че­ния мак­си­маль­но­го коли­че­ства дескрип­то­ров откры­тых фай­лов. Допол­ни­тель­ную инфор­ма­цию об этом шаге мож­но най­ти в доку­мен­та­ции по Elasticsearch «Заме­ча­ния по исполь­зо­ва­нию в про­из­вод­стве и зна­че­ния по умол­ча­нию».

При­ме­ча­ние. В доку­мен­те «Заме­ча­ния по исполь­зо­ва­нию в про­из­вод­стве и зна­че­ния по умол­ча­нию» для Elasticsearch так­же ука­зы­ва­ет­ся воз­мож­ность отклю­че­ния под­кач­ки для повы­ше­ния про­из­во­ди­тель­но­сти. В зави­си­мо­сти от вида уста­нов­ки Kubernetes и про­вай­де­ра, под­кач­ка может быть уже отклю­че­на. Что­бы про­ве­рить это, выпол­ни­те коман­ду exec в рабо­та­ю­щем кон­тей­не­ре и запу­сти­те cat /proc/swaps для выво­да актив­ных устройств под­кач­ки. Если этот спи­сок пустой, под­кач­ка отключена.

Мы опре­де­ли­ли глав­ный кон­тей­нер при­ло­же­ний и кон­тей­не­ры ини­ци­а­ли­за­ции, кото­рые будут запус­кать­ся перед ним для настрой­ки ОС кон­тей­не­ра. Теперь мы можем доста­вить в наш файл опре­де­ле­ния объ­ек­та StatefulSet заклю­чи­тель­ную часть: блок volumeClaimTemplates.

[codesyntax lang="php"]

[/codesyntax]

 

В этом бло­ке мы опре­де­ля­ем для StatefulSet шаб­ло­ны volumeClaimTemplates. Kubernetes исполь­зу­ет эти настрой­ки для созда­ния посто­ян­ных томов для подов. В при­ве­ден­ном выше бло­ке мы исполь­зо­ва­ли имя data-nfs-shara (это имя, на кото­рое мы уже ссы­ла­лись в опре­де­ле­нии volumeMounts), и при­сво­и­ли ему тот же ярлык app: elasticsearch, что и для набо­ра StatefulSet.

Затем мы зада­ем для него режим досту­па ReadWriteOnce, и это озна­ча­ет, что его может мон­ти­ро­вать для чте­ния и запи­си толь­ко один узел. В этом обу­ча­ю­щем моду­ле мы опре­де­ля­ем класс хра­не­ния managed-nfs-storage. Вам сле­ду­ет изме­нить это зна­че­ние в зави­си­мо­сти от того, где вы запус­ка­е­те свой кла­стер Kubernetes. Допол­ни­тель­ную инфор­ма­цию мож­но най­ти в доку­мен­та­ции по посто­ян­ным томам.

В заклю­че­ние мы ука­жем, что каж­дый посто­ян­ный том дол­жен иметь раз­мер 100 ГиБ. Вам сле­ду­ет изме­нить это зна­че­ние в зави­си­мо­сти от про­из­вод­ствен­ных потребностей.

После раз­вер­ты­ва­ния всех подов вы може­те исполь­зо­вать запрос REST API, что­бы убе­дить­ся, что кла­стер Elasticsearch функ­ци­о­ни­ру­ет нормально.

Для это­го вна­ча­ле нуж­но пере­на­пра­вить локаль­ный порт 9200 на порт 9200 одно­го из узлов Elasticsearch (es-cluster-0) с помо­щью коман­ды kubectl port-forward:

kubectl port-forward es-cluster-0 9200:9200 --namespace=efk

В отдель­ном окне тер­ми­на­ла отправь­те запрос curl к REST API:

curl http://localhost:9200/_cluster/state?pretty
Резуль­тат дол­жен выгля­деть сле­ду­ю­щим образом:

[codesyntax lang="php"]

[/codesyntax]

 

Это пока­зы­ва­ет, что жур­на­лы minikube наше­го кла­сте­ра Elasticsearch успеш­но созда­ны с 3 узла­ми: es-cluster-0es-cluster-1 и es-cluster-2. В каче­стве глав­но­го узла высту­па­ет узел es-cluster-0.

Теперь ваш кла­стер Elasticsearch запу­щен, и вы може­те перей­ти к настрой­ке на нем кли­ент­ско­го интер­фей­са Kibana.

Шаг 3 — Создание развертывания и службы Kibana

Что­бы запу­стить Kibana в Kubernetes, мы созда­дим служ­бу с име­нем kibana, а так­же раз­вер­ты­ва­ние, состо­я­щее из одной копии пода. Вы може­те мас­шта­би­ро­вать коли­че­ство копий в зави­си­мо­сти от ваших про­из­вод­ствен­ных потреб­но­стей и ука­зы­вать тип LoadBalancer, что­бы служ­ба запра­ши­ва­ла балан­си­ров­ку нагруз­ки на подах развертывания.

В этом слу­чае мы созда­дим служ­бу и раз­вер­ты­ва­ние в одном и том же фай­ле. Открой­те файл с име­нем kibana.yaml

[codesyntax lang="php"]

[/codesyntax]

 

Затем сохра­ни­те и закрой­те файл.

В этой спе­ци­фи­ка­ции мы опре­де­ли­ли служ­бу с име­нем kibana в про­стран­стве имен efk и при­сво­ить ему ярлык app: kibana.

Так­же мы ука­за­ли, что она долж­на быть доступ­на на пор­ту 5601, и исполь­зо­ва­ли ярлык app: kibana для выбо­ра целе­вых подов службы.

В спе­ци­фи­ка­ции Deployment мы опре­де­лим раз­вер­ты­ва­ние с име­нем kibana и ука­жем, что нам тре­бу­ет­ся 1 копия пода.

Мы будем исполь­зо­вать образ docker.elastic.co/kibana/kibana:7.2.0. Сей­час вы може­те заме­нить этот образ на соб­ствен­ный част­ный или пуб­лич­ный образ Kibana, кото­рый вы хоти­те использовать.

Мы ука­жем, что нам тре­бу­ет­ся гаран­ти­ро­вать для пода не менее 0.1 vCPU и не более 1 vCPU при пико­вой нагруз­ке. Вам сле­ду­ет изме­нить эти зна­че­ния в зави­си­мо­сти от ожи­да­е­мой нагруз­ки и доступ­ных ресурсов.

Теперь мы исполь­зу­ем пере­мен­ную сре­ды ELASTICSEARCH_URL для уста­нов­ки конеч­ной точ­ки и пор­та для кла­сте­ра Elasticsearch. При исполь­зо­ва­нии Kubernetes DNS эта конеч­ная точ­ка соот­вет­ству­ет назва­нию служ­бы elasticsearch. Этот домен раз­ре­шит­ся в спи­сок IP-адре­сов для 3 подов Elasticsearch. Допол­ни­тель­ную инфор­ма­цию о Kubernetes DNS мож­но полу­чить в доку­мен­те DNS для служб и подов.

Нако­нец мы настро­им для кон­тей­не­ра Kibana порт 5601, куда служ­ба kibana будет пере­на­прав­лять запросы.

 

теперь посмот­рим ingres для кибана:

kibana_ingress.yaml

[codesyntax lang="php"]

[/codesyntax]

 

Шаг 4 — Создание набора демонов Fluentd

мы настро­им Fluentd как набор демо­нов. Это тип рабо­чей зада­чи Kubernetes, запус­ка­ю­щий копию ука­зан­но­го пода на каж­дом узле в кла­сте­ре Kubernetes. Исполь­зуя кон­трол­лер набо­ра демо­нов, мы раз­вер­нем под аген­та реги­стра­ции дан­ных Fluentd на каж­дом узле наше­го кла­сте­ра. Допол­ни­тель­ную инфор­ма­цию об архи­тек­ту­ре реги­стра­ции дан­ных мож­но най­ти в доку­мен­те «Исполь­зо­ва­ние аген­та реги­стра­ции дан­ных узлов» в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

В Kubernetes при­ло­же­ния в кон­тей­не­рах запи­сы­ва­ют дан­ные в stdout и stderr, и их пото­ки реги­стри­ру­е­мых дан­ных запи­сы­ва­ют­ся и пере­на­прав­ля­ют­ся в фай­лы JSON на узлах. Под Fluentd отсле­жи­ва­ет эти фай­лы жур­на­лов, филь­тру­ет собы­тия жур­на­лов, пре­об­ра­зу­ет дан­ные жур­на­лов и отправ­ля­ет их на сер­ве­нюу часть реги­стра­ции дан­ных Elasticsearch, кото­рую мы раз­вер­ну­ли на шаге 2.

Поми­мо жур­на­лов кон­тей­не­ров, агент Fluentd так­же отсле­жи­ва­ет жур­на­лы систем­ных ком­по­нен­тов Kubernetes, в том чис­ле жур­на­лы kubelet, kube-proxy и Docker. Пол­ный спи­сок источ­ни­ков, отсле­жи­ва­е­мых аген­том реги­стра­ции дан­ных Fluentd, мож­но най­ти в фай­ле kubernetes.conf, исполь­зу­е­мом для настрой­ки аген­та реги­стра­ции дан­ных. Допол­ни­тель­ную инфор­ма­цию по реги­стра­ции дан­ных в кла­сте­рах Kubernetes мож­но най­ти в доку­мен­те «Реги­стра­ция дан­ных на уровне узлов» в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

Для нача­ла открой­те файл fluentd-daemonset.yaml

[codesyntax lang="php"]

[/codesyntax]

 

опи­шем каж­дый блок:

[codesyntax lang="php"]

[/codesyntax]

Здесь мы созда­ем слу­жеб­ную учет­ную запись fluentd, кото­рую поды Fluentd будут исполь­зо­вать для досту­па к Kubernetes API. Мы созда­ем ее в про­стран­стве имен efk и сно­ва при­сва­и­ва­ем ей ярлык app: fluentd. Допол­ни­тель­ную инфор­ма­цию о слу­жеб­ных учет­ных запи­сях в Kubernetes мож­но най­ти в доку­мен­те «Настрой­ка слу­жеб­ных учет­ных запи­сей для подов» в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

[codesyntax lang="php"]

[/codesyntax]

Здесь мы опре­де­ля­ем блок ClusterRole с име­нем fluentd, кото­ро­му мы предо­став­ля­ем раз­ре­ше­ния getlist и watch для объ­ек­тов pods и namespaces. ClusterRoles поз­во­ля­ет предо­став­лять доступ к ресур­сам в кла­сте­ре Kubernetes, в том чис­ле к узлам. Допол­ни­тель­ную инфор­ма­цию о кон­тро­ле досту­па на осно­ве ролей и ролях кла­сте­ров мож­но най­ти в доку­мен­те «Исполь­зо­ва­ние авто­ри­за­ции RBAC» в офи­ци­аль­ной доку­мен­та­ции Kubernetes.

[codesyntax lang="php"]

[/codesyntax]

В этом бло­ке мы опре­де­ля­ем объ­ект ClusterRoleBinding с име­нем fluentd, которй при­вя­зы­ва­ет роль кла­сте­ра fluentd к слу­жеб­ной учет­ной запи­си fluentd. Это дает слу­жеб­ной учет­ной запи­си fluentd раз­ре­ше­ния, задан­ные для роли кла­сте­ра fluentd.

[codesyntax lang="php"]

[/codesyntax]

Здесь мы опре­де­ля­ем набор демо­нов с име­нем fluentd в про­стран­стве имен efk и назна­ча­ем ему ярлык app: fluentd.

[codesyntax lang="php"]

[/codesyntax]

Здесь мы сопо­став­ля­ем ярлык app: fluentd, опре­де­лен­ный в .metadata.labels и назна­ча­ем для набо­ра демо­нов слу­жеб­ную учет­ную запись fluentd. Так­же мы выби­ра­ем app: fluentd как поды, управ­ля­е­мые этим набо­ром демонов.

Затем мы опре­де­ля­ем допуск NoSchedule для соот­вет­ствия экви­ва­лент­но­му вызо­ву в глав­ных узлах Kubernetes. Это гаран­ти­ру­ет, что набор демо­нов так­же будет раз­вер­нут на глав­ных узлах Kubernetes. Если вы не хоти­те запус­кать под Fluentd на глав­ных узлах, уда­ли­те этот допуск. Допол­ни­тель­ную инфор­ма­цию о вызо­вах и допус­ках Kubernetes мож­но най­ти в раз­де­ле «Вызо­вы и допус­ки» в офи­ци­аль­ной доку­мен­та­ции по Kubernetes.

Теперь мы нач­нем опре­де­лять кон­тей­нер пода с име­нем fluentd.

Мы исполь­зу­ем офи­ци­аль­ный образ v1.4.2 Debian от коман­ды, обслу­жи­ва­ю­щей Fluentd. Если вы хоти­те исполь­зо­вать свой част­ный или пуб­лич­ный образ Fluentd или исполь­зо­вать дру­гую вер­сию обра­за, изме­ни­те тег image в спе­ци­фи­ка­ции кон­тей­не­ра. Файл Dockerfile и содер­жа­ние это­го обра­за доступ­ны в репо­зи­то­рии fluentd-kubernetes-daemonset на Github.

Теперь мы настро­им Fluentd с помо­щью несколь­ких пере­мен­ных среды:

  • FLUENT_ELASTICSEARCH_HOST: мы настро­им служ­бу Elasticsearch без глав­ных узлов, кото­рую мы опре­де­ли­ли ранее: elasticsearch.efk.svc.minikube. Это раз­ре­ша­ет­ся спи­сок IP-адре­сов для 3 подов Elasticsearch. Ско­рее все­го, реаль­ный хост Elasticsearch будет пер­вым IP-адре­сом, кото­рый будет выве­ден в этом спис­ке. Для рас­пре­де­ле­ния жур­на­лов в этом кла­сте­ре вам потре­бу­ет­ся изме­нить кон­фи­гу­ра­цию пла­ги­на выво­да Fluentd Elasticsearch. Допол­ни­тель­ную инфор­ма­цию об этом пла­гине мож­но най­ти в доку­мен­те «Пла­гин выво­да Elasticsearch».
  • FLUENT_ELASTICSEARCH_PORT: в этом пара­мет­ре мы зада­ем ранее настро­ен­ный порт Elasticsearch 9200.
  • FLUENT_ELASTICSEARCH_SCHEME: мы зада­ем для это­го пара­мет­ра зна­че­ние http.
  • FLUENTD_SYSTEMD_CONF: мы зада­ем для это­го пара­мет­ра зна­че­ние disable, что­бы пода­вить вывод systemd, кото­рый не настро­ен в контейнере.

[codesyntax lang="php"]

[/codesyntax]

Здесь мы ука­зы­ва­ем пре­дель­ный объ­ем памя­ти 512 МиБ в поде FluentD и гаран­ти­ру­ем выде­ле­ние 0,1 vCPU и 200 МиБ памя­ти. Вы може­те настро­ить эти огра­ни­че­ния ресур­сов и запро­сы в зави­си­мо­сти от ожи­да­е­мо­го объ­е­ма жур­на­ла и доступ­ных ресурсов.

Затем мы смон­ти­ру­ем пути хостов /var/log и /var/lib/docker/containers в кон­тей­нер, исполь­зуя varlog и varlibdockercontainers volumeMounts. Эти тома опре­де­ля­ют­ся в кон­це блока.

Послед­ний пара­метр, кото­рый мы опре­де­ля­ем в этом бло­ке, — это пара­метр terminationGracePeriodSeconds, даю­щий Fluentd 30 секунд для без­опас­но­го выклю­че­ния при полу­че­нии сиг­на­ла SIGTERM. После 30 секунд кон­тей­не­ры полу­ча­ют сиг­нал SIGKILL. Зна­че­ние по умол­ча­нию для terminationGracePeriodSeconds состав­ля­ет 30 с, так что в боль­шин­стве слу­ча­ев этот пара­метр мож­но про­пу­стить. Допол­ни­тель­ную инфор­ма­цию о без­опас­ном пре­кра­ще­нии рабо­чих задач Kubernetes мож­но най­ти в доку­мен­те Google «Луч­шие прак­ти­ки Kubernetes: осто­рож­ное пре­кра­ще­ние рабо­ты».

теперь мож­но запускать:

[root@minikub efk]# kubectl apply -f namespace.yml -f elasticsearch_service.yaml -f elasticsearch_statefulset.yaml -f fluentd-daemonset.yaml -f kibana_ingress.yaml -f kibana.yaml
namespace/efk created
service/elasticsearch created
statefulset.apps/es-cluster created
serviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd created
clusterrolebinding.rbac.authorization.k8s.io/fluentd created
daemonset.apps/fluentd created
ingress.extensions/kibana created
service/kibana created
deployment.apps/kibana created

 

====================================================================================================

 

Мой рабочий вариант.

тут будет для каж­до­го нейм­с­пей­са свой индекс. Шара висит на NFS

cat namespace.yml

[codesyntax lang="php"]

[/codesyntax]

cat elasticsearch_service.yaml

[codesyntax lang="php"]

[/codesyntax]

cat elasticsearch_statefulset.yaml

[codesyntax lang="php"]

[/codesyntax]

cat fluentd-daemonset.yaml

[codesyntax lang="php"]

[/codesyntax]

в этом кон­фи­ге мы сра­зу соби­ра­ем логи наше­го при­ло­же­ния иду­щие в stdout

в кон­фи­ге флю­ен­та в источ­ни­ке ука­зы­ва­ем путь до дирек­то­рии с лога­ми, и теги­ру­ем лог:
<source>
@type tail
path /var/log/containers/*terminal-soft*.log
tag terminal-soft

после ука­зы­ва­ем какое мы ищем совпадение:
<match terminal-soft**>

а так же как будут назы­вать­ся индек­сы в elasticsearch:

logstash_prefix test-index-terminal

cat fluentd-configmap_fluent_conf.yaml

[codesyntax lang="php"]

[/codesyntax]

в этом кон­фи­ге зада­ём шаб­лон для созда­ния индек­сов, что­бы рабо­тал ролловер.

cat fluentd-configmap_template_json.yaml
[codesyntax lang="php"]

[/codesyntax]

 

 

cat kibana.yaml

[codesyntax lang="php"]

[/codesyntax]

cat kibana_ingress.yaml

[codesyntax lang="php"]

[/codesyntax]

запус­ка­ем:
kubectl apply -f namespace.yml
kubectl apply -f .

далее захо­дим по ссылке:
http://efk.prod.test.local

пере­хо­дим в созда­ние патер­на для индексов:

пере­хо­дим в нуж­ный нам патерн

уви­деть все индек­сы и их ста­тус мож­но тут:

 

настро­ить их жиз­нен­ный цикл мож­но сле­ду­ю­щим образом:

созда­ём шаблон:

шаб­лон создан, цеп­ля­ем на него политику

как видим всё нор­маль­но подцепилось:

индек­сы созда­ют­ся сле­ду­ю­щим обра­зом, и рол­ло­вер нор­маль­но их не удаляет:

заве­сти не уда­лось, поэто­му хер зна­ет что ему не нра­вит­ся, поэто­му 2 вари­ан­та либо при­кру­чи­вать curator и нах ILM или ста­вим вме­сто efk - elk