😎

k8sの基礎をまとめてみた

2023/02/27に公開

kubanetesのアーキテクチャーに関して

red hadの公式ドキュメントより参照
https://www.redhat.com/ja/topics/containers/kubernetes-architecture

上記の図を見るとわかるがKubernetes クラスタは 2 つのパーツとして視覚化できます。コントロールプレーンと、コンピュートマシンつまりノードです。上記の図を見るとわかるがKubernetes クラスタは 2 つのパーツとして視覚化できます。コントロールプレーンと、コンピュートマシンつまりノードです。

コントロールプレーンとは

コントロールプレーンにはクラスタを制御する Kubernetes コンポーネントと、クラスタの状態と構成に関するデータがあります。これらは、Kubernetes のコアコンポーネントが、十分な数のコンテナが必要なリソースで実行されていることを確認するという重要な作業を担います。

簡単にいうと理想状態と現実状態のデータを取得し、理想状態に近づけようとする部分で理想状態の変更などのリクエストなども受け取る部分

各コンポーネントについて説明します

  • kube-apiserver

クラスター内部外部のやりとりをする部分
Kubernetes コントロールプレーンのフロントエンドであり、内部からの要求と外部からの要求を処理します。API サーバーは要求が有効かどうかを判断し、有効な場合は処理します。
ここでkubectlコマンドの指示を受け取ります。またkubeletとの通信を行いnodeに指示を出す

  • kube-scheduler

クラスターが理想状態であるかなどを監視し、新しいコンテナが必要な場合、どこにデプロイするのかなどを
Pod のリソースニーズ (CPU やメモリーなど) を考慮し判断する部分
どのwoker nodeで起動するのかなどを決める(スケジュール)する部分

  • kube-controller-manager
    コントローラーは実際のクラスタの実行を処理します。Kubernetes コントローラー・マネージャー 1 つで、いくつかのコントローラー機能を実行します。あるコントローラーはスケジューラーに問い合わせて、正しい数の Pod が稼働していることを確認します。Pod がダウンした場合、別のコントローラーが検知して応答します。あるコントローラーは、要求が適切なエンドポイントに送信されるようサービスを Pod に接続します。また、アカウントや API アクセストークンを作成するためのコントローラーもあります。

コントローラーの中核でcontrollerが理想状態かを判断し、思想状態でなければ各コンポーネントを操作し、理想状態に近づけようとする部分

  • etcd
    構成データとクラスタの状態に関する情報をkey-value 形式で保存する
    現在のクラスターの現実状態がここに保存される
    クラスター内に幾つのwoker nodeが起動しているのか
    各worker nodeに何のアプリケーションが起動しているのか
    リソースはどれくらい使われているのかなどが保存されている

コンピュートマシン(node)とは

各ノードは独立した Linux 環境または仮想マシンなどです。
すなわち実際の動作環境にあたる

Pod は、ノードで実行されるようにスケジュールされ、オーケストレーションされます。クラスタの容量をスケールアップする必要がある場合は、ノードを追加します。

  • Pod
    Pod は、Kubernetes オブジェクトモデルで最小かつ最も単純なユニットです。
    基本的には1pot、1コンテナが基本となるので、一つのコンテナだと思えば良い

  • コンテナ・ランタイム・エンジン
    コンテナを実行するために、各コンピュートノードにコンテナ・ランタイム・エンジンがあります。Docker は 1 つの例ですが、Kubernetes は rkt や CRI-O などの他の Open Container Initiative 準拠のランタイムもサポートしています。

  • kubelet

コントロールプレーンと通信する部分です。
kubelet は、コンテナが Pod で実行されていることを確認します。コントロールプレーンが、ノードでの何らかの処理を必要とする場合、kubelet がアクションを実行します。


podが起動した、エラーで停止したなどを送信する

  • kube-proxy

nodeのネットワークの管理をしている部分
各コンピュートノードには、Kubernetes ネットワークサービスを容易にするためのネットワークプロキシである kube-proxy も含まれています。kube-proxy は、オペレーティングシステムのパケットフィルタリング・レイヤーまたはトラフィック自体の転送に依存して、クラスタ内外のネットワーク通信を処理します。

k8sリソースについて

ワークノードについて

  • Pod: 基本1コンテナで最小単位
  • ReplicaSet: Podをいくつか合わせたもので、Podをスケールするもの
  • Deployment: ReplicaSetを世代管理するもの。ロールバックすることができる
  • StatfulSet: Deploymentと似ているが、Podをスケールする際に名前が一定ルールでつけられる

サービスについて

  • Service: 外部公開する部分で。L4ロードバランサー、名前解決する、内部ロードバランサー
  • ingress: 外部公開する部分で。L7ロードバランサー、名前解決する

設定系

  • configMap: 設定情報の保存
  • secret: 機密情報を保存する部分、base64エンコードして保存する

ストレージ

  • Persistent Volume: ストレージへの接続情報、ストレージを抽象化、永続化への実態情報になる
  • Persistent Volume Clain: 抽象化されたストレージ情報を要求する部分

k8sのネットワーク(kube proxyが管理)

nodeは実サーバーに一致し、リソースは各woker nodeに配置されます。
もちろんpodもリソースなので配置されます。

kubanetesはクラスターネットワークと外部ネットワークがあり外部ネットワークからはクラスターネットワークへは直接アクセスはすることができない

pcなどの端末は外部ネットワークに接続されているので、podにアクセスするためにはkubectlでexecして接続する、別の踏み台コンテナに接続して接続する方法、他にはデバッグ用のserviceを作成して接続する方法がある

k8sでhello worldコンテナを起動する

docker for mac のkubanetesを有効にしておいてください

下記でhello-worldというpod名でhello-world イメージを起動する

kubectl run hello-world --image hello-world

> pod/hello-world created

起動したことを確認

kubectl get pod

>
NAME          READY   STATUS      RESTARTS      AGE
hello-world   0/1     Completed   4 (61s ago)   2m3s

logを確認してみる

kubectl logs pod/hello-world

>
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

podを削除してみる

kubectl delete pod/hello-world

k8sの基本操作

k8sではマニュフェストファイルを作成して、それを下記コマンドで設定を適用される

kubectl apply -f マニュフェストファイルパス

適用されたリソースは下記で確認できる

kubectl get -f マニュフェストファイルパス

削除する時は

kubectl delete -f マニュフェストファイルパス


hellow worldコンテナ用のマニュフェストファイル作成

apiVersion: v1  <= kindにより記述が決まっている
kind: Pod  <=  リソースの種類
metadata:
  name: test
  namespace: default  <= namespaseの中で一意になるnameを指定する必要がある
  labels: <= ここは任意でキーバリュー形式で記載することができる
    env: study
spec:
  containers:
  - name: hello-world <= コンテナの名前を指定
    image: hello-world <= 起動するコンテナのイメージを指定

適用

kubectl apply -f hello-world.yml

確認

kubectl get -f hello-world.yml

podだけ確認するコマンド

kubectl get pod

削除方法

kubectl delete -f hello-world.yml

nginxのpodを作成してみる

apiVersion: v1
kind: Pod
metadata:
  name: test-1
  namespace: default
  labels:
    env: test
spec:
  containers:
  - name: test-nginx
    image: nginx:latest
kubectl apply -f nginx.yml

マニュフェストファイルコマンドと引数について

apiVersion: v1
kind: Pod
metadata:
  name: debug
  namespace: default
spec:
  containers:
    - name: debug
      image: centos:7
      command:  <= dockerでいうENTRYPOINT
        - "sh"
        - "-c"
      args: <= dockerでいうCMD
        - |
          while true
          do
            sleep ${DELAY}
          done
      env:
        - name: "DELAY"
          value: "5"

apiVersionの探し方

公式ドキュメントを見る
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#pod-v1-core

apiVerstionは上記のGroup/Verstionの形になる、Groupがcoreの場合が省略が可能

Kindは公式ドキュメントのKindを記載すればOK!

ingressのapiverstionを確認してみると
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#ingress-v1-networking-k8s-io

networking.k8s.io/v1

コンテナに入る

kubectl exec -it POD sh

コンテナから出る方法

プロセスを終了してログアウト
exit

プロセスを残したままログアウト
 ctrl P からのctrl Q

デバッグ用のcentOSからnginxのコンテナに接続する

apiVersion: v1
kind: Pod
metadata:
  name: debug
  namespace: default
spec:
  containers:
    - name: debug
      image: centos:7
      command:
        - "sh"
        - "-c"
      args:
        - |
          while true
          do
            sleep ${DELAY}
          done
      env:
        - name: "DELAY"
          value: "86400"

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest

接続に必要なipアドレスの確認 -o wide

kubanetes % kubectl get pod -o wide
NAME     READY   STATUS             RESTARTS         AGE     IP          NODE             NOMINATED NODE   READINESS GATES
debug    1/1     Running            0                2m18s   10.1.0.9    docker-desktop   <none>           <none>
nginx    1/1     Running            0                2m18s   10.1.0.10   docker-desktop   <none>           <none>
test     0/1     CrashLoopBackOff   16 (2m36s ago)   60m     10.1.0.7    docker-desktop   <none>           <none>
test-1   1/1     Running            0                46m     10.1.0.8    docker-desktop   <none>           <none>

デバッグPodからnginxに接続してみる

kubectl exec -it debug 

コンテナ内でnigixに接続

curl http://10.1.0.10

ホスト間でのファイル転送

基本コマンド

kubectl cp 転送元ファイル 転送先ファイル

ホストからPodにファイル転送

kubectl cp 転送元ファイル名 Pod名:転送元フォルダー名/ファイル名

Podからホストへのファイル転送

kubectl cp pod名:転送元ファイル名 転送先フォルダー名/ファイル名

状況の確認方法

kubectl describe 名前
で基本は確認できる

kubectl logs 名前でログが確認できる

nginxのアクセスログを確認してみる
pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: debug
  namespace: default
spec:
  containers:
    - name: debug
      image: centos:7
      command:
        - "sh"
        - "-c"
      args:
        - |
          while true
          do
            sleep ${DELAY}
          done
      env:
        - name: "DELAY"
          value: "86400"

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2-alpine

下記を実行すると

kubectl describe pod/debug

結果は下記で重要なのはEventの部分でEventが表示される

kubanetes % kubectl describe pod/debug
Name:         debug
Namespace:    default
Priority:     0
Node:         docker-desktop/192.168.65.4
Start Time:   Mon, 20 Feb 2023 23:51:42 +0900
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           10.1.0.9
IPs:
  IP:  10.1.0.9
Containers:
  debug:
    Container ID:  docker://ad6e3bde4200b39eb7b54cc7b20fdccadf509d58722f877341fc330a2b10078c
    Image:         centos:7
    Image ID:      docker-pullable://centos@sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
    Args:
      while true
      do
        sleep ${DELAY}
      done
      
    State:          Running
      Started:      Mon, 20 Feb 2023 23:52:17 +0900
    Ready:          True
    Restart Count:  0
    Environment:
      DELAY:  86400
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-5wpxj (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-5wpxj:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  23h   default-scheduler  Successfully assigned default/debug to docker-desktop
  Normal  Pulling    23h   kubelet            Pulling image "centos:7"
  Normal  Pulled     23h   kubelet            Successfully pulled image "centos:7" in 28.7877147s
  Normal  Created    23h   kubelet            Created container debug
  Normal  Started    23h   kubelet            Started container debug

デバッグ用のcentOSに接続し、ログを確認する
下記でcentOSのipアドレスを確認

kubectl get pod -o wide

デバッグPodにexecする

kubectl exec -it debug sh

>
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
sh-4.2# 

curlでnigixに接続する

sh-4.2# curl http://10.1.0.10

logを確認する

kubectl logs pod/nginx

結果

logs pod/nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/02/20 14:51:51 [notice] 1#1: using the "epoll" event method
2023/02/20 14:51:51 [notice] 1#1: nginx/1.23.3
2023/02/20 14:51:51 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2023/02/20 14:51:51 [notice] 1#1: OS: Linux 5.10.76-linuxkit
2023/02/20 14:51:51 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/02/20 14:51:51 [notice] 1#1: start worker processes
2023/02/20 14:51:51 [notice] 1#1: start worker process 31
2023/02/20 14:51:51 [notice] 1#1: start worker process 32
10.1.0.9 - - [21/Feb/2023:14:50:31 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"

k8sリソースについて

podマニフェストファイルについて

apiVersion: v1
kind: Pod
metadata:
  name: sample
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Never  <= Neverはローカルのイメージを使用、 Alwaysは毎回リポジトリから取得する、IfNotPresentはローカルに存在していれば使用なければリポジトリーから取得する
    commond: ["sh", "-c"] 
    args: echo "${MESSAGE}"
    env: [{name: "MESSAGE", value: "Hello world"}]
    volumeMounts: <= コンテナにマウントするストレージを指定する、マウントとはファイルを共有すること
    - name: storage  <= volumes.nameと一致させておく必要がある、ホストサーバーのどこに保存するかを指定する
      mountPath: /home/nginx  <= コンテナのどのディレクトリーと紐付けるかを指定
  volumes: <= 実際の保存場所を指定
  - name: storage
    hostPath: <= hostPathはPodの実サーバー上に保存、nfsはNFSサ
    ーバー、configMapやsercretはkubanetesリソースへ、emptyDirはからフォルダーへ保存される
      path: "/data/storage"
      type: Directory <= Directoryは実在するディレクトリー、DirectoryOrCreateは存在しなければ作成、File存在するファイル、FileOrCreate 存在しなければファイルを作成

nfs

configMap

Secret

replicsetについて

マニュフェスト

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3 <= podの起動数
  selector: <= templateに含めるpodのmetadataに合わせることでそのラベルを持つpodを3台起動することができる
    matchLabels:
      app: web
      env: study
  template:  <= podのマニュフェストと同じで起動したpodの情報を書く
    metadata:
      name: nginx
      labels:
        app: web
        env: study
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2-alpine

deployment

replicsetの集合でreplicsetの世代管理ができるもの
記述する部分はreplicasetと同じで、基本はdeploymentを使ってpodをコントロールする
マニュフェスト

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  annotations:
    kubernetes.io/change-cause: "ここのコメントがhistoryで表示される"
spec:
  replicas: 2
  selector: 
    matchLabels:
      app: web
      env: study
  revisionHistoryLimit: 14  <= replicasetの履歴保存数になるdefualは10
  strategy:  <= デプロイ方法を指定するもの
    type: RollingUpdate <= 基本的にはRollingUpdate
    rollingUpdate:
      maxSurge: 1 <= レプリカ数を超えて良いPod数
      maxUnavailable: 1 <= 一度に消失するPod数、ローディングアップデートのスピードを示す
  template:
    metadata:
      name: nginx
      labels:
        app: web
        env: study
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2-alpine

ロールアウトの履歴確認方法は

kubectl rollout history type/name

ロールバック方法は(オプションで--to-revision=Nで戻りたいリビジョン番号を指定できる)

kubectl rollout undo type/name [--to-revision=N]

serviceについて

serviceはL4ロードバランサー、名前解決、外部公開を行う部分

serviceの種類

  • ClasterIP
    クラスターネットワーク内にIPアドレスを公開
    名前指定でpodに到達する。主にデバッグ用などで使用される

  • NodePort
    ClasterIPに加え、Nodeのポートにマッピングすることで外部公開が可能になる

  • LoadBalanser
    NodePortに加えロードバランシングしながら外部公開が可能(内部公開もある)

  • ExternalName
    外部サービスに接続が可能

マニフェスト

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: web
    env: study
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2-alpine

---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  type: NodePort  <= serviceのtypeを指定する、typeがClusterの時はClusterIPでIPアドレス指定やNoneを指定するとHandlessサービスの作成が可能
  selector: <=転送先のpodを特定するためのlabel
    app: web
    env: study
  ports:
  - port: 80 <= サービスのポート受付番号
    targetPort: 80 <= コンテナに流すコンテナのポート
    nodePort: 30000 <= srvice typeがNodePortの時はnodeの受付ポートを指定する

ConfigMapについて

設定ファイルを集約する部分
環境変数として渡す方法とファイルをマウントすることでデータを渡す方法がある

configMapとpodのマニフェスト

apiVersion: v1
kind: ConfigMap
metadata:
  name: sample-config
  namespace: default
data:
  sample.cfg: | <= ファイルに保存する用のconfigMap sample.cfgファイルにデータが保存される
    user: test.user <= sample.cfgに初期状態から書かれることになる、ファイルマウントでこの情報ごとマウントすることでデータを送ることができる
  apllication_type: "application" <= key value形式で値を渡すための

---
apiVersion: v1
kind: Pod
metadata:
  name: sample
  namespace: default
spec:
  containers:
  - name: sample
    image: nginx:1.17.2-alpine
    env:
    - name: TYPE <= TYPEという環境変数にconfigMapのapllication_typeの値が設定される
      valueFrom: <= これでconfigMapの値を参照することができるようになる
        configMapKeyRef:
          name: sample-config <= 使いたいconfigMapのmetadataのname
          key: apllication_type <= 使いたい値のキー
    volumeMounts: <=コンテナにマウントする先を決める
    - name: config-storage
      mountPath: /home/nginx
  volumes: <= host側のマウント先を指定
  - name: config-storage <= volumeMountsと名前を一致させる必要がある
    configMap:
      name: sample-config <= configの名前を指定する
      items:
      - key: sample.cfg <= configMapのキーを指定
        path: sample.cfg <=何でもいいが同じものの方が良い!コンテナ側にpathを作成しそことキーに指定したconfigMapのフイルがマッピングされる

sercretについて

base64エンコードして保存
secret作成方法

  • コマンドを利用する方法
kubectl create secret generic 名前 オプション

オプション
--form-literal=key=value キーバリューを指定して生成
--form-literal=filename ファイルから作成

base64で文字列作成方法

echo -n '生成したい文字れつ' | base64

secretの使い道としてはconfigMapと同様に
環境変数として渡す方法とファイルとしてマウントする方法がある
事前に下記コマンドでsecretを生成しておく必要がある

kubectl create secret generic sample-secret --from-literal=message='Hello World !' --from-file=./keyfile

作成されたsecretからマニュフェスト作成

kubectl get secret/samle-secret -o yaml

マニュフェスト

apiVersion: v1
kind: Secret
metadata:
  name: sample-secret
data:
  message: SGVsbG8gV29ybGQgIQ==     # echo -n 'Hello World !' | base64 で出力した結果でもOK
  keyfile: WU9VUi1TRUNSRVQtS0VZ     # cat ./keyfile | base64 で出力した結果でもOK

---
apiVersion: v1
kind: Pod
metadata:
  name: sample
  namespace: default
spec:
  containers:
  - name: sample
    image: nginx:1.17.2-alpine
    env:
    - name: MESSAGE
      valueFrom:
        secretKeyRef:
          name: sample-secret
          key: message
    volumeMounts:
    - name: secret-storage
      mountPath: /home/nginx
  volumes:
  - name: secret-storage
    secret:
      secretName: sample-secret
      items:
      - key: keyfile
        path: keyfile

データ永続化(PersistentVolume(PV)とPersistentVolumeClaim(PVC))

  • PVについて
    ストレージへの接続情報とストレージを抽象化する部分
    永続化のボリューム自体を表すリソースです。

  • PVCについて
    PVを要求するもの。抽象化されたリソース情報を抽出するもの
    PVに対して必要な容量を確保するリソースです。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume-01
  labels:
    env: study
spec:
  storageClassName: slow <=ストレージの種類
  accessModes: <= アクセスのモードを指定する ReadWriteOnce: 単一ノードから読み書きする, ReadOnlyMany: 複数ノードから読み取りのみ行う, ReadWriteMany: 
  - ReadWriteOnce
  capacity: <= ストレージ容量の定義
    storage: 1Gi
  persistentVolumeReclaimPolicy: Retain  <= 削除時の動作を定義する, Retain: PVCが消えてもPVを残す, Delete: PVCが消えたらPVも消す, Recycle: 非推奨だが、対象ボリューム内のデータを削除して再利用する
  hostPath:  <= 保存先、今回はhostに定義するのhostPathだがNFSなどもある
    path: "/data/storage"
    type: Directory  <= Directory: 存在するディレクトリー, DirectoryOrCreate: ディレクトリーが存在しなければ作成, File: 存在するファイル, FileOrCreate: ファイルが存在しなかれば作成

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: volume-claim
  labels:
    env: study
spec:
  storageClassName: slow 
  accessModes:
  - ReadWriteOnce
  resources: <= PVではcapacityだったがPVCではリソースを要求するものなので、requestになる
    requests:
      storage: 1Gi

StatefullSetについて

Podの集合で、Podがスケールする際の名前が一定規則に沿ってつけられる

apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume-01
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 1Gi
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /data/storage
    type: DirectoryOrCreate

---
apiVersion: v1
kind: Service
metadata:
  name: sample-svc
spec:
  clusterIP: None
  selector:
    app: web
    env: study
  ports:
  - port: 80
    targetPort: 80

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
      env: study
  revisionHistoryLimit: 14
  serviceName: sample-svc <= headless Serviceを指定する(headless serviceとはcluster ipにNoneを指定したサービスであるとされています。 つまり、ロードバランサがサービスを公開するアドレスがないということです。)
  template:
    metadata:
      name: nginx
      labels:
        app: web
        env: study
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2-alpine
        volumeMounts:
        - name: storage
          mountPath: home/nginx
  volumeClaimTemplates: <= PVCの指定を書く
  - metadata:
      name: storage
    spec:
      storageClassName: slow
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi

動かしてみる

  • apply
kubanetes %  apply -f statefullSet.yml
persistentvolume/volume-01 created
service/sample-svc created
statefulset.apps/nginx created

デバッグ用podを起動してStatefullSet内のnginxのpodにアクセスしてみる

前提:
StatefulSetがHeadlessServiceを利用している場合、Pod名でIPアドレスを引くことができる
本来であればpodのipアドレスtがわからないとアクセスできないがHeadlessServiceを
使えばpod名でアクセスできるようになる

  • デバッグ用podを起動する
kubectl run debug --image=centos:7 -it --rm --restart=Never -- sh

補足: kebectl runによってpodを作成する時のrestart policy
引数はAlways, OnFailure, Neverの3つ
--restart=AlwaysならDeploymentが作成される
--restart=OnFailureならJobがが作成される
--restart=Neverなら通常のpodが作成される
デフォルト値はAlwaysである
CronJobsを作成する時は--restart=Neverとする
OnFailureかNeverを選択した場合は、kubectl run replicas=1とする必要がある

  • curlでpod名でアクセスしてみる
sh-4.2# curl http://nginx-0.sample-svc/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
sh-4.2# 

ingressについて

外部公開、L7ロードバランサー
L7ロードバランサーはurlでサービスを切り替えることができるもの

マニュフェスト

apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  selector:
    app: web
    env: study
  ports:
  - port: 80
    targetPort: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
      env: study
  template:
    metadata:
      name: nginx
      labels:
        app: web
        env: study
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2-alpine

---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: frontend
  annotations:
    kubernetes.io/ingress.class: "nginx" <= minicubeの場合はingressはnignxで動いているのでこちらを指定
    nginx.ingress.kubernetes.io/ssl-redirect: "false"  <= SSLリダイレクトを殺す
spec:
  rules:
  - http:
      paths:
      - path: / <= ここにパスを指定してそのpathに対するserviceを切り替える
        backend:
          serviceName: web-svc <= パスにアクセスされた時にアクセスするサービスを指定
          servicePort: 80

Discussion