Skip to content

Commit

Permalink
Merge pull request #6 from armory-io/refactor/eks-update
Browse files Browse the repository at this point in the history
fix: check node state before udating
  • Loading branch information
minhthong582000 authored Sep 6, 2023
2 parents d29b811 + 307c130 commit 03ee704
Show file tree
Hide file tree
Showing 14 changed files with 575 additions and 209 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.swp
.idea

.vscode
dist/
15 changes: 7 additions & 8 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,27 @@ archives:
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
name_template: "checksums.txt"
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- "^docs:"
- "^test:"
dockers:
## standard AMIs e.g. eks m5.2xlarae types
## standard AMIs e.g. eks m5.2xlarae types
- image_templates:
- "ghcr.io/armory-io/eks-auto-updater:{{ .Version }}-linux-amd64"
use: buildx
goos: linux
build_flag_templates:
- "--platform=linux/amd64"
## This is graviton2 in AWS like mg5g.2xlarge types
## This is graviton2 in AWS like mg5g.2xlarge types
- image_templates:
- "ghcr.io/armory-io/eks-auto-updater:{{ .Version }}-linux-arm64v8"
use: buildx
Expand All @@ -62,7 +62,6 @@ docker_manifests:
image_templates:
- "ghcr.io/armory-io/eks-auto-updater:{{ .Version }}-linux-amd64"
- "ghcr.io/armory-io/eks-auto-updater:{{ .Version }}-linux-arm64v8"

# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
Expand Down
43 changes: 35 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
# eks-auto-updater

Auto updater docker image designed to take a target cluster and update both managed node pools and addon versions to latest releases

# What?
## What?

Currently EKS updates are... painful. This is a tool to auto update a given clusters dependencies like:
* Addons - find the current default version for a set of addons and update the addon version
* Managed node AMI - TF doesn't see version changes. This triggers an update of managed node pool
* CAUTION: IF YOU DO NOT have pod disruption budgets or other protections in place, this WILL cause downtime on services.

- Addons - find the current default version for a set of addons and update the addon version.
- Managed node AMI - TF doesn't see version changes. This triggers an update of managed node pool
- CAUTION: IF YOU DO NOT have pod disruption budgets or other protections in place, this WILL cause downtime on services.

## How?

To update your nodegroups, run the following command:

```bash
eks-auto-updater nodegroups \
--cluster-name <cluster-name> \
--region <region> \
--role-arn <role-arn> \
--nodegroup-wait-time <nodegroup-wait-time> \
--nodegroup-name <nodegroup-name>
```

To update your addons, run the following command:

```bash
eks-auto-updater addons \
--cluster-name <cluster-name> \
--region <region> \
--role-arn <role-arn> \
--addons <comma-separated-list-of-addons>
```

## Long term goals
* Possibly update the EKS cluster version?
* Auto update multiple node pools vs. a single one and set of addons
* Lookup addons vs. requiring to be passed
* Lookup addon configuration/identifiy differences vs. just overwriting

- Possibly update the EKS cluster version?
- Auto update multiple node pools vs. a single one and set of addons
- Lookup addons vs. requiring to be passed
- Lookup addon configuration/identifiy differences vs. just overwriting
73 changes: 73 additions & 0 deletions cmd/addons.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cmd

import (
"errors"
"strings"
"sync"

"github.com/armory-io/eks-auto-updater/internal/updater"
"github.com/armory-io/eks-auto-updater/pkg/aws"
"github.com/armory-io/eks-auto-updater/pkg/aws/options"

"github.com/spf13/cobra"
)

// addonsCmd represents the addons command
var addonsCmd = &cobra.Command{
Use: "addons",
Short: "Upgrades EKS addons to the latest version",
Long: "",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
region := cmd.Flag("region").Value.String()
roleArn := cmd.Flag("role-arn").Value.String()
clusterName := cmd.Flag("cluster-name").Value.String()
addons := cmd.Flag("addons").Value.String()
addonsList := strings.Split(addons, ",")

awsClient, err := aws.NewClient(ctx,
options.WithRegion(region),
options.WithRoleArn(roleArn),
)
if err != nil {
return err
}

var wg sync.WaitGroup
errChan := make(chan error)
defer close(errChan)

updater := updater.NewEKSUpdater(awsClient.EKS())
for _, addon := range addonsList {
wg.Add(1)

go func(addon string) {
errChan <- updater.UpdateAddon(ctx, &clusterName, &addon, &wg)
}(addon)
}

var errResult error
go func() {
for err := range errChan {
if err != nil {
errResult = errors.Join(errResult, err)
}
}
}()

wg.Wait()

// Return all of the errors that were sent to the errChan channel
if errResult != nil {
return errResult
}

return nil
},
}

func init() {
rootCmd.AddCommand(addonsCmd)

addonsCmd.Flags().StringP("addons", "a", "kube-proxy,vpc-cni,coredns,aws-ebs-csi-driver", "Comma separated list of addons to update. For example: kube-proxy,vpc-cni,coredns,aws-ebs-csi-driver. Defaults to all addons")
}
51 changes: 51 additions & 0 deletions cmd/nodegroups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cmd

import (
"github.com/armory-io/eks-auto-updater/internal/updater"
"github.com/armory-io/eks-auto-updater/pkg/aws"
"github.com/armory-io/eks-auto-updater/pkg/aws/options"

"github.com/spf13/cobra"
)

// nodegroupCmd represents the nodegroup command
var nodegroupsCmd = &cobra.Command{
Use: "nodegroups",
Short: "Upgrades EKS nodegroups to the latest version",
Long: "",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
region := cmd.Flag("region").Value.String()
roleArn := cmd.Flag("role-arn").Value.String()
clusterName := cmd.Flag("cluster-name").Value.String()
nodegroupName := cmd.Flag("nodegroup-name").Value.String()
waitForNodeUpdates, _ := cmd.Flags().GetInt("nodegroup-wait-time")

awsClient, err := aws.NewClient(ctx,
options.WithRegion(region),
options.WithRoleArn(roleArn),
)
if err != nil {
return err
}

updater := updater.NewEKSUpdater(awsClient.EKS())
err = updater.UpdateClusterNodeGroup(ctx, &clusterName, &nodegroupName, waitForNodeUpdates)
if err != nil {
return err
}

return nil
},
}

func init() {
rootCmd.AddCommand(nodegroupsCmd)

// Nodegroup Name
nodegroupsCmd.Flags().String("nodegroup-name", "", "Name of the EKS nodegroup to update")
nodegroupsCmd.MarkFlagRequired("nodegroup-name")

// Nodegroup Wait Time
nodegroupsCmd.Flags().Int("nodegroup-wait-time", 120, "Time in minutes to wait for node group update to complete. Defaults to 120 minutes")
}
42 changes: 42 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cmd

import (
"os"

"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "eks-auto-updater",
Short: "Updates EKS cluster components to the latest version",
Long: `eks-auto-updater is a CLI tool that updates following components of an EKS cluster to the latest version:
- Nodegroups
- Addons
`,
// Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

// region
rootCmd.PersistentFlags().String("region", "us-west-2", "AWS Region to use")
rootCmd.MarkPersistentFlagRequired("region")

// cluster name
rootCmd.PersistentFlags().String("cluster-name", "", "Name of the EKS cluster to update")
rootCmd.MarkPersistentFlagRequired("cluster-name")

// role arn
rootCmd.PersistentFlags().String("role-arn", "", "ARN of the role to assume")
}
Loading

0 comments on commit 03ee704

Please sign in to comment.