Skip to main content

3 posts tagged with "aws"

View All Tags

· One min read

Описание

https://github.com/GoogleCloudPlatform/terraformer

Terraformer - тулза преобразующая существующие облачные ресурсы в terraform код. Может быть полезна в различных кейсах, например: при обучении aws-у и terraform-у - создали ресурсы через console по курсу, а потом дампнули это в terraform код. Либо более классический кейс - описываете существующую инфраструктуру в IaC.

Использование

info

запустить получилось вот так, но это вряд ли best practices

Экспортируем креды доступа к aws-apo

export AWS_DEFAULT_PROFILE=my-profile  # ~/.aws/credentials
export AWS_ACCESS_KEY_ID=id
export AWS_SECRET_ACCESS_KEY=key

Так же нам нужен tf провайдер aws:

terraform {
required_version = ">= 1.3.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "4.42.0"
}
}
}

Инициализируем провайдер, запускаем terraformer и натравливаем на нужный нам aws ресурс

terraform init # инициализируем провайдер в директорию ./.terraform
terraformer import aws --resources=route53 --regions=us-east-1 --profile my-profile
terraformer import aws --resources=route53 --regions=us-east-1 --profile my-profile --filter="Type=route53_zone;Name=tags.Name;Value=my.example.com"

· 7 min read

История, Архитектура

1) aws account mc-legacy

img

Имеется legacy приложение в aws аккаунте:

  1. В route53 зарегистрирован домен <my-company>.io и аналогичная hosted zone
  2. В зоне есть запись <my-service>.<my-company>.io , смотрит на <lb>.<my-company>.io
  3. Балансировщик ведет на ASG
  4. ASG управляет EC2 инсансами на которых работает приложение <my-service>

2) aws account mc-project

img

Принимается решение перевезти приложение в kubernetes, для удобства под каждую команду создается свой aws аккаунт и свой k8s кластер:

  1. В aws поднимается NLB балансировщик <lb-my-project>
  2. Через target groups он смотрит на EC2 инстансы, на которых запущен pod с ingress controller-ом.
  3. Попадая в pod ингресса, запрос через Ingress перенаправляется на pod-ы за <my-service> с помощью k8s service.

3) combine

img

r53 запись <my-service>.<my-company>.io начинает смотреть на CNAME <lb-my-project>, все работает, но SSL не терминируется.

Зона <my-company>.io слишком критична для бизнеса, и передавать в нее управление контроллерам типа external-dns, cert-manager не хочется.

В тоже время aws аккаунтов типа mc-project может быть много, как и кластеров k8s, вручную доставлять секрет с tls сертификатом не хочется.

4) Concept

img

  1. Создается специальный management aws аккаунт и k8s кластер.
  2. В него каким-то образом доставляется секрет с tls сертификатом *.<my-company>.io
  3. Специальный контроллер kubed синхронизирует секрет *.<my-company>.io в другие кластеры k8s с помощью аннотаций.
  4. Секрет *.<my-company>.io используется в Ingress, SSL траффик терминируется.

Конфигурации

info

В последующих конфигурационных файлах роли для mc-mgmt будут называться kubed-master, а mc-project-* - kubed-follower

AWS IAM RBAC

info

На схеме mc-mgmt = CI, mc-project - Target

img

Нужно сделать кросс-аккаунт aws iam rbac роли, для того, чтобы kubed из mc-mgmt мог управлять секретами в k8s кластерах других aws аккаунтов, в данном случае mc-project.

mc-mgmt aka kubed-master

locals {
kubed_followers_arns = [
for _, id in local.aws_accounts_map : "arn:aws:iam::${id}:role/kubed-follower"
]
}

module "iam_assumable_role_kubed_master" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
version = "4.2.0"

create_role = true
role_name = "kubed-master"

provider_url = replace(local.cluster_oidc_issuer_url, "https://", "")

role_policy_arns = [
aws_iam_policy.kubed_master.arn,
aws_iam_policy.kubed_eks.arn,
]

oidc_fully_qualified_subjects = [
"system:serviceaccount:kube-system:kubed"
]
}

data "aws_iam_policy_document" "kubed_master" {
statement {
sid = "kubedMaster"
effect = "Allow"
actions = [
"sts:AssumeRole",
]
resources = local.kubed_followers_arns
}
}

resource "aws_iam_policy" "kubed_master" {
name = "kubed-master"
policy = data.aws_iam_policy_document.kubed_master.json
}

data "aws_iam_policy_document" "kubed_eks" {
statement {
sid = "kubedEks"
effect = "Allow"
actions = [
"eks:DescribeCluster",
"eks:ListClusters"
]
resources = ["*"]
}
}

resource "aws_iam_policy" "kubed_eks" {
name = "kubed-eks"
policy = data.aws_iam_policy_document.kubed_eks.json
}

mc-project aka kubed-follower

locals {
mc_mgmt_id = "<mc-mgmt_id>"
}

data "aws_iam_policy_document" "kubed_follower_assume" {
statement {
sid = "kubedFollowerAssume"
effect = "Allow"
principals {
identifiers = toset(["arn:aws:iam::${local.mc_mgmt_id}:role/kubed-master"])
type = "AWS"
}
actions = [
"sts:AssumeRole",
]
}
}

data "aws_iam_policy_document" "kubed_follower" {
statement {
sid = "kubedEks"
effect = "Allow"
actions = [
"eks:DescribeCluster",
"eks:ListClusters"
]
resources = ["*"]
}
}


resource "aws_iam_policy" "kubed_follower" {
name = "kubed-follower"
policy = data.aws_iam_policy_document.kubed_follower.json
}


resource "aws_iam_role" "kubed_follower" {
name = "kubed-follower"
description = "IAM role which allows kubed sync secrets from mc-mgmt to this account"
assume_role_policy = data.aws_iam_policy_document.kubed_follower_assume.json
managed_policy_arns = [aws_iam_policy.kubed_follower.arn]
}

ServiceAccount kubed

На ServiceAccount kubed-master нужно повесить аннотацию:

annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<mc-mgmt_id>:role/kubed-master

ConfgiMap aws-auth

apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- "groups":
- "system:masters"
"rolearn": "arn:aws:iam::<mc-mgmt_id>:role/kubed-master"
"username": ""
...

Docker image

Образ от разработчиков scratch, в нем есть только бинарник kubed, нам же нужны утилиты aws для генерирования kubeconfig.

FROM appscode/kubed:v0.13.2 as downloader

FROM alpine:3.17

COPY --from=downloader /kubed /usr/bin/kubed

RUN apk add --no-cache \
curl~=7.86 \
py3-pip~=22.3 \
&& pip install --no-cache-dir \
awscli~=1.27 \
&& curl -Lo aws-iam-authenticator https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v0.5.9/aws-iam-authenticator_0.5.9_linux_amd64 \
&& chmod +x aws-iam-authenticator \
&& mv aws-iam-authenticator /usr/bin/

RUN addgroup --gid 1950 app \
&& addgroup --gid 1000 app \
&& adduser \
--uid 1000 \
--home /home/app \
--shell /bin/ash \
--ingroup app \
--disabled-password \
app \
&& addgroup app app

USER 1000
WORKDIR /home/app

ENTRYPOINT ["/usr/bin/kubed"]

K8s controller

В mc-mgmt кластере так же работает обычный интанс kubed-а, установленный helm чартом, из него мы и берем все необходимые k8s RBAC-и.

danger

Этот способ деструктивен, неверная конфигурация kubed-master может реверсировать синхронизацию секретов между namespace-ами. Рекомендация держать специальный кластер для kubed-master

---
apiVersion: v1
kind: ConfigMap
metadata:
name: kubed-master-aws
namespace: kube-system
data:
credentials: |-
[mc-mgmt]
role_arn = arn:aws:iam::<mc-mgmt_id>:role/kubed-master
web_identity_token_file = /var/run/secrets/eks.amazonaws.com/serviceaccount/token
[mc-project]
role_arn = arn:aws:iam::<mc-project_id>:role/kubed-follower
source_profile = mc-mgmt
role_session_name = mc-project
generate-kubeconfig.sh: |-
#!/bin/bash
set -eux

aws eks update-kubeconfig --name mc-project-k8s --alias mc-project-k8s --profile mc-project

# NOTE: mc-mgmt-k8s should the last due to current-context
aws eks update-kubeconfig --name mc-mgmt-k8s --alias mc-mgmt-k8s --profile mc-mgmt

Синхронизация конфигураций

---

apiVersion: v1
kind: ConfigMap
metadata:
name: cross-acc-sync-demo
namespace: prod
annotations:
kubed.appscode.com/sync-contexts: "mc-project-k8s"
data:
foo: bar
spam: eggs

Нюансы работы

info

конфигурация: это ConfigMap, Secret

  • Синхронизация возможно только из namespace-а указанного во флагах контроллера в namespace с таким же названием в follower кластерах. При это annotations и labels на конфигурациях в follower кластерах не сохраняется.
  • Поводом для синхронизации конфигураций является: перезапуск pod-а контроллера, обновление .data конфигурации. Т.е. если конфигурация будет удалена в follower кластере, она не синхронизуется автоматом.
  • Удаление конфигурации в master аккаунте, удалит конфигурацию во всех follower-ах.
  • В случае, если в follower кластере есть свой kubed для синхронизации между namespace-ами, то можно добавить annotation-ию вручную и конфигурация разбежится по namespace-ам. Причем обновление .data в master кластере синхронизирует секрет в follower, но не перетрет эту аннотацию.

Добавляем аннотацию в follower кластере

kubectl --context mc-project annotate cm cross-acc-sync-demo "kubed.appscode.com/sync=sync/kubed-master=true"

Добавляем label на другой namespace в follower кластере, чтобы местный kubed засинхронизировал cm между namespace-ами.

---

kind: Namespace
apiVersion: v1
metadata:
name: env-ahorbach
labels:
name: env-ahorbach
sync/kubed-master: "true"

Ссылки

· 2 min read

Предыстория

Когда я только знакомился с AWS по youtube плейлисту, я смастерил VPC в двух AZ с несколькими подсетями. Один из типов подсетей был private - с nat-gateway, в курсах забыли сказать, что они не входят во фритир. За пару дней за 2 гейта накапало около $6. Было обидно, я поставил биллинг аларм.

#!NOTE

Тот самый курс от Курс ADV-IT

История

Совсем недавно я учился (на котиках) созданию артефактов с помощью packer. После тренировки в AWS я со спокойной душой в console нужного региона убил все AMI и пошел дальше.

Неделю спустя в почте заметил очередное письмо от AWS (мне иногда на личный gmail аккаунт приходят от них billing репорты, всегда пустые, и приглашения не re:invent).

alert

Увидел что я потратил 85% "фри-тирного" места под снэпшоты ebs дисков.

info

AWS Free Tier - тут можно прочитать сколько вам в месяц выделяется того или иного ресурса бесплатно в рамках фри-тира.

Ага - из-за негодяя packer-а помимо AMI-шек создаются еще и такие сущности.

snapshots

Мораль
  • пермым делом во фри-тире сделайте не рутового пользователя, вторым настройте биллинг алерты (я бы поставил трешхолд на 50% - в моем случае бюджет таял быстро).
  • Авторам видео / гайдлайнов, конечно, стоило бы указывать, что это не входит во фри-тир - или входит, но слабые лимиты.