kubernetes
docker等のコンテナのオーケストレーションシステム
#k8s とも表記する
official: https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/
学習にはkubekoda https://www.katacoda.com/
masterと呼ばれるコントローラーがNodeを管理
Node上で実際のコンテナ群であるPodが稼働
Podを動かすNodeをWorkerと呼ぶ
どのNodeにどのPodを動かすかはMasterがコントロールする。
MasterにAPI経由で指示をする
masterの持つ機能を総合してControll Planeと呼ばれる
Maseter 機能
kube-spiserver
etcd
node-controller
replica-controllerS
Worker 機能
kubelet
コントロールプレーンと連携してk8sのコンテナを動かすデーモン
container runtime
各機能はModuleという単位で呼ばれる
Deployment
Service etc
WSLにinstallもできるらしい
minikubeとかとりあえずローカルで使うのに便利
Ingress -> Service -> Pod
PodへのアクセスをコントロールするためのリソースとしてのIngressとService
ServiceはclusetrIPを付与して同一クラスタ内でのみ公開
Ingressリソースで作られるLoadBalanserを通じてServiceをクラスタ外へ公開
pathごとに別のServiceへルーティングとかもできる
Podの指定はselectorで
あくまでPodを指定している
Deployment -> ReplicaSet -> Pod
Deployment、ReplicaSetはPodを管理するためのリソース
Pod
https://kubernetes.io/docs/concepts/workloads/pods/
アプリケーションをホストするアプリケーションコンテナとそれに不随する以下の共有リソースをまとめた概念
共有ストレージ
ネットワーク
コンテナのイメージバージョンや使用ポート
1Podに複数コンテナとかもありうる。
コンテナをまとめた概念がPod
ユーザーからのアクセスを受け取るコンテナ、内部処理をするサイドカーコンテナをセットにできる。
yamlで定義。
この手のリソース管理系のファイルをmanifestと呼ぶ。
環境ごとの差分管理面のために実際は生yamlではなく、kustomize, jsonetを利用する
code:pod.yaml
//api versionは kindによって変わる
//POD v1, service,v1, ReplicaSet apps/v1, Deploymnet apps/v1
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: myapp //key:value。自由に付けれる。
spec:
replicas: 2
containers: //配列なので複数定義可能
- name: nginx
image: nginx:latest
kubectl get podsでpodの状態確認
ライフサイクルという寿命がある。
ReplicaSetで自動的にもとに戻る。
実際のところPodを直接定義せずDeploymentあるいはJobとして定義するのが良い。
Service
PODを外部公開するためのリソース
Seriviceで各PODを接続することでmicro service的にサービスを定義できる
Podの論理セットとアクセスに必要なポリシーをまとめたもの
複数のコンテナで構成されたPodのうちどれか1つにアクセスさせたいときに使う
リバースプロキシ
Serviceによって適切なPodにパケットがルーティングされる。
クラスタ外部、または内部のみに公開とコントロールできる。
PodがNodeを跨いでいても利用者は気にしなくてもよい。
YAMLで定義
code:service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector: // selectorでserviceとしての対象を指定 replicasetまたはdeploymentを指定
component: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
ServiceとPodセットの紐づけはLabel,Selectorで決定。
Labelはkey/valueのペアのタグでしかない。
versionやprod,stage,dev等の識別に使える。
SelectorはSeriviceで紐づけるLabelの指定をするためのもの。
公開するうえで複数のtypeがある。https://kubernetes.io/docs/tutorials/services/source-ip/
ClusterIP(default): クラスタ内部IPでServiceを公開。クラスター内でのみ到達可能
NodePort: NATを利用してクラスタ内のノードへアクセス
外部からNodeIP:NodePortでアクセス可能。Port forwadring。
ロードバランシングも可能
NodeのIPで外部公開
外部公開するnodePortはdefaultでは 30000-32767しか使えない
minikube service myapp-service --urlで外部公開のURLを出力できる
LoadBalance: 別途ロードバランサーを作成して、Serviceに外部のIPを割り当てて公開。
ExternalName: CNAMEで名前ベースでforwardingして公開。
Deployment
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
k8sのPod,Replicasetのアップデート、デプロイ方法について定義
これがあるので直接Pod, ReplicaSetを定義することはあまりない。
ローリングアップデート
障害時のセルフヒーリング
たとえ1台構成でもDeploymentとしてPod,ReplicasSetを構築しておくとよい
実際はPod,ReplicaSetで直接定義せずDeploymentとして定義するのがほとんど
code:deployment.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
component: nginx
spec:
replicas: 3
selector:
matchLabels:
component: nginx
template:
metadata:
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
pod-template-hashが自動で付与される
定義に変更があるかコントローラーの判断に使う。勝手に変更しない事。
kubectl create deploymentで構築
docker hub等のdocker imageを指定
稼働中のサービスでimageを変えるとローリングアップデートする
defaultの Strategy TypeはRollingUpdate
すべてのpodを削除して新規PODを一気に作り直すRecreateもある
この場合は全てのPODを削除したタイミングで全断する。
時間制約や新旧の互換性に問題なければrolling updateでよい。
変更ログを内部で保持されているのでundoコマンドでimage versionを戻すローリングアップデート可能
kubectl rollout undo deployment/nginx-deployment
kubectl apply
対象とするオブジェクトの状態に応じて自動でcreate, replace,patchを実施する。
ConfigMap
コンテナイメージから設定データを分割するためのリソース。
key、valueで登録して置いて他のPodから参照させる
Secretという機密情報を書くのするためのリソースもある
Secretリソース作成のためのマニフェスト自体は暗号化されていないので注意
あくまでk8s上で
ヘルスチェック
k8sでコンテナの監視をする上での死活監視用ヘルスチェック(Prob)がある
LivenessProbe
コンテナの生存チェック用。このProbeが通らなくなった時に死亡判定でコンテナが再作成
ReadinessProbe
コンテナがReady状態になっているかのチェック用
初期のロード処理、重いリクエストで動作中だが新規リクエストがさばけない時
コンテナをサービスから切り離す。再作成はされないので途中の処理は止まらない
Probには次の種類がある
exec
コンテナ内でコマンドを実行する
httpGet
httpGetリクエストの発行
tcpSocket
tcp connectionが確立できるか
authentication
k8sではクラスタに不特定多数がアクセスできる想定なので認証の仕組みが複数ある
https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies
https://knowledge.sakura.ad.jp/21129/
https://amateur-engineer-blog.com/kubernetes-user/#toc10
Service AccountとUser Accountに二種類ある
Service Account
Podで動くプロセスのためのもの
k8sの管理対象、ネームスペースに紐づく
User Account
クラスタレベルでネームスペースに紐づかない
k8sでは管理されない。ユーザーのオブジェクトはk8s上には存在しない
kubectl get sa
kubectl create sa
Service Acount作成コマンド
namespceごとに自動的にservice account defaultを作成する。
~/.kube/configにkubectlで利用するユーザー認証情報を保存
認証方式
Token File認証
ユーザー名とトークンを列挙したトークンファイルで管理
X509証明書認証:
認証のためにk8s構築時に登録したCAから発行したクライアント証明書を使う
/etc/kubernetes/pki/ca.crtがkubeadm作成時でのデフォルトCA
/etc/kubernetes/pki/ca.keyがCA鍵
このCA証明書と鍵からで受け取ったユーザーのCSRで署名証明書を発行
コンテキスト追加
code:ユーザー追加例
# 秘密鍵生成
openssl genrsa -out user.key 2048
# CSR生成
# Organization Name(ex: system:masters)とCommon Nameに適切に値を入れる
openssl req -new -key user.key -out user.csr
# CSRをk8s master nodeに送りCAで署名
openssl x509 -req -in user.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out user.crt -days 350
#testuserユーザーの認証情報登録
kubectl config set-credentials testuser --client-certificate=user.crt --client-key=user.key --embed-certs=true
# kubernetes cluster定義
kubectl config set-cluster kubernetes --server=https://1.2.3.4:6443 --insecure-skip-tls-verify=true
#[kubernetes」クラスタと「testuser」ユーザーを紐付けた「test」contextを作成
# testuserに権限を付与が必要。初期はtestuserは無権限なので何もできない。
kubectl config set-context test --user=testuser --cluster=kubernetes
# context change確認
kubectl config use-context test
authorization
kubectl get clusterrolebinding,rolebinding --all-namespaces=true
RBAC(Role Based Access Control)リソースであるRole,ClusterRoleリソースを作成
この二つにユーザーを紐づけるRoleBiding,ClusterRoleBindingリソースを作成
kubectl apply -f RoleBinding.yaml
code:RoleBinding.yaml
# User tanisobeとClsuterRole cluster-adminを紐づけするBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tanisobe
subjects:
- kind: User
name: tanisobe
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Networking
Podごとにアドレス付与。
完全にinternalなIP。internalなネットワークなのでそのままでは外部接続性はない。
PODへのアクセスもそのままではできない
PODを外部公開するためにはService リソースを利用
外部へ通信はk8sで用意したNAT越しに通信
ノード間通信はCNIによって解決
CNIがネットワーク周りをすべて解決する。
CNI
calico
flannel
cilimu
VXLANでoverray netowrkをNode同士で組むことでノード間ネットワークを構築
flannel
overray networkを組まずにBGPでpod IPを外部広報したりとか。
calico
debug
kubectl logs -l POD
PODのログをみる
kubectl port-forward deployment/nginx 8080:80
指定したPOD、DEPLOYMNETへポートフォワード設定
あくまでどれか一つのPODへのポートフォワードなのでプロキシ先のPODが死ぬとプロキシ接続は切れる。
一度切れたらもう一度コマンドを発行し直すこと
component
以下のpodが動作している
kube-apiserver
コントロールプレーンで動作
外部へk8s apiを提供するフロントエンド
kube-controller-manager
もろもろのコントロールプロセスを実行
kube-proxy
各ノードで動作
クラスタ外、内からPodにアクセスするためもの
実装としてはiptablesで行われるのがデフォルト
要はIPレベルで各PODへパケとを振り分けを行ったり、逆にNATしたり
kube-scheduler
コントロールプレーンで動作
Podのノード割り当て監視、またPodの割り当てを管理
etcd
k8sのデータ保管場所
バックアッププランを用意すること
クラスタ構築
今時自前で構築するなという話はあるんだが、やらなきゃいけないときもある。
kubeadm
#k8s