Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem

36 views

Published on

You must have noticed how Docker and containers is playing a more and more important part in .NET development. Docker support is everywhere, so it should be easy to build solutions based on container technology, right? But, it takes a bit more to architect and create a .NET solution that use Docker at its core. Many questions arise: How do you design a solution architecture that fits well with containers? Would I use .NET or .NET Core? What is a proper way to migrate to such an architecture? What changes in the .NET implementation from pre-Docker solutions with micro-services? Where do container orchestrators fit in and how do I build and deploy my solutions on a Docker container cluster, such as Azure Kubernetes Service?
These and many other questions will be answered in this session. You will learn how to design and architect your .NET solutions and get a flying start to create, build and run Docker-based containerized applications.

Published in: Education
  • Be the first to comment

  • Be the first to like this

.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem

  1. 1. ARCHITECTING .NET SOLUTIONS IN A DOCKER ECOSYSTEM ALEX THISSEN
  2. 2. 3 Agenda A story on creating .NET applications using container technology Featuring Docker and Visual Studio With highlights and some emphasis on .NET Core
  3. 3. 4 Task: Fit your application into a container
  4. 4. 5 Making progress. It will fit. It must…
  5. 5. 6 There I fixed it!
  6. 6. 7 Building and running .NET applications
  7. 7. 8 Running containers on Linux
  8. 8. 9 Containers on Windows Better isolation from hypervisor virtualization Container management Docker Engine Compute
  9. 9. 10 Docker and containers Standardized tooling Adopted for standalone and cluster scenarios
  10. 10. 11 Changes when switching to containers Environments Configuration Security Networking Storage Composition Lifecycle Hosting Monitoring
  11. 11. 12 Application architecture less relevant Featuring your favorite patterns Microservices or Monolith
  12. 12. 13 Container application lifecycle
  13. 13. 14 Web APIWeb API containercontainer Leaderboard Microservice Identity Microservice ASP.NET Core Web App Client applications (browser) Web Page Games reporting high-scores
  14. 14. 15 Container workflow and lifecycle Inner loop Run Code Validate Outer loop
  15. 15. 16 Deploying .NET apps with containers
  16. 16. 17 VS2019 container building Multi-stage Dockerfile per project Can be built without VS2019 FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base WORKDIR /app EXPOSE 13995 EXPOSE 44369 … FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "Leaderboard.WebAPI.dll"]
  17. 17. 18 mcr.microsoft.com/windows/servercore:1903 -or- debian:buster-slimdebian:buster-slim Docker image layers .NET Core mcr.microsoft.com/dotnet/core/runtime:3.0 mcr.microsoft.com/dotnet/core/runtime-deps mcr.microsoft.com/dotnet/core/aspnet:3.0 Your application layer: e.g. alexthissen/gamingwebapp:latest
  18. 18. 19 Container image registries Push and store your images to centralized location Each image is in its own repository
  19. 19. 20 Build pipeline in Azure DevOps Contains steps to: Docker images need to be created on correct host OS Produce artifacts to be used during deployment
  20. 20. 21 Release pipelines in Azure DevOps Create deployment file to apply on cluster Elaborate scenarios involve multiple environments
  21. 21. Demo: Lifecycle A new development lifecycle for Docker based solutions Visual Studio 2019 Azure DevOps
  22. 22. 23 From single-node host to multi-node clusters
  23. 23. 24 Hosting using cluster orchestrators Cluster FabricHigh Availability Hyper-Scale Hybrid Operations High Density Rolling Upgrades Stateful services Low Latency Fast startup & shutdown Container Orchestration & lifecycle management Replication & Failover Simple programming models Load balancing Self-healingData Partitioning Automated Rollback Health Monitoring Placement Constraints Microservices Mesos DC/OS Docker Swarm Google Kubernetes Azure Service Fabric Largely cloud provider-agnostic
  24. 24. 25 Many more Azure options for hosting
  25. 25. Composing applications
  26. 26. 27 Container cluster Examples of external resources Solution composed of multiple containers Different compositions per environment Web Frontend Web API Composing .NET solutions Backend service
  27. 27. 28 Container cluster Redis cache External resources Web Frontend Web API Backend service SQL Server on Linux RabbitMQ Maximize isolation in development and testing
  28. 28. 29 Composing container solutions Docker-compose: “Orchestration tool for container automation” Single command: docker-compose YAML files describe composition
  29. 29. 30 services: service-name: docker-image how to build other services key/value pairs port mappings networks: network-name: volumes: volume-name:
  30. 30. 31 Web API Web App SQL Server on Linux
  31. 31. 32 Composing docker-compose files Order of files matters: last one wins docker-compose -f "docker-compose.yml" -f "docker-compose.override.yml" -p composition up -d
  32. 32. 33 Changing environments
  33. 33. 34 Environment: e.g. developer laptop, staging or production cluster Environments everywhere Container images are immutable Environments are not same docker run –it –-env key=value alexthissen/gamingwebapp Container image { "ConnectionString": "Server=tcp:…", "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Warning" } } } appsettings.json
  34. 34. 35 Working with environments in .NET Core Bootstrapping environment variables public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } ENV variablesSettings files
  35. 35. 36 Docker-compose file development.yml production.yml For .NET 4.7.1+ use similar strategy with new ConfigurationBuilders Environmental variables overrides Non-container development environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://0.0.0.0:1337 - ConnectionString=Server=sql.data;… environment: - ASPNETCORE_ENVIRONMENT=Production - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionString=DOCKERSECRETS_KEY { "ConnectionString": "Server=tcp:…", "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Warning" } } } appsettings.json
  36. 36. 37 Base compositions • Services • Images using registry names • Dependencies between services • Networks Composing for different environments Environmental overrides: • Port mappings • Endpoint configurations • Non-production services SQL Server on Linux Redis cache Azure SQL Database Azure Cache
  37. 37. 39 public class HomeController : Controller { private readonly IOptionsSnapshot<WebAppSettings> settings; // Inject snapshot of settings public HomeController(IOptionsSnapshot<WebAppSettings> settings) { this.settings = settings; } public void ConfigureServices(IServiceCollection services) { // Add framework services. services.Configure<WebAppSettings>(Configuration); services.AddMvc(); } public class WebAppSettings { public string BaseURL … public int MaxRetryCount … }
  38. 38. 40 Security and secrets
  39. 39. 41 Everything in Docker ecosystem is inspectable Secrets in configuration
  40. 40. 42 Configuration Dealing with secrets in configuration Where would you leave sensitive data? Production appsettings. development.json Cluster secrets docker- compose.debug.yml docker- compose.production.yml User Secrets Azure KeyVault appsettings. secrets.json Connection strings Passwords appsettings. secrets.json
  41. 41. 43 Managed by and distributed across cluster echo "azurekeysecret" | docker secret create azurekeyvault_secret – docker secret ls Specific to cluster orchestrator Other orchestrators have similar mechanisms e.g. kubectl create secret docker-compose.production.yml var builder = new ConfigurationBuilder() // ... .AddEnvironmentVariables() .AddDockerSecrets(); services: leaderboardwebapi: secrets: - azurekeyvault_secret secrets: azurekeyvault_secret: external: true
  42. 42. 44 Reading secrets from Azure Key Vault Available from IConfiguration in ASP.NET Core Key and secret names Connecting to KeyVault securely if (env.IsProduction()) { builder.AddAzureKeyVault( $"https://{Configuration["azurekeyvault_vault"]}.vault.azure.net/", Configuration["azurekeyvault_clientid"], Configuration["azurekeyvault_clientsecret"]); Configuration = builder.Build(); }
  43. 43. Demo: Secrets Creating and reading secrets in a Kubernetes cluster Mounting secret settings in volume Reading individual secrets Read from Azure KeyVault
  44. 44. Building resilient applications
  45. 45. 47 Resiliency: design for failure Determine your strategy for resiliency Focus on dependencies outside of your own container Cloud and containers: Transient errors are a fact, not a possibility
  46. 46. 48 Dealing with transient faults Containers will crash or be terminated External dependencies might not be available
  47. 47. 49 Built-in Retry mechanisms Most Azure services and client SDKs include retry mechanism Patterns and Practices TFH Application Block (.NET FX) Roll your own for container connectivity services.AddDbContext<LeaderboardContext>(options => { string connectionString = Configuration.GetConnectionString("LeaderboardContext"); options.UseSqlServer(connectionString, sqlOptions => { sqlOptions.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); });
  48. 48. 50 Fault handling policies Use policy configurations Centralize policies in registry Policy.Handle<HttpRequestException>().WaitAndRetryAsync( 6, // Number of retries retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, timeSpan, retryCount, context) => { // On retry logger.LogWarning( "Retry {Count} at {ExecutionKey} : {Exception}.", retryCount, context.ExecutionKey, exception); })
  49. 49. 51 Creating resilient HTTP clients with Polly Leverage HttpClientFactory Built-in Polly support
  50. 50. Demo: Resiliency Preparing for failures Typed Clients Polly support
  51. 51. 53 Other options: service meshes Provides several capabilities:
  52. 52. 54 Challenges for cluster hosted apps Keeping entire system running Determine state of entire system and intervene How to know health status of individual services? Collecting/correlating performance and health data Sentry.ioRaygun.io RunscopeNewRelic AlertSite DataDogAppMetrics Azure Monitor
  53. 53. 55 ASP.NET Core application /api/v1/… Middle ware Integrating health checks New in .NET Core 2.2 Bootstrap health checks in ASP.NET Core app services.AddHealthChecks(); endpoints.MapHealthChecks("/health); /health DefaultHealthCheckService Microsoft.Extensions.Diagnostics.HealthChecks .Abstractions .EntityFramework Microsoft.AspNetCore.Diagnostics.HealthChecks
  54. 54. 56 Integrating health checks services .AddHealthChecks() .AddCheck("sync", () => … ) .AddAsyncCheck("async", async () => … ) .AddCheck<SqlConnectionHealthCheck>("SQL") .AddCheck<UrlHealthCheck>("URL"); ASP.NET Core application /health DefaultHealthCheckService
  55. 55. 57 Probing containers to check for availability and health Readiness and liveness Kubernetes node Kubernetes node Kubernetes nodes Containers Readiness Liveliness
  56. 56. 58 Implementing readiness and liveliness 1. Add health checks with tags 2. Register multiple endpoints with filter using Options predicate /api/v1/… /health /health/ready /health/lively app.UseHealthChecks("/health/ready", new HealthCheckOptions() { Predicate = reg => reg.Tags.Contains("ready") }); services.AddHealthChecks() .AddCheck<CircuitBreakerHealthCheck>( "circuitbreakers", tags: new string[] { "ready" }); app.UseHealthChecks("/health/lively", new HealthCheckOptions() { Predicate = _ => true });
  57. 57. 59 Zero downtime deployments Original pods only taken offline after new healthy one is up Allows roll forward upgrades: Never roll back to previous version
  58. 58. 60 Networking
  59. 59. 61 Connecting containerized services
  60. 60. 62 Docker containers in same network are connected Drivers determine network type Docker networks Bridge network 172.17.0.0/16 Host IP 172.31.1.10
  61. 61. 63 Hosts may span across cloud providers Docker networks: overlay in Swarm Overlay network 10.0.0.0/24 Host IP 172.31.1.10 Host IP 192.168.2.13 docker_gwbridge 172.18.0.0/16 docker_gwbridge
  62. 62. 64 Exposing containers Port publishing Built-in DNS
  63. 63. 65 Composing networks By default single network is created Create user-defined networks for network isolation Backend network Frontend network Web API Web App SQL Server
  64. 64. 66 Backend network Frontend network Web API Web App SQL Server
  65. 65. 67 Gear your architecture to work with containers Environments Configuration Security Networking Storage Composition Lifecycle Hosting Monitoring
  66. 66. Thanks!
  67. 67. Resources https://dot.net/ https://www.visualstudio.com https://github.com/microsoft/dotnet https://xpirit.com/inspiration/#downloads

×