Kubernetes 入門2 [ Ingress ] [ 備忘録 ]

# 事前準備
## 一つ前の記事
https://qiita.com/oyne2561/items/5bdd8ed10a41a7fe142d

## 準備コマンド
### 1. ローカル環境でKubernetesクラスターを起動する
```
minikube start
```

```
# 別ターミナルので実行
watch 'kubectl get pod,svc,ingress -o wide'
```

### 2. helloworldのpodを作成
```
kubectl run --port 8080 --image gcr.io/google-samples/hello-app:1.0 --restart Never helloworld
```

クラスター内の他のPodから、HelloWorld Podへのアクセスをテスト
```
kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

# curl helloworld pod
curl  10.244.0.11:8080
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077353/485a907f-1c2e-4a62-8aee-4fe7985105aa.png)


### 3. ClusterIP Serviceの作成
```
kubectl expose pod helloworld --type ClusterIP --port 8080 --name helloworld-clusterip
```

# kubectl expose コマンドパラメーター解説

## 基本構文
```bash
kubectl expose pod helloworld --type ClusterIP --port 8080 --name helloworld-clusterip
```


### 各パラメーターの詳細

### # `kubectl expose`
- Kubernetesリソースを外部に公開するためのコマンド
- Pod、Deployment、ReplicaSetなどのリソースに対してServiceを作成する

#### `pod helloworld`
- `pod`: 公開するリソースタイプ（この場合はPod）
- `helloworld`: 公開するPodの名前

#### `--type ClusterIP`
- Serviceのタイプを指定
- `ClusterIP`: クラスター内部からのみアクセス可能（デフォルト）
- 他のオプション: `NodePort`、`LoadBalancer`、`ExternalName`

#### `--port 8080`
- Serviceが受け付けるポート番号
- 外部からこのポートでアクセスできる
- Podの実際のポートと異なっていても構わない

#### `--name helloworld-clusterip`
- 作成されるServiceの名前を指定
- 指定しない場合は、元のリソース名（この場合は"helloworld"）が使用される

#### 実行結果
このコマンドにより、`helloworld`というPodに対してクラスター内部からポート8080でアクセス可能なServiceが作成されます。他のPodからは`helloworld-clusterip:8080`でアクセスできるようになります。

```
# クラスター内の他のPodから、helloworld ClusterIP serviceアクセスをテスト
kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

# curl helloworld `ClusterIP` service
curl helloworld-clusterip:8080
```

### 4. NodePort Serviceの作成

```
kubectl expose pod helloworld --type NodePort --port 8080 --name helloworld-nodeport
```
クラスター内の他のPodから、helloworld `NodePort` serviceアクセスをテスト
```
kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

# curl helloworld NodePort service
curl helloworld-nodeport:8080
```

### 5. LoadBalancer Serviceの作成

```
kubectl expose pod helloworld --type LoadBalancer --port 8080 --name helloworld-lb
```

クラスター内の他のPodから、helloworld `LoadBalancer` serviceアクセスをテスト

```
kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

curl helloworld-lb:8080
```

クラスター外のMacから接続
```
minikube service helloworld-lb --url
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077353/99b25355-fbdf-4cde-b132-eeae33524dd2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077353/e8a9c592-097b-44bd-9da4-2b9f91b33093.png)

最終のターミナルはこちら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077353/27db216a-11ba-45ce-8b23-9d00b15b868b.png)

# Kubernetesサービス比較ガイド

Kubernetesにおけるネットワークアクセスの方法として、4つの主要なサービスタイプがあります。それぞれの特徴と使い分けについて詳しく解説します。

## サービス比較表

| サービスタイプ | アクセス範囲 | 用途 | ポート範囲 | 外部からのアクセス | 負荷分散 |
|---|---|---|---|---|---|
| **ClusterIP** | クラスター内のみ | 内部通信 | 任意 | 不可 | あり |
| **NodePort** | ノードのIP経由 | 開発・テスト環境 | 30000-32767 | 可能 | あり |
| **LoadBalancer** | 外部ロードバランサー経由 | 本番環境 | 任意 | 可能 | あり |
| **Ingress** | HTTP/HTTPSルーティング | Webアプリケーション | 80/443 | 可能 | あり |

## 各サービスタイプの詳細

### ClusterIP（デフォルト）

**概要**  
クラスター内部でのみアクセス可能な仮想IPアドレスを提供します。

**特徴**
- Kubernetesのデフォルトサービスタイプ
- クラスター内のPod間通信に使用
- 外部からは直接アクセス不可
- DNSによる名前解決が可能

**使用場面**
- データベースサービス
- 内部API
- マイクロサービス間の通信

**設定例**
```yaml
apiVersion: v1
kind: Service
metadata:
  name: my-clusterip-service
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
```

### NodePort

**概要**  
各ノードの特定ポート（30000-32767）を通じて外部からアクセス可能にします。

**特徴**
- クラスターの全ノードで同じポートが開放される
- `<NodeIP>:<NodePort>`でアクセス可能
- ClusterIPも自動的に作成される
- ファイアウォール設定が必要な場合あり

**使用場面**
- 開発環境での外部アクセス
- テスト環境
- 小規模なアプリケーション

**設定例**
```yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30001
```

### LoadBalancer

**概要**  
クラウドプロバイダーの外部ロードバランサーを自動的に作成し、外部アクセスを提供します。

**特徴**
- クラウドプロバイダー（AWS、GCP、Azure等）が必要
- 外部IPアドレスが自動割り当て
- 高可用性と負荷分散を提供
- NodePortとClusterIPも自動作成

**使用場面**
- 本番環境のWebアプリケーション
- 外部公開が必要なサービス
- 高可用性が求められるシステム

**設定例**
```yaml
apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
```

### Ingress

**概要**  
HTTP/HTTPSトラフィックをクラスター内のサービスにルーティングするルールを定義します。

**特徴**
- Layer 7（アプリケーション層）での負荷分散
- ホスト名やパスベースのルーティング
- SSL/TLS終端処理
- IngressControllerが必要

**使用場面**
- 複数のWebアプリケーションをホスト
- SSL証明書の一元管理
- パスベースルーティング
- サブドメインルーティング

**設定例**
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80
```

## 選択指針

### ClusterIPを選ぶべき場合
- 内部サービス間の通信のみ必要
- データベースやキャッシュサービス
- セキュリティを重視する内部API

### NodePortを選ぶべき場合
- 開発・テスト環境での外部アクセス
- シンプルな外部公開が必要
- クラウドプロバイダーを使用していない

### LoadBalancerを選ぶべき場合
- 本番環境での外部公開
- 高可用性が必要
- クラウド環境での運用

# Ingress
**helloworldコンテナをIngress（L7　LB）でクラスタ外部からhost/pathURLでアクセス可能にする**
- IngressはPodをクラスター内外に公開するL７ロードバランサー
- クラスター外部からURLのホスト・パスによるServiceへの振り分けアクセスができるL7ロードバランシング（負荷分散）

## Ingress addonを追加

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

# Ingress addonを追加
minikube addons enable ingress

# Ingress controller podをチェック
kubectl get pods -n ingress-nginx
```

`ingress.yaml`を作成
```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: helloworld
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: helloworld-nodeport
            port:
              number: 8080
```

ingress resourceを作成
```
kubectl apply -f ingress.yaml    
```

ingressをリストアップ
```
kubectl get ingress
```

virualbox driverでminikubeを立ち上げないとホストからサービスに接続できないらしいので、実験はここで終了。
https://github.com/kubernetes/minikube/issues/15965

### クラスター内の他のPodからの通信は確認できたので環境が悪さをしているみたい。

helloworld_v2を作成しingressの動作確認

`ingress_path.yaml`
```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: helloworld-v2
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - http:
      paths:
      - path: /helloworld_v2
        pathType: Prefix
        backend:
          service:
            name: helloworld-v2-nodeport
            port:
              number: 8080
```

実行
```
# pod
kubectl run --image gcr.io/google-samples/hello-app:2.0 --port 8080 --restart Never helloworld-v2

# service
kubectl expose pod helloworld-v2 --type NodePort --port 8080 --name helloworld-v2-nodeport

# ingress
kubectl apply -f ingress_path.yaml
```

調査
```
kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

If you don't see a command prompt, try pressing enter.
/ $ curl 10.244.0.20:8080
Hello, world!
Version: 2.0.0
Hostname: helloworld-v2
/ $ curl helloworld-v2-nodeport:8080
Hello, world!
Version: 2.0.0
Hostname: helloworld-v2
/ $ curl 192.168.49.2 
Hello, world!
Version: 1.0.0
Hostname: helloworld
/ $ curl 192.168.49.2/helloworld_v2 
Hello, world!
Version: 2.0.0
Hostname: helloworld-v2
```

# 参考
## 削除コマンド
```
kubectl delete pod helloworld
kubectl delete service helloworld-clusterip
kubectl delete service helloworld-nodeport 
kubectl delete service helloworld-lb

kubectl delete pod helloworld-v2
kubectl delete service helloworld-v2-nodeport 
kubectl delete ingress helloworld
kubectl delete ingress helloworld-v2
```

クリーンアップ完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077353/43a36a3d-1120-4176-88eb-d9af87aa5920.png)