嗨!這個最有深度的『研究筆記』由程序員界最會排版の追星族運營
2020年
2月4日
kubernetesv1.17集群生態搭建筆記
小編:Lateautumn4lin(逆向小小小學生)
![kubernetesv1.17集群生态搭建笔记](http://p2.ttnews.xyz/loading.gif)
前言
上一次接觸到kubernetes集群的時候已經是一年以前了,那個時候官方的版本還只是<code>v1.10/<code>,而現在過去一年的時間了,官方版本已經快速的迭代到了<code>v1.17/<code>了,社區也越來越成熟、相關的生態組件也越來越豐富,可見在過去的<code>K8S元年/<code>,它發展是多麼迅猛。最近想把自己寫的一些小東西封裝成開放API暴露出來,於是想把自己的幾臺機器搞成個kubernetes集群,所以這裡想重溫下集群構建的流程。以下的所有文件都可以在Github<code>https://github.com/lateautumn4lin/KubernetesResearch/<code>的<code>ClusterEcology目錄/<code>中尋找到
kubernetes集群搭建實戰
首先要做的是搭建一個最基本的Kubernetes集群。
準備階段
準備階段主要包括兩個方面,一是準備好至少兩臺機器,做master-worker的集群架構,二是瞭解我們需要安裝好哪些軟件才能構建最基本的集群。
1. 機器配置
這次實驗我選用的是騰訊雲的雲服務器<code>CVM/<code>,由於我是通過不同的賬號購買的,所以我選用的機器之間是通過外網來進行互通,配置方面的話選擇官方默認的最低配置<code>2核4GB/<code>。
<table><thead>2. 軟件配置
<table><thead>基本的軟件我們需要安裝Kubernetes與Docker,安裝Kubernetes我們需要使用到其中的Kubeadm與Kubectl工具,Kubeadm是官方推薦的初始化工具,並且在v1.13版本中已經正式GA(General Availability)了,也就是說可以在生產環境中使用。而需要Docker是因為Kubernetes中的Pod需要使用到CRI(Container Runtime),也就是容器運行時,Docker是非常標準且通用的CRI,其他的例如Containerd、CRI-O並且在v1.14版本之後如果你的機器中有多種CRI,那麼Kubernetes也會默認使用Docker的,所以我們這裡就選擇Docker。
檢查與配置階段
這個階段我們主要是檢查我們的服務器配置以及把我們幾個服務器給串聯起來。
1. 修改Hostname,配置Host文件
使用hostnamectl分別對worker1和master1進行hostname的永久性修改,並且配置host,之所以這麼做是因為我們要統一給各個機器標記,這樣我們在之後的集群管理中能夠更好的通過hostname瞭解每臺機器的作用。
<code>hostnamectl set-hostname master1
echo "127.0.0.1 $(hostname)" >> /etc/hosts
echo "192.144.152.23 master1" >> /etc/hosts
echo "49.233.81.20 worker1" >> /etc/hosts
/<code>
2. 檢查CPU核數與內存
這一步我們使用lscpu命令來查看我們的服務器的架構以及我們系統的內核數,因為我們要搭建一個Kubernetes集群,master節點不能低於2核,這點是必須要保證的,如果內核數過低會導致整個集群的不穩定和高延遲。
<code>lscpu
# 請使用 lscpu 命令,核對 CPU 信息
# Architecture: x86_64 本安裝文檔不支持 arm 架構
# CPU(s): 2 CPU 內核數量不能低於 2
/<code>
3. 檢查網絡
在所有節點執行命令
<code>[root@master1 ~]# ip route show
default via 172.21.0.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.21.0.0/20 dev eth0 proto kernel scope link src 172.21.0.11
[root@master1 ~]# ip address
1: lo: <loopback> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <broadcast> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:2c:42:7d brd ff:ff:ff:ff:ff:ff
inet 172.21.0.11/20 brd 172.21.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe2c:427d/64 scope link
valid_lft forever preferred_lft forever
/<broadcast>/<loopback>/<code>
3.1 kubelet使用的IP地址
ip route show 命令中,可以知道機器的默認網卡,通常是 <code>eth0/<code>,如<code>default via 172.21.0.1 dev eth0/<code>
ip address 命令中,可顯示默認網卡的 IP 地址,Kubernetes 將使用此 IP 地址與集群內的其他節點通信,如 <code>172.21.0.11/<code>
所有節點上 Kubernetes 所使用的 IP 地址必須可以互通(無需 NAT 映射、無安全組或防火牆隔離)
如果兩臺機器是在共同的內網中可以使用<code>內網IP/<code>進行直接通信,不過我們這次的機器是在兩個不同的騰訊雲賬號之中,彼此內網隔離,所以我們直接使用機器的<code>外網IP/<code>進行通信,不建議大家在生產環境中使用。
4. 配置機器之間的免登錄
這一步我們要通過配置各機器之間的免登錄打通各個機器,把各個機器串聯起來,這樣方便於我們之後在各臺機器之間的操作。
4.1 每臺服務器生成公私鑰
<code>ssh-keygen –t rsa
/<code>
4.2 將id_rsa.pub追加到授權的key裡面去
<code>cat id_rsa.pub >> authorized_keys
/<code>
4.3 修改.ssh文件夾和其文件的權限,並重啟SSH服務
<code>chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
service sshd restart
/<code>
4.4 將.ssh文件夾中三個文件拷貝到目標服務器
<code>scp ~/.ssh/authorized_keys [email protected]:~/.ssh/
scp ~/.ssh/id* [email protected]:~/.ssh/
/<code>
上面是兩臺機器之間如何進行免登錄配置,同理可以用於其他某兩臺機器。
正式安裝階段
準備好上面的機器並且檢查、配置好各個參數之後我們就可以開始正式安裝了。
1. 安裝Kubelet以及Docker
切換到ClusterEcology目錄中,可以看到install_kubelet.sh腳本,使用如下命令快速安裝。
<code>cat install_kubelet.sh | sh -s 1.17.2
/<code>
我們快速看看這個腳本中的代碼,瞭解具體每一步的作用
<code>#!/bin/bash
# 在 master 節點和 worker 節點都要執行
# 安裝 docker
# 參考文檔如下
# https://docs.docker.com/install/linux/docker-ce/centos/
# https://docs.docker.com/install/linux/linux-postinstall/
# 卸載舊版本
yum remove -y docker \\
docker-client \\
docker-client-latest \\
docker-common \\
docker-latest \\
docker-latest-logrotate \\
docker-logrotate \\
docker-selinux \\
docker-engine-selinux \\
docker-engine
# 設置 yum repository
yum install -y yum-utils \\
device-mapper-persistent-data \\
lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安裝並啟動 docker
yum install -y docker-ce-18.09.7 docker-ce-cli-18.09.7 containerd.io
systemctl enable docker
systemctl start docker
# 安裝 nfs-utils
# 必須先安裝 nfs-utils 才能掛載 nfs 網絡存儲
yum install -y nfs-utils
yum install -y wget
# 關閉 防火牆
systemctl stop firewalld
systemctl disable firewalld
# 關閉 SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
# 關閉 swap
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
# 修改 /etc/sysctl.conf
# 如果有配置,則修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf
# 可能沒有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
# 執行命令以應用
sysctl -p
# 配置K8S的yum源
cat </etc/yum.repos.d/kubernetes.repo /<code>
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 卸載舊版本
yum remove -y kubelet kubeadm kubectl
# 安裝kubelet、kubeadm、kubectl
yum install -y kubelet-${1} kubeadm-${1} kubectl-${1}
# 修改docker Cgroup Driver為systemd
# # 將/usr/lib/systemd/system/docker.service文件中的這一行 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# # 修改為 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# 如果不修改,在添加 worker 節點時可能會碰到如下錯誤
# [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
# Please follow the guide at https://kubernetes.io/docs/setup/cri/
sed -i "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g" /usr/lib/systemd/system/docker.service
# 設置 docker 鏡像,提高 docker 鏡像下載速度和穩定性
# 如果您訪問 https://hub.docker.io 速度非常穩定,亦可以跳過這個步驟
curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s https://registry.cn-hangzhou.aliyuncs.com
# 重啟 docker,並啟動 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet
docker version
執行如上的命令之後,如果執行正確的話我們會得到Docker的版本信息
<code>Client:
Version: 18.09.7
API version: 1.39
Go version: go1.10.8
Git commit: 2d0083d
Built: Thu Jun 27 17:56:06 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.7
API version: 1.39 (minimum version 1.12)
Go version: go1.10.8
Git commit: 2d0083d
Built: Thu Jun 27 17:26:28 2019
OS/Arch: linux/amd64
Experimental: false
/<code>
2. 初始化 master 節點
切換到ClusterEcology目錄中,可以看到init_master.sh腳本,我們首先配置好環境變量,然後使用執行腳本快速安裝。
<code># 只在 master 節點執行
# 替換 x.x.x.x 為 master 節點實際 IP(生產請使用內網 IP)
# export 命令只在當前 shell 會話中有效,開啟新的 shell 窗口後,如果要繼續安裝過程,請重新執行此處的 export 命令
export MASTER_IP=192.144.152.23
# 替換 apiserver.demo 為 您想要的 dnsName
export APISERVER_NAME=apiserver.demo
# Kubernetes 容器組所在的網段,該網段安裝完成後,由 kubernetes 創建,事先並不存在於您的物理網絡中
export POD_SUBNET=10.100.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
cat init_master.sh | sh -s 1.17.2
/<code>
3. 檢查 master 初始化結果
上一步安裝好之後我們要檢驗Kubernetes集群的成果,按下面的命令進行執行。
<code># 只在 master 節點執行
# 執行如下命令,等待 3-10 分鐘,直到所有的容器組處於 Running 狀態
watch kubectl get pod -n kube-system -o wide
# 查看 master 節點初始化結果
kubectl get nodes -o wide
/<code>
如果成功的話可以看到以下輸出
<code>[root@master1 dashboard]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master1 Ready master 7h26m v1.17.2 172.21.0.11 <none> CentOS Linux 7 (Core) 3.10.0-862.el7.x86_64 docker://18.9.7
/<none>/<code>
表示我們的集群中master節點已經正式可用
4. 獲得 join命令參數
下面我們要將我們的其餘worker節點加入集群,worker加入集群需要得到整個集群的token和ca證書,我們首先需要在master節點上面去獲取,包括加入的token和ca證書。
<code>kubeadm token create --print-join-command
# 我們會得到如下輸出,這是我們加入集群的憑證
kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303
/<code>
5. 初始化 worker節點
針對所有的 worker 節點執行
<code># 只在 master 節點執行
# 替換 x.x.x.x 為 master 節點實際 IP(生產請使用內網 IP)
# export 命令只在當前 shell 會話中有效,開啟新的 shell 窗口後,如果要繼續安裝過程,請重新執行此處的 export 命令
export MASTER_IP=192.144.152.23
# 替換 apiserver.demo 為 您想要的 dnsName
export APISERVER_NAME=apiserver.demo
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 替換為 master 節點上 kubeadm token create 命令的輸出
kubeadm join apiserver.demo:6443 --token mpfjma.4vjjg8flqihor4vt --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303
/<code>
加入之後我們再使用下面的命令來查看worker是否正確加入集群
<code>kubectl get nodes
/<code>
6. 查看集群整體的狀況
查看集群整體狀況只能在master節點執行如下命令
<code>kubectl get nodes -o wide
/<code>
可以看到如下的輸出,集群都Ready就表示節點可用
<code>[root@master1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 Ready master 5m3s v1.17.2
worker1 Ready <none> 2m26s v1.17.2
/<none>/<code>
生態組件構建
安裝好Kubernetes集群之後,我們得到的只是一個最基本的集群,還有很多問題我們沒有解決,比如說我們想要通過可視化的方式通過頁面點擊的方式來操作整個集群,或者說我們想要一個類似於Python中的pip那樣的包管理工具那樣利用類似工具來管理我們部署在Kubernetes集群的應用,再或者我們想要讓我們的集群和外網能夠進行很方便的通信等等,所以這就需要我們利用其它的組件來不斷完善我們的Kubernetes生態。
我們選用的是如下的軟件
<table><thead>1. Dashboard插件
安裝Dashboard是因為它是一個綜合性的管理平臺,也是屬於Kubernetes 的官方項目,具體可以在這個倉庫去看<code>https://github.com/kubernetes/dashboard/<code>,雖然之前Dashboard因為操作不人性化,界面醜而廣泛被人詬病,但是經過Kubernetes Dashboard團隊半年多閉關研發,Dashboardv2.0版本新鮮出爐,界面和操作性也有很大提升,也是官方推薦的管理界面之一。
1.1 Dashboard插件安裝
具體的部署方案我根據官方的方案整理成了幾個Yaml文件,項目都在目錄<code>ClusterEcology/InitDashboard/<code>下面
<code>kubectl apply -f k8s-dashboard-rbac.yaml
kubectl apply -f k8s-dashboard-configmap-secret.yaml
kubectl apply -f k8s-dashboard-deploy.yaml
kubectl apply -f k8s-dashboard-metrics.yaml
kubectl apply -f k8s-dashboard-token.yaml
/<code>
執行好上面的命令之後Dashboard的服務以及用戶基本已經創建好,下面我們需要獲取用戶token來登錄我們的Dashboard
1.2 獲取用戶Token
<code>kubectl describe secret/$(kubectl get secret -n kube-system |grep admin|awk '{print $1}') -n kube-system
/<code>
1.3 檢查服務是否可用
在之前的Yaml文件中設置了NodePort端口為31001和類型為NodePort方式訪問 Dashboard,所以訪問地址:<code>https://192.144.152.23:31001//<code>進入 Kubernetes Dashboard頁面,然後輸入上一步中創建的ServiceAccount的Token進入 Dashboard,可以看到新的Dashboard。
輸入Token我們可以看到Dashboard的界面,如下所示是正常的Dashboard界面
2. Helm組件
<code>Helm/<code>組件的產生也是源於一個關鍵痛點,就是我們雖然已經部署好Kubernetes集群環境,但是每個微服務也得維護一套Yaml文件,而且每個環境下的配置文件也不太一樣,所以想要重新部署新的環境或者做環境移植的成本是真的很高。如果我們能使用類似於yum那樣的工具來安裝我們的應用的話豈不是會方便很多?基於這點,<code>Helm/<code>就誕生了,從此讓Kubernetes集群擁有一個正式的<code>應用市場/<code>。
舊版本Helm整體分為兩個部分,包括Helm Client和Tiller Server,Helm Client主要是用戶命令行工具,負責管理用戶自定義的包文件,而Tiller Server服務接受Client的請求並且解析請求之後與Kubernetes集群進行交互。
而新版本,也就是Helm3之後,Helm移除了Tiller組件,使用Helm命令會直接使用了kubeconfig來與Kubernetes集群通信,這樣就可以做更細粒度的權限控制,這樣方便了完成和使用,另一個好處是Release name範圍縮小至Namespace,這樣就能夠保證不同的NameSpace可以使用相同的Release name。
2.1 Helm Client組件安裝
我們首先要去官網<code>https://github.com/kubernetes/helm/releases/<code>去下載Helm的壓縮包。
解壓後將可執行文件Helm拷貝到/usr/local/bin目錄下即可,這樣Helm客戶端就在這臺機器上安裝完成了。
<code>cp helm /usr/local/bin/
/<code>
2.2 Helm使用
初始化Helm
<code>helm init --client-only --stable-repo-url https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts/
helm repo add incubator https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator/
helm repo add seldon https://storage.googleapis.com/seldon-charts
helm repo update
/<code>
安裝一個最簡單的服務
<code>helm install seldon-core seldon/seldon-core-operator
/<code>
可以看到Helm已經和Kubernetes集群交互從而生成一個seldon-core的服務了
<code>[root@master1 linux-amd64]# helm install seldon-core seldon/seldon-core-operator
NAME: seldon-core
LAST DEPLOYED: Tue Feb 4 22:43:58 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
[root@master1 linux-amd64]# helm list
NAME NAMESPACEREVISIONUPDATED STATUS CHART APP VERSION
seldon-coredefault 1 2020-02-04 22:43:58.232906547 +0800 CSTdeployedseldon-core-operator-1.0.1
/<code>
3. Traefik組件
3.1 Traefik組件安裝
Traefik是另一個Kubernetes集群中必備的組件,可以把它認為是Nginx的替代品,做一個統一網關的管理工具,它的優點也是有幾個方面,比如有漂亮的dashboard 界面、可基於容器標籤進行配置、新添服務簡單,不用像 nginx 一樣複雜配置,並且不用頻繁重啟等等,雖然性能方面和Nginx會有些許差距,但是作為個人使用的話,還是很讓人愛不釋手的。
4. metrics-server插件
<code>metrics-server/<code>是Kubernetes 官方的集群資源利用率信息收集器,是Heapster瘦身後的替代品。metrics-server收集的是集群內由各個節點上kubelet暴露出來的利用率信息,算是集群中基礎的監控信息了,主要是提供給例如調度邏輯等核心系統使用。
<code>git clone https://github.com/kubernetes-incubator/metrics-server.git
cd metrics-server/
kubectl create -f deploy/1.8+/
/<code>
安裝成功後,過一段時間我們就可以在Dashboard中看到具體的監控信息了
疑難故障分析
有關於Kubernetes集群的疑難故障主要分為幾類:
(1)資源調度類
(2)網絡通信類
(3)配置參數類
大多數問題都是圍繞這三點來進行的(不全是,大佬勿噴),下面列舉我這次安裝中某些問題,有些問題在此次安裝中沒有涉及到,所以以後涉及到的話會講解。
1. 節點不允許被調度
我們在安裝過程中會遇到下面這個問題
<code>1 node(s) had taints that the pod didn't tolerate
/<code>
這個表示某個節點被標記為不可調度,這個是K8S官方默認的,因為這個是確保Master節點不會被調度到額外的容器從而消耗資源,不過我們這個實驗中可以設置所有節點允許調度來避免出現這個問題。
<code>kubectl taint nodes --all node-role.kubernetes.io/master-
/<code>
2. 鏡像問題
按照上面的安裝步驟理論上是可以完全正確的部署好K8S集群的,不過安裝速度會根據網速的情況有差異,我在安裝的時候也安裝了一個多小時,原因也是因為鏡像下載的慢,當我們看到某些<code>pod/<code>一直在<code>pending/<code>的時候,我們可以通過如下命令查看具體的情況。
<code>kubectl describe pod calico-node-ndwqv -n kube-system
/<code>
使用到<code>describe/<code>命令來查看具體組件的情況,雖然也可以使用<code>logs/<code>命令來查看,不過不如<code>describe/<code>方便。
3. Chrome 您的連接不是私密連接
創建好Dashboard之後,第一次通過Chrome登錄Dashboard我們會發現報出這個錯誤<code>您的連接不是私密連接/<code>,這個是由於Chrome最新版本的錯誤導致,我們修改啟動參數就可以了。
END
鉄子,“在看”來一個
閱讀更多 心萊科技 的文章