k8s環境ハンズオン k8s各種リソース解説編

# k8s各種リソース解説編

本セクションでは主要なKubernetesリソースの使い方を学習していきます。

- Pod
- ReplicaSet
- Deployment
- Service
- ConfigMap
- Secret
- PersistentVolume
- PersistentVolumeClaim
- StatefulSet
- Ingress

Kubernetesを使った開発を行っていく上で基本となるリソースの使い方を学習していきます。

各リソースの特徴や記述方法について学習し、使えるようになることを目指しましょう！


-----------------------------------------------------------------------------------------------
## Pod

podとは、最小単位。同一環境で動作するdockerコンテナ集合

１つのpodに複数のdockerコンテナが入れられる。


- マニフェストファイル書き方


```pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2-alpine
    volumeMounts:
    - name: storage
      mountPath: /home/nginx
  volumes:
  - name: storage
    hostPath:
      path: "/data/storage"
      type: Directory
```



imagePullpolicyの各種オプション

|種別|説明|
|:--|:--|
|Always|毎回リポジトリからダウンロードを行う|
|Never|ローカルのイメージを利用|
|ifNotpresent|ローカルに存在すればローカルを利用し存在しなければリポジトリからダウンロード|


マニフェスト設定は下記の通り

|種別|説明|
|:--|:--|
|spec:containers:name|コンテナ名指定|
|spec:containers:image|イメージ名指定|
|spec:containers:command|コンテナへ引き渡すエントリポイントのコマンドを指定|
|spec:containers:args|コンテナへ引き渡すcmdコマンドを指定|
|spec:containers:env|コンテナへ引き渡す環境変数を指定|
|spec:containers:volumeMounts|コンテナへマウントするストレージを指定|


主要なspecは  containersとvolumes


spec:volumes
マウントしたいストレージ先は状況に応じて選択


spec:volumes:name
ストレージ名を指定


spec:volumes:hostPath
保存先がpod実行サーバのフォルダ


spec:volumes:hostPath:typeの各種オプション

|種別|説明|
|:--|:--|
|Directory|存在するディレクトリ|
|DirectoryOrCreate|ディレクトリが存在しなければ作成|
|File|存在するファイル|
|FileOrCreate|ファイルが存在しなければ作成|

spec:volumes:nfs
保存先がnfsサーバのフォルダ


spec:volumes:configmap
configmapリソースをファイルとしてマウントさせる


spec:volumes:sercret
sercretリソースをファイルとしてマウントさせる。


spec:volumes:emptydir
一時的な空フォルダ




演習：pod作成
- ホストにフォルダ、ファイルを作成
- 作成したフォルダをマヌントしたpodマニフェストファイルを作成
- リソース作成


テストファイルとしてmessageファイルを/data/storage配下に置く。

```
vi /data/storage/message
hello k8s
```

下記のマニフェストファイルを作業ディレクトリ配下に置く

```pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: sample
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2-alpine
    volumeMounts:
    - name: storage
      mountPath: /home/nginx
  volumes:
  - name: storage
    hostPath:
      path: "/data/storage"
      type: Directory
```


マニフェストファイルを元にpod作成する。

```
kubectl apply -f pod.yml
```


作成したpodがマウントされているか確認する。

```
kubectl exec -it pod/sample sh
```


続いてマウントしているはずであるフォルダに移動する。

```
cd /home/nginx/
ls
cat message
```


うまくいったらpodを削除。

```
kubectl delete -f pod.yml
```



-----------------------------------------------------------------------------------------------
## ReplicaSet


ReplicaSetとは、podの集合。podをスケールできる。

１つのpodに複数のdockerコンテナが入れられる。


- マニフェストファイル


主要なspecはreplicas,selector,template


```yml:replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  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
```


上記のマニフェストファイルを作業ディレクトリに配置してreplicaset.ymlを作成する。

```
kubectl apply -f replicaset.yml
```

作成したreplicaset.ymlの動作確認をする。

```
kubectl get all
```

```
NAME                    DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx   3         0         0       9s
```

スケールアウトを試し見る。
replicasの数値を2にしてみる(更新)

```
NAME                    DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx   2         0         0       9s
```


削除。

```
kubectl delete -f replicaset.yml
```




-----------------------------------------------------------------------------------------------
## Deployment


```yml:deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  annotations:
    kubernetes.io/change-cause: "First release."
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
      env: study
  revisionHistoryLimit: 14
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      name: nginx
      labels:
        app: web
        env: study
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2-alpine
```



上記のマニフェストファイルを作業ディレクトリに配置してDeploymentを作成する。

```
kubectl apply -f deployment.yml
```

作成したDeploymentの動作確認をする。

```
kubectl get all
```

ロールアウトを試みる。(更新)

```
kubectl rollout history deploy/nginx
```

初回は何も表示されない

```
deployment.extensions/nginx
No rollout history found.
```

vi deployment.yml
kubernetes.io/change-cause: ここの箇所を書き換えて再apply

```
kubectl rollout history deploy/nginx
```

一度試みたロールアウトの履歴が確認できる。

```
deployment.extensions/nginx
REVISION  CHANGE-CAUSE
1         second release.
```

ロールバックを試みる。(巻き戻り)

```
kubectl rollout undo deploy/nginx
```

kubernetes.io/change-cause: ここの箇所を書き換えて再apply

```
kubectl rollout history deploy/nginx
```

削除。

```
kubectl delete -f deployment.yml
```


-----------------------------------------------------------------------------------------------
## Service


```yml:service.yml
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
  selector:
    app: web
    env: study
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30000
```


上記のマニフェストファイルを作業ディレクトリに配置してservice作成する。

```
kubectl apply -f service.yml
```

作成したserviceの動作確認をする。

```
kubectl get all
```


```
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        16h
service/web-svc      NodePort    10.101.233.192   <none>        80:30000/TCP   48s
```

仮想サーバのホストにポートを指定する。
192.168.1.10:30000


うまくいったらpodを削除。

```
kubectl delete -f service.yml
```


-----------------------------------------------------------------------------------------------
## ConfigMap

![(24) 07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/e9e9ffe0-e142-5ad7-c267-f3682fdce95a.jpeg)
![(24) 11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/bbffb12f-11c4-5800-a270-753a7307658f.jpeg)
![(24) 12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/329b1ea3-4898-fad1-1917-37fd578e0659.jpeg)
![(24) 20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/cbba8851-3db3-cd3b-a71a-e0be261ea68c.jp

```yml:configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: sample-config
  namespace: default
data:
  sample.cfg: |
    user: tsuyoshi.tanaka
  type: "application"

---
apiVersion: v1
kind: Pod
metadata:
  name: sample
  namespace: default
spec:
  containers:
  - name: sample
    image: nginx:1.17.2-alpine
    env:
    - name: TYPE
      valueFrom:
        configMapKeyRef:
          name: sample-config
          key: type
    volumeMounts:
    - name: config-storage
      mountPath: /home/nginx
  volumes:
  - name: config-storage
    configMap:
      name: sample-config
      items:
      - key: sample.cfg
        path: sample.cfg
```



上記のマニフェストファイルを作業ディレクトリに配置してconfigmap作成する。

```
kubectl apply -f configmap.yml
```

作成したconfigmapの動作確認をする。

```
kubectl get pod
```

```
kubectl exec -it sample sh
```

うまくいったらpodを削除。

```
kubectl delete -f configmap.yml
```



-----------------------------------------------------------------------------------------------
## Secret

![(25) 08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/79fee03b-1e1b-3781-efa1-dee58a705db7.jpeg)
![(25) 13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/8911b48b-fd80-608e-73bf-1eceea3884fb.jpeg)
![(25) 14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/d532cd65-59d1-46a2-b6f8-82941cacce0a.jpeg)
![(25) 18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/09ebeb0c-7e1e-2e43-9efe-ea8bed3a242f.jpeg)
![(25) 20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/8bf0e652-e2d5-8212-1bb2-8a7bea8804fc.jpeg)
![(25) 23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/b334169c-906a-95ef-45d9-17dbb30a1a96.jpeg)
![(25) 26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/ff7ade87-34c5-794e-a8f9-cf8283a1ccaa.jpeg)
![(25) 28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/fc4be54e-0d61-2a77-5bb5-3c8a6b774314.jp

```yml:sercret.yml
apiVersion: v1
kind: Secret
metadata:
  name: sample-secret
data:
  message: SGVsbG8gV29ybGQgIQ==     # echo -n 'Hello World !' | base64
  keyfile: WU9VUi1TRUNSRVQtS0VZ     # cat ./keyfile | base64

---
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
```

上記のマニフェストファイルを作業ディレクトリに配置してsercret作成する。

```
kubectl apply -f secret.yml
```


鍵ファイルを使って、sercretを暗号化する。

```
kubectl create secret generic sample-sercret
```

作成したsercretの動作確認をする。

```
kubectl get secret
```

作成したsercretの詳細な動作確認をする。

```
kubectl get secret/sample-sercret -o yaml
```


secret.ymlを削除。

```
kubectl delete -f secret.yml
```


-----------------------------------------------------------------------------------------------
## 永続データ（PersistentVolume,PersistentVolumeClaim）

![(26) 08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/932dc472-2f7a-2180-da1b-329d71b1f786.jpeg)
![(26) 16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/5b14bb54-afa3-3458-2835-6f3664db3995.jpeg)
![(26) 22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/53c50544-0112-00c2-a3e6-78a20466a50d.jpeg)
![(26) 26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/ad27af96-1c60-efc5-496b-d27dd2ec7630.jpeg)
![(26) 27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/61a3d2c1-20a3-f466-d57c-85e3fb366e91.jpeg)
![(26) 34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/32012c9c-977b-3cd7-7243-f055297f48fc.jpeg)
![(26) 35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/299e0b15-6612-5313-0c4c-9e2931f7092a.jpeg)



```yml:storage.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume-01
  labels:
    env: study
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 1Gi
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: "/data/storage"
    type: Directory

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: volume-claim
  labels:
    env: study
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
```


上記のマニフェストファイルを作業ディレクトリに配置してstorage作成する。

```
kubectl apply -f storage.yml
```

storage.ymlの動作を確認する。

```
kubectl get pvc,pv
```

マウントされていることが確認できる。

```
NAME                                 STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/volume-claim   Pending                                      slow           73s

NAME                         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM   STORAGECLASS   REASON   AGE
persistentvolume/volume-01   1Gi        RWO            Retain           Pending           slow                    74s
```

削除。

```
kubectl delete -f storage.yml
```

-----------------------------------------------------------------------------------------------
#### StatefulSet

![(27) 08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/2a8c959c-fef8-393a-c801-58791416f3a7.jpeg)


![(27) 12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/cb2f629d-a909-9050-634c-4be82bb5525b.jpeg)



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

---
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
  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:
  - metadata:
      name: storage
    spec:
      storageClassName: slow
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
```


上記のマニフェストファイルを作業ディレクトリに配置してstatefulset.yml作成する。

```
kubectl apply -f statefulset.yml
```

作成したstatefulset.ymlの動作確認をする。

```
kubectl get all
```

続いて、centospodを起動してアクセスする。


```
kubectl run debug --image-centos:7 -it --rm --restart=Never -- sh
```


うまくいったらstatefulset.ymlを削除。

```
kubectl delete -f statefulset.yml
```



-----------------------------------------------------------------------------------------------
#### Ingress

![(28) 10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/825417c0-bd83-b8da-acbd-c9dcfa94b9d0.jpeg)


![(28) 15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/28865561-77a8-3caa-6ae6-93955e38d142.jpeg)


![(28) 17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/868a0046-7919-0ba8-3a24-70942c105307.jpeg)


![(28) 20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/057f3999-da9e-87f8-a442-a5d2ddc737e1.jpeg)



```
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"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: web-svc
          servicePort: 80
```


上記のマニフェストファイルを作業ディレクトリに配置してingress作成する。

```
kubectl apply -f ingress.yml
```

作成したingressの動作確認をする。

```
kubectl get ing,svc,deploy
```

下記のように外部アドレスが表示されない場合、設定されるまで数分待つ。


```
NAME                          HOSTS   ADDRESS   PORTS   AGE
ingress.extensions/frontend   *                 80      3m8s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   15h
service/web-svc      ClusterIP   10.110.116.66   <none>        80/TCP    3m8s

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/nginx   0/2     2            0           3m9s
```


うまくいったらingress.ymlを削除。

```
kubectl delete -f ingress.yml
```



-----------------------------------------------------------------------------------------------

本セクションではKubernetesリソースの使い方を学習しました。
このまとめでは各リソースのサンプルコードおよびコード中にポイントとなる箇所をまとめます。



◆ワークロード

○Pod

apiVersion: v1
kind: Pod
metadata:
  name: sample
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2-alpine
    volumeMounts:
    - name: storage
      mountPath: /home/nginx
  volumes:
  - name: storage
    hostPath:
      path: "/data/storage"
      type: Directory


○ReplicaSet

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      env: study
  template:                   # Podと同じものを記述
    metadata:
      name: nginx
      labels:
        app: web
        env: study
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2-alpine


○Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  annotations:
    kubernetes.io/change-cause: "First release."
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
      env: study
  revisionHistoryLimit: 14    # デフォルト 10
  strategy:
    type: 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


○StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
      env: study
  revisionHistoryLimit: 14
  serviceName: sample-svc     # HeadlessServiceと紐づける
  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:       # PersistentVolumeClaimと同じものを記述
  - metadata:
      name: storage
    spec:
      storageClassName: slow
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi


◆サービス

○Service

apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  type: NodePort              # ClasterIP(デフォルト), NodePort, LoadBalancer, ExternalName
  selector:
    app: web
    env: study
  ports:
  - port: 80                  # 受付ポート
    targetPort: 80            # 転送先ポート
    nodePort: 30000           # ノード上にマッピングするポート（type: NodePort 時のみ）


○Ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: frontend
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: web-svc
          servicePort: 80


◆設定

○ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: sample-config
data:
  sample.cfg: |
    user: tsuyoshi.tanaka
  type: "application"


○Secret

apiVersion: v1
kind: Secret
metadata:
  name: sample-secret
data:
  message: SGVsbG8gV29ybGQgIQ==     # echo -n 'Hello World !' | base64
  keyfile: WU9VUi1TRUNSRVQtS0VZ     # cat ./keyfile | base64


◆ストレージ

○PersistentVolume

apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume-01
  labels:
    env: study
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteOnce                   # ReadWriteOnce, ReadOnlyMany, ReadWriteMany
  capacity:
    storage: 1Gi
  persistentVolumeReclaimPolicy: Retain   # Retain, Delete, Recycle(非推奨)
  hostPath:
    path: "/data/storage"
    type: Directory


○PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: volume-claim
  labels:
    env: study
spec:
  storageClassName: slow
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi


記述のポイントはおさえられたでしょうか？
これから実践に入っていく際、基本となりますので忘れたときにはここへ立ち返って復習しながら進めましょう！