Google Cloud 用にオペレーティング システムを適応させる


このドキュメントでは、ライセンスをお持ちのエンタープライズ OS イメージを使用するようにGoogle Cloud でオペレーティング システム(OS)イメージを適応させる方法について説明します。

Google Cloud は、Debian、Ubuntu LTS、Rocky Linux、Container-Optimized OS の OS イメージを提供します。提供されているイメージを使用する場合は、インスタンスを作成して、インスタンスの作成時に使用するイメージを選択します。

Google Cloud で OS イメージが提供されていないエンタープライズ OS のライセンス(Windows、Red Hat Enterprise Linux(RHEL)、SUSE Linux Enterprise Server(SLES)など)をお持ちの場合は、このドキュメントで説明するスクリプトを使用して、お持ちのライセンスでイメージを使用できるように適応させます。このスクリプトにより、イメージを使用して Google Cloudにインスタンスを作成するために必要なドライバがインストールされます。

始める前に

OS 適応スクリプト

Google Cloud用にイメージを適応させるため、 Google Cloud には、次の処理を行うスクリプトが用意されています。

  1. Cloud Storage からディスクを使用してインスタンスを作成し、インスタンスのディスクで OS 適応ツールを実行します。このプロセスでは、OS イメージが Google Cloudで機能するために必要なドライバがインストールされます。
  2. OS 適応レポートを展開し、出力ファイルをローカルマシンにコピーします。このレポートには、適応プロセスの結果と、検出された OS の詳細情報が含まれています。スクリプトが正常に実行されなかった場合、レポートには、エラー、警告、適応に関する問題を修正するためのアクション アイテムが含まれます。
  3. インスタンスのディスクからイメージを作成します。このイメージを使用して、 Google Cloudにインスタンスを作成できます。
  4. このプロセスで作成されたインスタンスとディスクを削除します。この手順では、プロジェクトから不要なリソースをクリーンアップします。

次のスクリプトは、 Google Cloudで使用できるようにイメージを適応させます。

完全な OS 適応スクリプト

#!/usr/bin/env bash

# Sets variables

set -e
set -x
set -o pipefail

UNIQUE_ID=''
TPC_PREFIX=''
ZONE=''
PROJECT=''
INPUT_IMAGE=''
INPUT_DISK=''
IMAGE_NAME=''
ADAPTATION_INSTANCE_TYPE='c3-highcpu-4' # needs to support nested virtualization



usage() {
  echo ""
  echo "Usage:"
  echo "       $0 -g  -o -z -t  -p "
  echo ""
  echo ""
  echo "Parameters:"
  echo "       -i  OR -d  OR -g "
  echo "       -o "
  echo "       -z "
  echo "       -t "
  echo "       -p "
  echo "       -h (help)"
  echo ""
}

while getopts ":i:d:g:o:z:t:p:h" opt; do
  case "${opt}" in
    i)
      INPUT_IMAGE="${OPTARG}"
      ;;
    d)
      INPUT_DISK="${OPTARG}"
      ;;
    g)
      INPUT_GCS_OBJECT="${OPTARG}"
      ;;
    o)
      IMAGE_NAME="${OPTARG}"
      ;;
    z)
      ZONE="${OPTARG}"
      ;;
    t)
      TPC_PREFIX="${OPTARG}"
      ;;
    p)
      PROJECT="${OPTARG}"
      ;;
    h)
      echo "$0 help:"
      usage
      exit 0
      ;;
    *)
      echo "Unknown arg -${opt} ${OPTARG}"
      usage
      exit 1
      ;;
  esac
done
shift $((OPTIND-1))

# Defines errors

if [[ -n "${INPUT_IMAGE}" && -n "${INPUT_DISK}" ]] ||
   [[ -n "${INPUT_IMAGE}" && -n "${INPUT_GCS_OBJECT}" ]] ||
   [[ -n "${INPUT_DISK}" && -n "${INPUT_GCS_OBJECT}" ]]; then
  echo "Only one of -i, -d, or -g must be specified"
  usage
  exit 1
fi

if [[ -z "${IMAGE_NAME}" ]]; then
  echo "The name of the image must be specified"
  usage
  exit 1
fi

if [[ -z "${ZONE}" ]]; then
  echo "Zone must be specified"
  usage
  exit 1
fi

if [[ -z "${TPC_PREFIX}" ]]; then
  echo "TPC prefix must be specified"
  usage
  exit 1
fi

if [[ -z "${PROJECT}" ]]; then
  echo "Project must be specified"
  usage
  exit 1
fi

# Creates disk

OS_ADAPTATION_IMAGE="projects/${TPC_PREFIX}:v2v-community/global/images/family/v2v-tpc-stable"

if [[ -z "${UNIQUE_ID}" ]]; then
  UNIQUE_ID=$(head /dev/urandom | tr -dc a-z0-9 | head -c4)
fi

if [[ -n "${INPUT_IMAGE}" ]]; then
  DISK_ID="${IMAGE_NAME}-disk-${UNIQUE_ID}"
  echo "Creating disk ${DISK_ID} from image ${INPUT_IMAGE}..."
  gcloud compute disks create "${DISK_ID}" --zone="${ZONE}" --image "${INPUT_IMAGE}"
elif [[ -n "${INPUT_GCS_OBJECT}" ]]; then
  DISK_ID="${IMAGE_NAME}-disk-${UNIQUE_ID}"

  echo "Creating disk ${DISK_ID} from GCS object ${INPUT_GCS_OBJECT}..."
  CURL_OUTPUT=$(curl \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H 'Content-Type: application/json' \
    -X POST  \
    "https://compute.googleapis.com/compute/v1/projects/${TPC_PREFIX}:${PROJECT}/zones/${ZONE}/disks" \
    -d '{"name":"'"${DISK_ID}"'", "sourceStorageObject":"'"${INPUT_GCS_OBJECT}"'"}')
  OPERATION_ID=$(jq -r '.name' <<< "${CURL_OUTPUT}")
  while ! gcloud compute operations describe --zone "${ZONE}" --format=json \
    "${OPERATION_ID}" | jq -e '.status == "DONE"' >/dev/null; do
    sleep 5
  done
elif [[ -n "${INPUT_DISK}" ]]; then
  DISK_ID="${INPUT_DISK}"
fi

QUERY_PATH='v2v/report'
DEVICE_NAME="dev-${UNIQUE_ID}"
OUTPUT_DIR='/var/v2v'
STARTUP_SCRIPT="docker run --privileged -v /dev:/dev -v ${OUTPUT_DIR}:${OUTPUT_DIR} v2v-tpc -vv --log file=${OUTPUT_DIR}/output.log,level=trace --report file=${OUTPUT_DIR}/report.json --report file=http://metadata.google.internal/computeMetadata/v1/instance/guest-attributes/${QUERY_PATH},headers=Metadata-Flavor=Google --license=byol --in-place --drive file=/dev/disk/by-id/google-${DEVICE_NAME},format=raw"

# Creates instance and runs adaptation tool on disk

echo "Adapting disk ${DISK_ID}"

INSTANCE="os-adaptation-instance-${UNIQUE_ID}"
gcloud compute instances create "${INSTANCE}" \
  --zone="${ZONE}" \
  --machine-type="${ADAPTATION_INSTANCE_TYPE}" \
  --enable-nested-virtualization \
  --metadata="^@@@^enable-guest-attributes=TRUE@@@startup-script=${STARTUP_SCRIPT}" \
  --create-disk="auto-delete=yes,boot=yes,image=${OS_ADAPTATION_IMAGE}" \
  --disk="name=${DISK_ID},auto-delete=no,device-name=${DEVICE_NAME}"


# Retrieves report

while [[ -z "${REPORT}" ]]; do
  sleep 5
  set +e
  REPORT=$(gcloud compute instances get-guest-attributes "${INSTANCE}" \
    --zone="${ZONE}" \
    --query-path="${QUERY_PATH}" \
    --format='value(value)') 2>/dev/null
  echo -n '.'
  set -e
done
echo "Operating System adaptation report:"
jq . <<< "${REPORT}"

gcloud compute scp --recurse "${INSTANCE}:${OUTPUT_DIR}" "$(pwd)"
echo "Output file: $(pwd)/v2v/output.log, Report file: $(pwd)/v2v/report.json"

echo "Deleting ${INSTANCE}..."
gcloud compute instances delete "${INSTANCE}" --zone="${ZONE}" --quiet

if jq --exit-status '.status != "SUCCESS"' <<< "${REPORT}" >/dev/null; then
  echo "Operating System adaptation failed"
  exit 1
fi

# Creates image

echo "Operating System adaptation successful, creating image..."

IMAGE="image-${UNIQUE_ID}"
gcloud compute images create "${IMAGE}" \
  --source-disk-zone="${ZONE}" \
  --guest-os-features="$(jq --raw-output '.guest_os_features | join(",")' <<< "${REPORT}")" \
  --source-disk="${DISK_ID}"

if [[ -z "${INPUT_DISK}" ]]; then
  gcloud compute disks delete "${DISK_ID}" --zone="${ZONE}" --quiet
fi

echo "Adapted image: ${IMAGE}"

OS 適応スクリプトを実行する

Google Cloudに OS イメージを適応させる手順は次のとおりです。

  1. シェル スクリプトを作成します。
  2. OS 適応スクリプトをコピーして、シェル スクリプト ファイルに貼り付けます。
  3. 次のフラグを使用して、シェル スクリプトを実行します。

    SCRIPT_NAME \
     -g 'INPUT_GCS_OBJECT' \
     -o 'IMAGE_NAME' \
     -z 'ZONE' \
     -p 'PROJECT' \
     -t 'TPC_PREFIX'

    次のように置き換えます。

    • SCRIPT_NAME: OS 適応スクリプト ファイルの名前
    • INPUT_GCS_OBJECT: Cloud Storage バケット内のディスクへのパス
    • IMAGE_NAME: 適応するイメージの名前
    • ZONE: 適応するイメージのゾーン
    • PROJECT: 実際の Google Cloud プロジェクト ID
    • TPC_PREFIX: リソース名に使用される接頭辞

スクリプトが正常に実行されると、次のメッセージが出力されます。

Adapted image: IMAGE_NAME

次のステップ

イメージからインスタンスを作成する