Привет, Хабр!
Очень важно не только писать хороший код, но и использовать все возможности инфраструктуры на максимум. Именно с этой целью в этой статье рассмотрим, как правильно использовать инструменты кэширования внутри Kubernetes и как настроить CDN для максимума производительности Python-приложения.
Кэширование
kube-fledged
kube-fledged — это дополнение для Kubernetes, позволяющее управлять кэшами образов контейнеров непосредственно на рабочих узлах кластера. Основная цель — ускорение запуска и масштабирования подов за счет предварительного кэширования образов на рабочих узлах.
Для начала работы с kube-fledged, нужно установить его в кластер:
kubectl apply -f https://raw.githubusercontent.com/senthilrch/kube-fledged/master/deploy/kube-fledged.yaml
После установки можно создать ресурс ImageCache
для указания, какие образы должны кэшироваться на каких узлах. Пример манифеста для кэширования образа Python:
apiVersion: kubefledged.io/v1alpha2
kind: ImageCache
metadata:
name: python-image-cache
spec:
cacheSpec:
images:
- name: python:3.12-alpine
pullPolicy: IfNotPresent
nodeSelector:
matchLabels:
disktype: ssd
Манифест указывает Kubernetes кэшировать образ python:3.12-alpine
на всех узлах с меткой disktype: ssd
. Так ускорим запуск подов, использующих этот образ, поскольку образ уже будет находиться на узле и не потребуется его загрузка с Docker Hub или другого реестра.
kuik
kube-image-keeper — это еще один инструмент, который сохраняет образы контейнеров в локальном реестре.
Kuik использует веб-хук для автоматической модификации спецификаций подов, чтобы использовать локально кэшированные образы. Пример конфигурации kuik, которая создает кэш для образа nginx:
apiVersion: kuik.io/v1alpha1
kind: CachedImage
metadata:
name: nginx-cached
spec:
image: nginx:latest
Установив kuik в кластере, можно управлять кэшем через Kubernetes API.
Промежуточное кэширование результатов API
Ещё один способ ускорения приложений — кэширование ответов от API.
Например, используем Redis для кэширования ответов API в Python-приложении. Предположим, есть функция, которая обращается к внешнему сервису для получения информации о погоде. Можно кэшировать эти данные, чтобы при последующих запросах снизить задержку:
import redis
import requests
cache = redis.Redis(host='localhost', port=6379, db=0)
def get_weather(city):
# попытка получить данные из кэша
if (cached_weather := cache.get(city)) is not None:
return cached_weather.decode('utf-8')
# запрос к API для получения погоды
response = requests.get(f'http://api.weatherapi.com/v1/current.json?key=API_KEY&q={city}')
weather_data = response.json()['current']['condition']['text']
# кэширование данных
cache.setex(city, 3600, weather_data) # кэш действителен 1 час
return weather_data
current_weather = get_weather('Moscow')
print(current_weather)
Если информация о погоде для указанного города уже есть в кэше, мы извлекаем её оттуда, в противном случае делаем запрос к API и сохраняем результат в кэше на один час.
CDN
Cloudflare CDN с контроллерами входа Kubernetes позволяет распределять статические ресурсы и оптимизировать маршрутизацию трафика. Все это достигается за счет кэширования статических активов, что снижает нагрузку на кластер и улучшает время ответа для конечных пользователей. Для интеграции потребуется создать Ingress ресурс в Kubernetes и настроить DNS записи в Cloudflare для указания на Ingress контроллер.
Пример настройки Ingress в Kubernetes с Cloudflare:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
После настройки Ingress, настраиваем CNAME запись в Cloudflare аккаунте, чтобы указать на Ingress контроллер.
Еще есть Cloudflare Workers, который позволяет манипулировать запросами и ответами на лету, прежде чем они достигнут приложения:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
let response = await fetch(request)
// логика для изменения ответа
return new Response(response.body, response)
}
Помимо всего этого, есть функция автоматической оптимизации изображений, которая существенно сокращает размер файлов без потери качества. Для включения этой функции нужно будет активировать настройку Polish в Cloudflare аккаунте.
Пример управление этим через API:
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/polish" \
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: API_KEY" \
-H "Content-Type: application/json" \
--data '{"value":"lossless"}'
Так можно активировать оптимизацию изображений в режиме lossless.
Rocket Loader — еще одна полезная функция Cloudflare, которая улучшает время загрузки страниц за счет асинхронной загрузки JavaScript.
Включение Rocket Loader также возможно через API:
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/settings/rocket_loader" \
-H "X-Auth-Email: YOUR_EMAIL" \
-H "X-Auth-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
--data '{"value":"on"}'
Спасибо за прочтение статьи! Какие вы еще знаете методы для оптимизации кода в Python с помощью Kubernetes? Было бы интересно почитать ваши способы в комментариях!
Статья подготовлена в преддверии старта курса "Инфраструктурная платформа на основе Kubernetes". Узнать подробнее о курсе и записаться на бесплатные вебинары можно тут.