Linux.中国 - 开源社区

 找回密码
 骑士注册

QQ登录

微博登录


CoreOS那些事之系统升级

2015-4-14 13:57    评论: 1 收藏: 2    

手动升级系统

CoreOS始终会自动在后台下载和部署新版本系统,即使将升级策略设为off(这样只是禁止自动重启)。因此在绝大多数情况下,除非处于测试目的和紧急的版本修复,用户是不需要手动触发系统升级的。不过,大概是考虑到总是有新版本强迫症用户的需求(其实主要是系统测试的需求啦),CoreOS还是提供了手动更新的途径。

查看当前系统版本

相比手动更新,用户也许更想看到的仅仅是:现在的系统到底是部署的哪个版本啦。方法很简单,查看一下etc目录下面的 os-release 文件就可以了。

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

这个文件实际上是一个软链接,指向系统分区的 /usr/lib/os-release 文件,而后者是只读分区的一部分,因此不用担心这个文件中的内容会被外部篡改。

自动升级的频率

CoreOS会在 启动后10分钟 以及之后的 每隔1个小时 自动检测系统版本,如果检查到新版本就会自动下载下来放到备用分区上,然后依据之前的那个升级策略决定是否自动重启节点。OK,就这么简单。

具体的升级检测记录可以通过 journalctl -f -u update-engine 命令查看到。

手动触发升级

恩,下面这个命令是给升级强迫症用户准备滴。

命令非常简单:update_engine_client -update,如果提示 "Update failed" 则表示当前已经是最新版本(搞不懂CoreOS那班人为啥不弄个友好点的提示信息)。如果检测到有新版本的系统则会立即将其下载和部署到备用系统分区上。

$ update_engine_client -update
[0404/032058:INFO:update_engine_client.cc(245)] Initiating update check and install.
[0404/032058:INFO:update_engine_client.cc(250)] Waiting for update to complete.
LAST_CHECKED_TIME=1428117554
PROGRESS=0.000000
CURRENT_OP=UPDATE_STATUS_UPDATE_AVAILABLE
NEW_VERSION=0.0.0.0
... ...
CURRENT_OP=UPDATE_STATUS_FINALIZING
NEW_VERSION=0.0.0.0
NEW_SIZE=129636481
Broadcast message from locksmithd at 2015-04-04 03:22:56.556697323 +0000 UTC:
System reboot in 5 minutes!
LAST_CHECKED_TIME=1428117554
PROGRESS=0.000000
CURRENT_OP=UPDATE_STATUS_UPDATED_NEED_REBOOT
NEW_VERSION=0.0.0.0
NEW_SIZE=129636481
[0404/032258:INFO:update_engine_client.cc(193)] Update succeeded -- reboot needed.

部署完成后,如果用户的升级策略不是 off,系统会发送消息给所有登录当前的用户:“5分钟后系统将重启”。当然,你自己也会在5分钟后被踢出SSH登录,等再次登录回来的时候,就会发现系统已经变成新的版本了。

更好的升级策略

在看到CoreOS的4种升级策略时候,不晓得读者有没发现一个问题。前3种策略都会让新的系统版本下载部署后马上重启服务器,如果这个时候恰好是系统访问的高峰期,即使重启过程中,服务会自动迁移到其他的节点继续运行,仍然可能会造成短暂的服务中断的情况。而第4种策略索性等待管理员用户来重启系统完成升级,又引入了额外的人工干预,如果重启不及时还会使得集群得不到必要的安全更新。

有没有办法既让服务器不要在服务高峰期重启,又不至于很长时间没有更新呢?CoreOS给出了一种推荐的解决方法。我将它称为第5种升级策略:基于定时检测的自动重启。

这种升级策略没有在内置的选项当中,我们需要做些额外的工作:

  • 将升级策略设置成 off
  • 增加一个服务用来检测备用分区是否已经部署新的系统版本,如果部署了就进行重启
  • 增加一个定时器在集群的低峰时段触发执行上面那个服务

检测和重启服务

首先来看最关键的这个服务update-window.service,它会去执行放在 /opt/bin 目录下面的update-window.sh脚本文件。

[Unit]
Description=Reboot if an update has been downloaded
[Service]
ExecStart=/opt/bin/update-window.sh

这个脚本首先使用 update_engine_client -status 检测了备份分区是否已经部署好了新版本的系统。如果发现新的版本已经部署好,就根据 Etcd 服务是否启动来选择通过 Locksmith 调度重启节点(先获取锁然后重启动)或延迟一个随机的时间后重启节点,这样做的目的是防止太多节点在同一个时间重启导致集群不稳定。

#!/bin/bash
# If etcd is active, this uses locksmith. Otherwise, it randomly delays. 
delay=$(/usr/bin/expr $RANDOM % 3600 )
rebootflag='NEED_REBOOT'
if update_engine_client -status | grep $rebootflag; then
    echo -n "etcd is "
    if systemctl is-active etcd; then
        echo "Update reboot with locksmithctl."
        locksmithctl reboot
    else
        echo "Update reboot in $delay seconds."
        sleep $delay
        reboot
    fi
fi

定时触发服务

接下来添加定时器update-window.timer在集群访问的低峰时段触发前面那个服务,

[Unit]
Description=Reboot timer
[Timer]
OnCalendar=*-*-* 05,06:00,30:00

这个定时器Unit文件的功能类似于一个crontab记录,只不过对于用了Systemd启动的系统比较推荐使用这样的方式。上面的配置表示每天早上的5:00, 5:30, 6:00 和 6:30。

写到 cloud-init 里

既然是每个节点都要有的东东,当然要放到cloud-init 配置里面。把上面的内容统统写进去,看起来就是这个样子的了:

#cloud-config
coreos:
  update:
    reboot-strategy: off
  units:
    - name: update-window.service
      runtime: true
      content: |
        [Unit]
        Description=Reboot if an update has been downloaded
        [Service]
        ExecStart=/opt/bin/update-window.sh 
    - name: update-window.timer
      runtime: true
      command: start
      content: |
        [Unit]
        Description=Reboot timer
        [Timer]
        OnCalendar=*-*-* 05,06:00,30:00
write_files:
  - path: /opt/bin/update-window.sh
    permissions: 0755
    owner: root
    content: |
        #!/bin/bash
        # If etcd is active, this uses locksmith. Otherwise, it randomly delays. 
        delay=$(/usr/bin/expr $RANDOM % 3600 )
        rebootflag='NEED_REBOOT'
        if update_engine_client -status | grep $rebootflag; then
            echo -n "etcd is "
            if systemctl is-active etcd; then
                echo "Update reboot with locksmithctl."
                locksmithctl reboot
            else
                echo "Update reboot in $delay seconds."
                sleep $delay
                reboot
            fi
        fi
        exit 0

到这里,CoreOS升级相关的事儿已经侃得差不多了。不过总觉得还差点什么。

查看其它分页:

发表评论


最新评论

我也要发表评论

lyhabc 2015-4-14 21:32
看过了
6 回复

热点评论

lyhabc 2015-4-14 21:32
看过了
6
返回顶部

分享到微信朋友圈

打开微信,点击底部的“发现”,
使用“扫一扫”将网页分享至朋友圈。