ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure SignalR Service で ASP.NET SignalR を使ってみる

この記事は、Azure Advent Calendar 2018 の 8 日目 の記事です。
qiita.com
Ignite 2018 で GA が発表された Azure SignalR Service ですが、ASP.NET Core SignalR だけでなく、まだプレビューですが ASP.NET SignalR にも対応しています。
今回は、Core ではない ASP.NET SignalR を使って試してみました。

Azure SignalR Service とは

Azure SignalR Service は、SignalR を使って開発したアプリケーションのコネクションやスケーリングを管理してくれるマネージドサービスです。
build 2018 のセッションから引用したスライドです。
f:id:TonyTonyKun:20181118124127j:plain
アプリケーションの規模が大きくなると、バックエンドで Redis や Service Bus を使ったコネクションやスケーリングの管理が必要になります。このような面倒なところを Azure SignalR Service に任せることができます。
Azure SignalR Service の使い方は、こちらの公式ドキュメントにある通りですが、早速試していきます。
github.com

Azure SignalR Service を作成する

Azure Portal から、Azure SignalR Service を作成します。

f:id:TonyTonyKun:20181118142922p:plain

Standard プラン以外の他に、20 コネクションまでの Free プランもあります。東日本リージョンもあるので、安心して使えます。

ASP.NET SignalR のコードを変更する

ASP.NET SignalR のプロジェクトに対して、Azure SignalR Service に対応するための変更を加えていきます。

NuGet ライブラリのインストール

まず、Azure SignalR Service 用の NuGet ライブラリの Microsoft.Azure.SignalR.AspNet をインストールします。

PM> Install-Package Microsoft.Azure.SignalR.AspNet -Version 1.0.0-preview1-10259

NuGet ライブラリをインストールしたら、HTML ファイルで指定されている JavaScript のパスを変更します。

<script src="Scripts/jquery.signalR-2.4.0-preview2-20181018-02.min.js"></script>

Startup クラスを変更する

Startup クラスで呼び出している MapSignalR メソッドを MapAzureSignalR メソッドに置き換えます。引数には、他のアプリケーションと区別する一意な名前を渡します。

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        //app.MapSignalR();
        app.MapAzureSignalR(this.GetType().FullName);
    }
}

接続文字列の追加

Web.config に Azure SignalR Service の接続文字列を設定します。接続文字列は、Azure Portal から取得できます。

<connectionStrings>
  <add name="Azure:SignalR:ConnectionString" connectionString="Endpoint=xxx;AccessKey=xxx;Version=1.0;"/>
</connectionStrings>

動作確認

ASP.NET SignalR のサンプルとして、クリスマスなので懐かしい Fireworks のアプリケーションを Azure Web Apps にデプロイしました。

f:id:TonyTonyKun:20181208094616p:plain

自分で打ち上げた花火を、他のブラウザでもリアルタイムに観ることができます。
試してみたい方は、こちらの URL からどうぞ。

ブラウザの開発者ツールで確認すると、Azure SignalR Service に接続されていることがわかります。

f:id:TonyTonyKun:20181208103828p:plain

まとめ

ASP.NET SignalR は、チャットやダッシュボードなどのリアルタイムな Web アプリケーションを開発できるフレームワークです。
今から開発するなら ASP.NET Core SignalR を選択すべきですが、それが難しい場合でも Azure SignalR Service を使うことができます。
本番運用では、バックエンドでコネクションやスケーリングの管理が必須となるので、 Redis や Service Bus を使わずに Azure に任せられる嬉しいサービスだと思います。

Azure Container Service (AKS) を試してみた

先週、Azure のマネージドな Kubernetes サービスとして Azure Container Service (AKS) のプレビューがリリースされたので、試してみました。
azure.microsoft.com

Azure Container Service (AKS) を作成する

Azure Container Service (AKS) Documentation - Tutorials, API Reference | Microsoft Docs

公式ドキュメントにも記載されているように、Azure Portal の Cloud Shell を使うと、サクッと試すことができます。
ただ、実際の開発作業で使うことを考えると、ローカルの開発マシンで AKS を操作したいので、Azure CLI の Docker Image を使って試してみます。

Cloud Shell には、Kubectl (Kubernetes のクライアントツール) と Helm (Kubernetes のパッケージマネージャー)がインストール済みですが、 Azure CLI の Docker Image には含まれていません。
そのため、Kubectl と Helm がインストール済みの Dockerfile を書いてみました。

FROM azuresdk/azure-cli-python:2.0.20

# Install kubectl
RUN wget -O /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.8.2/bin/linux/amd64/kubectl \
 && chmod +x /usr/local/bin/kubectl

# Install Helm
RUN wget https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-linux-amd64.tar.gz \
 && tar -zxvf helm-v2.7.0-linux-amd64.tar.gz \
 && mv linux-amd64/helm /usr/local/bin/helm \
 && rm -rf linux-amd64

ローカルの開発マシンでは、Kubectl と Helm の接続情報、SSH 接続キーをマウントして、この Docker Image を実行します。
develop ディレクトリは、Kubernetes にデプロイする YAML ファイルやカスタムの Helm Chats を想定して、マウントしてます。

$ docker run -it --rm -v ${HOME}/.kube/aks:/root/.kube -v ${HOME}/.helm/aks:/root/.helm -v ${HOME}/.ssh/aks:/root/.ssh -v ${HOME}/develop:/develop thara0402/azure-cli-k8s:latest

Azure CLI にログインします。

$ az login

まだプレビュー中なので、サブスクリプションごとにアクティブ化が必要です。

$ az provider register -n Microsoft.ContainerService

リソースグループを作成します。利用できるリージョンは限られており、まだ日本は使えません。

$ az group create --name aks --location westus2

AKS を作成します。

$ az aks create --resource-group aks --name myK8sCluster --node-count 1 --generate-ssh-keys

kubectl の接続情報をダウンロードします。

$ az aks get-credentials --resource-group=aks --name=myK8sCluster

Agent Node が1つ作成されました。Master Node は、Azure 側に管理を任せているので表示されません。

$ kubectl get nodes
NAME                        STATUS    ROLES     AGE       VERSION
aks-agentpool1-29980149-0   Ready     agent     2d        v1.7.7

Azure Portal で確認すると、2つのリソースグループが作成されています。どちらのリソースグループにも、Master Node の仮想マシンは表示されていません。

ASP.NET Core アプリケーションをデプロイする

ASP.NET Core アプリケーションの Docker Image を使って、AKS にデプロイします。

$ kubectl run mvcapp --image thara0402/mvcapp:v1
$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
mvcapp-614172684-tddnb   1/1       Running   0          1m

$ kubectl expose deployments mvcapp --port=5000 --type=LoadBalancer
$ kubectl get svc
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)          AGE
kubernetes   ClusterIP      10.0.0.1       <none>           443/TCP          2d
mvcapp       LoadBalancer   10.0.121.196   52.175.213.163   5000:31552/TCP   3m

ブラウザで 52.175.213.163:5000 に接続すると、ASP.NET Core MVC のテンプレートが表示されます。
f:id:TonyTonyKun:20171031035658p:plain
次に、Agent Node の数を3つに増やしてみます。

$ az aks scale --resource-group=aks --name=myK8SCluster --agent-count 3
$ kubectl get nodes
NAME                        STATUS     ROLES     AGE       VERSION
aks-agentpool1-29980149-0   Ready      agent     29m       v1.7.7
aks-agentpool1-29980149-1   Ready      agent     16m       v1.7.7
aks-agentpool1-29980149-2   Ready      agent     16m       v1.7.7

最後に、Kubernetes Cluster を ver.1.8.1 にバージョンアップしてみます。

$ az aks upgrade --name myK8sCluster --resource-group aks --kubernetes-version 1.8.1
$ kubectl get nodes
NAME                        STATUS     ROLES     AGE       VERSION
aks-agentpool1-29980149-0   Ready      agent     40m       v1.8.1
aks-agentpool1-29980149-1   Ready      agent     30m       v1.8.1
aks-agentpool1-29980149-2   Ready      agent     30m       v1.8.1

Helm を使ってデプロイする

Helm を使ってデプロイしようと試しましたが、エラーが発生してしまいました。

$ helm list
Error: forwarding ports: error upgrading connection: error dialing backend: dial tcp 10.240.0.4:10250: getsockopt: connection refused

調べてみると、Helm の FAQ に該当しそうな Workaround があったのですが、Master Node で作業する必要があり、試すことができませんでした。

helm/install_faq.md at master · kubernetes/helm · GitHub

これ以外にも、Kubernetes Dashboard が表示できなかったりするので、まだプレビューということもあり、もう少し様子をみたいと思います。

まとめ

これまでも Azure Container Service で Kubernetes を展開することはできましたが、どちらかと言うと仮想マシンのテンプレートでした。
ちょっとした動作確認に使う分にはいいですが、本番環境で運用するとなると、IaaS と同等の運用コストがかかります。
AKS は、Google Container Engine (GKE) のようなサービスで、Kubernetes の Master Node の管理を Azure 側に任せてしまい、Agent Node とデプロイするアプリケーションの管理に注力できます。
GA に向けて、クラウドらしい便利なサービスになることを期待したいです。

Azure Container Service の Kubernetes に Helm を使ってアプリケーションをデプロイする

Azure Container Service に Kubernetes を展開して、Helm を使ってアプリケーションをデプロイしてみます。

Helm とは

Kubernetes のパッケージマネージャーです。

docs.helm.sh

Kubernetes にデプロイする YAML ファイルをまとめたパッケージは、Charts と呼ばれます。Helm の公式リポジトリとして、KubeApps が提供されていて、WordPress や Jenkins など100以上のアプリケーションの Charts が公開されています。

Helm をインストールする

こちらのドキュメントに従ってインストールします。

docs.helm.sh

まず、Azure Portal から Azure Container Service を作成します。Kubernetes の Master Node に SSH で接続して、Helm のバイナリをダウンロードします。

$ curl -O https://storage.googleapis.com/kubernetes-helm/helm-v2.6.1-linux-amd64.tar.gz
$ tar -zxvf helm-v2.6.1-linux-amd64.tar.gz
$ sudo mv linux-amd64/helm /usr/local/bin/helm

次に、helm init コマンドを実行します。

$ helm init

これで、Helm のインストールが完了です。

Helm を使って WordPress をデプロイする

KubeApps で公開されている Charts を使って、WordPress をデプロイしてみます。
WordPress の Charts を指定して、helm install コマンドを実行します。

$ helm install --name my-wp stable/wordpress
NAME:   my-wp
LAST DEPLOYED: Sat Sep 23 17:43:09 2017
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/PersistentVolumeClaim
NAME             STATUS  VOLUME                                    CAPACITY  ACCESSMODES  STORAGECLASS  AGE
my-wp-wordpress  Bound   pvc-493f1d91-a03b-11e7-944e-000d3a72a60e  10Gi      RWO          default       13s
my-wp-mariadb    Bound   pvc-4942547b-a03b-11e7-944e-000d3a72a60e  8Gi       RWO          default       13s

==> v1/Service
NAME             CLUSTER-IP    EXTERNAL-IP  PORT(S)                     AGE
my-wp-mariadb    10.0.73.148   <none>       3306/TCP                    13s
my-wp-wordpress  10.0.193.167  <pending>    80:30912/TCP,443:30683/TCP  13s

==> v1beta1/Deployment
NAME             DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
my-wp-mariadb    1        1        1           0          13s
my-wp-wordpress  1        1        1           0          13s

==> v1/Secret
NAME             TYPE    DATA  AGE
my-wp-wordpress  Opaque  3     14s
my-wp-mariadb    Opaque  2     14s

==> v1/ConfigMap
NAME           DATA  AGE
my-wp-mariadb  1     14s

NOTES:
1. Get the WordPress URL:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w my-wp-wordpress'

  export SERVICE_IP=$(kubectl get svc --namespace default my-wp-wordpress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP/admin

2. Login with the following credentials to see your blog

  echo Username: user
  echo Password: $(kubectl get secret --namespace default my-wp-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

WordPress と MariaDB がデプロイされたことが分かります。Kubernetes の5つのオブジェクトで構成されています。

  • PersistentVolumeClaim
  • Service
  • Deployment
  • Secret
  • ConfigMap

これらのオブジェクトを1つのパッケージとして、Helm Install コマンドだけでデプロイできました。Charts の内容は、GitHub で確認することができます。

github.com

数分待つと、デプロイが完了するので、サービスの EXTERNAL IP にブラウザからアクセスしてみます。

f:id:TonyTonyKun:20170930163933p:plain

削除するときは、Helm delete コマンドを使います。

$ helm delete my-wp --purge

Helm Charts を作ってみる

自分が作った ASP.NET Core のアプリケーションをデプロイする Charts を作ってみます。
helm create コマンドを実行すると、Charts のテンプレートが作成されます。

$ helm create mvcapp

f:id:TonyTonyKun:20170930164003p:plain

deployment.yaml と service.yaml を確認します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ template "fullname" . }}
  labels:
    chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ template "fullname" . }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.internalPort }}
        livenessProbe:
          httpGet:
            path: /
            port: {{ .Values.service.internalPort }}
        readinessProbe:
          httpGet:
            path: /
            port: {{ .Values.service.internalPort }}
        resources:
{{ toYaml .Values.resources | indent 12 }}
apiVersion: v1
kind: Service
metadata:
  name: {{ template "fullname" . }}
  labels:
    chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
spec:
  type: {{ .Values.service.type }}
  ports:
  - port: {{ .Values.service.externalPort }}
    targetPort: {{ .Values.service.internalPort }}
    protocol: TCP
    name: {{ .Values.service.name }}
  selector:
    app: {{ template "fullname" . }}

この yaml を見ると分かるように、Charts に対して外部からパラメータを指定できるようになっています。
values.yaml を編集して、ASP.NET Core のアプリケーションをデプロイできるようにします。

replicaCount: 1
image:
  repository: thara0402/mvcapp
  tag: v1
  pullPolicy: IfNotPresent
service:
  name: mvcapp-service
  type: LoadBalancer
  externalPort: 80
  internalPort: 5000
resources:

この Charts を指定して、helm install コマンドを実行します。

$ helm install --name my-mvc ./mvcapp
NAME:   my-mvc
LAST DEPLOYED: Sat Sep 23 17:43:18 2017
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME           CLUSTER-IP    EXTERNAL-IP  PORT(S)       AGE
my-mvc-mvcapp  10.0.124.120  <pending>    80:30617/TCP  4s

==> v1beta1/Deployment
NAME           DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
my-mvc-mvcapp  1        1        1           0          4s


NOTES:
1. Get the application URL by running these commands:
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get svc -w my-mvc-mvcapp'
  export SERVICE_IP=$(kubectl get svc --namespace default my-mvc-mvcapp -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:80

ASP.NET Core アプリケーションがデプロイされたことを確認できます。

f:id:TonyTonyKun:20170930164049p:plain

まとめ

Kubernetes に Helm を使って、アプリケーションをデプロイしてみました。
使いたいアプリケーションが KubeApps にあればすぐにデプロイできますし、自分で Charts を作ることもできます。Kubernetes の Service や Deployment だけなく、アプリとデータベースをまとめることもできます。
Helm は、Kubernetes にデプロイするアプリケーションを管理できる便利なツールなので、積極的に活用していきたいです。