This commit is contained in:
Ryan Nowak 2020-03-14 23:23:07 -07:00
Родитель fd5679cd01
Коммит 0b1838207f
4 изменённых файлов: 256 добавлений и 86 удалений

Просмотреть файл

@ -2,48 +2,47 @@
This tutorial assumes that you have completed the [Frontend Backend Run Sample](frontend_backend_run.md)
Before we deploy, make sure you have the following installed on your machine.
> :bulb: `tye` will use your current credentials for pushing Docker images and accessing kubernetes clusters. If you have configured kubeclt with a context already, that's what `tye deploy` is going to use!
Before we deploy, make sure you have the following ready...
1. Installing [docker](https://docs.docker.com/install/) based on your operating system.
1. A container registry. Docker by default will create a container registry on [DockerHub](https://hub.docker.com/). You could also use [Azure Container Registry](https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-prepare-acr) or another container registry of your choice.
2. A container registry. Docker by default will create a container registry on [DockerHub](https://hub.docker.com/). You could also use [Azure Container Registry](https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-prepare-acr) or another container registry of your choice.
1. A Kubernetes Cluster. There are many different options here, including:
3. A Kubernetes Cluster. There are many different options here, including:
- [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-deploy-cluster)
- [Kubernetes in Docker Desktop](https://www.docker.com/blog/docker-windows-desktop-now-kubernetes/), however it does take up quite a bit of memory.
- [Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/)
- Another Kubernetes provider of your choice.
> :warning: If you choose a container registry provided by a cloud provider (other than Dockerhub), you will likely have to take some steps to configure your kubernetes cluster to allow access. Follow the instructions provided by your cloud provider.
## Deploying the application
Now that we have our application running locally with multiple containers, let's deploy the application. In this example, we will deploy to Kubernetes by using `tye deploy`.
1. Adding a container registry to `tye.yaml`
Based on what container registry you configured, add the following line in the `tye.yaml` file:
```yaml
name: microservice
registry: <registry_name>
```
If you are using dockerhub, the registry_name will be in the format of 'example'. If you are using Azure Kubernetes Service (AKS), the registry_name will be in the format of example.azurecr.io.
1. Deploy to Kubernetes
Next, deploy the rest of the application by running.
Deploy the rest of the application by running.
```text
tye deploy
tye deploy --interactive
```
> Enter the Container Registry (ex: 'example.azurecr.io' for Azure or 'example' for dockerhub):
You will be prompted to enter your container registry. This is needed to tag images, and to push them to a location accessible by kubernetes.
If you are using dockerhub, the registry name will your dockerhub username. If you are a standalone container registry (for instance from your cloud provider), the registry name will look like a hostname, eg: `example.azurecr.io`.
`tye deploy` does many different things to deploy an application to Kubernetes. It will:
- Create a docker image for each project in your application.
- Push each docker image to your container registry.
- Generate a Kubernetes Deployment and Service for each project.
- Apply the generated Deployment and Service to your current Kubernetes context.
- Generate a Kubernetes `Deployment` and `Service` for each project.
- Apply the generated `Deployment` and `Service` to your current Kubernetes context.
1. Test it out!
2. Test it out!
You should now see two pods running after deploying.
@ -57,13 +56,82 @@ Now that we have our application running locally with multiple containers, let's
frontend-84bbdf4f7d-6r5zp 1/1 Running 0 85m
```
You can visit the frontend application by port forwarding to the frontend pod.
You'll have two services in addition to the built-in `kubernetes` service.
```text
kubectl port-forward frontend-84bbdf4f7d-6r5zp 8000:80
kubectl get service
```
Now navigate to <http://localhost:8000> to view the frontend application working on Kubernetes.
```text
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend ClusterIP 10.0.147.87 <none> 80/TCP 11s
frontend ClusterIP 10.0.20.168 <none> 80/TCP 14s
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 3d5h
```
You can visit the frontend application by port forwarding to the frontend service.
```text
kubectl port-forward svc/frontend 5000:80
```
Now navigate to <http://localhost:5000> to view the frontend application working on Kubernetes. You should see the list of weather forcasts just like when you were running locally.
> :bulb: Currently `tye` does not provide a way to expose pods/services created to the public internet. We'll add features related to `Ingress` in future releases.
> :warning: Currently `tye` does not automatically enable TLS within the cluster, and so communication takes place over HTTP instead of HTTPS. This is typical way to deploy services in kubernetes - we may look to enable TLS as an option or by default in the future.
## Exploring tye.yaml
Tye has a optional configuration file (`tye.yaml`) to allow customizing settings. If you want to use `tye deploy` as part of a CI/CD system, it's expected that you'll have a `tye.yaml`.
1. Scaffolding `tye.yaml`
Run the `tye init` command in the `microservices` directory to generate a default `tye.yaml`
```text
tye init
```
The contents of `tye.yaml` should look like:
```yaml
# tye application configuration file
# read all about it at https://github.com/dotnet/tye
#
# when you've given us a try, we'd love to know what you think:
# <survey link>
#
name: microservice
services:
- name: frontend
project: frontend/frontend.csproj
- name: backend
project: backend/backend.csproj
```
The top level scope (like the `name` node) is where global settings are applied.
`tye.yaml` lists all of the application's services under the `services` node. This is the place for per-service configuration.
See [schema](schema.md) for more details about `tye.yaml`.
> :bulb: We provide a json-schema for `tye.yaml` and some editors support json-schema for completion and validation of yaml files. See [json-schema](/src/schema/README.md) for instructions.
2. Adding a container registry to `tye.yaml`
Based on what container registry you configured, add the following line in the `tye.yaml` file:
```yaml
name: microservice
registry: <registry_name>
```
If you are using dockerhub, the registry_name will your dockerhub username. If you are a standalone container registry (for instance from your cloud provider), the registry_name will look like a hostname, eg: `example.azurecr.io`.
Now it's possible to use `tye deploy` without `--interactive` since the registry is stored as part of configuration.
> :question: This step may not make much sense if you're using `tye.yaml` to store a personal Dockerhub username. A more typical use case would storing the name of a private registry for use in a CI/CD system.
## Next Steps

Просмотреть файл

@ -25,7 +25,14 @@ This tutorial will demonstrate how to use `tye run` to run a multi-project appli
With just a single application, tye will do two things: start the frontend application and run a dashboard. Navigate to <http://localhost:8000> to see the dashboard running.
The dashboard should show the `frontend` application running. You should be able to view the application logs and you should be able to hit navigate to the application in your browser.
The dashboard should show the `frontend` application running.
- The `Logs` column has a link to view the streaming logs for the service.
- the `Bindings` column has links to the listening URLs of the service.
Navigate to the `frontend` service using one of the links on the dashboard.
The dashboard will use port 8000 if possible. Services written using ASP.NET Core will have their listening ports assigned randomly if not explicitly configured.
## Running multiple applications with tye run
@ -39,13 +46,12 @@ This tutorial will demonstrate how to use `tye run` to run a multi-project appli
```text
dotnet new sln
dotnet sln add frontend
dotnet sln add backend
dotnet sln add frontend backend
```
You should have a solution called `microservice.sln` that references the `frontend` and `backend` projects.
1. If you haven't already, stop the existing `tye run` command using `Ctrl + C`. Run the `tye` command line in the folder with the solution.
2. If you haven't already, stop the existing `tye run` command using `Ctrl + C`. Run the `tye` command line in the folder with the solution.
```text
tye run
@ -53,10 +59,14 @@ This tutorial will demonstrate how to use `tye run` to run a multi-project appli
The dashboard should show both the `frontend` and `backend` services. You can navigate to both of them through either the dashboard of the url outputted by `tye run`.
> :warning: The `backend` service in this example was created using the `webapi` project template and will return an HTTP 404 for its root URL.
## Getting the frontend to communicate with the backend
Now that we have two applications running, let's make them communicate. By default, `tye` enables service discovery by injecting environment variables with a specific naming convention.
1. Open the solution in your editor of choice.
1. Add a `GetUri()` method to the frontend project at the bottom of the Startup.cs class:
```C#
@ -66,9 +76,9 @@ Now that we have two applications running, let's make them communicate. By defau
}
```
This method resolved the URL using the `tye` naming convention for services. For more information on this, see the [Service Definition](service_discovery.md).
This method resolved the URL using the `tye` naming convention for services. For more information on, see [service discovery](service_discovery.md).
1. Add a file `WeatherForecast.cs` to the `frontend` project.
2. Add a file `WeatherForecast.cs` to the `frontend` project.
```C#
using System;
@ -90,7 +100,7 @@ Now that we have two applications running, let's make them communicate. By defau
This will match the backend `WeatherForecast.cs`.
1. Add a file `WeatherClient.cs` to the `frontend` project with the following contents:
3. Add a file `WeatherClient.cs` to the `frontend` project with the following contents:
```C#
using System.Net.Http;
@ -101,23 +111,30 @@ Now that we have two applications running, let's make them communicate. By defau
{
public class WeatherClient
{
private readonly JsonSerializerOptions options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy. CamelCase,
};
private readonly HttpClient client;
public WeatherClient(HttpClient client)
{
this.client = client;
}
public async Task<WeatherForecast[]> GetWeatherAsync()
public async Task<WeatherForecast[]> GetWeatherAsync()
{
var responseMessage = await this.client.GetAsync("/weatherforecast");
return await JsonSerializer.DeserializeAsync<WeatherForecast[]>(await responseMessage.Content.ReadAsStreamAsync());
var responseMessage = await this.client. GetAsync("/weatherforecast");
var stream = await responseMessage.Content. ReadAsStreamAsync();
return await JsonSerializer. DeserializeAsync<WeatherForecast[]>(stream, options);
}
}
}
```
1. Now register this client in `Startup.cs` class in `ConfigureServices` of the `frontend` project:
4. Now register this client in `Startup.cs` class in `ConfigureServices` of the `frontend` project:
```C#
public void ConfigureServices(IServiceCollection services)
@ -133,7 +150,7 @@ Now that we have two applications running, let's make them communicate. By defau
This will wire up the `WeatherClient` to use the correct URL for the `backend` service.
1. Add a `Forecasts` property to the `Index` page model under `Pages\Index.cshtml.cs` in the `frontend` project.
5. Add a `Forecasts` property to the `Index` page model under `Pages\Index.cshtml.cs` in the `frontend` project.
```C#
public WeatherForecast[] Forecasts { get; set; }
@ -148,9 +165,15 @@ Now that we have two applications running, let's make them communicate. By defau
}
```
1. Change the `Index.cshtml` razor view to render the `Forecasts` property in the razor page:
6. Change the `Index.cshtml` razor view to render the `Forecasts` property in the razor page:
```cshtml
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
```html
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
@ -181,8 +204,10 @@ Now that we have two applications running, let's make them communicate. By defau
</table>
```
1. Run the project and the `frontend` service should be able to successfully call the `backend` service!
7. Run the project and the `frontend` service should be able to successfully call the `backend` service!
When you visit the `frontend` service you should see a table of weather data. This data was produced randomly in the `backend` service. The fact that you're seeing it in a web UI in the `frontend` means that the services are able to communicate.
## Next Steps
Now that you are able to run a multi-project application with `tye run`, see the [Frontend Backend Deploy Sample](frontend_backed_deploy.md) to learn how to deploy this application to Kubernetes.
Now that you are able to run a multi-project application with `tye run`, move on to the [Frontend Backend Deploy Sample](frontend_backed_deploy.md) to learn how to deploy this application to Kubernetes.

Просмотреть файл

@ -6,23 +6,18 @@ We just showed how `tye` makes it easier to communicate between 2 applications r
`Tye` can use `docker` to run images that run as part of your application. If you haven't already, make sure docker is installed on your operating system ([install docker](https://docs.docker.com/install/)) .
1. To create a `tye` manifest from the solution file.
```
tye init microservice.sln
```
This will create a manifest called `tye.yaml` with the following contents:
```yaml
name: microservice
services:
- name: frontend
project: frontend\frontend.csproj
- name: backend
project: backend\backend.csproj
1. Change the `WeatherForecastController.Get()` method in the `backend` project to cache the weather information in redis using an `IDistributedCache`.
Add the following `using`s to the top of the file:
```C#
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
```
This will be the source of truth for `tye` execution from now on. To see a full schema of file, see the reference in the [schema reference](schema.md).
And update `Get()`:
1. Change the `WeatherForecastController.Get` method in the `backend` project to cache the weather information in redis using an `IDistributedCache`.
```C#
[HttpGet]
public async Task<string> Get([FromServices]IDistributedCache cache)
@ -53,14 +48,15 @@ We just showed how `tye` makes it easier to communicate between 2 applications r
This will store the weather data in Redis with an expiration time of 15 seconds.
1. Add a package reference to `Microsoft.Extensions.Caching.StackExchangeRedis` in the backend project:
2. Add a package reference to `Microsoft.Extensions.Caching.StackExchangeRedis` in the backend project:
```
cd backend/
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
```
1. Modify `Startup.ConfigureServices` in the `backend` project to add the redis `IDistributedCache` implementation.
3. Modify `Startup.ConfigureServices` in the `backend` project to add the redis `IDistributedCache` implementation.
```C#
public void ConfigureServices(IServiceCollection services)
{
@ -82,63 +78,146 @@ We just showed how `tye` makes it easier to communicate between 2 applications r
```
The above configures redis to use the host and port for the `redis` service injected by the `tye` host.
1. Modify `tye.yaml` to include redis as a dependency.
4. Modify `tye.yaml` to include redis as a dependency.
> :bulb: You should have already created `tye.yaml` in a previous step near the end of the deployment tutorial.
```yaml
name: microservice
services:
- name: backend
project: backend\backend.csproj
project: backend\backend.csproj
- name: frontend
project: frontend\frontend.csproj
project: frontend\frontend.csproj
- name: redis
dockerImage: redis
bindings:
- port: 6379
dockerImage: redis
bindings:
- port: 6379
- name: redis-cli
dockerImage: redis
args: "redis-cli -h host.docker.internal MONITOR"
dockerImage: redis
args: "redis-cli -h host.docker.internal MONITOR"
```
We've added 2 services to the `tye.yaml` file. The redis service itself and a redis-cli service that we will use to watch the data being sent to and retrieved from redis.
We've added 2 services to the `tye.yaml` file. The `redis` service itself and a `redis-cli` service that we will use to watch the data being sent to and retrieved from redis.
1. Run the `tye` command line in the solution root
5. Run the `tye` command line in the solution root
> :bulb: Make sure your command-line is in the `microservices/` directory. One of the previous steps had you change directories to edit a specific project.
```
tye run
```
Navigate to <http://localhost:8000> to see the dashboard running. Now you will see both `redis` and the `redis-cli` running. Navigate to the `frontend` application and verify that the data returned is the same after refreshing the page multiple times. New content will be loaded every 15 seconds, so if you wait that long and refresh again, you should see new data. You can also look at the redis-cli logs and see what data is being cached in redis.
Navigate to <http://localhost:8000> to see the dashboard running. Now you will see both `redis` and the `redis-cli` running listed in the dashboard.
Navigate to the `frontend` application and verify that the data returned is the same after refreshing the page multiple times. New content will be loaded every 15 seconds, so if you wait that long and refresh again, you should see new data. You can also look at the `redis-cli` logs using the dashboard and see what data is being cached in redis.
## Deploying redis
1. Deploy redis to Kubernetes
`tye deploy` will not deploy the redis configuration, so you need to deploy it first. Run:
```
kubectl apply -f https://raw.githubusercontent.com/dotnet/tye/d79f790ba13791c1964ed03c31da0cd12b101f39/docs/yaml/redis.yaml?token=AB7K4FLEULBCQQU6NLXZEDC6OPIU4
```text
kubectl apply -f https://raw.githubusercontent.com/dotnet/tye/master/docs/yaml/redis.yaml?token=AAK5D65XGABGEPUJ2MFJBM26O35M2
```
This will create a deployment and service for redis. You can see that by running:
```
```text
kubectl get deployments
```
You will see redis deployed and running.
1. Deploy to Kubernetes
2. Add secrets to the application
Next, deploy the rest of the application by running.
In order to access redis we need to add some code to the `backend` project to be able to read secrets from inside the container.
```
tye deploy
First, add the `KeyPerFile` configuration provider package to the backend project using the command line.
```text
cd backend
dotnet add package Microsoft.Extensions.Configuration.KeyPerFile
cd ..
```
1. Test it out!
Next, add the following `using`s for the configuration provider near the top of `Program.cs`
```C#
using System.IO;
using Microsoft.Extensions.Configuration.KeyPerFile;
```
Then, add the following method to the `Program` class:
```C#
private static void AddTyeBindingSecrets(IConfigurationBuilder config)
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
}
```
Then update `CreateHostBuilder` to call the new method:
```C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
AddTyeBindingSecrets(config);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
```
3. Deploy to Kubernetes
Next, deploy the rest of the application by running:
```text
tye deploy --interactive
```
You'll be prompted for the connection string for redis.
```text
Validating Secrets...
Enter the connection string to use for service 'redis':
```
Enter the following to use instance that you just deployed:
```text
redis:6379
```
`tye deploy` will create kubernetes secret to store the connection string.
```text
Validating Secrets...
Enter the connection string to use for service 'redis': redis:6379
Created secret 'binding-production-redis-redis-secret'.
```
> :question: `--interactive` is needed here to create the secret. This is a one-time configuration step. In a CI/CD scenario you would not want to have to specify connection strings over and over, deployment would rely on the existing configuration in the cluster.
> :bulb: Tye uses kubernetes secrets to store connection information about dependencies like redis that might live outside the cluster. Tye will automatically generate mappings between service names, binding names, and secret names.
4. Test it out!
You should now see three pods running after deploying.
```
```text
kubectl get pods
```
@ -147,5 +226,12 @@ We just showed how `tye` makes it easier to communicate between 2 applications r
backend-ccfcd756f-xk2q9 1/1 Running 0 85m
frontend-84bbdf4f7d-6r5zp 1/1 Running 0 85m
redis-5f554bd8bd-rv26p 1/1 Running 0 98m
```
Just like last time, we'll need to port-forward to access the `frontend` from outside the cluster.
```text
kubectl port-forward svc/frontend 5000:80
```
Visit `http://localhost:5000` to see the `frontend` working in kubernetes.

Просмотреть файл

@ -40,12 +40,3 @@ spec:
targetPort: 6379
selector:
app.kubernetes.io/name: redis
---
apiVersion: v1
kind: Secret
metadata:
name: binding-production-redis-redis-secret
type: Opaque
stringData:
connectionstring: redis:6379