利用 Kubernetes 搭建便攜式開發環境之 MySQL 和 Redis

之前給大家介紹過, 我自己用的開發環境都是容器化的,只不過前兩年不會用 K8,大部分都是用的 Docker 或者 Docker-Compose。隨着這一年多對 K8 的學習和工作中的使用,一直有想法用 K8 做一套便攜式開發環境,以後換電腦就不用再愁數據庫、緩存、隊列這些基礎軟件的安裝了。正好下個月我就能換新的辦公電腦啦,也不能拿『能用就行』的理由再拖延下去了。

如果問你 “平時開發程序依賴最多的基礎軟件時啥?”,我猜大部分人會回答:“MySQL 和 Redis”,畢竟萬物皆是增刪改查,整天做 CURD 的我們怎麼能離開它們呢。

準備工作

工具選擇

既然是要在本地 Kubernetes 上搭建開發環境,那電腦上得先有 Kubernetes 集羣纔行。目前可以在本地運行 Kubernetes 集羣的工具有:Minikube 、Kind 和 K3d ,我們的 MySQL 和 Redis 都是靠先編寫資源定義 YAML 文件,再通過 kubectl 交給 Kubernetes 集羣執行的,所以這三種工具用哪種都行。

我自己在本地使用的是 Minikube,這是 Kubernetes 官方提供的工具,說實話運行起來後電腦有點卡,Minikube 的安裝步驟可以參考我以前寫的文章「Minikube - 運行在筆記本電腦上的 Kubernetes 集羣」。另外兩種 Kind 和 K3d 則是輕量級集羣,支持多節點部署。其中我比較推薦 K3d,尤其是使用 M1 芯片 MacBook 的同學,現在暫時只能使用 K3d 安裝 Kubernetes 集羣。

K3d 是使用 docker 容器在本地運行 k3s 集羣,k3s 是由 Rancher Lab 開源的輕量級 Kubernetes。k3d 完美繼承了 k3s 的簡單、快速和佔用資源少的優勢,鏡像大小隻有 100 多 M,啓動速度快,支持多節點集羣。雖然 k3s 對 Kubernetes 進行了輕量化的裁剪,但是提供了完整了功能,像 Istio 這樣複雜的雲原生應用都可以在 k3s 上順利運行。

K3d 除了啓動速度快和佔用資源少以外,在邊緣計算和嵌入式領域也有着不俗的表現。因爲 k3s 本身應用場景主要在邊緣側,所以支持的設備和架構很多,如:ARM64 和 ARMv7 處理器。很多老舊 PC 和樹莓派這樣的設備都可以拿來做成 k3s 集羣,爲本地研發測試燃盡最後的生命。

預備知識點

說完了安裝工具的選擇,我們再來說一下在 Kubernetes 上從零搭建開發環境需要提前做哪些知識儲備,如果你已經對 Kubernetes 這些基礎概念已經有所瞭解可以直接跳過去看實操環節了,如果還比較生疏的話,我建議大家先看看下面這幾篇文章,這些都是我們搭建開發環境時需要用到的。

Kubernetes Pod 入門指南

應用編排利器之 Deployment

學練結合,快速掌握 Kubernetes Service

用面向對象的方式管理配置文件

深入理解 StatefulSet,用 Kubernetes 編排有狀態應用

安裝 MySQL

在正式開始在 Kubernetes 上安裝 MySQL 和 Redis 前我先說明下安裝這兩個基礎軟件服務的思路。

  1. 首先因爲是用作開發環境,我們就不追求高可用了,儘量精簡。文章後面我會給出安裝主從和集羣式數據庫的一些教程鏈接,供大家參考。

  2. 安裝 MySQL 和 Redis 的思路是一樣的,每個服務都由下面幾個主要的部分構成:

    ① 一個單副本 Pod 作爲運行 MySQL 或者 Redis 的載體。

    ② 一個調度 Pod 用的 Deployment 控制器,因爲服務裏只包含一個 Pod,不需要維持構建的順序,所以不用使用 StatefulSet 作爲 Pod 的控制器。

    ③一個 ConfigMap 對象,包含了 MySQL 或者 Redis 配置文件裏需要的配置項,在創建 Pod 時會作爲配置文件掛載到應用所在的容器中。

    ④一個 Service 對象,將應用 Pod 作爲自己的後端端點,以始終保持不變的 NodeId:NodePort 方式向外暴露服務。

下面這張圖很好的解釋了這四部分的協作關係。

MySQL on Kubernetes

解釋清楚我們在 Kubernetes 上搭建 MySQL 和 Redis 開發環境的思路後,下面就可以進入實操環節啦,我爲大家準備了可以直接拿來使用的 YAML 資源定義文件。

創建 MySQL 配置

我們先來創建一個名爲 mysql-db-config 的 ConfigMap,稍後會把這些配置作爲 my.cnf 配置文件掛載到 MySQL 應用 Pod 的容器裏。

### 文件名 mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-db-config
  namespace: default
  labels:
    app: mysql-db-config
data:
  my.cnf: |
    [client]
    default-character-set=utf8mb4
    [mysql]
    default-character-set=utf8mb4
    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    init_connect='SET NAMES utf8mb4'
    skip-character-set-client-handshake = true
    max_connections=2000
    secure_file_priv=/var/lib/mysql
    datadir=/var/lib/mysql
    bind-address=0.0.0.0
    symbolic-links=0

假定 MySQL 相關的 YAML 定義文件都放在 mysql-singleton 這個目錄下,通過 kubectl 把這個 ConfigMap 提交給 Kubernetes 進行創建即可:

kubectl apply -f mysql-singleton/mysql-configmap.yaml

創建 MySQL 容器和 Service

有了 MySQL 配置相關的 ConfigMap 後,我們就能在創建運行 MySQL 的容器時,把他作爲配置文件掛載到容器中:

### 文件名 deployment-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: NodePort
  ports:
    - port: 3306
      nodePort: 30306
      targetPort: mysql
  selector:
    app: mysql
---
apiVersion:
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - image: mysql:5.7
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: root
            - name: MYSQL_USER
              value: user
            - name: MYSQL_PASSWORD
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
            - name: mysql-config
              mountPath: /etc/mysql/conf.d/my.cnf
              subPath: my.cnf
      volumes:
        - name: mysql-persistent-storage
          emptyDir: {}
        - name: mysql-config
          configMap:
            name: mysql-db-config
            items:
              - key: my.cnf
                path: my.cnf

同樣的,使用 kubectl 把 YAML 提交給 Kubernetes 後,等資源創建完畢我們的開發環境 MySQL 就算搭建好了

kubectl apply -f mysql-singleton/deployment-service.yaml

通過上面的 YAML 文件中,有三點需要詳細說明一下:

  1. 使用 mysql-db-config 這個 ConfigMap 中 my.cnf 這個配置項以 my.cnf 文件名掛載到容器中去,但是因爲掛載進去後會覆蓋容器中 conf.d 目錄中的內容。通過 volumeMounts.subPath 可以支持選定 ConfigMap 中的 Key-Value 掛載到容器中而不覆蓋容器中原有的文件。

  2. Service 用 30306 端口向集羣外暴露了 MySQL 服務,客戶端從電腦上使用 NodeIP:NodePort 即可連接到這裏創建的數據庫,如果用的是 Minikube 創建的 Kubernetes 集羣, 可以通過 minikube ip 命令查到 NodeIP。

  3. emptyDir 類型的數據卷的生命週期與 Pod 同步,這裏的同步指的是 Pod 被 kubectl delete 主動刪除時纔會銷燬對應的數據卷,如果是 Pod 自己崩潰,或者是集羣 Shotdown,等恢復後重建出來的 Pod 仍然會使用之前的數據卷,不會造成數據丟失。

在 Kubernetes 上創建完 MySQL 後,我們可以通過任意客戶端或者 mysql 命令行,連接 MySQL 服務。

mysql -uroot -puser -h {minikube-ip} -P 30306

安裝 Redis

聊清楚了怎麼用 Kubernetes 創建單節點的 MySQL 後,對於創建單例的 Redis 相信大家對大致流程也就比較清楚了,唯一少的就是定義 Redis 服務的這些 YAML 文件了。我已經幫你們踩好坑了,下面這些 YAML 都是我在線下調試過一段時間的,並且也能正確完成 Redis 數據的持久化。

由於聲明 Redis 配置的 ConfigMap 篇幅太長,爲了不影響文章的閱讀我就把這個安裝 Redis 需要的 YAML 文件都放在 GitHub 上了,可以點擊閱讀原文或者通過鏈接:https://github.com/kevinyan815/LearningKubernetes 訪問下載。

在這個倉庫裏我給出了 MySQL 和 Redis 的詳細安裝步驟,以及各種資源的 YAML 定義文件,包括之前安裝 ETCD 集羣的教程也整合到了這個倉庫裏。

安裝步驟詳解,參考 用 Kubernetes 搭建 ETCD 集羣和 WebUI

關於安裝過程中遇到的問題可以在留言裏跟我交流,大家還想看其他基礎軟件在 Kubernetes 上的安裝教程的話也可以告訴我。

總結

這篇文章裏整理了在 Kubernetes 上安裝 MySQL 和 Redis 這兩款我們常用的基礎軟件的操作步驟,由於目的是在本地開發環境用,所以力求資源定義儘量簡單,能做到數據可持久化就行了,高可用不再這裏討論。如果你對在 Kubernetes 上創建 MySQL 集羣有興趣,可以參考我下面給出的鏈接。

MySQL Operator FOR Kubernetnes[1]

資料引用

[1]

MySQL Operator FOR Kubernetnes: :https://medium.com/oracledevs/getting-started-with-the-mysql-operator-for-kubernetes-8df48591f592

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/pkpPc2Fho_rQ-IRBm78NFA