Skip to content

Commit

Permalink
Add the ability to spin up Hetzner servers from custom snapshots
Browse files Browse the repository at this point in the history
This comes in handy when using tools such as Packer to generate customized images.
  • Loading branch information
marvinpinto committed Jun 20, 2021
1 parent 6e3e05d commit dfa2ce2
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
8 changes: 7 additions & 1 deletion cluster-autoscaler/cloudprovider/hetzner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ The cluster autoscaler for Hetzner Cloud scales worker nodes.
# Configuration

`HCLOUD_TOKEN` Required Hetzner Cloud token.

`HCLOUD_CLOUD_INIT` Base64 encoded Cloud Init yaml with commands to join the cluster, Sample [examples/cloud-init.txt for (Kubernetes 1.20.1)](examples/cloud-init.txt)
`HCLOUD_IMAGE` Defaults to `ubuntu-20.04`, @see https://docs.hetzner.cloud/#images

`HCLOUD_IMAGE` Defaults to `ubuntu-20.04`, @see https://docs.hetzner.cloud/#images. Alternatively, supply the description of a custom snapshot and the most recent (snapshot) image will be used. Useful when building images with tools such as Packer.

`HCLOUD_NETWORK` Default empty , The name of the network that is used in the cluster , @see https://docs.hetzner.cloud/#networks

`HCLOUD_SSH_KEY` Default empty , This SSH Key will have access to the fresh created server, @see https://docs.hetzner.cloud/#ssh-keys

Node groups must be defined with the `--nodes=<min-servers>:<max-servers>:<instance-type>:<region>:<name>` flag.

Multiple flags will create multiple node pools. For example:
```
--nodes=1:10:CPX51:FSN1:pool1
Expand Down
32 changes: 30 additions & 2 deletions cluster-autoscaler/cloudprovider/hetzner/hcloud-go/hcloud/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,41 @@ func (c *ImageClient) GetByName(ctx context.Context, name string) (*Image, *Resp
return images[0], response, err
}

// GetBySnapshot retrieves the most recent image given a snapshot description. If the image cannot be found, nil is returned.
func (c *ImageClient) GetBySnapshot(ctx context.Context, name string) (*Image, *Response, error) {
if name == "" {
return nil, nil, nil
}

images, response, err := c.List(ctx, ImageListOpts{
Type: []ImageType{ImageTypeSnapshot},
Status: []ImageStatus{ImageStatusAvailable},
Sort: []string{"created:desc"},
})

for _, i := range images {
if i.Description == name {
return i, response, err
}
}

return nil, response, err
}

// Get retrieves an image by its ID if the input can be parsed as an integer, otherwise it
// retrieves an image by its name. If the image does not exist, nil is returned.
func (c *ImageClient) Get(ctx context.Context, idOrName string) (*Image, *Response, error) {
if id, err := strconv.Atoi(idOrName); err == nil {
return c.GetByID(ctx, int(id))
if image, resp, err := c.GetByID(ctx, int(id)); err == nil && image != nil {
return image, resp, nil
}
}
return c.GetByName(ctx, idOrName)

if image, resp, err := c.GetByName(ctx, idOrName); err == nil && image != nil {
return image, resp, nil
}

return c.GetBySnapshot(ctx, idOrName)
}

// ImageListOpts specifies options for listing images.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,18 @@ func serverTypeAvailable(manager *hetznerManager, instanceType string, region st

func createServer(n *hetznerNodeGroup) error {
StartAfterCreate := true

image, _, err := n.manager.client.Image.Get(n.manager.apiCallContext, n.manager.image)
if err != nil {
return fmt.Errorf("unable to find image named %s: %v", n.manager.image, err)
}

opts := hcloud.ServerCreateOpts{
Name: newNodeName(n),
UserData: n.manager.cloudInit,
Location: &hcloud.Location{Name: n.region},
ServerType: &hcloud.ServerType{Name: n.instanceType},
Image: &hcloud.Image{Name: n.manager.image},
Image: image,
StartAfterCreate: &StartAfterCreate,
Labels: map[string]string{
nodeGroupLabel: n.id,
Expand Down

0 comments on commit dfa2ce2

Please sign in to comment.