DigitalOceanKubernetesでAmbassadorを使用してAPIゲートウェイを作成する方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
Ambassador は、クラウドネイティブアプリケーション用のAPIゲートウェイであり、異種サービス間でトラフィックをルーティングし、分散型ワークフローを維持します。 単一のエントリポイントとして機能し、サービスディスカバリ、構成管理、ルーティングルール、レート制限などのタスクをサポートします。 それはあなたのサービスに大きな柔軟性と設定の容易さを提供します。
Envoy は、クラウドネイティブアプリケーション向けに設計されたオープンソースのサービスプロキシです。 Kubernetesでは、Ambassadorを使用してEnvoy構成をインストールおよび管理できます。 Ambassadorは、ダウンタイムなしの構成変更と、認証、サービスディスカバリ、サービスメッシュなどの他の機能との統合をサポートします。
このチュートリアルでは、Helmを使用してKubernetesクラスターにAmbassador API Gatewayをセットアップし、ルーティングルールに基づいて着信トラフィックをさまざまなサービスにルーティングするように構成します。 ホスト名または関連するサービスへのパスに基づいてトラフィックをルーティングするように、これらのルールを構成します。
前提条件
このガイドを開始する前に、次のものが必要です。
- kubectlが構成されたDigitalOceanKubernetesクラスター。 DigitalOceanでKubernetesクラスタを作成するには、Kubernetesクイックスタートをご覧ください。
- ローカルマシンにインストールされているHelmパッケージマネージャーと、クラスターにインストールされているTiller。 HelmPackageManagerを使用してKubernetesクラスターにソフトウェアをインストールする方法のステップ1と2を完了します
- 少なくとも2つのAレコードが構成された完全に登録されたドメイン名。 このチュートリアルでは、全体を通して
svc1.your-domain、svc2.your-domain、およびsvc3.your-domainを使用します。 DNSクイックスタートに従って、DigitalOceanにレコードを設定できます。
ステップ1—アンバサダーのインストール
このセクションでは、KubernetesクラスターにAmbassadorをインストールします。 Ambassadorは、Helmチャートを使用するか、YAML構成ファイルをkubectlコマンドに渡すことでインストールできます。
注:DigitalOceanKubernetesではデフォルトでRBACが有効になっているため、インストールにYAML構成ファイルを使用する場合は、RBACが有効な構成ファイルを使用する必要があります。 Ambassadorのドキュメントで、YAMLを介したAmabassadorのKubernetesへのデプロイの詳細を確認できます。
このチュートリアルでは、 Helm チャートを使用して、Ambassadorをクラスターにインストールします。 前提条件を満たしたら、Helmをクラスターにインストールします。
まず、次のコマンドを実行して、Helm経由でAmbassadorをインストールします。
helm upgrade --install --wait ambassador stable/ambassador
次のような出力が表示されます。
OutputRelease "ambassador" does not exist. Installing it now. NAME: ambassador LAST DEPLOYED: Tue Jun 18 02:15:00 2019 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE ambassador 3/3 3 3 2m39s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE ambassador-7d55c468cb-4gpq9 1/1 Running 0 2m38s ambassador-7d55c468cb-jr9zr 1/1 Running 0 2m38s ambassador-7d55c468cb-zhm7l 1/1 Running 0 2m38s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer 10.245.183.114 139.59.52.164 80:30001/TCP,443:31557/TCP 2m40s ambassador-admins ClusterIP 10.245.46.43 <none> 8877/TCP 2m41s ==> v1/ServiceAccount NAME SECRETS AGE ambassador 1 2m43s ==> v1beta1/ClusterRole NAME AGE ambassador 2m41s ==> v1beta1/ClusterRoleBinding NAME AGE ambassador 2m41s ==> v1beta1/CustomResourceDefinition NAME AGE authservices.getambassador.io 2m42s consulresolvers.getambassador.io 2m41s kubernetesendpointresolvers.getambassador.io 2m42s kubernetesserviceresolvers.getambassador.io 2m43s mappings.getambassador.io 2m41s modules.getambassador.io 2m41s ratelimitservices.getambassador.io 2m42s tcpmappings.getambassador.io 2m41s tlscontexts.getambassador.io 2m42s tracingservices.getambassador.io 2m43s . . .
これにより、Kubernetesクラスターノードが接続されたAmbassadorデプロイメント、サービス、およびロードバランサーが作成されます。 ドメインのAレコードにマップするには、ロードバランサーのIPが必要です。
アンバサダーロードバランサーのIPアドレスを取得するには、次のコマンドを実行します。
kubectl get svc --namespace default ambassador
次のような出力が表示されます。
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer your_cluster_IP your-IP-address 80:30001/TCP,443:31557/TCP 8m4s
この手順で外部IPyour-IP-addressをメモし、ドメインを(ドメインプロバイダー経由で)svc1.your-domain、svc2.your-domain、およびsvc3.your-domainをマップしてこのIPアドレスを指すようにします。 。
SSLターミネーションの構成方法に記載されている手順を使用して、DigitalOceanロードバランサーでHTTPSを有効にできます。 ロードバランサーを介してTLSターミネーションを構成することをお勧めします。 TLSターミネーションを設定する別の方法は、AmbassadorのTLSサポートを使用することです。
Helmを使用してKubernetesクラスターにAmbassadorをインストールしました。これにより、デフォルトの名前空間に3つのレプリカを持つAmbassadorデプロイメントが作成されました。 これにより、すべてのトラフィックをAPIGatewayにルーティングするためのパブリックIPを備えたロードバランサーも作成されました。 次に、このAPIゲートウェイのテストに使用する3つの異なるサービスのKubernetesデプロイを作成します。
ステップ2—Webサーバー展開のセットアップ
このセクションでは、3つの異なるWebサーバーコンテナを実行するための3つのデプロイメントを作成します。 3つの異なるウェブサーバーコンテナのKubernetesデプロイの定義を使用してYAMLファイルを作成し、kubectlを使用してデプロイします。
好みのテキストエディタを開いて、NginxWebサーバーの最初のデプロイメントを作成します。
nano svc1-deploy.yaml
ファイルに次のyaml構成を入力します。
svc1-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: svc1
spec:
replicas: 1
selector:
matchLabels:
app: nginx
name: svc1
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: nginx
name: svc1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- name: http
containerPort: 80
ここでは、[X118X]と呼ばれる1レプリカでデプロイされるnginx:latestコンテナイメージを使用してKubernetesDeploymentを定義しました。 Deploymentは、ポート80でクラスター内を公開するように定義されています。
ファイルを保存して閉じます。
次に、次のコマンドを実行して、この構成を適用します。
kubectl apply -f svc1-deploy.yaml
作成を確認する出力が表示されます。
Outputdeployment.extensions/svc1 created
次に、2番目のWebサーバーデプロイメントを作成します。 svc2-deploy.yamlというファイルを次のファイルで開きます。
nano svc2-deploy.yaml
ファイルに次のYAML構成を入力します。
svc2-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: svc2
spec:
replicas: 1
selector:
matchLabels:
app: httpd
name: svc2
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: httpd
name: svc2
spec:
containers:
- name: httpd
image: httpd:latest
ports:
- name: http
containerPort: 80
ここでは、svc2と呼ばれる1レプリカとともにデプロイされるhttpdコンテナイメージを使用してKubernetesDeploymentを定義しました。
ファイルを保存して閉じます。
次のコマンドを実行して、この構成を適用します。
kubectl apply -f svc2-deploy.yaml
次の出力が表示されます。
Outputdeployment.extensions/svc2 created
最後に、3番目の展開では、svc3-deploy.yamlファイルを開いて作成します。
nano svc3-deploy.yaml
次の行をファイルに追加します。
svc3-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: svc3
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
name: svc3
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: httpbin
name: svc3
spec:
containers:
- name: httpbin
image: kennethreitz/httpbin:latest
ports:
- name: http
containerPort: 80
ここでは、svc3と呼ばれる1レプリカとともにデプロイされるhttpbinコンテナイメージを使用してKubernetesDeploymentを定義しました。
ファイルを保存して閉じます。
最後に、次のコマンドを実行して適用します。
kubectl apply -f svc3-deploy.yaml
そして、次の出力が表示されます。
Outputdeployment.extensions/svc3 created
Kubernetesデプロイを使用して3つのウェブサーバーコンテナをデプロイしました。 次のステップでは、これらの展開をインターネットトラフィックに公開します。
ステップ3—アンバサダーアノテーション付きのサービスを使用してアプリを公開する
このセクションでは、ウェブアプリをインターネットに公開し、アンバサダーアノテーションを使用してKubernetesサービスを作成し、トラフィックをそれらにルーティングするルールを構成します。 Kubernetesのアノテーションは、オブジェクトにメタデータを追加する方法です。 アンバサダーは、サービスからのこれらのアノテーション値を使用して、ルーティングルールを構成します。
念のため、ドメイン(svc1.your-domain、svc2.your-domain、svc3.your-domainなど)をDNSレコードのロードバランサーのパブリックIPにマッピングする必要があります。
次のファイルを作成して開くことにより、Ambassadorアノテーションを使用してsvc1デプロイ用のKubernetesサービスを定義します。
nano svc1-service.yaml
注:マッピング名は、すべてのAmbassadorアノテーションブロックで一意である必要があります。 マッピングはすべての注釈ブロックの識別子として機能し、繰り返されると古い注釈ブロックとオーバーラップします。
svc1-service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc1
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: svc1-service_mapping
host: svc1.your-domain
prefix: /
service: svc1:80
spec:
selector:
app: nginx
name: svc1
ports:
- name: http
protocol: TCP
port: 80
このYAMLコードでは、ホスト名svc1.your-domainをこのサービスにマッピングするために、Ambassadorアノテーションを使用してKubernetesサービスsvc1を定義しました。
svc1-service.yamlを保存して終了し、次を実行してこの構成を適用します。
kubectl apply -f svc1-service.yaml
次の出力が表示されます。
Outputservice/svc1 created
アンバサダーアノテーションを使用して、svc2デプロイ用の2番目のKubernetesサービスを作成します。 これは、Ambassadorを使用したホストベースのルーティングの別の例です。
svc2-service.yaml
次の構成をファイルに追加します。
svc2-service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc2
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: svc2-service_mapping
host: svc2.your-domain
prefix: /
service: svc2:80
spec:
selector:
app: httpd
name: svc2
ports:
- name: http
protocol: TCP
port: 80
これをsvc2-service.yamlとして保存します。 ここでは、Ambassadorがhostヘッダー値をsvc2.your-domainとしてリクエストを受信したときに、トラフィックをsvc2にルーティングするために、Ambassadorアノテーションを使用して別のKubernetesサービスを定義しました。 したがって、このホストベースのルーティングでは、サブドメインsvc2.your-domainにリクエストを送信できます。これにより、トラフィックがサービスsvc2にルーティングされ、httpdWebサーバーからリクエストが処理されます。 。
このサービスを作成するには、次を実行します。
kubectl apply -f svc2-service.yaml
次の出力が表示されます。
Outputservice/svc2 created
svc3デプロイメント用に3番目のKubernetesサービスを作成し、パスsvc2.your-domain/binを介してサービスを提供します。 これにより、Ambassadorのパスベースのルーティングが構成されます。
svc3-service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc3
spec:
selector:
app: httpbin
name: svc3
ports:
- name: http
protocol: TCP
port: 80
これをsvc3-service.yamlとして保存し、以下を実行して構成を適用します。
kubectl apply -f svc3-service.yaml
出力は次のようになります。
Outputservice/svc3 created
svc2-service.yamlを編集して、/binをsvc3サービスにルーティングする2番目のアンバサダーアノテーションブロックを追加します。
nano svc2-service.yaml
svc2-service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc2
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: svc2-service_mapping
host: svc2.your-domain
prefix: /
service: svc2:80
---
apiVersion: ambassador/v1
kind: Mapping
name: svc3-service_mapping
host: svc2.your-domain
prefix: /bin
service: svc3:80
spec:
selector:
app: httpd
name: svc2
ports:
- name: http
protocol: TCP
port: 80
2番目のAmbassadorアノテーションブロックを追加して、/binで始まるパスをsvc3Kubernetesサービスにマッピングするように構成しました。 svc2.your-domain/binのリクエストをsvc3にルーティングするために、ここに2番目のアノテーションブロックをホスト値svc2.your-domainとして追加しました。これは、両方のブロックで同じです。 したがって、パスベースのルーティングを使用すると、svc2.your-domain/binにリクエストを送信できます。このリクエストは、サービスsvc3によって受信され、このチュートリアルのhttpbinアプリケーションによって提供されます。
次に、以下を実行して変更を適用します。
kubectl apply -f svc2-service.yaml
次の出力が表示されます。
Outputservice/svc2 configured
3つのデプロイ用にKubernetesサービスを作成し、Ambassadorアノテーションを使用してホストベースおよびパスベースのルーティングルールを追加しました。 次に、これらのサービスに高度な構成を追加して、ルーティング、リダイレクト、およびカスタムヘッダーを構成します。
ステップ4—ルーティング用の高度なアンバサダー構成
このセクションでは、ヘッダーの変更およびリダイレクトの構成を行うために、さらにアンバサダーアノテーションを使用してサービスを構成します。
curlドメインsvc1.your-domainを確認し、応答ヘッダーを確認します。
curl -I svc1.your-domain
出力は次のようになります。
OutputHTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 21:41:00 GMT content-type: text/html content-length: 612 last-modified: Tue, 21 May 2019 14:23:57 GMT etag: "5ce409fd-264" accept-ranges: bytes x-envoy-upstream-service-time: 0
この出力は、Ambassadorを使用してルーティングされたサービスから受信したヘッダーを示しています。 Ambassadorアノテーションを使用して、サービスレスポンスにカスタムヘッダーを追加し、新しく追加されたヘッダーの出力を検証します。
サービス応答にカスタムヘッダーを追加するには、応答からヘッダーx-envoy-upstream-service-timeを削除し、svc1の新しい応答ヘッダーx-geo-location: Indiaを追加します。 (要件に応じて、このヘッダーを変更できます。)
ファイルsvc1-service.yamlを編集します。
nano svc1-service.yaml
次の強調表示された行で注釈を更新します。
svc1-service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc1
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: svc1-service_mapping
host: svc1.example.com
prefix: /
remove_response_headers:
- x-envoy-upstream-service-time
add_response_headers:
x-geo-location: India
service: svc1:80
spec:
selector:
app: nginx
name: svc1
ports:
- name: http
protocol: TCP
port: 80
ここでは、svc1サービスを変更して、x-envoy-upstream-service-timeを削除し、HTTP応答にx-geo-location: Indiaヘッダーを追加しました。
行った変更を適用します。
kubectl apply -f svc1-service.yaml
次の出力が表示されます。
Outputservice/svc1 configured
次に、curlを実行して、サービス応答の更新されたヘッダーを検証します。
curl -I svc1.your-domain
出力は次のようになります。
OutputHTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 21:45:26 GMT content-type: text/html content-length: 612 last-modified: Tue, 21 May 2019 14:23:57 GMT etag: "5ce409fd-264" accept-ranges: bytes x-geo-location: India
次に、svc3-service.yamlを編集して、ホスト名svc3.your-domainの要求をパスsvc2.your-domain/binにリダイレクトします。
nano svc3-service.yaml
次のYAMLに示すように、Ambassadorアノテーションブロックを追加して保存します。
svc3-service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc3
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Mapping
name: redirect_mapping
host: svc3.your-domain
prefix: /
service: svc2.your-domain
host_redirect: true
path_redirect: /bin
spec:
selector:
app: httpbin
name: svc3
ports:
- name: http
protocol: TCP
port: 80
host_redirect: trueを追加して、ホスト名svc3.your-domainのsvc3からsvc2.your-domain/binへの301リダイレクト応答を構成しました。 host_redirectパラメーターは、301リダイレクト応答をクライアントに送信します。 設定されていない場合、リクエストは301HTTP応答ではなく200HTTP応答を受信します。
次に、次のコマンドを実行して、これらの変更を適用します。
kubectl apply -f svc3-service.yaml
次のような出力が表示されます。
Outputservice/svc3 configured
curlを使用して、svc3.your-domainの応答を確認できるようになりました。
curl -I svc3.your-domain
出力は次のようになります。
OutputHTTP/1.1 301 Moved Permanently location: http://svc2.your-domain/bin date: Mon, 17 Jun 2019 21:52:05 GMT server: envoy transfer-encoding: chunked
出力は、サービスsvc3.your-domainに対するリクエストの応答のHTTPヘッダーであり、サービスアノテーションのhost_redirect: trueの構成がHTTPステータスコード301 Moved Permanentlyを正しく提供していることを示しています。
HTTPヘッダーを変更し、リダイレクトを構成するために、Ambassadorアノテーションを使用してサービスを構成しました。 次に、AmbassadorAPIGatewayサービスにグローバル構成を追加します。
ステップ5—アンバサダーグローバル構成のセットアップ
このセクションでは、Ambassadorサービスを編集して、グローバルGZIP圧縮構成を追加します。 GZIP圧縮は、HTTPアセットのサイズを圧縮し、ネットワーク帯域幅の要件を減らして、Webクライアントの応答時間を短縮します。 この構成は、AmbassadorAPIGatewayを介してルーティングされるすべてのトラフィックに影響します。 同様に、Ambassadorを使用して他のグローバルモジュールを構成できます。これにより、Ambassadorの特別な動作をグローバルレベルで有効にできます。 これらのグローバル構成は、Ambassadorサービスへのアノテーションを使用して適用できます。 詳細については、アンバサダーのグローバル構成のドキュメントを参照してください。
次のkubectl editコマンドは、デフォルトのエディターであるvimを開きます。 たとえば、nanoを使用するには、環境変数KUBE_EDITORをnanoに設定できます。
export KUBE_EDITOR="nano"
アンバサダーサービスを編集します。
kubectl edit service ambassador
次に、強調表示された行をGZIP圧縮用の新しい注釈ブロックに追加します。
アンバサダーサービスの編集
apiVersion: v1
kind: Service
metadata:
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v1
kind: Module
name: ambassador
config:
service_port: 8080
---
apiVersion: ambassador/v0
kind: Module
name: ambassador
config:
gzip:
memory_level: 5
min_content_length: 256
compression_level: BEST
compression_strategy: DEFAULT
content_type:
- application/javascript
- application/json
- text/html
- text/plain
disable_on_etag_header: false
remove_accept_encoding_header: false
creationTimestamp: "2019-06-17T20:45:04Z"
labels:
app.kubernetes.io/instance: ambassador
app.kubernetes.io/managed-by: Tiller
app.kubernetes.io/name: ambassador
helm.sh/chart: ambassador-2.8.2
name: ambassador
namespace: default
resourceVersion: "2153"
. . .
AmbassadorアノテーションブロックをAmbassadorサービスに追加し、APIGateway用にGZIPをグローバルに構成しました。 ここには、memory_levelで使用される内部メモリの量を制御するための構成が含まれています。これは1から9までの値にすることができます。 BESTに設定されたcompression_levelは、より高いレイテンシーを犠牲にして、より高い圧縮率を保証します。 min_content_lengthを使用して、最小応答長を256バイトに構成しました。 content_typeには、圧縮を生成するメディアタイプ(以前のMIMEタイプ)のセットが具体的に含まれています。 最後に、圧縮を可能にするために、最後の2つの構成をfalseとして追加しました。
GZIP圧縮の詳細については、EnvoyのGZIPページを参照してください。
このサービスの変更は、APIゲートウェイのグローバル構成として適用されます。
エディターを終了すると、次のような出力が表示されます。
Outputservice/ambassador edited
値gzipを持つcontent-encodingヘッダーについて、curlを使用してsvc1.your-domainを確認します。
curl --compressed -i http://svc1.example.com
出力は次のようになります。
OutputHTTP/1.1 200 OK
server: envoy
date: Mon, 17 Jun 2019 22:25:35 GMT
content-type: text/html
last-modified: Tue, 21 May 2019 14:23:57 GMT
accept-ranges: bytes
x-geo-location: India
vary: Accept-Encoding
content-encoding: gzip
transfer-encoding: chunked
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
ここでは、受信した応答のcontent-encodingがgzip圧縮されていることを示す応答ヘッダーを含むNginxのデフォルトのHTMLページを見ることができます。
アンバサダーにグローバル構成を追加して、APIゲートウェイ全体で選択したコンテンツタイプの応答に対してGZIP構成を有効にしました。
結論
これで、Ambassadorを使用してKubernetesクラスターのAPIゲートウェイが正常にセットアップされました。 ホストベースおよびパスベースのルーティング、カスタムヘッダー、グローバルGZIP圧縮を使用してアプリを公開できるようになりました。
アンバサダーの注釈と構成パラメーターの詳細については、アンバサダーの公式ドキュメントを参照してください。