Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cloud Development Kits - Are we on the road to Infrastructure Nirvana?!

Cloud Development Kits - Are we on the road to Infrastructure Nirvana?!

What happens when you apply a software engineering mindset to infrastructure as code? With the rise of Cloud Development Kits, a new world is opening up. How do full-featured programming languages allow us to express the needs of our solutions? And how do you code these higher level abstractions?

It feels like we have yet to unlock the potential that CDKs bring us... what will it take to reach infrastructure Nirvana... can we ever declare our high-level non-functionals and let the infra code make it happen?!

Nico Krijnen

November 04, 2022
Tweet

More Decks by Nico Krijnen

Other Decks in Programming

Transcript

  1. Cloud Development Kits? CDKs? – Learn from Software Engineering! –

    Infrastructure Nirvana?! Are we on the road to infrastructure Nirvana?!
  2. CloudFormation Terraform Chef Puppet Ansible ARM Bicep resource elasticsearch_xpack_role my_product-all_env-read

    { role_name = "my_product-all_env-read" indices = { names = [ "logs-kubernetes.container_logs-my_product.uat", "metrics-*-my_product.uat", "traces-apm*-my_product.uat", "logs-apm*-my_product.uat", "logs-kubernetes.container_logs-my_product.pre", "metrics-*-my_product.pre", "traces-apm*-my_product.pre", "logs-apm*-my_product.pre", "logs-kubernetes.container_logs-my_product.prod", "metrics-*-my_product.prod", "traces-apm*-my_product.prod", "logs-apm*-my_product.prod" ] privileges = ["read", "view_index_metadata"] } applications = { application = "kibana-.kibana" privileges = ["space_all"] resources = ["space:my_product"] new XpackRole(scope, this.roleId, { roleName: this.roleId, indices: [ { names: [ ...this.indexPatterns(), ], privileges: ["read", "view_index_metadata"] }, ], applications: [ { application: "kibana-.kibana", privileges: ["space_all"], resources: [`space:${this.space}`] } ], }); TypeScript Python Go Java C#
  3. • Rich expressiveness • No more YAML ! • Rich

    tooling support • Rich language features
  4. • Rich expressiveness • No more YAML ! • Rich

    tooling support • Rich language features • Abstractions!
  5. What can we learn from Software Engineering? CDKs? – Learn

    from Software Engineering! – Infrastructure Nirvana?! Are we on the road to infrastructure Nirvana?!
  6. 10x more time reading “Indeed, the ratio of time spent

    reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. ... [Therefore,] making it easy to read makes it easier to write.” ― Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship
  7. Mark Seemann Code That Fits in Your Head No more

    than 7 (±2) https://youtu.be/FPEEiX5unWI
  8. terraform required_providers elasticsearch { source = "phillbaker/elasticsearch" version = "..."

    } provider = { elasticsearch = { url = "..." username = "..." } } resource elasticsearch_xpack_role my_product-all_env-read { applications = { application = "kibana-.kibana" privileges = ["space_all"] resources = ["space:my_product"] } indices = { names = [ "logs-kubernetes.container_logs-my_product.uat", "metrics-*-my_product.uat", "traces-apm*-my_product.uat", "logs-apm*-my_product.uat", "logs-kubernetes.container_logs-my_product.pre", "metrics-*-my_product.pre", "traces-apm*-my_product.pre", "logs-apm*-my_product.pre", "logs-kubernetes.container_logs-my_product.prod", "metrics-*-my_product.prod", "traces-apm*-my_product.prod", "logs-apm*-my_product.prod" ] privileges = ["read", "view_index_metadata"] } role_name = "my_product-all_env-read" } resource elasticsearch_xpack_role my_product-prod_env-read { applications = { application = "kibana-.kibana" privileges = ["space_all"] resources = ["space:my_product"] } indices = { names = [ "logs-kubernetes.container_logs-my_product.prod", "metrics-*-my_product.prod", "traces-apm*-my_product.prod", "logs-apm*-my_product.prod" ] privileges = ["read", "view_index_metadata"] } role_name = "my_product-prod_env-read" } resource elasticsearch_xpack_role_mapping my_product_support_team { role_mapping_name = "my_product_support_team" roles = ["my_product-prod_env-read"] rules = "{\"all\":[{\"field\":{\"realm.name\": \"azure_saml\"}},{\"field\":{\"groups\": \"af8c120a-547b-49df-9c4f-32320816666bb\"}}]}" } resource elasticsearch_xpack_role_mapping my_product_team { role_mapping_name = "my_product_team" roles = ["my_product-all_env-read"] rules = "{\"all\":[{\"field\":{\"realm.name\": \"azure_saml\"}},{\"any\":[{\"field\":{\"groups\": \"630d6107-8a7f-4632-932b-2ca201c639a8\"}},{\"field\":{\"groups\": \"d45fbb82-8759-423e-a889-f53b120bad65\"}}]}]}" }
  9. function grantAccessForProductTeams(scope: Construct) { const allEnvsRole = new EnvironmentRole(scope, ["my_product.uat",

    "my_product.pre", "my_product.prod"] ); const onlyProdRole = new EnvironmentRole(scope, ["my_product.prod"] ); allEnvsRole.grantAccessTo("my_product_team", azure_ad_groups.product.dev, azure_ad_groups.product.management, ); onlyProdRole.grantAccessTo("my_product_support_team", azure_ad_groups.product.support, ); }
  10. What can we learn from Software Engineering? CDKs? – Learn

    from Software Engineering! – Infrastructure Nirvana?! Are we on the road to infrastructure Nirvana?!
  11. What makes code easy to change? • Easy to read

    and understand intention • Version control
  12. What makes code easy to change? • Easy to read

    and understand intention • Version control • Automated tests
  13. What makes code easy to change? • Easy to read

    and understand intention • Version control • Automated tests Safety net }
  14. SOLID • Single-responsibility principle • Open–closed principle • Liskov substitution

    principle • Interface segregation principle • Dependency inversion principle Robert C. Martin – Uncle Bob
  15. CUPID – for joyful coding • Composable • Unix philosophy

    • Predictable • Idiomatic • Domain-based https://dannorth.net/2022/02/10/cupid-for-joyful-coding/ Daniel Terhorst-North
  16. CUPID – for joyful coding • Composable • Unix philosophy

    • Predictable • Idiomatic • Domain-based https://dannorth.net/2022/02/10/cupid-for-joyful-coding/ Daniel Terhorst-North
  17. CUPID – Composable Plays well with others • Small surface

    area • Intention-revealing • Minimal dependencies Daniel Terhorst-North
  18. CUPID – Unix philosophy Does one thing well • A

    simple, consistent model • Single purpose vs. single responsibility Daniel Terhorst-North
  19. CUPID – Predictable Does what you expect • Behaves as

    expected • Deterministic • Observable Daniel Terhorst-North
  20. CUPID – Predictable Does what you expect • Behaves as

    expected • Deterministic • Observable Daniel Terhorst-North
  21. CUPID – Domain-based The solution domain models the problem domain

    in language and structure • Domain-based language • Domain-based structure • Domain-based boundaries Daniel Terhorst-North
  22. CUPID – Domain-based The solution domain models the problem domain

    in language and structure • Domain-based language • Domain-based structure • Domain-based boundaries Daniel Terhorst-North I've seen way too many stacks with 700 lines of code instead of being split into domain driven constructs.
  23. CUPID – for joyful coding • Composable • Unix philosophy

    • Predictable • Idiomatic • Domain-based https://dannorth.net/2022/02/10/cupid-for-joyful-coding/ Daniel Terhorst-North
  24. CUPID – for joyful coding • Composable • Unix philosophy

    • Predictable • Idiomatic • Domain-based https://dannorth.net/2022/02/10/cupid-for-joyful-coding/ Daniel Terhorst-North
  25. Right level of abstraction? Code is not done until it

    is absolutely gorgeous (simple design rules): 1.Works 2.Communicates 3.No duplicates 4.Fewest methods & classes
  26. Common refactor recipes • Rename • Extract method & Inline

    method • Extract variable & Inline variable
  27. Infrastructure Nirvana?! CDKs? – Learn from Software Engineering! – Infrastructure

    Nirvana?! Are we on the road to infrastructure Nirvana?!
  28. Value of a software system? Features Value it brings to

    users Availability Performance Security
  29. Value of a software system? Features Value it brings to

    users Non-functional Functional Availability Performance Security
  30. Single-Page App [TypeScript, Svelte, CloudFront, S3] Backend API [Node, Hapi.js,

    AWS Fargate] SQL Database [AWS RDS Aurora] const productionApp = new ThreeTierApp(this, "productionApp" { redundancy: Redundancy.twoAvailabilityZones, autoScaling: true, backendLatencyAlertThreshold: Duration.ofSeconds(0.8), backendMemory: MemorySize.ofGB(4), databaseMemory: DatabaseMemorySize.ofGB(8), encryptionAtRest: true, });
  31. Single-Page App [TypeScript, Svelte, CloudFront, S3] Backend API [Node, Hapi.js,

    AWS Fargate] SQL Database [AWS RDS Aurora] const productionApp = new ThreeTierApp(this, "productionApp" { redundancy: Redundancy.twoAvailabilityZones, autoScaling: true, backendLatencyAlertThreshold: Duration.ofSeconds(0.8), backendMemory: MemorySize.ofGB(4), databaseMemory: DatabaseMemorySize.ofGB(8), encryptionAtRest: true, }); const stagingApp = new ThreeTierApp(this, "stagingApp" { redundancy: Redundancy.noRedundancy, autoScaling: false, backendMemory: MemorySize.ofGB(4), databaseMemory: DatabaseMemorySize.ofGB(4), encryptionAtRest: false, });
  32. Single-Page App [TypeScript, Svelte, CloudFront, S3] Backend API [Node, Hapi.js,

    AWS Fargate] SQL Database [AWS RDS Aurora] const productionApp = new ThreeTierApp(this, "productionApp" { redundancy: Redundancy.twoAvailabilityZones, autoScaling: true, backendLatencyAlertThreshold: Duration.ofSeconds(0.8), backendMemory: MemorySize.ofGB(4), databaseMemory: DatabaseMemorySize.ofGB(8), encryptionAtRest: true, }); const stagingApp = new ThreeTierApp(this, "stagingApp" { redundancy: Redundancy.noRedundancy, autoScaling: false, backendMemory: MemorySize.ofGB(4), databaseMemory: DatabaseMemorySize.ofGB(4), encryptionAtRest: false, }); export class ThreeTierApp extends cdk.Construct { constructor(scope: cdk.Construct, id: string, props: ThreeTierAppProps) { super(scope, id); ... } } export interface ThreeTierAppProps { redundancy: Redundancy; autoScaling: boolean; backendLatencyAlertThreshold?: Duration; backendMemory: MemorySize; databaseMemory: DatabaseMemorySize; encryptionAtRest: boolean; } export enum Redundancy { noRedundancy, twoDatacenters, twoRegions } export class MemorySize { private constructor(readonly sizeInGB: number) { if (this.sizeInGB < 0.5) throw new Error("Memory cannot be less than 512 MiB"); if (this.sizeInGB > 120) throw new Error("Memory cannot be more than 120 GB"); } static ofGB(sizeInGB: number): MemorySize { return new MemorySize(sizeInGB); } }