初学者がKubernetesをはじめてみた ~#2 HelloWorld Podをデプロイしてcluster外からアクセスする~

# はじめに
30代未経験からエンジニアを目指して勉強中のYNと申します。
インフラを勉強しだすと、k8sありきみたいな空気感に焦りますよね。キャッチアップのために学んだことなどを記録していきたいと思います。
[前回](https://qiita.com/theFirstPenguin/items/5266300214de6d7c7228)の続きです。

# やったこと
MinikubeのIPに対してcurlするとHelloWorldを返してくれるpodをデプロイします。だけです。
リクエストに対してHelloWorldを返してくれる、[HelloWorldイメージはこちら](https://console.cloud.google.com/gcr/images/google-samples/GLOBAL/hello-app?gcrImageListsize=30)を使います。
![スクリーンショット 2020-12-02 11.42.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/1ec7455b-11c3-f4a3-044d-12e20f4d7915.png)


# 事前準備
## `kubectl`を`k`にエイリアス
コマンドを`kubectl`から`k`にエイリアスすると楽です。そしてついでにコマンドの補完も追加しておきます。[詳細はこちらの記事を参照ください。](https://qiita.com/superbrothers/items/cd26ad2d266995ca7021)
以降、この記事では特に断りなく`kubectl`の代わりに`k`を使います。

```~/.zshrc
source <(kubectl completion zsh)
alias k=kubectl
complete -o default -F __start_kubectl k
```
## コマンドでyamlファイルを生成する
`--dry-run=client -o yaml`でkubectlコマンドの内容をyamlファイルに書き起こすことができます。楽ですね。
↓例えばpodを起動する場合

```
# yamlファイルの生成
k run --port 8080 --image gcr.io/google-samples/hello-app:1.0 --restart Never --dry-run=client -o yaml helloworld > pod.yaml

# yamlファイルの実行
k apply -f pod.yaml
```
## 常にコンポーネントの動きをみておく
watchコマンドを使ってgetコマンドを2秒おきに実行します。変化がわかっていいですね。`-o wide`でclusterの内部IPとかも表示されます。

```
watch 'kubectl get pod,svc,replicaset,deployment,namespace,ingress -o wide'                                                                               
```
## MinikubeにIngress addonを追加
MinikubeにIngress addonを追加します。nginxのプロキシサーバーを設定し、cluster外（Minikube外）からのhttpリクエストを捌きます。

```
# Addonをリスアップ
minikube addons list

# Ingress addonを追加
minikube addons enable ingress
```
アドオンを追加すると、`ingress-nginx-admission-create`・`ingress-nginx-admission-patch`・`ingress-nginx-controller`の3つのpodが`kube-system namespace`に追加されていることが分かります。

アドオン追加前: `k get pods --namespace=kube-system`↓

```
NAME                               READY   STATUS    RESTARTS   AGE
coredns-f9fd979d6-zfbfz            1/1     Running   0          9h
etcd-minikube                      1/1     Running   0          9h
kube-apiserver-minikube            1/1     Running   0          9h
kube-controller-manager-minikube   1/1     Running   0          9h
kube-proxy-r6pxg                   1/1     Running   0          9h
kube-scheduler-minikube            1/1     Running   0          9h
storage-provisioner                1/1     Running   0          9h
```
アドオン追加後: `k get pods --namespace=kube-system`↓

```
NAME                                        READY   STATUS      RESTARTS   AGE
coredns-f9fd979d6-zfbfz                     1/1     Running     0          9h
etcd-minikube                               1/1     Running     0          9h
ingress-nginx-admission-create-8trdq        0/1     Completed   0          25s
ingress-nginx-admission-patch-fgvk4         0/1     Completed   0          25s
ingress-nginx-controller-799c9469f7-cqkss   1/1     Running     0          26s
kube-apiserver-minikube                     1/1     Running     0          9h
kube-controller-manager-minikube            1/1     Running     0          9h
kube-proxy-r6pxg                            1/1     Running     0          9h
kube-scheduler-minikube                     1/1     Running     0          9h
storage-provisioner                         1/1     Running     0          9h
```
# HelloWorld Podをデプロイしてcluster外からアクセスする
## Deploymentをつくる
HelloWorld podをもつDeploymentを作ります。Replicasetのデフォルト設定は1つです。
![スクリーンショット 2020-12-02 11.31.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/ccee66fc-84a1-1f7a-41ff-7231bb099f7d.png)

```
# deploy.yamlの作成
k create deployment --port 8080 --image gcr.io/google-samples/hello-app:1.0 --dry-run=client -o yaml helloworld > deployment.yaml

# deploy.yamlの実行
k apply -f deployment.yaml
```
### ローリングアップデート
Deploymentの便利な特徴である、ローリングアップデートも簡単にできます。

```
# HelloWorldイメージをv2にアップデート
k set image deploy/helloworld helloworld=gcr.io/google-samples/hello-app:2.0

# v1にロールバック
k rollout undo deploy/helloworld
```
## NodePortをつくる
Deploymentをserviceを使ってexposeします。serviceのtypeからNodePortを選ぶことで外部からアクセスすることができます。
![スクリーンショット 2020-12-02 11.33.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/ef07d909-fdca-d23a-d159-9119bc69bc20.png)

```
# nodeport.yamlの作成
k expose deployment helloworld --type NodePort --port 8080 --name helloworld-nodeport --dry-run=client -o yaml > nodeport.yaml

# nodeport.yamlの実行
k apply -f nodeport.yaml
```
この状態でもculster外からアクセスすることができますが、Nodeのport番号を調べる必要があります。そのため、Ingressを使ってプロキシする必要があります。
![スクリーンショット 2020-12-02 11.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/01975f77-3b35-ca93-b3fe-43ce75d2c8b8.png)

![スクリーンショット 2020-12-02 11.54.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/c074b591-a6cb-818e-5ee0-e3a1d144c2eb.png)


## Ingressをつくる
Ingressを実行してcluster外からのアクセスをプロキシします。同時にL7ロードバランサとして機能させることもできます。
![スクリーンショット 2020-12-02 11.39.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572098/4e60a941-2469-32e2-034f-d4d39b00415d.png)

### ingress.yamlの作成
```ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: helloworld
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /
            backend:
              serviceName: helloworld-nodeport
              servicePort: 8080
```
### ingress.yamlの実行
```
k apply -f ingress.yaml
```
## 動作確認
MinikubeんぼIPにリクエストを送ると、IngressにプロキシされてHelloWorldが返ってきます。

```
curl 192.168.99.100 

# もしくは
curl $(kubectl get ingress | awk '{ print $4 }' | tail -1)
```
下記の応答が返ってきます。

```
Hello, world!
Version: 1.0.0
Hostname: helloworld-7f7df774df-lf4gv
```
ここでローリングアップデートすると、すぐに応答も代わります。

```
k set image deploy/helloworld helloworld=gcr.io/google-samples/hello-app:2.0
```
```
Hello, world!
Version: 2.0.0
Hostname: helloworld-7669cd7c6-vv696
```
## おかたづけ
```
k delete -f deployment.yaml
k dekete -f nodeport.yaml
k delete -f ingress.yaml
```

# 参考にさせていただいた記事
https://www.ibm.com/blogs/solutions/jp-ja/8-kubernetes-tips-and-tricks/
https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/master/hello-app