[Kubernetes]kubectl run/create/exposeによるワンライナーでのリソース作成

#はじめに
Kubernetesのリソースのデプロイはマニフェストファイルを作ってapplyするのが基本ですが、マニフェストファイルを作成しなくてもkubectlコマンドのワンライナーでもデプロイができます。
ちょっとテストをしてみたいときや、これを応用してマニフェストファイルを作成することもできますので、覚えておくと便利です。

今回は以下のバージョンの結果をご紹介します。バージョンによってコマンドの書式が微妙に変わってたりしますので、お気をつけください。

```
$ kubectl version --short
Client Version: v1.18.3
Server Version: v1.18.3
```

[kubectl Command Reference(V1.18)](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#run)

#Pod
##Podを作成する
Pod名とイメージ名は必須で指定する必要があります。

```
$ kubectl run nginx1 --image=nginx
pod/nginx1 created
```

##Podを作成しラベルとポートを設定する
ラベルとポートを指定してPodを作成します。なお、ラベルを指定しないで`kubectl run`コマンドでPodを作成すると、ラベルにPod名が付きます。

```
$ kubectl run nginx2 --image=nginx --port=80 --labels="app=app1,env=prd"
pod/nginx2 created
```

指定できるオプションは、このほかに「--restart」「--command」「--env」「--namespace」などがあります。

##Podを作成せずにマニフェストファイルをyaml形式で保存する

「--dry-run=client」で実際に作成しない、「-o yaml」でyaml形式で出力します。この内容をファイルにリダイレクトするとマニフェストファイルを作成できます。
マニフェストファイルを一から作るのは慣れないと大変ですし、KubernetesのバージョンによってAPIバージョンが変わってたりもしますので、この方法を覚えておくと便利だと思います。

```
$ kubectl run nginx3 --image=nginx --port=80 --labels="app=app1,env=prd" --dry-run=client -o yaml >/tmp/nginx3.yaml
```
```/tmp/nginx3.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    app: app1
    env: prd
  name: nginx3
spec:
  containers:
  - image: nginx
    name: nginx3
    ports:
    - containerPort: 80
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
```

##Podを一時的に起動する
--rmオプションを付けると、Podを起動後コマンドを実行し、削除されます。
他のコンテナの疎通確認など一時的な利用に便利です。

```
$ kubectl run testpod --image=centos:7 --rm -it -- curl -s http://10.97.96.74:8080
If you don't see a command prompt, try pressing enter.
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
・・・
</body>
</html>
Session ended, resume using 'kubectl attach testpod -c testpod -i -t' command when the pod is running
pod "testpod" deleted
```


#Deployment
##Deploymentを作成し、Replica数を指定する
Deploymentもワンライナー（`kubectl create`コマンド）で作成できますが、Replica数の指定ができません。Replica数を指定するには、`kubectl scale`コマンドでReplica数を指定します。

```
$ kubectl create deployment nginx-dep --image=nginx
deployment.apps/nginx-dep created
$ kubectl scale --replicas=2 deployment nginx-dep
deployment.apps/nginx-dep scaled
```

##Deploymentは作成せずにマニフェストファイルを作成する。
`kubectl run`コマンドと同様に「--dry-run=client」「-o yaml」を指定して、ファイルにリダイレクトするとマニフェストファイルを作成できます。
Replica数の指定はできませんので、Replica数を1以外にする場合にはファイルを編集する必要があります。また、`kubectl create`コマンドで指定できるオプションは`kubectl run`コマンドと比べると少ないので、オプションの指定もファイルを編集する必要があります。

```
$ kubectl create deployment nginx-dep --image=nginx --namespace=example  --dry-run=client -o yaml > /tmp/nginx-dep.yaml
```

```/tmp/nginx-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx-dep
  name: nginx-dep
  namespace: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-dep
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-dep
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
```

#Service
Serviceを作成するには`kubectl expose`コマンドを使用します。

##作成済みのPodを公開するためのClusterIPを作成する
「--type=ClusterIP」を指定します。指定しない場合のデフォルトはClusterIPです。

```
$ kubectl expose pod nginx1 --port=8080 --target-port=80 --name=nginx1-ci --type=ClusterIP
service/nginx1-ci exposed
```

##作成済みのPodを公開するためのNodePortを作成する
「--type=NodePort」を指定します。

```
$ kubectl expose pod nginx2 --port=8080 --target-port=80 --name=nginx2-np --type=NodePort
service/nginx2-np exposed
```

なお、Selectorは、指定したPodのラベルに合わせて設定されます。

```
$ kubectl describe svc nginx2-np
Name:                     nginx2-np
Namespace:                default
Labels:                   app=app1
                          env=prd
Annotations:              <none>
Selector:                 app=app1,env=prd
Type:                     NodePort
IP:                       10.103.189.89
Port:                     <unset>  8080/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30610/TCP
Endpoints:                192.168.69.253:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
```

##作成済みのDeploymentを公開するためのLoadBalancerを作成する
「--type=LoadBalancer」を指定します。

```
$ kubectl expose deployment nginx-dep --port=8080 --target-port=80 --name=dep-lb --type=LoadBalancer
service/dep-lb exposed
```

##マニフェストファイルを作成する

`kubectl run`コマンドと同様に、`kubectl expose`コマンドも「--dry-run=client」「-o yaml」を指定してマニフェストファイルを作成できます。

```
$ kubectl expose deployment nginx-dep --port=8080 --target-port=80 --name=dep-lb --type=LoadBalancer --dry-run=client -o yaml > /tmp/lb.yaml
```

```/tmp/lb.yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx-dep
  name: dep-lb
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-dep
  type: LoadBalancer
status:
  loadBalancer: {}
```


##PodとClusterIPを同時に作成する
`kubectl run`コマンドに「--expose」を指定することで、ClusterIPを同時に作成できたりもします。
なお、「--type」が指定できないので、同時に作成できるサービスはデフォルトのClusterIPのみです。（おそらく。間違ってたら教えてください。）

```
$ kubectl run httpd --image=httpd:alpine --namespace=example --port=80 --expose
service/httpd created
pod/httpd created
$ kubectl -n example get all
NAME        READY   STATUS    RESTARTS   AGE
pod/httpd   1/1     Running   0          11s

NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/httpd   ClusterIP   10.100.143.138   <none>        80/TCP    10s
```

#まとめ
今回はマニフェストファイルを作成せずにリソースをデプロイする方法をご紹介しました。
デプロイできるリソースは、ご紹介したPod/Deploymet/ClusterIP/NodePort/LoadBalancerだけでなく、CronJobやReplicaSetなどもありますし、指定できるオプションも他にもあります。私が便利そう、よく使いそうだと思ったコマンド/オプションをあげています。
調べてみると未知なるオプションがまだまだあって、Kubernetesの奥深さを感じます。