🐔

Migarte to Containers を使用して Web アプリケーションをお手軽に GCE から GKE へ移行

2024/12/25に公開

はじめに

こんにちは。
クラウドエースの中野(大)と申します。

今回は Google Cloud の移行プロダクトの 1 つである Migrate to Containers を使用して GCE 上の Web アプリケーションを GKE へ移行した際の手順や自分なりのポイントについて執筆しました。

この記事の位置付け

今後 仮想マシン (VM) から GKE へ Web アプリケーションを移行したいと考えている方や Migrate to Containers の名前を知っているが、使用方法が分からないといった方に向けて執筆しました。

Migrate to Containers とは

Migrate to Containers は、VM インスタンスで実行される従来のアプリケーションをモダナイズして、GKE や Cloud Run で実行されるネイティブコンテナに変換することができるサービスです。

Apache、Tomcat、WordPress、Windows IIS アプリケーションのモダナイゼーション、Linux ベースのアプリケーションのコンテナ化をサポートしています。

移行フロー

以下のような形で Migrate to Containers を使用して移行します。
01.png

  1. 移行元 VM のファイルシステムを中継 VM がコピーし、それを元に移行アーティファクトを生成
  2. 移行アーティファクトを移行先 GKE へデプロイ

Migrate to Containers のポイント

  • 移行元 VM で Migrate to Containers を使用するのではなく、中継 VM を建ててそこで Migrate to Containers を使用するようなイメージです。
  • 中継 VM は移行元 VM よりもディスクサイズを大きくする必要があります(例だと移行元 VM ディスクの 2.5 倍ほどで実行)。
  • 中継 VM に移行元 VM のファイルシステムをコピーしてそこから GKE へ移行させるような形になります。
  • Migrate to Containers は GUI ではなく CLI です。

移行の検証

Google Cloud の公式ドキュメント Migrate to Containers CLI を使用して Linux VM を移行するを参考に実施しました。
また、検証をしていて Google Cloud の公式ドキュメント通りの設定で動作しなかった部分もありましたので、その点についても記載します。

本記事の手順では以下のように表現します。

  • 移行元 VM : source-vm
  • Migrate to Containers を実行する中継 VM : local-vm
  • 移行先 GKE : test-cluster
移行元 VM 中継 VM 移行先 GKE(ノード)
マシンタイプ e2-medium e2-medium e2-medium
ゾーン(ロケーション) asia-northeast1-a asia-northeast1-a asia-northeast1-a
OS ubuntu ubuntu ubuntu
ディスク 20GB 50GB 100GB

移行元 Web アプリケーションの作成

  1. 移行元 VM の作成
    ここでは移行元 VM として GCE を使用します。
gcloud compute instances create source-vm \
  --zone=asia-northeast1-a --machine-type=e2-medium  \
  --subnet=default --scopes="cloud-platform" \
  --tags=http-server,https-server --image=ubuntu-2204-jammy-v20240208 \
  --image-project=ubuntu-os-cloud --boot-disk-size=20GB --boot-disk-type=pd-standard \
  --boot-disk-device-name=source-vm
  1. HTTP でアクセスを許可するファイアウォールルールを作成
gcloud compute firewall-rules create default-allow-http \
  --direction=INGRESS --priority=1000 --network=default --action=ALLOW \
  --rules=tcp:80 --source-ranges=0.0.0.0/0 --target-tags=http-server
  1. 1 で作成した GCE インスタンスへ接続
  2. 移行元 GCE インスタンスに Apache のインストール
sudo apt-get update && sudo apt-get install apache2 -y
  1. 検証用 Web ページの作成
echo '<!doctype html><html><body><h1>Hello World!</h1></body></html>' | sudo tee /var/www/html/index.html
  1. Google Cloud コンソールの VM インスタンスで source-vm の外部 IP アドレスをコピーし、ブラウザ上で「http://<EXTERNAL-IP>」を入力後、Hello World! が表示されることを確認

Migrate to Containers を動作する中継 GCE の作成

  1. 中継 GCE インスタンスの作成
gcloud compute instances create local-vm \
  --zone=asia-northeast1-a --machine-type=e2-medium  \
  --subnet=default --scopes="cloud-platform" \
  --tags=http-server,https-server --image=ubuntu-2204-jammy-v20240208 \
  --image-project=ubuntu-os-cloud --boot-disk-size=50GB --boot-disk-type=pd-standard \
  --boot-disk-device-name=local-vm

移行先 GKE クラスタの作成

  1. 移行先 GKE クラスタの作成
gcloud container clusters create test-cluster \
  --zone=asia-northeast1-a --machine-type=e2-medium \
  --image-type=ubuntu_containerd --num-nodes=1 \
  --logging=SYSTEM,WORKLOAD,API_SERVER,SCHEDULER,CONTROLLER_MANAGER

今回の移行方法が Linux VM container による移行であるため、 GKE クラスタのノードの OS を Ubuntu にします。

Migrate to Containers を実行する中継 VM の準備(local-vm での操作)

  1. local-vm へ接続
  2. Google Cloud CLI の準備
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg

echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list

sudo apt-get update && sudo apt-get install google-cloud-cli

gcloud init
  1. Docker のインストール
curl -fsSL https://get.docker.com -o install-docker.sh

sudo sh install-docker.sh

sudo usermod -aG docker $USER

newgrp docker
  1. Skaffold のインストール
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && \
sudo install skaffold /usr/local/bin/
  1. Migrate to Containers CLI のダウンロード
curl -O "https://m2c-cli-release.storage.googleapis.com/$(curl -s https://m2c-cli-release.storage.googleapis.com/latest)/linux/amd64/m2c"
chmod +x ./m2c

移行元 VM のファイルシステムのコピー(local-vm での操作)

移行元 VM ファイル システムをコピーする際に、Migrate to Containers CLI は、デフォルトのフィルタを使用して、コピーされたファイルシステムのサイズを小さくします。
今回は Apache サーバを移行するため、「/var/log」 が必要です。
0. local-vm へ接続

  1. filters.txt ファイルにあるデフォルトの Migrate to Containers フィルタのリストを取得
./m2c copy default-filters > filters.txt
  1. filters.txt ファイルを開き、「- /var/log/*」 を削除
  2. 移行元 GCE インスタンスのファイルシステムをコピー
./m2c copy gcloud \
  --project <プロジェクト ID> --zone asia-northeast1-a \
  --vm-name source-vm --output vm-filesystem \
  --filters filters.txt
  1. 移行計画を作成
./m2c analyze \
  --source vm-filesystem --plugin linux-vm-container \
  --output analysis-output
  1. 移行アーティファクトを生成
./m2c generate --input analysis-output --output migration-artifacts

ワークロードのデプロイ(local-vm での操作)

  1. local-vm へ接続
  2. gke-gcloud-auth-plugin プラグインをインストール
sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin
  1. kubectl コマンドをインストール
sudo apt-get install kubectl
  1. GKE クラスタ(test-cluster)に接続
gcloud container clusters get-credentials test-cluster  --zone asia-northeast1-a --project <プロジェクト ID>
  1. migration-artifacts フォルダへ遷移
cd migration-artifacts
  1. deployment_spec.yaml ファイルを開き、以下の設定を追加
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
   anthos-migrate.cloud.google.com/type: linux-container
   migrate-for-anthos-optimization: "true"
   migrate-for-anthos-version: m2c-cli-1.2.2
name: linux-system
spec:
clusterIP: None
selector:
   app: linux-system
type: ClusterIP
# 以下から追加
---
apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  selector:
    app: linux-system  # Deploymentのラベルと一致させる
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer
---
  1. 移行した VM をデプロイ
skaffold run -d eu.gcr.io/<プロジェクト ID>
  1. 移行後の VM の外部 IP アドレスを取得
kubectl get service hello-service
  1. 以下が表示される
nakano@local-vm:~/migration-artifacts$ kubectl get service hello-service
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
hello-service   LoadBalancer   <CLUSTER-IP>    <EXTERNAL-IP>    80:31496/TCP    7m53s

9.ブラウザ上で「http://<EXTERNAL-IP>」を入力し、遷移したのち移行前と同様の画面が表示されることを確認

移行後の確認

ここで Google Cloud のクイックスタートにはありませんが、移行前の VM と移行後の GKE でいくつか確認したいと思います。

ファイルシステムの確認

移行前後でファイルシステムがどのくらい変化があるか確認します。

まず移行前の VM から確認していきます。
移行前 VM へ SSH 接続し、df -h コマンドを実行します。

root@source-vm:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       9.6G  3.8G  5.8G  40% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           783M  980K  782M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
efivarfs         56K   24K   27K  48% /sys/firmware/efi/efivars
/dev/sda15      105M  6.1M   99M   6% /boot/efi
tmpfs           392M  4.0K  392M   1% /run/user/1001

次に移行後の GKE のファイルシステムを確認します。

  1. cloud shell を起動し、GKE の pod 名を取得します。
hogehoge@cloudshell:~ (project名)$ kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
linux-system-666d7578-4wd4l   1/1     Running   0          2d14h
  1. pod 名を取得後、GKE コンテナへログインします。
hogehoge@cloudshell:~ (project名)$ kubectl exec -it linux-system-666d7578-4wd4l /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@linux-system-666d7578-4wd4l:/#

これで GKE コンテナへのログインが完了しました。

  1. 移行前 VM と同様に df -h コマンドを実行します。
root@linux-system-666d7578-4wd4l:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          97G   11G   86G  12% /
tmpfs            64M     0   64M   0% /dev
/dev/root        97G   11G   86G  12% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs           2.8G   12K  2.8G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs           2.0G     0  2.0G   0% /proc/acpi
tmpfs           2.0G     0  2.0G   0% /proc/scsi
tmpfs           2.0G     0  2.0G   0% /sys/firmware
tmpfs           2.0G     0  2.0G   0% /sys/devices/virtual/powercap

GKE はコンテナであるため、VM に比べディレクトリサイズが増加しています。
そのため、GKE へ移行する際は移行元 VM のディスクサイズよりも多めにディスクサイズを確保しておく必要があります。

Apache2 の確認

次に、Apache2 のディレクトリの中身も確認してみます。

  • 移行前 VM
root@source-vm:/etc/apache2# ls -lh
total 80K
-rw-r--r-- 1 root root 7.1K Jul 17 18:57 apache2.conf
drwxr-xr-x 2 root root 4.0K Oct 18 01:07 conf-available
drwxr-xr-x 2 root root 4.0K Oct 18 01:07 conf-enabled
-rw-r--r-- 1 root root 1.8K Dec  4  2023 envvars
-rw-r--r-- 1 root root  31K Dec  4  2023 magic
drwxr-xr-x 2 root root  12K Oct 18 01:07 mods-available
drwxr-xr-x 2 root root 4.0K Oct 18 01:07 mods-enabled
-rw-r--r-- 1 root root  320 Dec  4  2023 ports.conf
drwxr-xr-x 2 root root 4.0K Oct 18 01:07 sites-available
drwxr-xr-x 2 root root 4.0K Oct 18 01:07 sites-enabled
  • 移行後 GKE
root@cs-22667700496-default:/etc/apache2# ls -lh
total 8.0K
drwxr-xr-x 2 root root 4.0K Dec 15 08:10 conf-available
drwxr-xr-x 2 root root 4.0K Dec  2 12:36 mods-available

上記 2 ディレクトリのみ移行されていました。
また、移行前後で conf-available、mods-available の中身も変わっており、
移行後の conf-available ディレクトリの中には php8.3-cgi.conf、mods-available は空のディレクトリでした。
詳細は割愛しますが、移行前の conf-available ディレクトリの中にはいくつかの conf ファイル、mods-available ディレクトリの中には多くの load ファイルが存在していました。

conf-available ディレクトリの php8.3-cgi.conf の内容は以下です。

root@cs-22667700496-default:/etc/apache2/conf-available# cat php8.3-cgi.conf 
# This file replaces old system MIME types and sets them only in the
# Apache webserver

# Using (?:pattern) instead of (pattern) is a small optimization that
# avoid capturing the matching pattern (as $1) which isn't used here
# application/x-httpd-php                        phtml php
<FilesMatch ".+\.ph(?:ar|p|tml)$">
    SetHandler application/x-httpd-php
</FilesMatch>
# application/x-httpd-php-source                 phps
<FilesMatch ".+\.phps$">
    SetHandler application/x-httpd-php-source
    # Deny access to raw php sources by default
    # To re-enable it's recommended to enable access to the files
    # only in specific virtual host or directory
    Require all denied
</FilesMatch>
# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(?:ar|p|ps|tml)$">
    Require all denied
</FilesMatch>

# To enable PHP CGI site-wide, just uncomment following lines, however
# as a security measure, it's recommended to enable PHP just in the
# specific virtual servers or just specific directories

#ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
#<Directory "/usr/lib/cgi-bin">
#    AllowOverride None
#    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
#    Order allow,deny
#    Allow from all
#</Directory>
#Action application/x-httpd-php /cgi-bin/php8.3

上記のファイルにより Apche ウェブサーバで PHP ファイルを処理しているようです。

上記から移行元 VM のファイルをそのまま移行するのではなく、移行先の GKE で動作するような形で conf ファイルを生成しているように感じました。

index ファイルの確認

最後に index ファイルの中身も確認しようと思います。

  • 移行前 VM
root@source-vm:/var# cd /var/www/html
root@source-vm:/var/www/html# ls -l
total 4
-rw-r--r-- 1 root root 63 Oct 18 01:11 index.html
root@source-vm:/var/www/html# cat index.html 
<!doctype html><html><body><h1>Hello World!</h1></body></html>
  • 移行後 GKE
root@linux-system-666d7578-4wd4l:/# cd /var/www/html
root@linux-system-666d7578-4wd4l:/var/www/html# ls -l
total 4
-rw-r--r-- 1 root root 63 Oct 18 01:11 index.html
root@linux-system-666d7578-4wd4l:/var/www/html# cat index.html 
<!doctype html><html><body><h1>Hello World!</h1></body></html>

index ファイルの中は特に変更なく移行できていることが確認できました。

まとめ

Migrate to Containers を使用して GCE 上の Web アプリケーションを GKE へ移行する手順について記載していきました。
個人的な一番の驚きポイントとして感じたのは移行元の仮想マシンに Migrate to Containers CLI を導入する形ではなくて、中継 VM に導入して実施するのが意外に感じました。
また、Migrate to Containers は GKE だけでなく Cloud Run にも移行することが可能です。Cloud Run への移行については検証でき次第またブログ記事として執筆したいと考えています。

Discussion