管理ワークステーションの作成

このページでは、管理ワークステーション仮想マシン(VM)を初めて作成する方法について説明します。このページでは、プロキシを使用するようにワークステーションの Docker デーモンを構成する方法についても説明します。

既存の管理ワークステーションのアップグレードもご覧ください。

概要

HashiCorp Terraform バージョン 0.11 を使用して、vSphere の管理ワークステーション仮想マシン(VM)をプロビジョニングし、管理ワークステーションを使用して GKE On-Prem をインストールします。管理ワークステーション Open Virtual Appliance(OVA)ファイルをダウンロードし、Terraform を使用して VM を vSphere にデプロイします。

始める前に

  1. 管理ワークステーション OVA をダウンロードします
  2. 管理ワークステーションの概要を確認します

管理ワークステーション OVA のデプロイ

OVA をデプロイする手順は次のとおりです。

  1. DHCP または静的 IP のどちらを使用しているかに応じて、次のいずれかの Terraform 構成を保存します。TF ファイルと TFVARS ファイルの両方を必ず保存してください。TF ファイルは Terraform HCL config であり、TFVARS ファイルは構成で使用する変数を宣言します。

    dhcp.tf

    #########################
    ####### VARIABLES #######
    #########################
    
    # vSphere username
    variable "vsphere_user" { }
    # vSphere password
    variable "vsphere_password" { }
    # vSphere server address
    variable "vsphere_server" { }
    # Install this public key in the created VM
    variable "ssh_public_key_path" { default = "~/.ssh/vsphere_workstation.pub" }
    # vSphere network to use for the VM
    variable "network" { default = "VM Network"}
    # Hostname for the VM
    variable "vm_name" { default = "vsphere-workstation" }
    # vSphere datacenter to create this VM in
    variable "datacenter" { }
    # vSphere datastore to create this VM in
    variable "datastore" { }
    # vSphere cluster to create this VM in
    variable "cluster" { }
    # vSphere resource pool to create this VM in
    variable "resource_pool" { }
    # Number of CPUs for this VM. Recommended minimum 4.
    variable "num_cpus" { default = 4 }
    # Memory in MB for this VM. Recommended minimum 8192.
    variable "memory" { default = 8192 }
    # The VM template to clone
    variable "vm_template" { }
    # Enable the provided Docker registry. If you use your own registry, set to "false"
    variable "registry_enable" { default = "true" }
    # Username to set for the Docker registry
    variable "registry_username" { default = "gke" }
    # Password to set for the Docker registry
    variable "registry_password" { default = "password" }
    # Optional DNS hostname for the registry's certificate
    variable "registry_dns_hostname" { default = "" }
    
    #########################
    ##### FOR UPGRADING #####
    #########################
    # Path on disk to the htpasswd file
    variable "registry_htpasswd" { default = "" } // filepath
    # Path on disk to the certificate for the Docker registry in the admin workstation
    variable "registry_cert" { default = "" } // filepath
    # Path on disk to the registry's CA
    variable "registry_ca" { default = "" } // filepath
    # Path on disk to the registry's private key
    variable "registry_private_key" { default = "" } // filepath
    
    ##########################
    ##########################
    
    provider "vsphere" {
      version        = "~> 1.5"
      user           = "${var.vsphere_user}"
      password       = "${var.vsphere_password}"
      vsphere_server = "${var.vsphere_server}"
    
      # if you have a self-signed cert
      allow_unverified_ssl = true
    }
    
    ### vSphere Data ###
    
    data "vsphere_datastore" "datastore" {
      name          = "${var.datastore}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_datacenter" "dc" {
      name = "${var.datacenter}"
    }
    
    data "vsphere_compute_cluster" "cluster" {
      name          = "${var.cluster}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_resource_pool" "pool" {
      name          = "${var.resource_pool}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_network" "network" {
      name          = "${var.network}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_virtual_machine" "template_from_ovf" {
      name          = "${var.vm_template}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "template_file" "dhcp_ip_config" {
      template = <<EOF
    network:
      version: 2
      ethernets:
        ens192:
          dhcp4: true
    EOF
    }
    
    data "template_file" "user_data" {
      template = <<EOF
    #cloud-config
    apt:
      primary:
        - arches: [default]
          uri: http://us-west1.gce.archive.ubuntu.com/ubuntu/
    write_files:
      - path: /etc/netplan/99-dhcp.yaml
        permissions: '0644'
        encoding: base64
        content: |
          $${dhcp_ip_config}
    runcmd:
      - netplan apply
      - /var/lib/gke/guest-startup.sh $${reg_enable} $${reg_username} $${reg_password} $${reg_dns_hostname} $${reg_htpasswd} $${reg_cert} $${reg_private_key} $${reg_ca}
    EOF
      vars = {
        dhcp_ip_config = "${base64encode(data.template_file.dhcp_ip_config.rendered)}"
    
        reg_enable = "${var.registry_enable}"
        reg_username = "${var.registry_username}"
        reg_password = "${var.registry_password}"
        reg_dns_hostname = "${var.registry_dns_hostname}"
    
        reg_htpasswd = ""
        reg_cert = ""
        reg_private_key = ""
        reg_ca = ""
    
        #########################
        ##### FOR UPGRADING #####
        # reg_htpasswd = "${file(var.registry_htpasswd)}"
        # reg_cert = "${file(var.registry_cert)}"
        # reg_private_key = "${file(var.registry_private_key)}"
        # reg_ca = "${file(var.registry_ca)}"
        #########################
      }
    }
    
    ### vSphere Resources ###
    
    resource "vsphere_virtual_machine" "vm" {
      name             = "${var.vm_name}"
      resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
      datastore_id     = "${data.vsphere_datastore.datastore.id}"
      num_cpus         = "${var.num_cpus}"
      memory           = "${var.memory}"
      guest_id         = "${data.vsphere_virtual_machine.template_from_ovf.guest_id}"
      enable_disk_uuid = "true"
      scsi_type = "${data.vsphere_virtual_machine.template_from_ovf.scsi_type}"
      network_interface {
        network_id   = "${data.vsphere_network.network.id}"
        adapter_type = "${data.vsphere_virtual_machine.template_from_ovf.network_interface_types[0]}"
      }
    
      wait_for_guest_net_timeout = 15
    
      nested_hv_enabled = false
      cpu_performance_counters_enabled = false
    
      disk {
        label            = "disk0"
        size             = "${max(50, data.vsphere_virtual_machine.template_from_ovf.disks.0.size)}"
        eagerly_scrub    = "${data.vsphere_virtual_machine.template_from_ovf.disks.0.eagerly_scrub}"
        thin_provisioned = "${data.vsphere_virtual_machine.template_from_ovf.disks.0.thin_provisioned}"
      }
    
      cdrom {
        client_device = true
      }
    
      vapp {
        properties = {
          hostname    = "${var.vm_name}"
          public-keys = "${file(var.ssh_public_key_path)}"
          user-data   = "${base64encode(data.template_file.user_data.rendered)}"
        }
      }
    
      clone {
        template_uuid = "${data.vsphere_virtual_machine.template_from_ovf.id}"
      }
    }
    
    output "ip_address" {
      value = "${vsphere_virtual_machine.vm.default_ip_address}"
    }

    dhcp.tfvars

    vsphere_user = "administrator@vsphere.local"
    vsphere_password = ""
    # vSphere server IP or DNS name
    vsphere_server = ""
    ssh_public_key_path = "~/.ssh/vsphere_workstation.pub"
    
    vm_name = "admin-workstation"
    
    datastore = ""
    datacenter = ""
    cluster = ""
    resource_pool = ""
    network = "VM Network"
    
    num_cpus = 4
    memory = 8192
    vm_template = "gke-on-prem-admin-appliance-vsphere-1.0.2-gke.3"
    
    # docker registry credentials
    registry_enable = "true"
    registry_username = "gke"
    registry_password = "password"
    registry_dns_hostname = ""
    
    # only needed when re-creating the workstation and you want to
    # reuse registry certs. Each value is a filepath relative to this file.
    # registry_htpasswd=""
    # registry_cert=""
    # registry_ca=""
    # registry_private_key=""

    static-ip.tf

    #########################
    ####### VARIABLES #######
    #########################
    
    # vSphere username
    variable "vsphere_user" { }
    # vSphere password
    variable "vsphere_password" { }
    # vSphere server address
    variable "vsphere_server" { }
    # Install this public key in the created VM
    variable "ssh_public_key_path" { default = "~/.ssh/vsphere_workstation.pub" }
    # vSphere network to use for the VM
    variable "network" { default = "VM Network"}
    # Hostname for the VM
    variable "vm_name" { default = "vsphere-workstation" }
    # vSphere datacenter to create this VM in
    variable "datacenter" { }
    # vSphere datastore to create this VM in
    variable "datastore" { }
    # vSphere cluster to create this VM in
    variable "cluster" { }
    # vSphere resource pool to create this VM in
    variable "resource_pool" { }
    # Number of CPUs for this VM. Recommended minimum 4.
    variable "num_cpus" { default = 4 }
    # Memory in MB for this VM. Recommended minimum 8192.
    variable "memory" { default = 8192 }
    # The VM template to clone
    variable "vm_template" { }
    # The IP address to assign this this VM
    variable "ipv4_address" { }
    # Netmask prefix length
    variable "ipv4_netmask_prefix_length" { }
    # Default gateway to use
    variable "ipv4_gateway" { }
    # DNS resolvers to use
    variable "dns_nameservers" { }
    # Enable the provided Docker registry. If you use your own registry, set to "false"
    variable "registry_enable" { default = "true" }
    # Username to set for the Docker registry
    variable "registry_username" { default = "gke" }
    # Password to set for the Docker registry
    variable "registry_password" { default = "password" }
    # Optional DNS hostname for the registry's certificate
    variable "registry_dns_hostname" { default = "" }
    
    #########################
    ##### FOR UPGRADING #####
    #########################
    # Path on disk to the htpasswd file
    variable "registry_htpasswd" { default = "" } // filepath
    # Path on disk to the certificate for the Docker registry in the admin workstation
    variable "registry_cert" { default = "" } // filepath
    # Path on disk to the registry's CA
    variable "registry_ca" { default = "" } // filepath
    # Path on disk to the registry's private key
    variable "registry_private_key" { default = "" } // filepath
    
    ##########################
    ##########################
    
    provider "vsphere" {
      version        = "~> 1.5"
      user           = "${var.vsphere_user}"
      password       = "${var.vsphere_password}"
      vsphere_server = "${var.vsphere_server}"
    
      # if you have a self-signed cert
      allow_unverified_ssl = true
    }
    
    ### vSphere Data ###
    
    data "vsphere_datastore" "datastore" {
      name          = "${var.datastore}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_datacenter" "dc" {
      name = "${var.datacenter}"
    }
    
    data "vsphere_compute_cluster" "cluster" {
      name          = "${var.cluster}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_resource_pool" "pool" {
      name          = "${var.resource_pool}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_network" "network" {
      name          = "${var.network}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    data "vsphere_virtual_machine" "template_from_ovf" {
      name          = "${var.vm_template}"
      datacenter_id = "${data.vsphere_datacenter.dc.id}"
    }
    
    ##########################
    ### IF USING STATIC IP ###
    ##########################
    data "template_file" "static_ip_config" {
      template = <<EOF
    network:
      version: 2
      ethernets:
        ens192:
          dhcp4: no
          dhcp6: no
          addresses: ["${var.ipv4_address}/${var.ipv4_netmask_prefix_length}"]
          gateway4: ${var.ipv4_gateway}
          nameservers:
            addresses: [${var.dns_nameservers}]
    EOF
    }
    
    data "template_file" "user_data" {
      template = <<EOF
    #cloud-config
    apt:
      primary:
        - arches: [default]
          uri: http://us-west1.gce.archive.ubuntu.com/ubuntu/
    write_files:
      - path: /tmp/static-ip.yaml
        permissions: '0644'
        encoding: base64
        content: |
          $${static_ip_config}
    runcmd:
      - /var/lib/gke/guest-startup.sh $${reg_enable} $${reg_username} $${reg_password} $${reg_dns_hostname} $${reg_htpasswd} $${reg_cert} $${reg_private_key} $${reg_ca}
    EOF
      vars = {
        static_ip_config = "${base64encode(data.template_file.static_ip_config.rendered)}"
    
        reg_enable = "${var.registry_enable}"
        reg_username = "${var.registry_username}"
        reg_password = "${var.registry_password}"
        reg_dns_hostname = "${var.registry_dns_hostname}"
    
        reg_htpasswd = ""
        reg_cert = ""
        reg_private_key = ""
        reg_ca = ""
    
        ########################
        #### FOR UPGRADING #####
        # reg_htpasswd = "${file(var.registry_htpasswd)}"
        # reg_cert = "${file(var.registry_cert)}"
        # reg_private_key = "${file(var.registry_private_key)}"
        # reg_ca = "${file(var.registry_ca)}"
        ########################
      }
    }
    ##########################
    ### IF USING STATIC IP ###
    ##########################
    
    ### vSphere Resources ###
    
    resource "vsphere_virtual_machine" "vm" {
      name             = "${var.vm_name}"
      resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
      datastore_id     = "${data.vsphere_datastore.datastore.id}"
      num_cpus         = "${var.num_cpus}"
      memory           = "${var.memory}"
      guest_id         = "${data.vsphere_virtual_machine.template_from_ovf.guest_id}"
      enable_disk_uuid = "true"
      scsi_type = "${data.vsphere_virtual_machine.template_from_ovf.scsi_type}"
      network_interface {
        network_id   = "${data.vsphere_network.network.id}"
        adapter_type = "${data.vsphere_virtual_machine.template_from_ovf.network_interface_types[0]}"
      }
    
      wait_for_guest_net_timeout = 15
    
      nested_hv_enabled = false
      cpu_performance_counters_enabled = false
    
      disk {
        label            = "disk0"
        size             = "${max(50, data.vsphere_virtual_machine.template_from_ovf.disks.0.size)}"
        eagerly_scrub    = "${data.vsphere_virtual_machine.template_from_ovf.disks.0.eagerly_scrub}"
        thin_provisioned = "${data.vsphere_virtual_machine.template_from_ovf.disks.0.thin_provisioned}"
      }
    
      cdrom {
        client_device = true
      }
    
      vapp {
        properties = {
          hostname    = "${var.vm_name}"
          public-keys = "${file(var.ssh_public_key_path)}"
          user-data   = "${base64encode(data.template_file.user_data.rendered)}"
        }
      }
    
      clone {
        template_uuid = "${data.vsphere_virtual_machine.template_from_ovf.id}"
      }
    }
    
    output "ip_address" {
      value = "${vsphere_virtual_machine.vm.default_ip_address}"
    }

    static-ip.tfvars

    vsphere_user = "administrator@vsphere.local"
    vsphere_password = ""
    # vSphere server IP or DNS name
    vsphere_server = ""
    ssh_public_key_path = "~/.ssh/vsphere_workstation.pub"
    
    vm_name = "admin-workstation"
    
    datastore = ""
    datacenter = ""
    cluster = ""
    resource_pool = ""
    network = "VM Network"
    
    num_cpus = 4
    memory = 8192
    vm_template = "gke-on-prem-admin-appliance-vsphere-1.0.2-gke.3"
    
    # XXX.XXX.XXX.XXX
    ipv4_address = "100.115.250.100"
    # Eg 22
    ipv4_netmask_prefix_length = "22"
    # XXX.XXX.XXX.XXX
    ipv4_gateway = "100.115.251.254"
    # comma separated DNS servers
    dns_nameservers = "8.8.8.8,8.8.4.4"
    
    # docker registry credentials
    registry_enable = "true"
    registry_username = "gke"
    registry_password = "password"
    registry_dns_hostname = ""
    
    # only needed when re-creating the workstation and you want to
    # reuse registry certs. Each value is a filepath relative to this file.
    # registry_htpasswd=""
    # registry_cert=""
    # registry_ca=""
    # registry_private_key=""
  2. 管理ワークステーション VM に対して認証できるように、SSH Key-Value ペアを作成します。

    ssh-keygen -t rsa -f ~/.ssh/vsphere_workstation -N ""
  3. Terraform ファイルのディレクトリを作成します。

    mkdir [TERRAFORM_DIR]

    [TERRAFORM_DIR] は、Terraform ファイルを保持するディレクトリのパスです。

  4. ホスト ネットワークの構成が [TERRAFORM_DIR]/terraform.tf[TERRAFORM_DIR]/terraform.tfvars に一致する Terraform config をコピーします。

  5. terraform.tfvars で、vSphere 環境の要素を指定する次の変数の値を入力します。

    • vsphere_server
    • vspher_user
    • vsphere_password
    • datastore
    • datacenter
    • cluster
    • resource_pool
    • network
    • vm_template(前の手順で govc markastemplate を実行して作成済み。)

    vm_name の値を入力します。これは、作成する管理ワークステーションの名前です。任意の名前を使用できます。

    静的 IP アドレスを使用している場合は、次の変数の値を入力します。

    • ipv4_address
    • ipv4_netmask_prefix_length
    • ipv4_gateway
    • dns_nameservers

    管理ワークステーション VM で実行される Docker レジストリを使用する場合は、registry_enable を「true」に設定します。また、以下の変数の値を入力します。

    • registry_username
    • registry_password

    管理ワークステーション VM で実行される Docker レジストリの DNS ホスト名を使用する場合は、registry_dns_hostname の値を入力します。これは、管理ワークステーション VM に静的 IP アドレスがない場合に便利です。

    独自の非公開 Docker レジストリを使用する場合は、registry_enable を「false」に設定します。

  6. 管理ワークステーション VM を作成します。これには、数分かかることがあります。

    cd [TERRAFORM_DIR]
    terraform init && terraform apply -auto-approve -input=false

管理ワークステーションに SSH 接続する

  1. Terraform 構成が含まれているディレクトリに移動します。

  2. 管理ワークステーション VM の IP アドレスを取得します。

    terraform output ip_address
  3. 生成された鍵と IP アドレスを使用して、管理ワークステーションに SSH 接続します。

    ssh -i ~/.ssh/vsphere_workstation ubuntu@$(terraform output ip_address)

    アドレスを使用する場合は、次のようにします。

    ssh -i ~/.ssh/vsphere_workstation ubuntu@[IP_ADDRESS]

管理ワークステーションが正しく設定されていることを確認する

gkectldocker がインストールされていることを確認します。

gkectl version
docker version

registry_enable を「true」に設定すると、GKE On-Prem コンポーネントの Docker イメージが管理ワークステーション VM の Docker デーモンに読み込まれたことを確認できます。

docker images

すべての Docker イメージが読み込まれるまでに 15 分以上かかることがあります。

最終的に、管理ワークステーション VM によって Docker レジストリが実行されていることを確認できます。

docker ps

出力には、Docker レジストリが実行されているコンテナが表示されます。

IMAGE ...                      COMMAND ...              NAMES
docker-registry:v2.7.1-gke.0   "registry serve /e..."   registry2

プロキシを介して pull するように Docker を構成する

ネットワークがプロキシの背後で実行され、管理ワークステーション VM が Docker レジストリを実行している場合、管理ワークステーションで実行される Docker デーモンをプロキシ経由でイメージを pull するように構成する必要があります。

  1. HTTP プロキシと HTTPS プロキシのアドレスを収集します。

  2. プロキシを使用せずに接続する必要があるすべてのホストの IP アドレスとホスト名を収集します。

    • vCenter Server の IP アドレス。
    • すべての ESXi ホストの IP アドレス。
    • ロードバランサに構成する IP アドレス。
    • 192.168.0.0/16 の範囲。

    管理ワークステーションで、これらのアドレスを no_proxy 変数に追加します。

    printf -v no_proxy '%s,' [ADDRESSES];
    

    必要に応じて、後で参照できるように範囲を環境変数にエクスポートできます。アプリケーションとプロセスは、この変数を使用する場合があります。

    export no_proxy="${no_proxy%,}";
    
  3. /root/.docker/config.json/home/[ユーザー]/.docker/config.json、または設定に応じた場所に保存された Open Docker の構成ファイル

  4. config.json 内で、次の行を追加します。

    "proxies": {
    
    "default": {
           "httpProxy": "[HTTP_PROXY]",
           "httpsProxy": "[HTTPS_PROXY]",
           "noProxy": "[ADDRESSES]"
               }
    }

    ここで

    • [HTTP_PROXY] は HTTP プロキシです(存在する場合)。
    • [HTTPS_PROXY] は HTTPS プロキシです(存在する場合)。
    • [ADDRESSES] は、プロキシなしで接続する必要があるアドレスとホスト名のカンマ区切りのリストです。
  5. Docker を再起動して変更を反映します。

    sudo systemctl restart docker

トラブルシューティング

詳しくは、トラブルシューティングをご覧ください。

Terraform の vSphere プロバイダのセッション数の上限

GKE On-Prem は Terraform の vSphere プロバイダを使用して、vSphere 環境で VM を起動します。プロバイダのセッション数は最大 1,000 です。現在の実装では、使用後にアクティブなセッションが終了しません。実行中のセッションが多すぎると、503 エラーが発生する可能性があります。

セッションは 300 秒後に自動的に終了します。

現象

実行中のセッションが多すぎると、次のエラーが発生します。

Error connecting to CIS REST endpoint: Login failed: body:
  {"type":"com.vmware.vapi.std.errors.service_unavailable","value":
  {"messages":[{"args":["1000","1000"],"default_message":"Sessions count is
  limited to 1000. Existing sessions are 1000.",
  "id":"com.vmware.vapi.endpoint.failedToLoginMaxSessionCountReached"}]}},
  status: 503 Service Unavailable
考えられる原因

環境内で実行されている Terraform プロバイダのセッションが多すぎます。

解決策

現時点で、これは意図したとおりに機能しています。セッションは 300 秒後に自動的に終了します。詳細については、GitHub の問題 #618 をご覧ください。

Docker 用のプロキシの使用: oauth2: cannot fetch token

現象

プロキシの使用中に次のエラーが発生します。

oauth2: cannot fetch token: Post https://oauth2.googleapis.com/token: proxyconnect tcp: tls: oversized record received with length 20527
考えられる原因

HTTP ではなく HTTPS プロキシを指定した可能性があります。

解決策

Docker の構成で、プロキシ アドレスを https:// ではなく http:// に変更します。

ライセンスが有効であることを確認する

特に試用版ライセンスを使用している場合は、ライセンスが有効であることを確認してください。F5、ESXi ホスト、または vCenter ライセンスの有効期限が切れた場合、予期しないエラーが発生することがあります。

openssl で管理ワークステーション OVA を検証できない

現象

管理ワークステーションの OVA ファイルに対して openssl dgst を実行しても Verified OK が返されない

考えられる原因

OVA ファイルに問題があるため、正常な検証ができません。

解決策

管理ワークステーション OVA をダウンロードするの説明に従って、管理ワークステーションの OVA をもう一度ダウンロードしてデプロイしてみてください。問題が解決しない場合は、Google にお問い合わせください。

次のステップ

GKE On-Prem をインストールする前に、次のような構成オプションを使用できます。