k8s環境ハンズオン k8s基本学習編

# k8s環境ハンズオン k8s基本編

### もくじ
- k8sの概念を理解する。
- k8sの基本操作を覚える。


## k8sの概念を理解する。
- Hello World !（Kubernetes）
- Kubernetesとは
- Kubernetesリソース
- Kubernetesネットワーク
- 学習環境のネットワーク




#### Hello World !（Kubernetes）

- helloworldイメージをk8s上で実行、確認、削除してみよう

```
kubectl run hello-world --image hello-world --restart=Never
```

上記コマンド解説：
最初のhello-worldはk8sのpod名
次は実際に取ってくるドッカーイメージのhello-world
--restart=Never →podが存在しなくなったときに再起動しないようにする。

podが作成されているか、下記のコマンドで確認。

```
kubectl get pod
```

確認できたので、ログを確認してみる。

```
kubectl logs pod/hello-world
```

dockerコンテナの実行が確認できました。

最後に作成したpodを削除します。

```
kubectl delete pod/hello-world
```




#### Kubernetesとは

Kubernetesとはコンテナオーケストレーション
下記のようなシステム運用で困った課題を解決できる。


|課題|kubernetesができること|
|:--:|:--:|
|システムリソースの利益率に無駄がある|複数コンテナの共存|
|突発的な大量アクセスでシステムが応答しない|水平スケール|
|突然一部システムがダウンした|監視&自動デプロイ|
|リリースのたびにサービスが停止する|ローリングデプロイ|


使えるリソースを一元管理
kubectlでmasternodeに命令してmasternodeがworkernodeに命令して働かせる。


#### Kubernetesリソース

主なリソースは４分類１０種類のリソース

|分類|種別|
|:--:|:--:|
|ワークロード|(pod)(replicaset)(deployment）(statefulset)|
|サービス|(service)(ingress)|
|設定|(ConfigMap)(Secret)|
|ストレージ|(persistentvolume)(persistentvolumeclaim)|


|種別名|定義|
|:--:|:--:|
|ワークロード(pod) | 最小単位、dockerコンテナの集合|
|ワークロード(replicaset) | podの集合、podをスケールできる|
|ワークロード(deployment) | replicasetの集合、replicasetの世代管理が出来る|
|ワークロード(statefulset) | podの集合、podをスケールする際の名前が一定|


|種別名|定義|
|:--:|:--:|
|サービス(service)|外部公開、名前解決、L4ロードバランサ|
|サービス(ingress)|外部公開、L7ロードバランサ|


|種別名|定義|
|:--:|:--:|
|設定(ConfigMap)|設定情報|
|設定(Secret)|機微情報|


|種別名|定義|
|:--:|:--:|
|ストレージ(persistentvolume)|永続データの実態|
|ストレージ(persistentvolumeclaim)|永続データの要求|


#### Kubernetesネットワーク


NODEとpod
・nodeは実サーバに一致。
・リソースは各ワーカーノードに分散配置される。

２つの異なるネットワーク
・kubernetes には異なる二つのネットワークがある。
（外部ネットワーク）（クラスタネットワーク）

・「クラスタネットワーク」へ外から直接アクセスは出来ない。

コンテナへのアクセス
・管理端末は外部ネットワークに接続している。

コンテナへのアクセス方法は下記の３つ

①kubectlで直接コンテナにアクセス
![(13) 24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/b7608c10-2580-4ebf-fbab-d625c171aef1.jpeg)

②踏み台を経由してコンテナにアクセス
![(13) 26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/f0decea2-225c-4cb3-40a4-0c91f3fdf547.jpeg)

③サービス経由でアクセスする
![(13) 30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/444b60e0-ced3-ba74-6662-7914db6904ee.jpeg)


#### 学習環境のネットワーク

DockerもKubernetesも仮想マシン（ゲストOS）の中に納まっています。また、操作するターミナルもゲストOSのものを使って操作していきます。
すべてが仮想マシンに納まっていますので、操作的にはイメージしやすい環境です。

minikubeが作成するKubernetesクラスタはシングルノードなのでマスターやワーカーといった区別がありません。
minikubeをインストールした先で操作を行えば Kubernetes を操作できます。
![2019-11-01_07-46-31-ab85f68eade190b5dfa6ad6b83263227.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/7982fb5f-74c4-5162-25f0-73261514d45b.png)


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

## k8sの基本操作を理解する。
- リソースの作成/確認/削除
- コマンドでSecretリソース作成
- マニフェストファイル (kind, metadata, spec)
- マニフェストファイル (command, args, env)
- kindに応じたapiVersioniの確認
- リソース種別名の省略記法
- Podに入ってコマンド実行
- Podとホスト間でファイル転送
- Podのログ確認


#### リソースの作成/確認/削除

リソース作成手順
「定義作成」→「定義適用」の２ステップ

①「マニフェストファイル作成」：YAMLファイルを作成

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: test
  namespace: default
  labels:
    env: study
spec:
  containers:
  - name: hello-world
    image: hello-world
```

②「kubernetes反映」：kubectlコマンド利用して反映


- リソース作成/変更コマンド↓

```
kubectl apply -f <filename>

マニフェストファイルを指定してリソース作成変更します。

オプション
-f<filename> マニフェストファイルパス
```

- リソース確認コマンド↓

```
kubectl get [-f <filename>][TYPE]
指定したリソースを確認します

オプション
-f<filename> マニフェストファイルパス
TYPE リソース種別 (pod,resplicaset)
```

- リソース削除コマンド↓

```
kubectl delete [-f <filename>][TYPE/NAME][-o [wide|yaml]]
指定したリソースを削除します

オプション
-f<filename> マニフェストファイルパス
TYPE/NAME

-o [wide | yaml] 出力形式を指定します。
				-wide:追加情報の表示
   				-yaml:YAML形式で表示
```



演習：Podの作成/確認/削除
- hello-worldコンテナ含むpod作成
- podが起動していること確認
- podを削除


ymlファイルを作業ディレクトリに配置してhello-worldコンテナ含むpod作成する

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

podが出来ているか確認する。

```
kubectl get -f pod.yml
```

allでよく見るリソース一覧も表示できるpodが出来ているか確認する。

```
kubectl get all
```

kubectl get pod ならpodリソース限定で表示する。

```
kubectl get pod
```

指定したpodリソースを削除する。

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



----------------------------------------------
#### コマンドでSecretリソース作成

Sercretリソースコマンド作成
![sercret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/803be267-d993-eb36-e9b5-9b7204be64d5.png)



----------------------------------------------
#### マニフェストファイル (kind, metadata, spec)

今回はマニフェストファイルの書き方について学習します。
- マニフェストファイルの構成
- kind と　apiVersion
- metadata.name
- matadata.labels
- spec.containers.name
- spec.containers.image
- 演習：nginxポッドの作成


マニフェストファイルの構成は
種別、メタデータ、コンテナ定義の３構成。


```yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
    env: study
spec:
  containers:
    - name: nginx
      image: nginx:1.17.2-alpine
```
kindとapiversion
	kindはリソース種別。kindによってapiversionが決まる。
	
	
metadata.name：
	pod名はnamespaceと合わせて一意にする。


medatada.labels：
	ラベルは任意で付与できる。
	
	
spec:containers:name:
	podに含まれるコンテナ名を指定。
	
spec:containers:image:
	コンテナのイメージを指定するときはバージョンも指定する。
	
	バージョン指定がないとlatest指定になり誤動作に繋がる。


演習：Podの作成/確認/削除
- nginxを含むpodのマニフェストファイル作成
- k8sリソース作成
- podが起動していること確認
- podを削除



上記のnginxのイメージを定義したマニフェストファイルを作業ディレクトリに配置してpod作成する

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

podが出来ているか確認する。

```
kubectl get -f pod.yml
```

指定したpodリソースを削除する。

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



----------------------------------------------
#### マニフェストファイル (command, args, env)

今回もマニフェストファイルの書き方について学習します。
- マニフェストファイル
- kind と　apiVersion
- command, args
- env
演習：
- 終了しないポッドの作成


今回はマニフェストファイルに記載する環境変数を学習する。

```yaml
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: "5"
```

５秒ディレイ設定が入る。


commandとargs：
コンテナに対する処理を指定する。

commandとargsに引数を入れておくと実行時のコマンドを指定できる。

k8sとdockerでマッピングは異なる。

dockerにおけるエントリポイントはk8sのコマンドに相当します。

dockerのコマンドはk8sではargsに指定します。

環境変数を指定したい場合、envにオブジェクトを指定します。

k8sでは環境変数でコンテナ設定を渡すケースが多いのでenvは良く使う。



演習：終了しないpod作成
- centos:7にコマンド渡して終了しないマニフェストファイル作成
- podを作成
- podが起動していること確認
- podを削除



上記のcommandとargsを指定したマニフェストファイルを作業ディレクトリに配置してpod作成する

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

podが出来ているか確認する。（-wで状態まで確認する。）

```
kubectl get pod -w
```

指定したpodリソースを削除する。

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




----------------------------------------------
#### kindに応じたapiVersioniの確認

リソース種別に応じたapiversionの確認する方法について学習する。
kindからどのapiversionなるか調べられるのはAPIドキュメントから探すこと。


podのapiversionを確認する方法：
- k8sのAPIリファレンスを参照してする。

podだったらcore/v1→coreは省略できる。
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#pod-v1-core


ingressだったらnetworking.k8s.io/v1beta1
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#ingress-v1beta1-networking-k8s-io



----------------------------------------------
#### リソース種別名の省略記法

リソースの長い名前は短く省略することもできる。
![2019-09-29_03-24-06-f294e2553db6ad262d9d568a27f11e3d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99495/7f1d67c1-928c-598b-0a75-91681e3e3b84.png)

詳しくは下記のURL参照：
https://kubernetes.io/docs/reference/kubectl/overview/#resource-types


----------------------------------------------
#### Podに入ってコマンド実行


- コンテナへ入る

```
kubectl exec -it POD sh
指定したpodに入ってシェル操作を行えるようにします。

引数
POD 中に入りたいpod名
```


- コンテナから出る

```
exit
#プロセス終了してコンテナからログアウト

[ctrl] + [p] → [ctrl] + [q]
#プロセスを残したままコンテナからログアウト
```


演習：起動中のpodの中に入る
- centosとnginxを起動するマニフェストファイル作成
- centosとnginxのpodを起動
- podのipアドレス確認
- 起動したcentosコンテナ内に入る
- nginxに対してcurlを実行
- centosから出る
- centosとnginxのpodを削除




①centosとnginxを起動するマニフェストファイル作成

一つのマニフェストファイルで2つのpodを作成する

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

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

```
kubectl apply -f pods.yml
```

今回はデバッグ用podからnginxにアクセスしたいので
作成したpodのIPアドレスを調べたいので-o wideオプション使用して実行

```
kubectl get pod -o wide
```

```
NAME    READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
debug   1/1     Running   0          3m23s   172.17.0.3   minikube   <none>           <none>
nginx   1/1     Running   0          3m11s   172.17.0.2   minikube   <none>           <none>
```

ipが解ったのでdebugコンテナにログインを試し見る。

```
kubectl exec -it debug sh
```

続いてcurlでipを使ってアクセス

```
curl http://172.17.0.2/
```

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

nginxのコンテナにhttpでリクエスト出来ていることが確認できる。
続いて、コンテナから脱出する。

```
exit
```

実行してるpodを削除する。

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

----------------------------------------------
#### Podとホスト間でファイル転送


- ファイル転送

```
kubectl cp SRC DEST
指定されたファイルを指定された転送先に送ります。

引数
SRC 転送元ファイル
DEST 転送先ファイル
```




- ファイル転送（ホスト→pod）

```
kubectl cp <src> <pod-name>:<dest>
指定されたファイルを指定された転送先に送ります。

引数
src 転送元ファイル名/フォルダ名
pod-name 転送先のpod名
dest 転送先フォルダ名/ファイル名

```




演習：起動中のpodの中に入る
- centosのpodを起動
- ホスト上でファイル作成してpodへ転送
- podへ入って確認
- pod上でファイル作成
- podからホストへファイル転送して確認
- podからホストへファイルを転送して確認
- centosとpodの削除






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

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

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

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

```
kubectl get pod
```

作業ディレクトリに1.txtを作成してdebugPodにファイル転送する。

```
kubectl cp ./1.txt debug:/var/tmp/1.txt
```

作成出来たか確認するためdebugPodの中に入っていく。

```
kubectl exec -it debug sh

lsでファイル存在確認
ls /var/tmp/

catでファイル中身確認
cat /var/tmp/1.txt

```

続いてpodの中でファイルを作成してそれを取り出します。

```
cd ~;
vi 2.txt
中身はお好みで
exit
```

debugpodから作成した2.txtを取り出す。

```
kubectl cp debug:/root/2.txt ./2.txt

取り出せたら中身を確認
cat ./2.txt
```


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

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




----------------------------------------------
#### Podのログ確認


podがうまく動作しない時のためのログの確認方法を学ぶ
- 状況（概況）を確認
- ログ（詳細）を確認
- 演習：nginxのアクセスログ確認




- 状況（概況）を確認

```
kubectl describe [TYPE/NAME]
指定したリソースの状態を確認します。

引数
[TYPE/NAME] リソース種別とリソース名を指定
```


- ログ（詳細）を確認

```
kubectl logs [TYPE/NAME][--tail=n]
指定したリソースの状態を確認します。

引数
[TYPE/NAME] リソース種別とリソース名を指定
[--tail=n] 直近のnレコードだけ取得
```

kubectl logsコマンドはkubectl describeより詳細な情報を教えてくれる。




演習：nginxアクセスログを確認
- centosとnginxのpodを起動
- centosとnginxの状態を確認
- centosに入る
- curlでnginxにアクセス
- centosから出る
- nginxのログを確認
- centosとnginxのpodを削除




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

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

```
kubectl apply -f pods.yml
```

desclibeでpodの情報が何処まで確認できるか試す。

```
kubectl describe pod/debug
```

eventsでどんな動きをしてるか確認する。

```
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  97s   default-scheduler  Successfully assigned default/debug to minikube
  Normal  Pulled     83s   kubelet, minikube  Container image "centos:7" already present on machine
  Normal  Created    81s   kubelet, minikube  Created container debug
  Normal  Started    79s   kubelet, minikube  Started container debug
```

nginxも見てみる。

```
kubectl describe pod/nginx
```

centosに入って、nginxにアクセスログを確認する。

今回はデバッグ用podからnginxにアクセスしたいので
作成したpodのIPアドレスを調べたいので-o wideオプション使用して実行

```
kubectl get pod -o wide
```

```
NAME    READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
debug   1/1     Running   0          3m23s   172.17.0.2   minikube   <none>           <none>
nginx   1/1     Running   0          3m11s   172.17.0.3   minikube   <none>           <none>
```

ipが解ったのでdebugコンテナにログインを試し見る。

```
kubectl exec -it debug sh
```

続いてcurlでipを使ってアクセス

```
curl http://172.17.0.3/
```

続いて、コンテナから脱出する。

```
exit
```

nginxのアクセスログを確認する。

```
kubectl logs pod/nginx
```

```
172.17.0.2 - - [18/Jan/2020:06:28:22 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
```

使用したpodを削除する。

```
kubectl delete -f pods.yml
```