From 25aa89c6d2276b942bc76fd14c8d86f724845abf Mon Sep 17 00:00:00 2001 From: Hugo Samayoa Date: Fri, 30 Oct 2020 00:21:11 -0700 Subject: [PATCH 1/3] AWS EKS Cluster support --- Dockerfile | 8 +++++- internal/kube/kube.go | 33 ++++++++++++++++++++++- internal/kube/kube_test.go | 55 +++++++++++++++++++++++++++++++++++++- main.go | 6 ++++- 4 files changed, 98 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6a7a9bf..34870f5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,13 +14,18 @@ ENV HELM_URL=https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz ARG KUBECTL_VERSION=1.19.2 ENV KUBECTL_URL=https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl +ARG AWS_IAM_AUTHENTICATOR_VERION=1.18.8/2020-09-18 +ENV AWS_IAM_AUTHENTICATOR_URL=https://amazon-eks.s3.us-west-2.amazonaws.com/${AWS_IAM_AUTHENTICATOR_VERION}/bin/linux/amd64/aws-iam-authenticator + WORKDIR /tmp RUN true \ && wget -O helm.tgz "$HELM_URL" \ && tar xvpf helm.tgz linux-amd64/helm \ && mv linux-amd64/helm /usr/local/bin/helm \ && wget -O /usr/local/bin/kubectl "$KUBECTL_URL" \ - && chmod +x /usr/local/bin/kubectl + && chmod +x /usr/local/bin/kubectl \ + && wget -O /usr/local/bin/aws-iam-authenticator "$AWS_IAM_AUTHENTICATOR_URL" \ + && chmod +x /usr/local/bin/aws-iam-authenticator # --- @@ -28,6 +33,7 @@ FROM busybox:glibc COPY --from=downloader /usr/local/bin/helm /usr/local/bin/helm COPY --from=downloader /usr/local/bin/kubectl /usr/local/bin/kubectl +COPY --from=downloader /usr/local/bin/aws-iam-authenticator /usr/local/bin/aws-iam-authenticator COPY --from=builder /etc/ssl/certs /etc/ssl/certs COPY --from=builder /tmp/build/drone-helm3 /usr/local/bin/drone-helm3 diff --git a/internal/kube/kube.go b/internal/kube/kube.go index f999b78..cd65e23 100644 --- a/internal/kube/kube.go +++ b/internal/kube/kube.go @@ -14,6 +14,8 @@ type ( Certificate string SkipTLS bool Namespace string + EKSCluster string + EKSRoleARN string } Option func(*kubeConfig) @@ -39,7 +41,21 @@ clusters: users: - name: helm user: +{{- if .Token }} token: {{ .Token }} +{{- else if .EKSCluster }} + exec: + apiVersion: client.authentication.k8s.io/v1alpha1 + command: aws-iam-authenticator + args: + - "token" + - "-i" + - "{{ .EKSCluster }}" + {{- if .EKSRoleARN }} + - "-r" + - "{{ .EKSRoleARN }}" + {{- end }} +{{- end }} contexts: - name: helm @@ -67,6 +83,18 @@ func WithToken(token string) Option { } } +func WithEKSCluster(eksCluster string) Option { + return func(k *kubeConfig) { + k.EKSCluster = eksCluster + } +} + +func WithEKSRoleARN(eksRoleARN string) Option { + return func(k *kubeConfig) { + k.EKSRoleARN = eksRoleARN + } +} + func WithCertificate(certificate string) Option { return func(k *kubeConfig) { k.Certificate = certificate @@ -96,9 +124,12 @@ func CreateKubeConfig(options ...Option) error { if k.ApiServer == "" { return fmt.Errorf("no kubernetes api server provided") } - if k.Token == "" { + if k.Token == "" && k.EKSCluster == "" { return fmt.Errorf("no kubernetes token provided") } + if k.Token != "" && k.EKSCluster != "" { + return fmt.Errorf("token cannot be used simultaneously with eksCluster") + } if k.Namespace == "" { return fmt.Errorf("no namespace provided") } diff --git a/internal/kube/kube_test.go b/internal/kube/kube_test.go index e1ef85f..f198a52 100644 --- a/internal/kube/kube_test.go +++ b/internal/kube/kube_test.go @@ -82,6 +82,49 @@ contexts: user: helm `, }, + { + options: []Option{ + WithConfig(kubeconfig), + WithApiServer("https://example.com"), + WithCertificate("CERTDATA"), + WithEKSCluster("eks_cluster"), + WithEKSRoleARN("my-eks-role-arn"), + WithNamespace("myapp"), + }, + want: ` +apiVersion: v1 +kind: Config + +current-context: "helm" +preferences: {} + +clusters: + - name: helm + cluster: + server: https://example.com + certificate-authority-data: CERTDATA + +users: +- name: helm + user: + exec: + apiVersion: client.authentication.k8s.io/v1alpha1 + command: aws-iam-authenticator + args: + - "token" + - "-i" + - "eks_cluster" + - "-r" + - "my-eks-role-arn" + +contexts: + - name: helm + context: + cluster: helm + namespace: myapp + user: helm +`, + }, { options: []Option{ WithConfig(kubeconfig), @@ -137,10 +180,20 @@ contexts: options: []Option{ WithConfig(kubeconfig), WithApiServer("https://example.com"), + WithToken("token"), + WithEKSCluster("eks_cluster"), WithNamespace("myapp"), }, - err: fmt.Errorf("no kubernetes token provided"), + err: fmt.Errorf("token cannot be used simultaneously with eksCluster"), }, + { + options: []Option{ + WithConfig(kubeconfig), + WithApiServer("https://example.com"), + WithNamespace("myapp"), + }, + err: fmt.Errorf("no kubernetes token provided"), + }, { options: []Option{ WithConfig(kubeconfig), diff --git a/main.go b/main.go index bd70ed7..9622157 100644 --- a/main.go +++ b/main.go @@ -24,9 +24,11 @@ type ( KubeSkip bool `envconfig:"KUBE_SKIP" default:"false"` // skip creation of kubeconfig KubeConfig string `envconfig:"KUBE_CONFIG" default:"/root/.kube/config"` // path to kubeconfig KubeApiServer string `envconfig:"KUBE_API_SERVER" required:"true"` // kubernetes api server - KubeToken string `envconfig:"KUBE_TOKEN" required:"true"` // kubernetes token + KubeToken string `envconfig:"KUBE_TOKEN"` // kubernetes token KubeCertificate string `envconfig:"KUBE_CERTIFICATE"` // kubernetes http ca KubeSkipTLS bool `envconfig:"KUBE_SKIP_TLS" default:"false"` // disable kubernetes tls verify + EKSCluster string `envconfig:"EKS_CLUSTER"` // AWS EKS Cluster ID to put in kubeconfig + EKSRoleARN string `envconfig:"EKS_ROLE_ARN"` // AWS IAM role resource name to put in kubeconfig PushGatewayURL string `envconfig:"PUSHGATEWAY_URL" default:""` // url to a prometheus pushgateway server @@ -110,6 +112,8 @@ func main() { kube.WithConfig(cfg.KubeConfig), kube.WithApiServer(cfg.KubeApiServer), kube.WithToken(cfg.KubeToken), + kube.WithEKSCluster(cfg.EKSCluster), + kube.WithEKSRoleARN(cfg.EKSRoleARN), kube.WithNamespace(cfg.Namespace), kube.WithCertificate(cfg.KubeCertificate), kube.WithSkipTLS(cfg.KubeSkipTLS), From 3cedd90e476fd939b06e95d723d780935f7b2a6b Mon Sep 17 00:00:00 2001 From: Hugo Samayoa Date: Fri, 30 Oct 2020 00:48:25 -0700 Subject: [PATCH 2/3] add EKS documentation --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/README.md b/README.md index 383b54f..633eb73 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,60 @@ Example: An always up2date version of the availible config options can be viewed on the source on the `Config` `struct` [here][1]. +## Deploying to EKS + +Example: + +```yaml +- name: deploy app + image: bitsbeats/drone-helm3 + environment: + AWS_DEFAULT_REGION: us-east-1 + settings: + kube_api_server: kube.example.com + eks_cluster: my-eks-cluster + + chart: ./path-to/chart + release: release-name + namespace: namespace-name + timeout: 20m + helm_repos: + - bitnami=https://charts.bitnami.com/bitnami + envsubst: true + values: + - app.environment=awesome + - app.tag=${DRONE_TAG/v/} + - app.commit=${DRONE_COMMIT_SHA} +``` + +Role Based EKS Access Example: + +```yaml +- name: deploy app + image: bitsbeats/drone-helm3 + environment: + AWS_DEFAULT_REGION: us-east-1 + settings: + kube_api_server: kube.example.com + eks_cluster: my-eks-cluster + eks_role_arn: arn:aws:iam::[ACCOUNT ID HERE]:role/[ROLE HERE] + + chart: ./path-to/chart + release: release-name + namespace: namespace-name + timeout: 20m + helm_repos: + - bitnami=https://charts.bitnami.com/bitnami + envsubst: true + values: + - app.environment=awesome + - app.tag=${DRONE_TAG/v/} + - app.commit=${DRONE_COMMIT_SHA} +``` + +**Note**: +Depending on your setup you might also need to pass `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` to the environment. + ## Monitoring Its possible to monitor your builds and rollbacks using prometheus and From e04881e0ba437361f504c94cf2137c02f21d4060 Mon Sep 17 00:00:00 2001 From: Hugo Samayoa Date: Fri, 30 Oct 2020 00:55:16 -0700 Subject: [PATCH 3/3] small typo --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 34870f5..0649282 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,8 @@ ENV HELM_URL=https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz ARG KUBECTL_VERSION=1.19.2 ENV KUBECTL_URL=https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl -ARG AWS_IAM_AUTHENTICATOR_VERION=1.18.8/2020-09-18 -ENV AWS_IAM_AUTHENTICATOR_URL=https://amazon-eks.s3.us-west-2.amazonaws.com/${AWS_IAM_AUTHENTICATOR_VERION}/bin/linux/amd64/aws-iam-authenticator +ARG AWS_IAM_AUTHENTICATOR_VERSION=1.18.8/2020-09-18 +ENV AWS_IAM_AUTHENTICATOR_URL=https://amazon-eks.s3.us-west-2.amazonaws.com/${AWS_IAM_AUTHENTICATOR_VERSION}/bin/linux/amd64/aws-iam-authenticator WORKDIR /tmp RUN true \