ElasticSearch: Pecahan yang Tidak Ditugaskan, bagaimana cara memperbaikinya?

165

Saya memiliki cluster ES dengan 4 node:

number_of_replicas: 1
search01 - master: false, data: false
search02 - master: true, data: true
search03 - master: false, data: true
search04 - master: false, data: true

Saya harus me-restart search03, dan ketika kembali, itu bergabung kembali dengan cluster tidak ada masalah, tetapi meninggalkan 7 pecahan yang tidak ditugaskan meletakkan tentang.

{
  "cluster_name" : "tweedle",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 4,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 15,
  "active_shards" : 23,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 7
}

Sekarang kluster saya dalam kondisi kuning. Apa cara terbaik untuk mengatasi masalah ini?

  • Hapus (batalkan) pecahan?
  • Pindahkan pecahan ke simpul lain?
  • Mengalokasikan pecahan ke node?
  • Perbarui 'number_of_replicas' ke 2?
  • Sesuatu yang lain sama sekali?

Menariknya, ketika indeks baru ditambahkan, simpul itu mulai bekerja di sana dan bermain bagus dengan seluruh cluster, itu hanya meninggalkan pecahan yang belum ditetapkan meletakkan.

Ikuti pertanyaan: apakah saya melakukan sesuatu yang salah yang menyebabkan hal ini terjadi? Saya tidak memiliki banyak kepercayaan pada gugus yang berperilaku seperti ini ketika sebuah simpul dimulai kembali.

CATATAN: Jika Anda menjalankan satu cluster node untuk beberapa alasan, Anda mungkin perlu melakukan hal berikut:

curl -XPUT 'localhost:9200/_settings' -d '
{
    "index" : {
        "number_of_replicas" : 0
    }
}'
Spanky
sumber

Jawaban:

117

Secara default, Elasticsearch akan menetapkan ulang pecahan ke node secara dinamis. Namun, jika Anda telah menonaktifkan alokasi shard (mungkin Anda melakukan restart bergulir dan lupa untuk mengaktifkannya kembali), Anda dapat mengaktifkan kembali alokasi shard.

# v0.90.x and earlier
curl -XPUT 'localhost:9200/_settings' -d '{
    "index.routing.allocation.disable_allocation": false
}'

# v1.0+
curl -XPUT 'localhost:9200/_cluster/settings' -d '{
    "transient" : {
        "cluster.routing.allocation.enable" : "all"
    }
}'

Elasticsearch kemudian akan menugaskan kembali pecahan seperti biasa. Ini bisa lambat, pertimbangkan menaikkan indices.recovery.max_bytes_per_secdan cluster.routing.allocation.node_concurrent_recoveriesmempercepatnya.

Jika Anda masih melihat masalah, ada hal lain yang mungkin salah, jadi lihat di log Elasticsearch untuk mencari kesalahan. Jika Anda melihat EsRejectedExecutionExceptionkolam utas Anda mungkin terlalu kecil .

Akhirnya, Anda dapat secara eksplisit menetapkan ulang pecahan ke sebuah simpul dengan reroute API .

# Suppose shard 4 of index "my-index" is unassigned, so you want to
# assign it to node search03:
curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
    "commands": [{
        "allocate": {
            "index": "my-index",
            "shard": 4,
            "node": "search03",
            "allow_primary": 1
        }
    }]
}'
Wilfred Hughes
sumber
3
Ketika saya melakukan itu saya mendapat: { "error" : "ElasticsearchIllegalArgumentException[[allocate] failed to find [logstash-2015.01.05][1] on the list of unassigned shards]", "status" : 400 } Meskipun saya dapat melihat bahwa beling adalah salah satu yang tidak terisi di ES-Head
wjimenez5271
Kebetulan, pecahan lain melakukan pekerjaan yang terdaftar sebagai tidak terisi, dan kemudian yang tersisa memperbaiki diri.
wjimenez5271
ini saran yang bagus.
Yehosef
1
Sejak rilis 5.0, perintah "alokasikan" telah berubah untuk memberikan lebih banyak opsi - contoh di atas sekarang akan menjadi "alokasikan_empty_primary", menghilangkan parameter "allow_primary".
jmb
4
Anda perlu menambahkan -H 'Content-Type: application/json'jika Anda mendapatkan kesalahanContent-Type header [application/x-www-form-urlencoded] is not supported
luckydonald
56

OK, saya sudah menyelesaikan ini dengan bantuan dari dukungan ES. Keluarkan perintah berikut untuk API pada semua node (atau node yang Anda yakini sebagai penyebab masalah):

curl -XPUT 'localhost:9200/<index>/_settings' \
    -d '{"index.routing.allocation.disable_allocation": false}'

di mana <index>indeks yang Anda yakini sebagai pelakunya? Jika Anda tidak tahu, jalankan ini di semua node:

curl -XPUT 'localhost:9200/_settings' \
    -d '{"index.routing.allocation.disable_allocation": false}'

Saya juga menambahkan baris ini ke konfigurasi yaml saya dan sejak itu, setiap restart dari server / layanan telah bebas masalah. Pecahan dialokasikan kembali segera.

FWIW, untuk menjawab pertanyaan yang sering dicari, setel MAX_HEAP_SIZE ke 30G kecuali mesin Anda memiliki kurang dari 60G RAM, dalam hal ini setel ke setengah dari memori yang tersedia.

Referensi

Spanky
sumber
2
untuk menyelesaikan ini di versi 1.1.1, haruskah saya menggunakan cluster.routing.allocation.enable = tidak ada?
user3175226
1
Penonaktifan alokasi tidak lagi didokumentasikan di sana, setidaknya pada 20 November.
3
Perhatikan bahwa alokasi rute adalah pengaturan cluster-lebar, jadi tidak masalah simpul mana Anda mengirim perintah.
Wilfred Hughes
Saya menambahkan keduanya di file es yml saya. index.routing.allocation.disable_allocation : false cluster.routing.allocation.enable: noneTapi masih ada pecahan yang belum ditetapkan menunjukkan .. Apa yang bisa menjadi alasannya?
bagui
1
Dalam versi 6.8 saya mendapatkan kesalahan:{ "type": "illegal_argument_exception", "reason": "unknown setting [index.routing.allocation.disable_allocation] please check that any required plugins are installed, or check the breaking changes documentation for removed settings" } ],
Janac Meena
39

Skrip bash kecil ini akan mengubah tugas dengan paksa, Anda mungkin kehilangan data.

NODE="YOUR NODE NAME"
IFS=$'\n'
for line in $(curl -s 'localhost:9200/_cat/shards' | fgrep UNASSIGNED); do
  INDEX=$(echo $line | (awk '{print $1}'))
  SHARD=$(echo $line | (awk '{print $2}'))

  curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
     "commands": [
        {
            "allocate": {
                "index": "'$INDEX'",
                "shard": '$SHARD',
                "node": "'$NODE'",
                "allow_primary": true
          }
        }
    ]
  }'
done
W. Andrew Loe III
sumber
Bekerja seperti pesona. Terima kasih!
Paulo Pires
Saya mendapatkan kesalahan ini: <br> {"error": "JsonParseException [Karakter tak terduga r (',' (kode 44)): mengharapkan nilai yang valid (angka, String, array, objek, 'true', 'false' atau 'null') \ n di [Sumber: [B @ 3b1fadfb; baris: 6, kolom: 27]] "," status ": 500} <br> apa yang harus saya lakukan untuk memperbaikinya
biolinh
Terima kasih banyak! Ini menghemat waktu berharga !!
Sathish
Script melempar kesalahan:{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}
Janac Meena
17

Satu-satunya hal yang berhasil bagi saya adalah mengubah number_of_replicas (saya punya 2 replika, jadi saya mengubahnya menjadi 1 dan kemudian kembali ke 2).

Pertama:

PUT /myindex/_settings
{
    "index" : {
        "number_of_replicas" : 1
     }
}

Kemudian:

PUT /myindex/_settings
{
    "index" : {
        "number_of_replicas" : 2
     }
}

(Saya sudah menjawabnya dalam pertanyaan ini )

Edi
sumber
9

Elasticsearch secara otomatis mengalokasikan pecahan jika konfigurasi di bawah ini diatur ke semua. Konfigurasi ini dapat diatur menggunakan api sisanya juga cluster.routing.allocation.enable: all

Jika bahkan setelah penerapan konfigurasi di bawah ini, es gagal menetapkan pecahan secara otomatis, maka Anda harus memaksa menetapkan pecahan sendiri. Tautan resmi ES untuk ini

Saya telah menulis sebuah skrip untuk memaksa menetapkan semua pecahan yang belum ditetapkan di seluruh cluster.

array di bawah ini berisi daftar node di mana Anda ingin menyeimbangkan pecahan yang belum ditetapkan

#!/bin/bash
array=( node1 node2 node3 )
node_counter=0
length=${#array[@]}
IFS=$'\n'
for line in $(curl -s 'http://127.0.0.1:9200/_cat/shards'|  fgrep UNASSIGNED); do
    INDEX=$(echo $line | (awk '{print $1}'))
    SHARD=$(echo $line | (awk '{print $2}'))
    NODE=${array[$node_counter]}
    echo $NODE
    curl -XPOST 'http://127.0.0.1:9200/_cluster/reroute' -d '{
        "commands": [
        {
            "allocate": {
                "index": "'$INDEX'",
                "shard": '$SHARD',
                "node": "'$NODE'",
                "allow_primary": true
            }
        }
        ]
    }'
    node_counter=$(((node_counter)%length +1))
done
Nischal Kumar
sumber
Skrip ini tidak berfungsi, yaitu, setelah saya menjalankannya, saya masih memiliki pecahan yang TIDAK DITANDATANGANI.
Chris F
@ ChrisF Dalam line1: Anda perlu mengganti node1, node2, node3 dengan nama simpul yang sebenarnya. Anda bisa mendapatkannya dengan localhost ikal: 9200 / _cat / node.
sidi
6

Saya terjebak hari ini dengan masalah alokasi pecahan yang sama. Skrip yang diusulkan W. Andrew Loe III dalam jawabannya tidak berhasil untuk saya, jadi saya memodifikasinya sedikit dan akhirnya berhasil:

#!/usr/bin/env bash

# The script performs force relocation of all unassigned shards, 
# of all indices to a specified node (NODE variable)

ES_HOST="<elasticsearch host>"
NODE="<node name>"

curl ${ES_HOST}:9200/_cat/shards > shards
grep "UNASSIGNED" shards > unassigned_shards

while read LINE; do
  IFS=" " read -r -a ARRAY <<< "$LINE"
  INDEX=${ARRAY[0]}
  SHARD=${ARRAY[1]}

  echo "Relocating:"
  echo "Index: ${INDEX}"
  echo "Shard: ${SHARD}"
  echo "To node: ${NODE}"

  curl -s -XPOST "${ES_HOST}:9200/_cluster/reroute" -d "{
    \"commands\": [
       {
         \"allocate\": {
           \"index\": \"${INDEX}\",
           \"shard\": ${SHARD},
           \"node\": \"${NODE}\",
           \"allow_primary\": true
         }
       }
     ]
  }"; echo
  echo "------------------------------"
done <unassigned_shards

rm shards
rm unassigned_shards

exit 0

Sekarang, saya bukan semacam guru Bash, tetapi skrip benar-benar bekerja untuk kasus saya. Perhatikan, Anda harus menentukan nilai yang sesuai untuk variabel "ES_HOST" dan "NODE".

Asing
sumber
sayangnya ES5x pecah kompatibilitas: elastic.co/guide/en/elasticsearch/reference/5.1/...
Fawix
2
Agar skrip di atas berfungsi dengan ES5x ganti allocatedengan allocate_empty_primarydan ganti \"allow_primary\": truedengan\"accept_data_loss\": true
Fawix
Mendapatkan {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}bahkan setelah menerapkan saran Fawix ini
Janac Meena
6

Dalam kasus saya, batas atas ruang hard disk tercapai.

Lihat artikel ini: https://www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html

Pada dasarnya, saya berlari:

PUT /_cluster/settings
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "90%",
    "cluster.routing.allocation.disk.watermark.high": "95%",
    "cluster.info.update.interval": "1m"
  }
}

Sehingga akan mengalokasikan jika <90% ruang hard disk digunakan, dan memindahkan shard ke mesin lain di cluster jika> 95% ruang hard disk digunakan; dan memeriksa setiap 1 menit.

banyak jalan
sumber
4

Mungkin itu membantu seseorang, tetapi saya memiliki masalah yang sama dan itu karena kurangnya ruang penyimpanan yang disebabkan oleh log yang terlalu besar.

Semoga ini bisa membantu seseorang! :)

Juanjo Lainez Reche
sumber
4

Dalam kasus saya, ketika saya membuat indeks baru maka number_of_replicas default ditetapkan sebagai 1. Dan jumlah node di kluster saya hanya satu sehingga tidak ada simpul tambahan untuk membuat replika, sehingga kesehatan berubah menjadi kuning. Jadi ketika saya membuat indeks dengan properti pengaturan dan mengatur number_of_replicas sebagai 0. Kemudian itu berfungsi dengan baik. Semoga ini membantu.

PUT /customer
{
    "settings": {
        "number_of_replicas": 0
    }
}
Apoorv Nag
sumber
3

Saya memiliki masalah yang sama tetapi akar penyebabnya adalah perbedaan dalam nomor versi (1.4.2 pada dua node (dengan masalah) dan 1.4.4 pada dua node (ok)). Jawaban pertama dan kedua (pengaturan "index.routing.allocation.disable_allocation" menjadi false dan pengaturan "cluster.routing.allocation.enable" to "all") tidak berfungsi.

Namun, jawaban oleh @Wilfred Hughes (pengaturan "cluster.routing.allocation.enable" menjadi "semua" menggunakan transient) memberi saya kesalahan dengan pernyataan berikut:

[TIDAK (versi simpul target [1.4.2] lebih tua dari versi simpul sumber [1.4.4])]

Setelah memperbarui node lama ke 1.4.4 node ini mulai melakukan resnc dengan node baik lainnya.

Jörg Rech
sumber
3

Saya juga mengalami masalah ini, dan saya menemukan cara mudah untuk menyelesaikannya.

  • Dapatkan indeks pecahan yang belum ditetapkan

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Instal Alat kurator, dan gunakan itu untuk menghapus indeks

    $ curator --host 172.16.4.140 delete indices --older-than 1 \
           --timestring '%Y.%m.%d' --time-unit days --prefix logstash
    

    CATATAN: Dalam kasus saya, indeks adalah logstash hari ini 2016-04-21

  • Kemudian periksa pecahan lagi, semua pecahan yang tidak ditugaskan pergi!
pengguna3391471
sumber
1
@sim, terima kasih sudah sunting untuk jawaban saya. Saya sangat miskin saat mengedit, akan lebih memperhatikannya.
user3391471
Bagi saya, itu adalah:curator_cli --host 127.0.0.1 delete_indices --filter_list '[{"filtertype":"pattern","kind":"prefix","value":"logstash-"}]'
Gaui
2

Saya juga menemui situasi ini dan akhirnya memperbaikinya.

Pertama, saya akan menggambarkan situasi saya. Saya memiliki dua node dalam gugus ElasticSearch, mereka dapat menemukan satu sama lain, tetapi ketika saya membuat indeks dengan pengaturan "number_of_replicas": 2 , "number_of_shards": 5, ES menunjukkan sinyal kuning dan unassigned_shards adalah 5.

Masalahnya terjadi karena nilai number_of_replicas , ketika saya mengatur nilainya 1 , semua baik-baik saja.

Armstrongya
sumber
4
Jumlah replika harus selalu N-1 jumlah node yang Anda miliki. Jadi dalam skenario Anda dengan 2 node, 1 dari node berisi shard primer, sementara ia node lain memiliki replika, maka jumlah replika Anda harus ditetapkan ke 1. N = 2, N - 1 = 1.
slm
1

Dalam kasus saya, node lama dengan share lama bergabung dengan cluster, jadi kami harus mematikan node lama dan menghapus indeks dengan pecahan yang belum ditetapkan.

terima kasih
sumber
1

Saya mencoba beberapa saran di atas dan sayangnya tidak ada yang berhasil. Kami memiliki indeks "Log" di lingkungan bawah kami tempat aplikasi menulis kesalahan mereka. Ini adalah cluster node tunggal. Apa yang dipecahkan untuk saya adalah memeriksa file konfigurasi YML untuk node dan melihat bahwa ia masih memiliki pengaturan default "gateway.expected_nodes: 2". Ini mengesampingkan pengaturan lain yang kami miliki. Setiap kali kita membuat indeks pada node ini, ia akan mencoba untuk menyebarkan 3 dari 5 pecahan ke phantom 2nd node. Ini karena itu akan muncul sebagai tidak ditetapkan dan mereka tidak pernah bisa dipindahkan ke node 1 dan hanya.

Solusinya adalah mengedit konfigurasi, mengubah pengaturan "gateway.expected_nodes" menjadi 1, sehingga akan berhenti mencari saudara lelakinya yang tidak pernah ditemukan di cluster, dan memulai kembali instance layanan elastis. Juga, saya harus menghapus indeks, dan membuat yang baru. Setelah membuat indeks, semua pecahan muncul pada simpul 1 dan satu-satunya, dan tidak ada yang tidak ditetapkan.

# Set how many nodes are expected in this cluster. Once these N nodes
# are up (and recover_after_nodes is met), begin recovery process immediately
# (without waiting for recover_after_time to expire):
#
# gateway.expected_nodes: 2
gateway.expected_nodes: 1
Daniel Knowlton
sumber
1

Bagi saya, ini diselesaikan dengan menjalankan ini dari konsol dev: "POST / _cluster / reroute? Retry_failed"

.....

Saya mulai dengan melihat daftar indeks untuk melihat indeks mana yang merah dan kemudian berlari

"dapatkan /_cat/shards?h=[INDEXNAME[,shard,prirep,state,unassigned.reason"

dan melihat bahwa pecahannya macet dalam keadaan ALLOCATION_FAILED, jadi menjalankan coba lagi di atas menyebabkan mereka mencoba ulang alokasi.

ScottFoster1000
sumber
Pada versi 5.6.3 perintah harus mendapatkan /_cat/shards/[INDEXNAME[?h=,shard,prirep,state,unassigned.reason
fasantos
0

Mungkin bisa membantu, tetapi saya mengalami masalah ini ketika mencoba menjalankan ES dalam mode tertanam. Perbaiki adalah untuk memastikan Node memiliki set lokal (benar).

JARC
sumber
0

Alasan lain yang mungkin untuk pecahan yang belum ditetapkan adalah bahwa kluster Anda menjalankan lebih dari satu versi biner Elasticsearch.

replikasi beling dari versi yang lebih baru ke versi sebelumnya tidak akan berfungsi

Ini bisa menjadi akar penyebab pecahan yang belum ditetapkan.

Dokumentasi Elastis - Proses Peningkatan Bergulir

Marc Tamsky
sumber
0

Saya mengalami masalah yang sama persis. Ini dapat dicegah dengan mengatur sementara alokasi shard menjadi false sebelum memulai kembali elasticsearch, tetapi ini tidak memperbaiki pecahan yang belum ditetapkan jika sudah ada.

Dalam kasus saya itu disebabkan oleh kurangnya ruang disk kosong pada node data. Pecahan yang belum ditetapkan di mana masih pada node data setelah restart tetapi mereka di mana tidak dikenali oleh master.

Hanya dengan membersihkan 1 node dari disk, proses replikasi dimulai untuk saya. Ini adalah proses yang agak lambat karena semua data harus disalin dari 1 node data ke yang lain.

Brian van Rooijen
sumber
0

Saya mencoba untuk menghapus pecahan yang belum ditetapkan atau secara manual menetapkannya ke simpul data tertentu. Itu tidak berhasil karena pecahan yang tidak ditugaskan terus muncul dan status kesehatan "merah" berulang-ulang. Kemudian saya perhatikan bahwa salah satu data node terjebak dalam keadaan "restart". Saya mengurangi jumlah data node, membunuhnya. Masalahnya tidak dapat direproduksi lagi.

thepolina
sumber
0

Saya memiliki dua indeks dengan pecahan yang belum ditentukan yang tampaknya tidak sembuh sendiri. Saya akhirnya menyelesaikan ini dengan menambahkan sementara data-node [1] . Setelah indeks menjadi sehat dan semuanya stabil menjadi hijau, saya menghapus simpul ekstra dan sistem mampu menyeimbangkan kembali (lagi) dan menetap pada kondisi yang sehat.

Ini adalah ide yang baik untuk menghindari membunuh banyak data node sekaligus (itulah cara saya masuk ke keadaan ini). Kemungkinan besar, saya gagal menyimpan salinan / replika untuk setidaknya satu dari pecahan. Untungnya, Kubernetes menyimpan penyimpanan disk, dan menggunakannya kembali ketika saya meluncurkan kembali data-node.


... Beberapa waktu telah berlalu ...

Nah, kali ini hanya menambahkan simpul sepertinya tidak berfungsi (setelah menunggu beberapa menit untuk sesuatu terjadi), jadi saya mulai mencari-cari di REST API.

GET /_cluster/allocation/explain

Ini menunjukkan simpul baru saya dengan "decision": "YES".

By the way, semua node yang sudah ada sebelumnya "decision": "NO"karena "the node is above the low watermark cluster setting". Jadi ini mungkin kasus yang berbeda dari yang saya bahas sebelumnya.

Lalu aku membuat POST sederhana berikut [2] tanpa tubuh , yang menendang hal ke gigi ...

POST /_cluster/reroute

Catatan lain:


[1] Cukup mudah dilakukan di Kubernetes jika Anda memiliki ruang kepala yang cukup: cukup gunakan set stateful melalui dasbor.

[2] Dengan menggunakan antarmuka "Dev Tools" Kibana, saya tidak perlu repot dengan shell SSH / exec.

Brent Bradburn
sumber
0

Saya baru saja meningkatkan

"index.number_of_replicas"

oleh 1 (tunggu sampai node disinkronkan) kemudian turunkan dengan 1 setelahnya, yang secara efektif menghilangkan pecahan yang tidak ditugaskan dan cluster berwarna Hijau lagi tanpa risiko kehilangan data apa pun.

Saya percaya ada cara yang lebih baik tetapi ini lebih mudah bagi saya.

Semoga ini membantu.

Yusuf Demirag
sumber
0

Saat berurusan dengan pecahan yang rusak Anda dapat mengatur faktor replikasi ke 0 dan kemudian mengaturnya kembali ke nilai aslinya. Ini akan menghapus sebagian besar jika tidak semua pecahan Anda rusak dan memindahkan replika baru di cluster.

Menyetel indeks dengan replika yang belum ditetapkan untuk menggunakan faktor replikasi 0:

curl -XGET http://localhost:9200/_cat/shards |\
  grep UNASSIGNED | grep ' r ' |\
  awk '{print $1}' |\
  xargs -I {} curl -XPUT http://localhost:9200/{}/_settings -H "Content-Type: application/json" \
  -d '{ "index":{ "number_of_replicas": 0}}'

Mengaturnya kembali ke 1:

curl -XGET http://localhost:9200/_cat/shards |\
  awk '{print $1}' |\
  xargs -I {} curl -XPUT http://localhost:9200/{}/_settings -H "Content-Type: application/json" \
  -d '{ "index":{ "number_of_replicas": 1}}'

Catatan: Jangan jalankan ini jika Anda memiliki faktor replikasi yang berbeda untuk indeks yang berbeda. Ini akan membuat hardcode faktor replikasi untuk semua indeks menjadi 1.

bonzofenix
sumber