【Kubernetes】雛形yamlマニフェスト作成方法まとめ


# はじめに
- 主にCKA/CKADを受けるにあたり、個人的に役に立った雛形yamlマニフェストの作成方法を、本記事にまとめます
  - すでに先駆者の方々がほぼ同様の記事を挙げられていますが、備忘&自己整理も兼ねて執筆します。
- 記載するリソースの種類などは個人的に必要に駆られた際などに適宜追加&修正しようと思います

# 前提
- 本記事は`kubectl version : v1.20`環境で動作確認をしています
  - 基本的にkubernetesリソースの略称でコマンドを記述します
     - 参考 : [【Kubernetes】kubectlを用いて「Kubernetesリソースの省略名とapiVersion」を取得する方法](https://qiita.com/shinakazu/items/0b642ca23f679e9c63bb)
- 個人的に分類した以下のカテゴリ毎にまとめて記載させていただきます
  - Workload系
     - Pod
     - Deployment
     - Job
     - CronJob
  - Service&Network系
     - Service
     - NetworkPolicy
     - Ingress
  - Storage系
     - PersistentVolume
     - PersistentVolumeClaim
  - ClusterManagement系
     - Namespace
     - ServiceAccount
     - Role
     - ClusterRole
     - RoleBinding
     - ClusterRoleBinding


## 補足
- 基本的には以下のコマンドを叩くことで、その場でヘルプを出して確認することができます
  - kubectlのバージョンによっては本ページに記載の内容が不適切な場合もあるので、必要になった際にその場で確認する癖をつけるべしです
     - CKA/CKAD試験中はこれができるかどうかが大きなポイントです（個人的見解）

```bash
# Pod
$ kubectl run -h

# Service
$ kubectl expose -h

# Pod以外
$ kubectl create <deploy/svc/jobなどなど> -h
```
- `$ kubectl create -h`を実行すると`$ kubectl create`に対応しているリソースが取得できる
  - 後述のPersistentVolumeやNetworkPolicyは載っていない・・・

```bash
$ kubectl create -h
<=== 省略 ===>
Available Commands:
  clusterrole         Create a ClusterRole.
  clusterrolebinding  Create a ClusterRoleBinding for a particular ClusterRole
  configmap           Create a configmap from a local file, directory or literal value
  cronjob             Create a cronjob with the specified name.
  deployment          Create a deployment with the specified name.
  ingress             Create an ingress with the specified name.
  job                 Create a job with the specified name.
  namespace           Create a namespace with the specified name
  poddisruptionbudget Create a pod disruption budget with the specified name.
  priorityclass       Create a priorityclass with the specified name.
  quota               Create a quota with the specified name.
  role                Create a role with single rule.
  rolebinding         Create a RoleBinding for a particular Role or ClusterRole
  secret              Create a secret using specified subcommand
  service             Create a service using specified subcommand.
  serviceaccount      Create a service account with the specified name
<=== 省略 ===>
```

#  Workloads系
## Pod
```bash
$ kubectl run <pod-name> --image=<image:xxx> --dry-run=client -o=yaml
```
- `--expose`をつけるとServiceも一緒に作れる
  - `$ kubectl create deployment` には`--expose`オプションはない模様
- `--command -- <COMMAND> <args>`でコマンド入力可能
  - 複雑なコマンドを入れたい場合は`--command -- /bin/sh -c "<command>"`とするべし
     - https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
- `--env=[TMP_ENV=xxxx]` にてPod内に環境変数埋め込みもできる


## Deployment
```bash
$ kubectl create deploy <deploy-name> --image=<image:xxx> --dry-run=client -o=yaml
```
- `--replicas=3`などでReplica数を指定可能

## Job
```bash
$ kubectl create job <job-name> --image=<image> --dry-run=client -o=yaml　-- <command>
```
- 上記でマニフェストを作ったあと、以下パラメータを付与して用途に応じたJobを作成できる
  - `spec.completions` : 成功回数、ここで指定した回数成功するまでJobは繰り返される（デフォルトは「1」)
  - `spec.parallelism` : 並列度（デフォルトは「1」)
  - `spec.backoffLimit` : 失敗を許容する回数（デフォルトは「6」)
- `restartPolicy`による動作の違い
  - `spec.template.spec.restartPolicy: Never` : 新しいPodを作ってJobを継続実行
  - `spec.template.spec.restartPolicy: OnFailure` : 同一Podを使ってJobを継続実行
- コマンドの記載方法
  - 単発コマンドならばそのままの記載で良いが、複数の引数などが入るコマンドは`-- /bin/sh -c 'XXXX'`とするとよい
- 参考ページ : https://kubernetes.io/docs/concepts/workloads/controllers/job/

## CronJob
```bash
$ kubectl create cj <cj-name> --image=<image> --schedule='* * * * *' --dry-run=client -o=yaml
```
- `cronjob schedule syntax` : `* * * * *`の部分の書き方
  - https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax


# Service&Network系
## Service
### 【推奨】既存Pod/Replicaset/Deploymentに紐づくServiceを作成
```bash
$ kubectl expose <po/rs/deploy> <resource-name> --name=<service-name> --port=<XXXX> --dry-run=client -o=yaml
```
- `--type`を特に指定しない場合は`--type=ClusterIP`になる
  - 選択肢としては`ClusterIP`、`NodePort`、`LoadBalancer`など

### Serviceリソース単体を作成
```bash
$ kubectl create svc <clusterip/externalname/loadbalancer/nodeport> <svc-name> --tcp=<XXX> --dry-run=client -o=yaml
```
- このコマンドでServiceリソースを作成した場合、別途`spec.selector`などに公開先リソース情報を記載する必要がある

## NetworkPolicy
- kubectlコマンドでは雛形マニフェストを作成できない？ため、以下ページのマニフェストを参考に作る
  - https://kubernetes.io/ja/docs/concepts/services-networking/network-policies/
 
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978
```

## Ingress
```bash
$ kubectl create ing <ing-name> --rule=<host>/<path>=<svc-name>/<svc-port> --dry-run=client -o=yaml
```
- `host`には`<host-name>:XXXX`のような指定はできない

# Storage系
## PersistentVolume
- kubectlコマンドでは雛形マニフェストを作成できない？ため、以下ページのマニフェストを参考に作る
  - https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/#永続ボリューム
 
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2
```

- `5GiB`のように`B`をつけないこと

## PersistentVolumeClaim
- kubectlコマンドでは雛形マニフェストを作成できない？ため、以下ページのマニフェストを参考に作る
  - https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}
```
- `storageClassName`と`accessModes`は指定しないと、pvcにpvがアサインされない?
  - `$ kubectl apply -f xxx.yaml`でpvcはcreateされるものの、Pendingのままになる

# Config系
## ConfigMap
```bash
$ kubectl create cm <cm-name> --from-literal=AAA=bbb --dry-run=client -o=yaml
```
- `--from-literal`の箇所を`--from-file=<file-path>`とすることでファイルからの入力も可能

## Secret
```bash
$ kubectl create secret general <secret-name> --from-literal=AAA=bbb --dry-run=client -o=yaml
```
- `$ kubcectl create secret`の直後に`general`などのSecretのタイプの指定が必要


# ClusterManagement系
## Namespace
```bash
$ kubectl create ns <namespace-name> --dry-run=client -o=yaml
```

## ServiceAccount
```bash
$ kubectl create sa <sa-name> --dry-run=client -o=yaml
```
- PodでServiceAccountを指定する場合、Podのマニフェストの`spec.serviceAccountName`で対象saの指定が必要

## Role
```bash
$ kubectl create role <role-name> --verb=<verb> --resource=<resource> --dry-run=client -o=yaml
```
- `verb`も`resource`も対象が複数ある場合は「,」で区切って並列する
- `verb` : "get", "list", "watch", "create", "update", "patch", "delete",もしくは"*(すべての処理)"

## ClusterRole
```bash
$ kubectl create clusterrole <clusterrole-name> --verb=<verb> --resource=<resource> --dry-run=client -o=yaml
```
- 基本的にRoleと同じだが、Namespaceの指定ができない

## RoleBinding
```bash
$ kubectl create rolebinding <rolebinding-name> --role=<role-name> --user=<user-name> --dry-run=client -o=yaml
```

## ClusterRoleBinding
```bash
$ kubectl create clusterrolebinding <clusterrolebinding-name> --clusterrole=<role-name> --user=<user-name> --dry-run=client -o=yaml
```

# おわりに
使いこなせるとCKA/CKADに限らず非常に便利なコマンドたちなので、今後ともお世話になっていきたいと思います。