在WSL2上部署標(biāo)準(zhǔn)k8s集群并使用Prometheus監(jiān)控spring cloud服務(wù)

在WSL2上部署標(biāo)準(zhǔn)k8s集群并使用Prometheus監(jiān)控spring cloud服務(wù)

2019年Windows Build大會上,微軟發(fā)布 WSL2,意味著開發(fā)者們終于可以在Windows上開發(fā)和運行原汁原味 Linux 應(yīng)用。

本篇文章將教會大家如何在 WSL2 部署一個標(biāo)準(zhǔn)版的 k8s 集群以及使用 Prometheusgrafana 監(jiān)控 spring cloud 服務(wù)。

和第一代 WSL不同,WSL2 是運行在 hyper-v 上的一個 VM疟羹,因此可以運行原汁原味的 Linux 發(fā)行版,例如 Ubuntu禀倔,同樣對 Linux ABI 接口兼容也更好榄融,支持更多 Linux 應(yīng)用,例如 docker 救湖。

經(jīng)過將近一年時間的開發(fā)與優(yōu)化剃袍,微軟團(tuán)隊終于發(fā)布了正式版 WSL2,用戶只需將操作系統(tǒng)升級到 2004 以后的 Windows 10 即可捎谨。

準(zhǔn)備工作

安裝 WSL

前置條件:

  • 操作系統(tǒng)必須是 Windows 10 build 2004 以后的版本
  • C盤 剩余空間最好在 64G 以上
  • 內(nèi)存最好是 16G 以上民效,8g 內(nèi)存運行 k8s 集群后憔维,就沒有剩余內(nèi)存

安裝開始:

  1. 在桌面左下角 Windows 徽標(biāo)上,右鍵選擇 Windows Powershell(管理員)(A)畏邢,然后運行一下腳本
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

如果這里遇到失敗业扒,多半是操作系統(tǒng)沒有升到最新版本的 Windows 10 或者

  1. 安裝 WSL 2 之前,必須啟用“虛擬機(jī)平臺”可選功能舒萎。
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
  1. 重新啟動計算機(jī)程储,以完成 WSL 安裝并更新到 WSL 2。

  2. 將 WSL 2 設(shè)置為默認(rèn)版本

安裝新的 Linux 分發(fā)版時臂寝,請在 Powershell 中運行以下命令章鲤,以將 WSL 2 設(shè)置為默認(rèn)版本:

wsl --set-default-version 2
  1. 安裝所選的 Linux 分發(fā)版

打開 Microsoft Store,并選擇你偏好的 Linux 分發(fā)版咆贬。

Microsoft Store

單擊以下鏈接會打開每個分發(fā)版的 Microsoft Store 頁面:

  1. 在分發(fā)版的頁面中败徊,選擇“獲取”。
ubuntu-store
  1. 設(shè)置新分發(fā)版

首次啟動新安裝的 Linux 分發(fā)版時掏缎,將打開一個控制臺窗口皱蹦,系統(tǒng)會要求你等待一分鐘或兩分鐘,以便文件解壓縮并存儲到電腦上眷蜈。 未來的所有啟動時間應(yīng)不到一秒沪哺。

然后,需要為新的 Linux 分發(fā)版創(chuàng)建用戶帳戶和密碼酌儒。

ubuntu-install

將分發(fā)版版本設(shè)置為 WSL 1 或 WSL 2
可以打開 PowerShell 命令行并輸入以下命令(僅在 Windows 內(nèi)部版本 19041 或更高版本中可用)辜妓,來檢查分配給每個已安裝的 Linux 分發(fā)版的 WSL 版本:wsl -l -v

wsl --list --verbose

若要將分發(fā)版設(shè)置為受某一 WSL 版本支持,請運行:

wsl --set-version <distribution name> <versionNumber>

請確保將 <distribution name> 替換為你的分發(fā)版的實際名稱忌怎,并將 <versionNumber> 替換為數(shù)字“1”或“2”嫌拣。 可以隨時更改回 WSL 1,方法是運行與上面相同的命令呆躲,但將“2”替換為“1”。
此外捶索,如果要使 WSL 2 成為你的默認(rèn)體系結(jié)構(gòu)插掂,可以通過此命令執(zhí)行該操作:

wsl --set-default-version 2

這會將安裝的任何新分發(fā)版的版本設(shè)置為 WSL 2

  1. 排查安裝問題

下面是相關(guān)的錯誤和建議的修復(fù)措施腥例。 有關(guān)其他常見錯誤及其解決方法辅甥,請參閱 WSL 故障排除頁

  • 安裝失敗并出現(xiàn)錯誤 0x80070003
    • 適用于 Linux 的 Windows 子系統(tǒng)只能在系統(tǒng)驅(qū)動器(通常是 C: 驅(qū)動器)中運行燎竖。 請確保分發(fā)版存儲在系統(tǒng)驅(qū)動器上:
    • 打開“設(shè)置”->“存儲”->“更多存儲設(shè)置: 更改新內(nèi)容的保存位置”
  • WslRegisterDistribution 失敗并出現(xiàn)錯誤 0x8007019e
    • 未啟用“適用于 Linux 的 Windows 子系統(tǒng)”可選組件:
    • 打開“控制面板” -> “程序和功能” -> “打開或關(guān)閉 Windows 功能”-> 選中“適用于 Linux 的 Windows 子系統(tǒng)”璃弄,或使用本文開頭所述的 PowerShell cmdlet芳来。
  • 安裝失敗鞠评,出現(xiàn)錯誤 0x80070003 或錯誤 0x80370102
    • 請確保在計算機(jī)的 BIOS 內(nèi)已啟用虛擬化。 有關(guān)如何執(zhí)行此操作的說明因計算機(jī)而異扬舒,并且很可能在 CPU 相關(guān)選項下。
  • 嘗試升級時出錯:Invalid command line option: wsl --set-version Ubuntu 2
    • 請確保已啟用適用于 Linux 的 Windows 子系統(tǒng)脐供,并且你使用的是 Windows 內(nèi)部版本 19041 或更高版本浑塞。 若要啟用 WSL,請在 Powershell 提示符下以具有管理員權(quán)限的身份運行此命令:Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux政己。 可在此處找到完整的 WSL 安裝說明酌壕。
  • 由于虛擬磁盤系統(tǒng)的某個限制,無法完成所請求的操作歇由。虛擬硬盤文件必須是解壓縮的且未加密的卵牍,并且不能是稀疏的。
    • 請檢查 WSL Github 主題 #4103沦泌,其中跟蹤了此問題以提供更新的信息糊昙。
  • 無法將詞語“wsl”識別為 cmdlet、函數(shù)赦肃、腳本文件或可運行程序的名稱溅蛉。
    • 請確保已安裝“適用于 Linux 的 Windows 子系統(tǒng)”可選組件。 此外他宛,如果你使用的是 Arm64 設(shè)備船侧,并從 PowerShell 運行此命令,則會收到此錯誤厅各。 請改為從 PowerShell Core 或從命令提示符運行 wsl.exe镜撩。
  1. 額外工作
  • 禁用 swap

    因為 kubelet 不支持 swap 內(nèi)存,因此需要通過設(shè)置 wslconfig 禁用 swap 队塘。在 用戶根目錄 創(chuàng)建 .wslconfig 文件袁梗,例如: 'C:\Users\huang' ,添加以下內(nèi)容:

    [wsl2]
    swap=0 # 關(guān)閉swap
    
    [network]
    generateResolvConf = false # 解決域名解析失敗的問題
    

    然后在 powershellcmd 運行以下命令憔古,關(guān)閉 wsl遮怜,再點擊開始菜單 Ubuntu 圖標(biāo),即完成重啟 WSL鸿市。

    wsl --shutdown
    
  • 設(shè)置 /etc/resolve.conf

    因為每次 WSL 啟動會自動覆蓋 /etc/resolve.conf 文件锯梁,可能會導(dǎo)致域名解析失敗的問題,必要時可以設(shè)置自定義的 DNS服務(wù)器 焰情,把以下內(nèi)容追加到 /etc/resolve.conf 文件末尾:(需要 root 權(quán)限陌凳,記得加上 sudo)

    nameserver 8.8.8.8
    nameserver 114.114.114.114
    
  • 替換 apt

    Ubuntu 官方源在國內(nèi)并不好用,因此我們需要替換源内舟,提高軟件安裝和更新速度合敦。編輯 /etc/apt/sources.list,為了安全可以先備份以下原文件

    # 備份source.list文件
    sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak
    # 創(chuàng)建source.list文件
    sudo vim /etc/apt/sources.list
    

    i 進(jìn)入編輯模式验游,然后把以下內(nèi)容復(fù)制粘貼到 /etc/apt/sources.list 文件

    這是清華大學(xué) Ubuntu 18.04 LTS 的鏡像源充岛,可根據(jù)用戶安裝的發(fā)行版自行替換

    # 默認(rèn)注釋了源碼鏡像以提高 apt update 速度保檐,如有需要可自行取消注釋
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
    
    # 預(yù)發(fā)布軟件源,不建議啟用
    # deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
    # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
    deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable
    # deb-src [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable
    

    先按 esc裸准,再安裝 :展东,輸入 wq,回車就出退出并保存文件炒俱。然后更新本地緩存

    sudo apt update && sudo apt upgrade
    
  • 安裝 daemonize

    很多 Linux 應(yīng)用需要 systemd 運行盐肃,比如說 dockerkubelet。但是幾乎所有 WSL2 支持的鏡像都不能運行 systemd权悟,因此我們需要安裝 daemonize砸王。

    apt-get update && sudo apt-get install -yqq daemonize dbus-user-session fontconfig
    

    創(chuàng)建 /usr/sbin/start-systemd-namespace 文件,并復(fù)制粘貼以下內(nèi)容到文件中

    #!/bin/bash
    SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')
    if [ -z "$SYSTEMD_PID" ] || [ "$SYSTEMD_PID" != "1" ]; then
        export PRE_NAMESPACE_PATH="$PATH"
        (set -o posix; set) | \
            grep -v "^BASH" | \
            grep -v "^DIRSTACK=" | \
            grep -v "^EUID=" | \
            grep -v "^GROUPS=" | \
            grep -v "^HOME=" | \
            grep -v "^HOSTNAME=" | \
            grep -v "^HOSTTYPE=" | \
            grep -v "^IFS='.*"$'\n'"'" | \
            grep -v "^LANG=" | \
            grep -v "^LOGNAME=" | \
            grep -v "^MACHTYPE=" | \
            grep -v "^NAME=" | \
            grep -v "^OPTERR=" | \
            grep -v "^OPTIND=" | \
            grep -v "^OSTYPE=" | \
            grep -v "^PIPESTATUS=" | \
            grep -v "^POSIXLY_CORRECT=" | \
            grep -v "^PPID=" | \
            grep -v "^PS1=" | \
            grep -v "^PS4=" | \
            grep -v "^SHELL=" | \
            grep -v "^SHELLOPTS=" | \
            grep -v "^SHLVL=" | \
            grep -v "^SYSTEMD_PID=" | \
            grep -v "^UID=" | \
            grep -v "^USER=" | \
            grep -v "^_=" | \
            cat - > "$HOME/.systemd-env"
        echo "PATH='$PATH'" >> "$HOME/.systemd-env"
        exec sudo /usr/sbin/enter-systemd-namespace "$BASH_EXECUTION_STRING"
    fi
    if [ -n "$PRE_NAMESPACE_PATH" ]; then
        export PATH="$PRE_NAMESPACE_PATH"
    fi
    

    接著峦阁,創(chuàng)建 /usr/sbin/enter-systemd-namespace 文件谦铃,將以下內(nèi)容復(fù)制粘貼到文件中

    #!/bin/bash
    
    if [ "$UID" != 0 ]; then
        echo "You need to run $0 through sudo"
        exit 1
    fi
    
    SYSTEMD_PID="$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')"
    if [ -z "$SYSTEMD_PID" ]; then
        /usr/sbin/daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
        while [ -z "$SYSTEMD_PID" ]; do
            SYSTEMD_PID="$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')"
        done
    fi
    
    if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
        if [ -n "$1" ] && [ "$1" != "bash --login" ] && [ "$1" != "/bin/bash --login" ]; then
            exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a \
                /usr/bin/sudo -H -u "$SUDO_USER" \
                /bin/bash -c 'set -a; source "$HOME/.systemd-env"; set +a; exec bash -c '"$(printf "%q" "$@")"
        else
            exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a \
                /bin/login -p -f "$SUDO_USER" \
                $(/bin/cat "$HOME/.systemd-env" | grep -v "^PATH=")
        fi
        echo "Existential crisis"
    fi
    

    運行 sudo visudo 命令,把以下內(nèi)容復(fù)制粘貼到文件末尾:

    Defaults        env_keep += WSLPATH
    Defaults        env_keep += WSLENV
    Defaults        env_keep += WSL_INTEROP
    Defaults        env_keep += WSL_DISTRO_NAME
    Defaults        env_keep += PRE_NAMESPACE_PATH
    %sudo ALL=(ALL) NOPASSWD: /usr/sbin/enter-systemd-namespace
    

    添加剛才的 shell 腳本到 .bashrc榔昔, 運行以下命令即可:

    sudo sed -i 2a"# Start or enter a PID namespace in WSL2\nsource /usr/sbin/start-systemd-namespace\n" /etc/bash.bashrc
    

    最后驹闰,設(shè)置 Windows 環(huán)境變量,用管理員權(quán)限打開 powershell撒会,運行以下命令:

    cmd.exe /C setx WSLENV BASH_ENV/u
    cmd.exe /C setx BASH_ENV /etc/bash.bashrc
    # 關(guān)閉WSL
    wsl --shutdown
    

    點擊 開始菜單 上的 Ubuntu 應(yīng)用嘹朗,重新打開 WSL,正常進(jìn)入命令行界面說明操作成功诵肛。

啟動失敗powershell 執(zhí)行以下命令即可恢復(fù) wsl 到正常狀態(tài)

```powsershell
wsl -e sudo mv /etc/bash.bashrc /opt/bash.bashrc
```

重新進(jìn)入 `wsl` 后屹培,打開 `/opt/bash.bashrc` ,將上一步添加的兩行內(nèi)容如下刪除:

```sh
# Start or enter a PID namespace in WSL2
  source /usr/sbin/start-systemd-namespace
```
再把 `/opt/bash.bashrc` 放回 `/etc/` 目錄下怔檩,重走安裝 `daemonize` 流程

進(jìn)入正題

安裝 docker

移除舊版本docker

sudo apt-get remove docker docker-engine docker.io containerd runc

安裝docker

# 更新軟件索引
sudo apt-get update

# 安裝必備軟件
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

# 安裝 apt-key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 添加 repository
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

# 更新軟件索引
sudo apt-get update

# 安裝docker
sudo apt-get install docker-ce docker-ce-cli containerd.io

# 檢驗docker是否安裝成功
sudo docker run hello-world

配置 docker

使用 root 權(quán)限創(chuàng)建 '/etc/docker/daemon.json' 文件褪秀,并填寫以下內(nèi)容:

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
}

重啟 docker

sudo systemctl daemon-reload
sudo systemctl start docker

安裝 kubernetes

添加 apt-key.gpg 步驟可能需要梯子,可以通過手動下載 apt-key.gpg薛训,再用這個命令 cat /mnt/c/Users/huang/Downloads/apt-key.gpg | sudo apt-key add - 媒吗,/mnt/c/ 表示掛載 C盤,后面加上 apt-key.gpg 所在目錄

sudo apt-get update && sudo apt-get install -y apt-transport-https curl
# 添加apt-key.gpg步驟可能需要梯子
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

啟動 k8s集群

執(zhí)行 kubeadm init 命令之前乙埃,先下載必要的鏡像闸英,運行以下命令:

kubeadm config images list

得到以下結(jié)果:(冒號后面是鏡像的版本,會根據(jù)kubeadm版本而變化)

k8s.gcr.io/kube-apiserver:v1.18.5
k8s.gcr.io/kube-controller-manager:v1.18.5
k8s.gcr.io/kube-scheduler:v1.18.5
k8s.gcr.io/kube-proxy:v1.18.5
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.7

k8s.gcr.io 鏡像在國內(nèi)多半是拉取失敗的膊爪,所以要把 k8s.gcr.io 前綴換成 gotok8s ,再加上 'docker pull':

docker pull gotok8s/kube-apiserver:v1.18.5
docker pull gotok8s/kube-controller-manager:v1.18.5
docker pull gotok8s/kube-scheduler:v1.18.5
docker pull gotok8s/kube-proxy:v1.18.5
docker pull gotok8s/pause:3.2
docker pull gotok8s/etcd:3.4.3-0
docker pull gotok8s/coredns:1.6.7

逐行執(zhí)行以上命令嚎莉,待全部完成后米酬,再通過 docker tag 命令,把鏡像標(biāo)簽改成 k8s.gcr.io

docker tag gotok8s/kube-apiserver:v1.18.5 k8s.gcr.io/kube-apiserver:v1.18.5
docker tag gotok8s/kube-controller-manager:v1.18.5 k8s.gcr.io/kube-controller-manager:v1.18.5
docker tag gotok8s/kube-scheduler:v1.18.5 k8s.gcr.io/kube-scheduler:v1.18.5
docker tag gotok8s/kube-proxy:v1.18.5 k8s.gcr.io/kube-proxy:v1.18.5
docker tag gotok8s/pause:3.2 k8s.gcr.io/pause:3.2
docker tag gotok8s/etcd:3.4.3-0 k8s.gcr.io/etcd:3.4.3-0
docker tag gotok8s/coredns:1.6.7 k8s.gcr.io/coredns:1.6.7

再執(zhí)行以下命令趋箩,等待數(shù)分鐘后赃额,即可搭建一個標(biāo)準(zhǔn)版 k8s 集群

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 

出現(xiàn)以下命令時加派,說明創(chuàng)建 k8s 集群成功,再按照提示執(zhí)行以下命令:(如果創(chuàng)建集群失敗跳芳,通過運行 sudo kubeadm reset芍锦,然后輸入 Y 即可清除 kubeadm init 命令的操作)

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

最后一步,通過 kubectl apply 命令飞盆,安裝 CNI 插件娄琉,這里以 calico 為例:

kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml

通過 kubectl get node 命令獲取 node 節(jié)點的狀態(tài)是否 ready

NAME              STATUS   ROLES    AGE     VERSION
desktop-v6hkp49   Ready    master   2m24s   v1.18.5

壓軸環(huán)節(jié)

部署 spring cloud 集群

這里 spring cloud 示例源碼是本人18年學(xué)習(xí) spring cloud的demo,相關(guān)代碼已經(jīng)上傳到 Github

下載源碼構(gòu)建

git clone https://github.com/zaoying/datacenter.git

使用其他編程語言的項目也是可以的吓歇,只需要加上 prometheus 對應(yīng)的 sdk

Spring Boot 為例孽水,pom.xml 文件添加 ``

<project

    <properties>
    ...
    <!-- 使用tomcat作為servlet容器,請確保版本在8.5.32 以上 -->
        <tomcat.version>8.5.32</tomcat.version>
    ...
    </properties>>
  ...
    <dependencies>
    ...
        <!-- Micrometer Prometheus registry  -->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
    ...
    </dependencies>
</project>

修改配置文件 application.yml城看,增加以下內(nèi)容:

management:
  endpoints:
    web:
      exposure:
        include: "*"
    health:
      show-details: always
  metrics:
    tags:
      application: ${spring.application.name}

建議把 eureka 以及其他微服務(wù)組件的鏡像寫到同一個 Pod 中運行女气,各組件直接就可以通過 localhost 直接進(jìn)行通信

使用 maven 打包成jar

maven 環(huán)境的搭建不細(xì)說,以下命令可以在 Windows 上運行

# 切換到 datacenter 所在目錄
cd datacenter

# 構(gòu)建并打包eureka
cd eureka
mvn package -Dmaven.test.skip=true

# 構(gòu)建并打包school
cd school
mvn package -Dmaven.test.skip=true

# 構(gòu)建并打包teacher
cd teacher
mvn package -Dmaven.test.skip=true

# 構(gòu)建并打包student
cd student
mvn package -Dmaven.test.skip=true

使用 docker 打包鏡像

這里使用 WSL2 里面安裝的 docker 打包鏡像测柠。假設(shè)項目所在路徑是 c:/Users/huang/Documents/github炼鞠。

eurekaschool轰胁、teacherstudent 目錄下都寫好 Dockerfile谒主,以 eureka 為例:

FROM openjdk:8u242-jre-slim
COPY target/eureka-0.0.1-SNAPSHOT.jar ./app.jar
CMD java -jar app.jar

其他微服務(wù)模塊的 Dockerfile 也類似,把 eureka-0.0.1-SNAPSHOT.jar 替換成 xxx-0.0.1-SNAPSHOT.jar 即可软吐,xxx 就是微服務(wù)模塊的名稱瘩将。

Dockerfile 都編寫完成后,運行以下命令打包 Docker 鏡像

# 打包eureka鏡像
docker build -t datacenter-eureka:latest /mnt/c/Users/huang/Documents/github/datacenter/eureka

# 打包school鏡像
docker build -t datacenter-school:latest /mnt/c/Users/huang/Documents/github/datacenter/school

# 打包teacher鏡像
docker build -t datacenter-teacher:latest /mnt/c/Users/huang/Documents/github/datacenter/teacher

# 打包student鏡像
docker build -t datacenter-student:latest /mnt/c/Users/huang/Documents/github/datacenter/student

部署并初始化 mysql

為了方便管理凹耙,先創(chuàng)建一個新的 namespace姿现,名字就叫 spring-cloud

kubectl create namespace spring-cloud

mysql 有官方鏡像,直接拿過來使用即可肖抱,不用重新打包备典。另外因為 mysql 是個有狀態(tài)應(yīng)用,為了避免Pod重啟導(dǎo)致數(shù)據(jù)丟失意述,所以在運行之前提佣,需要先分配一個 Persistent VolumePersistent Volume Claim

kind: PersistentVolume
apiVersion: v1
metadata:
  name: mysql-pv-volume
  namespace: spring-cloud
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/opt/data/mysql"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  namespace: spring-cloud
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

可以根據(jù)實際情況,把 /opt/data/mysql 換成其他目錄荤崇,PVPVC 的大小也可以調(diào)整為其他大小拌屏,就目前的demo而已,2Gi 容量已經(jīng)足夠了术荤。

將上述內(nèi)容保存到 pvc.yml 文件倚喂,然后執(zhí)行 kubectl apply -f 命令創(chuàng)建:

kubectl apply -f pvc.yml

接下來,創(chuàng)建 mysql.yml 文件瓣戚,再將以下內(nèi)容添加到文件內(nèi):

apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: spring-cloud
spec:
  type: NodePort
  ports:
  - name: mysql
    protocol: TCP
    nodePort: 30306
    port: 3306
    targetPort: 3306
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: spring-cloud
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: bocloud@2019
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

還是通過 kubectl apply -f 命令創(chuàng)建 mysqlservicedeployment端圈, 然后同一個 namespacespring-cloud 命令空間的 Pod 就可以通過 mysql:3306 地址訪問 mysql焦读。

kubectl apply -f mysql.yml

通過 kubectl get pod -n spring-cloud 命令,查看 pod 是否 running

NAME                              READY   STATUS    RESTARTS   AGE
mysql-85bcfd68f6-qxmcj            0/1     Pending   0          4m59s

使用 kubectl descibe pod mysql-85bcfd68f6-qxmcj -n spring-cloud 查看舱权,發(fā)現(xiàn)以下原因:

Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  14s (x4 over 104s)  default-scheduler  0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.

說明 pod 不能在控制面 control panel 運行矗晃,可以通過以下命令解決:

kubectl taint nodes --all node-role.kubernetes.io/master-

編寫 datacenter.yml 并部署

創(chuàng)建 datacenter.yml 文件,并把以下內(nèi)容添加到文件內(nèi):

apiVersion: v1
kind: Service
metadata:
  name: datacenter
  namespace: spring-cloud
spec:
  ports:
    - name: eureka
      protocol: TCP
      port: 8761
      targetPort: 8761
      nodePort: 30761
    - name: school
      protocol: TCP
      port: 8084
      targetPort: 8084
      nodePort: 30084
    - name: teacher
      protocol: TCP
      port: 8082
      targetPort: 8082
      nodePort: 30082
    - name: student
      protocol: TCP
      port: 8083
      targetPort: 8083
      nodePort: 30083
  selector:
    app: datacenter
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: datacenter-dep
  namespace: spring-cloud
  labels:
    app: datacenter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: datacenter
  template:
    metadata:
      labels:
        app: datacenter
    spec:
      containers:
      - name: eureka
        image: datacenter-eureka:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8761
      - name: school
        image: datacenter-school:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: MYSQL_ADDRESS
          value: mysql:3306
        - name: MYSQL_PASSWORD
          value: bocloud@2019
        ports:
        - containerPort: 8084
      - name: teacher
        image: datacenter-teacher:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: MYSQL_ADDRESS
          value: mysql:3306
        - name: MYSQL_PASSWORD
          value: bocloud@2019
        ports:
        - containerPort: 8082
      - name: student
        image: datacenter-student:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: MYSQL_ADDRESS
          value: mysql:3306
        - name: MYSQL_PASSWORD
          value: bocloud@2019
        ports:
        - containerPort: 8083

運行以下命令宴倍,即可創(chuàng)建 datacenterservicedeployment张症,同一個 namespacePod 可以通過 datacenter:8761datacenter:8084啊楚、datacenter:8082吠冤、datacenter:8083 來分別訪問 eurekaschool恭理、teacherstudent 服務(wù)拯辙。

kubectl apply -f pvc.yml

部署 prometheusgrafana

為了方便管理,先創(chuàng)建 prometheus-k8snamespace

kubectl create namespace prometheus-k8s

然后颜价,再創(chuàng)建一個 configmap 來保存 prometheus 的配置:

# my global config
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9090']
  - job_name: 'school'
    metrics_path: "/actuator/prometheus"
    static_configs:
    - targets: ['datacenter.spring-cloud:8084']
  - job_name: 'teacher'
    metrics_path: "/actuator/prometheus"
    static_configs:
    - targets: ['datacenter.spring-cloud:8082']
  - job_name: 'student'
    metrics_path: "/actuator/prometheus"
    static_configs:
    - targets: ['datacenter.spring-cloud:8083']

然后把文件保存為 prometheus.yml涯保,再運行以下命令:

kubectl create configmap prometheus-config -n prometheus-k8s --from-file prometheus.yml

接著,創(chuàng)建 prometheusservicedeployment

apiVersion: v1
kind: Service
metadata:
  name: prometheus
  namespace: prometheus-k8s
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    nodePort: 30909
    port: 9090
    targetPort: 9090
  selector:
    app: prometheus
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: prometheus-k8s
spec:
  selector:
    matchLabels:
      app: prometheus
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - image: prom/prometheus
        name: prometheus
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9090
          name: http
        volumeMounts:
        - name: prometheus-config
          mountPath: /etc/prometheus/
      volumes:
      - name: prometheus-config
        configMap:
          name: prometheus-config
          items:
           - key: prometheus.yml
             path: prometheus.yml

把上述內(nèi)容保存為 serviceAndDeployment.yml 文件周伦,再運行以下命令:

kubectl apply -f serviceAndDeployment.yml

接著夕春,創(chuàng)建 grafanaservicedeployment

apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: prometheus-k8s
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    nodePort: 30009
    port: 3000
    targetPort: 3000
  selector:
    app: grafana
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: prometheus-k8s
spec:
  selector:
    matchLabels:
      app: grafana
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
      - image: grafana/grafana
        name: grafana
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000
          name: http

把上述內(nèi)容保存為 serviceAndDeployment-grafana.yml 文件,再運行以下命令:

kubectl apply -f serviceAndDeployment-grafana.yml

創(chuàng)建 ingress

創(chuàng)建 ingress-nginx-controller专挪,這里用到 hostNetwork及志,所以會占用宿主機(jī)的 80443 端口

kubectl apply -f https://raw.githubusercontent.com/zaoying/k8s-learning/master/nginx/mandatory.yaml

創(chuàng)建 ingress-nginx 服務(wù)

kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  externalTrafficPolicy: Local
  type: NodePort
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https

把以上內(nèi)容保存為 service-node-port.yml,再運行 kubectl apply -f service-node-port.yml 寨腔。

接著為 grafana 創(chuàng)建 tls secret速侈,信息可以隨便填

openssl genrsa -aes128 -out server.key 2048

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 3650 -out server.crt

kubectl create secret tls prometheus-secret-tls --cert=server.crt --key=server.key -n prometheus-k8s

把以下內(nèi)容保存到 ingress.yml,再運行 kubectl apply -f ingress.yml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: grafana
  namespace: prometheus-k8s
  annotations:
    nginx.ingress.kubernetes.io/ingress.class: nginx
spec:
  tls:
  - hosts:
    - grafana.local
    secretName: prometheus-secret-tls
  rules:
  - host: grafana.local
    http:
      paths:
      - path: /
        backend:
          serviceName: grafana
          servicePort: 3000

127.0.0.1 grafana.local 追加到 C:\Windows\System32\drivers\etc\hosts 文件末迫卢。

配置 grafana

  1. 在瀏覽器打開 https://grafana.local 就可以看到 grafana 網(wǎng)頁倚搬,因為是自簽名 tls 證書,所以瀏覽器會警告乾蛤,忽略警告每界。
grafana
  1. 輸入 admin/admin 登錄,然后修改密碼
datasource
  1. 點擊 Add your first data source家卖,選擇 prometheus 眨层,填寫 http://prometheus:9090 ,然后點擊 Save & Test 保存上荡。
import-dashboard
  1. 點擊 +趴樱,選擇 import,輸入 4701,點擊 Load
import
  1. prometheus 列選擇 prometheus伊佃, 然后點擊 import
jvm-micrometer
  1. 重復(fù)步驟 4-5,把 4701 換成 6756
spring-boot-statistic

至此沛善,本教程結(jié)束航揉!

參考文章:

安裝適用于 Linux 的 Windows 子系統(tǒng)

Running Snaps on WSL2 (Insiders only for now)

Install Docker Engine on Ubuntu

Creating a single control-plane cluster with kubeadm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市金刁,隨后出現(xiàn)的幾起案子帅涂,更是在濱河造成了極大的恐慌,老刑警劉巖尤蛮,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件媳友,死亡現(xiàn)場離奇詭異,居然都是意外死亡产捞,警方通過查閱死者的電腦和手機(jī)醇锚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坯临,“玉大人焊唬,你說我怎么就攤上這事】纯浚” “怎么了赶促?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挟炬。 經(jīng)常有香客問我鸥滨,道長,這世上最難降的妖魔是什么谤祖? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任婿滓,我火速辦了婚禮,結(jié)果婚禮上泊脐,老公的妹妹穿的比我還像新娘空幻。我一直安慰自己,他們只是感情好容客,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布秕铛。 她就那樣靜靜地躺著,像睡著了一般缩挑。 火紅的嫁衣襯著肌膚如雪但两。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天供置,我揣著相機(jī)與錄音谨湘,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛紧阔,可吹牛的內(nèi)容都是我干的坊罢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼擅耽,長吁一口氣:“原來是場噩夢啊……” “哼活孩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起乖仇,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤憾儒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后乃沙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體起趾,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年警儒,在試婚紗的時候發(fā)現(xiàn)自己被綠了训裆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜀铲,死狀恐怖缭保,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝙茶,我是刑警寧澤艺骂,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站隆夯,受9級特大地震影響钳恕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蹄衷,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一忧额、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愧口,春花似錦睦番、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至厚骗,卻和暖如春示启,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背领舰。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工夫嗓, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留迟螺,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓舍咖,卻偏偏與公主長得像矩父,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子排霉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355