aws

All posts in this category.

Lambda with redis client

sudo apt install python3-pip
pip install redis -t .

In index.py

import boto3
import redis
import datetime

# Redis configuration
redis_host = 'cluster-session.***.euc1.cache.amazonaws.com'
redis_port = 6379
redis_password = ''

# S3 configuration
s3_bucket_name = '*****-redis-sessions-debug'

def handler(event, context):
    # Connect to Redis
    client = redis.StrictRedis(
        host=redis_host,
        port=redis_port,
        password=redis_password,
        decode_responses=True
    )

    # Get all keys from Redis
    keys = client.keys('*')

    # Find the biggest key by size
    biggest_key = ''
    biggest_size = 0
    for key in keys:
        size = client.strlen(key)
        if size > biggest_size:
            biggest_key = key
            biggest_size = size

    # Get the value of the biggest key
    value = client.get(biggest_key)

    # Generate a dynamic filename based on the current date and time
    current_time = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M')
    filename = f'{current_time}.txt'

    # Upload the value as a file to S3
    s3 = boto3.resource('s3')
    s3_object = s3.Object(s3_bucket_name, filename)
    s3_object.put(Body=value)

    # Disconnect from Redis
    client.close()

    return 'Success'

The above code will be executed upon a cloudwatch alert (in our case redis cluster memory utilization above a certain threshold). Lambda will then be triggered and will connect to that redis cluster, list all keys and find the one with the biggest value. Then it will copy the value as a text file and send it to an s3 bucket for further dev review. The file itself is named using the current date time.

zip -r redis-debug.zip .

upload the zip file in Lambda
runtime: python 3.10 on arm64 infra
allowed ram: 2056 MB
max execution time: 1min or more depending on how busy your redis cluster is
remember to run lambda in a vpc and give it the appropriate permissions to write to the required s3 bucket

Restaurer un cluster rds aurora mysql depuis un snapshot

Créer le cluster d’abord et ensuite une fois qu’il est prêt ajouter une instance:

aws rds restore-db-cluster-from-snapshot \
    --db-cluster-identifier restored-db-01-march \
    --snapshot-identifier awsbackup:job-fdgdfsgds-5ef1-c33b-dfdfgdsfg \
    --engine aurora-mysql \
    --engine-version 5.7.mysql_aurora.2.10.3 \
    --db-cluster-parameter-group-name test-aurora-57-cluster-parameter-group \
    --vpc-security-group-ids sg-dfsqdgqfdsf \
    --db-subnet-group-name aurora-fdsqfdqs-mysql-dfdqsfqsdf

aws rds create-db-instance \
  --db-instance-identifier restored-db-01-march \
  --db-instance-class db.t4g.medium \
  --engine aurora-mysql \
  --db-cluster-identifier restored-db-01-march

Depuis la console aws ca se fait en une seule fois

Augmenter le nombre max de pods par node sous AWS EKS

Par défaut le nombre maximal de pods par instance EKS dépend du type de l’instance, voir les limites suivantes ici: https://github.com/awslabs/amazon-eks-ami/blob/master/files/eni-max-pods.txt

Ce nombre max peut être débridé en suivant ce guide: https://aws.amazon.com/blogs/containers/amazon-vpc-cni-increases-pods-per-node-limits/

Unmanaged nodegroups eksctl config:

...      
      privateNetworking: true
      overrideBootstrapCommand: |
        #!/bin/bash
        set -o xtrace
        /etc/eks/bootstrap.sh prod \
          --kubelet-extra-args '--register-with-taints="github-runners=arm64:NoSchedule" --node-labels=github-runners-arm=true --max-pods=150' --use-max-pods false

En plus il faut activer:

kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true
kubectl set env ds aws-node -n kube-system WARM_PREFIX_TARGET=1

Arm64 ou multiarch build sous Jenkins x86 / ecr

Docker Buildx est une extension de Docker qui permet de créer des images Docker pour plusieurs plates-formes, y compris des plates-formes d’architecture différentes. Il permet également de créer des images pour plusieurs architectures à la fois, ce qui facilite la création de conteneurs Docker multi-plateformes.

Les commandes ci-dessus créent un environnement de build pour la plate-forme arm64. La commande « docker buildx create –name arm64 –platform linux/arm64 » crée un environnement de build nommé « arm64 » avec la plate-forme Linux/arm64 configurée. La commande « docker buildx inspect arm64 –bootstrap » configure l’environnement de build pour utiliser la plate-forme arm64. La commande « docker buildx use arm64 » active l’environnement de build pour la plate-forme arm64.

Enfin, la commande « docker run –rm –privileged multiarch/qemu-user-static –reset -p yes » configure l’environnement pour utiliser QEMU, un émulateur de processeur, pour exécuter des binaires de différentes architectures. Cela permet de construire des images Docker pour des plates-formes d’architecture différentes, même si l’hôte de build ne prend pas en charge ces plates-formes directement.

#!/bin/bash

#user with limited permissions 
export AWS_REGION="eu-central-1"
export AWS_ACCESS_KEY_ID="***"
export AWS_SECRET_ACCESS_KEY="***"
export KUBECONFIG=/home/ubuntu/kubeconfig

aws ecr get-login-password | docker login --username AWS --password-stdin ***.dkr.ecr.eu-central-1.amazonaws.com/app-prod

docker buildx create --name arm64 --platform linux/arm64
docker buildx inspect arm64 --bootstrap
docker buildx use arm64

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

#get .env from secrets manager
aws secretsmanager get-secret-value --secret-id app-prod --query SecretString --output text| jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' > files/.env

docker buildx build --push --platform linux/arm64 -t ***.dkr.ecr.eu-central-1.amazonaws.com/app-prod:$GIT_COMMIT -f Dockerfile . --no-cache
sleep 10

#update daemonset in k8s
kubectl set image daemonset/generator-app-ds -n prod app=***.dkr.ecr.eu-central-1.amazonaws.com/app-prod:$GIT_COMMIT

Surveiller le nombre d’événements dans une file d’attente Redis sous Kubernetes et AWS CloudWatch

En gros, on créé un conteneur avec Redis et aws cli, qui va lire le nombre d’événements et envoyer l’info en tant que métrique personnalisée à CloudWatch. Ensuite on peut créer une alarme qui sera déclenchée à partir d’un certain seuil et comme action possible augmenter le nombre d’instances dans un groupe asg …

Commençons par construire une image Docker minimale:

FROM ubuntu:22.04

RUN  apt-get update; DEBIAN_FRONTEND=noninteractive apt-get install wget curl jq zip unzip -y \
     && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
     && unzip awscliv2.zip && bash ./aws/install \
     && apt autoclean \
     && apt autoremove

RUN apt-get install redis less -y

Ceci est le Dockerfile

docker build -t xxx.dkr.ecr.eu-central-1.amazonaws.com/docker-images:queue-monitor-v1 -f Dockerfile .
docker push xxx.dkr.ecr.eu-central-1.amazonaws.com/docker-images:queue-monitor-v1

Ensuite notre manifest pour k8s:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: queue-monitor-prod
  namespace: queue-monitor
  annotations:
    reloader.stakater.com/auto: "true"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: queue-monitor-prod
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: queue-monitor-prod
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: app
        securityContext:
          runAsUser: 0
          runAsGroup: 0
        command: [ "/bin/bash", "-c" ]
        args: [ "/etc/queue-monitor/startup.sh" ]
        image: xxx.dkr.ecr.eu-central-1.amazonaws.com/docker-images:queue-monitor-v1 
        imagePullPolicy: IfNotPresent
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "cp -a /etc/.aws /root/.aws"]
        env:
        - name: AWS_PROFILE
          value: prod
        resources:
          limits:
            cpu: 1
            memory: 1Gi
          requests:
            cpu: 1m
            memory: 1Mi
        livenessProbe:
          exec:
            command:
            - /bin/bash
            - -c
            - /etc/queue-monitor/health.sh
          failureThreshold: 1
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        readinessProbe:
          exec:
            command:
            - /bin/bash
            - -c
            - /etc/queue-monitor/health.sh
          initialDelaySeconds: 3
          periodSeconds: 5
          successThreshold: 1
          timeoutSeconds: 1
        volumeMounts:
        - name: config
          mountPath: "/etc/queue-monitor"
        - name: awsconfig
          mountPath: "/etc/.aws"
      volumes:
      - name: config
        projected:
          defaultMode: 0755
          sources:
          - configMap:
              name: queue-monitor-config-prod
      - name: awsconfig
        secret:
          secretName: queue-monitor-sec
          items:
          - key: credentials
            path: credentials
            mode: 0600
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: queue-monitor-config-prod
  namespace: queue-monitor
data:
  health.sh: |
    exit 0

  startup.sh: |
    #!/bin/bash
    #
    #loop starting

    while true
    do

    queue=$(redis-cli -h cluster-queue.xxxxxxxx.0001.euc1.cache.amazonaws.com LLEN queues:default | awk '{print $1}')
    TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
    aws cloudwatch put-metric-data --metric-name queue-monitoring-prod --namespace queue-monitoring --value "$queue" --timestamp "$TIMESTAMP"

    sleep 15

    done

Je vous laisse personnaliser le vôtre, ce setup n’est pas parfait car a dû être machiné en une dizaine de minutes seulement.

Get a list of all mysql users and their privileges

mysql -h***.us-west-2.rds.amazonaws.com -uroot -p*** --raw --silent -e "SELECT CONCAT('SHOW GRANTS FOR ''', user, '''@''', host, ''';') AS query FROM mysql.user" > /tmp/users.sql

This command uses the MySQL command line tool to generate a SQL file called « users.sql » in the /tmp directory. The SQL file contains a series of SHOW GRANTS statements for each user on the database.

mysql -h***.us-west-2.rds.amazonaws.com -uroot -p*** --raw --silent -e "source /tmp/users.sql" > /tmp/grants.sql ​

This command executes the SHOW GRANTS statements in the « users.sql » file and saves the output to a new SQL file called « grants.sql » in the /tmp directory.

sed -i 's/$/;/g' /tmp/grants.sql

This command uses sed to add a semicolon at the end of each line in the « grants.sql » file. This is necessary to make the file a valid SQL script.

After running these commands, the « grants.sql » file in the /tmp directory will contain a series of GRANT statements for each user on the database, allowing you to easily see the permissions granted to each user.