LoginSignup
21
19

More than 5 years have passed since last update.

OpenShift/Kubernetesクラスタのバックアップと復元

Last updated at Posted at 2018-02-22

OpenShift / Kubernetesクラスタのバックアップと復元

今回は、OpenShiftのドキュメントから、クラスタのバックアップと復元について紹介します。

ディザスタリカバリーを想定したドキュメントですが、OpenShiftやKubernetesのバージョンをアップデートするとき、新しいクラスタを立ててから古いクラスタを削除するというBlueGreen的なアプローチで行うときにもこの手順が参考になります。

概要

Kubernetesは(OpenShiftも)、クラスタの状態は全てetcdに格納されています。
クラスタのバックアップと復元というのは、etcdのバックアップと復元を意味します。
なので、このドキュメントの大部分はetcdの復元方法について記載されています。

しかし、OpenShiftの場合、oc export allでProject(namespace)の全部をエクスポートできるので、それでバックアップを取ることもできます。
Kubernetesでも、kubectl get --exportを駆使すれば同じようにyamlでクラスタをエクスポートできます。
「クラスタのバックアップと復元」の方法として、大きく以下の二つがあるわけです。

  • [低レベル方式] 普段etcdをバックアップしておく。Kubernetesクラスタ復元の際は、まずetcdを復元し、クラスタを再インストールする復元したetcdを参照する新規クラスタを立てる
  • [高レベル方式] クラスタの状態をyamlにexportしてバックアップしておく。Kubernetes復元の際は、新規Kubernetesクラスタを立てて、そこにバックアップしたyamlをインポートする

Kubernetesだと、exportするAPIオブジェクトの種別が増えたり減ったりするかもしれないですし、低レベル方式のほうが安心感がありますね。
(ただ、etcdのバックアップと復元は、KubernetesノードのIPが変わると復元したクラスタの動作がうまく行かなかったりしたので、不安が残る)

OpenShift Container Platformでは、クラスタレベルでのバックアップ(現在の状態を隔離されたストレージに保存)し、復元(隔離されたストレージからクラスタの状態を再現する)ことができます。
また、補助的なものとして、プロジェクトごとのバックアップも可能です。
「クラスタの状態」を構成するものは以下の4つです。

  • etcdのデータ
  • APIオブジェクト
  • イメージレジストリのストレージ
  • Volumeのストレージ

ここでは、永続ストレージのバックアップと復元については触れません。ストレージの実装に依存するからです。
しかし、アプリケーションデータのバックアップをどのように行うかの一般的な例を紹介します。

Kubernetes上で動いているアプリケーションはPVを通して永続ストレージを使用している場合があり、
その場合はもちろん、永続ストレージも復元する必要があります。

永続ストレージは、バックエンドの製品ごとに様々なバックアップ方法があるわけですが、
このドキュメントでは「コンテナの永続状態はアタッチされているボリュームにのみ保存されているはず」という観点から、
デプロイ設定のPVのパスに対してrsyncでバックアップと復元を行なっています。

! 注意
このドキュメントは、アプリケーションとOpenShiftクラスタのバックアップ方法について、一般論的に記載したものです。
様々な特殊な要件について考慮されているわけではありません。
実際には、そのような要件も考慮して、独自の完全なバックアップ手順を確率しなければなりません。
データの紛失を防ぐために、必要な予防措置を取ってください。

etcdのバックアップには、ストレージボリュームの参照情報が含まれていることに注意してください。
etcdをバックアップから復元すると、OpenShiftは、バックアップ時のpodをノード上で起動し、また同じストレージをアタッチしようとします。
これは実際、OpenShiftからノードを削除してから新しいノードを追加したときの挙動と変わりません。
ノードにアタッチされていた全てのストレージは、podがどのノードに再スケジュールされても再度podにアタッチされます。

! 注意
バックアップと復元は、特に保証のあるプロセスではなく、自分のデータを保全する責任はユーザーにあります。

前提条件

  1. 復元処理は完全な再インストールを伴うので、最初のインストール時に使用したすべてのファイルを保存しておいてください。 これには、以下のものが含まれます。
    • ~/.config/openshift/installer.cfg.yml (クイックインストールの場合)
    • Ansibleのplaybookとインベントリファイル (アドバンスドインストールの場合)
    • /etc/yum.repos.d/ose.repo (ネットワークが繋がらない環境でインストールした場合)
  2. インストールした後に何か追加処理を実施した場合、その手順を再現できるようにバックアップを取っておいてください。インストーラーに含まれていないインストール処理が実施されているかもしれません。例えば、OpenShiftの制御下にない外部サービスの変更や、監視エージェントのような追加サービスのインストールなどです。さらに、アドバンスドインストールでもサポートされていないOpenShiftの設定を変更した場合も気をつける必要があります。例えば、複数の認証方法のサポートなどです。
  3. 必要なコマンドラインツールをパッケージからインストールしておきます。
   yum install etcd

4: コンテナベースのインストーラーを使っている場合は、代わりにetcdのイメージをpullしておきます。

   docker pull rhel7/etcd

etcdのデータディレクトリ(以下のセクションでの$ETCD_DATA_DIR)は、どのようにetcdをデプロイしたかでパスが変わってくるので注意してください。

デプロイの種類 データディレクトリ
all-in-one cluster /var/lib/origin/openshift.local.etcd
外部etcd(masterや他のホストにある場合) /var/lib/etcd

! 注意
組み込みのetcdは、OpenShift Container Platform 3.7からサポートされなくなりました。
詳しくは組み込みのetcdを外部etcdに移行するを参照してください。

OpenShift Container Platformの3.6までは、OpenShiftのmasterに組み込まれたetcdでOpenShiftのクラスタを構築することができ、別途etcdクラスタを用意しなくていいというオプションがありました。
OpenShift 3.7からはそのオプションはサポートされなくなり、OpenShiftと別にetcdクラスタを用意する必要があります。
(OpenShiftのインストーラーは、etcdクラスタもいっしょに構築できるのでインストール時にはあまり意識しないかもしれませんが)

組み込みのetcdの場合、etcdのデータディレクトリが普通のetcdと違う場所にあるので、気をつけましょうという記載です。

クラスタのバックアップ

Masterのバックアップ

  1. 各masterにある証明書を全て保存してください。

    cd /etc/origin/master
    tar cf /tmp/certs-and-keys-$(hostname).tar *.key *.crt
    

etcdのバックアップ

  1. etcdが一つ以上のホストで動作している場合は、それぞれのetcdを以下のように停止してください。

    sudo systemctl stop etcd
    

    厳密には、このステップは必須というわけではないですが、こうしておくとetcdのデータが同期された状態になります。

  2. etcdのバックアップを作成する

    以下コマンドで、etcdのバックアップを作成します。

    etcdctl backup \
        --data-dir $ETCD_DATA_DIR \
        --backup-dir $ETCD_DATA_DIR.bak
    

    ! メモ
    etcdクラスタが複数のホストで構成されている場合も、各インスタンスは定期的にデータを同期しているので、いずれか
    のホストでバックアップを作成すれば大丈夫です。

    ! メモ:
    コンテナを使ってインストールしている場合、コンテナ内のetcdctlを実行するためにdocker execコマンドを使用します。

  3. dbファイルを作成したバックアップディレクトリにコピーします

    cp "$ETCD_DATA_DIR"/member/snap/db "$ETCD_DATA_DIR.bak"/member/snap/db
    
  • etcdのv3からは、(v3形式のデータは) snapshotコマンドでオンラインでバックアップと復元ができる
  • OpenShiftのv3.7からは、etcdのv3形式のデータが必須

ことから、snapshotでバックアップと復元をしても大丈夫そうです。
ただし、flannelなど、一部アプリケーションはv2形式のデータモデルを使用することがあるので、etcd v2とv3、複数形式のデータモデルが混在している場合、backupコマンドであれば両方の形式のバックアップが取れるので安全かもしれません。

レジストリの証明書をバックアップする

  1. レジストリの全証明書を全てのmasterおよびノードホストで保存します

    cd /etc/docker/certs.d/
    tar cf /tmp/docker-registry-certs-$(hostname).tar *
    

    ! メモ
    セキュアな外部レジストリを使用している場合、podを実行するには、イメージをpullしたりpushしたりする全てのホストでレジストリの証明書を信頼しなければなりません

クラスタの復元(etcdがシングルノードの場合)

OpenShiftのクラスタを復元するには、

  1. OpenShiftを再インストールします。これは、前回インストールした時と同じ方法で実施してください。
  2. インストール後の独自処理がある場合は、それを実行します。
  3. masterノード全てで、証明書と鍵を復元します。

    cd /etc/origin/master
    tar xvf /tmp/certs-and-keys-$(hostname).tar
    
  4. etcdのバックアップを復元します。

    mv $ETCD_DATA_DIR $ETCD_DATA_DIR.orig
    cp -Rp $ETCD_DATA_DIR.bak $ETCD_DATA_DIR
    chcon -R --reference $ETCD_DATA_DIR.orig $ETCD_DATA_DIR
    chown -R etcd:etcd $ETCD_DATA_DIR
    
  5. シングルノードのetcdクラスタを、--force-new-clusterオプションをつけて新しく作成します。/etc/etcd/etcd.confを使うか、一時的にsystemdのユニットファイルを書き換えてetcdを通常通り開始します。つまり、/usr/lib/systemd/system/etcd.serviceで以下のように--force-new-clusterを追加します。

    sed -i '/ExecStart/s/"$/  --force-new-cluster"/' /usr/lib/systemd/system/etcd.service
    systemctl show etcd.service --property ExecStart --no-pager
    
    # -> ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --force-new-cluster"
    

    それから、etcdを再起動します。

    systemctl daemon-reload
    systemctl start etcd
    
  6. etcdが正しく起動したら、/usr/lib/systemd/system/etcd.serviceを再度書き換え、--force-new-clusterオプションを削除しておきます。

    sed -i '/ExecStart/s/ --force-new-cluster//' /usr/lib/systemd/system/etcd.service
    systemctl show etcd.service --property ExecStart --no-pager
    
    # -> ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd"
    
  7. etcdを再起動し、etcdクラスタが正しく実行されていることとOpenShiftの設定が正しく表示されることを確認してください。

    systemctl daemon-reload
    systemctl restart etcd
    

クラスタの復元(etcdがマルチノードの場合)

外部のetcdホストを使用している場合、まず新しいシングルノードのetcdクラスタを作成してバックアップを復元する必要があります。
etcdをマルチノードで構成するのであれば、そのあとで新しいetcdメンバーを一つずつ追加します。

最初のetcdメンバーとなるシステムを選び、そこでバックアップと設定を復元します。

  1. 次のコマンドをetcdホストで実行します

    ETCD_DIR=/var/lib/etcd/
    mv $ETCD_DIR /var/lib/etcd.orig
    cp -Rp /var/lib/origin/etcd-backup-<timestamp>/ $ETCD_DIR
    chcon -R --reference /var/lib/etcd.orig/ $ETCD_DIR
    chown -R etcd:etcd $ETCD_DIR
    
  2. /etc/etcd/etcd.confをバックアップから、または.rpmsaveからリストアします。

  3. 環境に応じて、次セクションのコンテナ化されたetcdのデプロイまたは非コンテナ環境でのetcdのデプロイのどちらかを実行します。

OpenShiftのインストールでは、Atomic Hostにインストールする場合など、etcdをコンテナで動かす(docker run registry.access.redhat.com/rhel7/etcd)オプションがあります。
以下では、コンテナ化されたetcdとコンテナでないetcdの2パターンの記載が続きますが、コマンド名など細部が変わるくらいで手順としてはほぼ同じです。

コンテナ化されたetcdのデプロイ

  1. etcdの--force-new-clusterオプションを使って、新しいシングルノードクラスタを作成します。/etc/etcd/etcd.confまたはユニットファイルの書き換えでさらに複雑なコマンドを使うこともできます。以下のように、/etc/systemd/system/etcd_container.serviceを編集して--force-new-clusterオプションを追加します。

    sed -i '/ExecStart=/s/$/  --force-new-cluster/' /etc/systemd/system/etcd_container.service
    
    # -> ExecStart=/usr/bin/docker run --name etcd --rm -v \
    # -> /var/lib/etcd:/var/lib/etcd:z -v /etc/etcd:/etc/etcd:ro --env-file=/etc/etcd/etcd.conf \
    # -> --net=host --entrypoint=/usr/bin/etcd rhel7/etcd:3.1.9  --force-new-cluster
    

    それから、etcdを再起動します。

    systemctl daemon-reload
    systemctl start etcd_container
    
  2. etcdサービスが正しく起動したのを確認したら、再度/etc/systemd/system/etcd_container.serviceを編集して、--force-new-clusterオプションを削除します。

    sed  -i '/ExecStart=/s/ --force-new-cluster//' /etc/systemd/system/etcd_container.service
    
    # -> ExecStart=/usr/bin/docker run --name etcd --rm -v /var/lib/etcd:/var/lib/etcd:z -v \
    # -> /etc/etcd:/etc/etcd:ro --env-file=/etc/etcd/etcd.conf --net=host \
    # -> --entrypoint=/usr/bin/etcd rhel7/etcd:3.1.9
    
  3. etcdを再起動し、正しく起動すること、OpenShiftの設定が正しく表示されることを確認します。

    systemctl daemon-reload
    systemctl restart etcd_container
    etcdctl --cert-file=/etc/etcd/peer.crt \
        --key-file=/etc/etcd/peer.key \
        --ca-file=/etc/etcd/ca.crt \
        --peers="https://172.16.4.18:2379,https://172.16.4.27:2379" \
        ls /
    
  4. etcdのクラスタにメンバーを追加するときは、etcdメンバーを追加するを実施してください。そうではなく、シングルノードのetcdでよいのであれば、OpenShiftをオンラインに戻すに進んでください。

非コンテナ環境でのetcdのデプロイ

  1. etcdの--force-new-clusterオプションを使って、新しいシングルノードクラスタを作成します。/etc/etcd/etcd.confまたはユニットファイルの書き換えでさらに複雑なコマンドを使うこともできます。

    そのために、/usr/lib/systemd/system/etcd.serviceを編集し、--force-new-clusterを追加します。

    /usr/lib/systemd/system/etcd.service
    # sed -i '/ExecStart/s/"$/  --force-new-cluster"/' /usr/lib/systemd/system/etcd.service
    # systemctl show etcd.service --property ExecStart --no-pager
    
    ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --force-new-cluster"
    
  2. それから、etcdを再起動します。

    systemctl daemon-reload
    systemctl start etcd
    
  3. etcdサービスが正しく起動したのを確認したら、再度/usr/lib/systemd/system/etcd.serviceを編集して、--force-new-clusterオプションを削除します。

    /usr/lib/systemd/system/etcd.service
    # sed -i '/ExecStart/s/ --force-new-cluster//' /usr/lib/systemd/system/etcd.service
    # systemctl show etcd.service --property ExecStart --no-pager
    
    ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd"
    
  4. etcdを再起動し、正しく起動すること、OpenShiftの設定が正しく表示されることを確認します。

    systemctl daemon-reload
    systemctl restart etcd_container
    etcdctl --cert-file=/etc/etcd/peer.crt \
        --key-file=/etc/etcd/peer.key \
        --ca-file=/etc/etcd/ca.crt \
        --peers="https://172.16.4.18:2379,https://172.16.4.27:2379" \
        ls /
    
  5. もし、クラスタにetcdメンバーを追加するなら、etcdメンバーを追加するを実施してください。そうではなく、シングルノードのetcdでよいのであれば、OpenShiftをオンラインに戻すに進んでください。

etcdメンバーを追加する

メンバーの追加は、etcdctl member addを実行してから、対応するetcdサービスを立ち上げる、という順序で実行します。
あと、そのときは「一つmember add」-> 「一つetcd起動」を一個ずつやっていくのがベストプラクティスとされています。
クラスタが機能するために過半数のetcdノードが必要で、1つのetcdノードに対してmember addした状態だと、実際に新メンバーがオンラインになるまで過半数の合意が取れなくなるという理由です。

etcdメンバーをクラスタに追加するには、まず上記で起動した最初のメンバーが、peerURLslocalhostで登録されているのを修正します。

  1. 最初のメンバーのメンバーIDをmember listで取得します。

    etcdctl --cert-file=/etc/etcd/peer.crt \
        --key-file=/etc/etcd/peer.key \
        --ca-file=/etc/etcd/ca.crt \
        --peers="https://172.18.1.18:2379,https://172.18.9.202:2379,https://172.18.0.75:2379" \
        member list
    
  2. etcdctl member updateコマンドに前ステップで取得したメンバーIDを渡して、peerURLsの値を更新します。

    etcdctl --cert-file=/etc/etcd/peer.crt \
        --key-file=/etc/etcd/peer.key \
        --ca-file=/etc/etcd/ca.crt \
        --peers="https://172.18.1.18:2379,https://172.18.9.202:2379,https://172.18.0.75:2379" \
        member update 511b7fb6cc0001 https://172.18.1.18:2380
    

    または、curlを使うこともできます。

    curl --cacert /etc/etcd/ca.crt \
    --cert /etc/etcd/peer.crt \
    --key /etc/etcd/peer.key \
    https://172.18.1.18:2379/v2/members/511b7fb6cc0001 \
    -XPUT -H "Content-Type: application/json" \
    -d '{"peerURLs":["https://172.18.1.18:2380"]}'
    
  3. member listコマンドを再実行して、peerURLsにlocalhostが含まれていないことを確認してください。

  4. 終わったら、クラスタに新しいメンバーを一つずつ追加していきます。

    ! 注意
    etcdのメンバーは、クラスタに追加してから起動する、という手順を一つずつ、確実に実施していく必要があります。
    新しいメンバーがetcdのクラスタに追加されたら、peerURLsのリストはその時点で新しいメンバーを含めた正しいものになっていなければなりません。そのため、peerURLsはメンバーが追加されるたびに一つずつ大きくなっていく形になります。
    以下の手順で記載されている通り、新しいメンバーを起動する際にetcd.confに設定する値は、etcdctl member addコマンドを実行したときに出力されます。

    1. etcdのメンバーを追加するには、システムのetcd.confにある値を参照して、etcdctl member addを発行します。

      etcdctl --cert-file=/etc/etcd/peer.crt \
          --key-file=/etc/etcd/peer.key \
          --ca-file=/etc/etcd/ca.crt \
          --peers="https://172.16.4.18:2379,https://172.16.4.27:2379" \
          member add 10.3.9.222 https://172.16.4.27:2380
      
      Added member named 10.3.9.222 with ID 4e1db163a21d7651 to cluster
      
      ETCD_NAME="10.3.9.222"
      ETCD_INITIAL_CLUSTER="10.3.9.221=https://172.16.4.18:2380,10.3.9.222=https://172.16.4.27:2380"
      ETCD_INITIAL_CLUSTER_STATE="existing"
      
    2. メンバーのシステム自身にある/etc/etcd/etcd.confファイルを編集し、ファイル内の設定とetcdctl member addコマンドで出力された設定が一致するようにします。 1

    3. 新しいetcdメンバーを起動します。

      rm -rf /var/lib/etcd/member
      systemctl enable etcd
      systemctl start etcd
      
    4. サービスが正しく開始され、etcdクラスタがhealtyになっていることを確認します。

      etcdctl --cert-file=/etc/etcd/peer.crt \
          --key-file=/etc/etcd/peer.key \
          --ca-file=/etc/etcd/ca.crt \
          --peers="https://172.16.4.18:2379,https://172.16.4.27:2379" \
          member list
      
      51251b34b80001: name=10.3.9.221 peerURLs=https://172.16.4.18:2380 clientURLs=https://172.16.4.18:2379
      d266df286a41a8a4: name=10.3.9.222 peerURLs=https://172.16.4.27:2380 clientURLs=https://172.16.4.27:2379
      
      etcdctl --cert-file=/etc/etcd/peer.crt \
          --key-file=/etc/etcd/peer.key \
          --ca-file=/etc/etcd/ca.crt \
          --peers="https://172.16.4.18:2379,https://172.16.4.27:2379" \
          cluster-health
      
      cluster is healthy
      member 51251b34b80001 is healthy
      member d266df286a41a8a4 is healthy
      
    5. このプロセスを、次にクラスタに追加するメンバーにも繰り返します。

  5. 全てのetcdメンバーを追加し終わったら、OpenShiftをオンラインに戻すに進んでください。

新しいetcdホストの追加

etcdメンバーがエラーになっても、まだ過半数のメンバーが実行されているのであれば、その残ったメンバーを使ってダウンタイムなしでetcdメンバーを追加できます。

推奨されるクラスタサイズ

etcdのフォールトトレランスは、奇数個のetcdホストを持つことで実現されています。
奇数個にしてもクオラムに必要なホスト数は変わりませんが、エラーで落ちても大丈夫なホスト数が増えます。
例えば、クラスタが3台で構成されている場合、クオラムは2で、エラーで落ちても大丈夫な台数は1です。
これは、2つのメンバーがhealthyであれば、クラスタの動作が保証されるということです。

プロダクション環境では3台のetcdホストでクラスタを構築することを推奨します。

! 注意
以下の手順は、/etc/etcdの設定のバックアップがあることを前提にしています。

  1. もし新しいetcdメンバーがOpenShiftのノードとしても実行される場合、希望する数のホストをクラスターに追加するを参照してください。この手順ではホストを一つ追加しますが、複数のホストを追加する場合はそれぞれのホストで全てのステップを繰り返してください。
  2. 生き残っているノードでetcdとiptablesをアップグレードします。

    yum update etcd iptables-services
    

    etcd-2.3.7-4.el7.x86_64かそれ以上のバージョンのetcdがインストールされ、また全てのホストでetcdのバージョンが同じになっていることを確認します。

  3. etcdとiptablesを新しいホストでインストールします。

    yum install etcd iptables-services
    

    etcd-2.3.7-4.el7.x86_64かそれ以上のバージョンのetcdがインストールされ、新しいホストで、既存のetcdと同じバージョンがインストールされていることを確認します。

  4. クラスタの設定を変更する前に、必ずetcdデータのバックアップを実行してください。

  5. エラーになっているetcdメンバーを置き換える場合は、新しいetcdメンバーを追加する前にそのetcdメンバーを削除してください。

    etcdctl -C https://<surviving host IP>:2379 \
    --ca-file=/etc/etcd/ca.crt     \
    --cert-file=/etc/etcd/peer.crt     \
    --key-file=/etc/etcd/peer.key cluster-health
    
    etcdctl -C https://<surviving host IP>:2379 \
    --ca-file=/etc/etcd/ca.crt     \
    --cert-file=/etc/etcd/peer.crt     \
    --key-file=/etc/etcd/peer.key member remove <failed member identifier>
    

    そして、エラーになったetcdを停止します。

    systemctl stop etcd
    
  6. 新しいホストで、適切なiptablesのルールを追加します。

    systemctl enable iptables.service --now
    iptables -N OS_FIREWALL_ALLOW
    iptables -t filter -I INPUT -j OS_FIREWALL_ALLOW
    iptables -A OS_FIREWALL_ALLOW -p tcp -m state \
    --state NEW -m tcp --dport 2379 -j ACCEPT
    iptables -A OS_FIREWALL_ALLOW -p tcp -m state \
    --state NEW -m tcp --dport 2380 -j ACCEPT
    iptables-save > /etc/sysconfig/iptables
    
  7. 新しいetcdホストに必要な証明書を作成します。既存のetcdホストで以下を実行します。

    1. /etc/etcd/ca/ディレクトリのバックアップを取ってください。
    2. 証明書を生成するための環境変数と作業ディレクトリを用意し、PREFIXディレクトリが作成されていない場合は作成します。

      cd /etc/etcd
      export NEW_ETCD="<NEW_HOST_NAME>"
      
      export CN=$NEW_ETCD
      export SAN="IP:<NEW_HOST_IP>"
      export PREFIX="./generated_certs/etcd-$CN/"
      
    3. $PREFIXディレクトリを作成します。

      mkdir -p $PREFIX
      
    4. server.csrとserver.crt、二つの証明書を作成します。

      openssl req -new -keyout ${PREFIX}server.key \
      -config ca/openssl.cnf \
      -out ${PREFIX}server.csr \
      -reqexts etcd_v3_req -batch -nodes \
      -subj /CN=$CN
      
      openssl ca -name etcd_ca -config ca/openssl.cnf \
      -out ${PREFIX}server.crt \
      -in ${PREFIX}server.csr \
      -extensions etcd_v3_ca_server -batch
      
    5. peer.csrとpeer.crt、二つの証明書を作成します。

      openssl req -new -keyout ${PREFIX}peer.key \
      -config ca/openssl.cnf \
      -out ${PREFIX}peer.csr \
      -reqexts etcd_v3_req -batch -nodes \
      -subj /CN=$CN
      
      openssl ca -name etcd_ca -config ca/openssl.cnf \
      -out ${PREFIX}peer.crt \
      -in ${PREFIX}peer.csr \
      -extensions etcd_v3_ca_peer -batch
      
    6. etcd.confとca.crtをコピーし、ディレクトリをアーカイブします。

      cp etcd.conf ${PREFIX}
      cp ca.crt ${PREFIX}
      tar -czvf ${PREFIX}${CN}.tgz -C ${PREFIX} .
      
    7. このファイルを、新しいetcdホストに転送します。

      scp ${PREFIX}${CN}.tgz  $CN:/etc/etcd/
      
  8. 引き続き、既存のホスト上で作業し、新しいホストをクラスタに追加します。

    1. 新しいホストをクラスタに追加します。

      export ETCD_CA_HOST="<SURVIVING_ETCD_HOSTNAME>"
      export NEW_ETCD="<NEW_ETCD_HOSTNAME>"
      export NEW_ETCD_IP="<NEW_HOST_IP>"
      
      etcdctl -C https://${ETCD_CA_HOST}:2379 \
      --ca-file=/etc/etcd/ca.crt     \
      --cert-file=/etc/etcd/peer.crt     \
      --key-file=/etc/etcd/peer.key member add ${NEW_ETCD} https://${NEW_ETCD_IP}:2380
      
      ETCD_NAME="<NEW_ETCD_HOSTNAME>"
      ETCD_INITIAL_CLUSTER="<NEW_ETCD_HOSTNAME>=https://<NEW_HOST_IP>:2380,<SURVIVING_ETCD_HOST>=https:/<SURVIVING_HOST_IP>:2380
      ETCD_INITIAL_CLUSTER_STATE="existing"
      

      etcdctl member addの出力にある三つの環境変数をコピーしておいてください。後で使用します。

    2. 新しいホストの上で、転送された設定データを解凍し、パーミッションを設定してください。

      tar -xf /etc/etcd/<NEW_ETCD_HOSTNAME>.tgz -C /etc/etcd/ --overwrite
      chown -R etcd:etcd /etc/etcd/*
      
    3. 新しいホストで、全てのetcdデータを削除します。

      rm -rf /var/lib/etcd/member
      chown -R etcd:etcd /var/lib/etcd
      
  9. 新しいホストのetcd.confは、

    1. 前の手順で作った値で次のものを置き換えます
    * ETCD_NAME
    * ETCD_INITIAL_CLUSTER
    * ETCD_INITIAL_CLUSTER_STATE
    
    以下のものは、IPアドレスを`NEW_ETCD`の値で置き換えます。
    
    * ETCD_LISTEN_PEER_URLS
    * ETCD_LISTEN_CLIENT_URLS
    * ETCD_INITIAL_ADVERTISE_PEER_URLS
    * ETCD_ADVERTISE_CLIENT_URLS
    
    エラーになったetcdメンバーを置き換える場合、そのメンバーをetcdの設定から削除してください。
    
  10. etcdを新しいホストで開始します。

    systemctl enable etcd --now
    
  11. 新しいメンバーがちゃんと追加されていることを確認します。

    etcdctl -C https://${ETCD_CA_HOST}:2379 --ca-file=/etc/etcd/ca.crt \
    --cert-file=/etc/etcd/peer.crt     \
    --key-file=/etc/etcd/peer.key cluster-health
    
  12. Masterの設定を全てのmasterホストで更新し、新しいetcdホストをポイントするように修正します。

    1. クラスタ内の全てのmasterで、/etc/origin/master/master-config.ymlを編集する
    2. etcdClientInfoセクションを見つける
    3. 新しいetcdホストを、urlsリストに加える
    4. 失敗したetcdホストを入れ替える場合は、リストからそれを削除する

      すべてのmasterで以下を実行してください。

      systemctl restart atomic-openshift-master-api atomic-openshift-master-controllers
      

これで、etcdメンバーを追加する手順は完了です。

OpenShiftをオンラインに戻す

全てのOpenShiftのmasterで、masterとノードの設定をバックアップからリストアし、関連する全てのサービスをenable、retartします。

cp /etc/sysconfig/atomic-openshift-master-api.rpmsave /etc/sysconfig/atomic-openshift-master-api
cp /etc/sysconfig/atomic-openshift-master-controllers.rpmsave /etc/sysconfig/atomic-openshift-master-controllers
cp /etc/origin/master/master-config.yaml.<timestamp> /etc/origin/master/master-config.yaml
cp /etc/origin/node/node-config.yaml.<timestamp> /etc/origin/node/node-config.yaml
systemctl enable atomic-openshift-master-api
systemctl enable atomic-openshift-master-controllers
systemctl enable atomic-openshift-node
systemctl start atomic-openshift-master-api
systemctl start atomic-openshift-master-controllers
systemctl start atomic-openshift-node

ノードのほうは、node-config.yamlをバックアップからリストアし、atomic-openshift-nodeサービスをenable、restartしてください。

cp /etc/origin/node/node-config.yaml.<timestamp> /etc/origin/node/node-config.yaml
systemctl enable atomic-openshift-node
systemctl start atomic-openshift-node

これで、OpenShiftクラスタはオンラインに戻るはずです。

プロジェクトのバックアップ

将来的には、OpenShiftでプロジェクトのバックアップと復元を行う機能をサポートする予定です。

今のところは、プロジェクトレベルのAPIオブジェクトをバックアップするには、保存したいオブジェクトに対してoc exportをそれぞれ実行してください。
例えば、frontendのデプロイ設定をYAML形式で保存するには、以下のようにします。

oc export dc frontend -o yaml > dc-frontend.yaml

プロジェクトの全て(namespacesやprojectsのようなクラスタレベルのオブジェクト以外)をバックアップするには、以下のようにします。

oc export all -o yaml > project.yaml

Role Bindings

ときどき、プロジェクトでロールバインディングのポリシーをカスタマイズしている場合があります。例えば、プロジェクトの管理者が他のユーザーに特定のロールを与え、プロジェクトにアクセスできるようにするときなどです。

このようなロールバインディングは、以下のようにエクスポートできます。

oc get rolebindings -o yaml --export=true > rolebindings.yaml

Service Accounts

カスタムのService Accountがある場合は、それをエクスポートする必要があります。

oc get serviceaccount -o yaml --export=true > serviceaccount.yaml

Secrets

独自のSecretsを使用している場合、例えば、ソースコード管理システムの秘匿情報(SSHの公開鍵/ユーザー名とパスワード)などをSecretsで提供している場合、それらをエクスポートしなければなりません。

oc get secret -o yaml --export=true > secret.yaml

Persistent Volume Claims

プロジェクト内のアプリケーションが、Persisitent Volume Claim(PVC)を使ってPersistent Volume使用しているなら、そのPVCもバックアップする必要があります。

oc get pvc -o yaml --export=true > pvc.yaml

プロジェクトの復元

プロジェクトを復元するには、プロジェクトを再作成し、バックアップ時にエクスポートした全てのオブジェクトを再作成します。

oc new-project myproject
oc create -f project.yaml
oc create -f secret.yaml
oc create -f serviceaccount.yaml
oc create -f pvc.yaml
oc create -f rolebindings.yaml

! メモ
いくつかのリソースは作成に失敗する可能性があります(podやデフォルトのService Account)

アプリケーションデータのバックアップ

クラスタの状態が戻っても、アプリケーションの永続データをPVで保存している場合、そのPVも復旧しなければなりません。

PVのバックエンドとなるネットワークストレージ側でバックアップをとることも必要ですが、ここでは、コンテナに対してoc rsyncでrsyncを使う方法が紹介されています。
(Kubernetesの場合、kubectl cpが使えそうです)

rsyncの対象となるパスを、デプロイ設定のmountPathから取得しているのが面白いところです。

多くの場合、アプリケーションデータはoc rsyncコマンドでバックアップできます。コンテナイメージにrsyncがインストールされている想定ですが、Red Hatのrhel7のベースイメージにはrsyncが含まれています。
したがって、rhel7をベースにした全てのイメージにもrsyncは含まれています。CLI操作のトラブルシューティングとデバッグ - rsyncを参照してください。

! 注意
これはアプリケーションデータの一般的なバックアップ方法であり、アプリケーション固有のバックアップ手順(データベースの特殊なエクスポート/インポート手順など)は考慮していません。

また、PVの種類(例えば、CinderやNFS、Glusterなど)によっては、他のバックアップ手順があるかもしれません。

バックアップ対象のファイルパスも、アプリケーションごとに異なります。DeploymentConfigのmountPathを見れば、どのパスのデータをバックアップすべきか判断できます。

Jenkinsのアプリケーションデータをバックアップする例

  1. DeploymentConfigから、アプリケーションデータのmountPathを取得します。

    oc get dc/jenkins -o jsonpath='{ .spec.template.spec.containers[?(@.name=="jenkins")].volumeMounts[?(@.name=="jenkins-data")].mountPath }'
    # -> /var/lib/jenkins
    
  2. 現在実行されているpodの名前を取得します。

    oc get pod --selector=deploymentconfig=jenkins -o jsonpath='{ .metadata.name }'
    # -> jenkins-1-37nux
    
  3. oc rsyncコマンドでアプリケーションデータをバックアップします。

    oc rsync jenkins-1-37nux:/var/lib/jenkins /tmp/
    

! メモ
このアプリケーションデータのバックアップ方法は、現在実行されているアプリケーションのpodに対してしか実行できません。

記載されている通り、アプリケーションが稼働しているときにしか実行できない方法です。
アプリケーションが死んでからデータを救出するような用途には使えません。

アプリケーションデータの復元

アプリケーションデータのリストア手順は、oc rsyncを使ったアプリケーションのバックアップ手順と似たような手順になります。
制限事項も同じです。このアプリケーションデータのリストア手順も、PVがアタッチされていることが前提になっています。

Jenkinsのアプリケーションデータをリストアする例

  1. バックアップを検証します。

    ls -la /tmp/jenkins-backup/
    total 8
    drwxrwxr-x.  3 user     user   20 Sep  6 11:14 .
    drwxrwxrwt. 17 root     root 4096 Sep  6 11:16 ..
    drwxrwsrwx. 12 user     user 4096 Sep  6 11:14 jenkins
    
  2. oc rsyncを使って、データを実行中のpodにコピーします。

    oc rsync /tmp/jenkins-backup/jenkins jenkins-1-37nux:/var/lib
    

    ! メモ
    アプリケーションによっては、ここでアプリケーションの再起動が必要になるかもしれません

  3. 新しいデータでアプリケーションを再起動します(オプショナル)。

    oc delete pod jenkins-1-37nux
    

    または、そのデプロイをレプリカ数0になるまでスケールダウンし、再度スケールアップしてもかまいません。

    oc scale --replicas=0 dc/jenkins
    oc scale --replicas=1 dc/jenkins
    

  1. etcdctl member addの結果は、値がダブルクォーテーションで囲まれた形式で出力されますが、etcd.confに結果を貼り付けるときはダブルクォーテーションを外さないとうまくいかなかったです。 

21
19
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
21
19