Blog Post

Apps on Azure Blog
5 MIN READ

Building a path to success for microservices and .NET Core - Project Tye + GitHub Actions

Shayne Boyer's avatar
Shayne Boyer
Brass Contributor
Jul 01, 2020

Project Tye is an experimental developer tool that the .NET team is working on to make the experience of creating, testing and deploying microservices and distributed apps easier.  

 

If you've done any work in this space over the past many years you've no doubt seen the changes in technology and tools; Docker Swarm, Mesosphere, Kubernetes, and various tools and configuration options that more than likely caused some sort of pain.

 

The goals of Tye are to help make the development easier by running many services with a single command, options for using containers or not, service discovery by convention, and simplifying deployment to Kubernetes with minimal knowledge and/or configuration.

 

In March, the team gave a quick overview during the .NET Community StandUp

 

 

Getting Started

There are a number of resources for getting up and running.  

 

 

Tye is a .NET global tool and is installed using the command

 

dotnet tool install -g Microsoft.Tye --version "0.3.0-alpha.20319.3"

 

 

After installing the tye global tool, we can now create and run single and multiple services using the dotnet CLI commands.

 

# Create a Razor Pages App
dotnet new razor -n frontend 

# Create a WebAPI App
dotnet new webapi -n backend

# Create the Solution file and add the projects
dotnet new sln -n microservices
dotnet sln add frontend backend

 

 

Typically when creating multiple applications and wanting to run them all together there is usually some Dockerfile(s) involved, references, nginx.conf files etc.

 

With tye, that is handled for you. Just use the following:

 

tye run --dashboard

 

 

Using the --dashboard option automatically opens the tye dashboard web application and displayed the two applications, ports, logs and other information running. 

 

There is some work to be done to connect the backend and frontend applications, see the steps here for that work.

 

Deploying your application

Once you've successfully run the applications locally, the next step is to push your services and apps to your cluster. There are a few requirements:

  • Docker for your OS
  • Container registry for the images that are produced, tagged and pushed prior to deployment to the cluster. i.e. Azure Container Registry, Docker Hub, GitHub etc.
  • A Kubernetes Cluster like AKS for example.

Once all of these are setup, use the deploy command with the --interactive option.

 

tye deploy --interactive

 

 

You'll be prompted for your container registry and if you have configured an ingress controller; you may be asked about deployment options for this as well.

 

Once complete, you can use the standard commands from kubectl to inspect pods, services and deployments.

 

> kubectl get pods

NAME                                             READY   STATUS    RESTARTS   AGE
backend-ccdfd756f-xk2w2                          1/1     Running   0          5m
frontend-84dfdf4f7d-6r5vb                        1/1     Running   0          5m

 

 

Using tye deploy is a quick and easy motion to publish your things to the cloud, but is it the method we'd want to continually do for production? Or even QA and Test? What would it look like to use tye and a CI/CD system together?

 

Deploying your application with GitHub Actions

This sample uses the frontend/backend sample from a above but also adds an ingress controller to the cluster to expose a public IP address for the frontend application. The GitHub action will use tye in conjunction with an Azure Kubernetes Service (AKS) cluster and Azure Container Registry (ACR).

 

Before setting up the action, create the AKS with the proper integration with the ACR instance.

 

az aks create -n mytyecluster -g mytyegroup --generate-ssh-keys --attach-acr myregistry --node-count 3

 

 

Below is the tye.yaml configuration file created using tye init allowing for specifying the registry name as well as the ingress instance and routes to deploy.

 

name: microservice
registry: myregistry.azurecr.io
ingress:
  - name: ingress
    bindings:
      - port: 8080
    rules:
      - path: /
        service: frontend
      - path: /backend
        service: backend
services:
- name: frontend
  project: frontend/frontend.csproj
  replicas: 2
- name: backend
  project: backend/backend.csproj

 

 

Running locally using tye run works as we'd expect, browsing the tye dashboard you should see the applications and the ingress similar to the following.

GitHub Action

Setting up the GitHub Action requires a few actions to compose the complete integration.

First, the name of the AKS cluster, resource group, and container registry are set as Environment variables.

 

env:
  AZURE_AKS_CLUSTER: mytyecluster
  AKS_RESOURCE_GROUP: mytyegroup
  ACR_RESOURCE_URI: myregistry.azurecr.io

 

 

Next, ensure that the version of .NET Core and tye are installed.

 

- name: 🧰 Setup .NET Core
    uses: actions/setup-dotnet@v1.5.0
    with:
    dotnet-version: 3.1.300

- name:  Install Tye tools
    run: |
    dotnet tool install -g Microsoft.Tye --version "0.2.0-alpha.20258.3"

 

 

Using the name of the registry and the Azure docker action to login to your registry. This step is needed prior to running the deploy command which will build and push the images to the registry.

 

- name:  Login to ACR
    uses: Azure/docker-login@v1  
    with:  
    login-server: ${{ env.ACR_RESOURCE_URI }}
    username: ${{ secrets.ACR_USER }}  
    password: ${{ secrets.ACR_PASSWORD }}

 

 

Next, we need to set the current context for our AKS cluster. Use Azure aks-set-context action for this.

 

- name:  Set AKS context
    uses: azure/aks-set-context@v1
    with:
    creds: '${{ secrets.AZURE_CREDENTIALS }}'
    cluster-name: ${{ env.AZURE_AKS_CLUSTER }}
    resource-group: ${{ env.AKS_RESOURCE_GROUP }}

 

 

When deploying manually you can use the --interactive option and the tye CLI will detect the configuration, inspect the cluster and ask/prompt for deployment. However, in this case it is automated and we need to deploy it as a part of the action.

 

We can just use a run action and apply the standard ingress from tye.

 

- name:  Install ingress-nginx
    run: |
    kubectl apply -f https://aka.ms/tye/ingress/deploy

 

 

 Finally, deploy the application!

 

- name: ☸ tye deploy
    run: |
    tye deploy -v Debug

 

 

The complete action looks like the following snippet:

 

name: Build and Deploy

on: [push]

env:
  AZURE_AKS_CLUSTER: mytyecluster
  AKS_RESOURCE_GROUP: mytyegroup
  ACR_RESOURCE_URI: myregistry.azurecr.io

jobs:
  build:
    if: github.event_name == 'push' && contains(toJson(github.event.commits), '***NO_CI***') == false && contains(toJson(github.event.commits), '[ci skip]') == false && contains(toJson(github.event.commits), '[skip ci]') == false
    name: tye deploy
    runs-on: ubuntu-latest
    steps:
    - name: ✔ Checkout
      uses: actions/checkout@v2

    - name: 🧰 Setup .NET Core
      uses: actions/setup-dotnet@v1.5.0
      with:
        dotnet-version: 3.1.300

    - name:  Install Tye tools
      run: |
        dotnet tool install -g Microsoft.Tye --version "0.3.0-alpha.20319.3"

    - name:  Login to ACR
      uses: Azure/docker-login@v1  
      with:  
        login-server: ${{ env.ACR_RESOURCE_URI }}
        username: ${{ secrets.ACR_USER }}  
        password: ${{ secrets.ACR_PASSWORD }}

    - name:  Set AKS context
      uses: azure/aks-set-context@v1
      with:
        creds: '${{ secrets.AZURE_CREDENTIALS }}'
        cluster-name: ${{ env.AZURE_AKS_CLUSTER }}
        resource-group: ${{ env.AKS_RESOURCE_GROUP }}

    - name:  Install ingress-nginx
      run: |
        kubectl apply -f https://aka.ms/tye/ingress/deploy

    - name: ☸ tye deploy
      run: |
        tye deploy -v Debug

 

 

 

Viewing the deployed application

Using kubectl, look for the ingress-nginx namespace and LoadBalancer TYPE to find the external IP address for the frontend application.

 

> kubectl get all -n ingress-nginx

NAME                                         TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   10.0.125.110   52.142.9.218   80:31128/TCP,443:31740/TCP   9m
service/ingress-nginx-controller-admission   ClusterIP      10.0.103.118   <none>         443/TCP                      9m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           9m

 

 

Feedback

Please file any issues on the dotnet/tye repo, feel free to reach out to me on twitter @spboyer or ask questions here in post! 

Updated Jul 01, 2020
Version 2.0
No CommentsBe the first to comment