GA technologies, Blockchain Strategy Centerの中村です。 3回目の投稿ですが、またBlockchainから外れて今度はインフラ周りの記事です。
弊社で現在開発中の新規プロダクトではECS上でコンテナを稼働させており、公式クライアントツールの ecs-cli
を利用してCI/CD pipelineからデプロイを行うような構成をとっております。
しかしながらデプロイ後の不測の事態に伴うrollbackなど実運用を想定した際、ECS本体だけでは若干の機能不足が否めないのも事実です。
一方、比較対象として挙げられるkubernetesは本体がもはやオーケストレーションツールにとどまらないほど多機能で、周辺のエコシステムも豊富なツールを提供しています。
昨年末に丁度 EKSがtokyo regionでサポートされたというニュースもあり、本番環境での稼働を見据えた検証を行なったため備忘までに記事を書きます。
TL;DR
- EKSは現状、ほぼプレーンなk8sのmaster nodeのマネージドサービス
- CloudWatch Logsとの連携は、fluentdを介して行う
- SecurityGroupはannotationで操作する
- Podに対するIAM Roleの割り当ては、3rd Party Toolで対応
ログの集約
fluentd as DaemonSet
現状のEKSはほぼkubernetesのmaster nodeのマネージドサービスといった趣が強く、 annotation一行でCloudWatch Logsと連携してくれるような機能は提供されておりません。 そのため、fluentd等を経由し何らかのログ収集基盤に転送する必要があります。
fluentd => CloudWatch Logsの連携を行う場合方法はいくつか考えられますが、
最もお手軽なのはfluentdをkubernetesのDaemonSetとして稼働させるための公式イメージの利用です。
仕組みとしては、kubernetesがコンテナごとのログファイルを出力する WorkerNodeのディレクトリ /var/log/containers
に対して、
fluentd containerをvolumeMountして稼働させることでログを拾っています。
fluentdがtailしたログはコンテナごとにlog streamに分割されて集積されます。
用意されているmanifestファイルをほぼそのまま転用する事が可能ですが、下記のfluentdの環境変数のみ自身の環境に合わせて
設定してください。
尚、 FLUENT_UID
はmountしたvolumeのread/writeするために必要なものです。
env: - name: LOG_GROUP_NAME value: "any_log_group_name" - name: AWS_REGION value: "ap-northeast-1" - name: FLUENT_UID value: "0"
fluentd as Sidecar
その他、より細かな設定を行いたい場合はvolume containerをapplicationおよび、sidecarとして起動するfluentd containerと共有することで、
独自の fluent.conf
を利用したログ収集が可能です。
その際も公式で配布されている docker imageを利用すると良いでしょう。
下記は、fluent-plugin-cloudwatch-logs
pluginを導入する場合の最小限の設定になります。
FROM fluent/fluentd:v1.3.3-onbuild-1.0 USER root RUN apk add --no-cache --update --virtual .build-deps \ sudo build-base ruby-dev \ && sudo gem install \ fluent-plugin-cloudwatch-logs \ && sudo gem sources --clear-all \ && apk del .build-deps \ && rm -rf /home/fluent/.gem/ruby/2.5.0/cache/*.gem COPY fluent.conf /fluentd/etc/
ELBとの連携
EKSでは、kubernetesのServiceResouceのtype = LoadBalancer 経由でCLBと経由させる事が可能です。
(ALBやNLBを利用する事も可能ですが割愛します)
一方、EKSから起動するとdefaultで80 portが公開されたSecurityGroupが作成されてしまいます。
これは annotationによって internal LBとして作成した場合も同様の挙動になってしまいます。
対処方法としては、 spec.loadBalancerSourceRanges
によってSourceIPを絞ることが挙げられます。
Restrict Access For LoadBalancer Service
実はkubernetesのソースコードを読むと, まさにSecurityGroupを指定する service.beta.kubernetes.io/aws-load-balancer-security-groups
というannotationが用意されているのですが、これは v1.13
からの機能で、EKSの最新版である v1.11
では残念ながら利用できません。
そのため、社内からのアクセスに限定したLBを設置したい場合は現状下記のようになります。
apiVersion: v1 kind: Service metadata: labels: task: web name: http-server annotations: service.beta.kubernetes.io/aws-load-balancer-extra-security-groups: "{extraSG1},{extraSG2}" namespace: default spec: type: LoadBalancer loadBalancerSourceRanges: - {社内IP}/32 ports: - protocol: TCP port: 80 targetPort: 3000 selector: app: {metadata.labels.app of pod}
IAM Roleとの連携
これも現状ではPod単位でのIAM Roleの指定はできず、WorkerのRoleがそのまま引き継がれますので、細かい制御をしたい場合はkiamやkube2iamなどの利用や、kubernetesのSecret Resourceを利用して管理するのが良いと思われます。
おわりに
AWSでのcontainer周りの開発に関しては、GitHub上で ロードマップが公開されています。 ウォッチしつつ、実運用を想定して検証を進めていく所存です。
最後に、GA technologiesでは一緒に働く開発者を募集しています。(Blockchain Strategy Centerでも絶賛エンジニア募集中です!) ご興味を持たれた方はぜひ下記からご応募ください!