2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Elastic Stack (Elasticsearch)Advent Calendar 2022

Day 25

Elasticsearch Python Client (elasticsearch-py)でProxyを設定する方法

Last updated at Posted at 2022-12-24

概要

Elasticsearch Python Client (elasticsearch-py)をプロキシサーバを通して利用する方法がググってもあまり出てこないため、簡単に設定方法をまとめました。
elasticsearch-pyのバージョンによって設定方法が少し異なりますので、v7とv8で分けて記載します。
elasticsearch-pyのドキュメント
elasticsearch-pyのGitHub

準備

お手軽に試せるようにdocker-compose一発で環境が整うようにします。

Elastic Cloud

こちらを参考に作成

構成

以下のようなファイルを用意します。

.
├── app
│   ├── Dockerfile
│   ├── v7.py
│   └── v8.py
├── docker-compose.yml
└── squid
    └── Dockerfile

ではそれぞれのファイルの中身を見てみましょう。

プロキシサーバ

Docker HubにあるUbuntu/Squidイメージを使用します。
Dockerfileはこちら

FROM ubuntu/squid
RUN echo acl SSL_ports port 443 9243 >> /etc/squid/squid.conf

Elasticsearchのポートが9243ですのでこのポートだけ追加をしています。

Python Client

Docker Hubにあるpython:bullseyeを使用します。

Dockerfile

Dockerfileはこちら
apt installしているパッケージは後ほどプロキシ経由に通信を変更する際に使用します。

v8

FROM python:bullseye
RUN apt update
RUN apt install -y net-tools iputils-ping curl
RUN pip3 install requests elasticsearch
COPY v8.py v8.py

v7

version 7でのインストールを明記します。

FROM python:bullseye
RUN apt update
RUN apt install -y net-tools iputils-ping curl
RUN pip3 install requests elasticsearch==7.17.8
COPY v7.py v7.py

docker-compose

version: '3.7'
services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    container_name: app
    command: /bin/sh -c "while :; do sleep 10; done"
    privileged: true
  squid:
    build:
      context: ./squid
      dockerfile: Dockerfile
    container_name: squid
    ports:
      - 3128:3128

command部分はコンテナが落ちないようにしているだけです。

ソースコード

v8

from elasticsearch import Elasticsearch
from elastic_transport import RequestsHttpNode

es = Elasticsearch("https://xxxx.es.asia-northeast1.gcp.cloud.es.io:9243",basic_auth=("elastic","xxxxxxxx"),node_class=RequestsHttpNode)
print(es.info())

v8.xはシンプルです。プロキシサーバの情報は環境変数から持ってきます。

v7

from elasticsearch import Elasticsearch, RequestsHttpConnection

class MyConnection(RequestsHttpConnection):
    def __init__(self,*args, **kwargs):
        proxies = kwargs.pop('proxies', {})
        super(MyConnection, self).__init__(*args, **kwargs)
        self.session.proxies = proxies

es = Elasticsearch("https://xxxx.es.asia-northeast1.gcp.cloud.es.io:9243",http_auth=("elastic","xxxxxxx"),connection_class=MyConnection, proxies = {})
print(es.info())

v7.xではconnection classを自前で用意する必要があります。
MyConnectionクラスがそれにあたります。
こちらを参考にしました。
https://github.com/elastic/elasticsearch-py/issues/275
プロキシサーバの情報はv8と同じように環境変数から持ってきます。

動作確認

では実際に動かしてみましょう。

v8

Dockerfileをv8のものにしてdocker-compose build docker-compose up -dを実行します。docker-compose psで以下のようになればOKです。

Name               Command               State           Ports         
-----------------------------------------------------------------------
app     /bin/sh -c while :; do sle ...   Up                            
squid   entrypoint.sh -f /etc/squi ...   Up      0.0.0.0:3128->3128/tcp

ではdocker exec -it app /bin/bashappに入って実際に通信を見てみましょう。

# curl google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

# python v8.py 
{'name': 'instance-0000000001', 'cluster_name': 'e939240763684a8db3183d6f8b47d0a1', 'cluster_uuid': 'eLMujpfhTr2vc92rhENRvA', 'version': {'number': '8.4.2', 'build_flavor': 'default', 'build_type': 'docker', 'build_hash': '89f8c6d8429db93b816403ee75e5c270b43a940a', 'build_date': '2022-09-14T16:26:04.382547801Z', 'build_snapshot': False, 'lucene_version': '9.3.0', 'minimum_wire_compatibility_version': '7.17.0', 'minimum_index_compatibility_version': '7.0.0'}, 'tagline': 'You Know, for Search'}

これはもちろんプロキシサーバ経由ではありません。
少し乱暴ですがroute delete defaultでルートを潰してみます。

# route delete default
# curl google.com
curl: (6) Could not resolve host: google.com
# python v8.py 
Traceback (most recent call last):
  File "//v8.py", line 5, in <module>
    print(es.info())
          ^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/elasticsearch/_sync/client/utils.py", line 414, in wrapped
    return api(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/elasticsearch/_sync/client/__init__.py", line 2296, in info
    return self.perform_request(  # type: ignore[return-value]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/elasticsearch/_sync/client/_base.py", line 286, in perform_request
    meta, resp_body = self.transport.perform_request(
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/elastic_transport/_transport.py", line 329, in perform_request
    meta, raw_data = node.perform_request(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/elastic_transport/_node/_http_requests.py", line 244, in perform_request
    raise err from None
elastic_transport.ConnectionError: Connection error caused by: ConnectionError(Connection error caused by: ConnectionError(HTTPSConnectionPool(host='dep1.es.asia-northeast1.gcp.cloud.es.io', port=9243): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0xffff8341cdd0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))))

では次にプロキシサーバを環境変数で設定します。

export http_proxy=http://squid:3128
export https_proxy=http://squid:3128

curl google.compython v8.pyも問題なく動作します。
ここでSquidログを見てみます。

# docker-compose logs
...
squid    | 1671678795.332     92 192.168.0.2 TCP_MISS/301 869 GET http://google.com/ - HIER_DIRECT/172.217.175.46 text/html
squid    | 1671678828.075     72 192.168.0.2 TCP_TUNNEL/200 7151 CONNECT xxxxxxx.es.asia-northeast1.gcp.cloud.es.io:9243 - HIER_DIRECT/34.85.47.11 -

無事プロキシサーバ経由で動作していることが確認できます。

v7

v8と全く同じ手順でテストできます。

まとめ

ElasticのドキュメントにはPython Clientをプロキシサーバ経由で使用する場合についての記述がありません。
この記事が少しでもお役に立てばと思います。

おまけ

Advent Calendarが埋まってしまったため、一部掲載できない記事がありました。
弊社のコンサルタントによるKibana VEGAについての記事です。
こちらもぜひご覧ください。
https://gist.github.com/ijokarumawak/0dfcc1cca3ad38e1d5aae3b61b787cd4

Elastic Cloud 無料トライアル

こちらからElastic Cloudの14日間無料トライアルを是非お試しください
Elastic Cloud 無料トライアル

手順は下記リンクをご参照ください
Elastic Cloud について 〜実際にデプロイメントを作ってみよう〜

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?