در یکی از سناریوها، تصمیم گرفتم یک کلاستر Elasticsearch راهاندازی کنم؛ اما نه با Docker یا ماشین مجازی. هدف ما ایجاد محیطی بود که در عین سادگی، امن، پایدار و کاملاً سازگار با SELinux باشد.
انتخابم: Podman روی Rocky Linux — ترکیبی سبک، بدون daemon و مناسب برای سرویسهای حیاتی.

Elasticsearch برای معماری توزیعشده طراحی شده است. اما در حالت تکنودی نه مقیاسپذیری دارد و نه تحمل خطا.
در یک محیط چندنودی:
دادهها بهصورت shard و replica بین نودها پخش میشوند.
خرابی یک نود باعث از کار افتادن سرویس نمیشود.
ایندکسگذاری و query بهصورت موازی انجام میشوند.
از سه نود استفاده کردم: یک نود master و دو نود data. این ترکیب حداقل ساختاری است که quorum را تضمین میکند؛ یعنی اگر یکی از نودها از دسترس خارج شود، دو نود دیگر همچنان قادر به ادامه کار و حفظ هماهنگی هستند.
در محیطهای تولیدی بزرگتر، داشتن سه master اختصاصی و چند data node مجزا توصیه میشود.
اولین گام، فعالسازی ارتباط امن بین نودهاست. برای این کار از ابزار داخلی elasticsearch-certutil استفاده کردم تا برای هر نود گواهی و کلید اختصاصی تولید شود:
bin/elasticsearch-certutil cert --silent --pem \ --in config/instances.yml \ --ca-cert config/certs/ca/ca.crt \ --ca-key config/certs/ca/ca.key \ --out config/certs/certs.zip unzip config/certs/certs.zip -d config/certs/
فایل instances.yml باید شامل IP و نام هر نود باشد:
instances: - name: "master-node" ip: ["<MASTER_IP>"] - name: "data-node-01" ip: ["<DATA_NODE_01_IP>"] - name: "data-node-02" ip: ["<DATA_NODE_02_IP>"]
نتیجه: هر نود گواهی و کلید مخصوص خود را دارد، در حالیکه همه از یک CA مشترک استفاده میکنند.
cluster.name: es-cluster node.name: master-node discovery.seed_hosts: ["<MASTER_IP>", "<DATA_NODE_01_IP>", "<DATA_NODE_02_IP>"] cluster.initial_master_nodes: ["master-node"] network.host: 0.0.0.0 http.port: 9200 transport.port: 9300 xpack.security.enabled: true # HTTP TLS xpack.security.http.ssl.enabled: true xpack.security.http.ssl.key: certs/master-node/key.pem xpack.security.http.ssl.certificate: certs/master-node/crt.pem xpack.security.http.ssl.certificate_authorities: ["certs/ca/ca.crt"] # Transport TLS xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.key: certs/master-node/key.pem xpack.security.transport.ssl.certificate: certs/master-node/crt.pem xpack.security.transport.ssl.certificate_authorities: ["certs/ca/ca.crt"] xpack.security.transport.ssl.verification_mode: certificate node.roles: [ master, data, ingest ]
در این سناریو به دلیل محدودیت منابع، master نقش data و ingest را هم دارد. در محیطهای production این نقشها باید از هم جدا باشند.
Podman بهطور پیشفرض با SELinux سازگار است. اگر context فایلها اشتباه باشد، کانتینرها نمیتوانند به config یا cert دسترسی پیدا کنند.
sudo chcon -t container_file_t ~/es-config/elasticsearch.yml sudo chcon -R -t container_file_t ~/es-certs sudo chmod 644 ~/es-config/elasticsearch.yml sudo chmod -R 755 ~/es-certs sudo chown -R $(whoami):$(whoami) ~/es-config ~/es-certs
podman volume create es-data podman run -d --name elasticsearch \ --network=host \ --security-opt label=disable \ -v es-data:/usr/share/elasticsearch/data \ -v ~/es-config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro \ -v ~/es-certs:/usr/share/elasticsearch/config/certs:ro \ docker.io/library/elasticsearch:8.12.0 sleep 60 && podman logs -f elasticsearch
نکته: در محیطهای امنتر، بهتر است بهجای network=host-- از شبکه جداگانه (bridge یا CNI) استفاده شود.
بهجای ذخیره رمز عبور کاربر در فایل پیکربندی، از Service Token استفاده کردم:
TOKEN=$(curl -s -k -u elastic:<PASSWORD> -X POST \ "https://<MASTER_IP>:9200/_security/service/elastic/kibana/credential/token/kibana-svc" \ -H "Content-Type: application/json" | jq -r .value)
و سپس در فایل kibana.yml:
elasticsearch.hosts: ["https://<MASTER_IP>:9200"] elasticsearch.serviceAccountToken: "$TOKEN" elasticsearch.ssl.certificateAuthorities: ["/usr/share/kibana/config/certs/ca/ca.crt"] server.ssl.enabled: true server.ssl.certificate: /usr/share/kibana/config/certs/master-node/master-node.crt server.ssl.key: /usr/share/kibana/config/certs/master-node/master-node.key
اجرای Kibana:
podman run -d --name kibana \ --network=host \ --security-opt label=disable \ -v ~/kibana-config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro \ -v ~/es-certs:/usr/share/kibana/config/certs:ro \ docker.io/library/kibana:8.12.0
node.name: data-node-01 node.roles: [ data, ingest ] xpack.security.http.ssl.key: certs/data-node-01/key.pem xpack.security.http.ssl.certificate: certs/data-node-01/crt.pem ES_JAVA_OPTS: "-Xms2g -Xmx2g"
نام نود و مسیر گواهی باید دقیقاً با فایل instances.yml یکسان باشد.
sysctl -w vm.max_map_count=262144 ulimit -n 65535
در elasticsearch.yml:
cluster.routing.allocation.disk.watermark.low: 85% cluster.routing.allocation.disk.watermark.high: 90%
و برای حافظه JVM:
ES_JAVA_OPTS="-Xms2g -Xmx2g"
قانون کلی: حداکثر نیمی از RAM سیستم و حداکثر 32GB برای heap.
Snapshots به S3 یا فایلسیستم خارجی برای Disaster Recovery
Monitoring با X-Pack یا Prometheus Exporter
Rolling Restart — همیشه نودها را یکییکی بازنشانی کنید
ILM برای مدیریت چرخه عمر شاخصها و کنترل رشد حجم
Allocation Awareness در محیطهای چند zone یا چند host
اجرا شد. Podman در این سناریو جایگزین قابل اتکایی برای Docker بود، با کنترل امنیتی بهتر و سازگاری بیشتر در محیطهای Enterprise.
برای تیمهایی که به دنبال ترکیبی از سادگی، امنیت و پایداری هستند، Elasticsearch + Podman + Rocky Linux میتواند معماریای پایدار و منعطف بسازد.
#Elasticsearch #Podman #DevOps #Security #Linux #RockyLinux #SystemDesign #Infrastructure #Kibana #Containers