mirror of https://github.com/kubernetes/kops.git
Add support for deleting an InstanceGroup
This commit is contained in:
parent
c4f2fbfcaf
commit
0aed68c260
|
|
@ -0,0 +1,81 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kops/upup/pkg/fi/cloudup"
|
||||
"k8s.io/kops/upup/pkg/kutil"
|
||||
)
|
||||
|
||||
type DeleteInstanceceGroupCmd struct {
|
||||
}
|
||||
|
||||
var deleteInstanceceGroupCmd DeleteInstanceceGroupCmd
|
||||
|
||||
func init() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "instancegroup",
|
||||
Aliases: []string{"instancegroups", "ig"},
|
||||
Short: "Delete instancegroup",
|
||||
Long: `Delete an instancegroup configuration.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
glog.Exitf("Specify name of instance group to delete")
|
||||
}
|
||||
if len(args) != 1 {
|
||||
glog.Exitf("Can only edit one instance group at a time!")
|
||||
}
|
||||
err := deleteInstanceceGroupCmd.Run(args[0])
|
||||
if err != nil {
|
||||
glog.Exitf("%v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
deleteCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
func (c *DeleteInstanceceGroupCmd) Run(groupName string) error {
|
||||
if groupName == "" {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
_, cluster, err := rootCommand.Cluster()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
registry, err := rootCommand.InstanceGroupRegistry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
group, err := registry.Find(groupName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading InstanceGroup %q: %v", groupName, err)
|
||||
}
|
||||
if group == nil {
|
||||
return fmt.Errorf("InstanceGroup %q not found", groupName)
|
||||
}
|
||||
|
||||
cloud, err := cloudup.BuildCloud(cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d := &kutil.DeleteInstanceGroup{}
|
||||
d.Cluster = cluster
|
||||
d.Cloud = cloud
|
||||
d.InstanceGroupRegistry = registry
|
||||
|
||||
err = d.DeleteInstanceGroup(group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("InstanceGroup %q deleted\n", group.Name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -61,11 +61,10 @@ func (c *RollingUpdateClusterCmd) Run() error {
|
|||
}
|
||||
|
||||
d := &kutil.RollingUpdateCluster{}
|
||||
|
||||
d.Cluster = cluster
|
||||
d.Cloud = cloud
|
||||
|
||||
groups, err := d.ListInstanceGroups(instancegroups)
|
||||
warnUnmatched := true
|
||||
groups, err := kutil.FindCloudInstanceGroups(cloud, cluster, instancegroups, warnUnmatched)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -84,12 +83,18 @@ func (c *RollingUpdateClusterCmd) Run() error {
|
|||
t.AddColumn("READY", func(r *kutil.CloudInstanceGroup) string {
|
||||
return strconv.Itoa(len(r.Ready))
|
||||
})
|
||||
t.AddColumn("MIN", func(r *kutil.CloudInstanceGroup) string {
|
||||
return strconv.Itoa(r.MinSize())
|
||||
})
|
||||
t.AddColumn("MAX", func(r *kutil.CloudInstanceGroup) string {
|
||||
return strconv.Itoa(r.MaxSize())
|
||||
})
|
||||
var l []*kutil.CloudInstanceGroup
|
||||
for _, v := range groups {
|
||||
l = append(l, v)
|
||||
}
|
||||
|
||||
err := t.Render(l, os.Stdout, "NAME", "STATUS", "NEEDUPDATE", "READY")
|
||||
err := t.Render(l, os.Stdout, "NAME", "STATUS", "NEEDUPDATE", "READY", "MIN", "MAX")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ To preview the change:
|
|||
|
||||
> `kops create cluster --name <clustername> --dryrun`
|
||||
```
|
||||
...
|
||||
Will modify resources:
|
||||
*awstasks.LaunchConfiguration launchConfiguration/mycluster.mydomain.com
|
||||
InstanceType t2.medium -> t2.large
|
||||
|
|
@ -66,14 +67,54 @@ The procedure to resize an instance group works the same way:
|
|||
|
||||
## Creating a new instance group
|
||||
|
||||
Suppose you want to add a new group of nodes
|
||||
TODO
|
||||
Suppose you want to add a new group of nodes, perhaps with a different instance type. You do this using
|
||||
`kops create ig <InstanceGroupName>`. Currently it opens an editor with a skeleton configuration, allowing
|
||||
you to edit it before creation.
|
||||
|
||||
## Deleting an instance group
|
||||
So the procedure is:
|
||||
|
||||
TODO
|
||||
* `kops create ig morenodes`, edit and save
|
||||
* Preview: `kops create cluster --name <clustername> --dryrun`
|
||||
* Apply: `kops create cluster --name <clustername>`
|
||||
* (no instances need to be relaunched, so no rolling-update is needed)
|
||||
|
||||
## Converting an instance group to use spot instances
|
||||
|
||||
TODO
|
||||
Follow the normal procedure for reconfiguring an InstanceGroup, but set the maxPrice property to your bid.
|
||||
For example, "0.10" represents a spot-price bid of $0.10 (10 cents) per hour.
|
||||
|
||||
Warning: the t2 family is not currently supported with spot pricing. You'll need to choose a different
|
||||
instance type.
|
||||
|
||||
An example spec looks like this:
|
||||
|
||||
```
|
||||
metadata:
|
||||
creationTimestamp: "2016-07-10T15:47:14Z"
|
||||
name: nodes
|
||||
spec:
|
||||
machineType: m3.medium
|
||||
maxPrice: "0.1"
|
||||
maxSize: 3
|
||||
minSize: 3
|
||||
role: Node
|
||||
```
|
||||
|
||||
($0.10 per hour is a huge over-bid for an m3.medium - this is only an example!)
|
||||
|
||||
So the procedure is:
|
||||
|
||||
* Edit: `kops edit ig nodes`
|
||||
* Preview: `kops create cluster --name <clustername> --dryrun`
|
||||
* Apply: `kops create cluster --name <clustername>`
|
||||
* Rolling-update, only if you want to apply changes immediately: `kops rolling-update cluster`
|
||||
|
||||
|
||||
## Deleting an instance group
|
||||
|
||||
If you decide you don't need an InstanceGroup any more, you delete it using: `kops delete ig <name>`
|
||||
|
||||
Example: `kops delete ig morenodes`
|
||||
|
||||
No rolling-update is needed (and note this is not currently graceful, so there may be interruptions to
|
||||
workloads where the pods are running on those nodes).
|
||||
|
|
|
|||
|
|
@ -182,6 +182,18 @@ func (r *InstanceGroupRegistry) Find(name string) (*InstanceGroup, error) {
|
|||
return group, nil
|
||||
}
|
||||
|
||||
func (r *InstanceGroupRegistry) Delete(name string) (bool, error) {
|
||||
p := r.stateStore.VFSPath().Join("instancegroup", name)
|
||||
err := p.Remove()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("error deleting instancegroup configuration %q: %v", name, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *InstanceGroupRegistry) ReadAll() ([]*InstanceGroup, error) {
|
||||
names, err := r.List()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package kutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kops/upup/pkg/api"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
)
|
||||
|
||||
// DeleteInstanceGroup removes the cloud resources for an InstanceGroup
|
||||
type DeleteInstanceGroup struct {
|
||||
Cluster *api.Cluster
|
||||
Cloud fi.Cloud
|
||||
InstanceGroupRegistry *api.InstanceGroupRegistry
|
||||
}
|
||||
|
||||
func (c *DeleteInstanceGroup) DeleteInstanceGroup(group *api.InstanceGroup) error {
|
||||
groups, err := FindCloudInstanceGroups(c.Cloud, c.Cluster, []*api.InstanceGroup{group}, false)
|
||||
cig := groups[group.Name]
|
||||
if cig == nil {
|
||||
return fmt.Errorf("InstanceGroup not found in cloud")
|
||||
}
|
||||
if len(groups) != 1 {
|
||||
return fmt.Errorf("Multiple InstanceGroup resources found in cloud")
|
||||
}
|
||||
|
||||
err = cig.Delete(c.Cloud)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting cloud resources for InstanceGroup: %v", err)
|
||||
}
|
||||
|
||||
_, err = c.InstanceGroupRegistry.Delete(group.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -15,18 +15,17 @@ import (
|
|||
|
||||
// RollingUpdateCluster restarts cluster nodes
|
||||
type RollingUpdateCluster struct {
|
||||
Cluster *api.Cluster
|
||||
Cloud fi.Cloud
|
||||
Cloud fi.Cloud
|
||||
}
|
||||
|
||||
func (c *RollingUpdateCluster) ListInstanceGroups(instancegroups []*api.InstanceGroup) (map[string]*CloudInstanceGroup, error) {
|
||||
cloud := c.Cloud.(*awsup.AWSCloud)
|
||||
func FindCloudInstanceGroups(cloud fi.Cloud, cluster *api.Cluster, instancegroups []*api.InstanceGroup, warnUnmatched bool) (map[string]*CloudInstanceGroup, error) {
|
||||
awsCloud := cloud.(*awsup.AWSCloud)
|
||||
|
||||
groups := make(map[string]*CloudInstanceGroup)
|
||||
|
||||
tags := cloud.Tags()
|
||||
tags := awsCloud.Tags()
|
||||
|
||||
asgs, err := findAutoscalingGroups(cloud, tags)
|
||||
asgs, err := findAutoscalingGroups(awsCloud, tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -38,9 +37,9 @@ func (c *RollingUpdateCluster) ListInstanceGroups(instancegroups []*api.Instance
|
|||
var asgName string
|
||||
switch g.Spec.Role {
|
||||
case api.InstanceGroupRoleMaster:
|
||||
asgName = g.Name + ".masters." + c.Cluster.Name
|
||||
asgName = g.Name + ".masters." + cluster.Name
|
||||
case api.InstanceGroupRoleNode:
|
||||
asgName = g.Name + "." + c.Cluster.Name
|
||||
asgName = g.Name + "." + cluster.Name
|
||||
default:
|
||||
glog.Warningf("Ignoring InstanceGroup of unknown role %q", g.Spec.Role)
|
||||
continue
|
||||
|
|
@ -54,7 +53,9 @@ func (c *RollingUpdateCluster) ListInstanceGroups(instancegroups []*api.Instance
|
|||
}
|
||||
}
|
||||
if instancegroup == nil {
|
||||
glog.Warningf("Found ASG with no corresponding instance group: %q", name)
|
||||
if warnUnmatched {
|
||||
glog.Warningf("Found ASG with no corresponding instance group: %q", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
group := buildCloudInstanceGroup(instancegroup, asg)
|
||||
|
|
@ -107,12 +108,23 @@ type CloudInstanceGroup struct {
|
|||
Status string
|
||||
Ready []*autoscaling.Instance
|
||||
NeedUpdate []*autoscaling.Instance
|
||||
|
||||
asg *autoscaling.Group
|
||||
}
|
||||
|
||||
func (c *CloudInstanceGroup) MinSize() int {
|
||||
return int(aws.Int64Value(c.asg.MinSize))
|
||||
}
|
||||
|
||||
func (c *CloudInstanceGroup) MaxSize() int {
|
||||
return int(aws.Int64Value(c.asg.MaxSize))
|
||||
}
|
||||
|
||||
func buildCloudInstanceGroup(ig *api.InstanceGroup, g *autoscaling.Group) *CloudInstanceGroup {
|
||||
n := &CloudInstanceGroup{
|
||||
ASGName: aws.StringValue(g.AutoScalingGroupName),
|
||||
InstanceGroup: ig,
|
||||
asg: g,
|
||||
}
|
||||
|
||||
findLaunchConfigurationName := aws.StringValue(g.LaunchConfigurationName)
|
||||
|
|
@ -163,6 +175,41 @@ func (n *CloudInstanceGroup) RollingUpdate(cloud fi.Cloud) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *CloudInstanceGroup) Delete(cloud fi.Cloud) error {
|
||||
c := cloud.(*awsup.AWSCloud)
|
||||
|
||||
// TODO: Graceful?
|
||||
|
||||
// Delete ASG
|
||||
{
|
||||
asgName := aws.StringValue(g.asg.AutoScalingGroupName)
|
||||
glog.V(2).Infof("Deleting autoscaling group %q", asgName)
|
||||
request := &autoscaling.DeleteAutoScalingGroupInput{
|
||||
AutoScalingGroupName: g.asg.AutoScalingGroupName,
|
||||
ForceDelete: aws.Bool(true),
|
||||
}
|
||||
_, err := c.Autoscaling.DeleteAutoScalingGroup(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting autoscaling group %q: %v", asgName, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete LaunchConfig
|
||||
{
|
||||
lcName := aws.StringValue(g.asg.LaunchConfigurationName)
|
||||
glog.V(2).Infof("Deleting autoscaling launch configuration %q", lcName)
|
||||
request := &autoscaling.DeleteLaunchConfigurationInput{
|
||||
LaunchConfigurationName: g.asg.LaunchConfigurationName,
|
||||
}
|
||||
_, err := c.Autoscaling.DeleteLaunchConfiguration(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting autoscaling launch configuration %q: %v", lcName, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *CloudInstanceGroup) String() string {
|
||||
return "CloudInstanceGroup:" + n.ASGName
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ func findAutoscalingGroups(cloud *awsup.AWSCloud, tags map[string]string) ([]*au
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error listing autoscaling cluster tags: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(asgNames) != 0 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue