この記事は actindi Advent Calendar 2019 の13日目の記事です。 adventar.org
こんにちは!!こんにちは!!インフラエンジニアのyamamotoです。
AWSのリソースを作成・修正するのに、CloudFormationを使うととても便利に作れますね。
でもループ処理できなかったり、生のYAMLが見づらかったりと面倒なこともあります。
そこでCloud Development Kit(CDK)を使うと、CloudFormationスタックを手軽に作ることができます!
しかしCDKについてはまだまだ情報が少なく、思い通りに扱うのも割と大変です。ここでは私がCDKを使っていてつまづいた点を共有させていただきます。
※当ブログのコードはTypeScriptで記載しています。
マルチスタックにするときはこうする
ネット上のCDKのサンプルはシングルスタック(CloudFormationスタック一つで実行する)で扱われたものが多くあります。見通しがよく、一気にいろいろなリソースが構築できるので便利ですね。
ただ、実際の運用を考えると、VPCはVPCだけ、EC2はEC2だけ、というように、それぞれのリソースで別々に実行したくなってきます。
そこで、CDKではマルチスタックにできるようになっているのですが、マルチスタックのサンプルがあまり無いので、どういう書き方がスタンダードなのか分かりづらかったです。
結局、CDKのマルチスタック対応は、このように書きました。
bin/stack.ts
#!/usr/bin/env node import 'source-map-support/register'; import { App, Tag } from '@aws-cdk/core'; import FooStack from '../lib/FooStack'; import BarStack from '../lib/BarStack'; import BazStack from '../lib/BazStack'; const app = new App(); new FooStack(app, 'foo-stack'); new BarStack(app, 'bar-stack'); new BazStack(app, 'baz-stack');
単純に、このような感じで並べて書きました。
一つ一つ書くのが面倒なのですが、プログラムですし、色々なやり方があると思います。
なお、実行するときは、下記のように引数で実行したいスタックを指定します。
$ cdk deploy foo-stack
EKSでは既存のVPCを読むときにSubnetが無いとダメ
せっかくなのでKubernetesをやりましょう。CDKでEKSクラスタを作成して、でも既存環境があるので既存のVPCを読み込みたい、というときはVpc.fromLookup()メソッドを使います。
しかし、VPCを読み込んでEKSクラスターを作成しようとするとエラーが出てしまいます。
これもいろいろ探してみたものの事例が無く、原因もわかりませんでした。
あれこれ試してみたところ、EKSに読み込ませるVPCにはパブリックサブネットとプライベートサブネットが定義されてないとダメだとわかりました。
パブリック?プライベート?なんだかわからない定義ですが、要はインターネットゲートウェイにルーティングされたサブネットか否か、というだけのようです。
では、VPCスタックでサブネットを作ってVPCを読み込むように書いて、とやってもやはりエラーになります……なんで?
どうもVPCを読み込むときは、サブネットの作成がCDKコードに記載されていてもダメで、サブネットが実在していないと通らないようでした。
なので、サブネットを作成するスタックを先に実行して、作成が済んでからVPCを読み込ませるようなスタック構成にしないとうまく動きません。
bin/stack.ts
const vpcStack = new VpcStack(app, 'vpc-stack'); const vpc = Vpc.fromLookup(vpcStack, vpcName, { vpcId, vpcName });
上記の例では、VpcStack()内でサブネットを作成して、その後外でVpc.fromLookup()を実行しています。
このようにすることで、サブネットが作成された状態でVPCを読み込むことができます。
EKSマスターロールにはパスを付けてはダメ
さて、あれこれ試しながらようやくCDKでEKSクラスタを立ち上げました。しかしなぜか突然kubectlで接続できなくなってしまいました。
ロールを見直してもだめ、何度やっても不可思議なエラーが出てしまう。これは一体なんなんだろう。
こないだまではkubectlも問題なく動いていたのになんでだろう……ふと、最近修正したところを考えてみると……
ひょっとして、EKSのマスターロールにパスを追加したからダメなのか?
const eksRole = new Role(this, 'EksRole', { roleName: 'eks-master-role', assumedBy: new AccountRootPrincipal(), path: '/cdk', });
ロールにパスを追加しようとしたのには訳があって、CDKで取り扱うロールを明示的に区分けしたかったからなのですが、まさかEKS側で対応していないとは……
とはいえ、日進月歩で進化しているAWSですから、そのうち対応するでしょう。早く対応してほしいなぁ。
さいごに
CDKはまだまだ発展途上ではありますが、未来を感じさせるソリューションですね。
昔から考えると、コードでネットワークを構築してサーバーを立ち上げる、とか想像もつかないですよね。どんどん便利に快適なインフラ環境になっててワクワクします。
アクトインディではWebエンジニアを募集しています! actindi.net