sql >> データベース >  >> RDS >> MariaDB

Kubernetesを使用したProxySQLネイティブクラスタリング

    ProxySQLは、v1.4.2以降ネイティブクラスタリングをサポートしています。これは、複数のProxySQLインスタンスがクラスター対応であることを意味します。彼らは互いの状態を認識しており、構成バージョン、タイムスタンプ、およびチェックサム値に基づいて最新の構成に同期することにより、構成の変更を自動的に処理できます。 ProxySQLのクラスタリングサポートを構成する方法と、その動作を期待できる方法を示すこのブログ投稿を確認してください。

    ProxySQLは分散型プロキシであり、アプリケーションの近くにデプロイすることをお勧めします。このアプローチは、実行時に簡単に再構成できるように設計されているため、数百ノードまでもかなり適切に拡張できます。複数のProxySQLノードを効率的に管理するには、ノードの1つで実行された変更が、ファーム内のすべてのノードに適用されることを確認する必要があります。ネイティブクラスタリングを使用しない場合は、構成を手動でエクスポートして他のノードにインポートする必要があります(ただし、これは自分で自動化できます)。

    前回のブログ投稿では、KubernetesConfigMapを介したProxySQLクラスタリングについて説明しました。このアプローチは、ConfigMapの集中型構成アプローチで多かれ少なかれ効率的です。 ConfigMapにロードされたものはすべて、ポッドにマウントされます。構成の更新は、バージョン管理(proxysql.cnfコンテンツを変更し、別の名前でConfigMapにロード)を介して実行し、展開方法のスケジューリングと更新戦略に応じてポッドにプッシュできます。

    ただし、急速に変化する環境では、このConfigMapアプローチはおそらく最善の方法ではありません。これは、新しい構成をロードするために、ConfigMapボリュームを再マウントするためにポッドの再スケジュールが必要であり、これによりProxySQLサービス全体が危険にさらされる可能性があるためです。たとえば、私たちの環境では、厳格なパスワードポリシーにより、MySQLユーザーパスワードの有効期限が7日ごとに強制される必要があります。これにより、新しいパスワードのProxySQLConfigMapを毎週更新し続ける必要があります。補足として、ProxySQL内のMySQLユーザーは、バックエンドMySQLサーバー上のものと一致するユーザーとパスワードを必要とします。そこで、KubernetesでProxySQLネイティブクラスタリングのサポートを利用して、ConfigMapのバージョン管理やポッドの再スケジュールに煩わされることなく構成の変更を自動的に適用する必要があります。

    このブログ投稿では、Kubernetesでヘッドレスサービスを使用してProxySQLネイティブクラスタリングを実行する方法を紹介します。私たちの高レベルのアーキテクチャは、次のように説明できます。

    ClusterControlによって展開および管理されるベアメタルインフラストラクチャで実行されている3つのGaleraノードがあります:

    • 192.168.0.21
    • 192.168.0.22
    • 192.168.0.23

    私たちのアプリケーションはすべて、Kubernetes内でポッドとして実行されています。アイデアは、アプリケーションとデータベースクラスターの間に2つのProxySQLインスタンスを導入して、リバースプロキシとして機能させることです。次に、アプリケーションはKubernetesサービスを介してProxySQLポッドに接続します。このサービスは、負荷分散され、多数のProxySQLレプリカ間でフェイルオーバーされます。

    以下は、Kubernetesのセットアップの概要です。

    [email protected]:~# kubectl get nodes -o wide
    NAME    STATUS   ROLES    AGE     VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
    kube1   Ready    master   5m      v1.15.1   192.168.100.201   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7
    kube2   Ready    <none>   4m1s    v1.15.1   192.168.100.202   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7
    kube3   Ready    <none>   3m42s   v1.15.1   192.168.100.203   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7

    ConfigMapを介したProxySQLの構成

    まず、ConfigMapにロードされる基本構成を準備しましょう。 proxysql.cnfというファイルを作成し、次の行を追加します。

    datadir="/var/lib/proxysql"
    
    admin_variables=
    {
        admin_credentials="proxysql-admin:adminpassw0rd;cluster1:secret1pass"
        mysql_ifaces="0.0.0.0:6032"
        refresh_interval=2000
        cluster_username="cluster1"
        cluster_password="secret1pass"
        cluster_check_interval_ms=200
        cluster_check_status_frequency=100
        cluster_mysql_query_rules_save_to_disk=true
        cluster_mysql_servers_save_to_disk=true
        cluster_mysql_users_save_to_disk=true
        cluster_proxysql_servers_save_to_disk=true
        cluster_mysql_query_rules_diffs_before_sync=3
        cluster_mysql_servers_diffs_before_sync=3
        cluster_mysql_users_diffs_before_sync=3
        cluster_proxysql_servers_diffs_before_sync=3
    }
    
    mysql_variables=
    {
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
        interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.1.30"
        connect_timeout_server=10000
        monitor_history=60000
        monitor_connect_interval=200000
        monitor_ping_interval=200000
        ping_interval_server_msec=10000
        ping_timeout_server=200
        commands_stats=true
        sessions_sort=true
        monitor_username="proxysql"
        monitor_password="proxysqlpassw0rd"
        monitor_galera_healthcheck_interval=2000
        monitor_galera_healthcheck_timeout=800
    }
    
    mysql_galera_hostgroups =
    (
        {
            writer_hostgroup=10
            backup_writer_hostgroup=20
            reader_hostgroup=30
            offline_hostgroup=9999
            max_writers=1
            writer_is_also_reader=1
            max_transactions_behind=30
            active=1
        }
    )
    
    mysql_servers =
    (
        { address="192.168.0.21" , port=3306 , hostgroup=10, max_connections=100 },
        { address="192.168.0.22" , port=3306 , hostgroup=10, max_connections=100 },
        { address="192.168.0.23" , port=3306 , hostgroup=10, max_connections=100 }
    )
    
    mysql_query_rules =
    (
        {
            rule_id=100
            active=1
            match_pattern="^SELECT .* FOR UPDATE"
            destination_hostgroup=10
            apply=1
        },
        {
            rule_id=200
            active=1
            match_pattern="^SELECT .*"
            destination_hostgroup=20
            apply=1
        },
        {
            rule_id=300
            active=1
            match_pattern=".*"
            destination_hostgroup=10
            apply=1
        }
    )
    
    mysql_users =
    (
        { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
        { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
    )
    
    proxysql_servers =
    (
        { hostname = "proxysql-0.proxysqlcluster", port = 6032, weight = 1 },
        { hostname = "proxysql-1.proxysqlcluster", port = 6032, weight = 1 }
    )

    上記の構成行の一部は、以下のセクションごとに説明されています。

    admin_variables

    admin_credentialsに注意してください 「proxysql-admin」であるデフォルト以外のユーザーを使用した変数。 ProxySQLは、ローカルホストのみを介したローカル接続用にデフォルトの「admin」ユーザーを予約します。したがって、ProxySQLインスタンスにリモートでアクセスするには、他のユーザーを使用する必要があります。そうしないと、次のエラーが発生します:

    ERROR 1040 (42000): User 'admin' can only connect locally

    cluster_usernameも追加しました およびcluster_password admin_credentialsの値 自動同期を可能にするためにセミコロンで区切られた行。 cluster_ *で始まるすべての変数 ProxySQLネイティブクラスタリングに関連しており、自明です。

    mysql_galera_hostgroups

    これは、ProxySQL 2.xに導入された新しいディレクティブです(ProxySQLイメージは2.0.5で実行されています)。 ProxySQL 1.xで実行する場合は、この部分を削除して、代わりにスケジューラテーブルを使用してください。構成の詳細については、このブログ投稿「DockerでMySQLGaleraCluster用にProxySQL2.0を実行および構成する方法」の「ProxySQL2.xSupportforGaleraCluster」ですでに説明しました。

    mysql_servers

    すべての行は自明です。これは、ClusterControlから取得した次のトポロジのスクリーンショットに要約されているように、MySQLGaleraClusterで実行されている3つのデータベースサーバーに基づいています。

    proxysql_servers

    ここでは、ProxySQLピアのリストを定義します。

    • hostname-ピアのホスト名/IPアドレス
    • ポート-ピアの管理ポート
    • 重量-現在は使用されていませんが、将来の機能強化のロードマップに含まれています
    • コメント-自由形式のコメントフィールド

    Docker / Kubernetes環境では、コンテナのホスト名またはIPアドレスを検出してリンクし、ConfigMap、手動挿入、entrypoint.shスクリプト、環境変数、またはその他の手段を使用して、これらをこのテーブルに挿入する方法が複数あります。 Kubernetesでは、使用するReplicationControllerまたはDeploymentメソッドに応じて、StatefulSetで実行している場合を除き、ポッドの解決可能なホスト名を事前に推測するのはやや注意が必要です。

    作成されたポッドに安定した解決可能なホスト名を提供するStatefulStateポッド序数インデックスに関するこのチュートリアルを確認してください。これをヘッドレスサービス(さらに下で説明)と組み合わせると、解決可能なホスト名の形式は次のようになります。

    {app_name}-{index_number}。{service}

    ここで、{service}はヘッドレスサービスであり、「proxysql-0.proxysqlcluster」と「proxysql-1.proxysqlcluster」の由来を説明しています。 3つ以上のレプリカが必要な場合は、StatefulSetアプリケーション名に関連する昇順のインデックス番号を追加して、それに応じてエントリを追加します。

    これで、構成ファイルをConfigMapにプッシュする準備が整いました。これは、展開中にすべてのProxySQLポッドにマウントされます。

    $ kubectl create configmap proxysql-configmap --from-file=proxysql.cnf

    ConfigMapが正しくロードされているかどうかを確認します:

    $ kubectl get configmap
    NAME                 DATA   AGE
    proxysql-configmap   1      7h57m

    ProxySQL監視ユーザーの作成

    展開を開始する前の次のステップは、データベースクラスターにProxySQL監視ユーザーを作成することです。 Galeraクラスターで実行しているため、Galeraノードの1つで次のステートメントを実行します。

    mysql> CREATE USER 'proxysql'@'%' IDENTIFIED BY 'proxysqlpassw0rd';
    mysql> GRANT USAGE ON *.* TO 'proxysql'@'%';

    MySQLユーザーを作成していない場合(上記のmysql_usersセクションで指定)、それらも作成する必要があります:

    mysql> CREATE USER 'wordpress'@'%' IDENTIFIED BY 'passw0rd';
    mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%';
    mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
    mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'proxysql'@'%';

    それでおしまい。これで、展開を開始する準備が整いました。

    StatefulSetの導入

    まず、StatefulSetを使用して2つのProxySQLインスタンス、または冗長性を目的としたレプリカを作成します。

    まず、proxysql-ss-svc.ymlというテキストファイルを作成し、次の行を追加しましょう。

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: proxysql
      labels:
        app: proxysql
    spec:
      replicas: 2
      serviceName: proxysqlcluster
      selector:
        matchLabels:
          app: proxysql
          tier: frontend
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          labels:
            app: proxysql
            tier: frontend
        spec:
          restartPolicy: Always
          containers:
          - image: severalnines/proxysql:2.0.4
            name: proxysql
            volumeMounts:
            - name: proxysql-config
              mountPath: /etc/proxysql.cnf
              subPath: proxysql.cnf
            ports:
            - containerPort: 6033
              name: proxysql-mysql
            - containerPort: 6032
              name: proxysql-admin
          volumes:
          - name: proxysql-config
            configMap:
              name: proxysql-configmap
    ---
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
      labels:
        app: proxysql
        tier: frontend
      name: proxysql
    spec:
      ports:
      - name: proxysql-mysql
        nodePort: 30033
        port: 6033
        protocol: TCP
        targetPort: 6033
      - name: proxysql-admin
        nodePort: 30032
        port: 6032
        protocol: TCP
        targetPort: 6032
      selector:
        app: proxysql
        tier: frontend
      type: NodePort

    上記の定義には、StatefulSetとServiceの2つのセクションがあります。 StatefulSetは、ポッドまたはレプリカの定義であり、proxysql-configmapからロードされるConfigMapボリュームのマウントポイントです。次のセクションはサービス定義です。ここでは、ポッドを公開して内部ネットワークまたは外部ネットワークにルーティングする方法を定義します。

    ProxySQLステートフルセットとサービスを作成します:

    $ kubectl create -f proxysql-ss-svc.yml

    ポッドとサービスの状態を確認します:

    $ kubectl get pods,svc
    NAME             READY   STATUS    RESTARTS   AGE
    pod/proxysql-0   1/1     Running   0          4m46s
    pod/proxysql-1   1/1     Running   0          2m59s
    
    NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
    service/kubernetes        ClusterIP   10.96.0.1        <none>        443/TCP                         10h
    service/proxysql          NodePort    10.111.240.193   <none>        6033:30033/TCP,6032:30032/TCP   5m28s

    ポッドのログを見ると、次の警告が殺到していることがわかります。

    $ kubectl logs -f proxysql-0
    ...
    2019-08-01 19:06:18 ProxySQL_Cluster.cpp:215:ProxySQL_Cluster_Monitor_thread(): [WARNING] Cluster: unable to connect to peer proxysql-1.proxysqlcluster:6032 . Error: Unknown MySQL server host 'proxysql-1.proxysqlcluster' (0)

    上記は、proxysql-0が「proxysql-1.proxysqlcluster」を解決して接続できなかったことを意味します。これは、ProxySQL間通信に必要となるDNSレコード用のヘッドレスサービスを作成していないためです。

    Kubernetesヘッドレスサービス

    ProxySQLポッドが予想されるFQDNを解決して直接接続できるようにするには、解決プロセスで、仮想IPアドレスではなく、割り当てられたターゲットポッドのIPアドレスを検索できる必要があります。ここでヘッドレスサービスが登場します。 「clusterIP=None」を設定してヘッドレスサービスを作成する場合、負荷分散は構成されず、このサービスにクラスターIP(仮想IP)は割り当てられません。 DNSのみが自動的に構成されます。ヘッドレスサービスのDNSクエリを実行すると、ポッドのIPアドレスのリストが表示されます。

    「proxysqlcluster」のヘッドレスサービスDNSレコードを検索すると、次のようになります(この例では、3つのProxySQLインスタンスがあります):

    $ host proxysqlcluster
    proxysqlcluster.default.svc.cluster.local has address 10.40.0.2
    proxysqlcluster.default.svc.cluster.local has address 10.40.0.3
    proxysqlcluster.default.svc.cluster.local has address 10.32.0.2

    次の出力は、clusterIPに解決される「proxysql」と呼ばれる標準サービスのDNSレコードを示しています。

    $ host proxysql
    proxysql.default.svc.cluster.local has address 10.110.38.154

    ヘッドレスサービスを作成してポッドにアタッチするには、StatefulSet宣言内でServiceNameを定義する必要があり、以下に示すように、サービス定義には「clusterIP=None」が必要です。 proxysql-headless-svc.ymlというテキストファイルを作成し、次の行を追加します。

    apiVersion: v1
    kind: Service
    metadata:
      name: proxysqlcluster
      labels:
        app: proxysql
    spec:
      clusterIP: None
      ports:
      - port: 6032
        name: proxysql-admin
      selector:
        app: proxysql

    ヘッドレスサービスを作成する:

    $ kubectl create -f proxysql-headless-svc.yml

    確認のため、この時点で、次のサービスが実行されています。

    $ kubectl get svc
    NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
    kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP                         8h
    proxysql          NodePort    10.110.38.154   <none>        6033:30033/TCP,6032:30032/TCP   23m
    proxysqlcluster   ClusterIP   None            <none>        6032/TCP                        4s

    次に、ポッドのログの1つを確認します:

    $ kubectl logs -f proxysql-0
    ...
    2019-08-01 19:06:19 ProxySQL_Cluster.cpp:215:ProxySQL_Cluster_Monitor_thread(): [WARNING] Cluster: unable to connect to peer proxysql-1.proxysqlcluster:6032 . Error: Unknown MySQL server host 'proxysql-1.proxysqlcluster' (0)
    2019-08-01 19:06:19 [INFO] Cluster: detected a new checksum for mysql_query_rules from peer proxysql-1.proxysqlcluster:6032, version 1, epoch 1564686376, checksum 0x3FEC69A5C9D96848 . Not syncing yet ...
    2019-08-01 19:06:19 [INFO] Cluster: checksum for mysql_query_rules from peer proxysql-1.proxysqlcluster:6032 matches with local checksum 0x3FEC69A5C9D96848 , we won't sync.

    Clusterコンポーネントは、「proxysqlcluster」と呼ばれるヘッドレスサービスを介して、ポート6032上の他のピアproxysql-1.proxysqlclusterからの新しいチェックサムを解決、接続、および検出できることに気付くでしょう。このサービスはKubernetesネットワーク内でのみポート6032を公開するため、外部からは到達できないことに注意してください。

    この時点で、展開は完了です。

    ProxySQLへの接続

    ProxySQLサービスに接続する方法はいくつかあります。負荷分散されたMySQL接続は、Kubernetesネットワーク内からポート6033に送信し、クライアントが外部ネットワークから接続している場合はポート30033を使用する必要があります。

    外部ネットワークからProxySQL管理インターフェースに接続するには、NodePortセクションで定義されたポート30032に接続できます(192.168.100.203はホストkube3.localのプライマリIPアドレスです):

    $ mysql -uproxysql-admin -padminpassw0rd -h192.168.100.203 -P30032

    Kubernetesネットワーク内の他のポッドからアクセスする場合は、ポート6032でclusterIP 10.110.38.154(「proxysql」サービスで定義)を使用します。

    次に、必要に応じてProxySQL構成の変更を実行し、それらをランタイムにロードします。

    mysql> INSERT INTO mysql_users (username,password,default_hostgroup) VALUES ('newuser','passw0rd',10);
    mysql> LOAD MYSQL USERS TO RUNTIME;

    ポッドの1つに、構成の同期が完了したことを示す次の行が表示されます。

    $ kubectl logs -f proxysql-0
    ...
    2019-08-02 03:53:48 [INFO] Cluster: detected a peer proxysql-1.proxysqlcluster:6032 with mysql_users version 2, epoch 1564718027, diff_check 4. Own version: 1, epoch: 1564714803. Proceeding with remote sync
    2019-08-02 03:53:48 [INFO] Cluster: detected peer proxysql-1.proxysqlcluster:6032 with mysql_users version 2, epoch 1564718027
    2019-08-02 03:53:48 [INFO] Cluster: Fetching MySQL Users from peer proxysql-1.proxysqlcluster:6032 started
    2019-08-02 03:53:48 [INFO] Cluster: Fetching MySQL Users from peer proxysql-1.proxysqlcluster:6032 completed

    自動同期は、ProxySQLランタイムで構成が変更された場合にのみ発生することに注意してください。したがって、アクションを表示する前に、「LOAD...TORUNTIME」ステートメントを実行することが重要です。永続性のために、ProxySQLの変更をディスクに保存することを忘れないでください:

    mysql> SAVE MYSQL USERS TO DISK;

    制限

    ProxySQLは、永続性のためにConfigMapにロードするために後で使用できるテキスト構成ファイルへのアクティブな構成の保存/エクスポートをサポートしていないため、このセットアップには制限があることに注意してください。これには機能リクエストがあります。その間、変更をConfigMapに手動でプッシュできます。そうしないと、ポッドが誤って削除された場合、新しいポッドがConfigMapで定義されたものによってブートストラップされるため、現在の構成が失われます。

    このブログ投稿のアイデアを生み出し、ユースケースと実装に関する洞察を提供してくれたSampathKamineniに特に感謝します。


    1. DB内のすべてのスキーマを一覧表示するためのOracleSQLクエリ

    2. 重複する行を削除します(重複するすべての行を削除しないでください)

    3. PHPを使用してMySQLデータベースをバックアップ/エクスポートする方法

    4. SQLサーバーでBEFOREUPDATEDトリガーを実行するにはどうすればよいですか?