みなさんこんにちは、杉山です。花粉症に必死に抗う毎日ですが、気づいたら3月も残りわずかですね。同士のみなさん、がんばって乗り越えましょう!
さて今回は、私の前回記事:Amazon EKS 導入に続いて、少しだけ深堀りして Ingress の部分について書いてみたいと思います。
Amazon EKS の Ingress を考える
━ クラウドベンダーが提供するマネージド Kubernetes をやるということは、 Ingress を考えるということだ ━
このような言葉を、偉大なる先人の方に聞いたことがあります。(ないです)
EKS の構築について、当初は AWS Load Balancer Controller のみ利用して進めていました。その後、2023年末頃に Kubernetes の Gateway API が GA されたこともあって、そちらに舵を切ろうと考えていた時期もあり、実際 Ingress のことを考えている時間は長かったような気がします。
しかし、AWS での Gateway API 実装でもある VPC Lattice は、クラスター同士の通信に使うことを主たる用途としており、外部からのトラフィックを受ける Ingress としては活用できなさそうでした。(2024年3月現在)*1
個人的には、GKE が提供しているようなロール間の責任が明確に分離される構成にしたかったのですが、AWS ではちょっとまだ早い…ということで、他の手段を考えることに。参考までに、以下が GKE の提供しているものです。とても分かりやすいなーって思います。
さて、そんな紆余曲折を経て、最終的には AWS Load Balancer Controller (以下 ALBC) を利用したうえで、柔軟なトラフィックコントロールが可能となる Istio を利用することになりました。前述のとおり、ALBC は最初から利用してはいたのですが、マイクロサービスが追加される際に Namespace の分割を行うと、 Ingress の標準仕様では Namespace を跨いだルーティング設定が出来ません。なので「じゃあ Ingress を Namespace ごとに作成しよう」なんてことをすると、ALBC によって Ingress 単位で ALB が作成されてしまいます。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: # ここで指定した namespace 内のサービスのみパスベースルーティングに指定可能 namespace: service-A name: service-A-ingress annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/healthcheck-path: / alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:ap-northeast-1:123456789012:regional/webacl/xxxx-web-acl-ap-northeast-1-dev/xxxx-xxxx spec: # ここで alb と定義することで ALB が作成される ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: service-A port: number: 80
こういった背景もありながら、さらに今後のサービス拡大も見据えたとき、サービス間通信も発生するでしょうし、このタイミングで Service Mesh の恩恵を受けられるようにしておくのがベストだと考え、Istio を導入することにしました。Istio にした理由は、過去に運用経験のあるメンバーがいたり、最近認定試験が出たり、デファクトスタンダードになっていると感じているのもありますが、最後は「SRE としてお互いにがんばっていこう!」と会話しながら決めたのを覚えています。(脳内補正が入ってるかも…) 話し合いと納得感、大事ですね!私は毎日、色々と教えてもらっており、日々感謝です。
「あれ、AWS にしたのに、なんで App Mesh 使わないの?」という点については、最後まで悩んだのですが、ちょっとここでは書きづらいので、どこかでお話できたらと…苦笑
ALBC + Istio 全体構成
簡単な構成図は以下のとおりです。
全体構成としては、ALB Ingress から Istio Ingress Gatewy をターゲットとして構成し、ここまでを Gateway レイヤーとして定義して、アプリケーションへのルーティングには、 Istio Virtual Service を使用しています。 Virtual Service から各マイクロサービスの Service にルーティングさせることで、一つの ALB から各サービスへ流れていくような構成となりました。以下のドキュメントにある Shared gateway
のパターンです。
はじめは Istio Ingress Gateway をそのままプロビジョニングしたため、 Service type が LoadBalancer
になっており、 Internal な NLB が出来ていました…これもメンバーから「杉山さん、ナンデスカコレ」とありがたい指摘をいただき、急いで Istio Ingress Gateway を定義している Argo CD の values.yaml
に以下を追記…!持つべきものは頼れる仲間ですね。
# 一部抜粋... replicaCount: 2 autoscaling: enabled: true minReplicas: 2 maxReplicas: 4 # 急いで追記っっ service: type: NodePort
色々調べているとき、AWS 公式のブログも非常に参考になりましたので、こちらで紹介したいと思います。
構築してみる - ALBの作成 -
だいぶ細かくなってしまうのですが、実際のマニフェストから抜粋しつつ、続きを書いてみます。まず ALBC に ALB を作ってもらうため、以下のマニフェストを作成します。なお、ALBC 自体は Argo CD + Helm でインストールしています。(一部抜粋しているため、そのまま使うと動かない可能性があります)
# alb-istio-ingress-gateway.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: alb-istio-ingress-gateway namespace: istio-ingress annotations: # 一部抜粋... alb.ingress.kubernetes.io/group.name: istio-ingressgateway # istio ingress gateway service をターゲットとしてヘルスチェックを実施 alb.ingress.kubernetes.io/healthcheck-path: /healthz/ready alb.ingress.kubernetes.io/healthcheck-port: "15021" alb.ingress.kubernetes.io/healthcheck-protocol: HTTP alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxxxxx-xxxx-xxxxxxxxx alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06 alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:ap-northeast-1:123456789012:regional/webacl/xxx-wafv2-web-acl-ap-northeast-1/xxxxxxxx-xxxx-xxxxxxxxx spec: ingressClassName: alb rules: - http: paths: - path: /* pathType: ImplementationSpecific backend: service: name: istio-ingressgateway port: number: 80
Istio コアコンポーネントのインストール
次に、Istio のコアコンポーネントをインストールします。具体的には以下の3種類です。
istio-base
istiod
istio-ingress
これらも Argo CD + Helm で導入します。注意点としては、istio-ingress
のデプロイ時に istio-base
と istiod
が確実にデプロイされていないとエラーになることがある、というところでしょうか。Argo CD で 3種類のコンポーネントを一気に AutoSync させてしまい、依存関係が考慮されず、以下の Issues にあるように派手に転びました。
これで Istio Ingress Gateway のサービスが作成されます。このサービスを前述した Ingress で指定している形となります。( name: istio-ingressgateway
のところです)
Gateway リソースの作成
続いて Gateway リソースを作成します。これは Helm を利用せず、以下のようなマニフェストを定義します。ここでは Istio Ingress Gateway の Pod とバインディングされるよう、selector
にて istio: ingressgateway
を定義してあげます。
# sample-gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: sample-gateway namespace: istio-ingress spec: selector: istio: ingressgateway servers: - hosts: - "*" port: name: http number: 80 protocol: HTTP
作成したリソースは kubectl get gateway.networking.istio.io -n istio-ingress
のコマンドで見つけることが可能です。次は Virtual Service にトラフィックを転送させていく必要がありますが、以下のドキュメントにも記載されているように、Virtual Service が Gateway にバインドされることで、トラフィック転送を制御することが可能になっています。
The Gateway specification above describes the L4-L6 properties of a load balancer. A VirtualService can then be bound to a gateway to control the forwarding of traffic arriving at a particular host or gateway port.
実際の構築時には、ここまで構築するのに結構な時間が掛かってしまいました…Gateway のところが理解が難しく、ドキュメントを読んでいてもイマイチしっくり来なかったので、Virtual Service まで実際に作ってしまい、 Kiali を使って可視化しながら理解していきました。実際に手を動かして作ってしまうのも大切ですね…!
というわけで、ここまでで、以下のオレンジ枠内までが作成されました。最後は Virtual Service の作成です。
Virtual Service の作成
Virtual Service は各アプリケーション用マニフェストの方に定義しています。具体的には以下のような感じです。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: service-A-virtual-service namespace: service-A spec: hosts: - "*" gateways: # ここでGatewayを指定 - istio-ingress/sample-gateway http: - match: - uri: prefix: /api/v1/service-A route: - destination: host: service-A.service-A.svc.cluster.local port: number: 80
前述のとおり、Virtual Service を Gateway にバインドする必要があります。これは上記コメント箇所で Gateway を指定することで、バインドすることが可能です。ここまでで、無事にサービスまでトラフィックが流れるようになりました!
実際にやってみて
理解するまでは本当に大変でしたが、実際に構築して動かしていると、こんなに便利なものはない!というのが率直なところです。多くのサービスで Istio が利用されているのも納得しました。ただ、Kubernetes と違うサイクルでのバージョンアップ(半年ほど)があったり、Istio 自身も Gateway API の実装がベータ版で提供されていたりするので、これで終わりと満足せず、常にアップデートを追いかけ続けないといけないな、と感じています。ちょうど今、KubeCon + CloudNativeCon Europe 2024 も開催されていますし、ブログを拝見して追いかけているところです!
さいごに
今回は内製開発チームの Amazon EKS Ingress について紹介しました。ここは本当に肝になるところなので、SRE チームとしても Priority を上げて対応していきたいです!年内には Istio Gateway API 実装もベータから正式バージョンになりそうですし、今のうちに検証しておきたいですね。
私たちのチームは現在、積極的な採用活動を行っています!ご興味のある方は、ぜひ以下をご覧ください。
それでは、最後までお読みいただき、ありがとうございました!また次回の投稿でお会いしましょう!
*1:ご相談に乗っていただいた SA の方にはいつも感謝しかありません!ありがとうございます!