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

オーケストレーションツールを使用せずにMariaDBGaleraクラスターを実行する-DBコンテナー管理:パート2

    このブログの最初の部分で見たように、Galeraのような強一貫性のあるデータベースクラスターは、KubernetesやSwarmのようなコンテナーオーケストレーションツールではうまく機能しません。 Galeraをデプロイし、Dockerのプロセス管理を構成して、動作を完全に制御する方法を説明しました。このブログ投稿はその続きであり、クラスターの運用と保守について検討します。

    このブログのパート1の要点のいくつかを要約すると、ProxySQLとKeepalivedを備えた3ノードのGaleraクラスターを3つの異なるDockerホストにデプロイし、すべてのMariaDBインスタンスがDockerコンテナーとして実行されます。次の図は、最終的な展開を示しています。

    グレースフルシャットダウン

    MySQLの正常なシャットダウンを実行するには、SIGTERM(シグナル15)をコンテナーに送信するのが最善の方法です。

    $ docker kill -s 15 {db_container_name}

    クラスタをシャットダウンする場合は、すべてのデータベースコンテナで、一度に1つのノードで上記のコマンドを繰り返します。上記は、MariaDBのsystemdサービスで「systemctlstopmysql」を実行するのと似ています。 「dockerstop」コマンドを使用すると、データベースサービスにとってかなり危険です。これは、10秒間のタイムアウトを待機し、この期間を超えるとDockerがSIGKILLを強制するためです(適切な-timeout を使用しない場合)。 値)。

    正常にシャットダウンする最後のノードには、 seqnoがあります。 -1およびsafe_to_bootstrapと等しくない Dockerホストの/{datadirvolume} /grastate.datでフラグが1に設定されています(例:host2:

    )。
    $ cat /containers/mariadb2/datadir/grastate.dat
    # GALERA saved state
    version: 2.1
    uuid:    e70b7437-645f-11e8-9f44-5b204e58220b
    seqno:   7099
    safe_to_bootstrap: 1

    最も高度なノードの検出

    クラスタが正常にシャットダウンしなかった場合、またはブートストラップしようとしたノードがクラスタを離れる最後のノードではなかった場合、Galeraノードの1つをブートストラップできず、次のエラーが発生する可能性があります。 :

    2016-11-07 01:49:19 5572 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node.
    It was not the last one to leave the cluster and may not contain all the updates.
    To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .

    Galeraは、 safe_to_bootstrapを持つノードを尊重します 最初の参照ノードとしてフラグが1に設定されます。これは、データの損失を回避し、正しいノードが常にブートストラップされるようにするための最も安全な方法です。

    エラーが発生した場合は、最初にブートストラップされるノードとしてノードを選択する前に、最初に最も進んだノードを見つける必要があります。一時コンテナを作成します(-rm を使用) フラグ)、2つのMySQLコマンドフラグ-wsrep_recover を使用して、実際のデータベースコンテナと同じdatadirおよび構成ディレクトリにマップします。 および--wsrep_cluster_address 。たとえば、mariadb1の最後にコミットされた番号を知りたい場合は、次を実行する必要があります。

    $ docker run --rm --name mariadb-recover \
            --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
            --volume /containers/mariadb1/datadir:/var/lib/mysql \
            --volume /containers/mariadb1/conf.d:/etc/mysql/conf.d \
            mariadb:10.2.15 \
            --wsrep_recover \
            --wsrep_cluster_address=gcomm://
    2018-06-12  4:46:35 139993094592384 [Note] mysqld (mysqld 10.2.15-MariaDB-10.2.15+maria~jessie) starting as process 1 ...
    2018-06-12  4:46:35 139993094592384 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
    ...
    2018-06-12  4:46:35 139993094592384 [Note] Plugin 'FEEDBACK' is disabled.
    2018-06-12  4:46:35 139993094592384 [Note] Server socket created on IP: '::'.
    2018-06-12  4:46:35 139993094592384 [Note] WSREP: Recovered position: e70b7437-645f-11e8-9f44-5b204e58220b:7099

    最後の行は私たちが探しているものです。 MariaDBは、クラスターUUIDと最後にコミットされたトランザクションのシーケンス番号を出力します。番号が最も大きいノードは、最も進んだノードと見なされます。 -rmを指定したので 、コンテナが終了すると、コンテナは自動的に削除されます。 -volume を置き換えて、すべてのDockerホストで上記の手順を繰り返します。 それぞれのデータベースコンテナボリュームへのパス。

    すべてのデータベースコンテナによって報告された値を比較し、どのコンテナが最新のノードであるかを決定したら、 safe_to_bootstrapを変更します。 /{datadirvolume}/grastate.dat内で手動で1にフラグを立てます。すべてのノードが同じ正確なシーケンス番号を報告しているとしましょう。safe_to_bootstrapを変更することで、ブートストラップするmariadb3を選択できます。 1への値:

    $ vim /containers/mariadb3/datadir/grasate.dat
    ...
    safe_to_bootstrap: 1

    次の章で説明するように、ファイルを保存し、そのノードからクラスターのブートストラップを開始します。

    クラスターのブートストラップ

    クラスターのブートストラップは、クラスターを初めて起動するときに使用した最初のdockerrunコマンドに似ています。 mariadb1が選択されたブートストラップノードである場合、作成されたブートストラップコンテナを再実行するだけです。

    $ docker start mariadb0 # on host1

    それ以外の場合、ブートストラップコンテナが選択したノードに存在しない場合、たとえばhost2で、ブートストラップコンテナコマンドを実行し、既存のmariadb2のボリュームをマップします。 host2のコンテナ名としてmariadb0を使用して、ブートストラップコンテナであることを示しています。

    $ docker run -d \
            --name mariadb0 \
            --hostname mariadb0.weave.local \
            --net weave \
            --publish "3306" \
            --publish "4444" \
            --publish "4567" \
            --publish "4568" \
            $(weave dns-args) \
            --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
            --volume /containers/mariadb2/datadir:/var/lib/mysql \
            --volume /containers/mariadb2/conf.d:/etc/mysql/mariadb.conf.d \
            mariadb:10.2.15 \
            --wsrep_cluster_address=gcomm:// \
            --wsrep_sst_auth="root:PM7%[email protected]^1" \
            --wsrep_node_address=mariadb0.weave.local

    このガイドで説明されている以前のブートストラップコマンドと比較して、このコマンドがわずかに短いことに気付くかもしれません。最初のブートストラップコマンドで既にproxysqlユーザーが作成されているため、次の2つの環境変数をスキップできます。

    • --env MYSQL_USER =proxysql
    • --env MYSQL_PASSWORD =proxysqlpassword

    次に、残りのMariaDBコンテナーを開始し、ブートストラップコンテナーを削除して、ブートストラップされたホストで既存のMariaDBコンテナーを開始します。基本的に、コマンドの順序は次のようになります。

    $ docker start mariadb1 # on host1
    $ docker start mariadb3 # on host3
    $ docker stop mariadb0 # on host2
    $ docker start mariadb2 # on host2

    この時点で、クラスターが開始され、フルキャパシティーで実行されています。

    リソース制御

    メモリはMySQLの非常に重要なリソースです。これはバッファとキャッシュが保存される場所であり、MySQLがディスクに頻繁にアクセスすることによる影響を減らすことが重要です。一方、スワッピングはMySQLのパフォーマンスに悪影響を及ぼします。デフォルトでは、実行中のコンテナーにリソースの制約はありません。コンテナは、ホストのカーネルが許可する限り、特定のリソースを使用します。もう1つの重要なことは、ファイル記述子の制限です。 MySQLサーバーが同時に開くことができるファイルの数に対応するために、開くファイル記述子または「nofile」の制限をより高い値に増やすことができます。これを高い値に設定しても問題はありません。

    メモリ割り当てを制限し、データベースコンテナへのファイル記述子の制限を増やすには、-memoryを追加します。 、-memory-swap および--ulimit 「dockerrun」コマンドへのパラメータ:

    $ docker kill -s 15 mariadb1
    $ docker rm -f mariadb1
    $ docker run -d \
            --name mariadb1 \
            --hostname mariadb1.weave.local \
            --net weave \
            --publish "3306:3306" \
            --publish "4444" \
            --publish "4567" \
            --publish "4568" \
            $(weave dns-args) \
            --memory 16g \
            --memory-swap 16g \
            --ulimit nofile:16000:16000 \
            --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
            --volume /containers/mariadb1/datadir:/var/lib/mysql \
            --volume /containers/mariadb1/conf.d:/etc/mysql/mariadb.conf.d \
            mariadb:10.2.15 \
            --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
            --wsrep_sst_auth="root:PM7%[email protected]^1" \
            --wsrep_node_address=mariadb1.weave.local

    -memory-swapの場合は注意してください -memoryと同じ値に設定されます 、および--memory が正の整数に設定されている場合、コンテナはスワップにアクセスできません。 -memory-swapの場合 が設定されていない場合、コンテナスワップはデフォルトで-memory になります 2を掛けます。--memoryの場合 および--memory-swap が同じ値に設定されている場合、これにより、コンテナーがスワップを使用できなくなります。これは、-memory-swap は、使用できるメモリとスワップの合計量ですが、-memory 使用できる物理メモリの量のみです。

    次の例に示すように、メモリやCPUなどのコンテナリソースの一部は、「docker update」コマンドを使用して動的に制御し、コンテナmariadb1のメモリをオンザフライで32Gにアップグレードできます。

    $ docker update \
        --memory 32g \
        --memory-swap 32g \
        mariadb1

    新しい仕様に合わせてmy.cnfを調整することを忘れないでください。構成管理については、次のセクションで説明します。

    構成管理

    ほとんどのMySQL/MariaDB構成パラメーターは実行時に変更できます。つまり、変更を適用するために再起動する必要はありません。詳細については、MariaDBのドキュメントページをご覧ください。 「動的:はい」でリストされているパラメーターは、MariaDBサーバーを再起動する必要なしに、変数が変更されるとすぐにロードされることを意味します。それ以外の場合は、Dockerホストのカスタム構成ファイル内にパラメーターを設定します。たとえば、mariadb3で、次のファイルに変更を加えます。

    $ vim /containers/mariadb3/conf.d/my.cnf

    次に、データベースコンテナを再起動して、変更を適用します。

    $ docker restart mariadb3

    Dockerログを確認して、コンテナーがプロセスを開始することを確認します。クラスタ全体に変更を加える場合は、一度に1つのノードでこの操作を実行します。

    バックアップ

    MariaDBイメージにはmysqldumpバイナリも付属しているため、論理バックアップの作成は非常に簡単です。 「dockerexec」コマンドを使用してmysqldumpを実行し、ホストパスに関連するファイルに出力を送信するだけです。次のコマンドは、mariadb2でmysqldumpバックアップを実行し、host2内の/ backups/mariadb2に保存します。

    $ docker exec -it mariadb2 mysqldump -uroot -p --single-transaction > /backups/mariadb2/dump.sql

    PerconaXtrabackupやMariaDBBackupなどのバイナリバックアップでは、MariaDBデータディレクトリに直接アクセスするプロセスが必要です。このツールをコンテナ内にインストールするか、マシンホストを介してインストールするか、「perconalab / percona-xtrabackup」イメージなどの専用イメージを使用してバックアップを作成し、Dockerホストの/ tmp/backup内に保存する必要があります。

    $ docker run --rm -it \
        -v /containers/mariadb2/datadir:/var/lib/mysql \
        -v /tmp/backup:/xtrabackup_backupfiles \
        perconalab/percona-xtrabackup \
        --backup --host=mariadb2 --user=root --password=mypassword

    innodb_fast_shutdownを使用してコンテナを停止することもできます 0に設定し、datadirボリュームを物理ホストの別の場所にコピーします。

    $ docker exec -it mariadb2 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
    $ docker kill -s 15 mariadb2
    $ cp -Rf /containers/mariadb2/datadir /backups/mariadb2/datadir_copied
    $ docker start mariadb2

    復元

    mysqldumpの復元は非常に簡単です。 stdinを物理ホストからコンテナにリダイレクトするだけです:

    $ docker exec -it mariadb2 mysql -uroot -p < /backups/mariadb2/dump.sql

    この「dockerexec」コマンドを使用する代わりに、適切なホスト名とポート値を使用して、標準のmysqlクライアントコマンドラインをリモートで使用することもできます。

    $ mysql -uroot -p -h127.0.0.1 -P3306 < /backups/mariadb2/dump.sql

    PerconaXtrabackupおよびMariaDBBackupの場合、事前にバックアップを準備する必要があります。これにより、バックアップが終了した時点までバックアップがロールフォワードされます。 XtrabackupファイルがDockerホストの/tmp/ backupの下にあるとしましょう。準備するには、次のようにします。

    $ docker run --rm -it \
        -v mysql-datadir:/var/lib/mysql \
        -v /tmp/backup:/xtrabackup_backupfiles \
        perconalab/percona-xtrabackup \
        --prepare --target-dir /xtrabackup_backupfiles

    Dockerホストの/tmp/ backupの下に準備されたバックアップは、新しいコンテナーまたはクラスターのMariaDBデータディレクトリとして使用できます。スタンドアロンのMariaDBコンテナーでの復元を確認したいだけだとすると、次のように実行します。

    $ docker run -d \
        --name mariadb-restored \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        -v /tmp/backup:/var/lib/mysql \
        mariadb:10.2.15

    停止とコピーのアプローチを使用してバックアップを実行した場合は、datadirを複製し、複製されたディレクトリをボリュームマップとしてMariaDB datadirに使用して、別のコンテナーで実行できます。バックアップが/backups/ mariadb2 / datadir_copiedの下にコピーされたとすると、次のコマンドを実行して新しいコンテナを実行できます。

    $ mkdir -p /containers/mariadb-restored/datadir
    $ cp -Rf /backups/mariadb2/datadir_copied /containers/mariadb-restored/datadir
    $ docker run -d \
        --name mariadb-restored \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        -v /containers/mariadb-restored/datadir:/var/lib/mysql \
        mariadb:10.2.15

    MYSQL_ROOT_PASSWORDは、その特定のバックアップの実際のルートパスワードと一致する必要があります。

    Docker上のSevereninesMySQL:データベースをコンテナ化する方法Dockerコンテナ仮想化の上でMySQLサービスを実行することを検討する際に理解する必要があるすべてを発見するホワイトペーパーをダウンロードする

    データベースバージョンのアップグレード

    アップグレードには、インプレースアップグレードと論理アップグレードの2種類があります。

    インプレースアップグレードでは、MariaDBサーバーをシャットダウンし、古いバイナリを新しいバイナリに置き換えてから、古いデータディレクトリでサーバーを起動します。開始したら、 mysql_upgradeを実行する必要があります すべてのシステムテーブルをチェックおよびアップグレードし、ユーザーテーブルもチェックするスクリプト。

    論理アップグレードでは、mysqldumpなどの論理バックアップユーティリティを使用して現在のバージョンからSQLをエクスポートし、アップグレードされたバージョンのバイナリで新しいコンテナを実行してから、SQLを新しいMySQL/MariaDBバージョンに適用します。これは、前のセクションで説明したバックアップと復元のアプローチに似ています。

    それでも、破壊的な操作を実行する前に、常にデータベースをバックアップすることをお勧めします。現在のイメージであるMariaDB10.1.33から別のメジャーバージョンにアップグレードする場合は、次の手順が必要です。mariadb3上のMariaDB10.2.15はhost3にあります。

    1. データベースをバックアップします。物理的または論理的なバックアップは重要ではありませんが、mysqldumpを使用する後者をお勧めします。

    2. アップグレードしたい最新の画像をダウンロードします:

      $ docker pull mariadb:10.2.15
    3. データベースコンテナのinnodb_fast_shutdownを0に設定します:

      $ docker exec -it mariadb3 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
    4. データベースコンテナを正常にシャットダウンします:

      $ docker kill --signal=TERM mariadb3
    5. データベースコンテナの新しいイメージを使用して新しいコンテナを作成します。新しいコンテナ名を使用する場合を除いて、残りのパラメータはそのままにしておきます(そうしないと競合します):

      $ docker run -d \
              --name mariadb3-new \
              --hostname mariadb3.weave.local \
              --net weave \
              --publish "3306:3306" \
              --publish "4444" \
              --publish "4567" \
              --publish "4568" \
              $(weave dns-args) \
              --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
              --volume /containers/mariadb3/datadir:/var/lib/mysql \
              --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
              mariadb:10.2.15 \
              --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
              --wsrep_sst_auth="root:PM7%[email protected]^1" \
              --wsrep_node_address=mariadb3.weave.local
    6. mysql_upgradeスクリプトを実行します:

      $ docker exec -it mariadb3-new mysql_upgrade -uroot -p
    7. エラーが発生しなかった場合は、古いコンテナmariadb3(新しいコンテナはmariadb3-new)を削除します。

      $ docker rm -f mariadb3
    8. それ以外の場合、アップグレードプロセスが途中で失敗した場合は、前のコンテナにフォールバックできます:

      $ docker stop mariadb3-new
      $ docker start mariadb3

    メジャーバージョンのアップグレードは、マイナーバージョンのアップグレードと同様に実行できますが、MySQL/MariaDBは以前のバージョンからのメジャーアップグレードのみをサポートしていることに注意する必要があります。 MariaDB 10.0を使用していて、10.2にアップグレードする場合は、最初にMariaDB 10.1にアップグレードしてから、MariaDB10.2への別のアップグレード手順を実行する必要があります。

    メジャーバージョン間で導入および非推奨の構成変更に注意してください。

    フェイルオーバー

    ガレラでは、すべてのノードがマスターであり、同じ役割を果たします。図のProxySQLでは、Galera Clusterで実行されているプラ​​イマリコンポーネントがある限り(つまり、ノードの大部分が稼働している限り)、このゲートウェイを通過する接続は自動的にフェイルオーバーされます。 ProxySQLは接続を他の使用可能なノードにリダイレクトするだけなので、1つのデータベースノードがダウンしても、アプリケーションは違いに気づきません。

    アプリケーションがProxySQLをバイパスしてMariaDBに直接接続する場合、データベースノードが次の条件を満たす場合は、次に使用可能なノードをポイントして、アプリケーション側でフェイルオーバーを実行する必要があります。

    • ステータスwsrep_local_state_comment 同期されています( wsrep_sst_method の場合にのみ、「非同期/ドナー」状態も可能です。 xtrabackup、xtrabackup-v2、またはmariabackupです。
    • ステータスwsrep_cluster_status プライマリです。

    ガレラでは、利用可能なノードは、上記のステータスが確認されるまで、正常であることを意味しません。

    スケールアウト

    スケールアウトするには、同じネットワークに新しいコンテナーを作成し、その特定のホスト上の既存のコンテナーに同じカスタム構成ファイルを使用できます。たとえば、host3に4番目のMariaDBコンテナーを追加するとします。次の図に示すように、mariadb3用にマウントされた同じ構成ファイルを使用できます。

    host3で次のコマンドを実行して、スケールアウトします。

    $ docker run -d \
            --name mariadb4 \
            --hostname mariadb4.weave.local \
            --net weave \
            --publish "3306:3307" \
            --publish "4444" \
            --publish "4567" \
            --publish "4568" \
            $(weave dns-args) \
            --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
            --volume /containers/mariadb4/datadir:/var/lib/mysql \
            --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
            mariadb:10.2.15 \
            --wsrep_cluster_address=gcomm://mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local,mariadb4.weave.local \
            --wsrep_sst_auth="root:PM7%[email protected]^1" \
            --wsrep_node_address=mariadb4.weave.local

    コンテナが作成されると、クラスタに参加してSSTを実行します。外部またはWeaveネットワークの外部のポート3307、またはホスト内またはWeaveネットワーク内のポート3306からアクセスできます。 mariadb0.weave.localをクラスターアドレスに含める必要はなくなりました。クラスターがスケールアウトされたら、管理コンソールを介して新しいMariaDBコンテナーをProxySQL負荷分散セットに追加する必要があります。

    $ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
    mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (10,'mariadb4.weave.local',3306);
    mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (20,'mariadb4.weave.local',3306);
    mysql> LOAD MYSQL SERVERS TO RUNTIME;
    mysql> SAVE MYSQL SERVERS TO DISK;

    2番目のProxySQLインスタンスで上記のコマンドを繰り返します。

    最後に、最後のステップとして(ProxySQLで "SAVE .. TO DISK"ステートメントを既に実行している場合は、この部分をスキップできます)、proxysql.cnfに次の行を追加して、host1とhost2でコンテナーを再起動しても永続的にします。

    $ vim /containers/proxysql1/proxysql.cnf # host1
    $ vim /containers/proxysql2/proxysql.cnf # host2

    そして、mysql_serverディレクティブの下にmariadb4関連の行を追加します:

    mysql_servers =
    (
            { address="mariadb1.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
            { address="mariadb2.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
            { address="mariadb3.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
            { address="mariadb4.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
            { address="mariadb1.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
            { address="mariadb2.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
            { address="mariadb3.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
            { address="mariadb4.weave.local" , port=3306 , hostgroup=20, max_connections=100 }
    )

    ファイルを保存すると、次のコンテナの再起動に問題がないはずです。

    スケールダウン

    スケールダウンするには、コンテナを正常にシャットダウンするだけです。最適なコマンドは次のとおりです。

    $ docker kill -s 15 mariadb4
    $ docker rm -f mariadb4

    データベースノードがクラスターを正常に終了しなかった場合、それはスケールダウンの一部ではなく、クォーラムの計算に影響を与えることを忘れないでください。

    ProxySQLからコンテナを削除するには、両方のProxySQLコンテナで次のコマンドを実行します。たとえば、proxysql1:

    $ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
    mysql> DELETE FROM mysql_servers WHERE hostname="mariadb4.weave.local";
    mysql> LOAD MYSQL SERVERS TO RUNTIME;
    mysql> SAVE MYSQL SERVERS TO DISK;

    次に、proxysql.cnf内の対応するエントリを削除するか、そのままにしておくことができます。とにかく、ProxySQLの観点からはオフラインとして検出されます。

    概要

    Dockerを使用すると、MySQLまたはMariaDBサーバーを処理する従来の方法とは少し異なります。 Galera Clusterのようなステートフルサービスの処理は、ステートレスアプリケーションほど簡単ではなく、適切なテストと計画が必要です。

    このトピックに関する次のブログでは、オーケストレーションツールを使用せずにDockerでGaleraClusterを実行することの長所と短所を評価します。


    1. SQL Server(T-SQL)でテーブルを作成する

    2. 異なるデータ型で外部キーを設定する

    3. PostgreSQL外部キーが存在しない、継承の問題?

    4. Spring Data JPA Auditingが@Modifyingアノテーションを使用したJpaRepository更新メソッドで機能しないのはなぜですか?