AWS — Lambda: kubectl

Пример того, как можно создавать сущности в Kubernetes, используя AWS Lambda.

Функция будет на Python3, так что воспользуемся Kubernetes Python Client

Больше примеров по использованию можно найти тут.

Так как AWS Lambda не поддерживает данный пакет, упакуем в нашу функцию модули "kubernetes" и "boto3".

"boto3" понадобится для обращения в AWS SSM, где будет хранится kubeconfig

 

Подготовка

Создадим директорию для лямбды и перейдем в нее:

mkdir lambda
cd lambda

 

Дальше понадобится "virtualenv", если его нет, можно его установить используя "pip3":

pip3 install virtualenv

 

Создаем виртуальное окружение и активируем его:

python3 -m virtualenv .
source bin/activate

 

И ставим необходимые модули:

pip3 install kubernetes
pip3 install boto3

 

Дальше нам нужно только содержимое данной директории:

$VIRTUAL_ENV/lib/python3.7/site-packages

 

"python3.7" — замените на свою версию Python

 

Удобнее будет посмотреть путь окружения и скопировать содержимое в отдельно созданную директорию, уже не в виртуальном окружении:

echo $VIRTUAL_ENV/lib/python3.7/site-packages
/private/tmp/lambda/lib/python3.7/site-packages

 

Создадим директорию для лямбды, которую будем уже непосредственно загружать и скопируем наши модули:

mkdir ~/lambda_upload
cp -R /private/tmp/lambda/lib/python3.7/site-packages/. ~/lambda_upload/

 

SSM Parameter Store

В консоли AWS перейдем в "Systems Manager" -> "Parameter Store"

 

И создадим параметр с типом "SecureString" и в качестве значение скопируем содержимое "kubeconfig" файла. Если это EKS, предварительно создайте сервис аккаунт, чтобы он не требовал AWS авторизации, как в примере ниже:

Kubeconfig с AWS авторизацией:

...
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - eu-central-1
      - eks
      - get-token
      - --cluster-name
      - artem-services-stage-eks
      command: aws

 

Функция

Теперь в директории "~/lambda_upload" создадим файл с именем "lambda_function.py" и вставим в него следующий текст:

lambda_function.py:

import os
import time
import random
import string
import boto3

from kubernetes import config
from kubernetes.client import Configuration
from kubernetes.client.api import core_v1_api
from kubernetes.client.rest import ApiException
from kubernetes.stream import stream

# Get Kubeconfig from SSM
def get_kube_config():
    awsRegion = os.environ['AWS_REGION']
    ssmParameter = os.environ['SSM']

    ssm = boto3.client('ssm', region_name=awsRegion)
    parameter = ssm.get_parameter(Name=ssmParameter, WithDecryption=True)

    kubeconfig = open( '/tmp/kubeconfig.yaml', 'w' )
    kubeconfig.write(parameter['Parameter']['Value'])
    kubeconfig.close()

# Generate random string for unique name of Pod
def randomString(stringLength=8):
    letters = string.ascii_lowercase + string.digits
    return ''.join(random.choice(letters) for i in range(stringLength))

def exec_commands(api_instance):
    name = "busybox-" + randomString()
    namespace = "default"
    resp = None

    print("Creating pod...")

    pod_manifest = {
        'apiVersion': 'v1',
        'kind': 'Pod',
        'metadata': {
            'name': name
        },
        'spec': {
            'containers': [{
                'image': 'busybox',
                'name': 'busybox',
                "args": [
                    "/bin/sh",
                    "-c",
                    "while true;do date;sleep 5; done"
                ]
            }]
        }
    }
    resp = api_instance.create_namespaced_pod(body=pod_manifest, namespace=namespace)

    while True:
        resp = api_instance.read_namespaced_pod(name=name, namespace=namespace)
        if resp.status.phase == 'Pending' or resp.status.phase == 'Running':
            print("Done. Pod " + name + " was created.")
            break
        time.sleep(1)

def main(event, context):
    get_kube_config()

    config.load_kube_config(config_file="/tmp/kubeconfig.yaml")
    c = Configuration()
    c.assert_hostname = False
    Configuration.set_default(c)
    core_v1 = core_v1_api.CoreV1Api()

    exec_commands(core_v1)


if __name__ == '__main__':
    main()

 

Теперь все содержимое директории можно упаковывать в "zip" архив и загружать в Lambda функцию.

В переменном окружении создайте 2 переменных, в которых укажите ваш AWS Region и имя SSM Parameter Store, который создали раннее.

 

Для Lambda функции потребуются права на чтение из SSM, так что приатачте к роли, которую использует Lambda следующую политику:

arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess

 

После запуска функции, она создаст pod с именем "busybox-" + сгенерированная строка, из 8-ми символов. Проверки состояния pod'а нет, так как данный скрипт планируется использовать для EKS Fargate, чтобы не ждать 1-2 минуты, пока Fargate инстанс поднимется, так что при любом из состояний, "Pending" или "Running" считаем, что pod был успешно создан.

Метки: Метки

Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии