Skip to content

Instantly share code, notes, and snippets.

@koolii
Last active January 15, 2020 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koolii/95d48d27455b23d3ccdd0d9f4864f95b to your computer and use it in GitHub Desktop.
Save koolii/95d48d27455b23d3ccdd0d9f4864f95b to your computer and use it in GitHub Desktop.

セルフ・ヒーリング

実行条件にはプロセス監視以外にHTTP/TCPやシェルスクリプトで成否を設定することも可能

サービスディスカバリ

  • Istio
  • Linkerd
  • Contour
  • Ambassador

Envoy

Envoyを並べて、最初にそれを受けて、本体のコンテナへプロキシさせる

NodePool

各ノードにラベルを貼り付けることにより、Podをスケジューリングする際に選択基準の一つにすることが出来る (例えば、メモリ多いノード郡、CPU性能が高いノード郡等)

namespace

kube-publicに全ユーザが共通して使用する設定値(ConfigMap)を配置 Namespaceだけでは完全な分離性が確保されていないので、RBACやNetwork Policyで分離性を高める

kubens kubectx

namespace/contextを変更することを容易にする為のコマンド

Podに複数コンテナを作成するデザインパターン

例としては、プロキシ・設定値の動的な書き換え・ローカルキャッシュ用・SSL終端用等がある。 デザインパターンとしては

  • サイドカーパターン: メインコンテナに機能を追加する(データや設定関係が多い)
    • 特定の変更を検知した際に動的に設定を変更する
    • Gitリポジトリとローカルストレージを同期する(これは使えるかもしれないアプリケーションのアップデート)
      Pod コンテナA(Application) <- サイドカー <- Git Syncer
    • アプリケーションのログをオブジェクトストレージに転送する
  • アンバサダーパターン: 外部システムとのやり取りの代理で行う
    • アンバサダーコンテナで使用するDBを選択、メインコンテナからはDBにlocalhostで接続することで依存性を下げる
  • アダプターパターン: 外部からのアクセスのインターフェースとなる

サイドカーでメインコンテナに終了フラグ的なものを渡して、プロセスを終了させる、または更新されたソースコードにするとか? プロセスが終了するとセルフ・ヒーリングが動作するので。

Deploymentは使用できなくてもReplicaSetを使ってセルフヒーリング機能だけでも使用したい。 世代管理はラベル等でどうにかするしか無い。(ローリングアップデートはできない)

1つのcontainerPortを複数のコンテナが使用した場合にどうなるか -> 1つ目以降のコンテナは起動しなくなった

理由はPodはネットワークの名前空間を共有しているため(やはりPodに1つのNICが割り当てられている仕様の為) 例となるマニフェストを提示

apiVersion: v1
kind: Pod
metadata:
  name: simple-2-pods
spec:
  containers:
    - name: nginx-container-112
      image: nginx:1.12
    - name: nginx-container-113
      image: nginx:1.13

Deployment更新の一時停止

コマンドを使ってDeploymentoを変更しても適用は一時停止させることが出来る

停止) kubectl rollout pause deployment sample-deployment 再開) kubectl rollout resume deployment sample-deployment

DaemonSetの更新

1ノード1Podという制約があるため、Deployment(maxSurge: 超過可能Pod数)を選択出来ず、停止可能Pod数(maxUnavailable)で調整をする 例えばこれを2に設定すると、2つずつ更新が行われる

StatefulSet (ReplicaSet亜種)

StatefulSetによって作成される各Podに対して、PersistentVolumeClaimを設定すると、PersistentVolumeをPodにアタッチすることが出来るようになる これにより、Podの再起動時や別ノードへの移動時に同じデータを保持した状態でコンテナが再生成されるようになる

コンテナ内からの bind(listen)しているポートの確認

ss -napt | grep LISTEN

Deploymentなどの履歴データの残し方 --recordを追加

kubectl apply -f sample-deployment.yaml --record

Deploymentなどのアップデート状況を見たい

kubectl rollout status

ヘルスチェック

  • Liveness Probe: Podが正常に動作しているかの確認(失敗時はPodを再起動)
  • Readness Probe: Podがサービス飲する準備がで来ているかの確認(失敗時はトラフィックを流さない、Podも再起動しない)

ヘルスチェック方式(Pod内の全てのコンテナに実行され、どれか一つでも失敗した場合にはPod全体が失敗したとみなされる)

  • exec: コマンドを実行し、終了コードが0でなければ失敗
  • httpGet: HTTP GET リクエストを実行し、Statusが200-399でなければ失敗
  • tcpSocket: TCPセッションが確立出来なければ失敗

exec

livenessProbe:
  exec:
    command: ["ls", "/usr/sbin/nginx"]

httpGet

設定は細かい所まで行うことが可能

livenessProbe:
  httpGet:
    path: /health
    port: 80
    scheme: HTTP
    host: web.example.com
    httpHeaders:
      - name: Authorization
        value: Bearer TOKEN

tcpSocket

livenessProbe:
  tcpSocket:
    port: 80

Podの様子を監視する便利なコマンド

kubectl get pods sample-readiness --watch

コンテナのライフサイクルと再始動の restartPolicyプロパティ

  • Always: Podが停止すると、常にPodを再起動
  • OnFuilure: Podの停止が予期せぬ停止(終了コード0以外)の場合、Podを再起動させる (これがdockerの stopedなんとかか)
  • Never: Podが終了しても、Podを再起動させない

PriorityClassによるPodの優先度と退避

Kubernetes v1.8から導入されたPrioirtyClassを使うことで、Podがすでにリソースの限界までスケジューリングされている状態で より優先度の高いPodを作成しようとする場合に、既存のPodを退避させる事が可能になる

ReplicaSet自体を削除すると

それに紐づくPodも全て削除されてしまう。仕様上で停止機能はないので、削除するしかない。 Podのラベルを更新させて、ReplicaSetに紐付かないようにすると、ReplicaSetを削除したとしてもPod自身は残り続ける

ただし、ReplicaSetを削除するということはロールバック処理ができなくなる。 kubectl rollout undo ができなくなる。 が、一世代前のマニフェストを使って kubectl apply -f replicaset_manifest.yaml を実行すれば一つ前の物を作成することが出来る

TODO

  • Deploymentでローリングアップデートする時に、どうやってPodを選定しているのかを調査したい
  • リリース時に現時点でproduction投入されているReplicaSetだけ(Podには何もしない)を停止・削除処理をすると、セルフヒーリングは機能しなくなると考えたが、どうだろうか
  • セルフヒーリングが動作しないのであれば、ヘルフチェック等でリクエストを受け付けない設定にして、最終的に自身を終了するようにすれば行けるような

使用するモジュール

  • サイドカー
    • プロセスを終了させるステータス・フラグ/アプリのバージョン等のようなものをもたせる(メインコンテナで動作させるのが領域外と思われる)
    • またはメインコンテナで終了しても良いのかという状態をチェックさせる必要があるのならメインコンテナ側で終了可能チェックを追加しても良さそう
    • ヘルスチェックでそれをチェックし、メインコンテナ共々Podを終了させる
  • ReplicaSet:
    • セルフヒーリング(Pod数の担保)
  • Label
    • 更新/変更処理
    • ReplicaSetに紐付いているラベルを更新させる
  • restartPolicy(コンテナ)
    • onFailure
    • Podを再起動させない仕組み
  • ヘルスチェック
    • Readness Probe
    • これ以上アプリがアップデートされリクエストを受け付けたくない時

起動動作

  • PodをReplicaSetで作成する。 (この時ReplicaSetとPodのマニフェストを同一ファイル上に記述するかは考慮する必要がある
  • マニフェスト上にReadness Probeヘルスチェックを加えて、リクエストを受け付けなくなる条件を定義
  • kubectl apply -f f.yamlでReplicaSet/Podを生成

更新動作(組み方によってはDeploymentまで使えないかな?)

  • 新しいアプリが入った、ReplicaSetを新規作成する。その分のリソースは必要。あとからReplicaSetの数を増やせるので最初は小さくても良い。(A/Bテスト的に)
  • ReplicaSetを削除したい(理由はセルフヒーリング機能を起動させたくない、ただエラーがこの間に発生してしまうとどうする)
  • PodのラベルがReplicaSetに紐付いているので、ReplicaSetまたはPodのラベルを紐付かないように更新
  • ReplicaSetを削除
  • Podの処理が完了するまで待機
  • Podが現在の処理を終了し、手持ちタスクがなくなったらPodが死んでも良い状態になる
  • サイドカー等で新しいバージョンが来ていることを確認できるようにし、メインコンテナの状態を合わせてヘルスチェックが失敗する
  • Podがリクエストを受け付けなくなり、ただRunning状態になる
  • [ReplicaSetのときのラベルまたは、更新したラベルを使って、Podを削除する?]
  • [Podは restartPolicy: onFailure なので、Podは自分自身で終了してくれる?メインコンテナが正常終了すれば]
  • ReplicaSet/Podがなくなる

ロールバック動作

  • 削除したReplicaSetを再度作成し直す必要があり、一つ前のReplicaSetのマニフェストを使って kubectl apply -f file.yamlを実行
  • 新しいバージョンのアプリが入ったReplicaSetは削除
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment