本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
執行時間版本更新
您可以使用 CloudWatch 主控台、 AWS CLI 或 AWS SDK AWS CloudFormation來更新 Canary 的執行時間版本。當您使用 CloudWatch 主控台時,您可以一次更新最多五個 Canary,方法是在 Canary 清單頁面中選取它們,然後選擇 Actions (動作)、Update Runtime (更新執行時間)。
您可以在遞交執行時間更新之前先測試更新,以驗證更新。更新執行時期版本時,請在 CloudWatch 主控台中選擇開始模擬執行或稍後驗證並儲存選項,以建立原始 Canary 的模擬執行,以及您對組態所做的任何變更。模擬執行將更新並執行 Canary,以驗證執行時期更新對 Canary 是否安全。一旦您使用新的執行時期版本驗證 Canary,即可更新 Canary 的執行時期版本。如需詳細資訊,請參閱執行安全 Canary 更新。
或者,您可以先使用 CloudWatch 主控台複製 Canary 並更新其執行時期版本,以驗證升級。這樣一來,會建立另一個 Canary,它就是原來的 Canary 的複製。一旦您使用新的執行時間版本驗證了您的 Canary,您可以更新原始 Canary 的執行時間版本並刪除複製的 Canary。
您也可以使用升級指令碼更新多個 Canary。如需詳細資訊,請參閱Canary 執行時間升級指令碼。
如果您升級 Canary 但失敗了,請參閱 對失敗的 Canary 進行故障診斷。
Canary 執行時間升級指令碼
若要將 Canary 指令碼升級為支援的執行時間版本,請使用下列指令碼。
const AWS = require('aws-sdk'); // You need to configure your AWS credentials and Region. // https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html // https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html const synthetics = new AWS.Synthetics(); const DEFAULT_OPTIONS = { /** * The number of canaries to upgrade during a single run of this script. */ count: 10, /** * No canaries are upgraded unless force is specified. */ force: false }; /** * The number of milliseconds to sleep between GetCanary calls when * verifying that an update succeeded. */ const SLEEP_TIME = 5000; (async () => { try { const options = getOptions(); const versions = await getRuntimeVersions(); const canaries = await getAllCanaries(); const upgrades = canaries .filter(canary => !versions.isLatestVersion(canary.RuntimeVersion)) .map(canary => { return { Name: canary.Name, FromVersion: canary.RuntimeVersion, ToVersion: versions.getLatestVersion(canary.RuntimeVersion) }; }); if (options.force) { const promises = []; for (const upgrade of upgrades.slice(0, options.count)) { const promise = upgradeCanary(upgrade); promises.push(promise); // Sleep for 100 milliseconds to avoid throttling. await usleep(100); } const succeeded = []; const failed = []; for (let i = 0; i < upgrades.slice(0, options.count).length; i++) { const upgrade = upgrades[i]; const promise = promises[i]; try { await promise; console.log(`The update of ${upgrade.Name} succeeded.`); succeeded.push(upgrade.Name); } catch (e) { console.log(`The update of ${upgrade.Name} failed with error: ${e}`); failed.push({ Name: upgrade.Name, Reason: e }); } } if (succeeded.length) { console.group('The following canaries were upgraded successfully.'); for (const name of succeeded) { console.log(name); } console.groupEnd() } else { console.log('No canaries were upgraded successfully.'); } if (failed.length) { console.group('The following canaries were not upgraded successfully.'); for (const failure of failed) { console.log('\x1b[31m', `${failure.Name}: ${failure.Reason}`, '\x1b[0m'); } console.groupEnd(); } } else { console.log('Run with --force [--count <count>] to perform the first <count> upgrades shown. The default value of <count> is 10.') console.table(upgrades); } } catch (e) { console.error(e); } })(); function getOptions() { const force = getFlag('--force', DEFAULT_OPTIONS.force); const count = getOption('--count', DEFAULT_OPTIONS.count); return { force, count }; function getFlag(key, defaultValue) { return process.argv.includes(key) || defaultValue; } function getOption(key, defaultValue) { const index = process.argv.indexOf(key); if (index < 0) { return defaultValue; } const value = process.argv[index + 1]; if (typeof value === 'undefined' || value.startsWith('-')) { throw `The ${key} option requires a value.`; } return value; } } function getAllCanaries() { return new Promise((resolve, reject) => { const canaries = []; synthetics.describeCanaries().eachPage((err, data) => { if (err) { reject(err); } else { if (data === null) { resolve(canaries); } else { canaries.push(...data.Canaries); } } }); }); } function getRuntimeVersions() { return new Promise((resolve, reject) => { const jsVersions = []; const pythonVersions = []; synthetics.describeRuntimeVersions().eachPage((err, data) => { if (err) { reject(err); } else { if (data === null) { jsVersions.sort((a, b) => a.ReleaseDate - b.ReleaseDate); pythonVersions.sort((a, b) => a.ReleaseDate - b.ReleaseDate); resolve({ isLatestVersion(version) { const latest = this.getLatestVersion(version); return latest === version; }, getLatestVersion(version) { if (jsVersions.some(v => v.VersionName === version)) { return jsVersions[jsVersions.length - 1].VersionName; } else if (pythonVersions.some(v => v.VersionName === version)) { return pythonVersions[pythonVersions.length - 1].VersionName; } else { throw Error(`Unknown version ${version}`); } } }); } else { for (const version of data.RuntimeVersions) { if (version.VersionName === 'syn-1.0') { jsVersions.push(version); } else if (version.VersionName.startsWith('syn-nodejs-2.')) { jsVersions.push(version); } else if (version.VersionName.startsWith('syn-nodejs-puppeteer-')) { jsVersions.push(version); } else if (version.VersionName.startsWith('syn-python-selenium-')) { pythonVersions.push(version); } else { throw Error(`Unknown version ${version.VersionName}`); } } } } }); }); } async function upgradeCanary(upgrade) { console.log(`Upgrading canary ${upgrade.Name} from ${upgrade.FromVersion} to ${upgrade.ToVersion}`); await synthetics.updateCanary({ Name: upgrade.Name, RuntimeVersion: upgrade.ToVersion }).promise(); while (true) { await usleep(SLEEP_TIME); console.log(`Getting the state of canary ${upgrade.Name}`); const response = await synthetics.getCanary({ Name: upgrade.Name }).promise(); const state = response.Canary.Status.State; console.log(`The state of canary ${upgrade.Name} is ${state}`); if (state === 'ERROR' || response.Canary.Status.StateReason) { throw response.Canary.Status.StateReason; } if (state !== 'UPDATING') { return; } } } function usleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }