目標:GKEにデプロイし、AndroidのFlutterクライアント上からTLS通信を繋げる。
その際、Envoyプロキシを使う。
Envoyプロキシを使う理由
- モバイルクライアントで、クライアントが信用できないのでTLS終端をしたい。
- gRPCトラフィックを適切なKubernetes Serviceに転送する。
やり方
- Kubernetes ServiceをL4LBとして公開。 (ここにEXTERNAL_IPが払い出される)
- ServiceからL7LBであるEnvoyに転送する。
ヘルスチェックは必須。
クラスタを作り、Kubernetes Secret にcertを登録
APIの有効化
gcloud services enable container.googleapis.com
gcloud container clusters create envoy-grpc \
--enable-ip-alias \
--release-channel rapid \
--scopes cloud-platform \
--workload-pool <PROJECT_ID>.svc.id.goog \
--zone asia-northeast1-a
gcloud container clusters create envoy-grpc \
--enable-ip-alias \
--release-channel rapid \
--scopes cloud-platform \
--workload-pool gke-grpc-go.svc.id.goog \
--zone asia-northeast1-a
こんな感じのログがでたらよい
kubectl get serviceをしてみる
まだ外部IPがないことがわかる。
デプロイ
ArtifactRegistry
イメージ保管用のArtifactRegistryのロールを追加。
gcloud services enable artifactregistry.googleapis.com
リポジトリを作る
gcloud artifacts repositories create envoy-grpc-images \
--repository-format docker \
--location asia-northeast1
VMが使用するGoogleサービスアカウントにロールを付与する
PROJECT_NUMBER=$(gcloud projects describe <PROJECT_ID> --format 'value(projectNumber)')
gcloud artifacts repositories add-iam-policy-binding envoy-grpc-images \
--location asia-northeast1 \
--member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
--role roles/artifactregistry.reader
リポジトリのホスト名を認証ヘルパーエントリをCloudShellホームディレクトリのDocker構成ファイルに追加。
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
自己署名TLS証明書と秘密鍵を作る
openssl req -x509 -newkey rsa:4096 -nodes -sha256 -days 365 \
-keyout privkey.pem -out cert.pem -extensions san \
-config \
<(echo "[req]";
echo distinguished_name=req;
echo "[san]";
echo subjectAltName=DNS:grpc.example.com
) \
-subj '/CN=grpc.example.com'
自己署名TLS証明書を格納
kubectl create secret tls envoy-certs \
--key privkey.pem --cert cert.pem \
--dry-run=client --output yaml | kubectl apply --filename -
Skaffoldでコンテナイメージを作成し、それをリポジトリにPushして、アプリをGKEクラスタにデプロイする。
skaffold run \
--default-repo=asia-northeast1-docker.pkg.dev/<PROJECT_ID>/envoy-grpc-images \
--module=string-grpc \
--skip-tests
skaffold run --default-repo=asia-northeast1-docker.pkg.dev/gke-grpc-go/envoy-grpc-images --module=string-grpc --skip-tests
同様に、envoyもデプロイ
skaffold run \
--digest-source=none \
--module=envoy \
--skip-tests
この時点でgrpcurlしてみる。
EXTERNAL_IP=$(kubectl get service envoy \
--output=jsonpath='{.status.loadBalancer.ingress[0].ip}')
grpcurl -v -d '{"content": "["Hello", "World"]"}' -proto example.proto -authority grpc.example.com -cacert ../../cert.pem $EXTERNAL_IP:443 example.string/ProcessStrings
grpcurl -v -d '{"content": "["Hello", "World"]"}' -proto example.proto -authority 56ch.space 56ch.space:443 example.string/ProcessStrings
こんな感じのログが出たらよい
SSL通信
何らかの方法で鍵と証明書を入手し、envoy.yamlで指定された場所(コンテナ上に正しくマウントされるよう)に配置する。
最後。
Flutterアプリ上の設定を変える。
final channel = ClientChannel(
'<ドメイン>',
port: 443,
options: ChannelOptions(credentials: ChannelCredentials.secure(
authority: "<ドメイン>",
certificates: data.buffer.asInt8List(data.offsetInBytes,data.lengthInBytes)),
connectionTimeout: Duration(seconds: 100),
),
);
こんな感じでcredentialsの情報を書く