Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1 from tenjin/rotate-instance
Browse files Browse the repository at this point in the history
Single Instance Rotator
  • Loading branch information
complex64 authored Apr 23, 2019
2 parents c44f8f3 + 57d749a commit 0c48bca
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 5 deletions.
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ FROM golang:alpine as buildenv
WORKDIR /go/src/github.com/tenjin/rotate-eks-asg
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /rotate-eks-asg ./cmd/rotate-eks-asg
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /rotate-eks-instance ./cmd/rotate-eks-instance

# Extract `rotate-eks-asg` and ship with rest of tooling:
# Extract and ship with rest of tooling:

FROM python:3-alpine
RUN apk add --no-cache git
Expand All @@ -24,6 +25,7 @@ RUN chmod +x \
/usr/local/bin/aws-iam-authenticator

COPY --from=buildenv /rotate-eks-asg /usr/local/bin/
COPY --from=buildenv /rotate-eks-instance /usr/local/bin/
ADD ./script ./script

ENTRYPOINT ["./script/entrypoint.sh"]
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ deps:
GO111MODULE=on go mod vendor
install:
GO111MODULE=on go install -mod=vendor ./cmd/rotate-eks-asg
GO111MODULE=on go install -mod=vendor ./cmd/rotate-eks-instance
4 changes: 2 additions & 2 deletions cmd/rotate-eks-asg/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import (
)

var (
groups = kingpin.Arg("groups", "EKS Auto Scaling Groups to rotate").Required().Strings()
groups = kingpin.Arg("groups", "EKS Auto Scaling Groups to rotate").Required().Strings()
)

func init() { // TODO
func init() {
_ = os.Setenv("AWS_SDK_LOAD_CONFIG", "true")
}

Expand Down
28 changes: 28 additions & 0 deletions cmd/rotate-eks-instance/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"log"
"os"

"github.com/complex64/go-utils/pkg/ctxutil"
"gopkg.in/alecthomas/kingpin.v2"

"github.com/tenjin/rotate-eks-asg/internal/pkg/rotator"
)

var (
name = kingpin.Arg("name", "Internal DNS of EKS instance to rotate").Required().String()
)

func init() {
_ = os.Setenv("AWS_SDK_LOAD_CONFIG", "true")
}

func main() {
kingpin.Parse()
ctx, cancel := ctxutil.ContextWithCancelSignals(os.Kill, os.Interrupt)
defer cancel()
if err := rotator.RotateByInternalDNS(ctx, *name); err != nil {
log.Fatal(err)
}
}
49 changes: 49 additions & 0 deletions internal/pkg/rotator/aws.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rotator

import (
"errors"
"fmt"
"log"

Expand Down Expand Up @@ -30,6 +31,54 @@ func DescribeAutoScalingGroup(client *autoscaling.AutoScaling, name string) (*Gr
return g, nil
}

func DescribeInstanceByInternalDNS(
ec2Client *ec2.EC2,
asgClient *autoscaling.AutoScaling,
instanceInternalDNS string,
) (string, string, error) {
input := &ec2.DescribeInstancesInput{
Filters: []*ec2.Filter{{
Name: aws.String("network-interface.private-dns-name"),
Values: []*string{aws.String(instanceInternalDNS)},
}},
}
var instanceID string
err := ec2Client.DescribeInstancesPages(input,
func(output *ec2.DescribeInstancesOutput, isLast bool) bool {
instanceID = *(output.Reservations[0].Instances[0].InstanceId)
return false
})
if err != nil {
return "", "", err
}
if instanceID == "" {
return "", "", errors.New(fmt.Sprintf("%s: No matching instance could be found", instanceInternalDNS))
}

log.Printf("Internal DNS '%s' is instance ID '%s'", instanceInternalDNS, instanceID)

var groupName string
asgInput := &autoscaling.DescribeAutoScalingInstancesInput{
InstanceIds: []*string{aws.String(instanceID)},
}
err = asgClient.DescribeAutoScalingInstancesPages(asgInput,
func(output *autoscaling.DescribeAutoScalingInstancesOutput, isLast bool) bool {
for _, instance := range output.AutoScalingInstances {
groupName = *(instance.AutoScalingGroupName)
return false
}
return true
})
if err != nil {
return "", "", err
}
if groupName == "" {
return "", "", errors.New(fmt.Sprintf("%s: No matching ASG could be found", instanceInternalDNS))
}

return instanceID, groupName, nil
}

func getAutoScalingGroup(client *autoscaling.AutoScaling, name string) (*autoscaling.Group, error) {
in := &autoscaling.DescribeAutoScalingGroupsInput{
AutoScalingGroupNames: aws.StringSlice([]string{name}),
Expand Down
21 changes: 19 additions & 2 deletions internal/pkg/rotator/rotator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ package rotator

import (
"context"
"log"

"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/exec"
"log"
)

func RotateAll(ctx context.Context, groups []string) error {
Expand Down Expand Up @@ -46,6 +45,24 @@ func Rotate(ctx context.Context, groupId string) error {
return nil
}

func RotateByInternalDNS(ctx context.Context, instanceInternalIP string) error {
sess, err := session.NewSession()
if err != nil {
return err
}
asgClient := autoscaling.New(sess)
ec2Client := ec2.New(sess)
instanceID, groupID, err := DescribeInstanceByInternalDNS(ec2Client, asgClient, instanceInternalIP)
if err != nil {
return err
}
k8s, err := NewKubernetesClient()
if err != nil {
return err
}
return RotateInstance(ctx, k8s, asgClient, ec2Client, groupID, instanceID)
}

func RotateInstance(
ctx context.Context,
k8s *kubernetes.Clientset,
Expand Down

0 comments on commit 0c48bca

Please sign in to comment.