GCP: Compute Engine

CLI

インスタンスの作成

gcloud compute instances create <instance name>

# addressは指定しなくてもいい
gcloud compute instances create hoge \
--boot-disk-device-name=hoge-disk \
--boot-disk-size=10GB \
--boot-disk-type=pd-ssd \
--machine-type=n1-standard-2 \
--address *.*.*.*

使えるイメージのリストを取得

gcloud compute images list

インスタンスの一覧取得

gcloud compute instances list

インスタンスへの接続

インスタンスへの接続にはgcloud compute sshを使う。

gcloud compute ssh <instance-name> --zone <zone-name>

ローカル ⇔ インスタンス間でファイルのコピーをするにはgcloud compute scpを使う。

# ローカルマシンからインスタンスへコピー
gcloud compute scp ~/file-1 my-instance:~/remote-destination --zone us-central1-a

# インスタンスからローカルマシンへコピー
gcloud compute scp my-instance:~/file-1 ~/local-destination --zone us-central1-a

sshscpを直接使いたいときは以下のコマンドで~/.ssh/configを生成する。

# ~/.ssh/config を生成
gcloud compute config-ssh

# 以降、sshコマンドで直接接続できる
ssh <instance-name>.<region-name>.<project -name>

インスタンスの削除

instances deleteコマンドを使う。

gcloud compute instances delete <instance-name> --zone <zone-name>

インスタンスを削除すると自動で関連付けられている永続ディスクも削除される。 永続ディスクを削除したくない場合は--keep-disksフラグを使う。

起動スクリプトを渡す

Ref: https://cloud.google.com/compute/docs/startupscript?hl=ja

インスタンスの起動後に ssh 接続できるようになるまで待つ

スクリプトでインスタンスの起動とインスタンスへの接続を同時に行う場合にハマるポイント。 gcloud compute instances createの直後に gcloud compute sshすると Connection Refused になってしまう。 これは、createがインスタンスが起動するまでは待ってくれるけど ssh 接続できるようになるまでは待ってくれていないために起こる。

gcloud compute instances create my-instance --zone asia-northeast1-b

# ここですぐsshするとつながらない
# gcloud compute ssh my-user@my-instance

# 22番が開くまで待つ
IP=$(gcloud compute instances list | awk '/'my-instances'/ {print $5}')
if nc -w 5 -z $IP 22; then
    echo "OK! Ready for heavy metal"
else
    echo "Maybe later?"
fi

# sshできる
gcloud compute ssh my-user@my-instance

ディスクを追加・マウントする

ディスクを作成する。

gcloud compute disks create <name> \
    --size 30 \
    --type pd-ssd \
    --zone asia-northeast1-b

ディスクを VM インスタンスに割り当てる。

gcloud compute instances attach-disk <INSTANCE_NAME> \
    --disk <DISK_NAME>

ディスクをフォーマットする。

# ディスクを割り当てたVM上で実行すること

# デバイスの確認。素のUbuntu18.04にディスクを1つ割り当てるとsdbという名前で認識される
sudo lsblk

# ディスクをフォーマットする
sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb

マウントするディレクトリを作る。

mkdir -p /mnt/disks/dev

# マウントして全ユーザに対して書き込み権限を与える
sudo mount -o discard,defaults /dev/sdb /mnt/disks/dev
sudo chmod a+w /mnt/disks/dev

# 起動時に自動マウントする
echo UUID=`sudo blkid -s UUID -o value /dev/sdb` /mnt/disks/dev ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab

Ref: https://cloud.google.com/compute/docs/disks/add-persistent-disk?hl=ja#create_disk

VM シャットダウン時に Pub/Sub で通知する

Ref: https://stackoverflow.com/questions/49012909/publish-to-a-topic-using-google-cloud-pubsub-within-compute-engine

アイドル状態になったら自動シャットダウンさせる(Ubuntu)

cron_shutdownを作る。

*/5 * * * * root /root/shutdown_auto.sh

shutdown_auto.shを作る。

#!/bin/bash

UPTIME_MINUTE=$(echo $(awk '{print $1}' /proc/uptime) / 60 | bc)

if [ $UPTIME_MINUTE -lt 15 ] ; then
    exit 0
fi
if [ 480 -lt $UPTIME_MINUTE ] ; then
    sudo shutdown -h now
    exit 0
fi
sudo find /home -type f -mmin -15 | [ $(wc -c) -eq 0 ] && sudo shutdown -h now

メタデータを追加する

gcloud compute instances add-metadata KEY1=VALUE1,KEY2=VALUE2...

# 起動スクリプトとシャットダウンスクリプトを追加
gcloud compute instances add-metadata \
    shutdown-script="gcloud pubsub topics publish dev-info --message 'VM powered off...'",startup-script="gcloud pubsub topics publish dev-info --message 'VM powered on!!'"

VM インスタンスのポートを外部に公開する

次の手順でポートを外部に公開できる

  1. 好きなタグ名でファイアウォールルールを作成する
  2. VM インスタンスに 1 で作成したネットワークタグを設定する

Kafka 用にポート 2181 と 9092 を公開するファイアウォール設定の例

NAME='kafka'
TAG='use-kafka'
gcloud compute firewall-rules create $NAME \
    --network default \
    --priority 1000 \
    --direction ingress \
    --action allow \
    --target-tags $TAG \
    --rules tcp:2181,tcp:9092

Ref: ファイアウォール ルールを作成する

ヘルスチェック

https://cloud.google.com/load-balancing/docs/health-checks?hl=ja

ヘルスチェックからのトラフィックを許可するファイアウォールの作成

以下のヘルスチェックのソース IP 範囲を指定してファイアウォールを作成する。

  • 35.191.0.0/16
  • 130.211.0.0/22

NAT ゲートウェイ構築

https://cloud.google.com/vpc/docs/special-configurations?hl=ja#

https://cloud.google.com/vpc/docs/special-configurations#multiple-natgateways

Tips

GPU つきの Windows サーバーを作成する

PROJECT_ID="my-project"
NAME="win-vm"
gcloud beta compute --project=$PROJECT_ID instances create $NAME \
  --zone=asia-northeast1-a \
  --machine-type=n1-standard-8 \
  --subnet=default \
  --no-restart-on-failure \
  --maintenance-policy=TERMINATE \
  --preemptible \
  --accelerator=type=nvidia-tesla-t4,count=1 \
  --image-family windows-2019 \
  --image-project=windows-cloud \
  --boot-disk-size=300GB \
  --boot-disk-type=pd-standard \
  --boot-disk-device-name=$NAME

Chrome をインストールする。

$LocalTempDir = $env:TEMP; $ChromeInstaller = "ChromeInstaller.exe"; (new-object    System.Net.WebClient).DownloadFile('http://dl.google.com/chrome/install/375.126/chrome_installer.exe', "$LocalTempDir\$ChromeInstaller"); & "$LocalTempDir\$ChromeInstaller" /silent /install; $Process2Monitor =  "ChromeInstaller"; Do { $ProcessesFound = Get-Process | ?{$Process2Monitor -contains $_.Name} | Select-Object -ExpandProperty Name; If ($ProcessesFound) { "Still running: $($ProcessesFound -join ', ')" | Write-Host; Start-Sleep -Seconds 2 } else { rm "$LocalTempDir\$ChromeInstaller" -ErrorAction SilentlyContinue -Verbose } } Until (!$ProcessesFound)

Ref:
https://www.snel.com/support/install-chrome-in-windows-server/

startupScript(起動スクリプト)のログを表示する

起動スクリプトのログは次のファイルに書き込まれる。

  • CentOS、RHEL: /var/log/messages
  • Debian: /var/log/daemon.log
  • Ubuntu 14.04、16.04、16.10: /var/log/syslog
  • SLES 11 および 12: /var/log/messages

Ref:
起動スクリプトの実行  |  Compute Engine ドキュメント  |  Google Cloud

SFTP サーバ構築

startup.shを書く。

#!/usr/bin/env bash
set -eu

groupadd sftp_users
useradd -m -G sftp_users sftp-user
echo "sftp-user:sftp-password" | chpasswd

chown root /home/sftp-user
mkdir /home/sftp-user/upload
chown sftp-user /home/sftp-user/upload

cp /etc/ssh/sshd_config /etc/ssh/sshd_config-org
sed -i 's/\/usr\/lib\/openssh\/sftp-server/internal-sftp/' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config

cat >> /etc/ssh/sshd_config  << EOF
Match group sftp_users
  ChrootDirectory %h
  X11Forwarding no
  AllowTcpForwarding no
  ForceCommand internal-sftp
EOF

systemctl restart sshd

Terraform で構築する例:

resource "google_compute_instance" "sftp-server" {
  name         = "sftp-server"
  machine_type = "n1-standard-1"
  metadata_startup_script = "${file("startup_sftp_server.sh")}"

  boot_disk {
    initialize_params {
      image = "gce-uefi-images/ubuntu-1804-lts"
    }
  }
}

sftpコマンドで外部から接続する。

sftp sftp-user@<IP>
# password: sftp-password

sftp>