Kubernetesのアーキテクチャーについて読んだんでそのメモ

Kubernetesクラスタは7つのコンポーネントから構成されている。

また、kube-apiserverを中心としている。

etcd

  • Kubernetes Master上で動作するコンポーネント
  • KVS
  • etcdにはリーダーが存在し、なんらかの理由でリーダーが動作しなくなった場合、自動的に新しいリーダーが選出され、サービスを継続する
  • k8sクラスタに登録されている全ての情報が保存されている

kube-apiserver

  • Kubernetes Master上で動作するコンポーネント
  • kubectlはkubeapiserverに対してリクエストを送ることで、DeploymentやServiceといったリソースの作成/削除などの操作を行う
  • kube-scheduler/ kube-controller-manager/ kubeletなどのコンポーネントも、kube-apiserverに対してリクエストを送ることで処理を行う

kube-scheduler

  • Kubernetes Master上で動作するコンポーネント
  • ノードが未割り当てのPodを検知し、kube-apiserverにリクエストを送って更新することでスケジューリングを行う

kube-controller-manager

  • Kubernetes Master上で動作するコンポーネント
  • DeploymentやReplicaSetの状態を監視しながら、必要に応じてReplicaSetやPodを作成するためのコンポーネント
  • kubectlコマンドで登録するときと同じく、kube-controller-managerはkube-apiserverへPodを登録するだけで、実際のスケジューリングはkube-schedulerが行う

kubelet

  • Kubernetes Node上で動作するコンポーネント
  • コンテナの起動や停止などの管理を行う
  • kube-apiserver経由でPodが登録されると、kube-schedulerがどのNodeにPodを割り当てるのか決める。Nodeが決定されると、kubeletはそれを検知してPodを起動する。基本的にその流れ

kube-proxy

kube-dns

参考

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

k8sで構築した環境にjmeterで負荷テスト

環境構築した時のメモはこちら。

joe41203.hatenablog.com

今回は、k8sで構築した環境に負荷テストしてみました。

設定手順

以下の記事を真似るとできました。 Apache JMeterをDockerコンテナで試す(Mac編) - Qiita

今回は、users数1000、Ramp-up periodを5に設定しました。 f:id:joe41203:20190402144514p:plain

負荷テスト

webのPod数1で負荷テストしましたが、bad request でまくりです笑

f:id:joe41203:20190402144924p:plain

$ kubectl scale deployment web --replicas=8

replica数を増やしてみると、

f:id:joe41203:20190402145129p:plain

Pod数1よりはましですねw

f:id:joe41203:20190402145405p:plain

参考

qiita.com

クラウドデザインパターン設計ガイドを読んだ[WIP 読み終わるまで随時更新していきます]

基本パターン

SnapShotパターン

  • データバックアップのためのパターン。
  • ある瞬間のデータを複製したバックアップをスナップショットという。
  • APIを用いてスナップショットを定期的に取得すればバックアップが自動化ができる。
  • スナップショットはリージョン間でのコピーが可能で、例えば、東京リージョンで取得したスナップショットを定期的にシンガポールリージョンに転送すれば、東京リージョンが利用できなくなった場合でもシンガポールリージョンで復旧できる。

CDP:Snapshotパターン - AWS-CloudDesignPattern

Stampパターン

  • 環境設定済みの仮想サーバをコピーするためのパターン。
  • 環境設定済みの仮想サーバからImageを作成し、そのImageを用いて新しい仮想サーバを作成できる。

CDP:Stampパターン - AWS-CloudDesignPattern

ScaleUpパターン

  • 動的にサーバのスペックを上げ下げするパターン
  • 仮想サーバを起動した後にもスペックの変更ができる
  • CloudWatchなどでリソース利用量を把握し、スペック不足(または過剰)な場合は、インスタンスを停止・変更後インスタンスを再起動するのみ

CDP:Scale Upパターン - AWS-CloudDesignPattern

ScaleOutパターン

  • 同じようなスペックのサーバーを複数台並べ、高トラフィックのリクエストを処理するパターン
  • 複数の仮想サーバーを起動し、ロードバランサーを用いて各仮想サーバーに負荷を分散する
  • ロードバランサ―サービス、モニタリングツール、そして自動でスケールアウトするサービスを組み合わせることで、負荷に応じて自動でスケールアウトするシステムを構築できる

CDP:Scale Outパターン - AWS-CloudDesignPattern

OndemandDiskパターン

  • いつでも好きなタイミングで必要なだけの容量を確保するためのパターン

CDP:Ondemand Diskパターン - AWS-CloudDesignPattern

可用性を向上するパターン

Multi-Serverパターン

  • 仮想サーバーを複数台並べ、クラウドサービスとして提供されるロードバランサーを用いて適宜負荷を振り分けるパターン
  • あるインスタンスに障害が起きたとしても、システム全体としては稼働を続けることができる

Multi-Datacenterパターン

  • 距離が十分に離れたデータセンターを複数確保することで、データセンターレベルの障害や災害が発生しても耐えられるようにするパターン
  • 例えば、東京やシンガポールなどのリージョンの中のデータセンターにサーバを置くことでデータセンターレベルの障害や災害に耐えられるようにできる

Floating IPパターン

  • サーバーの停止はそのままサービスの停止につながるので、システム提供者としては、停止時間をできるだけ短くなるようにしなければならない。予備サーバーを立ち上げて(本番用サーバーの)IPアドレスを設定することで処理の代行をするパターン

CDP:Floating IPパターン - AWS-CloudDesignPattern

Deep Health Checkパターン

CDP:Deep Health Checkパターン - AWS-CloudDesignPattern

Routing-Based HAパターン

CDP:Routing-Based HAパターン - AWS-CloudDesignPattern

動的コンテンツを処理

Clone Serverパターン

  • 負荷分散が考慮されていないシステムを、容易に負荷分散可能なシステムにするためのパターン
  • 負荷分散できるようにコンテンツ同期などを調整したクローン用AMIを作成し、負荷が重くなればクローン用AMIからEC2インスタンスを起動する。それをELBの負荷分散対象に変更する

CDP:Clone Serverパターン - AWS-CloudDesignPattern

NFS Sharingパターン

  • 複数サーバー間で同じコンテンツをリアルタイムに読み書きできるようにするためのパターン

NFSとは | OSSでのシステム構築・デージーネット

CDP:NFS Sharingパターン - AWS-CloudDesignPattern

NFS Replicaパターン

CDP:NFS Replicaパターン - AWS-CloudDesignPattern

State Sharingパターン

  • 動的なコンテンツを生成する際、ユーザー固有の状態を持つステート情報(HTTPセッションの情報、ログイン情報)を利用することが多い。サーバーを増加したときのステート情報の引き継ぎや、サーバー台数が減少(障害含む)したときのステート情報の消失を防ぐためのパターン
  • ステート情報を耐久性の高い共有データストア(メモリー/ディスク)に置き、複数サーバーからその情報を参照する。そうすることで、サーバーにステート情報を持たせず、ステートレスにできる。新たにサーバーが追加されても共有データストアを参照できるため、ステート情報の引き継ぎが行われる。

CDP:State Sharingパターン - AWS-CloudDesignPattern

URL Rewritingパターン

  • アクセスの大半は静的なコンテンツへのリクエストであり、インターネットストレージを利用することで、仮想サーバーを増強することなく負荷対策するパターン
  • 静的コンテンツのアクセスをS3/CloudFrontに分散することにより、負荷に強くなり、またEC2のコストも削減できる

CDP:URL Rewritingパターン - AWS-CloudDesignPattern

Rewrite Proxyパターン

  • コンテンツを格納したサーバーの手前にプロキシーサーバーを配置し、そこで静的コンテンツのアクセス先をインターネットストレージやコンテンツデリバリーサービスに変更するパターン

CDP:Rewrite Proxyパターン - AWS-CloudDesignPattern

Cache Proxyパターン

  • 変化の少ない静的コンテンツや動的コンテンツをWeb/APサーバーの上流でキャッシュし、キャッシュの期限が切れるまで配信パフォーマンスの高い上流のキャッシュサーバーでコンテンツ配信を行うパターン

Varnish入門と仕組み - Qiita

CDP:Cache Proxyパターン - AWS-CloudDesignPattern

Scheduled Scale Outパターン

  • スケジューリングされたスケールアウトパターン
  • Scale Outパターンと基本構成は似ているが、スケールアウトするタイミングを時間指定して実行することが主な特徴

CDP:Scheduled Scale Outパターン - AWS-CloudDesignPattern

IP Poolingパターン

  • セキュリティ上の理由や、接続制限を行うために、接続元のIPアドレスを制限しているケースがある。事前に必要な分のグローバルIPアドレスを確保し、接続先に登録しておくパターン

CDP:IP Poolingパターン - AWS-CloudDesignPattern

静的コンテンツを処理

Web Storageパターン

  • 大容量のファイルをインターネットストレージへ配置し、そこから直接ファイルを配信することで、Webサーバーのネットワーク負荷とディスク容量の問題を解決するパターン

CDP:Web Storageパターン - AWS-CloudDesignPattern

Direct Hostingパターン

  • クラウドが提供するインターネットストレージをWebサーバとして利用し、画像や動画などの大容量な静的ファイルをホスティングするだけでなく、HTMLなどもホスティングするパターン

CDP:Direct Hostingパターン - AWS-CloudDesignPattern

Private Distributionパターン

  • インターネットストレージで提供される制限付きURL発行機能を用い、制限付きURLでのみコンテンツをダウンロードするようにすれば、期限が切れたリンクや異なるIPアドレスを持つ人がアクセスを試みてもダウンロードできない。実質的に特定ユーザーにのみコンテンツを提供することを可能にするパターン

CDP:Private Distributionパターン - AWS-CloudDesignPattern

Cache Distributionパターン

  • 現在の技術では、例えば日本から米国東海岸のサーバーにアクセスすると最低でも200ミリ秒程度の通信遅延が発生する。それを解決するパターン。
  • 世界各地に配置されたロケーションに、コンテンツ配信元(オリジン)から配布されるコンテンツのキャッシュデータを配置する。こうすることで、地理的により利用者に近いロケーションからコンテンツを配信することになり、地理的/物理的な制約を解決する。

CDP:Cache Distributionパターン - AWS-CloudDesignPattern

Rename Distributionパターン

  • Cache Distributionパターンを使用してコンテンツを配信する際、マスターサーバーのファイルを変更しても、エッジサーバー(キャッシュサーバー)のデータはタイムアウトになるまで更新されない。それを解決するパターン。
  • 更新したいファイルを違うファイル名で配置し、アクセスURL自体を変更することで、エッジサーバーのキャッシュタイムアウトにかかわらず新しいコンテンツを配信する。

CDP:Rename Distributionパターン - AWS-CloudDesignPattern

terraform/k8sでGEK上にRails+React+Nginx環境を構築した時のメモ

環境構築までの大まかな流れ

  1. terraformでGKE上にCluster作成
  2. RailsのDockerfileを作成・DockerHubにImageをpush
  3. NginxのDockerfileを作成・DockerHubにImageをpush
  4. k8sでNignxのDeployment・Serviceを作成してNginxでHelloWorld
  5. RailsのImageを4のDeployment・Serviceに追記してRailsでHelloWorld

1. terraformでGEK上にClusterを作成

以下を参考

joe41203.hatenablog.com

2. RailsのDockerfileを作成・DockerHubにImageをpush

普通にRailsのDockerfileを書くだけではなく、Dockerfile内でassets:precompileをするようにした。

RUN bundle exec rake assets:precompile RAILS_ENV=production

Podにimageをpullする際に、myapp/public 配下にコンパイルしたjsやcssを配置したいため。

また、Rails.root/config/puma.rb にも注意したい。 Nginxとsocketsを共有するため、以下のコードを追記する必要がある。

# Nginxと通信
app_root = File.expand_path('../..', __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

3. NginxのDockerfileを作成・DockerHubにImageをpush

Railsにプロキシする設定を追記。

upstream app {
  server unix:///myapp/tmp/sockets/puma.sock fail_timeout=0;
}

4,5 k8sでGEK上にデプロイ

socketsをNginxとRailsで共有したいのでマウントするPATHを指定。

volumeMounts:
  - mountPath: /myapp/tmp/sockets
     name: web-sock

assets:precompileコンパイルされたファイルは /myapp/public に配置されるが、空のボリュームをマウントするため、元々publicに入っていたものが消えてしまいます・・・

解決策はあるようですが、今回は飛ばしちゃいました。Nginxからassets配信したい・・

以下、解決策。

Google Container Engine上のRailsアプリにnginxを挟む - Qiita

Deployment全体はこちら。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: k8s-rails-app
        tier: web
    spec:
      volumes:
        - name: nginx-conf
          configMap:
            name: nginx-conf
        - name: web-assets
        - name: web-sock
      containers:
        - name: rails
          image: docker.io/kinjoyuji/webapp:latest
          imagePullPolicy: Always
          command: ['bundle', 'exec', 'puma', '-C', 'config/puma.rb']
          envFrom:
            - configMapRef:
                name: rails-config
          volumeMounts:
            - mountPath: /myapp/tmp/sockets
              name: web-sock
            # - mountPath: /myapp/public
            #   name: web-assets
        - name: nginx
          image: docker.io/kinjoyuji/nginx:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 80
              name: nginx-port
          volumeMounts:
            # - mountPath: /myapp/public
            #   name: web-assets
            #   readOnly: true
            - mountPath: /myapp/tmp/sockets
              name: web-sock
            - mountPath: /etc/nginx/
              name: nginx-conf
              readOnly: true

参考

qiita.com

TerraformでGEK上にクラスタを作成する

まずは、GCP上でプロジェクトの作成。

f:id:joe41203:20190330125908p:plain

IAM&AdminからTerraform用のサービスアカウントを作成する。

f:id:joe41203:20190330130554p:plain

Kubernetes EngineとCompute EngineのAPIを有効にする。 APIを有効にしたのちにサービスアカウントを作ると、APIを再有効化する必要があるらしいので注意。かなり詰まった。。。

ここまできたら、Terraformを書いてapply

# main.tf

variable "project" {}
variable "region" {}

provider "google" {
  credentials = "${file("./k8s-gcp-account.json")}"
  project     = "${var.project}"
  region      = "${var.region}"
}
# cluster.tf

variable "username" {}
variable "password" {}

# reference
# https://www.terraform.io/docs/providers/google/r/container_cluster.html

resource "google_container_cluster" "primary" {
  name                     = "k8s"
  location                 = "asia-northeast1-a"
  remove_default_node_pool = true
  initial_node_count       = 1

  master_auth {
    username = "${var.username}"
    password = "${var.password}"
  }
}

resource "google_container_node_pool" "primary_preemptible_nodes" {
  name       = "k8s-node-pool"
  location   = "asia-northeast1-a"
  cluster    = "${google_container_cluster.primary.name}"
  node_count = 3

  node_config {
    preemptible  = true
    machine_type = "n1-standard-1"

    metadata {
      disable-legacy-endpoints = "true"
    }

    oauth_scopes = [
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
    ]
  }
}

github.com

Kubernetes データの永続化についてのまとめ PersistentVolumeとPersistentVolumeClaimの関係

k8sのデータ永続化に関してのメモ。

Kubernetesではデータ永続化のためのPersistentVolumePersistentVolumeClaimというリソースが提供されている。

PersistentVolume

  • ストレージの実態
  • GCPではGCEPersistentDisk
  • AWSではawsElasticBlockStore

PersistentVolumeClaim

  • PersistentVolumeに対して必要な容量を動的に確保するためのリソース
  • PersistentVolumeはストレージの実態を作るのみで、PersistentVolumeClaimを通してPodにアクセスする

2つのリソースの関係

以下のリンクの図がかなりわかりやすかった!

また、PersistentVolumePersistentVolumeClaimを理解するにはStorageClassも知る必要があり、PersistentVolumeが確保するストレージの種類を定義できるリソースのこと。

cstoku.dev

参考

thinkit.co.jp

cstoku.dev

devopscube.com

Kubernetes Serviceの種類と役割についてまとめてみた

Serviceがどういう役割をしているのか知識不足だったのでメモがてらにまとめてみました。

Serviceとは

pods(podの集合)に対して外部と通信を行うための通り道みたいなものです。serviceひとつにpodsがぶらさがって、serviceに来たアクセスをどれかのpodにいい感じで分配します(内部に賢いroutingがいます)。

kubernetes初心者のための入門ハンズオン - Qiita

Serviceの種類

ClusterIP Service

  • デフォルトで作成されるService
  • ClusterIPではKubernetesクラスタ上の内部IPアドレスにServiceを公開できる
  • ClusterIP Serviceを使用するとPodから別のPodへアクセスすることができるようになる
  • ClusterIP Serviceを使用すると内部同士のアクセスはできるが、外部からのアクセスはできない

NodePort Service

  • クラスタ外からアクセスできるようにするService
  • ClusterIP Serviceの機能を包含している

LoadBalancer Service

  • 主にクラウドプラットフォームで提供されているロードバランサと連携するためのService
  • GCPであれば、Cloud Load Balancingと連携するためのService
  • AWSであれば、Elastic Load Balancingと連携するためのService
  • NodePort Serviceの機能を包含している

External Service

  • selectorもport定義ももたないService
  • クラスタ内から外部ホストを解決するためのエイリアスを提供する

参考

cstoku.dev

qiita.com