1
0

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 3 years have passed since last update.

さくらのクラウドのサーバの起動/停止をスケジューリングする

Last updated at Posted at 2022-03-29

概要

以前同じ内容でこちらの記事を書いたのですが、このときは実行環境に AWS を使っていましたし、saklient というライブラリも公開が終了したようなので、作り直すことにしました。
以下の希望がある場合は、本処理が参考になる可能性があります。

  • 検証用途などのサーバを業務時間外等に停止しておくことで課金額を抑えたい

手法

usacloudという CLIクライアントを利用して、対象となるサーバを特定し、起動または停止するスクリプトを作成します。
この処理を、cron で好きな時間帯に実行することで、自動化します。
今回は自前のサーバなどを用意しなくてもすむように、GitHub Actions を使用して、指定した時間帯で usacloud のコンテナを作成し、スクリプトを実行するようにしています。


注意事項

  • スクリプトはあくまでもサンプルなので、必要に応じて修正ください。
  • 全ゾーンを対象に、 myautostartstop タグが付いたサーバを対象としています。
  • 内閣府様の「国民の祝日」についてというサイトから、CSVをダウンロードして配置しておくことで、祝日を除外できるようにしてあります。ファイルに同じフォーマットで年月日を追加すれば、個別の休業日も除外可能です。
  • usacloud の起動/停止コマンドでは、タグを指定して以下のように全ゾーンに対して一括実行することが可能です。ただし、すでに起動しているサーバに対して起動依頼をかけるとエラーレスポンスがあります(停止の場合は無いようです)。それが少し微妙だったので(実害があるわけでは無さそうですが)、スクリプトでは現在のステータスを確認して実行対象を限定するようにしています。停止時には -f (強制シャットダウン)をつけていますが、これも気になる場合は外してください。
usacloud server shutdown --zone all -y -f --no-wait myautostartstop
usacloud server boot --zone all -y --no-wait myautostartstop

基本的な流れ

  1. GitHub のリポジトリを プライベート で作成してください。

    • パブリックで作成して公開してしまうと、ログが見えることになるので危険です。
  2. 該当リポジトリ内の Settings で、Secrets内の Actions に以下 Actions secrets を設定してください。

    Name
    SAKURACLOUD_ACCESS_TOKEN
    SAKURACLOUD_ACCESS_TOKEN_SECRET
    
  3. 以下ファイルを配置してください。

    startstop.sh
    #!/bin/bash
    
    HOLIDAYS=`cut -d ',' -f 1 ./syukujitsu.csv | sed -e '1d'`
    #HOLIDAYS=`curl -sS https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | awk -F',' 'NR>1 {print $1}'`
    TODAY=`TZ='Asia/Tokyo' date "+%Y/%-m/%-d"`
    TARGET_TAG="myautostartstop"
    TASK=$1
    SERVERSTATUS="up"
    POWERCOMMAND="boot"
    
    if [ "$TASK" = "start" ]; then
    	SERVERSTATUS="down"
    	POWERCOMMAND="boot"
    elif [ "$TASK" = "stop" ]; then
    	SERVERSTATUS="up"
    	POWERCOMMAND="shutdown -f"
    else
    	echo "Usage: startstop.sh start|stop"
    	exit 0
    fi
    
    echo ${HOLIDAYS} | grep ${TODAY} > /dev/null
    
    if [ ${?} -eq 0 ] ; then
    	echo "today is holiday"
    	exit 0
    fi
    
    for Zone in tk1a tk1b is1a is1b
    do
    	echo "---- List Target Servers of $Zone ----"
    	ServerIds=`usacloud server ls --tags $TARGET_TAG --zone $Zone --query="map(select( .InstanceStatus==\"$SERVERSTATUS\" )) | reverse | .[].ID" --query-driver=jq | xargs`
    
    	for ServerId in $ServerIds
    	do
    		echo "---- $ServerId ----"
    		usacloud server $POWERCOMMAND --zone $Zone -y --no-wait $ServerId
    	done
    done
    
    echo "---- Servers ----"
    usacloud server ls --tags $TARGET_TAG --zone all
    
    .github/workflows/start.yml
    name: StartServer
    
    on:
    #  push:
    #    branches:
    #      - main
      schedule:
        - cron:  '55 23 * * 1-5'
    
    jobs:
      node-docker:
        runs-on: ubuntu-latest
        container: #起動するコンテナイメージを指定
          image: ghcr.io/sacloud/usacloud #指定のdockerイメージを使用
    
        env:
          SAKURACLOUD_ACCESS_TOKEN: ${{ secrets.SAKURACLOUD_ACCESS_TOKEN }}
          SAKURACLOUD_ACCESS_TOKEN_SECRET: ${{ secrets.SAKURACLOUD_ACCESS_TOKEN_SECRET }}
          SAKURACLOUD_ZONE: "is1a"
        steps: #dockerコンテナ内でステップを実行
          - name: Log usacloud version
            run: |
              usacloud -v #バージョンの確認
              cat /etc/os-release #Linuxバージョンの確認
              apk add --update --no-cache tzdata
          - uses: actions/checkout@v2 #次ステップでファイル読み込むのでクローンが必要
          - name: Run a script
            run: sh ./startstop.sh start
    
    .github/workflows/stop.yml
    name: StopServer
    
    on:
    #  push:
    #    branches:
    #      - main
      schedule:
        - cron:  '55 8 * * 1-5'
    
    jobs:
      node-docker:
        runs-on: ubuntu-latest
        container: #起動するコンテナイメージを指定
          image: ghcr.io/sacloud/usacloud #指定のdockerイメージを使用
    
        env:
          SAKURACLOUD_ACCESS_TOKEN: ${{ secrets.SAKURACLOUD_ACCESS_TOKEN }}
          SAKURACLOUD_ACCESS_TOKEN_SECRET: ${{ secrets.SAKURACLOUD_ACCESS_TOKEN_SECRET }}
          SAKURACLOUD_ZONE: "is1a"
        steps: #dockerコンテナ内でステップを実行
          - name: Log usacloud version
            run: |
              usacloud -v #バージョンの確認
              cat /etc/os-release #Linuxバージョンの確認
              apk add --update --no-cache tzdata
          - uses: actions/checkout@v2 #次ステップでファイル読み込むのでクローンが必要
          - name: Run a script
            run: sh ./startstop.sh stop
    
  4. start.yml および stop.yml にあるとおり、日本時間の月~金の 8:55頃に起動し、17:55頃に停止するようになっていますので、必要に応じて実行時間を変更してください。

      schedule:
        - cron:  '55 23 * * 1-5'
    
      schedule:
        - cron:  '55 8 * * 1-5'
    
    • 必ずしも時間通りに実行されるかはわかりませんので、気になる場合は実行タイミングを複数作るか、負荷の少なそうな時間帯を探すか、おとなしく自前の実行環境を用意した方がいいかもしれません。
    • 実行時間については公式の情報も参照ください。
    ノート: scheduleイベントは、GitHub Actionsのワークフローの実行による高負荷の間、遅延させられることがあります。 
    高負荷の時間帯には、毎時の開始時点が含まれます。 
    遅延の可能性を減らすために、Ⅰ時間の中の別の時間帯に実行されるようワークフローをスケジューリングしてください。
    

サンプルログ

起動時のログを確認すると、以下のように見えます。
このときは 2つのサーバが対象になっていて、問題無く起動されています。
なお停止時は、InstanceStatus が cleaning など、途中の状態になっていることもありました。
--no-wait をつけてコマンドを実行しているためです。

Run sh ./startstop.sh start
---- List Target Servers of tk1a ----
---- List Target Servers of tk1b ----
---- ***********0 ----
---- ***********9 ----
---- List Target Servers of is1a ----
---- List Target Servers of is1b ----
---- Servers ----
+------+--------------+-----------------------------------+-------------------------+-----+--------+-----+-------------------+----------------+----------------+----------------+
| Zone |      ID      |               Name                |          Tags           | CPU | Memory | GPU |     IPAddress     | Upstream(Mbps) | InstanceStatus |  InstanceHost  |
+------+--------------+-----------------------------------+-------------------------+-----+--------+-----+-------------------+----------------+----------------+----------------+
| tk1b | ***********9 | ****************************-a... | [@auto-reboot @group... | 1   | 2      | 0   | ***.**.***.***/24 | shared/100     | up             | sac-tk1b-sv*** |
| tk1b | ***********0 | ****************************-a... | [@auto-reboot @group... | 1   | 2      | 0   | ***.**.***.***/24 | shared/100     | up             | sac-tk1b-sv*** |
+------+--------------+-----------------------------------+-------------------------+-----+--------+-----+-------------------+----------------+----------------+----------------+

最後に

管理サーバを用意して cron で実行する方が確実なのですが、そこにお金をかけたくない・・・という場合には、こういった方法もお手軽でおもしろいかなと思います。
とはいえ、予定通りに実行されない結果、クラウドの課金が増えたら本末転倒なので、一長一短かもしれませんが。
サーバの作成も Terraform で実行している場合は、そのコードとまとめて管理することもできて、ちょうどよいかもしれません。
参考になれば幸いです。
どうぞよいさくらのクラウドライフを!

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?