02-k8s部署環境

peng_boke發表於2024-10-14

前言

心有山水不造作,靜而不爭遠是非

7.叢集

7.1叢集常見的基本形式

叢集的目標

  • 高可用:主機當機對業務無影響。

    • 當機原因:網路卡、路由器、機房、CPU負載過高、記憶體溢位、自然災害等不可預期的原因導致,也稱單點問題
    • 解決方案:【選主式(雙主、raft選舉)】重新建立主節點
  • 單點效能限制:當單點資料量過大導致效能降低,所以需要多臺分擔共同儲存整個叢集資料,並且做好互相備份保證即使單點故障,也能在其他節點找到資料

    • 解決方案:【分片式(分庫分表)】
  • 資料備份容災:單點故障後,儲存的資料仍然可以在別的地方拉起

    • 解決方案:【主從複製】
  • 壓力分擔:避免單點壓力過高,例如單節點幾千億條資料讀取很慢,分離操作,各單點完成自己的工作完成整個工作

    • 解決方案:【讀寫分離】
  • 主從複製、讀寫分離可以一起實現

叢集的基礎形式

  • 主從式:
    • 主從複製:從節點複製主節點資料,保持一致(mysql)
    • 主從排程:所有請求由主節點排程,挑一個從節點響應請求(k8s)
  • 分片式:(可以看作有多套主從構成分片)
    • 資料分片儲存,突破單點限制
    • 分片之間互相備份,保證資料不丟失
    • 客戶端分片:由客戶端計算實際請求的分片地址(mycat)
    • 服務端分片:由服務端計算實際請求的分片地址(redis)
    • 例:訂單表,按地區分片,按時間分表
  • 選主式:
    • 為了容災選主
    • 為了排程選主

image-20240911015641724

7.2MySQL-常見叢集形式

叢集原理

image-20240912162711133

MySQL-MMM 是 Master-Master Replication Manager for MySQL(mysql 主主複製管理 器)的簡稱,是 Google 的開源專案 (Perl 指令碼)。MMM 基於 MySQL Replication 做的擴充套件架構,主要用 來監控 mysql 主主複製並做失敗轉 移。其原理是將真實資料庫節點的 IP(RIP)對映為虛擬 IP(VIP)集。 mysql-mmm 的監管端會提供多個 虛擬 IP(VIP),包括一個可寫 VIP, 多個可讀 VIP,透過監管的管理,這 些 IP 會繫結在可用 mysql 之上,當 某一臺 mysql 當機時,監管會將 VIP 遷移至其他 mysql。在整個監管過 程中,需要在 mysql 中新增相關授 權使用者,以便讓 mysql 可以支援監 理機的維護。授權的使用者包括一個mmm_monitor 使用者和一個 mmm_agent 使用者,如果想使用 mmm 的備份工具則還要添 加一個 mmm_tools 使用者。

image-20240912162817250

MHA(Master High Availability)目前在 MySQL 高可用方面是一個相對成熟的解決方案, 由日本 DeNA 公司 youshimaton(現就職於 Facebook 公司)開發,是一套優秀的作為 MySQL高可用性環境下故障切換和主從提升的高可用軟體。在MySQL故障切換過程中, MHA 能做到在 0~30 秒之內自動完成資料庫的故障切換操作(以 2019 年的眼光來說太 慢了),並且在進行故障切換的過程中,MHA 能在最大程度上保證資料的一致性,以 達到真正意義上的高可用。

InnoDB Cluster 支援自動 Failover、強一致性、讀寫分離、讀庫高可用、讀請求負載均 衡,橫向擴充套件的特性,是比較完備的一套方案。但是部署起來複雜,想要解決 router 單點問題好需要新增元件,如沒有其他更好的方案可考慮該方案。 InnoDB Cluster 主 要由 MySQL Shell、MySQL Router 和 MySQL 伺服器叢集組成,三者協同工作,共同為 MySQL 提供完整的高可用性解決方案。MySQL Shell 對管理人員提供管理介面,可以 很方便的對叢集進行配置和管理,MySQL Router 可以根據部署的叢集狀況自動的初始 化,是客戶端連線例項。如果有節點 down 機,叢集會自動更新配置。叢集包含單點寫 入和多點寫入兩種模式。在單主模式下,如果主節點 down 掉,從節點自動替換上來, MySQL Router 會自動探測,並將客戶端連線到新節點。

image-20240912162923920

7.3MySQL-主從同步

主機 ip
mysql-master 192.168.188.180:3317
mysql-slaver-01 192.168.188.180:3327

Master

執行一個mysql例項

引數說明

  • -p 3307:3306:將容器的 3306 埠對映到主機的 3307 埠 -v
  • /mydata/mysql/master/conf:/etc/mysql:將配置資料夾掛在到主機 -v
  • /mydata/mysql/master/log:/var/log/mysql:將日誌資料夾掛載到主機 -v
  • /mydata/mysql/master/data:/var/lib/mysql:將配置資料夾掛載到主機 -e
  • MYSQL_ROOT_PASSWORD=root:初始化 root 使用者的密碼
# 刪除目錄 如果需要清除環境
 docker stop mysql-master
 docker rm -f mysql-master
 rm -rf /mydata/mysql/master/data
 rm -rf /mydata/mysql/master/log
 rm -rf /mydata/mysql/master/conf

# 建立目錄
mkdir -p /mydata/mysql/master/{data,log}
mkdir -p /mydata/mysql/master/conf/{conf.d,mysql.conf.d}

# 執行
docker run -p 3317:3306 --name mysql-master \
  -v /mydata/mysql/master/log:/var/log/mysql \
  -v /mydata/mysql/master/data:/var/lib/mysql \
  -v /mydata/mysql/master/conf:/etc/mysql \
  -e MYSQL_ROOT_PASSWORD=root \
  -d mysql:5.7

修改 master 基本配置

# rm -f /mydata/mysql/master/conf/my.cnf
vim /mydata/mysql/master/conf/my.cnf

my.cnf

注意:skip-name-resolve 一定要加,不然連線 mysql 會超級

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

# 新增 master 主從複製部分配置
server_id=1
log-bin=mysql-bin

# 讀寫
read-only=0

# 只同步業務庫
binlog-do-db=mall_ums
binlog-do-db=mall_pms
binlog-do-db=mall_oms
binlog-do-db=mall_sms
binlog-do-db=mall_wms
binlog-do-db=mall_admin

# 不同步mysql基礎庫
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

重啟master

docker restart mysql-master
docker logs mysql-master

image-20240913005104794

Slave

執行一個mysql例項

# 刪除目錄 如果需要清除環境
 docker stop mysql-slaver-01
 docker rm -f mysql-slaver-01
 rm -rf /mydata/mysql/slaver/data
 rm -rf /mydata/mysql/slaver/log
 rm -rf /mydata/mysql/slaver/conf

# 建立目錄
mkdir -p /mydata/mysql/slaver/{data,log}
mkdir -p /mydata/mysql/slaver/conf/{conf.d,mysql.conf.d}

docker run -p 3327:3306 --name mysql-slaver-01 \
  -v /mydata/mysql/slaver/log:/var/log/mysql \
  -v /mydata/mysql/slaver/data:/var/lib/mysql \
  -v /mydata/mysql/slaver/conf:/etc/mysql \
  -e MYSQL_ROOT_PASSWORD=root \
  -d mysql:5.7

修改 slave 基本配置

vim /mydata/mysql/slaver/conf/my.cnf

my.cnf

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

# 新增 master 主從複製部分配置
server-id=2
log-bin=mysql-bin

# 只讀
read-only=1

# 只同步業務庫
binlog-do-db=mall_ums
binlog-do-db=mall_pms
binlog-do-db=mall_oms
binlog-do-db=mall_sms
binlog-do-db=mall_wms
binlog-do-db=mall_admin

# 不同步mysql基礎庫
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

重啟mysql-slaver-01

docker restart mysql-slaver-01

image-20240913010921666

檢視容器

docker ps

image-20240913005430355

為 master 授權使用者來他的同步資料

進入 master 容器

docker exec -it mysql-master mysql -u root -p

進入 mysql 內部

# 授權 root 可以遠端訪問( 主從無關,為了方便我們遠端連線 mysql)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;

# 新增用來同步的使用者
GRANT REPLICATION SLAVE ON *.* to 'backup'@'%' identified by '123456';

# 檢視 master狀態
show master status;

image-20240913005654146

配置 slaver 同步 master 資料

進入 slaver 容器

docker exec -it mysql-slaver-01 mysql -u root -p

進入 mysql 內部

# 授權 root 可以遠端訪問( 主從無關,為了方便我們遠端連線 mysql)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;

# 設定主庫連線
# MASTER_LOG_FILE是show master status;查master的File欄位
CHANGE MASTER TO MASTER_HOST='192.168.188.180',
                   MASTER_USER='backup',
                   MASTER_PASSWORD='123456',
                   MASTER_LOG_FILE='mysql-bin.000001',
                   MASTER_LOG_POS=0,
                   MASTER_PORT=3317;

# 啟動從庫同步
start slave;

# 檢視從庫狀態
show slave status;

image-20240913010748804

檢視從庫狀態

show slave status\G;

image-20240913011018615

測試

登入mysql-master,建立測試mall_admin

這裡建立的表名字只能是my.cnf配置的binlog-do-db

docker exec -it mysql-master mysql -u root -p

DROP DATABASE IF EXISTS mall_admin;

CREATE DATABASE mall_admin;

USE mall_admin;

CREATE TABLE IF NOT EXISTS test_table (
    id INT AUTO_INCREMENT PRIMARY KEY,     -- 自增主鍵列
    name VARCHAR(100)                      -- 名稱列,不能為空
);

INSERT INTO test_table (name) VALUES ('Alice');

登入mysql-slaver-01,發現庫和表成功同步

docker exec -it mysql-slaver-01 mysql -u root -p

show databases;

USE mall_admin;

SELECT * FROM test_table;

image-20240913012406067

主庫再刪除,從庫已同步

DROP DATABASE mall_admin;

image-20240913012710462

7.4ShardingSphere-簡介

官網地址:https://shardingsphere.apache.org/document/current/cn/quick-start/shardingsphere-jdbc-quick-start/

image-20240913020153057

7.5ShardingSphere-分庫分表&讀寫分離配置

下載地址:https://www.apache.org/dyn/closer.lua/shardingsphere/5.5.0/apache-shardingsphere-5.5.0-shardingsphere-proxy-bin.tar.gz

image-20240913020541233

解壓

image-20240913020831048

下載mysql驅動包

下載地址:https://shardingsphere.apache.org/document/current/cn/quick-start/shardingsphere-proxy-quick-start/#操作步驟

image-20240913020939003

mysql-connector-java-5.1.49.jar放到apache-shardingsphere\lib目錄下

image-20240913021110174

配置認證授權

https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-proxy/yaml-config/authority/#引數解釋

image-20240913021253708

配置apache-shardingsphere\confglobal.yaml

authority:
  users:
    - user: root@%
      password: root
    - user: sharding
      password: sharding
  privilege:
    type: ALL_PERMITTED

image-20240913021456215

配置database-sharding.yaml

image-20240913221038284

配置database-readwrite-splitting.yaml

image-20240913221141199

新增database-readwrite-splitting-1.yaml

image-20240913221745972

master節點 建立demo_ds_0demo_ds_1

CREATE DATABASE `demo_ds_0` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */;
CREATE DATABASE `demo_ds_1` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */;

修改masterslavermy.cnf

vim /mydata/mysql/master/conf/my.cnf
vim /mydata/mysql/slaver/conf/my.cnf

demo_ds_0demo_ds_1新增到主從同步

binlog-do-db=demo_ds_0
binlog-do-db=demo_ds_1

image-20240913221449274

啟動ShardingSphere

start.bat 3388

image-20240913221820975

在3388連結下建立表

CREATE TABLE `t_order` (
    `order_id` bigint(20) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    `status` varchar(50) COLLATE utf8_bin DEFAULT NULL, 
    PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


CREATE TABLE `t_order_item` (
  `order_item_id` bigint(20) NOT NULL,
  `order_id` bigint(20) NOT NULL,
  `user_id` int(11) NOT NULL,
  `content` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `status` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`order_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

新增測試資料

insert into t_order(user_id,status) values(1,2);
insert into t_order(user_id,status) values(2,2);
insert into t_order(user_id,status) values(3,2);

7.6Redis-Cluster基本原理

7.6.1Redis叢集形式

1.資料分割槽方案
1.1客戶端分割槽

image-20240913224728366

客戶端分割槽方案 的代表為 Redis Sharding,Redis Sharding 是 Redis Cluster 出來之前,業 界普遍使用的 Redis 多例項叢集 方法。Java 的 Redis 客戶端驅動庫 Jedis,支援 Redis Sharding 功能,即 ShardedJedis 以及 結合快取池 的 ShardedJedisPool。

優點 :

  • 不使用 第三方中介軟體,分割槽邏輯 可控,配置 簡單,節點之間無關聯,容易 線性擴充套件,靈 活性強。

缺點 :

  • 客戶端 無法 動態增刪 服務節點,客戶端需要自行維護 分發邏輯,客戶端之間 無連線共享, 會造成 連線浪費。
1.2代理分割槽

image-20240913224848495

1.3redsi-cluster
2.高可用方式
2.1Sentinel( 哨兵機制)支援高可用

前面介紹了主從機制,但是從運維角度來看,主節點出現了問題我們還需要透過人工干預的 方式把從節點設為主節點,還要通知應用程式更新主節點地址,這種方式非常繁瑣笨重, 而 且主節點的讀寫能力都十分有限,有沒有較好的辦法解決這兩個問題,哨兵機制就是針對第 一個問題的有效解決方案,第二個問題則有賴於叢集!哨兵的作用就是監控 Redis 系統的運 行狀況,其功能主要是包括以下三個

  • 監控(Monitoring): 哨兵(sentinel) 會不斷地檢查你的 Master 和 Slave 是否運作正常。
  • 提醒(Notification): 當被監控的某個 Redis 出現問題時, 哨兵(sentinel) 可以透過 API 向管理員或者其他應用程式傳送通知。
  • 自動故障遷移(Automatic failover): 當主資料庫出現故障時自動將從資料庫轉換為主數 據庫。

image-20240913225532631

哨兵的原理 Redis 哨兵的三個定時任務,Redis 哨兵判定一個 Redis 節點故障不可達主要就是透過三個定 時監控任務來完成的:

  • 每隔 10 秒每個哨兵節點會向主節點和從節點傳送"info replication" 命令來獲取最新的 拓撲結構
image-20240913225721488
  • 每隔 2 秒每個哨兵節點會向 Redis 節點的_sentinel_:hello 頻道傳送自己對主節點是否故 障的判斷以及自身的節點資訊,並且其他的哨兵節點也會訂閱這個頻道來了解其他哨兵 節點的資訊以及對主節點的判斷
image-20240913225804286
  • 每隔 1 秒每個哨兵會向主節點、從節點、其他的哨兵節點傳送一個 “ping” 命令來做心 跳檢測
image-20240913225828259

如果在定時 Job3 檢測不到節點的心跳,會判斷為“主觀下線”。如果該節點還是主節點那麼 還會通知到其他的哨兵對該主節點進行心跳檢測,這時主觀下線的票數超過了數 時,那麼這個主節點確實就可能是故障不可達了,這時就由原來的主觀下線變為了“客觀下 線”。

故障轉移和 Leader 選舉 如果主節點被判定為客觀下線之後,就要選取一個哨兵節點來完成後面的故障轉移工作,選 舉出一個 leader,這裡面採用的選舉演算法為 Raft。選舉出來的哨兵 leader 就要來完成故障轉 移工作,也就是在從節點中選出一個節點來當新的主節點,這部分的具體流程可參考引用.

2.2Redis-Cluster

https://redis.io/topics/cluster-tutorial/

7.6.2Redis-Cluster

https://redis.io/topics/cluster-tutorial/

Redis 的官方多機部署方案,Redis Cluster。一組 Redis Cluster 是由多個 Redis 例項組成,官 方推薦我們使用 6 例項,其中 3 個為主節點,3 個為從結點。一旦有主節點發生故障的時候, Redis Cluster 可以選舉出對應的從結點成為新的主節點,繼續對外服務,從而保證服務的高 可用性。那麼對於客戶端來說,知道知道對應的 key 是要路由到哪一個節點呢?Redis Cluster 把所有的資料劃分為 16384 個不同的槽位,可以根據機器的效能把不同的槽位分配給不同 的 Redis 例項,對於 Redis 例項來說,他們只會儲存部分的 Redis 資料,當然,槽的資料是 可以遷移的,不同的例項之間,可以透過一定的協議,進行資料遷移。

1.槽

image-20240913230107409

Redis 叢集的功能限制;Redis 叢集相對 單機 在功能上存在一些限制,需要 開發人員 提前 瞭解,在使用時做好規避。JAVA CRC16 校驗演算法

  • key 批次操作 支援有限。
    • 類似 mset、mget 操作,目前只支援對具有相同 slot 值的 key 執行 批次操作。 對於 對映為不同 slot 值的 key 由於執行 mget、mget 等操作可能存在於多個節 點上,因此不被支援。
  • key 事務操作 支援有限。
    • 只支援 多 key 在 同一節點上 的 事務操作,當多個 key 分佈在 不同 的節點上 時 無法 使用事務功能。
  • key 作為 資料分割槽 的最小粒度
  • 不能將一個 大的鍵值 物件如 hash、list 等對映到 不同的節點。
  • 不支援 多資料庫空間
    • 單機 下的 Redis 可以支援 16 個資料庫(db0 ~ db15),叢集模式 下只能使用 一 個 資料庫空間,即 db0。
  • 複製結構 只支援一層
    • 從節點 只能複製 主節點,不支援 巢狀樹狀複製 結構。
  • 命令大多會重定向,耗時多

image-20240913230330498

2.一致性 hash

一致性雜湊 可以很好的解決 穩定性問題,可以將所有的 儲存節點 排列在 收尾相接 的 Hash 環上,每個 key 在計算 Hash 後會 順時針 找到 臨接 的 儲存節點 存放。而當有節 點 加入 或 退出 時,僅影響該節點在 Hash 環上 順時針相鄰 的 後續節點。

image-20240913230639846

Hash 傾斜

如果節點很少,容易出現傾斜,負載不均衡問題。一致性雜湊演算法,引入了虛擬節點,在整 個環上,均衡增加若干個節點。比如 a1,a2,b1,b2,c1,c2,a1 和 a2 都是屬於 A 節點 的。解決 hash 傾斜問題。

7.7Redis-Cluster叢集搭建

安裝redis

下載redis:5.0.7映象

docker pull redis:5.0.7

image-20240913231739269

執行6個redis

for port in $(seq 7001 7006); \
do \
  mkdir -p /mydata/redis/node-${port}/conf
  touch /mydata/redis/node-${port}/conf/redis.conf
  cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.188.180
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
appendonly yes
EOF
  docker run -p ${port}:${port} -p 1${port}:1${port} --name redis-${port} \
  -v /mydata/redis/node-${port}/data:/data \
  -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
  -d redis:5.0.7 redis-server /etc/redis/redis.conf
done

image-20240913232006383

使用 redis 建立叢集

# 進入 Redis 容器
docker exec -it redis-7001 bash

# 執行 redis-cli 建立 Redis 叢集的命令
redis-cli --cluster create 192.168.188.180:7001 192.168.188.180:7002 192.168.188.180:7003 192.168.188.180:7004 192.168.188.180:7005 192.168.188.180:7006 --cluster-replicas 1
# 主
7001 76abe09d843b39c73891b8c5ce17ffa42b0fcbed
# 從
7006 2fe7a57c12444ed5eaba3d68f311464c350e59fa

# 主
7002 eef7fc312c11d3001485b0052e97a8362a8cd32e
# 從
7004 3d1b3b7f50eed63a0464fcf6cca7307744bd34ca

# 主
7003 a7d95522dafbc173d16149783867442b5fbc6ccf
# 從
7005 aaeb00b6025fe0b36e5d30d46778c06a14e87c21 

image-20240913232408745

測試

隨便進入某個redis容器

docker exec -it redis-7002 /bin/bash

使用 redis-cli 的 cluster 方式進行連線

redis-cli -c -h 192.168.188.180 -p 7006

獲取叢集資訊

cluster info

獲取叢集節點

cluster nodes

image-20240913233338733

7.8ElasticSearch-叢集原理

叢集原理

https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/distributed-cluster.html

elasticsearch 是天生支援叢集的,他不需要依賴其他的服務發現和註冊的元件,如 zookeeper 這些,因為他內建了一個名字叫 ZenDiscovery 的模組,是 elasticsearch 自己實現的一套用 於節點發現和選主等功能的元件,所以 elasticsearch 做起叢集來非常簡單,不需要太多額外 的配置和安裝額外的第三方元件。

1.單節點

image-20240914002155640

  • 一個執行中的 Elasticsearch 例項稱為一個節點,而叢集是由一個或者多個擁有相同 cluster.name 配置的節點組成, 它們共同承擔資料和負載的壓力。當有節點加入叢集 中或者從叢集中移除節點時,叢集將會重新平均分佈所有的資料。
  • 當一個節點被選舉成為 主節點時, 它將負責管理叢集範圍內的所有變更,例如增加、 刪除索引,或者增加、刪除節點等。 而主節點並不需要涉及到文件級別的變更和搜尋 等操作,所以當叢集只擁有一個主節點的情況下,即使流量的增加它也不會成為瓶頸。 任何節點都可以成為主節點。我們的示例叢集就只有一個節點,所以它同時也成為了主 節點。
  • 作為使用者,我們可以將請求傳送到 叢集中的任何節點 ,包括主節點。 每個節點都知 道任意文件所處的位置,並且能夠將我們的請求直接轉發到儲存我們所需文件的節點。 無論我們將請求傳送到哪個節點,它都能負責從各個包含我們所需文件的節點收集回數 據,並將最終結果返回給客戶端。 Elasticsearch 對這一切的管理都是透明的。

2.叢集健康

Elasticsearch 的叢集監控資訊中包含了許多的統計資料,其中最為重要的一項就是 叢集健 康 , 它在 status 欄位中展示為 green 、 yellow 或者 red 。

GET /_cluster/health

status 欄位指示著當前叢集在總體上是否工作正常。它的三種顏色含義如下:

  • green:所有的主分片和副本分片都正常執行。
  • yellow:所有的主分片都正常執行,但不是所有的副本分片都正常執行。
  • red:有主分片沒能正常執行。

3.分片

  • 一個 分片 是一個底層的 工作單元 ,它僅儲存了全部資料中的一部分。我們的文件被 儲存和索引到分片內,但是應用程式是直接與索引而不是與分片進行互動。分片就認為 是一個資料區
  • 一個分片可以是 主 分片或者 副本 分片。索引內任意一個文件都歸屬於一個主分片, 所以主分片的數目決定著索引能夠儲存的最大資料量。
  • 在索引建立的時候就已經確定了主分片數,但是副本分片數可以隨時修改。
  • 讓我們在包含一個空節點的叢集內建立名為 blogs 的索引。 索引在預設情況下會被分 配 5 個主分片, 但是為了演示目的,我們將分配 3 個主分片和一份副本(每個主分片 擁有一個副本分片):
PUT /blogs{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}}

image-20240914002450691

此時叢集的健康狀況為 yellow 則表示全部 主分片都正常執行(叢集可以正常服務所有請 求),但是 副本 分片沒有全部處在正常狀態。 實際上,所有 3 個副本分片都是 unassigned —— 它們都沒有被分配到任何節點。在同一個節點上既儲存原始資料又儲存副本是沒有意 義的,因為一旦失去了那個節點,我們也將丟失該節點上的所有副本資料。 當前我們的叢集是正常執行的,但是在硬體故障時有丟失資料的風險。

4.新增節點

當你在同一臺機器上啟動了第二個節點時,只要它和第一個節點有同樣的 cluster.name 配 置,它就會自動發現叢集並加入到其中。 但是在不同機器上啟動節點的時候,為了加入到 同一叢集,你需要配置一個可連線到的單播主機列表。 詳細資訊請檢視最好使用單播代替 組播

image-20240914002749562

此時,cluster-health 現在展示的狀態為 green ,這表示所有 6 個分片(包括 3 個主分片和 3 個副本分片)都在正常執行。我們的叢集現在不僅僅是正常執行的,並且還處於 始終可 用 的狀態。

5.水平擴容-啟動第三個節點

image-20240914002841028

Node 1 和 Node 2 上各有一個分片被遷移到了新的 Node 3 節點,現在每個節點上都擁 有 2 個分片,而不是之前的 3 個。 這表示每個節點的硬體資源(CPU, RAM, I/O)將被更少 的分片所共享,每個分片的效能將會得到提升。

在執行中的叢集上是可以動態調整副本分片數目的,我們可以按需伸縮叢集。讓我們把副本 數從預設的 1 增加到 2

PUT /blogs/_settings
{ 
    "number_of_replicas" : 2
}

blogs 索引現在擁有 9 個分片:3 個主分片和 6 個副本分片。 這意味著我們可以將叢集擴 容到 9 個節點,每個節點上一個分片。相比原來 3 個節點時,叢集搜尋效能可以提升3 倍。

image-20240914003008941

6.應對故障

image-20240914003108465

  • 我們關閉的節點是一個主節點。而叢集必須擁有一個主節點來保證正常工作,所以發生 的第一件事情就是選舉一個新的主節點: Node 2 。
  • 在我們關閉 Node 1 的同時也失去了主分片 1 和 2 ,並且在缺失主分片的時候索引 也不能正常工作。 如果此時來檢查叢集的狀況,我們看到的狀態將會為 red :不是所 有主分片都在正常工作。
  • 幸運的是,在其它節點上存在著這兩個主分片的完整副本, 所以新的主節點立即將這 些分片在 Node 2 和 Node 3 上對應的副本分片提升為主分片, 此時叢集的狀態將會 為 yellow 。 這個提升主分片的過程是瞬間發生的,如同按下一個開關一般。
  • 為什麼我們叢集狀態是 yellow 而不是 green 呢? 雖然我們擁有所有的三個主分片, 但是同時設定了每個主分片需要對應 2 份副本分片,而此時只存在一份副本分片。 所 以叢集不能為 green 的狀態,不過我們不必過於擔心:如果我們同樣關閉了 Node 2 , 我們的程式 依然 可以保持在不丟任何資料的情況下執行,因為 Node 3 為每一個分 片都保留著一份副本。
  • 如果我們重新啟動 Node 1 ,叢集可以將缺失的副本分片再次進行分配。如果 Node 1依然擁有著之前的分片,它將嘗試去重用它們,同時僅從主分片複製發生了修改的資料 檔案。

7.問題與解決

1、主節點

主節點負責建立索引、刪除索引、分配分片、追蹤叢集中的節點狀態等工作。Elasticsearch 中的主節點的工作量相對較輕,使用者的請求可以發往叢集中任何一個節點,由該節點負責分 發和返回結果,而不需要經過主節點轉發。而主節點是由候選主節點透過 ZenDiscovery 機 制選舉出來的,所以要想成為主節點,首先要先成為候選主節點。

2、候選主節點

在 elasticsearch 叢集初始化或者主節點當機的情況下,由候選主節點中選舉其中一個作為主 節點。指定候選主節點的配置為:node.master: true。 當主節點負載壓力過大,或者集中環境中的網路問題,導致其他節點與主節點通訊的時候, 主節點沒來的及響應,這樣的話,某些節點就認為主節點當機,重新選擇新的主節點,這樣 的話整個叢集的工作就有問題了,比如我們叢集中有 10 個節點,其中 7 個候選主節點,1 個候選主節點成為了主節點,這種情況是正常的情況。但是如果現在出現了我們上面所說的 主節點響應不及時,導致其他某些節點認為主節點當機而重選主節點,那就有問題了,這剩 下的 6 個候選主節點可能有 3 個候選主節點去重選主節點,最後叢集中就出現了兩個主節點 的情況,這種情況官方成為“腦裂現象”; 叢集中不同的節點對於 master 的選擇出現了分歧,出現了多個 master 競爭,導致主分片 和副本的識別也發生了分歧,對一些分歧中的分片標識為了壞片。

3、資料節點

資料節點負責資料的儲存和相關具體操作,比如 CRUD、搜尋、聚合。所以,資料節點對機 器配置要求比較高,首先需要有足夠的磁碟空間來儲存資料,其次資料操作對系統 CPU、 Memory 和 IO 的效能消耗都很大。通常隨著叢集的擴大,需要增加更多的資料節點來提高 可用性。指定資料節點的配置:node.data: true。 elasticsearch 是允許一個節點既做候選主節點也做資料節點的,但是資料節點的負載較重, 所以需要考慮將二者分離開,設定專用的候選主節點和資料節點,避免因資料節點負載重導 致主節點不響應。

4、客戶端節點

客戶端節點就是既不做候選主節點也不做資料節點的節點,只負責請求的分發、彙總等等, 但是這樣的工作,其實任何一個節點都可以完成,因為在 elasticsearch 中一個叢集內的節點 都可以執行任何請求,其會負責將請求轉發給對應的節點進行處理。所以單獨增加這樣的節 點更多是為了負載均衡。指定該節點的配置為: node.master: false node.data: false

5、腦裂”問題可能的成因

1.網路問題:叢集間的網路延遲導致一些節點訪問不到 master,認為 master 掛掉了從而選 舉出新的 master,並對 master 上的分片和副本標紅,分配新的主分片

2.節點負載:主節點的角色既為 master 又為 data,訪問量較大時可能會導致 ES 停止響應造 成大面積延遲,此時其他節點得不到主節點的響應認為主節點掛掉了,會重新選取主節點。

3.記憶體回收:data 節點上的 ES 程序佔用的記憶體較大,引發 JVM 的大規模記憶體回收,造成 ES 程序失去響應。

  • 腦裂問題解決方案:
    • 角色分離:即 master 節點與 data 節點分離,限制角色;資料節點是需要承擔儲存 和搜尋的工作的,壓力會很大。所以如果該節點同時作為候選主節點和資料節點, 那麼一旦選上它作為主節點了,這時主節點的工作壓力將會非常大,出現腦裂現象 的機率就增加了。
    • 減少誤判:配置主節點的響應時間,在預設情況下,主節點 3 秒沒有響應,其他節 點就認為主節點當機了,那我們可以把該時間設定的長一點,該配置是: discovery.zen.ping_timeout: 5
    • 選舉觸發:discovery.zen.minimum_master_nodes:1(預設是 1),該屬性定義的是 為了形成一個叢集,有主節點資格並互相連線的節點的最小數目。
      • 一 個 有 10 節 點 的 集 群 , 且 每 個 節 點 都 有 成 為 主 節 點 的 資 格 , discovery.zen.minimum_master_nodes 引數設定為 6。
      • 正常情況下,10 個節點,互相連線,大於 6,就可以形成一個叢集。
      • 若某個時刻,其中有 3 個節點斷開連線。剩下 7 個節點,大於 6,繼續執行之 前的叢集。而斷開的 3 個節點,小於 6,不能形成一個叢集。
      • 該引數就是為了防止”腦裂”的產生。
      • 建議設定為(候選主節點數 / 2) + 1,

8.叢集結構

以三臺物理機為例。在這三臺物理機上,搭建了 6 個 ES 的節點,三個 data 節點,三個 master 節點(每臺物理機分別起了一個 data 和一個 master),3 個 master 節點,目的是達到(n/2) +1 等於 2 的要求,這樣掛掉一臺 master 後(不考慮 data),n 等於 2,滿足引數,其他兩 個 master 節點都認為 master 掛掉之後開始重新選舉,

master 節點上

node.master = true 
node.data = false 
discovery.zen.minimum_master_nodes = 2 

data 節點上

node.master = false 
node.data = true

7.9ElasticSearch-叢集搭建

設定max_map_count

vm.max_map_count 是一個核心引數,表示一個程序可以擁有的最大記憶體對映區域數量。將其設定為 262144 增加了該限制,這在需要大量記憶體對映的應用程式(如某些資料庫或大型應用程式)中可能會有所幫助。

所有之前先執行

sysctl -w vm.max_map_count=262144

image-20240914012917847

我們只是測試,所以臨時修改。永久修改使用下面

#防止 JVM 報錯
echo vm.max_map_count=262144 >> /etc/sysctl.conf
sysctl -p

準備 docker 網路

建立一個新的 bridge 網路

docker network create --driver bridge --subnet=172.19.0.0/16 --gateway=172.19.0.1 mynet

檢視網路資訊,以後使用--network=mynet --ip 172.18.12.x 指定 ip

docker network inspect mynet

image-20240914013138228

建立Master節點

for port in $(seq 1 3); do
  mkdir -p /mydata/elasticsearch/master-${port}/config
  mkdir -p /mydata/elasticsearch/master-${port}/data
  chmod -R 777 /mydata/elasticsearch/master-${port}

  cat << EOF >/mydata/elasticsearch/master-${port}/config/elasticsearch.yml
cluster.name: my-es # 叢集的名稱,同一個叢集該值必須設定成相同的
node.name: es-master-${port} # 該節點的名字
node.master: true # 該節點有機會成為 master 節點
node.data: false # 該節點可以儲存資料
network.host: 0.0.0.0
http.host: 0.0.0.0 # 所有 http 均可訪問
http.port: 920${port}
transport.tcp.port: 930${port}
# discovery.zen.minimum_master_nodes: 2 # 設定這個引數來保證叢集中的節點可以知道其他 N 個有 master 資格的節點。官方推薦(N/2)+1
discovery.zen.ping_timeout: 10s # 設定叢集中自動發現其他節點時 ping 連線的超時時間
discovery.seed_hosts: ["172.19.12.21:9301", "172.19.12.22:9302", "172.19.12.23:9303"] # 設定叢集中的 Master 節點的初始列表,可以透過這些節點來自動發現其他新加入叢集的節點,es7 的新增配置
cluster.initial_master_nodes: ["172.19.12.21"] # 新叢集初始時的候選主節點,es7 的新增配置
EOF

  docker run --name elasticsearch-node-${port} \
    -p 920${port}:920${port} -p 930${port}:930${port} \
    --network=mynet --ip 172.19.12.2${port} \
    -e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
    -v /mydata/elasticsearch/master-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
    -v /mydata/elasticsearch/master-${port}/data:/usr/share/elasticsearch/data \
    -v /mydata/elasticsearch/master-${port}/plugins:/usr/share/elasticsearch/plugins \
    -d elasticsearch:7.4.2
done

image-20240914013240294

建立Data-Node節點

for port in $(seq 4 6); do
  mkdir -p /mydata/elasticsearch/node-${port}/config
  mkdir -p /mydata/elasticsearch/node-${port}/data
  chmod -R 777 /mydata/elasticsearch/node-${port}

  cat << EOF >/mydata/elasticsearch/node-${port}/config/elasticsearch.yml
cluster.name: my-es # 叢集的名稱,同一個叢集該值必須設定成相同的
node.name: es-node-${port} # 該節點的名字
node.master: false # 該節點有機會成為 master 節點
node.data: true # 該節點可以儲存資料
network.host: 0.0.0.0
# network.publish_host: 192.168.56.10 # 互相通訊 ip,要設定為本機可被外界訪問的 ip,否則無法通訊
http.host: 0.0.0.0 # 所有 http 均可訪問
http.port: 920${port}
transport.tcp.port: 930${port}
# discovery.zen.minimum_master_nodes: 2 # 設定這個引數來保證叢集中的節點可以知道其他 N 個有 master 資格的節點。官方推薦(N/2)+1
discovery.zen.ping_timeout: 10s # 設定叢集中自動發現其他節點時 ping 連線的超時時間
discovery.seed_hosts: ["172.19.12.21:9301", "172.19.12.22:9302", "172.19.12.23:9303"] # 設定叢集中的 Master 節點的初始列表,可以透過這些節點來自動發現其他新加入叢集的節點,es7 的新增配置
cluster.initial_master_nodes: ["172.19.12.21"] # 新叢集初始時的候選主節點,es7 的新增配置
EOF

  docker run --name elasticsearch-node-${port} \
    -p 920${port}:920${port} -p 930${port}:930${port} \
    --network=mynet --ip 172.19.12.2${port} \
    -e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
    -v /mydata/elasticsearch/node-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
    -v /mydata/elasticsearch/node-${port}/data:/usr/share/elasticsearch/data \
    -v /mydata/elasticsearch/node-${port}/plugins:/usr/share/elasticsearch/plugins \
    -d elasticsearch:7.4.2
done

image-20240914013259046

測試叢集

http://192.168.188.180:9201/_nodes/process?pretty  檢視節點狀況
http://192.168.188.180:9201/_cluster/stats?pretty  檢視叢集狀態
http://192.168.188.180:9201/_cluster/health?pretty 檢視叢集健康狀況
http://192.168.188.180:9202/_cat/nodes             檢視各個節點資訊

$ curl localhost:9200/_cat
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
/_cat/nodeattrs
/_cat/repositories
/_cat/snapshots/{repository}

image-20240914013410063

7.10RabbitMQ-映象叢集搭建

7.10.1叢集形式

RabbiMQ 是用 Erlang 開發的,叢集非常方便,因為 Erlang 天生就是一門分散式語言,但其 本身並不支援負載均衡。

RabbitMQ 叢集中節點包括記憶體節點(RAM)、磁碟節點(Disk,訊息持久化),叢集中至少有 一個 Disk 節點。

  • 普通模式(預設)

對於普通模式,叢集中各節點有相同的佇列結構,但訊息只會存在於叢集中的一個節 點。對於消費者來說,若訊息進入 A 節點的 Queue 中,當從 B 節點拉取時,RabbitMQ 會 將訊息從 A 中取出,並經過 B 傳送給消費者。 應用場景:該模式各適合於訊息無需持久化的場合,如日誌佇列。當佇列非持久化,且 建立該佇列的節點當機,客戶端才可以重連叢集其他節點,並重新建立佇列。若為持久化, 只能等故障節點恢復。

  • 映象模式

與普通模式不同之處是訊息實體會主動在映象節點間同步,而不是在取資料時臨時拉 取,高可用;該模式下,mirror queue 有一套選舉演算法,即 1 個 master、n 個 slaver,生產 者、消費者的請求都會轉至 master。

應用場景:可靠性要求較高場合,如下單、庫存佇列。

缺點:若映象佇列過多,且訊息體量大,叢集內部網路頻寬將會被此種同步通訊所消 耗。

(1)映象叢集也是基於普通叢集,即只有先搭建普通叢集,然後才能設定映象佇列。

(2)若消費過程中,master 掛掉,則選舉新 master,若未來得及確認,則可能會重複消費。

7.10.2搭建叢集

搭建叢集

建立目錄

mkdir /mydata/rabbitmq
cd rabbitmq/
mkdir rabbitmq01 rabbitmq02 rabbitmq03

image-20240914015659992

執行rabbitmq01rabbitmq02rabbitmq03

docker run -d --hostname rabbitmq01 --name rabbitmq01 \
  -v /mydata/rabbitmq/rabbitmq01:/var/lib/rabbitmq \
  -p 15673:15672 -p 5673:5672 \
  -e RABBITMQ_ERLANG_COOKIE='peng' \
  rabbitmq:management
  
docker run -d --hostname rabbitmq02 --name rabbitmq02 \
  -v /mydata/rabbitmq/rabbitmq02:/var/lib/rabbitmq \
  -p 15674:15672 -p 5674:5672 \
  -e RABBITMQ_ERLANG_COOKIE='peng' \
  --link rabbitmq01:rabbitmq01 \
  rabbitmq:management
  
docker run -d --hostname rabbitmq03 --name rabbitmq03 \
  -v /mydata/rabbitmq/rabbitmq03:/var/lib/rabbitmq \
  -p 15675:15672 -p 5675:5672 \
  -e RABBITMQ_ERLANG_COOKIE='peng' \
  --link rabbitmq01:rabbitmq01 \
  --link rabbitmq02:rabbitmq02 \
  rabbitmq:management

image-20240914020958196

節點加入叢集

進入rabbitmq01

docker exec -it rabbitmq01 /bin/bash

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit

image-20240914015848720

進入rabbitmq02

docker exec -it rabbitmq02 /bin/bash

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit

image-20240914021056417

進入rabbitmq03

docker exec -it rabbitmq03 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit

image-20240914021136041

實現映象叢集

在 cluster 中任意節點啟用策略,策略會自動同步到叢集節點 rabbitmqctl set_policy-p/ha-all"^"’{“ha-mode”:“all”}’ 策略模式 all 即複製到所有節點,包含新增節點,策略正規表示式為 “^” 表示所有匹配所有佇列名稱。“^hello”表示只匹配名為 hello 開始的佇列。

docker exec -it rabbitmq01 bash

rabbitmqctl set_policy -p / ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

#檢視 vhost/下面的所有 policy
rabbitmqctl list_policies -p /; 

image-20240914021158186

測試

http://192.168.188.180:15673/#/queues建立節點,剩下2個從節點自動同步

image-20240914021420173

8.k8s部署

8.1如何在k8s上部署有狀態應用

可以使用 kubesphere,快速搭建 MySQL 環境。

  • 有狀態服務抽取配置為 ConfigMap

  • 有狀態服務必須使用 pvc 持久化資料

  • 服務叢集內訪問使用 DNS

image-20240914022437559

8.2k8s部署MySQL

常用命令

# 建立目錄
mkdir -p /mydata/mysql/master/{data,log}
mkdir -p /mydata/mysql/master/conf/{conf.d,mysql.conf.d}

# 執行
docker run -p 3317:3306 --name mysql-master \
  -v /mydata/mysql/master/log:/var/log/mysql \
  -v /mydata/mysql/master/data:/var/lib/mysql \
  -v /mydata/mysql/master/conf:/etc/mysql \
  -e MYSQL_ROOT_PASSWORD=root \
  -d mysql:5.7

kubectl get statefulsets -n peng-mall
kubectl edit statefulset mysql-master-v1 -n peng-mall
kubectl get pods -n peng-mall

8.2.1部署mysql主節點

安裝

  • 建立配置mysql-master-cnf
  • 建立儲存卷mysql-master-pvc
  • 建立有狀態服務

建立配置mysql-master-cnf

基本資訊

image-20240928003047923

配置設定

my.cnf

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

# 新增 master 主從複製部分配置
server_id=1
log-bin=mysql-bin

# 讀寫
read-only=0

# 只同步業務庫
binlog-do-db=mall_ums
binlog-do-db=mall_pms
binlog-do-db=mall_oms
binlog-do-db=mall_sms
binlog-do-db=mall_wms
binlog-do-db=mall_admin

# 不同步mysql基礎庫
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

image-20240928003212613

image-20240928003537316

建立儲存卷mysql-master-pvc

基本資訊

image-20240928003343327

儲存卷設定

image-20240928003408383

image-20240928003521669

建立有狀態服務

image-20240928003603717

基本資訊

image-20240928003624804

映象設定

如果一直查詢不出來mysql:5.7,使用命令列工具docker search mysql:5.7查詢一下,我學習的這幾個月docker地址老是被牆

image-20240928003712917

解決辦法:

docker search不能使用映象加速,但是pull可以下載映象,提前把mysql:5.7映象下載下來

image-20240928003831915

分享我的daemon.json,如果後面還不能用,自己上網再查詢即可

cat << EOF > /etc/docker/daemon.json
{
    "exec-opts": ["native.cgroupdriver=systemd"],
    "registry-mirrors": [
        "https://dockerproxy.cn",
        "https://docker.rainbond.cc",
        "https://docker.udayun.com",
        "https://docker.211678.top",
        "https://hub.rat.dev",
        "https://docker.wanpeng.top",
        "https://doublezonline.cloud",
        "https://docker.mrxn.net",
        "https://lynn520.xyz",
        "https://ginger20240704.asia",
        "https://docker.wget.at",
        "https://dislabaiot.xyz",
        "https://dockerpull.com",
        "https://docker.fxxk.dedyn.io",
        "https://docker.m.daocloud.io"
    ],
    "live-restore": true,
    "log-driver": "json-file",
    "log-opts": {"max-size": "500m", "max-file": "3"},
    "storage-driver": "overlay2"
}
EOF

image-20240928004157712

然後重啟

sudo systemctl daemon-reload
sudo systemctl restart docker

我這裡三個節點都下載了mysql:5.7,你也不知道mysql會安裝在那個子節點上

image-20240928004412167

服務設定資源、埠

image-20240928004605258

映象下載完成後記得選擇優先使用本地映象

image-20240928015644286

環境配置,設定資料庫密碼,這裡的mysql-secret之前都配置過了

image-20240928004650395

掛載儲存

注意我這裡配置了1個儲存卷和3個配置檔案

/var/lib/mysql
/etc/mysql
/etc/mysql/conf.d
/etc/mysql/mysql.conf.d

按理說只需要配置/etc/mysql,但我這裡執行時會報錯,說是找不到/etc/mysql/conf.d/etc/mysql/mysql.conf.d,所以直接在這2個路徑下也新增配置檔案

image-20240928004917860

mysqld: Can't read dir of '/etc/mysql/conf.d/

image-20240927182756703

image-20240928004914981

高階設定

image-20240928005802166

8.2.2部署mysql子節點

安裝

  • 建立配置mysql-slave-01-cnf
  • 建立儲存卷mysql-slave-01-pvc
  • 建立有狀態服務

建立配置mysql-slave-01-cnf

基本資訊

image-20240928010325030

配置設定

配置項

my.cnf

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

# 新增 master 主從複製部分配置
server-id=2
log-bin=mysql-bin

# 只讀
read-only=1

# 只同步業務庫
binlog-do-db=mall_ums
binlog-do-db=mall_pms
binlog-do-db=mall_oms
binlog-do-db=mall_sms
binlog-do-db=mall_wms
binlog-do-db=mall_admin

# 不同步mysql基礎庫
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

image-20240928010424589

建立完成

image-20240928010438832

建立儲存卷mysql-slave-01-pvc

基本資訊

image-20240928010533587

儲存卷設定

image-20240928010556032

點選建立

image-20240928010628367

建立完成

image-20240928010643945

建立有狀態服務

image-20240928010704766

基本資訊

image-20240928010749869

映象

image-20240928010816335

資源配置

image-20240928010901329

環境變數

image-20240928010922914

掛在儲存,注意我們掛載的是子節點的儲存卷**mysql-slave-01-pvc**和配置檔案mysql-slave-01-cnf

/var/lib/mysql
/etc/mysql
/etc/mysql/conf.d
/etc/mysql/mysql.conf.d

image-20240928011124618

高階設定

image-20240928011221716

建立完成

image-20240928011247840

8.2.3配置mysql主從

進入mysql-master(mysql主節點)容器組

image-20240928011353239

進入容器

image-20240928011429205

為 master 授權使用者來他的同步資料

進入 master 容器

mysql -u root -p

進入 mysql 內部

# 授權 root 可以遠端訪問( 主從無關,為了方便我們遠端連線 mysql)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;

# 新增用來同步的使用者
GRANT REPLICATION SLAVE ON *.* to 'backup'@'%' identified by '123456';

# 檢視 master狀態
show master status;

記住mysql-bin.000004這個地址,一會同步從庫的時候要從mysql-bin.000004同步

image-20240928012355318

配置 slaver 同步 master 資料

進入從庫容器組mysql-slave-01-v1-0

image-20240928012604256

進入 slaver 容器

mysql -u root -p

mysql-master域名是mysql-master.peng-mall,資料同步位置是mysql-bin.000004,埠號是3306,所以同步命令

CHANGE MASTER TO MASTER_HOST='mysql-master.peng-mall',
                   MASTER_USER='backup',
                   MASTER_PASSWORD='123456',
                   MASTER_LOG_FILE='mysql-bin.000004',
                   MASTER_LOG_POS=0,
                   MASTER_PORT=3306;

image-20240928012935939

進入mysql內部

# 授權 root 可以遠端訪問( 主從無關,為了方便我們遠端連線 mysql)
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;

# 設定主庫連線
# MASTER_LOG_FILE是show master status;查master的File欄位
CHANGE MASTER TO MASTER_HOST='mysql-master.peng-mall',
                   MASTER_USER='backup',
                   MASTER_PASSWORD='123456',
                   MASTER_LOG_FILE='mysql-bin.000004',
                   MASTER_LOG_POS=0,
                   MASTER_PORT=3306;

# 啟動從庫同步
start slave;

# 檢視從庫狀態
show slave status\G;

image-20240928013246769

從庫配置完成

image-20240928013313544

8.2.4測試

進入容器mysql-master-v1-0建立資料庫mall_admin

再次進入容器mysql-slave-01-v1-0,發現資料庫mall_admin已同步從庫

mysql -u root -p

DROP DATABASE IF EXISTS mall_admin;

CREATE DATABASE mall_admin;

SHOW DATABASES;

USE mall_admin;

CREATE TABLE IF NOT EXISTS test_table (
    id INT AUTO_INCREMENT PRIMARY KEY,     -- 自增主鍵列
    name VARCHAR(100)                      -- 名稱列,不能為空
);

INSERT INTO test_table (name) VALUES ('Alice');

image-20240928013810418

8.3k8s部署Redis

安裝:

  • 建立配置redis-conf
  • 建立儲存卷redis-pvc
  • 建立有狀態服務

建立配置redis-conf

redis-conf

image-20240928020209401

配置設定

redis-conf
appendonly yes

image-20240928020254812

建立儲存卷redis-pvc

redis-pvc

基本資訊

image-20240928020403782

儲存卷設定

image-20240928020422947

建立完成

image-20240928020448550

建立有狀態服務

redis:5.0.7
# 或者
redis:latest

image-20240928020655149

資源、埠配置

6379

image-20240928020716759

新增啟動命令

redis-server
/etc/redis/redis.conf

image-20240928020935167

可以提前在主節點使用docker pull redis:5.0.7拉取映象,這裡建議設定優先使用本地映象

image-20241004173827466

掛載儲存

配置指定的配置檔案

/etc/redis
redis.conf

image-20240928021205031

redis儲存卷和配置檔案配置完成

/data

image-20240928021149643

建立完成

image-20240928021232545

pod一直處於ContainerCreating狀態,沒有可忽略

pod一直處於ContainerCreating狀態,如果之前我們在主節點下載了redis:5.0.7,可以在主節點打包,然後從主節點複製到子節點

也可以從有映象的地方打包,然後直接複製到子節點

image-2024100418035692

# 打包
docker save -o /root/k8s/redis_5.0.7.tar redis:5.0.7
# 複製
scp /root/k8s/redis_5.0.7.tar root@k8s-03:/root/k8s/

image-20241004180552403

然後到k8s-03子節點

cd k8s/
# 解壓映象
docker load -i /root/k8s/redis_5.0.7.tar

image-20241004180635912

在這裡可以確定redis安裝在了那個子節點

image-20241004180805906

測試

redis-cli
set aa bb
get aa

image-20240928021931210

8.4k8s部署ElasticSearch&Kibana

8.4.1部署ElasticSearch

安裝

  • 建立elasticsearch-conf
  • 建立elasticsearch-pvc
  • 建立有狀態服務elasticsearch

建立elasticsearch-conf

elasticsearch-conf

基本資訊

image-20240928023410497

配置設定

http.host = 0.0.0.0
discovery.type = single-node
ES_JAVA_OPTS = -Xms512m -Xmx512m

image-20240928023354218

建立elasticsearch-pvc

elasticsearch-pvc

基本資訊

image-20240928023503936

儲存卷設定

image-20240928023742759

建立有狀態服務elasticsearch

elasticsearch:7.12.1
# 或者 我這裡下載了這2個映象
docker.elastic.co/elasticsearch/elasticsearch:7.12.1

image-20240928024252691

配置資源、埠

9200
9300

image-20240928024317422

配置環境變數

image-20240928024326733

配置儲存卷

/usr/share/elasticsearch/data

image-20240928024508493

建立

image-20240928024521510

測試

使用admin登入

image-20240928025043874

訪問elasticsearch

curl http://elasticsearch.peng-mall:9200

image-20240928025110479

8.4.2部署Kibana

建立無狀態服務

image-20240928025254122

基本資訊

kibana

image-20240928025331807

設定映象

kibana:7.12.1

image-20240928025659723

配置埠5601

image-20240928025724939

配置環境變數

ELASTICSEARCH_URL = http://elasticsearch.peng-mall:9200

image-20240928025746885

不需要掛載儲存

高階設定

image-20240928025614538

kibana部署完成,我們訪問他的埠

image-20240928032729483

測試,訪問自己虛擬機器的30027埠,能夠傳送請求代表部署成功

http://192.168.188.181:30027/app/dev_tools#/console

image-20240928032956419

8.5k8s部署RabbitMQ

安裝:

  • 建立儲存卷rabbitmq-pvc
  • 建立有狀態服務rabbitmq

建立儲存卷rabbitmq-pvc

建立儲存卷-基本資訊

rabbitmq-pvc

image-20240928033435934

儲存卷設定

image-20240928033539147

建立有狀態服務rabbitmq

基本資訊

rabbitmq

image-20240928033828963

容器映象

rabbitmq:3.8-management

image-20240928033819531

配置資源和埠

    ports:
      - "5672:5672"                      # 對映主機的5672埠到容器的5672埠
      - "15672:15672"                    # 對映主機的15672埠到容器的15672埠(管理介面)

image-20240928033915261

掛載儲存

設定儲存卷

/var/lib/rabbitmq

image-20240928033954433

高階設定

image-20240928034112138

有時候映象下載不下來,可以先下載,在設定映象的時候設定優先選擇本地映象即可

image-20240928034854878

部署完成

image-20240928034815787

8.6k8s部署Nacos

8.6.1部署mysql8

services:
  mysql:
    image: mysql:latest
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root          # MySQL 根使用者密碼
      MYSQL_DATABASE: nacos              # 預設建立的資料庫
      MYSQL_PASSWORD: root               # MySQL 使用者密碼
      TZ: Asia/Shanghai
    ports:
      - "3306:3306"                      # 對映主機的3306埠到容器的3306埠
    volumes:
      # - mysql_data:/var/lib/mysql        # 持久化 MySQL 資料到名為 mysql_data 的卷
      - ./mysql/data:/var/lib/mysql 
      - ./mysql/conf:/etc/mysql/conf.d 
      # - ./root/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - peng-net                         # 指定連線的網路

建立mysql8-conf

mysql8-conf

image-20240928170625515

建立mysql8-cnf

mysql8.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'

image-20240928170741167

這樣就建立完成了mysql8的環境變數和配置

image-20240928170755158

建立mysql8-pvc

mysql8-pvc

image-20240928170848748

建立有狀態服務

mysql8

image-20240928171208093

設定映象

mysql:latest

image-20240928171059819

配置資源和埠

tcp-3306 3306 3306

image-20240928171132028

配置環境變數,選擇mysql8-conf

mysql8-conf

image-20240928171146884

配置掛載儲存

mysql8-pvc         /var/lib/mysql 
mysql8-cnf         /etc/mysql/conf.d

image-20240928171301592

高階設定

image-20240928171321933

部署nacos需要的資料

# 將nacos.sql複製到容器內
kubectl cp /root/k8s/nacos.sql peng-mall/mysql8-v1-0:/tmp/nacos.sql

# 進入容器
kubectl exec -it mysql8-v1-0 -n peng-mall -- /bin/bash

# 登入mysql
mysql -u root -p

# 執行
source /tmp/nacos.sql;

# 退出mysql
exit;

# 刪除
rm /tmp/nacos.sql

# 退出容器
exit;	

image-20240928170504237

mysql映象一直不能自動下載,如果主節點有mysql:latest,可以打包,然後複製到子節點重新載入

k8s-01打包mysql:latest

# 打包
docker save -o /root/k8s/mysql_latest.tar mysql:latest
# 複製到k8s-02
scp /root/k8s/mysql_latest.tar root@k8s-02:/root/k8s

image-20241005001915424

k8s-01

docker load -i /root/k8s/mysql_latest.tar

image-20241005002054809

8.6.2部署nacos

nacos:
    image: nacos/nacos-server:v2.1.0-slim
    container_name: nacos
    environment:
      - PREFER_HOST_MODE=hostname        # 使用主機名作為偏好模式
      - MODE=standalone
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=192.168.188.180  # MySQL 服務主機名
      - MYSQL_SERVICE_DB_NAME=nacos      # Nacos 使用的資料庫名
      - MYSQL_SERVICE_PORT=3306          # MySQL 服務埠
      - MYSQL_SERVICE_USER=root          # MySQL 使用者名稱
      - MYSQL_SERVICE_PASSWORD=root      # MySQL 使用者密碼
      - MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
      # - NACOS_AUTH_ENABLE=true           # 啟用 Nacos 認證
    ports:
      - "8848:8848"                      # 對映主機的8848埠到容器的8848埠
      - "9848:9848" 
      - "9849:9849"
    depends_on:
      - mysql                            # 啟動順序,先啟動 mysql 服務
    volumes:
      - nacos_data:/home/nacos/init.d    # 持久化 Nacos 資料到名為 nacos_data 的卷
    networks:
      - peng-net                

基本資訊

nacos-conf

image-20240928040317082

配置設定

image-20240928041331177

注意MYSQL_SERVICE_HOST配置的是mysql8服務的DNS

mysql8.peng-mall

image-20240928171706837

建立有狀態服務

nacos

image-20240928173202589

映象設定

nacos/nacos-server:v2.1.0-slim

image-20240928173011343

配置資源和埠

- "8848:8848"                    
- "9848:9848" 
- "9849:9849"

image-20240928173123108

環境變數

image-20240928173147699

儲存卷

nacos-pvc
/home/nacos/init.d

image-20240928173237288

高階設定

image-20240928173258603

8.7k8s部署Zipkin

zipkin:
    image: openzipkin/zipkin
    container_name: zipkin
    environment:
      STORAGE_TYPE: elasticsearch
      ES_HOST: elasticsearch
      ES_PORT: 9200
      ES_INDEX: zipkin
    ports:
      - "9411:9411"                      # 對映主機的9411埠到容器的9411埠
    networks:

建立zipkin-conf

image-20240928174104580

ES_HOST是部署elasticsearch後的域名

elasticsearch.peng-mall

image-20240928174152842

建立無狀態服務zipkin

zipkin

image-20240928174915790

映象設定

openzipkin/zipkin

image-20240928175006166

資源、埠配置

9411

image-20240928175021435

環境配置

image-20240928175101482

不需要配置掛載儲存

高階設定

允許外網訪問,選擇NodePort

image-20240928175123196

測試訪問http://192.168.188.181:30922/zipkin/

image-20240928175912433

8.8k8s部署Sentinel

  sentinel:
    image: bladex/sentinel-dashboard
    container_name: sentinel
    ports:
      - "8858:8858"                      # 對映主機的8858埠到容器的8858埠
    networks:
      - peng-net                         # 指定連線的網路

建立無狀態服務sentinel

sentinel

image-20240928175350765

映象設定

bladex/sentinel-dashboard

image-20240928175628409

資源、埠配置

8858

image-20240928175708266

無掛載儲存

高階設定

開啟外網訪問,選擇NodePort

image-20240928175818169

測試訪問http://192.168.188.181:30630/#/login

image-20240928180202772

8.9k8s部署應用的流程

image-20240928181050037

8.10生產環境配置抽取

8.10.1檢視服務域名內部是否可以訪問

使用admin賬號登入,開啟kubectl

image-20240929162613176

sentinel不可以訪問域名

image-20240929163402440

zipkin不可以訪問域名

image-20240929163457540

nacos可以訪問域名

image-20240929163609764

mysql8可以訪問域名

image-20240929163646763

rabbitmq可以訪問域名

image-20240929163728790

kibana不可以訪問域名

image-20240929163817596

elasticsearch可以訪問域名

image-20240929163918164

redis可以訪問域名

image-20240929164034030

8.10.3sentinel服務指定工作負載

選擇指定工作負載

image-20240929170012054

基本資訊

sentinel-service

image-20240929164327645

選擇EndPoint IP訪問

點選指定工作負載,選擇sentinel

繫結8858

image-20240929165151416

開啟會話保持,然後建立

image-20240929165343615

測試sentinel-service內部是否可以訪問

image-20240929165556666

8.10.3zipkin服務指定工作負載

選擇指定工作負載

image-20240929170012054

基本資訊

zipkin-service

image-20240929165716185

選擇EndPoint IP訪問

點選指定工作負載,選擇zipkin

繫結9411

http-zipkin   9411   9411

image-20240929165810597

開啟會話保持,然後建立

image-20240929165852843

測試zipkin-service內部是否可以訪問

image-20240929165949770

8.10.4mysql8服務指定工作負載

mysql8安裝後,我們需要初始化資料庫

mysql8建立工作負載

image-20241006025834964

基本資訊

mysql8-node-port

image-20241006025857310

複製設定

選擇指定工作負載,選擇mysql8-v1

image-20241006025932657

設定埠

http-3306 3306 3306

image-20241006030009931

高階設定

選擇外網訪問,選擇NodePort,選擇開啟會話保持

image-20241006030047773

連線mysql8-node-portIP任意一個k8s節點ip都可以,埠是隨機暴露的埠

image-20241006030448553

然後匯入所有的資料,nacos服務需要連線資料庫,如果之前沒匯入,這裡要匯入

image-20241006030528959

mall_admin
mall_oms
mall_pms
mall_sms
mall_ums
mall_wms
nacos
# 不使用可以不建立
seata

mysql編碼

utf8mb4
utf8mb4_unicode_ci

8.10.5nacos服務指定工作負載

如果我們要使用nacos控制檯檢視服務狀態,需要為nacos建立工作負載,允許外部訪問

基本資訊

建立ncaos工作負載

nacos-node-port

image-20241006030849281

服務設定

選擇指定工作負載,選擇nacos-v1

image-20241006031532116

http-8848   8848   8848

image-20241006031636140

高階設定

選擇外網訪問,選擇NodePort,選擇開啟會話保持

image-20241006031710887

進入nacos-node-port檢視訪問埠32750,然後訪問http://192.168.188.181:32750

image-20241006031910411

8.10.6生產環境配置

所有服務的地址

服務 域名
zipkin zipkin-service.peng-mall:9411
sentinel sentinel-service.peng-mall:8858
mysql8 mysql8.peng-mall:3306
nacos nacos.peng-mall:8848
rabbitmq rabbitmq.peng-mall:5672
kibana kibana.peng-mall:5601
elasticsearch elasticsearch.peng-mall:9200
redis redis.peng-mall:6379

給所有的服務新增生產環境配置檔案application-prod.yaml

我這裡以商品服務gulimall-order為例,然後更新對應的服務地址

image-20240929173615193

這裡需要留意的是我們不考慮強一致性的seata事務解決辦法,而且我們沒有在k8s上部署seata,這裡把seata服務關閉了

image-20240929173716094

8.11建立微服務Dockfile

所有服務的application-prod.yaml的啟動埠都改成8080

因為每個服務都一個獨立的容器,他們在容器內部執行8080沒有問題,對外對映的埠不一樣即可

image-20240929180239285

所有的服務新增Dockerfile,內容如下

  • FROM: 指定基礎映象。在這裡,使用的是 Java 8 的官方 Docker 映象。這意味著構建的映象將基於這個 Java 8 映象。
  • EXPOSE: 告訴 Docker 容器內部的應用會使用 8080 埠進行通訊。這並不會直接開放埠,只是為文件和將來的網路配置提供參考。
  • VOLUME: 建立一個掛載點,容器執行時會將 /tmp 目錄標記為持久化儲存。這樣,在容器重啟時,儲存在 /tmp 中的資料不會丟失。
  • ADD: 將構建上下文中的檔案(在這個例子中是 target 目錄下的 .jar 檔案)複製到容器中的 /app.jar 路徑。這一命令不僅可以複製檔案,還可以自動解壓歸檔檔案。
  • RUN: 在構建映象時執行命令。在這裡,它用於建立或更新 /app.jar 檔案的時間戳。這一命令通常用於確保該檔案在容器執行時被重新載入。
  • ENTRYPOINT: 設定容器啟動時執行的命令。在這裡,指定了使用 Java 命令來執行 /app.jar,並傳遞引數 --spring.profiles.active=prod,這意味著 Spring 應用將以 prod(生產)配置檔案啟動。
FROM java:8
EXPOSE 8080

VOLUME /tmp
ADD target/*.jar /app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java", "-jar", "/app.jar", "--spring.profiles.active=prod"]

image-20240929180425469

8.12建立微服務k8s部署描述檔案

8.12.1Deployment

官方demo地址:https://github.com/kubesphere/devops-java-sample/tree/master/deploy/prod-ol

image-20240929182308412

選擇sentinel-service,選擇工作負載,點選該服務

image-20240929185758622

選擇編輯檔案,複製sentinel-service的配置

image-20240929185819907

把所有app: sentinel替換為自己的微服務名稱app: gulimall-auth-service

app: sentinel
app: gulimall-auth-service

image-20240929222220857

8.12.2Service

官方demo地址:https://github.com/kubesphere/devops-java-sample/blob/master/deploy/prod-ol/devops-sample-svc.yaml

image-20240929230719560

選擇一個無狀態服務,這裡選擇的是sentinel,選擇編輯配置檔案,把配置檔案複製出來進行修改

image-20240929230128075

把所有app: sentinel替換為自己的微服務名稱app: gulimall-auth-service

app: sentinel
app: gulimall-auth-service

把所有 name: sentinel替換為自己的微服務名稱name: gulimall-auth-service

name: sentinel
name: gulimall-auth-service

image-20240929231415434

8.12.3完整配置

kind: Deployment
apiVersion: apps/v1
metadata:
  name: gulimall-auth-service
  namespace: peng-mall
  labels:
    app: gulimall-auth-service
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gulimall-auth-service
      version: v1
  template:
    metadata:
      labels:
        app: gulimall-auth-service
        version: v1
    spec:
      containers:
        - name: gulimall-auth-service
          image: $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 1000m
              memory: 500Mi
            requests:
              cpu: 10m
              memory: 10Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

---

kind: Service
apiVersion: v1
metadata:
  name: gulimall-auth-service
  namespace: peng-mall
  labels:
    app: gulimall-auth-serviceinel
    version: v1
spec:
  ports:
    - name: http
      port: 8080
      protocol: TCP
      targetPort: 8080
      nodePort: 20001
  selector:
    app: gulimall-auth-serviceinel
  type: NodePort
  sessionAffinity: None

8.12.4為所有服務新增deploy

gulimall-auth-servicedeploy資料夾複製到所有服務

把所有app: sentinel替換為自己的微服務名稱app: 微服務名稱

app: sentinel
app: 微服務名稱

把所有 name: sentinel替換為自己的微服務名稱name: 微服務名稱

name: sentinel
name: 微服務名稱

修改埠號,從200001開始+2

image-20240929233621479

8.13理解targetPort、Port、NodePort

targetPort:

  • 這是指向容器內部服務的埠。當服務接收到請求時,它會將請求轉發到指定的 targetPort
  • 可以是容器內部的埠號,也可以是名稱(如 "http" 或 "mysql"),表示容器內定義的埠。

port:

  • 這是服務在 Kubernetes 中暴露的埠,外部的請求透過這個埠訪問服務。
  • port 是服務的虛擬埠,通常用於叢集內部的通訊。

nodePort:

  • 這是一個可選欄位,用於將服務暴露給外部流量。Kubernetes 會在每個節點的指定埠上監聽並轉發請求到 port
  • nodePort 的值必須在 30000 到 32767 之間(預設情況下)。外部請求可以透過 NodeIP:nodePort 訪問服務。

image-20240929234514304

8.14備份

商城執行的基本程式都搭建完成的話記得備份

image-20241005003930257

創作不易,感謝支援。

wxzf

相關文章