fbpx

Istio Ingress入門:Kubernetesアプリのトラフィックを簡単に管理する方法 #docker #mirantis #kubernetes #k8s

この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。

本ブログは Mirantis社の blog記事「Introduction to Istio Ingress: The easy way to manage incoming Kubernetes app traffic」の翻訳記事です。

Istio はオープンソースのクラウドネイティブなサービスメッシュコンポーネントです。
アプリケーションデプロイの複雑さを軽減し、分散アプリケーション間でトラフィックがどのようにルーティングされるかを可視化して制御することで、開発チームの負担を軽減します。

Istio Ingress は、クラスタが受信トラフィックを処理するための Istio のサブセットです。 ingress はクラスタ全体を外部に公開させず安全にアプリケーションのみを公開します。アプリケーションの受信トラフィックを処理する部分だけを外部に公開して、そのトラフィックを内部のアプリケーションにルーティングしています。

これは Kubernetes の新しい概念ではありません。すでに利用した経験がある方は Kubernetes Ingressオブジェクトに慣れ親しんでいるかもしれません。Istio Ingress はこれをさらに一歩進めて、ルート、ヘッダー、IPアドレスなどに基づいてルーティングルールを追加できます。ルーティングにより、A/Bテスト、カナリアデプロイ、IPブラック/ホワイトリスト化などの概念を実装する機会が得られます。

それでは、Istio Ingress の使い方を見ていきましょう。

Istio の UCP への統合

Istio は互換性のある Kubernetes クラスタにインストールできます。ここでは Docker Enterprise の Universal Control Plane (UCP) を使った使い方を見てみましょう。

( Docker Enterprise をインストールしていない場合は、こちらから無料トライアルを入手できます。)

Docker Enterprise 3.1 には UCP 3.3.0 が含まれており、これには Kubernetes クラスタの Istio Ingress を簡単に利用する機能が含まれています。

Docker Enterprise 3.1でIstio Ingressを有効化するには、次の手順を実行します。

1. UCP ユーザインタフェースにログインします。
2. < ユーザ名 > → Admin Settings → Ingress を順にクリックします。 ( Getting Started の指示に従っている場合は、admin → Admin Settings → Ingress となります)
3. Kubernetes の下で、スライダーをクリックして Ingress for Kubernetes を有効にします。

次にプロキシを設定して、 Kubernetes が Istio Ingress にどのポートを使用するかを設定する必要があります。(本番環境の場合、通常はクラウドプロバイダーが作成したロードバランサーを介してサービスを公開しますが、今回は Ingress がどのように動作するかに焦点を当てています。)

4. HTTPリクエストを受信するための特定のポートを設定し、必要に応じてUCPサーバーの External IP を追加して、 Save をクリックして設定を保存します。

数秒で構成が適用され、UCP は Istio Ingress を動かすサービスをデプロイします。
設定を適用して、Istio Ingress の機能を利用する準備ができました。

次に利用する方法を見てみましょう。

サンプルアプリーケーションをデプロイする

次のステップは、サンプルアプリケーションを Kubernetes クラスタにデプロイし、 Istio Ingress 経由で公開することです。例として、HTTPリクエストをテストできるシンプルな httpbin アプリを使用します。このステップを実行するには、UI経由とCLI経由の2つの方法があります。どちらを使うかは好みによりますが、どちらの方法でも同じことができます。この記事では両方の方法を説明します。

UCP の UI からアプリケーションをデプロイする

UI を使ってアプリケーションをインストールするには、 Docker Enterprise にログインして以下の手順に従います。

1. Kubernetes → Create と遷移します。

2. default の namespace を選択し、次のYAMLをエディタに貼り付けます。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/asankov/httpbin:1.0
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80

3. Create をクリックします。

この YAML は、 Kubernetes に1つの httpbin を実行する Deployment を作成し、クラスタ内で静的IPとドメイン名を作成するための Service と、アプリケーションを実行するための ServiceAccount を作成するように指示します。

これでアプリケーションがクラスタ内で動作するようになりましたが、アプリケーションを外部に公開しなければなりません。

Istio Gateway の作成

最初のステップは、 Kubernetes クラスタに入ってくるすべてのトラフィックのエントリポイントとなる Istio Gateway を作成することです。そのためには、以下の手順に従います。

1. Kubernetes → Ingress と遷移します。

2. Gateways → Create とクリックし、 httpbin-gateway という名前の Gatewayオブジェクトを作成します。 Gateway名は任意です。後で作成する Virtual Services を Gateway へ接続するために使用します。

3. 下にスクロールして「Add Server」をクリックして、ポート 80 とすべてのホスト (*) の HTTP サーバーを追加し、ポートに gateway-port などの名前を付けます。

4. Generate YML をクリックします。
5. default namespace を選択します。

6. Create をクリックします。

これで Gateway が作成されました。次に Virtual Service を作成する必要があります。

Virtual Service のデプロイ

Virtual Service は、配置したい実際のルーティングロジックを処理する為のもう一つの Istio 構成です。作成するには、以下の手順に従います。

1. Kubernetes → Ingress と遷移します。

2. Virtual Services → Create とクリックし、すべてのホストからのリクエストを受け付ける httpbin-vs という新しいサービスを作成し、前のセクションで作成した httpbin-gateway にリンクします。

3. Generate YML をクリックします。

4. default namespace を選択します。

5. Create をクリックし、Virtual Service 画面に遷移します。

6. 先程作成した Virtual Service を選択し、歯車アイコンをクリックして編集し、最初のルーティングを追加します。 (これはサービスを作成する前に行うこともできます)。

7. Virtual Service 設定の YAML エディターが表示されます。Virtual Service を使用できるようになる前に、ルーティング情報を追加するためにいくつかの調整をする必要があります。この場合、すべてのリクエスト (/) を受け取り、ポート 8000 で公開されている httpbin サービスに送信するルートを作成します。

...
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: httpbin
        port:
          number: 8000

最終的に、Virtual Service の設定は次のようになります。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  generation: 1
  name: httpbin-vs
spec:
  gateways:
  - httpbin-gateway
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: httpbin
        port:
          number: 8000

8. Save をクリックして、サービスに変更を加えます。これでサービスにアクセスできるようになりました。そのためには、 Istio Ingress を設定したときに指定したプロキシのブラウザを開きます。

<PROTOCOL>://<IP_ADDRESS>:<NODE_PORT>

今回のプロキシの設定は次のようになりました。

サービスを HTTPプロトコルとして設定したので、今回の環境でのURLは次の様になります。

http://34.219.89.235:33000

CLI からアプリケーションをデプロイする

CLI経由で UCP と通信するには、まずクライアントバンドルをダウンロードし、環境スクリプトを実行して現在のクラスタを指すように kubectl を設定する必要があります。(その方法については、チュートリアルのGetting started(日本語訳)で説明しています)。

これでビルドを始める準備が整いました。

1. アプリの deployment、service account、service などを作成することから始めます。

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/asankov/httpbin:1.0
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80
EOF

2. 次に、通信を受け入れるゲートウェイを作成します。

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP
EOF

3. ここで、アプリケーションの Pod への ingress トラフィックのルーティングを担当する Virtual Service を作成します。

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  generation: 1
  name: httpbin-vs
spec:
  gateways:
  - httpbin-gateway
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: httpbin
        port:
          number: 8000
EOF

これで、アプリケーションのすべての設定が完了しました。

Istio Ingress を利用した blue/green デプロイメントの設定

前の例では、Istio Ingress 経由でアプリケーションを公開して単純なルーティングを行う方法を見ましたが、Istio Ingress はそれよりもはるかに強力です。これらの機能をさらに掘り下げてみましょう。

このケースでは、Istio Ingress を介して カナリアデプロイ (blue/green) を行うシナリオを探っていきます。

カナリアデプロイでは、アプリケーションの 2 つのバージョンを並べてデプロイし、新しいバージョンを一部のクライアントにのみ提供します。この方法では、すべてのエンドユーザーに見せることなく、新しいバージョンに関するメトリクスを収集できます。新しいバージョンですべてが問題ないと判断した場合は、全員にロールアウトします。逆に、問題が見つかればロールバックします。

このシナリオを探求するために、まずアプリケーションの2番目のバージョンをデプロイする必要があります。 そのために、少し修正したバージョンの httpbin を用意しました。メインページのヘッダに httpbin.org V2 と書かれている以外はすべて同じです。

新しいアプリケーションをクラスタにデプロイするには、以下の手順に従ってください。

1. Docker Entperirse の UCP にログインします。
2. Kubernetes → Create と遷移します。
3. default namespace を選択してください
4. 次の YAML をエディタに貼り付け、 Create をクリックします

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v2
  template:
    metadata:
      labels:
        app: httpbin
        version: v2
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/asankov/httpbin:2.0
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80

これで、httpbin の V1 と V2 がクラスタ内で並んで動作するようになりました。デフォルトでは、 Kubernetes はラウンドロビンのロードバランシングを行いますので、約50%のユーザーが V1 を見て、残りの50%のユーザーが V2 を見ることになります。これはアプリケーションのページをリロードすることで確認できます。

しかし、Canary デプロイメントを行うときには、通常、新しいバージョンを見るユーザーの割合をもっと小さくしたいと考えます。

各バージョンに行くトラフィックの割合を制御するために、Destination Rule を作成する必要があります。これは、 V1 と V2 を区別するために使用する Istio の構成です。

そのためには、以下の手順に従います。

1. Docker Entperirse の UCP にログインします。
2. Kubernetes → Create と遷移します。
3. default namespace を選択してください
4. 次の YAML をエディタに貼り付け、 Create をクリックします

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin-destination-rule
spec:
  host: httpbin
  subsets:
  - name: 'v1'
    labels:
      version: 'v1'
  - name: 'v2'
    labels:
      version: 'v2'

アプリケーションの異なるバージョンを指す2つの異なるサブセットを作成しました。

  1. 次に、新しく作成した Destination Rule を利用するために、既存の Virtual Service を編集する必要があります。Kubernetes → Ingress と遷移し、 Virtual Services をクリックします。
  2. リストの中から Virtual Service を見つけて(この時点では1つしかないはずです)、歯車のアイコンをクリックして Edit をクリックします。
  3. service が以下の YAML のようになるように、http プロパティの内容を編集し Save をクリックします。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin-vs
spec:
  gateways: 
  - httpbin-gateway
  hosts:
  - '*'
  http:
  - route:
    - destination:
        host: httpbin
        subset: 'v1'
      weight: 70
    - destination:
        host: httpbin
        subset: 'v2'
      weight: 30

前のステップで作成したサブセットのそれぞれに、ルーティングで特定のweightが追加されていることに注目してください。URLにアクセスしてページを更新すると、10回のうち約7回は V1 、残りの3回は V2 が表示されます。

以上の操作によって、現時点では70-30の比率で canary デプロイに成功しています。次のステップは、 V2 のウェイトが100%になるまで、新しいバージョンを参照するユーザーの割合を徐々に増やしていくことです。全てのユーザが新しいバージョンを参照する状態になれば、旧バージョンを完全に削除できます。

次のステップ

この時点で、Istio Ingress を使用してアプリケーションを安全に公開し、トラフィックの流れを制御して canary のデプロイなどのシナリオを作成するためのルーティングルールを作成する方法がわかりました。

より複雑な状況を実装するには、これらのテクニックを使用して、今回のケースと同じようにカスタム・ルーティング・ルールを作成できます。

Istio Ingress のライブデモを見るには、このビデオをチェックしてください。

Docker Enterprise 3.1 の新機能について知りたい場合は、Docker Enterprise 3.1 正式リリース! もご覧ください。

新規CTA