---
description: >-
  在上一篇文章中，我們介紹了 Kubernetes Ingress 與 Nginx Ingress Controller
  的基本使用方法。本篇文章將進一步說明如何為 Ingress 配置 TLS（HTTPS），讓服務可以透過加密的 HTTPS 協議安全地提供外部訪問。
---

# Ingress TLS Easy setup

### 目錄

1. [Ingress TLS 簡介](https://chatgpt.com/c/c30f6099-ca46-4331-bdd4-c40728479478#ingress-tls-%E7%B0%A1%E4%BB%8B)
2. [建立與生成自簽證書（Local 測試）](https://chatgpt.com/c/c30f6099-ca46-4331-bdd4-c40728479478#%E5%BB%BA%E7%AB%8B%E8%88%87%E7%94%9F%E6%88%90%E8%87%AA%E7%B0%BD%E8%AD%89%E6%9B%B8local-%E6%B8%AC%E8%A9%A6)
3. [建立 Kubernetes Secret](https://chatgpt.com/c/c30f6099-ca46-4331-bdd4-c40728479478#%E5%BB%BA%E7%AB%8B-kubernetes-secret)
4. [更新 Ingress 資源，啟用 TLS](https://chatgpt.com/c/c30f6099-ca46-4331-bdd4-c40728479478#%E6%9B%B4%E6%96%B0-ingress-%E8%B3%87%E6%BA%90%E5%95%9F%E7%94%A8-tls)
5. [測試 HTTPS 訪問](https://chatgpt.com/c/c30f6099-ca46-4331-bdd4-c40728479478#%E6%B8%AC%E8%A9%A6-https-%E8%A8%AA%E5%95%8F)
6. [總結](https://chatgpt.com/c/c30f6099-ca46-4331-bdd4-c40728479478#%E7%B8%BD%E7%B5%90)

***

### 1. Ingress TLS 簡介

當 Kubernetes Ingress 需要支援 **HTTPS**，我們必須配置 TLS 憑證。通常有兩種方式：

1. **使用真實 CA（Certificate Authority）簽發的證書**
2. **使用自簽證書（Self-Signed Certificate）**（適用於本地測試環境）

這篇文章會使用 **自簽證書** 來演示如何啟用 **TLS**，並將其綁定到 **AP 服務（app.caster.com）** 及 **MySQL 服務（mysql.caster.com）**。

***

### 2. 建立與生成自簽證書（Local 測試）

我們將使用 `openssl` 生成自簽證書，並設定 **域名 `caster.com`**。

#### **步驟 1：生成私鑰與證書**

執行以下指令來生成一個 **2048-bit RSA** 私鑰：

```bash
openssl req -x509 -nodes -days 365 -keyout caster_com.key -out caster_com.crt -config ssl.conf
```

```
// ssl.conf
[req]
default_bits       = 2048
default_keyfile    = privkey.pem
distinguished_name = req
x509_extensions    = v3_ca
prompt = no
utf8 = yes

[dn]
C = TW
ST = Taiwan
L = Taipei
O = Caster Inc.
OU = IT Department
emailAddress = service@caster.com

[ req_distinguished_name ]
CN = *.caster.com

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.caster.com
```

#### **步驟 2：驗證憑證**

確認 `caster_com.key` 和 `caster_com.crt` 是否成功生成：

```bash
ls -l caster_com.*
```

***

### 3. 建立 Kubernetes Secret

現在我們需要將 **憑證** 和 **私鑰** 轉換為 Kubernetes **Secret**，讓 Ingress Controller 可以使用它們。

執行以下命令來創建 **Secret（名稱為 `caster-tls`）**：

```bash
kubectl create secret tls caster-tls --key caster_com.key --cert caster_com.crt
```

檢查 Secret 是否成功建立：

```bash
kubectl get secret caster-tls
```

輸出應該類似：

```bash
NAME         TYPE                DATA   AGE
caster-tls   kubernetes.io/tls   2      5s
```

***

### 4. 更新 Ingress 資源，啟用 TLS

接下來，我們需要修改 **Ingress** 配置，新增 **TLS 設定**，並綁定剛剛創建的 Secret。\
記得先把之前的 ingress.yml 停用，建立新的 tls-ingress.yaml

編輯 `tls-ingress.yaml`：

```yaml
# tls-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: caster-ingress
    namespace: default
    labels:
        app.kubernetes.io/name: caster-ingress
    annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
spec:
    ingressClassName: nginx
    tls:
        -   hosts:
                - "app.caster.com"
#                - "mysql.caster.com" # 我目前也不知道這樣是否會生效....
            secretName: caster-tls
    rules:
        -   host: app.caster.com  # 替換為你的域名
            http:
                paths:
                    -   path: /
                        pathType: Prefix
                        backend:
                            service:
                                # 你要提供服務的 k8s Service 名稱以及他的 port
                                name: normal-project-service
                                port:
                                    number: 9000
        -   host: mysql.caster.com  # 替換為你的域名
            http:
                paths:
                    -   path: /
                        pathType: Prefix
                        backend:
                            service:
                                # 你要提供服務的 k8s Service 名稱以及他的 port
                                name: mysql-service
                                port:
                                    number: 3309
```

套用 Ingress 配置：

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

***

### 5. 測試 HTTPS 訪問

#### **步驟 1：應用新的 Ingress**

```bash
kubectl apply -f tls-ingress.yaml
```

#### **步驟 2：修改 `/etc/hosts`**

因為 `app.caster.com` 不是一個真實域名，我們需要手動將其解析到 Ingress Controller 的 IP：\
windows 位置: `C:\Windows\System32\drivers\etc\hosts`

```bash
# 為了方便後續測試，我是有先把會用到的域名都先補上。
172.20.61.17 app.caster.com
172.20.61.17 mysql.caster.com
172.20.61.17 redis.caster.com
172.20.61.17 zookeeper.caster.com
```

#### **步驟 3：使用 `curl` 測試 HTTPS**

```bash
curl -k https://app.caster.com/common/healthy
```

> **`-k` 參數** 允許 `curl` 忽略自簽證書的安全警告。

如果一切正常，應該能夠看到來自 `normal-project` 的回應。

```bash
C:\Users\caster>curl -k https://app.caster.com/common/healthy
{"appVersion":"V1.1.2","podIp":"10.1.0.132","time":"2025-02-04T07:26:53.39806","podId":"0d429a0d-d11d-45ee-9dff-f86b6ff47817"}
```

### ※額外測試 mysql.caste.com 連線至DB (這部分測試僅限再本機環境才會達成)

#### **🚀 問題分析**

1. **你透過 Ingress 設定 `mysql.caster.com`，但 Ingress 只處理 HTTP/HTTPS，並不適用於 MySQL（TCP 服務）**
   * **Ingress Controller（如 ingress-nginx）主要負責 HTTP 流量，不支援 MySQL 這類 TCP 服務的轉發**。
   * 你的 **MySQL 服務跑在 TCP 3309**，所以 Ingress Controller 根本不會處理這個請求。
2. **Service Type 設定影響 MySQL 的可達性**
   * **`NodePort` 模式：**
     * 你應該直接連接 `NodeIP:NodePort`（而不是 `mysql.caster.com:3309`）。
     * `NodePort` 會在每個 Kubernetes 節點上開一個高位元的 Port（例如 `32023`）。
     * **但 Ingress 不會轉發 TCP 連線到 `NodePort`**，所以你的 `mysql.caster.com:3309` 連線失敗。
   * **`LoadBalancer` 模式：**
     * 如果你在 **雲端環境（AWS, GCP, Azure）**，Kubernetes 會為 MySQL 申請一個外部 LoadBalancer IP，讓 `mysql.caster.com:3309` 直接連到 MySQL。
     * **在本機（如 Minikube, Kind），`LoadBalancer` 會自動綁定 `localhost`，讓 `mysql.caster.com:3309` 連線成功**。

#### **🚨 重要結論**

* **Ingress 不能處理 MySQL（TCP）流量，不能靠它轉發 MySQL 服務！**
* **如果用 `NodePort`，請連 `NodeIP:NodePort`，而不是 `mysql.caster.com:3309`**
* **如果用 `LoadBalancer`，可以直接連 `mysql.caster.com:3309`（但本機環境可能不支援真正的 LoadBalancer）**

所以我使用 Intellij database tool 連線成功，完全是亂用這個機制，也是因為我的 hosts 檔案修改才會有這樣的結果，當然本機環境本來就是拿來測試使用的，就...亂用...

<figure><img src="https://1934262382-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRmnDr9RXeSmhkUmaUsX7%2Fuploads%2FepvcYLKBipe1Gu2UGznR%2Fconnected_k8s_mysql_used_domain.png?alt=media&#x26;token=8c75b40a-b353-4caf-8d22-d8ec8cedd6ef" alt=""><figcaption><p>使用域名去連線K8S MySQL 但不確定要怎麼使用SSL 方式去連線...</p></figcaption></figure>

可以確定這樣的做法，完全不能算是使用SSL連線，上網查了一下，還有一大堆設定要搞，痾.... 我沒有那們多的時間玩這個，這部分就先這樣，後續有時間再搞了...

***

### 6. 總結

在本文中，我們介紹了如何在 Kubernetes **Nginx Ingress Controller** 上啟用 **TLS/HTTPS**，主要步驟如下：

1. 使用 `openssl` 生成 **自簽證書**（適用於 Local 測試）。
2. 創建 Kubernetes **Secret**，存儲憑證和私鑰。
3. 更新 `Ingress` 資源，添加 `tls` 設定並綁定 Secret。
4. 測試 HTTPS 訪問。

這種方式適合 **本地開發和測試環境**，如果是 **正式環境**，建議使用 **Let's Encrypt** 或 **CA 簽發的 SSL 憑證** 來實現更安全的 HTTPS 部署。

***

💡 **進階閱讀**

* [Kubernetes 官方文檔 - Ingress TLS](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls)
* [Nginx Ingress Controller 官方 GitHub](https://github.com/kubernetes/ingress-nginx)
