Container

AWSのKubernetesでサービスを公開する最高の方法~ALB,ACM,Route53の自動作成~

Kubernetesが流行っているので、これからEKSを使ってサービスを公開していこうと考えている方の参考になれば嬉しいです。
AWSのEKSを使って構築しています。

はじめに

EKSでサービスを公開したいけど、ロードバランサとか証明書とかの設定面倒くさいと考えている方が多いと思います。
今回の記事のゴールはymlファイルをKubernetesにデプロイするだけで、ALB作成、Route53にレコードセット追加、ACMの証明書をALBに割当の作業を自動でできるようにします。
EKSのGetting StartではCLB(Classic Load Balancer)を使用していますが、L7ロードバランサがいいのでALBで作成します。ホストベースでもパスベースでもどちらでもルーティングしてくれるので。。

本記事丁寧に説明するのですごく長くなりそうです。。。

(2019/02/04 追記)
EKSでHorizonalPodAutoscalerとEC2インスタンスのオートスケールも試しました!
AWSのKubernetesで オートスケール~EC2のオートスケールもやっちゃう~

アーキテクト

  • AWS ALB Ingress Controller
    ALBの自動デプロイをするいい感じのツール
    AWS ALB Ingress Controller をpodで起動しておくことで特定のannotationがついた Ingress リソースをみつけるとそのannotationの情報に応じて ALB を作成してくれます。
    https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/controller/config/

  • kube2iam
    PodからAWSリソースを操作するためのIAM権限の管理をするいい感じのツール
    https://github.com/jtblin/kube2iam

  • external-dns
    KubernetesのServiceやIngressをDNSプロバイダに対して同期するいい感じのツール
    条件にあったIngressやServiceリソースが作成された時に AWSであればRoute53でDNSレコードを作成してくれます。
    https://github.com/kubernetes-incubator/external-dns

やっていく

IAMロールの作成

3つのロールを準備する必要があります。

Worker Node用のIAMロール

まずはWorker Node用のIAMロールに対して権限を付与します。
eksctlを使ってクラスタを構築した場合、XXXXXXXX-NodeInstanceRole-YYYYYYYYYYYYという名前のロールが作成されます。

このロールに対してconfig/node-role-permission-policy.jsonのポリシーをアタッチします。

ALB用のIAMロール

config/ingress-iam-policy.json公式手順にあるポリシー をダウンロードしています。

external-dns用のIAMロール

ALB用のIAMロールと同じようにexternal-dns用のIAMロールも作成していきます。
config/route53-iam-policy.jsonファイルは次のようにしています。

以上で3つのIAMロールの準備ができました。

kube2iam

仕組み

ここであえて説明するとすれば AWS ALB Ingress Controller に付与するポリシーをどうするかです。
AWS ALB Ingress ControllerはALBの作成をしてくれるので、公式手順 だとこんな感じのポリシーが必要になります。

公式手順ではこのポリシーをノードのロールにアタッチしていますが、これをするとノード配下のPodに対しても同様の権限が与えられるというセキュリティ上恐ろしいことが起こってしまします。
そこでkube2iamを使ってノードに権限を与えるのではなくPodに権限を与えます。
類似プロダクトとしてkiamというものもあるみたいです。
Kubernetes(のアクセス管理機能)とIAMの間に入ってアクセス権限の管理を行ってくれるのが「kube2iam」や「kiam」です。

デプロイ

下記のmanufest.ymlファイルをデプロイするとDaemonsetでPodが各ノードで動きます。

デプロイコマンド

kube2iamのオプションパラメーター(args:)の意味は以下の通りです。

--auto-discover-base-arn
ロールのARNのベース部分(arn:aws:iam::XXXXXXX:role/)を自動検出します。

--iptables=true
「true」を指定した場合、ホスト(EC2)のiptablesに必要な設定を自動登録します。

--host-ip=$(HOST_IP)
「--iptables」を指定する場合は「--host-ip」もセットで必ず指定する必要があります。

--host-interface=eni+
「Getting Started」の手順に従ってEKS環境を構築した場合はPod Networkingとして「amazon-vpc-cni-k8s」が採用されるため、このオプションは「eni+」を指定する必要があります。

--verbose
詳細なログを出力します。

以上でkube2iamの準備は完了です。

AWS ALB Ingress Controller

続いてAWS ALB Ingress Controllerをやっていきます。

仕組み

  • ALB Ingress Controllerは、KubernetesのAPI ServerからのEventを監視し、該当のEvent を検知したらAWSのリソースを作成し始めます。
  • annotationを指定することで、サブネットやインターネット向けか内部向けかも決めることもできます。
  • リスナーは、ingressのannotationで指定したポート用に作成されます。ポートが指定されていない場合、80または443を使用。ACMも使用することもできます。
  • 入力リソースで指定された各パスに対してルールが作成され、特定のパスへのトラフィックが正しい KubernetesのService にルーティングされる。

とまあ、めちゃくちゃいろいろできて超便利です!

デプロイ

  • ALB の向き先となるターゲットグループは、ingressに記述されたServiceごとにAWSで作成。
    公式手順 通りにrbac-role.yamlファイルをデプロイします。

AWS ALB Ingress Controller本体をデプロイします。
[公式のymlファイル](https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/alb-ingress-controller.yaml" > alb-ingress-controller.yaml)をダウンロードして2箇所変更します。

--cluster-name=を自分のクラスタの名前に変更します。
alb-ingress-controller.yamlファイルの下記の部分のappの下に追記します。

ymlファイルを保存してデプロイします。

サブネットにタグを付与

AWS ALB Ingress Controllerは自動でクラスタのサブネットを見つけてくれるのですが、そのためにはPublicサブネットにタグを付与する必要があります。
Keyにkubernetes.io/role/alb-ingressを追加してValueは空。
Keyにkubernetes.io/role/elbを追加してValueは1にして保存。

これでAWS ALB Ingress Controllerの準備は完了です。

ACMの準備

example.comと*.example.comで証明書を取得してください。
手順はこちらを参考にしていただければと思います。

AWSで独自ドメインを無料で簡単にSSL化!
ゴール お名前.comで取得したドメイン(example.comとする)のサブドメイン(test.example.com)にアクセスして、EC2に構築したNginxの画面がhttpsで見えること。 下記構成図の環境構築を目指す。 前提 お名前.comまたは他のドメイン事業者でドメインを取得していること 取得しているドメインにCNAMEを設定できること 説明しないこと CNAMEって?みたいなドメインの基礎的なこと ALB,EC2、セキュリティグループの作成方法 ワイルドカードって?みたいな説明 やっていく その前に。。 ACMって?? AWS Certificate Manager により、AWS の各種サービスとお客様の内部接続リソースで使用するパブリックとプライベートの Secure Sockets Layer/Transport Layer Security (SSL/TLS) 証明書のプロビジョニング、管理、およびデプロイを簡単に行えます。SSL/TLS 証明書は、ネットワーク通信を保護し、プライベートネットワーク上のリソースと同様にインターネット上の Web サイトのアイデンティティを確立するために使用されます。AWS Certificate Manager を使用すれば、SSL/TLS 証明書の購入、アップロード、および更新という時間のかかるプロセスを手動で行う必要がなくなります。 つまり、ドメインさえあれば無料でSSL証明書を取得して、AWSの各リソース(ALB,ELB,EC2など)を簡単にSSL化することができるもの。ワイルドカードも対応しているみたい。 今まで、なんで存在を知らんかったんや。めちゃくちゃ便利やんけ!ってことで、やっていきます。 やっていく 流れとしては、次の5Stepです。 1. ACMで証明書をリクエスト 2. ドメインの設定を 3. ACMで証明書を取得 4. ALB作成 5. Route53 ACMで証明書のリクエスト まずは、ACMで証明書のリクエストをします。 AWSのリソース一覧からCertificate Managerを選びます。 "証明書のリクエスト"をクリック。

external-dns

仕組み

ExternalDNSを使用するとKubernetesのYAML内でドメイン名を指定するだけで、Route53のHosted Zoneにレコードが登録できて非常に便利です。

デプロイ

下記のmanufest.ymlファイルのexample.comと<external-dns用のIAMロールのArn>をご自身の環境に変更してください。

デプロイコマンド

external-dnsのオプションパラメーター(args:)の意味は以下の通りです。

--source
どのリソースをもとにroute53のレコードセットを作成するかを決めます。今回はServiceとIngressを指定しています。

--domain-filter
HostedZoneに対応するドメイン名に置き換えます。

--provider
AWSを使うのでAWSで大丈夫です。他にもGoogleやAzureなどが指定できるようです。

--policy
syncにすると削除も反映されます。作成のみにしたい場合はupsert-onlyにしてください。

--registry
txtレコードの登録を行います。

--txt-owner-id
ここは適当にしましたが問題なく動きました。

サンプルアプリケーション

すべての準備ができましたので、サンプルアプリケーションをデプロイしてみます。
サンプルアプリケーションはClassMethodさんのサイトのものを使っています。

ECRの作成

ECRを作成してログインします。

repositoryUriは後で使うのでコピーしておいてください。

Dockerの準備

アクセスしたらPod名を返却するWebサーバを作成します。

イメージを作成してECRにプッシュします。XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.comはECRのrepositoryUriに変更してください。

target2も同じように作成してECRにプッシュしてください。

パスベースのルーティング

test.example.com/target1にアクセスしたらtarget1のPodに、test.example.com/target2にアクセスしたらtarget2のPodにアクセスするmanufest.ymlファイルを作成します。

デプロイコマンド

test.example.com/target1とtest.example.com/target2にアクセスして挙動を確かめてください。

ホストベースでのルーティング

先ほど作成したmanufest.ymlファイルのingressのspecの部分のみ変更しています。

これをデプロイすることでホストベースでもアクセス振り分けができます。

ALBのセキュリティグループにIPアドレスでアクセス制限

manufest.ymlファイルのingress[metadata][anotations]に下記行を追加することで,セキュリティグループにIPアドレス制限の設定を追加することが出来ます.

複数のIPアドレスをホワイトリストに追加したい場合はこうします.

ymlファイルを書いたら長くなったので、あとでGithubにソース上げておきます。

Reference

ALB Ingress Controller を使う - Qiita
この記事では、 [ALB Ingress Controller](https://github.com/coreos/alb-ingress-controller) について書きます。

※ [zalando-incubator/ku...

Echo server - AWS ALB Ingress Controller

Kubernetesのexternal-dnsでRoute53 RecordSetを自動作成する - Qiita
# external-dnsとは

> [kubernetes-incubator/external-dns]
(https://github.com/kubernetes-incubator/external-dns)
>
> Co...

Feature: Annotation for Default Security Group Rules · Issue #691 · kubernetes-sigs/aws-alb-ingress-controller
Currently bring your own security group(s) is supported with the annotation alb.ingress.kubernetes.io/security-groups and absent that, you get a default SG on the ALB AND on the target instance(s) ...

-Container
-, , , , , ,

Translate »