LambdaからEKSを操作する


はじめに

KubernetesではJobやCronJobが用意されていますが、ジョブ内容によってはLambdaに寄せてもよい場合があります。
今回はEKSクラスタに対するkubectl操作をLambdaから実施するための手順を説明します。

設定手順

Lambda Layerのデプロイ

AWSコンソールのLambdaのページから作成していきます。

Serverless Application Repositoryからlambda-layer-kubectlを選択します。

LayerNameに任意の名前を入力しデプロイします。

IAM Roleの作成

Lambda関数で使用するIAM Roleをlambda-kubectlという名前で作成します。

EKSの権限を持つ以下のようなIAM Policyをアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:*",
                "eks:*"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

また、信頼関係には以下のようにLambdaサービスを入れておきます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

aws-authの更新

以下のようにaws-authを編集しapplyします。

aws-auth.yaml
apiVersion: v1
data:
  mapRoles: |
+    - rolearn: 'arn:aws:iam::XXXXXXXXXXXX:role/lambda-kubectl'
+      username: 'lambda-kubectl'
+      groups:
+        - 'system:masters'
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
$ kubectl apply -f aws-auth.yaml

Lambda関数の作成

Lambda Layer同様、AWSコンソールのLambdaのページから作成していきます。

カスタムランタイムを使用し、先述のIAM Roleを付与します。

まずはLambda Layerを追加します。

ARNを指定して追加します。

bootstrapにkubectlの処理を追記します。

bootstrap
#!/bin/sh
set -euo pipefail

# Handler format: <script_name>.<bash_function_name>
#
# The script file <script_name>.sh  must be located at the root of your
# function's deployment package, alongside this bootstrap executable.
source $(dirname "$0")/"$(echo $_HANDLER | cut -d. -f1).sh"

while true
do
+   export PATH=$PATH:/opt/awscli:/opt/kubectl
+   aws eks update-kubeconfig --name test-cluster --kubeconfig /tmp/kubeconfig
+   kubectl get node --kubeconfig /tmp/kubeconfig
    # Request the next event from the Lambda runtime
    HEADERS="$(mktemp)"
    EVENT_DATA=$(curl -v -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
    INVOCATION_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)

    # Execute the handler function from the script
    RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")

    # Send the response to Lambda runtime
    curl -v -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$INVOCATION_ID/response" -d "$RESPONSE"
done

確認

Lambdaのテストイベントでジョブを実行してみます。
関数で定義したようにEKSに対して操作できていることが確認できます。

まとめ

LambdaからEKSを操作する方法を説明しました。
使用したLambda Layerのlambda-layer-kubectlにはAWS CLIやkubectlの他、helmやjqも同梱されているので汎用性が高いです。

EKSがprivateである場合はLambdaを同一VPC内で実行するようにしましょう。