asanger.dev

eventbridge.tf:

data "aws_subnet" "subnet_id_A" {
  filter {
    name   = "tag:aws:cloudformation:logical-id"
    values = ["PrivateSubnetA"]
  }
}

data "aws_subnet" "subnet_id_B" {
  filter {
    name   = "tag:aws:cloudformation:logical-id"
    values = ["PrivateSubnetB"]
  }
}

data "aws_subnet" "subnet_id_C" {
  filter {
    name   = "tag:aws:cloudformation:logical-id"
    values = ["PrivateSubnetC"]
  }
}


### Lambda Function
## Create Lambda Role
resource "aws_iam_role" "announcement-nodegroup-rollout" {
  name = "announcement-nodegroup-rollout"

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

## Create LogGroup
resource "aws_cloudwatch_log_group" "announcement-nodegroup-rollout" {
  name              = "/aws/lambda/announcement-nodegroup-rollout"
  retention_in_days = 7
}

resource "aws_iam_policy" "announcement-nodegroup-rollout" {
  name        = "announcement-nodegroup-rollout"
  path        = "/"
  description = "IAM policy for logging from a lambda"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    },
    {
        "Effect": "Allow",
        "Action": [
            "ec2:CreateNetworkInterface",
            "ec2:DeleteNetworkInterface",
            "ec2:DescribeNetworkInterfaces"
        ],
        "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "announcement-nodegroup-rollout" {
  role       = aws_iam_role.announcement-nodegroup-rollout.name
  policy_arn = aws_iam_policy.announcement-nodegroup-rollout.arn
}
##

resource "aws_lambda_function" "announcement-nodegroup-rollout" {

  description      = "Send Nodegroup Rollout Announcement to Teams"
  filename         = data.archive_file.lambda_zip.output_path
  source_code_hash = data.archive_file.lambda_zip.output_base64sha256
  function_name    = "announcement-nodegroup-rollout"
  role             = aws_iam_role.announcement-nodegroup-rollout.arn
  timeout          = 180
  runtime          = "python3.12"
  handler          = "lambda_function.lambda_handler"
  memory_size      = 256

  vpc_config {

    subnet_ids         = [data.aws_subnet.subnet_id_A.id, data.aws_subnet.subnet_id_B.id, data.aws_subnet.subnet_id_C.id]
    security_group_ids = lookup(var.security_group_ids, var.stage)
  }

  environment {
    variables = {
      stage       = var.stage
      webhook_url = var.webhook_url
    }
  }

  tags = {
    Function        = "announcement-nodegroup-rollout"
    Customer        = "os/tvnow/systems"
    CustomerProject = "r5s-announcements"
  }
}

data "archive_file" "lambda_zip" {
  type        = "zip"
  source_dir  = "${path.module}/lambda-nodegroup-rollout-source/package"
  output_path = "${path.module}/lambda-nodegroup-rollout-source/package/lambda_function.zip"
}


###
resource "aws_lambda_permission" "announcement-nodegroup-rollout" {
  statement_id  = "AllowExecutionFromEventBridge"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.announcement-nodegroup-rollout.function_name
  principal     = "events.amazonaws.com"
  source_arn    = module.eventbridge.eventbridge_rule_arns["logs"]
}



module "eventbridge" {
  source  = "terraform-aws-modules/eventbridge/aws"
  version = "v2.3.0"

  create_bus = false

  rules = {
    logs = {
      name          = "announcement-UpdateNodegroupVersion"
      description   = "announcement-UpdateNodegroupVersion"
      event_pattern = jsonencode({ "detail" : { "eventName" : ["UpdateNodegroupVersion"] } })
    }
  }

  targets = {
    logs = [
      {
        name = "announcement-UpdateNodegroupVersion"
        arn  = aws_lambda_function.announcement-nodegroup-rollout.arn
      }
    ]
  }
}

lambda_function.py:

import urllib3
import json
import os

class TeamsWebhookException(Exception):
    """custom exception for failed webhook call"""
    pass


class ConnectorCard:
    def __init__(self, hookurl, http_timeout=60):
        self.http = urllib3.PoolManager()
        self.payload = {}
        self.hookurl = hookurl
        self.http_timeout = http_timeout

    def text(self, mtext):
        self.payload["text"] = mtext
        return self

    def send(self):
        headers = {"Content-Type":"application/json"}
        r = self.http.request(
                'POST',
                f'{self.hookurl}',
                body=json.dumps(self.payload).encode('utf-8'),
                headers=headers, timeout=self.http_timeout)
        if r.status == 200: 
            return True
        else:
            raise TeamsWebhookException(r.reason)

def lambda_handler(event, context):
        print(event['detail']['requestParameters']['nodegroupName'])
        
        if("r5s-default" not in event['detail']['requestParameters']['nodegroupName']):
            return {
                'statusCode': 200,
                'body': json.dumps('Announcing only default Node Group')
            }            
        stage = os.environ['stage']
        webhook_url = os.environ['webhook_url']
        f = open("announcement.tpl", "r").read().replace('###STAGE###', stage)
        myTeamsMessage = ConnectorCard(webhook_url)
        myTeamsMessage.text(f)
        myTeamsMessage.send()

announcement.tpl:

<h1><b>r5s Node Rollout gestarted</b></h1>
Soeben wurde auf r5s ###STAGE### ein Node Rollout gestarted (angestoßen durch Updates, Config Changes,...).<br />

Environment Varbales:

stage = dev|preprod|prod

webhook_url: <webhook url>

    - helm diff -n $namespace upgrade jira-exporter jira-exporter --values jira-exporter/values.yaml --allow-unreleased
     --set ingress.tls[0].hosts[0]="jira-prometheus-exporter.cloud"
     --set ingress.hosts[0].host="jira-prometheus-exporter.cloud"
     --set image.tag=$VERSION
     --set secretstore=$secretstore
     --set secretstore_role=$secretstore_role
     --set sa_role=$sa_role
     --set env=$ENV
    - helm upgrade --install jira-exporter jira-exporter -f jira-exporter/values.yaml -n $namespace --create-namespace $DRYRUN
     --set ingress.tls[0].hosts[0]="jira-prometheus-exporter.cloud"
     --set ingress.hosts[0].host="jira-prometheus-exporter.cloud"
     --set image.tag=$VERSION
     --set secretstore=$secretstore
     --set secretstore_role=$secretstore_role
     --set sa_role=$sa_role
     --set env=$ENV

Da ingress eine Map ist muss dieser auch entsprechend gesetzt werden.

kubectl rollout restart deployment/subgraph-pbf

Synopsis

Manage the rollout of one or many resources.

Valid resource types include:

  • deployments
  • daemonsets
  • statefulsets
kubectl rollout SUBCOMMAND

Examples

  # Rollback to the previous deployment
  kubectl rollout undo deployment/abc
  
  # Check the rollout status of a daemonset
  kubectl rollout status daemonset/foo
  
  # Restart a deployment
  kubectl rollout restart deployment/abc
  
  # Restart deployments with the 'app=nginx' label
  kubectl rollout restart deployment --selector=app=nginx

Hier wird erst eine Liste von PIDs erstellt denen dann 50% CPU zugewiesen wird.

ps faux | grep '/usr/local/bin/node --' | awk '{print $2}' |  xargs -I{} cpulimit -p {} -l 50
git reset --soft HEAD^

Diese Command kann wiederholt werden im weitere Commits zu resetten.

git reset --soft HEAD^^^

Hier werden die letzten 3 Commits resetted

helm upgrade --install  jira-exporter -f jira-exporter/values.yaml jira-exporter

GitOps ist ein Ansatz für die Verwaltung von Infrastruktur- und Anwendungsdeklarationen in einer Kubernetes- oder Cloud-native-Umgebung. Im Wesentlichen bedeutet GitOps, dass das gesamte Systemzustandsmanagement und die Bereitstellung von Anwendungen in einem Git-Repository verwaltet werden.

Hier sind einige Kernkonzepte von GitOps:

  1. Git als Single Source of Truth: Alle Änderungen an der Infrastruktur und den Anwendungen werden in einem Git-Repository verfolgt. Dieses Repository fungiert als einzige Quelle der Wahrheit für den Zustand des Systems.
  2. Declarative Configuration: Die Infrastruktur- und Anwendungsdeklarationen werden in einer deklarativen Sprache (z.B. YAML) geschrieben, was bedeutet, dass sie den gewünschten Endzustand beschreiben, nicht die Schritte, um dorthin zu gelangen.
  3. Automatisierung durch Continuous Deployment: Änderungen, die in das Git-Repository eingecheckt werden, lösen automatisierte Bereitstellungsprozesse aus. Diese Prozesse aktualisieren den tatsächlichen Systemzustand, um mit dem im Git-Repository definierten Zustand übereinzustimmen.
  4. Observability und Monitoring: GitOps-Systeme bieten in der Regel Mechanismen zur Überwachung des Systemzustands und zur Erfassung von Metriken, um sicherzustellen, dass das System den gewünschten Zustand beibehält.
  5. Rollback-Fähigkeit: Da der Systemzustand in Git gespeichert ist, ist es einfach, zu früheren Versionen zurückzukehren, wenn ein Problem auftritt.

Durch die Nutzung von GitOps können Entwickler und Betriebsteams eine konsistente und effiziente Methode zur Verwaltung von Infrastruktur und Anwendungen implementieren, die stark auf Automatisierung und Best Practices für die Versionskontrolle setzt.

helm template hpa ingress-nginx -f ingress-nginx/values.yaml
  • hpa = Name
  • ingress-nginx = Verzeichnis mit dem Chart
  • -f Datei mit Values
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/*/nginx_ingress_controller_per_second" | jq .