Пример того, как можно создавать сущности в Kubernetes, используя AWS Lambda.
Функция будет на Python3, так что воспользуемся Kubernetes Python Client
Больше примеров по использованию можно найти тут.
Так как AWS Lambda не поддерживает данный пакет, упакуем в нашу функцию модули "kubernetes" и "boto3".
"boto3" понадобится для обращения в AWS SSM, где будет хранится kubeconfig
Подготовка
Создадим директорию для лямбды и перейдем в нее:
1 2 | mkdir lambda cd lambda |
Дальше понадобится "virtualenv", если его нет, можно его установить используя "pip3":
1 | pip3 install virtualenv |
Создаем виртуальное окружение и активируем его:
1 2 | python3 -m virtualenv . source bin /activate |
И ставим необходимые модули:
1 2 | pip3 install kubernetes pip3 install boto3 |
Дальше нам нужно только содержимое данной директории:
1 | $VIRTUAL_ENV /lib/python3 .7 /site-packages |
"python3.7" — замените на свою версию Python
Удобнее будет посмотреть путь окружения и скопировать содержимое в отдельно созданную директорию, уже не в виртуальном окружении:
1 2 | echo $VIRTUAL_ENV /lib/python3 .7 /site-packages /private/tmp/lambda/lib/python3 .7 /site-packages |
Создадим директорию для лямбды, которую будем уже непосредственно загружать и скопируем наши модули:
1 2 | 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 авторизацией:
1 2 3 4 5 6 7 8 9 10 11 12 | ... 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 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 был успешно создан.