nokoのブログ

こちらは暫定のメモ置き場ですので悪しからず

Kubernetesについて調べたことメモ

はじめに

  • Kubernetesまわりについて復習したときのメモ

参考

メモ

Docker全般

  • コンテナとは
    • ホストOS上に論理的な区画(コンテナ)を作って、一つのサーバのようにしたもの
  • コンテナの利点
    • アプリケーションのポータビリティ
    • 軽量で高速に動作する
      • サーバ仮想サーバと比較してオーバーヘッドが少ない
  • その他
    • プロキシ配下で使うとき
      • /etc/systemd/system/docker.service.d 配下にconfファイルを作成してフラッシュ & Dockerデーモン再起動

Kubernetes全般

  • オーケストレーション
    • マルチホストで構成されたクラスタでコンテナを運用するのに必要になってくる
      • 起動停止、ホスト間のネットワーク接続、ストレージ管理、どのホストで稼働させるかなどのスケジューリング機能、監視
    • クラスタを構成するノードとリソースの管理
    • アプリケーションのスケジューリング
  • Docker Compose
    • 複数のDockerコンテナをサービスとして定義/実行するための、コマンドラインツール
      • 複数コンテナ/イメージの同時構築・同時実行・ログ表示
    • -> しかし、コンテナの常時監視する機能がない、複数のクラスタにデプロイできない
    • -> Swarmが生まれた
  • Kubernetes
    • コンテナに対応したアプリケーションクラスタ環境上へ自動的にデプロイするためのオープンソースフレームワーク
    • Kubernetesが目指すところ
      • システム構築のための手作業を減らす
      • システムをセルフサービスで運用する
    • エコシステム
      • パッケージ管理: Helm(apt-get的な)
      • モニタリング: Prometheus
      • ログコレクタ: Fluentd
      • 分散KVS: etcd
      • コンテナランタイム: containerd
      • サービスメッシュ: Istio
    • 「宣言的設定」と「APIセントリック」が特徴
    • 分散システム
      • 分散システムの設計と運用は、例外処理との戦い
    • kubectl
      • Kubernetesクラスタの状態を確認したり、構成を変更したりするためのもの
      • 認証
        • ~/.kube/configに書かれている情報をもとにクラスタへ接続する
        • 接続先のサーバ情報や認証情報
      • kubectl コマンド タイプ 名前 フラグ
        • リソース: Kubernetesでは、コンテナアプリケーションであれネットワークであれジョブの実行であれ、全てリソースという抽象化した概念で管理する
        • 名前: リソースには識別するための固有の名前がついている

Kubernetesのサーバ構成

  • ハードウェア構成
    • クラスタを構成するマシンはMasterとNodeの二種類
    • Masterは奇数台。(etcdの特性に起因)

Kubernetesクラスタへのデプロイの仕組み

  • ① Masterに対してデプロイすべきコンテナのイメージや個数などの情報を指示する
    • Masterが提供するAPIサーバーに対してRESTでリクエストを送信(通常はラップしたkubectl)
  • ② Masterは指示された構成情報をetcdに永続化する
  • ③ Masterは情報に基づいて、コンテナをデプロイすべきNodeを決定する
    • MasterのSchedulerが、コンテナなどのリソースをどのNodeにデプロイするかを決定する
  • ④ MasterはNodeに対してコンテナの実行を指示する
    • NodeのKubeletがMasterと通信
  • ⑤ Nodeは必要に応じて指定されたコンテナイメージをpullしたうえで実行する
    • MasterのContoroller Manager
      • 指定したコンテナが、指定した個数だけ稼働しているかチェックしてくれる
      • リソースの変更を監視しており、変更を検知すると必要なコントローラを実行してくれる

Kubernetesコンポーネント

f:id:noko_htn:20200725143009p:plain

  • Master
    • API Server
      • リソース情報を管理するためのフロントエンドのREST API
      • コンポーネントからリソースの情報を受け取りデータストア(etcd)上に格納する
      • API Serverへのアクセスは基本的にkubectl
    • Scheduler
      • PodをどのNodeで動かすかを制御する(Podの配置先の割り当て)
    • Controller Manager
      • クラスタの状態を監視し、あるべき状態を維持する
      • 定義ファイルで指定したものと実際のNodeやコンテナで動作している状態をまとめて管理する
    • データストア(etcd)
      • どのようなPodをどう配置されるかなどの情報を持ち、API Serverから参照される
      • マニュフェストの内容が保存される
  • Node
    • kubelet
      • エージェント
      • Podの定義ファイルに従ってコンテナを実行したりストレージをマウントしたり
        • Nodeのステータスを定期的に監視、API Serverに通知する
    • kube-proxy
      • 様々な中継、変換を行うネットワークプロキシ

Kubernetesのリソース

アプリケーションの実行

  • Pod
    • Kubernetesではコンテナを素の状態でデプロイしない
    • 一個以上のコンテナを包含する「Pod」という単位でデプロイする
    • 「1コンテナ:1プロセス」を守りつつ複数プロセスを協調動作させるための仕組みがPod
    • Pod内の全コンテナが同一のNodeにデプロイされることが保証される
    • Pod内の複数のコンテナで仮想NIC(プライベートIP)を共有する
    • localhostでコンテナ間が通信できる
  • ReplicaSet
    • Deploymentとの使い分けに注意
    • オートヒーリングの機能を実現するためのリソース
    • Podを直接デプロイすることもできるが、Podに障害があっても自動回復しない
    • -> ReplicaSetは、稼働しているPodの数がreplicasと一致しているかどうかをチェックする
    • = クラスタ内で指定された数のPodを起動しておく仕組み
    • クラスタ内にPodをいくつ起動しておくかの値をレプリカ数と呼ぶ
    • もしPodが一つ異常終了したら、すぐに新しい別のPodを一つ起動する
    • Podのヘルスチェック
  • Deployment
    • 単純なアプリケーションのデプロイは、Pod・ReplicaSet・Serviceでいい。
    • -> Podを一つずつ更新していく、ローリングアップデートやロールバックを宣言的に行う仕組み
    • -> Deploymentを利用する場合は、ReplicaSetを明示的に作成せず、Deploymentによって自動的に生成されたものを利用するようになります
    • ReplicaSetの履歴を持つことで、ローリングアップデート・ロールバックを可能にする
    • Deployment作成コマンド
      • kubectl create -f nginx-deployment.yaml --record
  • DaemonSet
    • ReplicaSetは、どのマシンに配置されるが分からないが、どのノードにも配置したいPodがある
    • ログコレクタなど
    • 実はkube-proxyもこのDaemonSetを利用して動いている

ネットワークの管理

  • Service
    • ネットワークを管理する仕組み
    • PodにアサインされるIPはランダムに割り当てられる
    • -> Serviceはあるサービスの入り口となり、複数のPodで構成されるサービスを代表する
    • いくつか種類がある
      • LoadBalancer
        • Serviceに対応するIPアドレス+ポート番号にアクセスすると、複数のPodに対するL4レベルの負荷分散が行われる
    • Cluster IP と External IP
      • Cluster IP: クラスタ内のPod同士で通信するためのプライベートIP。
      • External IP: クラスタの外部に公開するIP。環境変数として参照できる。
    • External Service
      • RDBに接続するなど、PodからKubernetes外のサービスにアクセスするための仕組み
      • 外部サービスをクラスタ内のサービスと同様に扱うことができる
  • Ingress
    • L7の機能を提供

アプリケーション設定情報の管理

  • ConfigMap
    • 環境依存情報をコンテナイメージに含めてしまうと、環境ごとにコンテナイメージをビルドし直すことになり、ポータビリティが損なわれてしまう
    • -> 環境情報はConfigMapに分離しておく
    • ボリュームとしてマウント、環境変数やPod定義のパラメータとして参照する
  • Secret
    • 特殊なConfigMap
    • バイナリデータを格納(Base64エンコード
    • データはメモリ上に展開される(ディスクに書き込まれない)
    • 暗号化された状態でetcdに書き込まれる

バッチジョブの管理

  • Job/CronJob
    • Podは停止=異常終了だが、JobまたはCronJobは停止=ジョブの終了
    • ReplicaSetのバッチジョブ対応版
    • なぜJobを使うのか
      • Node障害時に別のNodeで実行
      • プロセス異常終了時の再起動
        • 処理が成功するまで、JobコントローラがPodを作り直す
      • タイムアウト
      • 実行回数と並列度

その他のリソース

  • ボリューム系
    • emptyDir
      • Podと同じライフサイクル
      • Podの消滅時に削除される
      • -> 同一Pod内の複数コンテナ間でのファイル共有のために利用される
    • 外部ストレージ
      • NFSAWS EBSなど
      • Podの定義の中で、ボリュームの定義 -> コンテナのvolumesMountsの定義から参照し、コンテナ内のマウントパスを指定、もできる
      • -> が、Pod定義が環境依存になるので、PersistentVolumeを使う
    • PersistentVolume
      • 外部ストレージを、Podから見て抽象化
      • 利用フロー
        • インフラ担当がNFSなどを用意
        • -> クラスタ担当がPVとしてKubernetesに登録
        • -> アプリケーション提供者がPVCを作成
        • -> KubernetesがPVCの条件に合致するPVがあればPVCとPVをバインドする
      • -> が、クラスタ管理者がPVを事前に準備しておく必要があるので、ダイナミックプロビジョニングを使う

Kubernetesの運用

拡張性

  • HorizontalPodAutoscaler(HPA)
    • 指定したメトリックをコントローラがチェックし、負荷に応じて必要なPodのレプリカ数になるよう自動でPodを増減する
    • Metric Serverを使ってリソースの使用状況を収集する
    • マニュフェストとしては、kindがHorizontalPodAutoscalerで、scaleTargetRefにスケールするReplicaSetを指定する
    • メトリックの収集は、Nodeで動くkubeletのcAdviserというエージェントで行う
    • メトリックをまとめて管理するのがMetric Server。Podの一つとして動いている。収集したメトリックの情報はメモリ上で管理する。
  • ノードのスケール
    • HPAとCluster Autoscalerは共存できる
    • 自動スケールのメトリックとして、外部のメトリックを使ったりもできる
      • メッセージキューを使うことが多い

運用作業

  • バージョンは、MasterおよびNodeの両方に気を配る必要がある
  • NodeのバージョンがMasterのバージョンより3つ以上古くなると、そのNodeは正しく動作しない場合がある
  • サーバのアップデート=OSや導入しているパッケージのアップデートを指す
  • unattended-upgradesパッケージを使ったり
  • 再起動をどうするかがポイント
    • Cordon/Uncordon/Drain

監視

  • Liveness Probe

その他

  • アドオンコンポーネントのPodはMasterではなくNodeに配置される
  • リソース分離で一番分かりやすいのはクラスタの分離。次に大きいのはNameSpace。
  • User Account と Service Account
    • Kubernetesは「人」を管理する仕組みがない
    • 一般ユーザを管理せず、統合管理できる外部のID管理システムにそれを任せている

Kubernetesの設計のポイント

  • ラベルのルール
    • 本番/開発環境
    • プロジェクト
    • GPU付き
  • リソース分離
    • NameSpace
      • プロジェクト
      • defaultは使わないように?
  • NodeSelector
  • Resource Requests
    • Podをスケジューリングするときは、実際のノードの使用量をチェックするわけではない
  • Limit Range
    • Namespaceで動く一つ一つのPodのリソース上限(総量ではない)
  • ResourceQuota
    • 総量を制限
  • 監視
    • メトリックバックエンド、ログ収集、ログバックエンド、可視化、アラート、サービス監視(外形監視)、オールインワン

ABC129-D_Lampをpythonで解いた(動的計画法)

問題

問題概要

任意のマスから光線が上下左右に伸びる(ただし、障害物は透過しない)。 明かりによって照らされるマスの個数を最大値を計算する。

解法

  • 障害物のあるグリッドなので、幅優先探索などの方法が考えられるが、上下左右にしか光線は伸びないので、ここはDPで解いていくのが良いと思われる。

方針

  • 今回の場合漸化式を解く際に一度にマスの計算をすることは難しい(理由は口頭で)。
    なので今回は以下のテーブルを準備する。 $$$ U[i][j] : \quad 上に何マス照らせるマスがあるか?\ D[i][j] : \quad 下に何マス照らせるマスがあるか?\ R[i][j] : \quad 右に何マス照らせるマスがあるか?\ L[i][j] : \quad 左に何マス照らせるマスがあるか? $$$ (ただし、$$D[i][j]、R[i][j]$$に関してはループの回す方向に注意する。)

更新式

$$$ U[i][j] = U[i-1][j] + 1\ D[i][j] = D[i+1][j] + 1\ R[i][j] = R[i][j+1] + 1\ L[i][j] = L[i][j-1] + 1 $$$ もし障害物のマスの場合は $$$ U[i][j] = 0\ ... $$$

最後合計のマスを計算する際、重複しているマス数3を引いておく。

コード

H,W = map(int,input().split())
S = [input() for i in range(H)]

U = [[0]*W for i in range(H)]
D = [[0]*W for i in range(H)]
R = [[0]*W for i in range(H)]
L = [[0]*W for i in range(H)]

for i in range(H):
    for j in range(W):
        if S[i][j] == '#':
            U[i][j] = 0
        elif i == 0 and S[i][j] == '.':
            U[i][j] = 1
        else:
            U[i][j] = U[i-1][j] + 1
            
    for j in range(W):
        if S[i][j] == '#':
            L[i][j] = 0
        elif j == 0 and S[i][j] == '.':
            L[i][j] = 1
        else:
            L[i][j] = L[i][j-1] + 1
            
for i in range(H-1,-1,-1):
    for j in range(W-1,-1,-1):
        if S[i][j] == '#':
            D[i][j] = 0
        elif i == H-1 and S[i][j] == '.':
            D[i][j] = 1
        else:
            D[i][j] = D[i+1][j] + 1
            
    for j in range(W-1,-1,-1):
        if S[i][j] == '#':
            R[i][j] = 0
        elif j == W-1 and S[i][j] == '.':
            R[i][j] = 1
        else:
            R[i][j] = R[i][j+1] + 1
            
ans = 0 

for i in range(H):
    for j in range(W):
        ans = max(ans,U[i][j]+R[i][j]+D[i][j]+L[i][j]-3)        
print(ans)    

written by 友達のtaniponyo

ABC128-D_equeueをpythonで解いた(その他)

問題

問題概要

宝石が$N$個横一列に並んでいる。
以下の4操作を$K$回まで行う。

  • 操作A: 左端の宝石を取る。
  • 操作B: 右端の宝石を取る。
  • 操作C: 持っている宝石から1個左端に置く。
  • 操作D: 持っている宝石から1個右端に置く。

方針

  • 全探索すると、$O(4K)$なので厳しい。
  • 操作C、Dは持っている宝石どれを置いてもよいので、先に操作A、Bをしてから操作C,Dをすれば良いのでは?$\rightarrow$実際正解。

解法

  • 左から$l$個、右から$r$個取り出し、どの宝石を戻すのかを探る。
  • 宝石の価値がマイナスになっているものを戻せばよい(ソートすればわかる)。

コード

N,K = map(int,input().split())
V = list(map(int,input().split()))

ans = -1

for l in range(N+1):
    for r in range(N+1):
        tmp = V[:l] + V[N-r:]
        if l+r > N:
            break
        res = K - (l+r)
        if res < 0:
            break
        tmp.sort()
        for i in range(min(res,len(tmp))):
            if tmp[0] < 0:
                tmp.pop(0)
            else:
                break
        ans = max(ans,sum(tmp))
            
print(ans)

written by 友達のtaniponyo

ABC127-D_IntegerCardsをpythonで解いた(その他)

問題

問題概要

カードが$$N$$枚あり、それぞれ整数$A_i$が書かれている。
$M$回以下の操作を行う。
カードを$B_j$枚まで選ぶ。選んだカードを$C_j$に書き換える
カードに書かれた数字の合計の最大値は?

解法

  • 小さい数字のカードを書き換えるのが正解?と思いきや、書き換えるカードの枚数は決まってはいないので、その解法では間に合わない。
  • カードの数字を書き換えることなく、計算する方法を考えよう。

方針

  • あらかじめ$C_j$で降順ソートしてあげ、$tmp += [C_j]*B_j$ といったリストを作成
  • $A + tmp$を降順ソートし、前から$N$枚の合計を計算することで、書き換えたこととなる。

$A = [1,2,3,4,5]$
$B,C = 2,3$
ならば、 $A + tmp = [1,2,3,4,5,3,3] = [5,4,3,3,3,2,1]$となり、$1,2$を書き換えるのが最善の操作である。

コード

N,M = list(map(int,input().split()))
A = list(map(int,input().split()))
BC = [list(map(int,input().split())) for i in range(M)]

BC.sort(key=lambda x:-x[1])
temp = []
for i in range(M):
    temp += [BC[i][1]]*BC[i][0]
    if len(temp) > N:
        break
    
A += temp

A.sort(reverse = True)

print(sum(A[:N]))

written by 友達のtaniponyo

ABC172-D_SumofDivisorsをpythonで解いた(約数)

問題

問題概要

Xの正の約数の個数をf(X)とするとき、∑K×f(K)

解法

ポイント

  • 整数問題は書き出して規則を捉える
    • 1から始まるときは(ある特定の区間でないときは)特に、一発で答えが出たりする
  • 横に集計しても、縦に集計しても同じ
    • -> 横に集計しづらいときは、縦に集計してみる
  • 約数の問題は、都度約数を求める場合と、小さい方から予めn倍して格納しておくといい場合がある

f:id:noko_htn:20200628205116p:plain

コード

n = int(input())

def calc(b, e):
    # 等差数列の和
    cnt = e // b
    return (b + e) * cnt // 2

ans = 0

for i in range(1, n+1):
    ans += calc(i, n//i * i)

print(ans)

ABC172-C_Tsundokuをpythonで解いた(累積和+二分探索or尺取り法)

問題

問題概要

  • 机が二つ。それぞれに本が積まれている。上から順に読んでいく。k分を超えない範囲で、何冊読めるか。

解法(1)

ポイント

  • 2つの変数の和の(条件下での)最大値を探す
    • -> 一つを固定して、二分探索 or 尺取り法
    • <- 単調増加であることが大事

f:id:noko_htn:20200628193949j:plain

  • 累積和
配列aに対して累積和sを求めると、配列aの区間[left, right]の総和が
s[right] - s[left]
でO(1)で求められる
from itertools import accumulate
a_list = list(map(int, input().split()))
# -> [60, 90, 120]

sum_a_list = list(accumulate([0] + a_list))
# -> [0, 60, 150, 270]
  • 二分探索
import bisect

example_list = [1,3,4,5,6,7,9,10,13,16,18,22,24,25,26] 
target = 22

example_list = sorted(example_list)

target_index = bisect.bisect_left(example_list,target)

print(target_index)

コード

n,m,k = map(int,input().split())
a_list = list(map(int,input().split()))
b_list = list(map(int,input().split()))

from itertools import accumulate
import bisect

sum_a_list = list(accumulate([0] + a_list))
sum_b_list = list(accumulate([0] + b_list))

ans = 0
b_idx = 0
for a_idx in range(n+1):
    if sum_a_list[a_idx] > k:
        continue

    time_rest = k - sum_a_list[a_idx]
    # 同じ数字を取った場合を考慮してleftでなくright
    b_idx = bisect.bisect_right(sum_b_list,time_rest) - 1

    ans = max(ans, a_idx + b_idx)

print(ans)

解法(2)

ポイント

* 実装イメージ
  * i(left)はfor文で最初から最後まで動かしていく
  * j(right)はwhile文で条件を満たす限り動かしていく
    * ポイントは、iをすすめるときに、jを初期化(i+1などに)しない。jはそのまま進めていく(ここで計算量を減らす)
    * = 単純に考えれば、right = left, left+1, left+2, ..., と調べて行って、条件を満たさなくなる場所を検出することで実現できるが、
    * ->left を固定して right を右に動かして、今度は left を 1 増やして...」という動きをさせる。この動きがしゃくとり虫のようなので、しゃくとり法と呼ばれます。

コード

n,m,k = map(int,input().split())
a_list = list(map(int,input().split()))
b_list = list(map(int,input().split()))

from itertools import accumulate
sum_a_list = list(accumulate([0] + a_list))
sum_b_list = list(accumulate([0] + b_list))

ans = 0
b_idx = m
for a_idx in range(n+1):
    if sum_a_list[a_idx] > k:
        continue

    while sum_a_list[a_idx] + sum_b_list[b_idx] > k:
        b_idx -= 1

    ans = max(ans, a_idx + b_idx)

print(ans)

システム構築案件が立ち上がったときにインフラ担当としてやっていること

はじめに

システム構築案件が立ち上がったときにインフラ担当としてまずやっていることをメモしました。抜け漏れはあります。

やったこと

1. スケジュール・マイルストーン確認

  • マスタスケジュール
    • 他システム、アプリ含めたスケジュール
    • → 全体の整合性を確認
  • インフラ構築スケジュール
    • 顧客、関連ベンダ含めた役割分担を認識合わせするため
      • 特にテストフェーズ
        • 仕様書作成
        • 環境構築
        • テスト実施
        • テスト結果レビュー、etc
    • マイルストーン確認
      • 対顧客、対アプリチーム
      • アプリチームへの環境引き渡しタイミングなど
    • 環境利用計画確認
      • 何面作ることになるか。いつまでに必要か。
  • → いつ誰が何をやるか、明確に

2. 成果物確認

  • 非機能要件定義書
    • 基礎数値表等
  • インフラ基本設計書
    • システム化方針
    • 全体システム俯瞰
    • アーキテクチャ構成
    • ネットワーク構成
    • ハードウェア構成
    • ソフトウェア構成
    • 処理方式概要
    • 製品・技術要素選定根拠
  • 監視設定一覧
    • 死活監視
    • ログ監視
    • リソース監視
  • バックアップ・リストア・改廃設定一覧(運用設定書)
  • 運用設計書
    • システム概要(サービス対象範囲)
    • 運用体制
    • 運用方針(サービス時間等)
    • 運用業務詳細
  • 運用作業手順書
    • リソース拡張
    • 監視設定追加・非監視設定
    • デプロイ
    • リストア
  • 非機能テスト仕様書
    • (インフラ単体テスト
      • パラメタ設定
      • 起動停止
      • 基本機能提供
    • (インフラ結合テスト
      • 業務処理通信
      • 運用処理通信
      • バックアップ改廃
      • アラート
      • 耐障害性
    • (セキュリティテスト)
    • 障害テスト
      • 可用性テスト
      • 監視通知テスト
    • 性能テスト
      • 負荷テスト
      • 限界テスト
      • 耐久テスト
    • (運用テスト)
      • キャパシティ管理
      • システムメンテナンス
      • システム監視
      • データ抽出
      • バックアップリストア
      • リリース
      • ログ管理
      • 障害対応
      • 定常作業
  • ソース

3. 直近のタスク確認

ヒアリング事項整理

  • 役割分担、制約条件をまず確認する

役割分担

  • Who: 担当者、関連ベンダ確認
  • Where, How: 作業担当スコープ整理+環境アクセス方法・モジュール連携方法確認
    • アカウント契約
    • DX契約
    • 構築作業
  • When: マイルストーン確認

制約条件

4. wiki整備(内部向け)

  • アプリ担当者向け
    • 環境構成図
    • 接続情報
    • 障害対応手順
  • インフラ担当者向け
    • 開発規約
    • ネットワーク
    • セキュリティ
    • デプロイ
    • 監視
    • バックアップ・リストア・改廃
    • テスト
    • 運用

5. WBS作成

  • 非機能要件定義作成
  • インフラ基本設計書作成
  • アカウント作成
  • ストレージ
  • ネットワーク
  • ルーティング
  • サービス
  • データストア
  • 運用環境(デプロイ)
  • 運用環境(セキュリティ)
  • 運用環境(監視)
  • 運用環境(バックアップ・リストア・改廃)
  • インフラ単体テスト
  • インフラ結合テスト
  • 性能テスト
  • 障害テスト
  • 運用テスト
  • 運用設計書作成
  • 運用作業手順書作成
  • 運用引き継ぎ

インフラエンジニアとしての心構え

  • システム(環境)全体を見れる立場から、早めにリスクを検知して潰し込み、リリースに着地させる義務がある
    • プロジェクトは想定通り行かない。想定外の事象が発生したときに、影響調査をして、誰がいつ何をすべきかを整理してインプットしていく。
    • 浮いてるタスクを検知し、論点を明確にした上で選択肢とメリデメを提示&ポジションを取る。

参考