> For the complete documentation index, see [llms.txt](https://xu-min-chang.gitbook.io/caster-develop-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xu-min-chang.gitbook.io/caster-develop-note/kubernetes/chu-ru-jiang-hu-k8s.md).

# 初入江湖(K8S)

## 先決條件

在開始之前，請確保您的系統上已安裝 Docker 和 Docker Compose，並且將Docker Desktop 開啟 Kubernetes。

啟用指南參考官網：[前往](https://docs.docker.com/desktop/kubernetes/)

<div><figure><img src="/files/tMIFASGKcKbgue4lkrL7" alt=""><figcaption><p>啟用kubernetes</p></figcaption></figure> <figure><img src="/files/OYWBmaqbsqgoZrmAJ2hN" alt=""><figcaption><p>確認啟用狀態</p></figcaption></figure></div>

在開始練習之前，我們應該對 Docker 和 Kubernetes 有一定的基本概念，否則會感到困惑。我自己也還有一些細節需要釐清，這就是我們需要深入了解的地方。教學相長，讓我們一同學習！

這次的測試內容為一個最基本的系統架構，包括：

1. MySQL
2. Spring Boot

這是最基礎、最簡單、也是最常見的架構之一。先不包含網管部分的架構，因為我認為這不應該是後端工程師必須具備的技能，不過你若對這方面有需求，網路上有很多資源可以參考。

廢話不多說，上扣！

## 步驟清單

1. 建立 MySQL 服務
2. 確認 MySQL 服務狀況與連線設定
3. 打包專案
4. 撰寫 Dockerfile 建立專案 image
5. Image push 到 Docker Hub（可選）
6. 建立 Spring Boot 服務
7. 進行測試

### 步驟一 至 二：建立 MySQL 服務

以下是一個建立 MySQL 服務的範例，主要包含了建立持久儲存空間、對外曝露的 Service Node 以及建立 MySQL 服務的三個步驟。

檔案名稱：`CreateMySQLV2.yml`

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: mysql-pv-claim
    labels:
        app: mysql
spec:
    accessModes:
        - ReadWriteOnce
    resources:
        requests:
            storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
    labels:
        app.kubernetes.io/name: mysql
    name: mysql
spec:
    replicas: 1
    selector:
        matchLabels:
            app.kubernetes.io/name: mysql
    template:
        metadata:
            labels:
                app.kubernetes.io/name: mysql
        spec:
            containers:
                -   image: mysql:8
                    name: mysql
                    env:
                        # 在實際使用時使用密鑰
                        - name: MYSQL_ROOT_PASSWORD
                          value: 1qaz2wsx
                    ports:
                        -   containerPort: 3306
                            name: mysql
                    volumeMounts:
                        -   name: mysql-persistent-storage
                            mountPath: /var/lib/mysql
            volumes:
                -   name: mysql-persistent-storage
                    persistentVolumeClaim:
                        claimName: mysql-pv-claim
---
apiVersion: v1
kind: Service
metadata:
    labels:
        app.kubernetes.io/name: mysql
    name: mysql-service
spec:
    selector:
        app.kubernetes.io/name: mysql
    ports:
        - protocol: TCP
          port: 3309
          targetPort: 3306
          nodePort: 32700
    type: LoadBalancer
```

部署指令：

```shell
kubectl apply -f CreateMySQLV2.yml
```

在執行專案打包前，我們需要確認 MySQL 的內部 IP，可以使用以下指令：

```shell
kubectl get all --output=wide
```

確認可以連線後，可以手動建立資料或在測試專案的 `\resources\db\migration\init.sql` 中有 SQL 可以執行。

<div><figure><img src="/files/Gne9d2K57urcOiDAvPjF" alt=""><figcaption><p>確認 MySQL 對外 IP 與 Port</p></figcaption></figure> <figure><img src="/files/6WmsKjtfAPm7EvGYLH0R" alt=""><figcaption><p>Test connection</p></figcaption></figure></div>

### **步驟三 至 五**：Build image&#x20;

1. 將 MySQL 曝露的 IP 與 Port 寫入 YAML 檔案
2. Package、Build Image，將 Image Push 到 Docker Hub（非必要）

```sh
# Build image command
docker build -t casterhsu/normal:v2 -f ./normal.Dockerfile .
```

### **步驟六**：Deploy

這是一個簡易的部署 Spring Boot 的範例。在將服務部署在 Kubernetes 上，需要做以下事項：

1. 如果有設定 `imagePullPolicy: Never` 則不需將 Image Push 到 Docker Hub
2. 執行 Kubernetes 部署指令

檔案名稱：`CreateNormalV2.yml`

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
    labels:
        app.kubernetes.io/name: normal-project
    name: normal
spec:
    replicas: 1
    selector:
        matchLabels:
            app.kubernetes.io/name: normal-project
    template:
        metadata:
            labels:
                app.kubernetes.io/name: normal-project
        spec:
            containers:
                - image: casterhsu/normal:v2
                  imagePullPolicy: Never #當前永遠不從 registry 拉取最新的映像。
                  name: normal-container
                  ports:
                      - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
    labels:
        app.kubernetes.io/name: normal-project
    name: normal-project-service
spec:
    selector:
        app.kubernetes.io/name: normal-project
    ports:
        - protocol: TCP
          port: 9000
          targetPort: 8080
          nodePort: 32701
    type: LoadBalancer
```

部署指令：

```shell
kubectl apply -f CreateNormalV2.yml
```

### **步驟七**：Testing

進行測試，並查看結果。

<figure><img src="/files/9haUKs1o7ueZwyleByo6" alt=""><figcaption></figcaption></figure>

### 參考與附件

* GitHub：[前往](https://github.com/MinchangHsu/normal)
* 基礎教學：[前往](https://chengweihu.com/kubernetes-tutorial-1-pod-node/)
* Minikube：[前往](https://minikube.sigs.k8s.io/docs/)
* Kubernetes官網：[前往](https://kubernetes.io/)
* 國人GitBook：[前往](https://kubernetes.feisky.xyz/)  [繁中版本](https://xu-min-chang.gitbook.io/kubernetes/)

## 結語

這次的實戰範例以 Docker 和 Kubernetes 為基礎，展示了建立一個基本系統架構的步驟。透過實際的操作，我們深入了解了如何建立 MySQL 服務和 Spring Boot 服務，以及在 Kubernetes 上的部署過程。

在這個過程中，我們學到了以下重點：

1. **基本概念的重要性**：在開始之前，對 Docker 和 Kubernetes 有一定的基本觀念是至關重要的，否則可能會感到困惑。
2. **系統架構的基礎**：範例中使用了最基本且最常見的系統架構，包括 MySQL 和 Spring Boot。這是一個適合初學者入門的例子。
3. **Kubernetes 實戰**：通過實際操作，我們學到了如何在 Kubernetes 上建立服務，包括 YAML 檔案的編寫、部署指令的執行等。

最後，這個實戰範例為我們提供了實際的練習機會，強調了基本觀念的重要性，同時也激發了我們對於 Docker 和 Kubernetes 更深入學習的動力。在未來的學習過程中，我們可以進一步挑戰更複雜的系統架構，不斷精進自己的技能。教學相長，讓我們共同進步！
