89
85

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

CoreOSAdvent Calendar 2014

Day 1

CoreOS の自動アップデートを理解する

Last updated at Posted at 2014-12-01

概要

CoreOS は以下の画像のようにルートパーティションを 2 つ持っており、いわば OS のアップデートをブルーグリーンデプロイする。その自動アップデートの仕組みを理解し、状況に合わせたアップデート戦略を設定できるようにする。

背景

CoreOS が実現したいものの一つとしてインターネットのバックエンドにあるインフラをもっとセキュアにしたいというのがある。個人的な印象として、セキュリティパッチを継続的にプロダクション環境に当て続けるのはそれなりの工夫やエネルギーを注ぐ必要があると思う。日々セキュリティ系以外の仕事もこなす必要があるはずなので、少なくとも何も考えずに運用しているだけでは対応できない。CoreOS は継続的にアップデートする方法として自動アップデート というアプローチを取る。これはブラウザの Chrome が自動でバージョンアップしているのと(技術的にも)同じ話。

アップデートの基本的な仕組み

まず、アップデートは常にアップデート郡が利用可能になったときに passive なパーティション(今 active じゃない方)にダウンロードされる。OS のリブートはアップデートの最後のステップとして実行され、active なパーティションと passive なパーティションが交換されて完了する。

4 種類のアップデート戦略

アップデート戦略 説明
best-effort デフォルトの戦略。etcd が動いている場合は、 etcd-lock が実行される。そうでない場合は単純に reboot がかかる。
etcd-lock etcd に分散ロックをかけた上でリブートする。
reboot アップデートが適用されたらすぐにリブートをかける。
off アップデートが適用されたあとに自動でリブートをしない

Best Effort

クラスタのメンバーとしてそのマシンが動いているかどうかを etcd が起動しているかで判断し、クラスタのメンバであったら場合は以下の etcd-lock 戦略を実行。そうでなければ reboot を実行。

etcd-Lock

etcd-lock 戦略は、各マシンを取得し、それらにリブートを許可する前にリブートロックを行う。
この戦略の主なゴールとしては、クラスタ上で動いているサービスのキャパシティを一気に減らしたり、クラスタを形成するのに必要なメンバー数以下にならないようにしながらクラスタに素早くアップデートを適用すること。
リブートロックはそのマシンのアップデートが無事に完了するまでの間かかっている。

Reboot Immediatedly

reboot 戦略は名前の通りで、アップデートが passive パーティションにインストールされるとすぐにリブートがかかる。もしクラスタ上で動いているアプリケーションが回復性に優れている(リブートしてもちゃんと立ち上がり直すとか、さらに立ち上がりも速いとか)ならばこの戦略がよい。

Off

off 戦略は単純。アップデートが passive パーティション上にインストールされ、アップデートを完了させるために手動でリブートがかかるのを待つ。通常のオペレーションワークフローの一部としてリブートを頻繁にかけているのでなければこの戦略はおすすめしない。

アップデート戦略の設定を行う

アップデート戦略は cloud-config にて定義できる。

#cloud-config
coreos:
  update:
    reboot-strategy: best-effort

オプション

コマンドライン locksmithctl から「一度に何台までリブートをかけて良いか」を設定できる。

$ locksmithctl set-max 4
Old: 1
New: 4

この設定は etcd に保存されるため、その他のマシンで作業を行う必要はない。

利用可能なスロット数を見てクラスタ内のどのマシンにロックがかかっているか見るには

$ locksmithctl status
Available: 1
Max: 1

必要ならばマシン ID を渡すことで手動でリブートロックをクリアすることもできる。

locksmithctl unlock 69d27b356a94476da859461d3a3bc6fd

実際に自動アップデートさせてみる

coreos-vagrant を使い、チャネルの最新バージョンではないクラスタを起動し自動アップデートを待つ。
(coreos-vagrant の導入・使い方に関しては Vagrant(Virtualbox) 上で CoreOS を動かす を参照)

# config.rb
$num_instances=4
$update_channel='alpha'

etcd の discovery token を取得して

$ curl -s https://discovery.etcd.io/new

user-data にセット

#cloud-config

coreos:
  update:
    group: alpha
    reboot-strategy: best-effort
  etcd:
    # generate a new token for each unique cluster from https://discovery.etcd.io/new
    # WARNING: replace each time you 'vagrant destroy'
    discovery: https://discovery.etcd.io/xxxxxxxxxxxxxxxxxxxxxxxxxxx
    addr: $public_ipv4:4001
    peer-addr: $public_ipv4:7001
  fleet:
    public-ip: $public_ipv4
  units:
    - name: etcd.service
      command: start
    - name: fleet.service
      command: start
    - name: docker-tcp.socket
      command: start
      enable: true
      content: |
        [Unit]
        Description=Docker Socket for the API

        [Socket]
        ListenStream=2375
        Service=docker.service
        BindIPv6Only=both

        [Install]
        WantedBy=sockets.target

CoreOS クラスタを起動する

$ vagrant up

アップデート戦略を確認

core@core-01 ~ $ cat /etc/coreos/update.conf
GROUP=alpha
REBOOT_STRATEGY=best-effort

core@core-01 ~ $ locksmithctl status
Available: 1
Max: 1

現在のバージョンを確認

core@core-01 ~ $ cat /etc/os-release
NAME=CoreOS
ID=coreos
VERSION=490.0.0
VERSION_ID=490.0.0
BUILD_ID=
PRETTY_NAME="CoreOS 490.0.0"
ANSI_COLOR="1;32"
HOME_URL="https://coreos.com/"
BUG_REPORT_URL="https://github.com/coreos/bugs/issues"

使用中のパーティションを確認

core@core-02 ~ $ sudo findmnt -n --raw --output=source --target=/usr
/dev/sda3
core@core-01 ~ $ sudo cgpt show -v /dev/sda3
       start        size    part  contents
      270336     2097152       3  Label: "USR-A"
                                  Type: Alias for coreos-rootfs
                                  UUID: 7130C94A-213A-4E5A-8E26-6CCE9662F132
                                  Attr: priority=1 tries=0 successful=1
core@core-01 ~ $ sudo cgpt show -v /dev/sda4
       start        size    part  contents
     2367488     2097152       4  Label: "USR-B"
                                  Type: Alias for coreos-rootfs
                                  UUID: E03DD35C-7C2D-4A47-B3FE-27F15780A57C
                                  Attr: priority=0 tries=0 successful=0

Attr に関して

  • priority が大きい方が最初に active パーティションとして選択される
  • tries の数だけリトライされ、0 になってもダメな場合は、次の priority をブートする。
  • successful=1 なもはブート可能のものと判断され、使い続けられる。

メモ:CoreOS の自動アップデートを手動でロールバックするより引用)

fleet 経由で unit を起動し、リブート時の挙動を見てみる。

# /etc/systemd/system/example@.service
[Unit]
Description=example

[Service]
ExecStartPre=-/usr/bin/docker kill example-%i
ExecStartPre=-/usr/bin/docker rm example-%i
ExecStart=/usr/bin/docker run --rm --name example-%i coreos/example:1.0.0
ExecStop=/usr/bin/docker stop example-%i
core@core-01 /etc/systemd/system $ fleetctl submit example@.service
core@core-01 /etc/systemd/system $ fleetctl start example@{1..4}.service
Unit example@3.service launched on e332f616.../172.17.8.101
Unit example@1.service launched on 056fd77b.../172.17.8.103
Unit example@2.service launched on 1b5490ea.../172.17.8.104
Unit example@4.service launched on f34ed28e.../172.17.8.102
core@core-01 ~ $ fleetctl list-units
UNIT			MACHINE				ACTIVE	SUB
example@1.service	056fd77b.../172.17.8.103	active	running
example@2.service	1b5490ea.../172.17.8.104	active	running
example@3.service	e332f616.../172.17.8.101	active	running
example@4.service	f34ed28e.../172.17.8.102	active	running

しばらく待つと自動アップデートがかかり以下のメッセージが出る。

Broadcast message from locksmithd at 2014-12-01 13:05:44.068872392 +0000 UTC:
System reboot in 5 minutes!

Connection to 127.0.0.1 closed by remote host.
Connection to 127.0.0.1 closed.

リブート中は core-01 上の unit が他のマシンに退避される

core@core-01 ~ $ fleetctl list-units
UNIT			MACHINE				ACTIVE	SUB
example@1.service	056fd77b.../172.17.8.103	active	running
example@2.service	1b5490ea.../172.17.8.104	active	running
example@3.service	f34ed28e.../172.17.8.102	active	running
example@4.service	f34ed28e.../172.17.8.102	active	running

リブートが終わると CoreOS がバージョンアップされている

core@core-01 ~ $ cat /etc/os-release
NAME=CoreOS
ID=coreos
VERSION=509.1.0
VERSION_ID=509.1.0
BUILD_ID=
PRETTY_NAME="CoreOS 509.1.0"
ANSI_COLOR="1;32"
HOME_URL="https://coreos.com/"
BUG_REPORT_URL="https://github.com/coreos/bugs/issues"

パーティションも交換されてる

core@core-01 ~ $ sudo findmnt -n --raw --output=source --target=/usr
/dev/sda4

USR-B パーティションの priority=2 になり、successful=1 となっている

core@core-01 ~ $ sudo cgpt show -v /dev/sda3
       start        size    part  contents
      270336     2097152       3  Label: "USR-A"
                                  Type: Alias for coreos-rootfs
                                  UUID: 7130C94A-213A-4E5A-8E26-6CCE9662F132
                                  Attr: priority=1 tries=0 successful=1
core@core-01 ~ $ sudo cgpt show -v /dev/sda4
       start        size    part  contents
     2367488     2097152       4  Label: "USR-B"
                                  Type: Alias for coreos-rootfs
                                  UUID: E03DD35C-7C2D-4A47-B3FE-27F15780A57C
                                  Attr: priority=2 tries=0 successful=1

Memo

自動アップデートに失敗してる事例も見受けられる

We began with one-machine-at-a-time restarts
Fleet got into a bad state once after a big update to it (alpha channel). We never figured out what happened. Now we disable restarts and do planned updates
CoreOS in Production

TODO: locksmith について記事を書く

TODO: Anatomy of a CoreOS Update のメモを追記

REF

89
85
3

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
89
85

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?