Skip to content

Latest commit

 

History

History
703 lines (516 loc) · 24.9 KB

File metadata and controls

703 lines (516 loc) · 24.9 KB

Serving

Servingの責務はオートスケールアウト・イン、トラフィックコントロール、バージョン管理などです。Servingは4つのコンポーネントから構成されます。

  • Configuration: 最新の設定
  • Revision: コードと設定の履歴
  • Route: Revisionへのルーティング
  • Service: RouteとConfigurationから構成されるサービス全体

つぎの図をイメージしながら進めてください。

https://github.com/knative/docs/tree/master/docs/serving

Hello World

まずはTARGET環境変数にセットした文字を使ってHello worldするアプリケーションをKnativeのServiceとしてデプロイします。

Cloud Shellでワークスペースを作成し、つぎのマニフェストをservice.yamlという名前で保存してください。

$ mkdir knative-workshop
$ cd knative-workshop
$ touch service.yaml

service.yaml

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: "gcr.io/knative-samples/helloworld-go"
            env:
            - name: "TARGET"
              value: "Knative serving"

つぎのコマンドでマニフェストを適用してください。

# マニフェストファイルの適用
$ kubectl apply -f service.yaml
service.serving.knative.dev/helloworld created

# KnativeのKubernetesオブジェクトの登録状況確認
$ kubectl get ksvc,configuration,route

各KubernetesオブジェクトのREADYがすべてTrueになったら準備完了です。

アプリケーションにアクセスしてみてください。

# IPアドレスの取得
$ export IP_ADDRESS=$(kubectl get svc istio-ingressgateway --namespace istio-system --output 'jsonpath={.status.loadBalancer.ingress[0].ip}')

# curlでリクエスト
$ curl -H "Host: helloworld.default.example.com" http://$IP_ADDRESS
Hello Knative serving!

KnativeのKubernetesオブジェクトだけでなく、組み込みのKubernetesオブジェクトも動いているのが確認できます。

$ kubectl get pod,replicaset,deployment,service

Service、Deployment、ReplicaSet、Podオブジェクトが作成されていることが確認できます。これらはRevisionが管理しているもので、Revision毎に作成されています。

また、Podはリクエストがないときには消えています。5分ほど経ってからまた同じコマンドで存在を確認してみてください。

つぎのような状態になっています。

確認ができたらいったん登録したKnativeのServiceを削除してください。

$ kubectl delete -f service.yaml

参考

  • 実行したアプリケーションのソースコード
  • Knativeを利用せずに、Kubernetesの組み込みオブジェクトでknative Serviceを構築する場合との比較
  • Knative = Kubernetes Networking++の全訳
    • Knativeはサーバーレスのビルディングブロックであるという文脈でで説明されることが多く、本来メリットを受けることができるはずのKubernetes上のアプリケーションやマイクロサービスの開発者、運用・管理者などに便利な機能が伝わってないという話があるようです。

オートスケール

今度は負荷をかけながらPodがどのようにスケールするのかを確認します。

負荷をかけるのにはrakyll/heyというツールを利用します。

つぎのコマンドでインストールしてください。

$ go get -u github.com/rakyll/hey
$ hey
Usage: hey [options...] <url>

Options:
  -n  Number of requests to run. Default is 200.
...

つぎのマニフェストをautoscale-go.yamlという名前で保存してください。

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: autoscale-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        # KPA
        # Knative concurrency-based autoscaling (default).
        # autoscaling.knative.dev/class: kpa.autoscaling.knative.dev
        # autoscaling.knative.dev/metric: concurrency

        # Target 10 in-flight-requests per pod.
        autoscaling.knative.dev/target: "10"

        # HPA
        # Standard Kubernetes CPU-based autoscaling.
        # autoscaling.knative.dev/class: hpa.autoscaling.knative.dev
        # autoscaling.knative.dev/metric: cpu
    spec:
      containers:
      - image: gcr.io/knative-samples/autoscale-go:0.1

つぎのコマンドでマニフェストを適用してください。

# マニフェストファイルの適用
$ kubectl apply -f autoscale-go.yaml
service.serving.knative.dev/autoscale-go created

# KnativeのKubernetesオブジェクトの登録状況確認
$ kubectl get ksvc,configuration,route

heyコマンドを利用して負荷をかけてみてください。

# 30秒間50並列リクエスト
$ hey -z 30s -c 50 \
  -host "autoscale-go.default.example.com" \
  "http://${IP_ADDRESS?}?sleep=100&prime=10000&bloat=5" \
  && kubectl get pod

オートスケールの様子をGrafanaを使って確認してみましょう。

$ kubectl port-forward --namespace knative-monitoring $(kubectl get pods --namespace knative-monitoring --selector=app=grafana  --output=jsonpath="{.items..metadata.name}") 8080:3000

ダッシュボードはブラウザで確認できます。ポート8080でプレビューを選択してください。

Knarive Serving - Scaling Debugingを選択するとオートスケールの様子が確認できます。

確認ができたらいったん登録したKnativeのServiceを削除してください。

$ kubectl delete -f autoscale-go.yaml

参考

トラフィック分割

Revisionに流すトラフィックの割合を変更してみましょう。ブルーグリーンデプロイメントなどを実現するための機能です。

この例ではあるRevision(blue)へのリクエストを徐々に別のRevision(green)に移行していきます。

つぎのマニフェストをblue-green-config.yamlという名前で保存してください。

apiVersion: serving.knative.dev/v1alpha1
kind: Configuration
metadata:
  name: blue-green-demo
  namespace: default
spec:
  template:
    metadata:
      labels:
        knative.dev/type: container
    spec:
      containers:
        - image: gcr.io/knative-samples/helloworld-go
          env:
            - name: TARGET
              value: "blue"

マニフェストを適用してConfigurationを作成してください。先ほどの例ではServiceを作成することでServiceが管理するConfigurationRouteを間接的に作成しましたが、この例ではそれぞれ個別に作成します。実行するアプリケーションはTARGET環境変数にblueをセットしたhelloworldです。

$ kubectl apply --filename blue-green-config.yaml

適用するとConfigurationが登録され、Revisionが作成されます。

このConfiguration登録を登録したときに作成されたRevisionにトラフィックを流すためのRouteを登録します。

まずつぎのコマンドでRevision名を取得してください。

$ kubectl get configurations blue-green-demo -o=jsonpath='{.status.latestCreatedRevisionName}'
blue-green-demo-66h62 # 人によって異なります。

つぎのマニフェストをblue-green-route.yamlという名前で保存し、適用してください。spec.traffic[0].revisionNameは上で取得したもので置き換えが必要です。

apiVersion: serving.knative.dev/v1alpha1
kind: Route
metadata:
  name: blue-green-demo
  namespace: default
spec:
  traffic:
    - revisionName: blue-green-demo-66h62 # 取得したRevision名に置き換える
      percent: 100
$ kubectl apply --filename blue-green-route.yaml

図のようにRoute -> Revisonの状態になります。

アクセスしてみると、何度リクエストしてもHello blue!が出力されすはずです。

$ curl -H "Host: blue-green-demo.default.example.com" http://${IP_ADDRESS}
Hello blue!

新しいRevisionを作成してトラフィックをそちらに移行し始めましょう。ConfigurationのTARGET環境変数をgreenに変更し、適用してください。

変更後のblue-green-config.yamlはこちらです。

apiVersion: serving.knative.dev/v1alpha1
kind: Configuration
metadata:
  name: blue-green-demo
  namespace: default
spec:
  template:
    metadata:
      labels:
        knative.dev/type: container
    spec:
      containers:
        - image: gcr.io/knative-samples/helloworld-go
          env:
            - name: TARGET
              value: "green" # blueからgreenに変更

変更後に適用してください。Configurationを更新するとRevisionが新たに作成されます。

$ kubectl apply --filename blue-green-config.yaml

環境変数TARGETがgreenのRevisionが作成されます。

新しく作成されたRevisonの名前を取得してください。

$ kubectl get configurations blue-green-demo -o=jsonpath='{.status.latestCreatedRevisionName}'
blue-green-demo-zdjbc # 人によって異なります。

新しく作成したRevisionへアクセスできるようにしてみましょう。

blue-green-route.yamlをつぎのように変更して保存し、適用てください。

apiVersion: serving.knative.dev/v1alpha1
kind: Route
metadata:
  name: blue-green-demo
  namespace: default
spec:
  traffic:
    - revisionName: blue-green-demo-66h62 # blue
      percent: 100
    - revisionName: blue-green-demo-zdjbc # 新しく作成したRevision名、green
      percent: 0
      tag: v2
$ kubectl apply --filename blue-green-route.yaml

現在はまだ先に作ったgreenに100%のトラフィックが流れている状態です。

$ curl -H "Host: blue-green-demo.default.example.com" http://${IP_ADDRESS}
Hello blue!

しかし、tagをつけたことでテスト用のエンドポイントが払い出され、動作確認できるようになりました。

$ curl -H "Host: v2-blue-green-demo.default.example.com" http://${IP_ADDRESS}
Hello green!

テストが済んだらトラフィックを半分新しいRevisionに流してみましょう。

blue-green-route.yamlをつぎのように変更して保存してください。

apiVersion: serving.knative.dev/v1alpha1
kind: Route
metadata:
  name: blue-green-demo
  namespace: default
spec:
  traffic:
    - revisionName: blue-green-demo-66h62 # blue
      percent: 50
    - revisionName: blue-green-demo-zdjbc # green
      percent: 50
      tag: v2

変更後に適用してください。

$ kubectl apply --filename blue-green-route.yaml

greenとblueに50%ずつトラフィックが流れます。何度かアクセスして確認してみてください。

$ curl -H "Host: blue-green-demo.default.example.com" http://${IP_ADDRESS}
Hello blue!

最終的にはgreenのRevisionへのpercentを100、blueのRevisionへのpercentを0にしてtag: v1をつけたらトラフィックの移行は完了です。

確認ができたらいったん登録したKnativeのConfiguration、Routeを削除してください。

$ kubectl delete --filename blue-green-config.yaml
$ kubectl delete --filename blue-green-route.yaml

参考

Eventing

Eventingの責務はイベントのバインディングとデリバリーです。つぎのコンポーネント(CRD)を通じてイベントドリブンなアーキテクチャを実現します。

  • Souces: イベントソース。「Souces」という名前のCRDがあるのではなく、種類ごとに独立したCRDになっている。
  • Broker: イベントを受け取り、フィルタリングされたものをService(subscriber)に渡す
  • Trigger: subscriberにわたすイベントのフィルター

つぎの図をイメージしながら進めてください。

https://medium.com/knative/announcing-knative-v0-5-release-cfe646ca8e30

Hello World

最初はイベントソースをCronJobSourceとするシンプルな例を見てみましょう。CronJobSourceで発生したイベントはKnativeのServiceで受け取ります。

まず、イベントを受け取るServiceを準備します。つぎのマニフェストをevent-display-service.yamlという名前で保存してください。

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: event-display
spec:
  template:
    spec:
      containers:
        - image: gcr.io/knative-releases/github.com/knative/eventing-sources/cmd/event_display

つぎのコマンドでマニフェストを適用してください。

$ kubectl apply --filename event-display-service.yaml

今度はCronJobSourceを準備します。つぎのマニフェストをcronjob-source.yamlという名前で保存してください。

apiVersion: sources.eventing.knative.dev/v1alpha1
kind: CronJobSource
metadata:
  name: cronjob-source
spec:
  schedule: "*/2 * * * *"
  data: '{"message": "Hello Eventing!"}'
  sink:
    apiVersion: serving.knative.dev/v1alpha1
    kind: Service
    name: event-display

つぎのコマンドでマニフェストを適用してください。

$ kubectl apply --filename cronjob-source.yaml

CronJobSourceはspec.scheduleに記述したクロン式に従ってイベントを発行します。この例では30秒毎にHello Eventing!というメッセージを発行します。

KnativeのServiceで受信したメッセージはコンテナのログで確認できます。つぎのコマンドを実行してメッセージを確認してください。

$ kubectl logs -l serving.knative.dev/service=event-display -c user-container

確認ができたらいったん登録したServiceCronJobSourceを削除してください。

$ kubectl delete --filename event-display-service.yaml
$ kubectl delete --filename cronjob-source.yaml

参考

PubSub

今度はCloud Pub/Subのイベントを処理してみましょう。

Cloud Pub/Subに登場する概念と、それをいかに抽象化しているかをイメージしながら追うと理解しやすいかもしれません。

https://cloud.google.com/pubsub/docs/overview

まずGCP Cloud Pub/Subをイベントソースとするためにつぎのコマンドを実行してください。

$ kubectl apply -f https://github.com/google/knative-gcp/releases/download/v0.10.1/cloud-run-events.yaml

利用しているGCPプロジェクトでCloud Pub/Sub APIを有効化してください。

$ gcloud services enable pubsub.googleapis.com

GCPのサービスアカウントを準備します。つぎのコマンドを実行して新しくサービスアカウントを作成してください。

$ gcloud iam service-accounts create cloudrunevents-pullsub

作成したサービスアカウントにPub/Sub Editorロールを付与してください。

$ gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:cloudrunevents-pullsub@$PROJECT_ID.iam.gserviceaccount.com \
  --role roles/pubsub.editor

サービスアカウントの秘密鍵をJSON形式でダウンロードしてください。

$ gcloud iam service-accounts keys create cloudrunevents-pullsub.json \
--iam-account=cloudrunevents-pullsub@$PROJECT_ID.iam.gserviceaccount.com

JSONファイルからKubernetesのSecretオブジェクトを作成してください。

$ kubectl --namespace default create secret generic google-cloud-key --from-file=key.json=cloudrunevents-pullsub.json

Secretはgoogle-cloud-keyという名前で参照します。

$ kubectl get secret

PubSubのトピックを作成してください。

$ export TOPIC_NAME=testing
$ gcloud pubsub topics create $TOPIC_NAME

イベントを処理するServiceを作成してください。CronJobの例と同じくevent-display-serviceです。

$ kubectl apply --filename event-display-service.yaml

つぎのマニフェストをpullsubscription.yamlという名前で保存し、適用してください。specにはPubSubのtopic名とイベントの送信先を記述しています。

apiVersion: pubsub.cloud.google.com/v1alpha1
kind: PullSubscription
metadata:
  name: testing-source-event-display
spec:
  topic: testing
  sink:
    apiVersion: serving.knative.dev/v1alpha1
    kind: Service
    name: event-display
$ kubectl apply -f pullsubscription.yaml
# READYがTRUEになるまで少し時間がかかるので注意
$ kubectl get pullsubscription

PubSubのトピックにイベントを発行してください。メッセージはなんでも大丈夫です。

$ gcloud pubsub topics publish testing --message="Hello PubSub"

KnativeのServiceで受信したメッセージはコンテナのログで確認できます。つぎのコマンドを実行してメッセージを確認してください。

$ kubectl logs -l serving.knative.dev/service=event-display -c user-container

確認ができたらいったん登録したServicePullSubscriptionを削除してください。

$ kubectl delete --filename event-display-service.yaml
$ kubectl delete --filename pullsubscription.yaml

参考

Tekton

Tektonの責務はKubernetes上で CI/CDパイプラインを構築、実行することです。KnativeのBuildコンポーネントを強化する形で始まりましたが、Buildはv0.7を最後に開発が終了しTektonに引き継がれました。

  • Task: 「コンテナイメージをビルドする」「Kubernetes上にデプロイする」などの粒度のタスクを表現したオブジェクトです。タスクは1つ以上のstepから構成され、それぞれがコンテナで実行されます。自分で書くことも、すでに準備されたものを選んで利用することもできます。
  • TaskRun: Taskを実行するオブジェクトです。Taskがテンプレートとすると、それに具体的な値を与える実体です。
  • PipelineResource: タスクで利用する入出力です。
  • Pipeline: Taskを構成要素とするCI/CDパイプライン全体を表現するオブジェクトです。
  • PipelineRun: Pipelineを実行するオブジェクトです。Pipelineがテンプレートとすると、それに具体的な値を与える実体です。TaskRunを作成してここのTaskを実行していきます。

Hello World

kanikoを利用したTaskを使ってコンテナイメージをビルドしてレジストリにプッシュしてみましょう。

まず、kaniko Taskを利用できるようにするためにつぎのコマンドを実行してください。

$ kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/master/kaniko/kaniko.yaml

kaniko Taskを実行するにあたってはTaskRunで2つのパラメタを設定する必要があります。

  • DOCKERFILE: Dockerfileへのパスです。デフォルトは./Dockerfile
  • CONTEXT: Dockerのビルドコンテキストです。デフォルトは./

ビルドの対象とするアプリケーションはhelloworld-goです。knative/docsリポジトリにソースコードがあるのでこれをビルドし、今利用しているGCPプロジェクトのGCRにプッシュします。

GCRのパスをご自身のGCPプロジェクトのPROJECT_IDに変更し、taskrun-build-kaniko-helloworld-gcr.yamlというファイル名で保存し、適用してください。

apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  name: build-kaniko-helloworld-gcr
spec:
  taskRef:
    name: kaniko
  inputs:
    resources:
    - name: source
      resourceSpec:
        type: git
        params:
        - name: url
          value: https://github.com/knative/docs
    params:
    - name: DOCKERFILE
      value: Dockerfile
    - name: CONTEXT
      value: docs/serving/samples/hello-world/helloworld-go/
  outputs:
    resources:
    - name: image
      resourceSpec:
        type: image
        params:
        - name: url
          # ご自身のGCPプロジェクトIDに置き換えてください
          value: gcr.io/<your-project-id>/helloworld-go:latest
$ kubectl apply -f taskrun-build-kaniko-helloworld-gcr.yaml

つぎのコマンドを実行してビルド&プッシュを見守ってください。

$ kubectl get po -w
build-kaniko-helloworld-gcr-pod-e686b3   0/4     Init:3/4          0    5s
build-kaniko-helloworld-gcr-pod-e686b3   0/4     PodInitializing   0    6s
build-kaniko-helloworld-gcr-pod-e686b3   4/4     Running           0    8s
build-kaniko-helloworld-gcr-pod-e686b3   4/4     Running           0    8s
build-kaniko-helloworld-gcr-pod-e686b3   3/4     Running           0    11s
build-kaniko-helloworld-gcr-pod-e686b3   2/4     Running           0    16s
build-kaniko-helloworld-gcr-pod-e686b3   0/4     Completed         0    78s

つぎのコマンドを実行してGCRにイメージがプッシュされているか確認してください。

$ gcloud container images list-tags gcr.io/$PROJECT_ID/helloworld-go

kubectl logs build-kaniko-helloworld-gcr-pod-e686b3(人によってe686b3の部分は異なります)を実行するとPodで複数のコンテナが動いていることが確認できます。-cオプションでそれぞれのコンテナを指定するとコンテナのログも確認できます。

確認ができたらいったん登録したTaskTaskRunを削除してください。

$ kubectl delete -f taskrun-build-kaniko-helloworld-gcr.yaml
$ kubectl delete -f https://raw.githubusercontent.com/tektoncd/catalog/master/kaniko/kaniko.yaml

参考

戻る | 次へ