A Coder

Coding My Dream!

0%

CoreOS 墙内为何不能更新升级?及另类办法

随着Docker的流行,CoreOS也开始风靡起来,阿里云提供CoreOS的镜像也有几个月的时间了,阿里云用的版本号是681.2.0而目前的最新版本都已经到1000.0.0了,落后的太多了,就想把系统升级到最新,也体验一下coreos最牛的特点--无痛升级。

好事总是多磨,在输入update_engine_client -update后,并没有像预期的那样哗啦啦升级成功,嗯,还是失败了,失败的原因,大家应该都知道--被墙了。

按照前辈的方式使用代理,但是手头上没有好用的翻墙代理,自己搭建折腾了半天搭好了,也没有更新成功……

对于不折腾会死的我并没有放弃,研究了一下升级更新日志 (可输入命令 journalctl -f -u update-engine 查看),了解了一下和网络相关的升级过程。

首先向升级服务器发送一个检查新版的请求
服务器地址:https://public.update.core-os.net/v1/update/
这个地址就是/etc/coreos/update.conf 配置的SERVER地址
请求内容如下:







返回结果如下:
如果有更新版本

<?xml version="1.0" encoding="UTF-8"?>
<response protocol="3.0" server="update.core-os.net">
 <daystart elapsed_seconds="0"></daystart>
 <app appid="e96281a6-d1af-4bde-9a0a-97b76e56dc57" status="ok">
  <updatecheck status="ok">
   <urls>
    <url codebase="https://commondatastorage.googleapis.com/update-storage.core-os.net/amd64-usr/899.13.0/"></url>
   </urls>
   <manifest version="899.13.0">
    <packages>
     <package hash="tQQEZ0fRs8Vvdb6acs/hxTKhpVc=" name="update.gz" size="186432352" required="false"></package>
    </packages>
    <actions>
     <action event="postinstall" ChromeOSVersion="" sha256="PST3qOC0q3ODIL/Ktcuz1CfK3tbtumPSOHWXwSj9zyo=" needsadmin="false" IsDelta="false" DisablePayloadBackoff="true"></action>
    </actions>
   </manifest>
  </updatecheck>
 </app>
</response>

如果没有更新:

<?xml version="1.0" encoding="UTF-8"?>
<response protocol="3.0" server="update.core-os.net">
    <daystart elapsed_seconds="0"></daystart>
    <app appid="e96281a6-d1af-4bde-9a0a-97b76e56dc57" status="ok">
        <updatecheck status="noupdate"></updatecheck>
    </app>
</response>

然后,如果有更新,则会去更新服务器返回的地址去下载更新包update.gz,如果没有更新就结束了。

更新包的地址是 https://commondatastorage.googleapis.com/update-storage.core-os.net/amd64-usr/899.13.0/update.gz,看到这里,你应该知道怎么回事了,coreos的服务器并没有被墙,被墙的是google提供的cdn加速服务,coreos使用了google的服务,反倒弄巧成拙了。 https://update-storage.core-os.net/amd64-usr/899.13.0/update.gz 是能够访问的!但是时好时坏…… 如果这个也不能下载,那么只能翻墙下载好放到自己的服务器上了!希望国内哪个土豪公司提供个mirror。

既然如此,那我想,如果把升级包的下载地址修改掉不用google的,不就能够更新了么?

简单粗暴的方式, 新建一个html文件,如 coreos.html 内容设置为 有更新时返回的xml,不同版本不一样,可以通过查看升级日志获得 如:

<?xml version="1.0" encoding="UTF-8"?>
<response protocol="3.0" server="update.core-os.net">
 <daystart elapsed_seconds="0"></daystart>
 <app appid="e96281a6-d1af-4bde-9a0a-97b76e56dc57" status="ok">
  <updatecheck status="ok">
   <urls>
    <url codebase="https://update-storage.core-os.net/amd64-usr/899.13.0/"></url>
   </urls>
   <manifest version="899.13.0">
    <packages>
     <package hash="tQQEZ0fRs8Vvdb6acs/hxTKhpVc=" name="update.gz" size="186432352" required="false"></package>
    </packages>
    <actions>
     <action event="postinstall" ChromeOSVersion="" sha256="PST3qOC0q3ODIL/Ktcuz1CfK3tbtumPSOHWXwSj9zyo=" needsadmin="false" IsDelta="false" DisablePayloadBackoff="true"></action>
    </actions>
   </manifest>
  </updatecheck>
 </app>
</response>

把这个文件放到服务器上,比如地址:http://xxx.com/coreos.html,然后之前提到的修改/etc/coreos/update.conf文件的SERVER配置为这个地址,如下:

GROUP=stable
SERVER=http://xxx.com/coreos.html

手动执行 update_engine_client -update 后竟然升级成功了。但是这样有一个问题,coreos会隔一段时间就自动检查一次更新,每次检查更新发现都有升级,所以系统会像吃了炫迈一样一直无限升级下去,根本停不下来……通过这种方式需要在升级完成后就将升级地址改掉。

B计划,自己建一个升级代理服务,通过程序自动替换升级包地址,PHP版本如下:

<?php

function send_post($url, $post)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}

$data = file_get_contents("php://input");
$url = "https://public.update.core-os.net/v1/update/";
$result = send_post($url, $data);
$result = str_replace("commondatastorage.googleapis.com/","",$result);
echo $result;

同样简单粗暴……