【#Kubernetes】Google Kubernetes Engine(GKE)を使ってKubernetesに入門してみる(Ingress、Deployment、StatefulSet編) #GKE #GCP #k8sjp #gcpug

"Google Kubernetes Engine(GKE)"を使って"Kubernetes"について勉強した際の内容を自分用のメモとしてまとめました

#### "Kubernetesクラスタ"内の`ノード`について

"Kubernetesクラスタ"は大きく2種類の`ノード`で構成されます

* Control Planeとなる**`マスターノード`**
* コンテナ実行環境となる**`ワーカーノード`**

"Google Kubernetes Engine(GKE)"では、`マスターノード`側はフルマネージド提供され課金対象にもなりません。そのため`ワーカーノード`のみ作成すれば、すぐに"Kubernetesクラスタ"環境を利用することが可能です。

#### "Kubernetesクラスタ"内のオブジェクトについて

"Kubernetesクラスタ"上のオブジェクトは、`Ingress`、`Service`、`Pod`の3つのレイヤーに別けることができます

![1_KIVa4hUVZxg-8Ncabo8pdg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/6dc56fcf-f5a9-74b0-f530-376d8d1c3eec.png)
出典: Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?
https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

|種類 |説明|
|--- |--- |
|**Ingress** |”Kubernetesクラスタの外部からのトラフィック”を制御する**"L7アプリケーションデリバリーコントローラー(ADC)"**です。”Ingress”は”ワーカーノード”とは別の場所に、"Google Kubernetes Engine(GKE)"環境においては、"Google Cloud Load Balancing"ベースのソフトウェア定義として作成されます。 |
|**Service** |”Ingressからのトラフィック”もしくは”同一Kubernetesクラスタ内部からのトラフィック”を制御する**”L4ロードバランサー”**です。|
|**Pod** |”ワーカーノード”上に作成する**”コンテナ”**と**”ボリューム”**です。”Pod”のデプロイ方式を管理するためのオブジェクト(ワークロード)として別途”Deployment”、”StatefulSet”、”DaemonSet”、”CronJob”といったオブジェクトがありますが、これらの説明については後述します。”Pod”内の永続的ボリュームを管理するオブジェクトとして”PersistentVolumeClaim”がありますが、こちらの説明についても後述します。 |

"GKE"を使って次の3つを実施し"Kubernetesクラスタ"上にWordpressのシステムを構築することを通じて"Kubernetesクラスタ"の仕組みを理解することを目指します

* スタティックなグローバルIPアドレスを1つ割り当てた**`Ingress`**の作成
* `HorizontalPodAutoscaler(HPA)`を使った**オートスケールするWebサーバーの`Pod`と`Service`**の作成
* `StatefulSet`を使った**永続的なDBMS(MySQL)の`Pod`と`Service`**の作成

## 1. "Google Kubernetes Engine(GKE)"上に`ワーカーノード`のクラスタを作成する


まず、`ワーカーノード`のクラスタの作成を"Google Cloud Platform(GCP)"のWebコンソールから行います。

### □手順1-1: "Google Cloud Platform(GCP)"のWebコンソールにログインします

<img width="1314" alt="capture_001_04082019_131138.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/e8fd7f00-30e4-b574-2465-68ffcaa5da8f.jpeg">


### □手順1-2: `ナビゲーションメニュー`から`Google Kubernetes Engine`>`クラスタ`を選択します

<img width="1314" alt="capture_002_04082019_131224.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/5e9c6601-748b-7f40-756d-9afee8318ee1.jpeg">

### □手順1-3: 画面右上の`Cloud Shell`アイコンをクリックします

<img width="929" alt="capture_001_08082019_161012.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/a596a19d-3bb5-e448-0da6-cf30b166c5bd.jpeg">

### □手順1-4: 画面下に`Cloud Shell`が表示されるまでしばらく待ちます

<img width="1314" alt="capture_001_09082019_161452.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/d42d1e73-3717-b83d-fa7d-bd4f0b20be01.jpeg">

### □手順1-5: `gcloud config set`コマンドで`region`の設定を行います

`asia-northeast1(東京リージョン)`を指定します

```bash:CloudShell
$ gcloud config set compute/region "asia-northeast1"
Updated property [compute/region].
```

### □手順1-6: 続けて`gcloud config set`コマンドで`zone`の設定を行います

```bash:CloudShell
$ gcloud config set compute/zone "asia-northeast1-a"
Updated property [compute/zone].
```

### □手順1-6: `cloud container clusters create`コマンドで`ワーカーノード`のクラスタを作成します

`my-worker-node-cluseter`という名前で作成します

```bash:CloudShell
$ gcloud container clusters create "my-worker-node-cluseter"
```

### □手順1-7: `ワーカーノード`のクラスタが作成されるまでしばく待ちます

<img width="1314" alt="capture_002_09082019_161936.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/d00cc982-03e8-0552-acb1-48b1690c5f03.jpeg">

### □手順1-8: `kubectl get all`コマンドを実行して`ワーカーノード`のクラスタが作成されたことを確認します

```bash
$ kubectl get all
NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.15.240.1   <none>        443/TCP   91s
```

#### 上記のように表示されれば、`ワーカーノード`のクラスタ作成は完了です

#### 参考: `gcloud compute instances list`コマンドで個別の`ワーカーノード`の情報を確認することができます

```bash:CloudShell
$ gcloud compute instances list
NAME                                                 ZONE               MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP     STATUS
gke-my-worker-node-cluse-default-pool-924284ce-bm6s  asia-northeast1-a  n1-standard-1               10.146.0.15  35.243.112.157  RUNNING
gke-my-worker-node-cluse-default-pool-924284ce-kpcs  asia-northeast1-a  n1-standard-1               10.146.0.16  104.198.83.208  RUNNING
gke-my-worker-node-cluse-default-pool-924284ce-td1m  asia-northeast1-a  n1-standard-1               10.146.0.17  104.198.120.68  RUNNING
```

## 2. `Manifest`の作成と適用

"Kubernetesクラスタ"上に作成する各種オブジェクトについては、コマンドで個別に作成することも可能ですが`Manifest`と呼ばれるYAML形式のファイルを作成することにより一括した管理が可能になります

この`Manifest`の作成単位についてはいろいろ考え方があると思いますが、ここでは、`ワーカーノード`の外に作成される`Ingress`については独立して1つ作成し、`ワーカーノード`上に作成されるその他のオブジェクトについては`Service`の単位で作成したいと思います

### □手順2-1: `gcloud compute address create`コマンドでGCP上に`Ingress`に割り当てるための`スタティックなグローバルIPアドレス`を1つ作成します

```bash:CloudShell
$ gcloud compute addresses create "my-ingress-address" --global
Created [https://www.googleapis.com/compute/v1/projects/proud-command-246805/global/addresses/my-ingress-address].
```

### □手順2-2: `gcloud compute address list`コマンドで割り当てられた`スタティックなグローバルIPアドレス`を確認します

```bash:CloudShell
$ gcloud compute addresses list
NAME                ADDRESS/RANGE  TYPE      PURPOSE  NETWORK  REGION  SUBNET  STATUS
my-ingress-address  XXX.XXX.XXX.XXX  EXTERNAL                                    RESERVED
```

### □手順2-3: `Manifest`を配置するためのディレクトリを作成してカレントディレクトリを移動します

```bash:CloudShell
$ export MANIFESTS_PATH=$HOME/my-manifests
$ mkdir -p $MANIFESTS_PATH
$ cd $MANIFESTS_PATH
$ pwd
```

### □手順2-4: `kubectl create namespace`コマンドで`namespace`を作成します

`my-wordpress`という名前で`namespace`を作成します

```bash:CloudShell
$ kubectl create namespace "my-wordpress"
namespace/my-wordpress created
```

```bash:CloudShell
$ kubectl get namespace
NAME           STATUS   AGE
default        Active   24m
kube-public    Active   24m
kube-system    Active   24m
my-wordpress   Active   22s
```

### □手順2-5: この後のコマンドの実行を簡略化するために`kubectl config set-context`コマンドでデフォルトで使用する`namespace`を設定します

```bash:CloudShell
$ kubectl config set-context $(kubectl config current-context) --namespace="my-wordpress"
Context "gke_proud-command-246805_asia-northeast1-a_my-worker-node-cluseter" modified.
```

### □手順2-6: まず`namespace`名のディレクトリを作成します

```bash:CloudShell
$ mkdir -p $MANIFESTS_PATH/my-wordpress
```

### □手順2-7: 作成したディレクトリ下に`Ingress`の`Manifest(my-ingress.yaml)`を作成します

この`Manifest`では、`Ingress`のオブジェクトのみを定義しています

```bash:CloudShell
$ vi $MANIFESTS_PATH/my-wordpress/my-ingress.yaml
```

```yaml:$MANIFESTS_PATH/my-wordpress/my-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress  # このIngressの名前を定義します
  namespace: my-wordpress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: my-ingress-address  # 割り当てるスタティックIPアドレスを定義します
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:  # バックエンドのServiceとポート番号を定義します
          serviceName: web-service
          servicePort: 80

```

### □手順2-8: 続いて、Webサーバー側の`Service`の`Manifest(web-service.yaml)`を作成します

この`Manifest`では、`Service`と`Deployment`、`HorizontalPodAutoscaler`の3種類のオブジェクトを定義しています

`Deployment`はステートレス(非永続的)な`Pod`を管理するためのオブジェクトです

`HorizontalPodAutoscaler`は`Pod`のオートスケールを定義するためのオブジェクトです

`HorizontalPodAutoscaler`は指定したメトリックを30秒間隔で監視し、`targetAverageValue`で指定した値未満になるよう`Pod`数を`minReplicas`および`maxReplicas`の間で自動調整します

```bash:CloudShell
$ vi $MANIFESTS_PATH/my-wordpress/web-service.yaml
```

```yaml:$MANIFESTS_PATH/my-wordpress/web-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service  # このServiceの名前を定義します
  namespace: my-wordpress
  labels:  # このServiceに付与するラベルを定義します
    ServiceName: web-service
    Environment: development
spec:
  type: NodePort  # Kubernetesクラスタ外部からのトラフィックも許可する場合はNodePortを設定します
  ports:  # Serviceが使用するポート番号(port)と紐づけを行うPod側のポート番号(targetPort)、Node側のポート番号(nodePort)を定義します
  - port: 80
    targetPort: 80
    nodePort: 30080
    protocol: TCP
  selector:  # このServiceに紐づけるPodをPodに付与したラベルで定義します
    ServiceName: web-service
    Environment: development
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment  # このDeploymentの名前を定義します
  namespace: my-wordpress
  labels:  # このDeploymentに付与するラベルを定義します
    ServiceName: web-service
    Environment: development
spec:
  replicas: 3  # 作成するPod数を定義します
  selector:
    matchLabels:  # 作成するPodに付与するラベルを定義します
      ServiceName: web-service
      Environment: development
  template:
    metadata:
      labels:  # spec: -> selector: -> matchLabels: と同じ内容を記載する必要があります
        ServiceName: web-service
        Environment: development
    spec:
      containers:
      - name: web-container  # 作成するPodのコンテナ名を定義します
        ports:  # 作成するPodのコンテナで開放するポート情報を定義します
        - name: http
          containerPort: 80
          protocol: TCP
        resources:
          requests:  # コンテナデプロイ時に必要とするリソースを定義します(リソースが足りない場合デプロイはエラーになります)
            cpu: 100m  # 1vCPU = 1,000m を意味します
            memory: 256Mi
          limits: # コンテナリソースの上限を定義します(ノードのメモリが枯渇しないようにrequestsと同値を設定します)
            memory: 256Mi
        image: wordpress:5.2-apache  # 作成するPodのコンテナ作成時に使用するDockerイメージを定義します
        env:  # 作成するPodのコンテナに設定する環境変数を定義します
        - name: WORDPRESS_DB_HOST
          value: "db-service:3306"
        - name: WORDPRESS_DB_USER
          value: "wordpress"
        - name: WORDPRESS_DB_PASSWORD
          value: "wordpress!"
        - name: WORDPRESS_DB_NAME
          value: "wordpress"
        livenessProbe:  # ヘルスチェックに使用する情報を定義します
          httpGet:
            path: /readme.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 3
        readinessProbe:  # ヘルスチェックに使用する情報を定義します
          httpGet:
            path: /readme.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 3
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: web-deployment-horizontal-pod-autoscaler
  namespace: my-wordpress
spec:
  scaleTargetRef:  # オートスケールの対象とするDeploymentの名前を定義します
    apiVersion: apps/v1
    kind: Deployment
    name: web-deployment
  minReplicas: 3
  maxReplicas: 10
  metrics:  # オートスケールのトリガーとするメトリックを定義します
  - type: Pods
    pods:  # Pod 1台あたり 100 HTTP Requests per Second 以下になるよう調整します
      metricName: http_requests
      targetAverageValue: 100

```

#### 参考: `HorizontalPodAutoscaler`で監視対象として設定するメトリックについて
監視対象として指定するメトリックの種類については、"HTTP Requests per Second"など`RED Method`に基づいたものの方が良いと個人的に考えています

コンテナの性質上、CPU使用率/メモリ使用率など`USE Method`に基づいた監視対象メトリックのリソースが不足する場合は、`ワーカーノード`をオートスケールするように設定した方が良いと考えます

**The RED Method: How to Instrument Your Services**
https://grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services/

**The USE Method**
http://www.brendangregg.com/usemethod.html


### □手順2-9: DB(MySQL)側の`Service`の`Manifest(db-service.yaml)`を作成します

この`Manifest`では、``Service`と`StatefulSet`、`PersistentVolumeClaim`の3種類のオブジェクトを定義します

`StatefulSet`は`Deployment`とは異なりステートフル(永続的)な`Pod`を管理するためのオブジェクトです

永続化を行う際に使用するストレージ領域については`PersistentVolumeClaim`というオブジェクトで定義します

```bash:CloudShell
$ vi $MANIFESTS_PATH/my-wordpress/db-service.yaml
```

```yaml:$MANIFESTS_PATH/my-wordpress/db-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: db-service  # このServiceの名前を定義します
  namespace: my-wordpress
  labels:  # このServiceに付与するラベルを定義します
    ServiceName: db-service
    Environment: development
spec:
  type: ClusterIP  # Kubernetesクラスタ内のトラフィックのみ許可する場合はClusterIPを設定します
  ports:  # Serviceが使用するポート番号(port)と紐づけを行うPod側のポート番号(targetPort)を定義します
  - port: 3306
    targetPort: 3306
    protocol: TCP
  selector:  # このServiceに紐づけるPodをPodに付与したラベルで定義します
    ServiceName: db-service
    Environment: development
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db-statefulset  # このStatefulSetの名前を定義します
  namespace: my-wordpress
  labels:  # このStatefulSetに付与するラベルを定義します
    ServiceName: db-service
    Environment: development
spec:
  replicas: 1  # 作成するPod数を定義します
  serviceName: db-service  # このStatefulSetに紐付けるServiceを定義します
  selector:
    matchLabels:  # 作成するPodに付与するラベルを定義します
      ServiceName: db-service
      Environment: development
  template:
    metadata:
      labels:  # spec: -> selector: -> matchLabels: に記載した内容と同じ内容を記載する必要があります
        ServiceName: db-service
        Environment: development
    spec:
      volumes:
      - name: db-persistent-volume  # このPodのボリューム名を定義します
        persistentVolumeClaim:
          claimName: db-persistent-volume-claim  # このPodのボリュームに紐づけるPersistentVolumeClaimを定義します
      containers:
      - name: db-container  # 作成するPodのコンテナ名を定義します
        ports:  # 作成するPodのコンテナで開放するポート情報を定義します
        - name: mysql
          containerPort: 3306
          protocol: TCP
        resources:
          requests:  # コンテナデプロイ時に必要とするリソースを定義します(リソースが足りない場合デプロイはエラーになります)
            cpu: 100m  # 1vCPU = 1,000m を意味します
            memory: 512Mi
          limits: # コンテナリソースの上限を定義します(ノードのメモリが枯渇しないようにrequestsと同値を設定します)
            memory: 512Mi
        image: mysql:5.6  # 作成するPodのコンテナ作成時に使用するDockerイメージを定義します
        env:  # 作成するPodのコンテナに設定する環境変数を定義します
        - name: MYSQL_ROOT_PASSWORD
          value: "somewordpress"
        - name: MYSQL_DATABASE
          value: "wordpress"
        - name: MYSQL_USER
          value: "wordpress"
        - name: MYSQL_PASSWORD
          value: "wordpress!"
        volumeMounts:  # このPodのコンテナが使用するボリューム名とマウントポイントを定義します
        - name: db-persistent-volume
          mountPath: /var/lib/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-persistent-volume-claim  # このPersistentVolumeClaimの名前を定義します
  namespace: my-wordpress
  labels:  # このPersistentVolumeClaimに付与するラベルを定義します
    ServiceName: db-service
    Environment: development
spec:
  accessModes:
    - ReadWriteOnce  # Read/Writeは単一Podからのみ許可することを意味します
  resources:
    requests:
      storage: 20Gi  # 作成するボリュームのサイズを定義します

```

### □手順2-10: `kubectl apply`コマンドで、`db-service`関連のオブジェクトから作成します

```bash:CloudShell
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/db-service.yaml
```

### □手順2-11: `kubectl get all`コマンドでオブジェクトが作成されたことを確認します

```bash:CloudShell
$ kubectl get all
NAME                   READY   STATUS    RESTARTS   AGE
pod/db-statefulset-0   1/1     Running   0          46s
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/db-service   ClusterIP   10.15.241.248   <none>        3306/TCP   47s
NAME                              DESIRED   CURRENT   AGE
statefulset.apps/db-statefulset   1         1         47s
```

#### 参考: `StatefulSet`は、`ナビゲーションメニュー`の`Google Kubernetes Engine`>`ワークロード`から確認することができます

<img width="1314" alt="capture_003_09082019_171435.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/5f668380-8d5c-7a3b-56e1-6d57226f31a2.jpeg">

#### 参考: `Service`は、`ナビゲーションメニュー`の`Google Kubernetes Engine`>`ServiceとIngress`から確認することができます

<img width="1314" alt="capture_006_09082019_171823.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/1ca09059-6ba2-1dd0-7268-83d0bccc722f.jpeg">

#### 参考: `PersistentVolumeClaim`は、`ナビゲーションメニュー`の`Google Kubernetes Engine`>`ストレージ`から確認することができます

<img width="1314" alt="capture_007_09082019_171854.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/4b147f0e-c32c-3c74-9b68-eed9a29e531f.jpeg">

### □手順2-12: `kubectl run`コマンドを使ってテンポラリの`Pod`を作成し`Service`との接続確認を行います

`Service`に割り当てられている`ClusterIP`へは"Kubernetesクラスタ"内部からのみ疎通可能です

`kubectl run`コマンドを使えばテンポラリの`Pod`を簡単に作成できるので、これを用いて接続確認を行います

```bash:CloudShell
$ kubectl run "mysql-client-pod" --image=mysql:5.6 --rm --restart=Never -it -- mysql -h "db-service" -u "wordpress" -p'wordpress!'
If you don't see a command prompt, try pressing enter.
mysql> quit
Bye
pod "mysql-client-pod" deleted
```

### □手順2-13: 続いて、`web-service`関連のオブジェクトを作成します

```bash:CloudShell
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/web-service.yaml
```

### □手順2-14: `kubectl get all`コマンドでオブジェクトが作成されたことを確認します

```bash:CloudShell
$ kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/db-statefulset-0                  1/1     Running   0          29m
pod/web-deployment-5f4f68bf87-4vvnx   1/1     Running   0          16m
pod/web-deployment-5f4f68bf87-h2pr4   1/1     Running   0          16m
pod/web-deployment-5f4f68bf87-r5kjt   1/1     Running   0          16m
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/db-service    ClusterIP   10.15.241.248   <none>        3306/TCP       29m
service/web-service   NodePort    10.15.249.35    <none>        80:30080/TCP   16m
NAME                             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/web-deployment   3         3         3            3           16m
NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/web-deployment-5f4f68bf87   3         3         3       16m
NAME                              DESIRED   CURRENT   AGE
statefulset.apps/db-statefulset   1         1         29m
NAME                                                                           REFERENCE                   TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/web-deployment-horizontal-pod-autoscaler   Deployment/web-deployment   <unknown>/10   3         10        3          43s
```

#### 参考: `Deployment`は、`ナビゲーションメニュー`の`Google Kubernetes Engine`>`ワークロード`からが確認することができます

<img width="1314" alt="capture_008_09082019_174222.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/90164767-a444-00d4-9b2c-b4e29f03e95d.jpeg">

#### 参考: `Service`は、`ナビゲーションメニュー`の`Google Kubernetes Engine`>`ServiceとIngress`から確認することができます

<img width="1314" alt="capture_011_09082019_174940.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/ac126bc8-de3d-29d6-0b0f-3a29fb512b91.jpeg">

### □手順2-15: `kubectl run`コマンドを使ってテンポラリの`Pod`を作成し`Service`との接続確認を行います

Webサーバー側についても同様に`kubectl run`コマンドを使ってテンポラリの`Pod`を作成して接続確認を行います

```bash:CloudShell
$ kubectl run "curl-pod" --image=amazonlinux:2 --rm --restart=Never -it -- curl -I -Ss "http://web-service.my-wordpress.svc.cluster.local/readme.html"
HTTP/1.1 200 OK
Date: Fri, 09 Aug 2019 08:50:50 GMT
Server: Apache/2.4.38 (Debian)
Last-Modified: Mon, 08 Apr 2019 22:59:56 GMT
ETag: "1d17-5860ccb887300"
Accept-Ranges: bytes
Content-Length: 7447
Vary: Accept-Encoding
Content-Type: text/html

pod "curl-pod" deleted
```

### □手順2-16: `kubectl apply`コマンドで`Ingress(my-ingress)`を作成します

```bash:CloudShell
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/my-ingress.yaml
ingress.extensions/my-ingress created
```

### □手順2-17: `kubectl get ingress`コマンドで`Ingress`が作成されたことを確認します

"Google Kubernetes Engine(GKE)"環境において、`Ingress`の実体は、"Google Cloud Load Balancing"ベースのソフトウェア定義です

そのため、`Ingress`の作成には5分ほど要します

次に示すようにIPアドレスが割りてられるまで待つ必要があります

```bash:CloudShell
$ kubectl get ingress
NAME         HOSTS   ADDRESS         PORTS   AGE
my-ingress   *       35.244.156.32   80      4m39s
```

#### 参考: `Ingress`は、`ナビゲーションメニュー`の`Google Kubernetes Engine`>`ServiceとIngress`から確認することができます

<img width="1314" alt="capture_013_09082019_194119.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/748127e6-3464-1928-6c2b-aecc3c5c801e.jpeg">

### □手順2-18: `ナビゲーションメニュー`から`Kubernetes Engine`>`Service と Ingress`を選択します

<img width="1314" alt="capture_016_09082019_194255.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/b45483b0-a152-7b8d-66ce-4eef7627528e.jpeg">

### □手順2-19: `my-ingress`列の`エンドポイント`欄部分をクリックして"Wordpress"の初期設定画面が表示されれば成功です

<img width="1314" alt="capture_019_09082019_194529.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/63f34d30-d2a6-1ab7-5025-09e6f0eb9d10.jpeg">


<img width="1314" alt="capture_018_09082019_194455.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/20864482-4379-fb29-7387-7dc9c6a2ea5f.jpeg">

#### 以上、Google Kubernetes Engine(GKE)上を使って "Wordpress" のシステムを構築するまでの手順でした

ここまでの手順が上手くいかなかった場合のトラブルシューティングの方法をいくつか記載しておきますので、参考にしてください

#### 参考: `kubectl port-forward`コマンドを使ったトラブルシューティング

`Service`に割り当てられた`ClusterIP`へは"Kubernetesクラスタ"内部からのみしか接続できませんので、`Ingress`側の問題との切り分けを行う際はポートフォワーディングの設定が有効です

`kubectl port-forward`コマンドで`Service`に対してポートフォワーディングを設定します

```bash:CloudShell
$ kubectl port-forward service/web-service 8080:80
```

`Cloud Shell`の右上にある`ウェブでプレビュー`アイコンをクリック後`プレビューのポート:8080`を選択します

<img width="1314" alt="capture_022_09082019_194742.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/9d8dd903-93d7-11a0-3bf5-146ec7364585.jpeg">

"ポートフォワーディング"によりWebブラウザから直接`Service`の`ClusterIP`に対してアクセスが可能になりました

<img width="1314" alt="capture_023_09082019_194815.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/91afe3df-a82a-d4c0-c713-4a10b18c3d43.jpeg">

#### 参考: `Pod`のトラブルシューティング

`kubectl logs`コマンドを使用することで`Pod`個別のログメッセージを確認できます

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE    IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          159m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4vvnx   1/1     Running   0          146m   10.12.2.15   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-h2pr4   1/1     Running   0          146m   10.12.2.14   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-r5kjt   1/1     Running   0          146m   10.12.1.5    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>

$ kubectl logs <Pod Name>
 :
中略
 ：
```

より詳細な調査が必要な場合は、`kubectl excec`コマンドを使用することで`Pod`に直接`bash`でログインすることができます

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE    IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          159m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4vvnx   1/1     Running   0          146m   10.12.2.15   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-h2pr4   1/1     Running   0          146m   10.12.2.14   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-r5kjt   1/1     Running   0          146m   10.12.1.5    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>

$ kubectl exec <Pod Name> -it -- bash
root@<Pod Name>:/#h
```

## 3. Podのアップデートとロールバック

"Kubernetes"では、各`Pod`の"Dockerイメージ"を簡単にアップデートしたりロールバックしたりすることが可能です

### □手順3-1: `sed`コマンドを使って`Manifest`上のDockerイメージの値を`wordpress:5.2-apache`から`wordpress:5.2.2-apache`に書き換えます

```bash:CloudShell
sed -i -e "s/wordpress:5.2-apache/wordpress:5.2.2-apache/g" $MANIFESTS_PATH/my-wordpress/web-service.yaml
```

### □手順3-2: `kubectl apply`コマンドで修正した`Manifest`を上書き適用します

```bash:CloudShell
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/web-service.yaml
service/web-service unchanged
deployment.apps/web-deployment configured
horizontalpodautoscaler.autoscaling/web-deployment-horizontal-pod-autoscaler configured
```

### □手順3-3: `kubectl get pods`コマンドで`Pod`の状態を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS              RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running             0          3h24m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5b7f866c47-c4b6w   0/1     ContainerCreating   0          24s     <none>       gke-my-worker-node-cluse-default-pool-924284ce-bm6s   <none>
web-deployment-5b7f866c47-swvvb   1/1     Running             0          41s     10.12.2.24   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-h2pr4   1/1     Running             0          3h11m   10.12.2.14   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-r5kjt   1/1     Running             0          3h11m   10.12.1.5    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>
```

元々あった3つの`Pod`はそのままで4つめの`Pod`が作成されています

### □手順3-4: しばらく待って、もう一度`kubectl get pods`コマンドで`Pod`の状態を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          3h26m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5b7f866c47-c4b6w   1/1     Running   0          2m29s   10.12.0.7    gke-my-worker-node-cluse-default-pool-924284ce-bm6s   <none>
web-deployment-5b7f866c47-qjg84   1/1     Running   0          112s    10.12.2.25   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5b7f866c47-swvvb   1/1     Running   0          2m46s   10.12.2.24   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
```

`Pod`の名前を確認するとすべての`Pod`が差し替えられた事がわかります

### □手順3-5: `kubectl rollout history`コマンドを実行します

```bash:CloudShell
$ kubectl rollout history deployment web-deployment
deployment.extensions/web-deployment
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
```

### □手順3-5: `kubectl rollout history`コマンドで1つ目の`Revision`の情報を確認します

```bash:CloudShell
$ kubectl rollout history deployment web-deployment --revision 1
deployment.extensions/web-deployment with revision #1
Pod Template:
  Labels:       Environment=development
        ServiceName=web-service
        pod-template-hash=5f4f68bf87
  Containers:
   web-container:
    Image:      wordpress:5.2-apache
    Port:       80/TCP
    Host Port:  0/TCP
    Limits:
      memory:   256Mi
    Requests:
      cpu:      100m
      memory:   256Mi
    Liveness:   http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
    Readiness:  http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
    Environment:
      WORDPRESS_DB_HOST:        db-service:3306
      WORDPRESS_DB_USER:        wordpress
      WORDPRESS_DB_PASSWORD:    wordpress!
      WORDPRESS_DB_NAME:        wordpress
    Mounts:     <none>
  Volumes:      <none>

```

Dockerイメージとして`wordpress:5.2-apache`を使用していたことが確認できます

### □手順3-6: 同様に2つ目の`Revision`の詳細を確認します

```bash:CloudShell
$ kubectl rollout history deployment web-deployment --revision 2
deployment.extensions/web-deployment with revision #2
Pod Template:
  Labels:       Environment=development
        ServiceName=web-service
        pod-template-hash=5b7f866c47
  Containers:
   web-container:
    Image:      wordpress:5.2.2-apache
    Port:       80/TCP
    Host Port:  0/TCP
    Limits:
      memory:   256Mi
    Requests:
      cpu:      100m
      memory:   256Mi
    Liveness:   http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
    Readiness:  http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
    Environment:
      WORDPRESS_DB_HOST:        db-service:3306
      WORDPRESS_DB_USER:        wordpress
      WORDPRESS_DB_PASSWORD:    wordpress!
      WORDPRESS_DB_NAME:        wordpress
    Mounts:     <none>
  Volumes:      <none>
```

使用しているDockerイメージが`wordpress:5.2.2-apache`に変更されていることが確認できます

### □手順3-7: `kubectl rollout undo`コマンドを実行しロールバックを行います

```bash:CloudShell
$ kubectl rollout undo deployment web-deployment --to-revision 1
deployment.extensions/web-deployment
```

### □手順3-8: `kubectl rollout history`コマンドを実行します

```bash:CloudShell
$ kubectl rollout history deployment web-deployment
deployment.extensions/web-deployment
REVISION  CHANGE-CAUSE
2         <none>
3         <none>
```

`Revision 1`が無くなって`Revision 3`が追加されています

### □手順3-9: `kubectl get pods`コマンドで`Pod`の状態を確認します

```bash:CloudShell
 kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          3h40m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4ztjn   1/1     Running   0          5m39s   10.12.2.27   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-m8wtz   1/1     Running   0          5m50s   10.12.2.26   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-nfwbz   1/1     Running   0          6m4s    10.12.1.6    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>
```

`Pod`の名前を確認するとすべての`Pod`がまた差し替えられた事がわかります


### □手順3‐10: `kubectl rollout history`コマンドで3つ目の`Revision`の情報を確認します

```bash:CloudShell
$ kubectl rollout history deployment web-deployment --revision 3
deployment.extensions/web-deployment with revision #3
Pod Template:
  Labels:       Environment=development
        ServiceName=web-service
        pod-template-hash=5f4f68bf87
  Containers:
   web-container:
    Image:      wordpress:5.2-apache
    Port:       80/TCP
    Host Port:  0/TCP
    Limits:
      memory:   256Mi
    Requests:
      cpu:      100m
      memory:   256Mi
    Liveness:   http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
    Readiness:  http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
    Environment:
      WORDPRESS_DB_HOST:        db-service:3306
      WORDPRESS_DB_USER:        wordpress
      WORDPRESS_DB_PASSWORD:    wordpress!
      WORDPRESS_DB_NAME:        wordpress
    Mounts:     <none>
  Volumes:      <none>
```

使用しているDockerイメージが`wordpress:5.2-apache`に戻っていることを確認できます

### `Pod`の"Dockerイメージ"を簡単にアップデートしたりロールバックしたりできることを確認できました

## 4. Pod障害時の挙動確認

#### `Pod`障害時の挙動について確認してみます。まず`Deployment`によって作成された非永続的な`Pod`が障害になったときの挙動について確認します

### □手順4‐1: `kubectl get pods`コマンドで現在稼働している`Pod`の情報を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          3h44m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4ztjn   1/1     Running   0          9m41s   10.12.2.27   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-m8wtz   1/1     Running   0          9m52s   10.12.2.26   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-nfwbz   1/1     Running   0          10m     10.12.1.6    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>
```

### □手順4‐2: `kubectl delete pod <Pod Name>`コマンドでリストの一番下の`Pod`を削除してみます

```bash:CloudShell
$ kubectl delete pod "web-deployment-5f4f68bf87-nfwbz"
pod "web-deployment-5f4f68bf87-nfwbz" deleted
```

### □手順4‐3: `kubectl get pods`コマンドで直後の`Pod`の状態を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          3h47m   10.12.2.7    gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4ztjn   1/1     Running   0          11m     10.12.2.27   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-m8wtz   1/1     Running   0          12m     10.12.2.26   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-sst4v   1/1     Running   0          41s     10.12.2.28   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
```

### すぐに新しい`Pod`が別の名前で再作成されたことが確認できました。続いて`StatefulSet`によって作成された永続的な`Pod`が障害になった場合の挙動について確認します

### □手順4‐4: `kubectl delete pod`コマンドで`db-statefulset-0`を削除してみます

```bash:CloudShell
$ kubectl delete pod "db-statefulset-0"
pod "db-statefulset-0" deleted
```

### □手順4‐5: `kubectl get pods`コマンドで`Pod`の状態を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          59s     10.12.2.29   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4ztjn   1/1     Running   0          14m     10.12.2.27   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-m8wtz   1/1     Running   0          15m     10.12.2.26   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-sst4v   1/1     Running   0          3m41s   10.12.2.28   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
```

#### `StatefulSet`によって作成された`Pod`については、`Deployment`の時とは異なり同じ名前の`Pod`が再作成されることが確認できました

## 5. ワーカーノード障害時の挙動確認

#### 最後に、`ワーカーノード`障害時の挙動について確認してみます

### □手順5‐1: `kubectl get pods`コマンドで現在稼働している`Pod`の情報を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   0          6m51s   10.12.2.29   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4ztjn   1/1     Running   0          20m     10.12.2.27   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-cddpk   1/1     Running   0          2m      10.12.1.7    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>
web-deployment-5f4f68bf87-dvfns   1/1     Running   0          51s     10.12.2.31   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
```

### □手順5‐2: `StatefulSet`によって作成された`Pod`が稼働している`ワーカーノード`にログインします

```bash:CloudShell
$ gcloud compute ssh "gke-my-worker-node-cluse-default-pool-924284ce-kpcs"
WARNING: The public SSH key file for gcloud does not exist.
WARNING: The private SSH key file for gcloud does not exist.
WARNING: You do not have an SSH key for gcloud.
WARNING: SSH keygen will be executed to generate a key.
This tool needs to create the directory [/home/kukita_keisuke/.ssh]
before being able to generate SSH keys.
Do you want to continue (Y/n)?  Y
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/kukita_keisuke/.ssh/google_compute_engine.
Your public key has been saved in /home/kukita_keisuke/.ssh/google_compute_engine.pub.
The key fingerprint is:
SHA256:FUxUU0YJTt5ObFMLIacFwiDU1kKz0ZAhqHeRiid6Eo8 kukita_keisuke@cs-6000-devshell-vm-e9163938-594a-4670-8c13-1d9ca474820d
The key's randomart image is:
+---[RSA 2048]----+
|    o++BO=++*O=..|
|   . oo=++o===o..|
|  o . o.. ..o *. |
|.+ + .   .   + . |
|.++ .   S     .  |
|E o              |
| o               |
|                 |
|                 |
+----[SHA256]-----+
Did you mean zone [asia-east1-b] for instance:
gke-my-worker-node-cluse-default-pool-924284ce-kpcs] (Y/n)?  n
No zone specified. Using zone [asia-northeast1-a] for instance: [gke-my-worker-node-cluse-default-pool-924284ce-kpcs].
Updating project ssh metadata...⠶Updated [https://www.googleapis.com/compute/v1/projects/proud-command-246805].
Updating project ssh metadata...done.
Waiting for SSH key to propagate.
Warning: Permanently added 'compute.147868497783857976' (ED25519) to the list of known hosts.
Welcome to Kubernetes v1.12.8-gke.10!
You can find documentation for Kubernetes at:
  http://docs.kubernetes.io/
The source for this release can be found at:
  /home/kubernetes/kubernetes-src.tar.gz
Or you can download it at:
  https://storage.googleapis.com/kubernetes-release-gke/release/v1.12.8-gke.10/kubernetes-src.tar.gz
It is based on the Kubernetes source at:
  https://github.com/kubernetes/kubernetes/tree/v1.12.8-gke.10
For Kubernetes copyright and licensing information, see:
  /home/kubernetes/LICENSES
```

### □手順5‐3: `ワーカーノード`を再起動します

```bash:WorkerNode
$ sudo /sbin/shutdown -r now
Connection to 104.198.83.208 closed by remote host.
Connection to 104.198.83.208 closed.
ERROR: (gcloud.compute.ssh) [/usr/bin/ssh] exited with return code [255].
```

### □手順5‐4: `kubectl get pods`コマンドで`Pod`の状態を確認します

```bash:CloudShell
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE                                                  NOMINATED NODE
db-statefulset-0                  1/1     Running   1          18m   10.12.2.36   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-4ztjn   1/1     Running   2          32m   10.12.2.35   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
web-deployment-5f4f68bf87-cddpk   1/1     Running   0          13m   10.12.1.7    gke-my-worker-node-cluse-default-pool-924284ce-td1m   <none>
web-deployment-5f4f68bf87-dvfns   1/1     Running   2          12m   10.12.2.32   gke-my-worker-node-cluse-default-pool-924284ce-kpcs   <none>
```

#### `ワーカーノード`障害時にも各`Pod`は自動的に復旧されることが確認できます

---

## おまけ: "Google Kubernetes Engine(GKE)" では1つの "Ingress" で "namespace" が異なる "Service" を登録できない？

"１つのグローバルIPアドレス"(≒1つの`Ingress`)で複数の`Service`へのトラフィックを管理することが可能だというのが`Ingress`のメリットでもあります

この場合、`namespace`は分けて管理したくなるのですが、"Google Kubernetes Engine(GKE)"側の制約として NG のようです（Kubernetes側の仕様としては問題ないです）

当初は以下のような`Manifest`を作成し、`Ingress`と`Service`とは異なる`namespace`を使って管理することを考えていました

```bash:CloudShell
$ vi $MANIFESTS_PATH/default/my-ingress.yaml
```

```yaml:$MANIFESTS_PATH/default/my-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress  # このIngressの名前を定義します
  namespace: default  # Ingressのnamespaceはdefaultにします
  annotations:
    kubernetes.io/ingress.global-static-ip-name: my-ingress-address  # 割り当てるスタティックIPアドレスを定義します
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:  # バックエンドのServiceとポート番号を定義します
          serviceName: web-service
          servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: default  # Ingressは同じ名前空間のServiceのみバックエンドとして登録可能です
  labels:  # このServiceに付与するラベルを定義します
    ServiceName: web-service
    Environment: development
spec:
  type: ExternalName  # ExternalName(外部名)は異なるnamespace上のServiceとリンクするために使用します
  externalName: web-service.my-wordpress.svc.cluster.local # リンク先のServiceを指定します
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

```

ところがこの方法で`Ingress`を作成すると下記のようなエラーメッセージが出力されてしまいました

```
error while evaluating the ingress spec: service "default/web-service" is type "ExternalName", expected "NodePort" or "LoadBalancer"
```

<img width="1314" alt="capture_012_09082019_192314.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44745/3196fc20-b5b3-b87d-ffb3-bc69bfe4da90.jpeg">

どうやらこれは、現時点での"Google Kubernetes Engine(GKE)"の制約↓のようですので、改善を期待したいところです

**Cross-namespace Ingress #17088**
https://github.com/kubernetes/kubernetes/issues/17088

---

以上、Google Kubernetes Engine(GKE)"を使って"Kubernetes"について勉強した際の内容でした

今回は、`Deployment`と`StatefulSet`を中心に動きを確認してみましたが、`Pod`を管理するためのオブジェクトとしては、他にも `DaemonSet`、`CronJob`といったものがあるため、別の記事としてまとめていきたいと思います