Slide 1

Slide 1 text

Cloud Superpowers with F# Mikhail Shilkov

Slide 2

Slide 2 text

About me • Mikhail Shilkov • Software engineer at Pulumi .NET SDK, Azure, Core platform • Serverless • Functional programming, F# • Microsoft Azure MVP @MikhailShilkov [email protected]

Slide 3

Slide 3 text

Intro ● Pulumi: Modern Infrastructure as Code ● F# to manage cloud resources Cloud Superpowers ● Provisioning ● Architecture ● Testing ● Delivery Agenda

Slide 4

Slide 4 text

General-purpose Programming Languages

Slide 5

Slide 5 text

F#!

Slide 6

Slide 6 text

Providers ● AWS ● Azure ● GCP ● Digital Ocean ● Cloudflare … and more ● Docker ● Kubernetes ● OpenStack ● PostgreSQL ● New Relic

Slide 7

Slide 7 text

Static Website on AWS Demo 3

Slide 8

Slide 8 text

Provisioning with Desired State Configuration 8

Slide 9

Slide 9 text

Desired State Configuration Target Current Tool

Slide 10

Slide 10 text

Managing Resource Graphs Target Current Tool

Slide 11

Slide 11 text

Tools that you love ● .NET Core 3.1 ● OS: Windows, macOS, Linux ● Editor and IDE: Visual Studio, Code, Rider ● IntelliSense, ReSharper, StyleCop, DocFX ● Package Manager: Paket, NuGet, MyGet ● NUnit, xUnit.net, Moq, FsUnit, FsCheck

Slide 12

Slide 12 text

let resourceGroup = ResourceGroup "rg" let storageAccount = Account("storage", AccountArgs (ResourceGroupName = io resourceGroup.Name, AccountReplicationType = input "LRS", AccountTier = input "Standard")) F# Example

Slide 13

Slide 13 text

Desired State! let resourceGroup = ResourceGroup "rg" let storageAccount = Account("storage", AccountArgs (ResourceGroupName = io resourceGroup.Name, AccountReplicationType = input "LRS", AccountTier = input "Standard"))

Slide 14

Slide 14 text

How Pulumi Works CLI & engine Last deployed state Program.fs Language host AWS Azure GCP Kubernetes new Resource() CRUD

Slide 15

Slide 15 text

let resourceGroup = ResourceGroup "rg" let storageAccount = Account("storage", AccountArgs (ResourceGroupName = io resourceGroup.Name, AccountReplicationType = input "LRS", AccountTier = input "Standard")) Dependency Definitions

Slide 16

Slide 16 text

Architecture Reusable Abstractions 12

Slide 17

Slide 17 text

Resources to Provision an Azure Function Blob App Plan Container Storage Account Function App

Slide 18

Slide 18 text

// A resource group to contain our Azure Functions let resourceGroup = ResourceGroup "functions-rg" // A .NET Azure Function let dotnet = ArchiveFunctionApp("http", ArchiveFunctionAppArgs (ResourceGroup = resourceGroup, Archive = new FileArchive("./dotnet/publish"))) .NET Azure Function

Slide 19

Slide 19 text

Let’s run pulumi up … Type Name Plan + pulumi:pulumi:Stack functions-dev create + ├─ azure:appservice:ArchiveFunctionApp http create + │ ├─ azure:storage:Account http create + │ ├─ azure:appservice:Plan http create + │ ├─ azure:storage:Container http create + │ ├─ azure:storage:ZipBlob http create + │ └─ azure:appservice:FunctionApp http create + └─ azure:core:ResourceGroup rg create

Slide 20

Slide 20 text

// A resource group to contain our Azure Functions let resourceGroup = ResourceGroup "functions-rg" // A .NET Azure Function let dotnet = ArchiveFunctionApp("http", ArchiveFunctionAppArgs (ResourceGroup = resourceGroup, Archive = new FileArchive("./ javascript ") Runtime = "node")) Node.js Azure Function

Slide 21

Slide 21 text

let linuxResourceGroup = ResourceGroup "linux-rg" let linuxPlan = Plan("linux-asp", PlanArgs (ResourceGroupName = io linuxResourceGroup.Name, Kind = input "Linux", Reserved = input true)) let python = ArchiveFunctionApp(...); Python Azure Function on Linux

Slide 22

Slide 22 text

let linuxResourceGroup = ResourceGroup "linux-rg" let linuxPlan = Plan("linux-asp", PlanArgs ( ... )) let python = ArchiveFunctionApp("py", ArchiveFunctionAppArgs (ResourceGroup = linuxResourceGroup, Archive = new FileArchive("./python"), Plan = linuxPlan, Runtime = "python")) Python Azure Function on Linux

Slide 23

Slide 23 text

Testing Validate infrastructure definition 15

Slide 24

Slide 24 text

[] member this.ResourceGroupHasEnvironmentTag() = let resources = Deployment.TestAsync() |> runSync let resourceGroup = resources.OfType() |> Seq.head let tags = getValue resourceGroup.Tags tags.Should().NotBeNull("Tags must be defined") |> ignore tags.Should().ContainKey("Environment", null) |> ignore Unit Testing

Slide 25

Slide 25 text

[] member this.ResourceGroupHasEnvironmentTag() = let resources = Deployment.TestAsync() |> runSync let resourceGroup = resources.OfType() |> Seq.head let tags = getValue resourceGroup.Tags tags.Should().NotBeNull("Tags must be defined") |> ignore tags.Should().ContainKey("Environment", null) |> ignore Unit Testing

Slide 26

Slide 26 text

[] member this.ResourceGroupHasEnvironmentTag() = let resources = Deployment.TestAsync() |> runSync let resourceGroup = resources.OfType() |> Seq.head let tags = getValue resourceGroup.Tags tags.Should().NotBeNull("Tags must be defined") |> ignore tags.Should().ContainKey("Environment", null) |> ignore Unit Testing

Slide 27

Slide 27 text

https://mikhail.io/2020/05/unit-testing-cloud-deployments-with-pulumi-in-fsharp/

Slide 28

Slide 28 text

Delivery Multi-cloud cross-stack automation 17

Slide 29

Slide 29 text

Deployment process Allow developers to iterate quickly on dev environments. Gain visibility and change management with Continuous Delivery.

Slide 30

Slide 30 text

Cloud Transition Kubernetes Azure Functions AWS S3 Azure Analytics Google ML MySQL DataDog App Docker DataDog New Relic App MySQL EARLY CLOUD Mostly Static N-Tier Apps VMs Private Cloud CURRENT CLOUD Partly Dynamic Less Monolithic VMs and Containers* Hybrid - Public/Private *Experimentation FUTURE CLOUD Fully Dynamic Hyper-Connected Services Containers and Serverless Mostly Public Cloud

Slide 31

Slide 31 text

Infrastructure Landscape Foundation Security IAM KMS Networking VPC Subnets Firewalls Load Balancing DNS Compute VMs Containers Clusters Registries APM Monitoring Logging Alerting Serverless Functions API Gateways Data Object Stores Databases SQL NoSQL MQ Queues Pub/Sub Applications Images Container Images Code Packaging CI/CD

Slide 32

Slide 32 text

Example: Kubernetes Managed Kubernetes cluster Infrastructure Resources (networking, storage, identity) Managed Service Managed Service Application Application Application

Slide 33

Slide 33 text

Conclusions 20

Slide 34

Slide 34 text

PROVISIONING Developer-friendly Familiar language experience, toolchain, packages – applied to cloud infrastructure. Developers and operators working in a team. Cloud Engineering Transformed TESTING Confidence and quality Unit testing and TDD with battle-tested tools to ensure correctness. Policy as Code for compliance, cost control, and company-wide best practices. ARCHITECTURE Logic and abstractions Conditionals, loops, functions, classes, and packages out of the box. Reusable components that encapsulate complex logic and provider the right level of abstraction. Modern Infrastructure as Code Capabilities to ship faster and with confidence

Slide 35

Slide 35 text

Useful Links http://bit.ly/pulumilinks

Slide 36

Slide 36 text

Q&A Twitter: @MikhailShilkov Email: [email protected]