すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:イングレスゲートウェイを使用して mTLS ベースの gRPC サービスを構成する

最終更新日:Jan 13, 2025

イングレスゲートウェイを使用すると、相互 TLS (mTLS)プロトコルに基づく Google Remote Procedure Call (gRPC)サービスを構成できます。このセキュリティメカニズムにより、承認されたクライアントのみが gRPC サービスにアクセスできます。データ送信プロセス全体でエンドツーエンドの暗号化と双方向認証が実装され、盗聴、改ざん、不正アクセスから情報を効果的に保護します。

前提条件

背景情報

イングレスゲートウェイを使用して、ASM インスタンス内の gRPC サービスにトラフィックをルーティングできます。Service Mesh gRPC サービスは HTTP/2 プロトコル上に構築されています。これにより、TLS または mTLS プロトコルを使用して送信データを暗号化し、データセキュリティを確保できます。イングレスゲートウェイは、TLS または mTLS を使用した gRPC をサポートしています。暗号化された TCP データストリームがイングレスゲートウェイを通過するときに、TLS ターミネーションが実行されます。ASM インスタンス内のアプリケーションに TLS を構成する必要はありません。

手順

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

  1. ACK コンソール にログインします。左側のナビゲーションペインで、[クラスター] をクリックします。

  2. [クラスター] ページで、管理するクラスターを見つけ、その名前をクリックします。左側のペインで、[ワークロード] > [デプロイメント] を選択します。

  3. [デプロイメント] ページの上部にある [名前空間] ドロップダウンリストから名前空間を選択し、[YAML から作成] をクリックします。

  4. [作成] ページで、次の YAML コードをコードエディターにコピーし、[作成] をクリックします。

    展開して YAML コードを表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: istio-grpc-server-v1
      labels:
        app: istio-grpc-server
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: istio-grpc-server
          version: v1
      template:
        metadata:
          labels:
            app: istio-grpc-server
            version: v1
        spec:
          containers:
          - args:
            - --address=0.0.0.0:8080
            image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-server
            imagePullPolicy: Always
            livenessProbe:
              exec:
                command:
                - /bin/grpc_health_probe
                - -addr=:8080
              initialDelaySeconds: 2
            name: istio-grpc-server
            ports:
            - containerPort: 8080
            readinessProbe:
              exec:
                command:
                - /bin/grpc_health_probe
                - -addr=:8080
              initialDelaySeconds: 2
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: istio-grpc-server
      labels:
        app: istio-grpc-server
    spec:
      ports:
      - name: grpc-backend
        port: 8080
        protocol: TCP
      selector:
        app: istio-grpc-server
      type: ClusterIP
    ---
    説明

    サービス設定の ports フィールドの name パラメーターは、http2- または grpc- で始まる必要があります。そうでない場合、Istio はサービスプロトコルを識別できません。

手順 2:イングレスゲートウェイを作成する

この例では、デフォルトポート 443 を使用してサービスを公開します。詳細については、「イングレスゲートウェイの作成」をご参照ください。

手順 3:Istio ゲートウェイと仮想サービスを構成する

  1. ASM コンソール にログインします。左側のナビゲーションペインで、[service Mesh] > [メッシュ管理] を選択します。

  2. [メッシュ管理] ページで、構成する ASM インスタンスを見つけ、インスタンス名をクリックするか、管理[アクション] 列の をクリックします。

  3. Istio ゲートウェイを作成します。

    1. ASM インスタンスの詳細ページで、左側のナビゲーションペインの [ASM ゲートウェイ] > [ゲートウェイ] を選択します。

    2. [ゲートウェイ] ページで、[YAML から作成] をクリックします。

    3. [作成] ページで、デフォルト[名前空間] ドロップダウンリストから 作成 を選択し、次の YAML コードをコードエディターにコピーして、 をクリックします。

      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: gw-grpc-443
        namespace: default
      spec:
        selector:
          istio: ingressgateway
        servers:
          - hosts:
              - '*'
            port:
              name: https
              number: 443
              protocol: HTTPS
            tls:
              credentialName: example-credential
              mode: MUTUAL
                                      
  4. 仮想サービスを作成します。

    1. ASM インスタンスの詳細ページで、左側のナビゲーションペインの [トラフィック管理センター] > [virtualservice] を選択します。

    2. [virtualservice] ページで、[YAML から作成] をクリックします。

    3. [作成] ページで、デフォルト[名前空間] ドロップダウンリストから 作成 を選択し、次の YAML コードをコードエディターにコピーして、 をクリックします。

      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: grpc-vs
      spec:
        hosts:
        - "*"
        gateways:
        - gw-grpc-443
        http:
          - match:
              - port: 443
            route:
              - destination:
                  host: istio-grpc-server

手順 4:証明書を登録する

通常、gRPC クライアントには Subject Alternative Name (SAN)証明書が必要です。grpc-go に記載されている証明書を使用することをお勧めします。イングレスゲートウェイは証明書を必要とするため、証明書を ACK クラスターの istio-system 名前空間に登録します。

  • 1.17 より前のバージョンの ASM インスタンスの場合

    次のコマンドを実行して、istio-system 名前空間にシークレットを作成します。

    kubectl create -n istio-system secret generic example-credential --from-file=tls.key=server_key.pem --from-file=tls.crt=server_cert.pem --from-file=ca.crt=client_ca_cert.pem
    説明

    シークレット名は、Istio ゲートウェイで構成された credentialName と同じである必要があります。

  • バージョン 1.17 以降の ASM インスタンスの場合

    1. ASM コンソール にログインします。左側のナビゲーションペインで、[service Mesh] > [メッシュ管理] を選択します。

    2. [メッシュ管理] ページで、ASM インスタンスの名前をクリックします。左側のナビゲーションペインで、[ASM ゲートウェイ] > [証明書管理] を選択します。

    3. [証明書管理] ページで、[作成] をクリックします。[証明書情報] パネルで、必要なパラメーターを構成し、[OK] をクリックします。

手順 5:gRPC クライアントを起動する

この例では、mTLS を使用する gRPC クライアントが起動されます。詳細については、gRPC の公式 Web サイトを参照してください。

  1. 依存関係をインストールします。詳細については、「Go での gRPC のクイックスタート」をご参照ください。

  2. gRPC-go コードリポジトリをクローンします。詳細については、「gRPC-go」をご参照ください。

  3. /grpc-go/examples/helloworld/greeter_client/ パスの main.go ファイルの内容を次のコードに置き換え、address の値を ${イングレスゲートウェイの IP アドレス}:443 に変更します。

    展開してサンプルコードを表示

    /*
     *
     * Copyright 2015 gRPC authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    
    // Package main implements a client for Greeter service. // パッケージmainは、Greeterサービスのクライアントを実装します。
    package main
    
    import (
        "context"
        "crypto/tls"
        "crypto/x509"
        "flag"
        "io/ioutil"
        "log"
        "time"
    
        "google.golang.org/grpc"
        "google.golang.org/grpc/credentials"
        pb "google.golang.org/grpc/examples/helloworld/helloworld"
    )
    
    const (
        defaultName = "world"
    )
    
    var (
        addr       = flag.String("addr", "localhost:50051", "the address to connect to") // 接続先のアドレス
        name       = flag.String("name", defaultName, "Name to greet") // あいさつする名前
        cert       = flag.String("cert", "./data/x509/client_cert.pem", "server cert for mTLS") // mTLS用のサーバー証明書
        key        = flag.String("key", "./data/x509/client_key.pem", "server key for mTLS") // mTLS用のサーバーキー
        cacert     = flag.String("cacert", "./data/x509/ca_cert.pem", "ca cert for mTLS") // mTLS用のCA証明書
        servername = flag.String("servername", "x.test.example.com", "the cert name of server") // サーバーの証明書名
    )
    
    func main() {
        flag.Parse()
    
        certPair, err := tls.LoadX509KeyPair(*cert, *key)
        if err != nil {
            log.Fatalf("failed to load client cert: %v", err) // クライアント証明書の読み込みに失敗しました: %v
        }
    
        ca := x509.NewCertPool()
        caFilePath := *cacert
        caBytes, err := ioutil.ReadFile(caFilePath)
        if err != nil {
            log.Fatalf("failed to read ca cert %q: %v", caFilePath, err) // CA証明書 %q の読み込みに失敗しました: %v
        }
        if ok := ca.AppendCertsFromPEM(caBytes); !ok {
            log.Fatalf("failed to parse %q", caFilePath) // %q の解析に失敗しました
        }
    
        tlsConfig := &tls.Config{
            ServerName:   *servername,
            Certificates: []tls.Certificate{certPair},
            RootCAs:      ca,
        }
    
        conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
        if err != nil {
            log.Fatalf("did not connect: %v", err) // 接続できませんでした: %v
        }
        defer conn.Close()
        c := pb.NewGreeterClient(conn)
    
        // Contact the server and print out its response. // サーバーに接続して応答を出力します。
        ctx, cancel := context.WithTimeout(context.Background(), time.Second)
        defer cancel()
        r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
        if err != nil {
            log.Fatalf("could not greet: %v", err) // あいさつできませんでした: %v
        }
        log.Printf("Greeting: %s", r.GetMessage())
    }
                            
  4. examples パスに移動し、次のコマンドを実行します。

    go run helloworld/greeter_client/main.go

    予期される結果:

    Greeting: Hello World

    次の図に示すエラーが返された場合、証明書が無効です。上記の手順を実行して、証明書を再度登録してください。2