the ugly organization - we write ugly code

desu

the ugly organization

WE

  • write ugly code to solve one problem
  • embrace the ugly odyssey
  • are truth

TRUTH NOT LIES

  • ugly simplicity not beautiful complexity
  • ugly replaceable not beautiful reusable
  • ugly gardeners not beautiful architects

Find us here: dqk5k2hnalqa1.cloudfront.net

objectives of the diary

  • focus on software engineering more than code and tooling specifics
  • a product that works

product

  • first mvp
    • our product will be a frontend, a link aggregator for /dev blog posts or resources
    • we will have a thread in /dev that we will scrap every hour to refresh our aggregator
    • we will make use of Mediavida user system and voting system to start
    • our frontend will just scrap the content and show it in a ranking in a pretty way
  • future ideas
    • add "users and voting capabilities with other mechanisms" so we do not depend on /dev only
    • add features like automatic tagging for the content
    • add feature to summarise content of the links and show a preview in our aggregator
    • add feature to filter by tags, filter by time of contribution...
    • add a search or custom chat bot to our aggregator, we could ask the question "what is a pointer?" and get relevant links
    • improve TROLLING / SPAM detection mechanisms
    • ... see how all of this are backend powered ideas

code

All code available under: https://github.com/uglyorganization/

  • aws: terraform to manage aws infrastructure.
  • backend: golang backend.
  • frontend: frontend, html and javascript.
  • cron: this cron-content-generator, as the name suggest generates content for our frontend, this method keeps all our code static.

context

in order to make engineering decisions we need a context, this context will evolve every iteration and is open to suggestions.

Initial context:

  • assume we are an early startup, 5 employees.
  • assume we have one end-user facing product, mobile, front-end.
  • assume we have \~100s daily users and growing.
  • assume we have an initial capital or a small equity private round to survive 1 year.
  • assume we use https://aws.amazon.com/startups or similar. we decided to use aws.

We will simulate events like:

  • What happens if we have an incident? How do we troubleshoot and fix the issue?
  • What happens if we receive traffic bursts?
  • How do we monetise? Assume an initial MMR and stakeholders feedback (you).
8
desu

day 1:

resultados
problemas que me he encontrado
notas
1 respuesta
B

This is a spanish forum bro... go home!

1 respuesta
crb2222

Pero tu no vivias en China? Porque se te han configurado los buckets en EUWest

7
desu

#3 quiero tener #1 en ingles. porque me gusta como se lee el manifesto del "código feo". todos lo demas en español. y en el futuro lo quiero re-utilizar.

Sobre el diario en si, la duración sera de 1 mes con update diarios.

Por mi parte hablare poco ademas de esto. Que quien quiera pregunte o se discutid entre vosotros libremente, si algo es relevante lo tocare en código y en el siguiente update relevante. Si me gusta una idea o un fix la implementare sin problema. PR y CR bien recibidos.

Seguimos mañana.

1 respuesta
squ4r3

#5 veo que te gusta vivir peligrosamente

run: terraform apply -auto-approve -input=false

has pensado en ejecutar un plan en cada PR a main para evitar YOLOear cambios a infra?

Normalmente yo hago plan en pr, apply en pr, y después del apply es cuando se mergea a main. Porque el hecho de que el plan funcione no significa que el apply vaya a funcionar. Hay herramientas como Atlantis que facilitan esto.

también movería la ID de tu cuenta de AWS a una env var al menos , para evitar information disclosure si el repo va a ser público.

no conocía lo del random_id de terraform, me la apunto

1 respuesta
JuAn4k4

Terraform es una mierda (Horrorform lo llaman), usa Pulumi y así tienes todo en go.

Espero que estes usando assume role para ejecutarlo y no vayas con los root credentials por ahí pululando, que se te cuelan por algún lado y te soplan KK€ enseguida minando bitcoins

1 respuesta
desu

Resumen del día 2:

spoiler

Cuestiones destacadas:

spoiler

2
K

Pues con TF empieza regular la cosa. Todo en un solo fichero, sin separación por directorios y sin módulos

En cuanto crezca un poco más se hace inmantenible

1 2 respuestas
JuAn4k4

#9 Es ugly org, no has leído el manifiesto ? Si no hace falta modulo, no hace falta.

1
desu

Resumen del día 3:

spoiler

Cuestiones destacadas:

spoiler

PS: chatgpt para spelling


Para terminar agradecer a todos los que seguis el hilo, mucha gente me pregunta, ayuda y sugiere ideas por privado tambien.

desu

Resumen del día 4:

spoiler
GaN2

#2

al tener terraform el estado, no puedes borrar las cosas a mano, asi que he creado una acción en GitHub para destruir recursos

Entonces para usáis TF si la gestión de estados os la pasáis por el forro de los cojones? Para eso no uséis TF por amor de Dios, luego que si sobre ingeniería…

2 1 respuesta
desu

Resumen del día 5:

spoiler

cuestiones variopintas

spoiler
1 respuesta
desu

update

he pillado a mitchellangelo creador de terraform y demas q tambien lleva un tiempo que no caga con nix y me ha dicho que soy un fpero sin remedio. le he tenido que poner en su sitio. (me han echado del discord).

dicho esto, os comparto el planning para este finde y la semana que viene, va cargadito. Nuevo repo y nueva infrastructura que tenemos que montar. Creo que este sera interesante de seguir ya que literalmente vamos a hacer solo ugly code para montar todo, nada de logica de producto/negocio jaja.

Le he pedido a ChatGPT que me haga un resumen para vosotros.

spoiler

Todo esto con su role y su policy minima con AssumeRoleWithWebIdentity para github y cada repo. No se si esto es la manera mas correcta y segura la verdad. Para cada repositorio, un rol y una policy para desplegar con ssh a una o multiples instancias ec2 de ese servicio.

Los objetivos son:

  • tener HTTPS en nuestros servicios
  • tener el devops requerido para montar todo de manera segura

Futuros problemas:

  • tener HTTPS en multi entornos dev/pre/pro, como testear en local...
  • tener devops para multi entornos dev/pre/pro, escalar o reducir instancias
K

Lo del rol por repo es así, lo que entiendo que la policy que ha de tener es para que pueda modificar la infra en AWS. Para hacer un ssh no necesita ningún tipo de policy ya que no hace una llamada a la API de AWS.

Por otro lado, entiendo que la instancia en cuestión ha de tener una IP pública o DNS name público, sino, la GitHub Action no podrá conectar

1 respuesta
squ4r3

lo suyo es conectarte usando SSM y dejar que AWS haga su magia, así no tienes que tener ip pública ni escuchar en el 22

https://github.com/marketplace/actions/aws-ssm-send-command

1 respuesta
K

#17 joder, cierto. Cómo hace poco que lo descubrí, me olvido siempre de tirar SSM que diría que todas las AMIs Amazon Linux lo traen incorporado

1
desu
#16kokre:

lo que entiendo que la policía que ha de tener es para que pueda modificar la infra en AWS.

  • Tenemos un rol en AWS llamado github-aws que tiene permisos para tocar la infra en el repo de aws
  • Este tiene una policy attached para los permisos.
  • Este al igual que todos los otros roles, lo puedes ver en terraform, usa AssumeRoleWithWebIdentity para que solo se pueda ejecutar desde github actions.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Federated": "arn:aws:iam::${var.AWS_ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com"
                },
                "Action": "sts:AssumeRoleWithWebIdentity",
                "Condition": {
                    "StringEquals": {
                        "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                    },
                    "StringLike": {
                        "token.actions.githubusercontent.com:sub": "repo:uglyorganization/aws:*"
                    }
                }
            }
        ]
    }
    

Así para cada repositorio en nuestro github que interactúa con nuestra cuenta AWS_ACCOUNT_ID, tenemos el AssumeRoleWithWebIdentity en el rol para es repositorio concreto, y ademas una policy única. 1 rol = 1 repo = 1 policy.

La convencion que sigo es github-REPOSITORY_NAME.

#16kokre:

Para hacer un ssh no necesita ningún tipo de policy ya que no hace una llamada a la API de AWS.

No entiendo a que te refieres. Para el ssh necesitamos una policy con la accion ssm:StartSession. Seria algo asi, aun no lo he hecho:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:DescribeInstances",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "ssm:StartSession",
      "Resource": "arn:aws:ec2:region:account-id:instance/instance-id",
      "Condition": {
        "StringEquals": {
          "ssm:resourceTag/Name": "YourEC2TagName"
        }
      }
    }
  ]

No se si esta completa esta policy statement, es un ejemplo que tengo preparado para manana.

#16kokre:

Por otro lado, entiendo que la instancia en cuestión ha de tener una IP pública o DNS name público, sino, la GitHub Action no podrá conectar

No hace falta, para exponer el servicio el DNS voy a usar el publico del ELB para montar el certificado SSL y tener HTTPS. La alternativa y recomendacion seria tener un dominio propio, pero de momento no pago nada.

Para la action es lo que explico arriba de todo.

K

Nah, ni caso. No recordaba el servicio SSM. Viejos vicios de cuando no existía esa opción

desu

no worries, todo comentario bien recibido, y si alguien quiere comentar como se hacia en el pasado es un gran punto de vista comparar ambas opciones.

porque estamos con aws y github que todo se integra fácil, pero saber como hacerlo de otras maneras nos sirve para montar cosas in-house, u otros proveedores...

la suciedad mas importante que tenemos que hacer primero es:

  • (done) seguridad entre componentes con oauth, roles, policies, y similares...
  • (wip) encriptacion con https, certificados, rotacion de certificados
  • logs
  • metricas
  • alarmas
  • (done) ci y cd (wip)

Todo esto son requerimientos mínimos antes de picar una sola linea de negocio que sirva para algo. Y y después vendrían encima los problemas operacionales típicos:

  • versionado de productos, rollbacks y despliegues a versiones concretas
  • multi entorno, sportar dev/pre/pro
  • escalado vertical y horizontal de recursos (i.e cambiar instancias, incrementar o disminuir instancias de un servicio)
  • cambiar recursos (i.e quiero cambiar una dynamodb por un s3, quiero cambiar la distribution de mi frontend)
  • transformación de la arquitectura (i.e quiero anadir una cache delante de mi dynamodb o quiero quitarla)

todo lo operacional de segundo nivel, debe funcionar con los requisitos de primer nivel y tenemos que tener garantizar 0 downtime de nuestros servicios.

no se si me he dejado algún requerimiento mínimo de desarrollo o producción.

1 respuesta
JuAn4k4

#21 ¿ Lo quieres hacer todo gratis ?

1 respuesta
desu

Resumen del día 6:

  • tengo este repo para nuestro nuevo producto que ya explicare en que consistira: https://github.com/uglyorganization/backend-lxd
  • ando haciendo toda la infra y workflows que comente en #15
  • en el resumen de #15 veo que chatGPT se dejo de comentar el VPC y los grupos de instancias, pero bueno, se entiende.
  • primer paso tener el package https://github.com/uglyorganization/backend-lxd/pkgs/container/backend-lxd
  • cada vez que mergeo a main se crea un tag, este tag se publica, cuando se publica el tag otra action crea el package con el container
  • mi aws no tiene submodulos, pero si he creado ficheritos jaja menuda ostia de realidad el networking de aws, vpcs, nat, azs... pff a ver que monto

cuestiones

#22 no es ese el objetivo. tenemos dos grupos de ideas principales de exploración:

primero ingenieria en diversos escenarios:

  • tengo unos números hechos comparando fargate/api gateway/elb+ec2 y como evolucionan en distintos casos.
  • ahora estoy haciendo la solución barata, barata en dinero, pero cara en recursos humanos.
  • en que casos es mejor usar un producto u otro? en que tipos de empresas? para que tipos de productos?
  • si tu producto es un frontend y captar usuarios pues paga un api gateway y desarrolla features.
  • diria que para la gran mayoria de productos que quieras hacer, el primer anyo o segundo de vida te compensa no mirar el dinero y solo centrarte en ganar dinero y usuarios.
  • pero a la que la empresa ya esta establecida, ahi es donde empieza a importar la optimizacion de recursos.

luego juegamos con los principios fundamentales de código sucio y la jardinería obtenemos:

  • tenia un repo "frontend", lo cambie a otro repo "fronten-dev" porque tardaba menos en tirarlo que en adaptarlo
  • preferencia por el código estático, compilado, generado > codigo runtime, javascript, usar apis
    • por ejemplo: frontends ligeros y estáticos que se generan, podríamos tener 1 frontend dedicado a 1 usuario todo estatico y seria gratis y rapido
    • podemos ir a mas, usando github runners como lambdas, proxies, api gateways "gratis" de orquestracion, tenemos 2000 minutos gratis al mes de CPU, solo con github runners puedes montar una empresa que sirva frontends y tenga backends en cron jobs. hasta tienes github pages para el frontend.

aquí juego mucho con la idea de, para que voy a tener una api para hacer cruds? si puedo llamar de un repo a otro directamente y cambiar los datos en build time? jaja

1 respuesta
JuAn4k4

#23 Eso lo hizo uno con su web de vender coches (miniaturas), tenia una spreadsheet con los coches que podía vender y tal, y en un cronjob generaba la web en HTML estático. El actualizaba el google sheets los coches que le iban llegando y los enviaba. Cumplí con ugly organization.

1 respuesta
desu

#24 La realidad es que para la gran mayoría de frontends de consultar datos... es la mejor opción.

ranteo random
desu

Hago update, me he peleado bastante con el networking de AWS, no tengo ni puta idea de nada de lo que hago. Creo que estoy cerca pero no veo el fallo. Este finde le dare una vueltecita, a ver si alguien me echa un cable si ve el error.

En teoria esta todo montado, y tenemos una pipeline que mediante SSM nos va a desplegar nuestro "backend-lxd" a instancias de ec2. No me va.

An error occurred (AccessDeniedException) when calling the SendCommand operation: User: arn:aws:sts::***:assumed-role/github-backend-lxd/GitHubActions is not authorized to perform: ssm:SendCommand on resource: arn:aws:ssm:eu-west-1::document/AWS-RunShellScript because no identity-based policy allows the ssm:SendCommand action
Error: Process completed with exit code 254.

Me falla algun permiso pero no lo veo.

Estos son todos nuestros recursos en AWS gestionados con terraform (terraform list), relacionados:

spoiler

no lo veo, voy a quizas sacar que mi rol solo pueda modificar las instancias de backend-lxd... he visto en un coment que daba error a otra gente, pero no entiendo xq deberia ser el motivo. creo que me falta alguna cosa sobre el ssm pero no lo veo.

desu

he estado 4 horas para esto:

aun no me funciona porque no me encuentra las instancias pero ya no dice que no tengo el permiso...

madre mia, quien entienda esto jajaja

no es lo mismo tener todo en 1 statement que en 2 statements, entiendoque por el condition... pero tio... vaya puto error de mierda me ha devuelto AWS macho. voy a crearles una issue en github para que lo arreglen.

desu

transparencia empresarial.

la factura de esta semana:


de donde viene el coste?
https://repost.aws/articles/ARknH_OR0cTvqoTfJrVGaB8A/why-am-i-seeing-charges-for-public-ipv4-addresses-when-i-am-under-the-aws-free-tier#

asi que tenemos un coste 0,120 euros al dia, * 30 dias, 3,6 euros al mes por tener una ip publica.

y ya que comparto cosas la infra que hemos montado:

3 zonas en europa, publicas y privadas, decide hacerlas chicas. para cada zona que soporta nuestra region.

una public routing table para exponer nuestro trafico de las subnets publicas a la internet gateway (IGW)


troubleshooteando launc_template y el ssm
desu

Segundo sprint dia 1:

  • Primero disculpas que no haya podido terminar bien el primero, montar la network en AWS me ocupo mas de un día, cambio de prioridades.

  • Aquí es como lo tenemos, como nos gustaría tenerlo

    • frontends con cdn y s3 todo automatizado, https y todo bien ok
    • arquitectura con alb, security group, lb targets, ec2 etc
      • falto el deploy automático de github (lo hice a mano xd),
      • https y
      • me falto meter una db en la red privada
  • No tengo HTTPS aunque sea un must, porque me centre en las operaciones de deployear todo automatico y terraform.

  • Se podria haber hecho en paralelo si no lo hiciese solo :(

  • La DB pues es menos prioritaria que el HTTPS.


  • antes de terminar la segunda arquitectura, voy a montarla igual pero usando https://aws.amazon.com/es/api-gateway/
    • para cosas publicas API Gateway es interesante
  • otra alternativa que me han sugerido, seria una opción intermedia con Fargate: https://aws.amazon.com/es/fargate/
    • fargate para cosas privadas puede ser interesante, si vas a usar Fargate para exponer cosas como sugirieron no lo veo, mejor API Gateway que te lo hace todo, o hacerlo tu a mano como en la arquitectura anterior

Es una decision un poco a ojimetro, viendo los costes bases. Sin carga de trabajo real y peticiones y consumo de bandwith real no se puede hacer estimaciones buenas.

Lo que hago es para cada uno de mis escenarios suponer un numero de peticiones y usuarios:
https://blogs.perficient.com/2021/06/17/aws-cost-analysis-comparing-lambda-ec2-fargate/

En esta comparación de 2021, podéis ver que no es todo lineal y cristalino.

Y por lo que hacen los "costes operacionales" de mantener, desarrollar escalar y tal:

  • ec2 son los mas caros al gestionar todo a mano.
  • lambda mayor coste de desarrollo y acoplamiento al ser serverless.
  • fargate es el intermedio que quita costes de operacion de ec2 sin tener que tocar codigo.

Según el análisis de arriba: lambda > fargate > ec2
Según si necesitas 1/4 de 24h, 1/2 de 24h o 24h de cpu al día.
Pero, no tenemos en cuenta el coste operacional en esos costes, que este es el difícil de calcular.

1 respuesta
aren-pulid0

#29 no expongas tus instancias a internet, si vas a usar ALB mete tus instancias a una private subnet, en caso de que necesites que tengan acceso a internet lee acerca de NAT Gateways

1 respuesta