17170: Merge branch 'master'
authorTom Clegg <tom@curii.com>
Thu, 14 Jan 2021 16:08:46 +0000 (11:08 -0500)
committerTom Clegg <tom@curii.com>
Thu, 14 Jan 2021 16:08:46 +0000 (11:08 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

doc/admin/spot-instances.html.textile.liquid
doc/install/config.html.textile.liquid
doc/install/crunch2-cloud/install-compute-node.html.textile.liquid
doc/install/crunch2-cloud/install-dispatch-cloud.html.textile.liquid
doc/install/install-shell-server.html.textile.liquid
doc/sdk/java-v2/index.html.textile.liquid
lib/cloud/azure/azure.go
lib/cloud/azure/azure_test.go
services/login-sync/bin/arvados-login-sync

index 7f49d6961292f7371436cb04cbe3892a1a0efadb..07b72150295c5bb7ea34eea1bc36e379e956d3e8 100644 (file)
@@ -12,11 +12,11 @@ SPDX-License-Identifier: CC-BY-SA-3.0
 
 This page describes how to enable preemptible instances.  Preemptible instances typically offer lower cost computation with a tradeoff of lower service guarantees.  If a compute node is preempted, Arvados will restart the computation on a new instance.
 
-Currently Arvados supports preemptible instances using AWS spot instances.
+Currently Arvados supports preemptible instances using AWS and Azure spot instances.
 
 h2. Configuration
 
-To use preemptible instances, set @UsePreemptibleInstances: true@ and add entries to @InstanceTypes@ with @Preemptible: true@ to @config.yml@.  Typically you want to add both preemptible and non-preemptible entries for each cloud provider VM type.  The @Price@ for preemptible instances is the maximum bid price, the actual price paid is dynamic and may be lower.  For example:
+To use preemptible instances, set @UsePreemptibleInstances: true@ and add entries to @InstanceTypes@ with @Preemptible: true@ to @config.yml@.  Typically you want to add both preemptible and non-preemptible entries for each cloud provider VM type.  The @Price@ for preemptible instances is the maximum bid price, the actual price paid is dynamic and will likely be lower.  For example:
 
 <pre>
 Clusters:
@@ -42,11 +42,17 @@ Clusters:
 
 When @UsePreemptibleInstances@ is enabled, child containers (workflow steps) will automatically be made preemptible.  Note that because preempting the workflow runner would cancel the entire workflow, the workflow runner runs in a reserved (non-preemptible) instance.
 
-If you are using "arvados-dispatch-cloud":{{site.baseurl}}/install/crunch2-cloud/install-dispatch-cloud.html no additional configuration is required.
+No additional configuration is required, "arvados-dispatch-cloud":{{site.baseurl}}/install/crunch2-cloud/install-dispatch-cloud.html will now start preemptible instances where appropriate.
+
+h3. Cost Tracking
+
+Preemptible instances prices are declared at instance request time and defined by the maximum price that the user is willing to pay per hour. By default, this price is the same amount as the on-demand version of each instance type, and this setting is the one that @arvados-dispatch-cloud@ uses for now, as it doesn't include any pricing data to the spot instance request.
+
+For AWS, the real price that a spot instance has at any point in time is discovered at the end of each usage hour, depending on instance demand. For this reason, AWS provides a data feed subscription to get hourly logs, as described on "Amazon's User Guide":https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html.
 
 h2. Preemptible instances on AWS
 
-For general information, see "using Amazon EC2 spot instances":https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html .
+For general information, see "using Amazon EC2 spot instances":https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html.
 
 h3. Permissions
 
@@ -58,9 +64,12 @@ BaseHTTPError: AuthFailure.ServiceLinkedRoleCreationNotPermitted: The provided c
 
 The account needs to have a service linked role created. This can be done by logging into the AWS account, go to _IAM Management_ &rarr; _Roles_ and create the @AWSServiceRoleForEC2Spot@ role by clicking on the @Create@ button, selecting @EC2@ service and @EC2 - Spot Instances@ use case.
 
-h3. Cost Tracking
+h2. Preemptible instances on Azure
+
+For general information, see "Use Spot VMs in Azure":https://docs.microsoft.com/en-us/azure/virtual-machines/spot-vms.
 
-Amazon's Spot instances prices are declared at instance request time and defined by the maximum price that the user is willing to pay per hour. By default, this price is the same amount as the on-demand version of each instance type, and this setting is the one that @arvados-dispatch-cloud@ uses for now, as it doesn't include any pricing data to the spot instance request.
+When starting preemptible instances on Azure, Arvados configures the eviction policy to 'delete', with max price set to '-1'. This has the effect that preemptible VMs will not be evicted for pricing reasons. The price paid for the instance will be the current spot price for the VM type, up to a maximum of the price for a standard, non-spot VM of that type.
 
-The real price that a spot instance has at any point in time is discovered at the end of each usage hour, depending on instance demand. For this reason, AWS provides a data feed subscription to get hourly logs, as described on "Amazon's User Guide":https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-data-feeds.html.
+Please note that Azure provides no SLA for preemptible instances. Even in this configuration, preemptible instances can still be evicted for capacity reasons. If that happens and a container is aborted, Arvados will try to restart it, subject to the usual retry rules.
 
+Spot pricing is not available on 'B-series' VMs, those should not be defined in the configuration file with the _Preemptible_ flag set to true. Spot instances have a separate quota pool, make sure you have sufficient quota available.
index b768147df857dcae4bf0859c117930842392a83b..28ddf7eff7ab48e2269349d893e413242067d920 100644 (file)
@@ -9,7 +9,7 @@ Copyright (C) The Arvados Authors. All rights reserved.
 SPDX-License-Identifier: CC-BY-SA-3.0
 {% endcomment %}
 
-h2. Arados /etc/arvados/config.yml
+h2. Arvados /etc/arvados/config.yml
 
 The configuration file is normally found at @/etc/arvados/config.yml@ and will be referred to as just @config.yml@ in this guide.  This configuration file must be kept in sync across every service node in the cluster, but not shell and compute nodes (which do not require config.yml).
 
index cdecc88152e38f1e34e2a1ebdbc26e6271174a96..0638ce70e6dbf6bc39129906ed0e2c242beae876 100644 (file)
@@ -16,8 +16,8 @@ arvados-dispatch-cloud is only relevant for cloud installations. Skip this secti
 # "Introduction":#introduction
 # "Create an SSH keypair":#sshkeypair
 # "The build script":#building
-# "Build an Azure image":#azure
 # "Build an AWS image":#aws
+# "Build an Azure image":#azure
 
 h2(#introduction). Introduction
 
@@ -110,33 +110,23 @@ Options:
       Output debug information (default: false)
 </code></pre></notextile>
 
-h2(#azure). Build an Azure image
+h2(#aws). Build an AWS image
 
-<notextile><pre><code>~$ <span class="userinput">./build.sh --json-file arvados-images-azure.json \
+<notextile><pre><code>~$ <span class="userinput">./build.sh --json-file arvados-images-aws.json \
            --arvados-cluster-id ClusterID \
-           --azure-resource-group ResourceGroup \
-           --azure-location AzureRegion \
-           --azure-sku AzureSKU \
-           --azure-secrets-file AzureSecretsFilePath \
+           --aws-profile AWSProfile \
+           --aws-source-ami AMI \
+           --aws-vpc-id VPC \
+           --aws-subnet-id Subnet \
+           --ssh_user admin \
            --resolver ResolverIP \
            --public-key-file ArvadosDispatchCloudPublicKeyPath
 </span>
 </code></pre></notextile>
 
-For @ClusterID@, fill in your cluster ID. The @ResourceGroup@ and @AzureRegion@ (e.g. 'eastus2') should be configured for where you want the compute image to be generated and stored. The @AzureSKU@ is the SKU of the base image to be used, e.g. '18.04-LTS' for Ubuntu 18.04.
-
-@AzureSecretsFilePath@ should be replaced with the path to a shell script that loads the Azure secrets with sufficient permissions to create the image. The file would look like this:
-
-<notextile><pre><code>export ARM_CLIENT_ID=...
-export ARM_CLIENT_SECRET=...
-export ARM_SUBSCRIPTION_ID=...
-export ARM_TENANT_ID=...
-</code></pre></notextile>
-
-These secrets can be generated from the Azure portal, or with the cli using a command like this:
+For @ClusterID@, fill in your cluster ID. The @VPC@ and @Subnet@ should be configured for where you want the compute image to be generated and stored. The @AMI@ is the identifier for the base image to be used. Current AMIs are maintained by "Debian":https://wiki.debian.org/Cloud/AmazonEC2Image/Buster and "Ubuntu":https://cloud-images.ubuntu.com/locator/ec2/.
 
-<notextile><pre><code>~$ <span class="userinput">az ad sp create-for-rbac --name Packer --password ...</span>
-</code></pre></notextile>
+@AWSProfile@ should be replaced with the name of an AWS profile with sufficient permissions to create the image.
 
 @ArvadosDispatchCloudPublicKeyPath@ should be replaced with the path to the ssh *public* key file generated in "Create an SSH keypair":#sshkeypair, above.
 
@@ -151,23 +141,33 @@ Alternatively, the services could be hardcoded into an @/etc/hosts@ file. For ex
 
 Adding these lines to the @/etc/hosts@ file in the compute node image could be done with a small change to the Packer template and the @scripts/base.sh@ script, which will be left as an exercise for the reader.
 
-h2(#aws). Build an AWS image
+h2(#azure). Build an Azure image
 
-<notextile><pre><code>~$ <span class="userinput">./build.sh --json-file arvados-images-aws.json \
+<notextile><pre><code>~$ <span class="userinput">./build.sh --json-file arvados-images-azure.json \
            --arvados-cluster-id ClusterID \
-           --aws-profile AWSProfile \
-           --aws-source-ami AMI \
-           --aws-vpc-id VPC \
-           --aws-subnet-id Subnet \
-           --ssh_user admin \
+           --azure-resource-group ResourceGroup \
+           --azure-location AzureRegion \
+           --azure-sku AzureSKU \
+           --azure-secrets-file AzureSecretsFilePath \
            --resolver ResolverIP \
            --public-key-file ArvadosDispatchCloudPublicKeyPath
 </span>
 </code></pre></notextile>
 
-For @ClusterID@, fill in your cluster ID. The @VPC@ and @Subnet@ should be configured for where you want the compute image to be generated and stored. The @AMI@ is the identifier for the base image to be used. Current AMIs are maintained by "Debian":https://wiki.debian.org/Cloud/AmazonEC2Image/Buster and "Ubuntu":https://cloud-images.ubuntu.com/locator/ec2/.
+For @ClusterID@, fill in your cluster ID. The @ResourceGroup@ and @AzureRegion@ (e.g. 'eastus2') should be configured for where you want the compute image to be generated and stored. The @AzureSKU@ is the SKU of the base image to be used, e.g. '18.04-LTS' for Ubuntu 18.04.
 
-@AWSProfile@ should be replaced with the name of an AWS profile with sufficient permissions to create the image.
+@AzureSecretsFilePath@ should be replaced with the path to a shell script that loads the Azure secrets with sufficient permissions to create the image. The file would look like this:
+
+<notextile><pre><code>export ARM_CLIENT_ID=...
+export ARM_CLIENT_SECRET=...
+export ARM_SUBSCRIPTION_ID=...
+export ARM_TENANT_ID=...
+</code></pre></notextile>
+
+These secrets can be generated from the Azure portal, or with the cli using a command like this:
+
+<notextile><pre><code>~$ <span class="userinput">az ad sp create-for-rbac --name Packer --password ...</span>
+</code></pre></notextile>
 
 @ArvadosDispatchCloudPublicKeyPath@ should be replaced with the path to the ssh *public* key file generated in "Create an SSH keypair":#sshkeypair, above.
 
index 151e211653c0d77d73af31749bf71836124998e1..a2186a42fe75819533a2d207d1324fd598de8e88 100644 (file)
@@ -74,10 +74,12 @@ Add or update the following portions of your cluster configuration file, @config
 
 h4. Minimal configuration example for Amazon EC2
 
+The <span class="userinput">ImageID</span> value is the compute node image that was built in "the previous section":install-compute-node.html#aws.
+
 <notextile>
 <pre><code>    Containers:
       CloudVMs:
-        ImageID: ami-01234567890abcdef
+        ImageID: <span class="userinput">ami-01234567890abcdef</span>
         Driver: ec2
         DriverParameters:
           AccessKeyID: XXXXXXXXXXXXXXXXXXXX
@@ -95,10 +97,12 @@ h4. Minimal configuration example for Azure
 
 Using managed disks:
 
+The <span class="userinput">ImageID</span> value is the compute node image that was built in "the previous section":install-compute-node.html#azure.
+
 <notextile>
 <pre><code>    Containers:
       CloudVMs:
-        ImageID: "zzzzz-compute-v1597349873"
+        ImageID: <span class="userinput">"zzzzz-compute-v1597349873"</span>
         Driver: azure
         # (azure) managed disks: set MaxConcurrentInstanceCreateOps to 20 to avoid timeouts, cf
         # https://docs.microsoft.com/en-us/azure/virtual-machines/linux/capture-image
@@ -134,7 +138,7 @@ Using an image from a shared image gallery:
 <notextile>
 <pre><code>    Containers:
       CloudVMs:
-        ImageID: "shared_image_gallery_image_definition_name"
+        ImageID: <span class="userinput">"shared_image_gallery_image_definition_name"</span>
         Driver: azure
         DriverParameters:
           # Credentials.
@@ -167,10 +171,12 @@ Using an image from a shared image gallery:
 
 Using unmanaged disks (deprecated):
 
+The <span class="userinput">ImageID</span> value is the compute node image that was built in "the previous section":install-compute-node.html#azure.
+
 <notextile>
 <pre><code>    Containers:
       CloudVMs:
-        ImageID: "https://zzzzzzzz.blob.core.windows.net/system/Microsoft.Compute/Images/images/zzzzz-compute-osDisk.55555555-5555-5555-5555-555555555555.vhd"
+        ImageID: <span class="userinput">"https://zzzzzzzz.blob.core.windows.net/system/Microsoft.Compute/Images/images/zzzzz-compute-osDisk.55555555-5555-5555-5555-555555555555.vhd"</span>
         Driver: azure
         DriverParameters:
           # Credentials.
index 97854e524000894c021e80754a4d871fc1637da6..43a4cdc723b84fb4396b07a2f18a3de87816d545 100644 (file)
@@ -24,7 +24,7 @@ Arvados support for shell nodes allows you to use Arvados permissions to grant L
 
 A shell node runs the @arvados-login-sync@ service to manage user accounts, and typically has Arvados utilities and SDKs pre-installed.  Users are allowed to log in and run arbitrary programs.  For optimal performance, the Arvados shell server should be on the same LAN as the Arvados cluster.
 
-Because it _contains secrets_ shell nodes should *not* have a copy of the Arvados @config.yml@.
+Because Arvados @config.yml@ _contains secrets_ it should not *not* be present on shell nodes.
 
 Shell nodes should be separate virtual machines from the VMs running other Arvados services.  You may choose to grant root access to users so that they can customize the node, for example, installing new programs.  This has security considerations depending on whether a shell node is single-user or multi-user.
 
@@ -89,6 +89,8 @@ If this is a multi-user shell node, then @ARVADOS_API_TOKEN@ should be an admini
 
 Set @ARVADOS_VIRTUAL_MACHINE_UUID@ to the UUID from "Create record for VM":#vm-record
 
+h3. Standalone cluster
+
 <notextile>
 <pre>
 <code>shellserver:# <span class="userinput">umask 0700; tee /etc/cron.d/arvados-login-sync &lt;&lt;EOF
@@ -100,6 +102,24 @@ EOF</span></code>
 </pre>
 </notextile>
 
+h3. Part of a LoginCLuster federation
+
+If this cluster is part of a "federation with centralized user management":../admin/federation.html#LoginCluster , the login sync script also needs to be given the host and user token for the login cluster.
+
+<notextile>
+<pre>
+<code>shellserver:# <span class="userinput">umask 0700; tee /etc/cron.d/arvados-login-sync &lt;&lt;EOF
+ARVADOS_API_HOST="<strong>ClusterID.example.com</strong>"
+ARVADOS_API_TOKEN="<strong>xxxxxxxxxxxxxxxxx</strong>"
+LOGINCLUSTER_ARVADOS_API_HOST="<strong>LoginClusterID.example.com</strong>"
+LOGINCLUSTER_ARVADOS_API_TOKEN="<strong>yyyyyyyyyyyyyyyyy</strong>"
+ARVADOS_VIRTUAL_MACHINE_UUID="<strong>zzzzz-2x53u-zzzzzzzzzzzzzzz</strong>"
+*/2 * * * * root arvados-login-sync
+EOF</span></code>
+</pre>
+</notextile>
+
+
 h2(#confirm-working). Confirm working installation
 
 A user should be able to log in to the shell server when the following conditions are satisfied:
index 300ec3085a72da4261d2e0e4df90221baaf6e395..b3336d51dfa56eb3e441ed903e6adc5524e18dc6 100644 (file)
@@ -16,7 +16,7 @@ h2. Using the SDK
 
 The SDK is packaged as a JAR named @arvados-java-<version>.jar@, which is published to Maven Central and can be included using Maven, Gradle, or by hand.
 
-Here is an example @build.gradle@ file that uses the Arados java sdk:
+Here is an example @build.gradle@ file that uses the Arvados java sdk:
 
 <pre>
 apply plugin: 'application'
index 7f949d9bdb3e2fb83c539a0df5f15efec6ca2612..1ff0798ea6e499396667d70091b62de2eddaaadf 100644 (file)
@@ -528,6 +528,17 @@ func (az *azureInstanceSet) Create(
                },
        }
 
+       if instanceType.Preemptible {
+               // Setting maxPrice to -1 is the equivalent of paying spot price, up to the
+               // normal price. This means the node will not be pre-empted for price
+               // reasons. It may still be pre-empted for capacity reasons though. And
+               // Azure offers *no* SLA on spot instances.
+               var maxPrice float64 = -1
+               vmParameters.VirtualMachineProperties.Priority = compute.Spot
+               vmParameters.VirtualMachineProperties.EvictionPolicy = compute.Delete
+               vmParameters.VirtualMachineProperties.BillingProfile = &compute.BillingProfile{MaxPrice: &maxPrice}
+       }
+
        vm, err := az.vmClient.createOrUpdate(az.ctx, az.azconfig.ResourceGroup, name, vmParameters)
        if err != nil {
                // Do some cleanup. Otherwise, an unbounded number of new unused nics and
index 96d6dca69e451c0802220a884e4978fbb906f447..b6aa9a16b6187b4fd5486037076885fe4eb69d19 100644 (file)
@@ -136,6 +136,15 @@ func GetInstanceSet() (cloud.InstanceSet, cloud.ImageID, arvados.Cluster, error)
                                Price:        .02,
                                Preemptible:  false,
                        },
+                       "tinyp": {
+                               Name:         "tiny",
+                               ProviderType: "Standard_D1_v2",
+                               VCPUs:        1,
+                               RAM:          4000000000,
+                               Scratch:      10000000000,
+                               Price:        .002,
+                               Preemptible:  true,
+                       },
                })}
        if *live != "" {
                var exampleCfg testConfig
@@ -185,6 +194,17 @@ func (*AzureInstanceSetSuite) TestCreate(c *check.C) {
        c.Check(tags["TestTagName"], check.Equals, "test tag value")
        c.Logf("inst.String()=%v Address()=%v Tags()=%v", inst.String(), inst.Address(), tags)
 
+       instPreemptable, err := ap.Create(cluster.InstanceTypes["tinyp"],
+               img, map[string]string{
+                       "TestTagName": "test tag value",
+               }, "umask 0600; echo -n test-file-data >/var/run/test-file", pk)
+
+       c.Assert(err, check.IsNil)
+
+       tags = instPreemptable.Tags()
+       c.Check(tags["TestTagName"], check.Equals, "test tag value")
+       c.Logf("instPreemptable.String()=%v Address()=%v Tags()=%v", instPreemptable.String(), instPreemptable.Address(), tags)
+
 }
 
 func (*AzureInstanceSetSuite) TestListInstances(c *check.C) {
index 8162e22a2ff6f815ac7904d28ad6ec0413faa7c3..a9bff05464740d804ed3b1f5827c757740c97187 100755 (executable)
@@ -31,6 +31,9 @@ keys = ''
 
 begin
   arv = Arvados.new({ :suppress_ssl_warnings => false })
+  logincluster_arv = Arvados.new({ :api_host => (ENV['LOGINCLUSTER_ARVADOS_API_HOST'] || ENV['ARVADOS_API_HOST']),
+                                   :api_token => (ENV['LOGINCLUSTER_ARVADOS_API_TOKEN'] || ENV['ARVADOS_API_TOKEN']),
+                      :suppress_ssl_warnings => false })
 
   vm_uuid = ENV['ARVADOS_VIRTUAL_MACHINE_UUID']
 
@@ -190,7 +193,7 @@ begin
 
     begin
       if !File.exist?(tokenfile)
-        user_token = arv.api_client_authorization.create(api_client_authorization: {owner_uuid: l[:user_uuid], api_client_id: 0})
+        user_token = logincluster_arv.api_client_authorization.create(api_client_authorization: {owner_uuid: l[:user_uuid], api_client_id: 0})
         f = File.new(tokenfile, 'w')
         f.write("ARVADOS_API_HOST=#{ENV['ARVADOS_API_HOST']}\n")
         f.write("ARVADOS_API_TOKEN=v2/#{user_token[:uuid]}/#{user_token[:api_token]}\n")