@amsy810's Blog

~Kubernetes / Cloud Native / Docker / etc~

Kubernetes は辛いのか?

こんにちは。 @amsy810 です。

下記のブログが出てから『Kubernetes は運用しきれない』と耳にすることが多くなってきたので、雰囲気で曲解されて Kubernetes is difficult とならないよう、マネージドでシンプルに使うだけなら難しくないよと伝えるために書きました。

Kubernetes がいいよと伝えるためではありません。

yakst.com

TL;DR

上記のブログについては概ね同意見です。

辛いのは自前で Kubernetes クラスタの管理自体を行う場合です。

GKE などのマネージド Kubernetes サービスを利用するケースでは、Kubernetes の管理は殆ど必要がなくなります。

例えば GKE の場合には、自動クラスタアップグレード・自動クラスタスケーリングなどが用意されています。他にも自動ノードプロビジョニング機能(CPU・メモリ・GPU の割り当て要求に従って、良い感じのノードを自動でクラスタに追加・削除する)を利用すると ノードの管理ですら必要なくなり 、抽象度の高い(利便性の高い)基盤として利用することが可能です。

また、アプリケーション開発者として Kubernetes を利用するだけなら実際は非常にシンプルに利用することが可能です。

マネージド Kubernetes を使えるなら、開発者として利用するだけなのでそこまで難しくありません。

前提条件

コンテナを利用するべきかや、Nomad・ECS・Kubernetes といったオーケストレータ(あるいは Fargate など)を利用するべきか否かというところについては述べません。この辺りが必要な方向けに書いています。なんだかんだ VM のワークロードが必要というケースも多々あるでしょう。また、PaaS も良いと思います。あくまでコンテナオーケストレータだけの話をしています。

この前提は、再現性・管理性・復元力・可観測性・自動化・疎結合性といった特性を組織が享受できる状態か(享受したい状態か)どうかによって異なります。

なお、すでにクラウドを利用している組織で新規プロジェクトの技術選定なのだとしたら、ステートフルなものはマネージドサービスを利用しつつステートレスなアプリケーションに利用していくことは障壁も少なくおすすめです。

どのオーケストレータを選択すべきか

国内では選択したオーケストレーターを今後も長く使っていくケースが非常に多くなるかと思います。

海外では大規模なクラウド間の移行やプラットフォームの移行をやってのけるケースも多々あるため、その気概があるなら正直何から始めてもいいと思います。

日本にはなかなか真似できない部分ですね。

なるべく塩漬けにしたい場合には、「拡張性がある」「コミュニティが活発」「エコシステムが豊富」といったあたりの長く利用できるかどうか、やりたいことが増えた際に魔改造しないで済むかどうかという点を考慮すべきだと思います。

OSS だと下火になった際の影響が大きいため、選択肢がいくつかある際は個人的にはこういったところを重視しています。

ECS などのマネージドサービスに関しては、今後もあまり心配はないと思います。

ただ忘れないで欲しいのが、Kubernetes であっても アプリケーション開発者から見ると「シンプルにも利用可能」 であるという点です(あとで紹介します)。

でも流石に PaaS の利便性には勝てないとは思います。あくまでオーケストレータを純粋に比較した場合です。

オンプレで Kubernetes を選択するべきか?

オンプレ上で Kubernetes をやろうとするのであれば、少なくとも少人数で選択することはオススメしません。

やるとしてもサポート付きの商用 Kubernetes ディストリビューションを利用するか、Kubernetes を専門に面倒をみるチームが必要でしょう。

trivago さんのケースでも 4 人チームでオンプレ上に構築して利用するというものだったので、Kubernetes はかなりオーバーだと思います。

利用者としての Kubernetes

Kubernetes を利用するということは、 GCPAWS・Azure といったパブリッククラウドを利用するのと近しいもの だと考えています。

そのため、当然パブリッククラウド自体を自前で構築して運用することを少人数で成し遂げることは困難です(例:OpenStack)。

一方で利用者から見るとパブリッククラウドは非常に便利かつ高機能ですね。

そのためアプリケーション開発者がどの環境でやるのが一番楽かという面では、マネージド Kubernetes サービスを利用するのが一番だと思います。

管理された Kubernetes 上でコンテナを起動させる場合、コンテナを起動させてくれる抽象度の高いマネージドサービスと余り差はない と思います。

例えば、シンプルに利用するだけであれば Kubernetes でも 下記のように Deployment リソース(コンテナを起動する)と Service リソース(ロードバランサ)の2つだけを使っても達成できます。

パブリッククラウドでも全ての機能を把握して選択することはないのと同様に、そのほかのリソース(機能)に関してはやりたいことが出来た際にやり方を調べれば良いと思います。その時にできることがたくさんあった方が良いとは思います。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.13
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: sample-lb
spec:
  type: LoadBalancer
  ports:
    - name: "http-port"
      protocol: "TCP"
      port: 80
  selector:
    app: sample-app

なおCI/CD では、上記の様なマニフェストのボイラープレートを作って使い回すことが可能です。

Kubernetes を採択する規模は?

規模が大きい方が得られる恩恵は大きくなりますが、小さい規模でも恩恵は大きいと思います。

ただし、小さい規模の場合は人員も少ないため、そこを担当できる(したい)エンジニアがいるかという点につきますね。

Kubernetes は抽象度の高い環境を提供できるか?

Kubernetes も HorizontalPodAutoscaler・ClusterAutoscaler や Knative などを利用することにより、PaaS のような抽象度の高い(利便性の高い)環境を提供することは可能です。

いわゆる Fargate に近しい何かも設定次第では実現できます。

Kubernetes へ移行するべきか?

Nomad・ECS・Kubernetes など様々なコンテナオーケストレータが存在します。

ECS・Nomad のいずれも足りない機能を補う様にアップデートを重ねてきており、徐々に Kubernetes にしか無かった機能が実装されてきています。

そのため、すでに ECS や Nomad で稼働している場合には Kubernetes に移行するメリットは大きくないと思います。

既存のレガシーな環境から移行するべきかという点についても同等なのですが、もし今後もシステムが改修され続けていく状況で移行コストをかけられる様であれば移行も選択肢の一つです。

主軸としては移行しなければ開発効率が上がらないかどうかが判断材料ですね。

(余談)オンプレ上で Kubernetes をやると良いところ

基本的にオンプレ上で Database as a Service や Queue as a Service などを実現するのは運用コストや仕組みづくりが大変です。

Kubernetes の周辺エコシステムを利用することでマネージドサービスを Kubernetes 上で展開することも可能になってきています(mysql-operator、Vitess、NATS など)。

そのため、オンプレ上での Kubernetes にはプライベートクラウドの充実という可能性も感じています。

まとめ

技術選定は組織ごとに好みがあると思うので、あくまでも個人の見解です。

何を選択するにせよ、様々な情報を元に適切に判断すれば良いと思います。

雰囲気で曲解されて Kubernetes is difficult とならないよう、あくまで Kubernetes の苦手意識がなくなるためだけに、一意見として書いてみました。

まとめのまとめ(心の声)

Kubernetes、いいよ。)

追記 (4/3 15:00)

何度も言いますが、どの環境を使っても良いと思います。コードを書いたら良い感じにしてくれるのが目的です。PaaS でも ECS でも Kubernetes でもアプリケーション開発者からしたらなんでも良いでしょう。

Kubernetes も頑張って CI/CD 整備やマニフェストを書く人がいることによって PaaS の様にして利用しています。

Kubernetes は本当に素の Platform なので、ちゃんとした CI/CD がないとアプリケーション開発に集中できる環境を提供するという目的は達成できません。そのため、あくまでもインフラや SRE にある程度知見のあるメンバーは必要でしょう。

環境を整備すると PaaS も KubernetesNomad も ECS もいちアプリケーション開発者からすると透過的なのが良い形だと思います。

正直単純にオーケストレータを利用する範囲であれば、その学習コストよりもその周辺の考えなきゃいけないこの方が辛いです。

また、どのオーケストレータを選択しても従来の VM で環境を作った時にはいずれも近しい程度の学習コストはかかると思っていた方が良いです。

さくらインターネット研究所 に 客員研究員 としてジョインしました。

こんにちは。amsy810です。

春といえば新しいことを始める時期ですね。

4/1 より さくらインターネット研究所 さんに 客員研究員 としてジョインしました。

新しい経験もしてみたいと思い下記のようなツイートをしたところ、ありがたいことにお誘いを頂いたため新しい挑戦を始めることになりました。

まつもとりーさんからDMで連絡があったのですが、予想外なお話だったので最初は驚きました。 普段からまつもとりーさんのブログなどはウォッチしていたので、お話をいただいた時点で面白そうだなというのは明白でした。

ご存知の方も多いかと思いますが、さくらインターネット研究所さんでは「超個体型データセンター」についての研究を行なっております。 私もこの辺りのお話に携わらせていただく予定です。

f:id:masaya_aoyama:20190322022125p:plain
さくらインターネット研究所 中長期ビジョン

詳しくは所長の鷲北さんがまとめています。他にもまつもとりーさんや 研究所のみなさま がまとめた記事もたくさんあるので、探してみてください。(エキスパートのみなさまとお仕事をするのは緊張します。)

research.sakura.ad.jp

数年後に期待されるであろう技術を考えることや、大規模なクラウド事業者の向かう方向性に触れられるのは楽しみです。 最近では "Cloud Native" が広まってきましたが、次のプラットフォームになるようなコアコンセプトなどを考えていけたらと思っております。

また、さくらインターネットさんも CNCF(Cloud Native Computing Foundation)にシルバーメンバーとして参加しています。

再びですが、 CyberAgent を退職するわけではありません。 しっかりとメリハリをつけて本業も頑張りつつ、新しい経験を通じて CA でも引き続き頑張ります。

クリエーションラインに 技術アドバイザー としてジョインしました。

こんにちは。amsy810です。

春といえば新しいことを始める時期ですね。

3/18 より クリエーションラインさんに 技術アドバイザー としてジョインしました。 f:id:masaya_aoyama:20190325231512p:plain

今とは異なる要件で新しい経験もしてみたいと思い下記のようなツイートをしたところ、ありがたいことにお誘いを頂いたため新しい挑戦を始めることになりました。

主に Kubernetes やコンテナ関連のお仕事をさせていただく予定です。

私自身、技術が好きでこの業界に入ってきたほどなので、色々なことが楽しみです。

クリエーションラインさんは CNCF が提供する 日本で最初の KCSP (Kubernetes Certified Service Providers) で、CNCF 公式のKubernetesレーニングの提供を含む、Kubernetesやコンテナ関連の事業を展開しています。

具体的な内容についてお話しできないことも多々ありますが、普段中々経験できない業界だったりするので、とても良い経験ができそうだなとワクワクしています。

なお、CyberAgent を退職するわけではありません。

しっかりとメリハリをつけて本業も頑張りつつ、新しい考え方を学んで CA でも引き続き頑張ります。

なお、新しいことを始める話には続きがあり…数日後にまたご報告させていただきます。

【Kubernetes】GKEのBackendConfigとNetwork Endpoint Groups(NEGs)

この記事はAdvent Calendar 1日目の記事になります。

Japan Container Days v18.12の運営やshowKsやセッション資料の作成に追われ、遅れてしまい申し訳ありません。)

こんにちは。 @amsy810 です。

GKE では、最近ネットワークに関する便利な機能追加が多く行われており、この記事ではそれらについて紹介したいと思います。 主に下記の2つについて紹介します。

  • BackendConfig Resource
  • Network Endpoint Groups (NEGs)

BackendConfig Resource

BackendConfig Resource は GKE でのみ利用可能な CRD(Custom Resource Definition)で、HTTP/HTTPS Load Balancing(Ingress Resource)をする際に、下記の機能を付随して利用することが可能になります。

  • Cloud Content Delivery Network (Cloud CDN)
  • Cloud Armor
  • Cloud Identity-Aware Proxy (Cloud IAP)
  • Timeout, Connection draining timeout, Session affinity

もう少しいうと、GCE用のIngress ControllerがこのBackendConfigリソースをみて、連携を行なっているようです。Ingress ResourceのSpecは一般化されたリソースのためこのような記述をすることができず、もしできるとしてもAnnotationsで設定することになってしまうと思います。 そのため、BackendConfigとして実装する道を辿ったのだと思います。 現時点ではBackendConfigはGKE用のリソースとなっています。 実際の処理部分は下記のあたりです。

ingress-gce/pkg/backends/features at v1.4.0 · kubernetes/ingress-gce · GitHub

なお、BackendConfigのリソースは、下記のリンク先にある構造体を持っています。

ingress-gce/types.go at v1.4.0 · kubernetes/ingress-gce · GitHub

全部埋めた状態だとこんな感じですね。

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: sample-backend-config
  namespace: default
spec:
  iap:
    enabled: true
    oauthclientCredentials:
      secretName: my_secret
      # Secret で clientID と clientSecret を指定する場合は不要
      # clientID: my_client_id
      # clientSecret: my_client_secret
  cdn:
    enabled: true
    cachePolicy:
      includeHost: true
      includeProtocol: true
      includeQueryString: false
      QueryStringBlacklist:
        - ""
      QueryStringWhitelist:
        - ""
  securityPolicy:
    name: my_policy
  timeoutSec: 40
  connectionDraining:
    drainingTimeoutSec: 60
  sessionAffinity:
    affinityType: "GENERATED_COOKIE"
    affinityCookieTtlSec: 50

ちなみにCloud IAPとCloud CDNを両方とも1つのBackendConfigに設定することはできません。 また、作成したBackendConfigは、ServiceのAnnotationsに beta.cloud.google.com/backend-config を記述することで利用します。 Ingress ResourceのAnnotationsに設定するイメージでしたが、Serviceの方に設定するんですね。 おそらく、複数のIngress ObjectからServiceのNodePortを指定することができるため下流の方で設定をかけたかったか、Ingress ControllerはService Objectの情報を元に動作する(NEGsはServiceのNodePortに送られるのではなく、Serviceに紐付くPodのIPをDiscoveryしている)思想で作られたのかなと思っています。

apiVersion: v1
kind: Service
metadata:
  annotations:
    beta.cloud.google.com/backend-config:
      '{"ports": {"http":"config-http", "http2" :"config-http2"}, "default": "config-default"}'
  name: my-service
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 8080
  - name: http2
    protocol: TCP
    port: 443
    targetPort: 8080
  - name: http3
    protocol: TCP
    port: 49152
    targetPort: 49152

Cloud Armor

Cloud Armorは、DDOS対策・IP Addressの Allow/Deny・Geo-based Access Controlをはじめとした様々なセキュリティ機能を利用することができます。

現状では事前に gcloud beta compute security-policies rules create コマンドでポリシーを作成しておき、そのポリシーを使うことを明示的にBackendConfigリソースに指定してあげる必要があります。

例えば、事前にポリシーとルールを作成し、

$ gcloud beta compute security-policies create sample-policy

$ gcloud beta compute security-policies rules create 1000 \
    --security-policy sample-policy \
    --description "Deny traffic from 192.0.2.0/24." \
    --src-ip-ranges "192.0.2.0/24" \
    --action "deny-404"

下記のようなBackendConfigを作るような形になっています。

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: sample-backend-config
  namespace: default
spec:
  securityPolicy:
    name: sample-policy

現状ではKubernetesの世界で設定を完結できないようになっていますが、この辺りは下記のようにいずれK8sの世界で管理できるようになってくるのではないでしょうか。

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: sample-backend-config
  namespace: default
spec:
  securityPolicy:
    - srcIPRange: 192.0.2.0/24
       action: deny-404
       priority: 1000

Configuring Cloud Armor  |  Kubernetes Engine  |  Google Cloud

Cloud IAP (Identity-Aware Proxy)

Cloud IAPは、GCP(GKE)上にデプロイされたアプリへのAccess Controlを行うサービスです。 事前にClient IDとClient SecretのデータをSecretに登録しておきます。

apiVersion: v1
kind: Secret
metadata:
  name: sample-db-auth
type: Opaque
data:
  client_id: XXXXXXX
  client_secret: XXXXXXX

Cloud IAPの設定項目としては、Client IDとClient Secret になります。Secret経由で渡している場合には、Secret名を指定すれば問題ありません。

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: sample-backend-config
  namespace: default
spec:
  iap:
    enabled: true
    oauthclientCredentials:
      secretName: my_secret
      # Secret で clientID と clientSecret を指定する場合は不要
      # clientID: my_client_id
      # clientSecret: my_client_secret

Cloud CDN (Content Delivery Network)

Cloud CDNは、GCPCDNです。 設定項目としてはキャッシュポリシーに関わるものがあります。

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: sample-backend-config
  namespace: default
spec:
  cdn:
    enabled: true
    cachePolicy:
      includeHost: true
      includeProtocol: true
      includeQueryString: false
      QueryStringBlacklist:
        - ""
      QueryStringWhitelist:
        - ""

そのほかの設定

そのほかにもタイムアウトの設定や、セッションアフィニティの設定などを行うことも可能です。

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: sample-backend-config
  namespace: default
spec:
  timeoutSec: 40
  connectionDraining:
    drainingTimeoutSec: 60
  sessionAffinity:
    affinityType: "GENERATED_COOKIE"
    affinityCookieTtlSec: 50

注意事項・参考資料

現在はまだ beta リリースなため、SLAが担保されていなかったり、後方互換のない変更が行われる可能性があるため注意してください。

BackendConfig custom resource  |  Kubernetes Engine  |  Google Cloud

Network Endpoint Groups (NEGs)

NEGsは、IPとPortのペアをネットワークエンドポイントとしてLoadBalancerの設定に利用するものです。 NEGsとPod Nativeなネットワーク(CalicoなどでPod Network / Internal Network に対してVM Networkから疎通性がある構成)を利用することで、LoadBalancerから直接Podまでリクエストを受けることができます。

通常はこのように、LoadBalancerからKubernetes Nodeに対してリクエストが送られると、Node上に到達した後に、再度負荷分散(2段階ロードバランシング)が行われます。 NodeからPodへのロードバランシング(kube-proxyの担当範囲)は、usermode・iptables・ipvsと3つのモードがありますが、いずれの場合にも一定の負荷・レイテンシの微増・分散のばらつきが生じます。

f:id:masaya_aoyama:20181206035829p:plain

一方でNEGsを利用することで、直接Pod宛てに負荷分散を行うことができるため、これらの問題を低減することが可能です。

f:id:masaya_aoyama:20181206035824p:plain

AWSの場合には、aws-vpc-cni-k8sとalb-ingress-controllerを使うと同様のことが実現できるそうです。(未検証)

Using container-native load balancing  |  Kubernetes Engine  |  Google Cloud

また、Ingressの実装の違いについては下記を参考にしてみてください。

speakerdeck.com

(あ、こんなところにKubernetes 本...)

www.amazon.co.jp