寫在前面
最近在研究K8S,今天就輸出部分研究成果吧,後續也會持續更新。
叢集規劃
IP | 主機名 | 節點 | 作業系統版本 |
---|---|---|---|
192.168.175.101 | binghe101 | Master | CentOS 8.0.1905 |
192.168.175.102 | binghe102 | Worker | CentOS 8.0.1905 |
192.168.175.103 | binghe103 | Worker | CentOS 8.0.1905 |
基礎配置
在三臺伺服器上的/etc/hosts檔案中新增如下配置項。
192.168.175.101 binghe101
192.168.175.102 binghe102
192.168.175.103 binghe103
檢查系統環境
分別在三臺伺服器上檢查系統的環境。
1.檢視伺服器作業系統版本
cat /etc/redhat-release
安裝Docker和K8S叢集的伺服器作業系統版本需要在CentOS 7以上。
2.檢視伺服器的主機名
hostname
注意:叢集中伺服器的主機名不能是localhost。
3.檢視伺服器的CPU核數
lscpu
注意:叢集中伺服器的CPU核數不能少於2個。
4.檢視伺服器網路
以binghe101(Master)伺服器為例。在伺服器上執行 ip route show
命令來檢視伺服器的預設網路卡,如下所示。
[root@binghe101 ~]# ip route show
default via 192.168.175.2 dev ens33 proto static metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.175.0/24 dev ens33 proto kernel scope link src 192.168.175.101 metric 100
在上面的輸出資訊中有如下一行標註了binghe101伺服器所使用的預設網路卡。
default via 192.168.175.2 dev ens33 proto static metric 100
可以看到,binghe101伺服器使用的預設網路卡為ens33。
接下來,使用ip address
命令檢視伺服器的IP地址,如下所示。
[root@binghe101 ~]# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:68:06:63 brd ff:ff:ff:ff:ff:ff
inet 192.168.175.101/24 brd 192.168.175.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::890f:5a92:4171:2a11/64 scope link noprefixroute
valid_lft forever preferred_lft forever
可以看到,binghe101伺服器上的預設網路卡的IP地址為192.168.175.101
,K8S將使用此 IP 地址與叢集內的其他節點通訊。叢集中所有K8S所使用的IP地址必須可以互通。
Docker安裝
分別在三臺伺服器上安裝Docker並配置阿里雲映象加速器。
1.安裝Docker
新建auto_install_docker.sh指令碼檔案
vim auto_install_docker.sh
檔案的內容如下所示。
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
dnf install yum*
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf install https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
yum install docker-ce docker-ce-cli -y
systemctl enable docker.service
systemctl start docker.service
docker version
或者指定Docker的版本進行安裝,此時auto_install_docker.sh指令碼檔案的內容如下所示。
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
dnf install yum*
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
yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io
systemctl enable docker.service
systemctl start docker.service
docker version
使用如下命令賦予auto_install_docker.sh檔案可執行許可權。
chmod a+x ./auto_install_docker.sh
接下來,直接執行auto_install_docker.sh指令碼檔案安裝Docker即可。
./auto_install_docker.sh
2.配置阿里雲映象加速器
新建指令碼檔案aliyun_docker_images.sh。
vim aliyun_docker_images.sh
檔案內容如下所示。
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
為aliyun_docker_images.sh指令碼檔案賦予可執行許可權,如下所示。
chmod a+x ./aliyun_docker_images.sh
執行aliyun_docker_images.sh指令碼檔案配置阿里雲映象加速器。
./aliyun_docker_images.sh
系統設定
分別在三臺伺服器上進行系統設定。
1.安裝nfs-utils
yum install -y nfs-utils
yum install -y wget
2.關閉防火牆
systemctl stop firewalld
systemctl disable firewalld
3.關閉 SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
4.關閉 swap
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
5.修改 /etc/sysctl.conf
新建sys_config.sh指令碼檔案。
vim sys_config.sh
sys_config.sh指令碼檔案的內容如下所示,
# 如果有配置,則修改
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
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=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
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
# 執行命令以應用
sysctl -p
執行如下命令賦予sys_config.sh檔案可執行許可權。
chmod a+x ./sys_config.sh
執行sys_config.sh指令碼檔案。
./sys_config.sh
安裝K8S
分別在三臺伺服器上安裝K8S。
1.配置K8S yum源
新建k8s_yum.sh指令碼檔案。
vim k8s_yum.sh
檔案的內容如下所示。
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[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
賦予k8s_yum.sh指令碼檔案的可執行許可權。
chmod a+x ./k8s_yum.sh
執行k8s_yum.sh檔案。
./k8s_yum.sh
2.解除安裝舊版本的K8S
yum remove -y kubelet kubeadm kubectl
3.安裝kubelet、kubeadm、kubectl
yum install -y kubelet-1.18.2 kubeadm-1.18.2 kubectl-1.18.2
4.修改docker Cgroup Driver為systemd
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
5.重啟 docker,並啟動 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet
綜合安裝指令碼
綜上,上述安裝Docker、進行系統設定,安裝K8S的操作可以統一成auto_install_docker_k8s.sh指令碼。指令碼的內容如下所示。
#安裝Docker 19.03.8
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
dnf install yum*
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
yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io
systemctl enable docker.service
systemctl start docker.service
docker version
#配置阿里雲映象加速器
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
#安裝nfs-utils
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
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=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
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
# 執行命令以應用
sysctl -p
# 配置K8S的yum源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[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
# 解除安裝舊版本K8S
yum remove -y kubelet kubeadm kubectl
# 安裝kubelet、kubeadm、kubectl,這裡我安裝的是1.18.2版本,你也可以安裝1.17.2版本
yum install -y kubelet-1.18.2 kubeadm-1.18.2 kubectl-1.18.2
# 修改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 ${REGISTRY_MIRROR}
# 重啟 docker,並啟動 kubelet
systemctl daemon-reload
systemctl restart docker
systemctl enable kubelet && systemctl start kubelet
docker version
注意:我安裝的K8S版本是1.18.2,大家在安裝K8S時,也可以選擇其他版本進行安裝
賦予auto_install_docker_k8s.sh指令碼檔案可執行許可權。
chmod a+x ./auto_install_docker_k8s.sh
執行auto_install_docker_k8s.sh指令碼檔案。
./auto_install_docker_k8s.sh
注意:需要在每臺伺服器上執行auto_install_docker_k8s.sh指令碼檔案。
初始化Master節點
只在binghe101伺服器上執行的操作。
1.初始化Master節點的網路環境
# 只在 master 節點執行
# export 命令只在當前 shell 會話中有效,開啟新的 shell 視窗後,如果要繼續安裝過程,請重新執行此處的 export 命令
export MASTER_IP=192.168.175.101
# 替換 k8s.master 為 您想要的 dnsName
export APISERVER_NAME=k8s.master
# Kubernetes 容器組所在的網段,該網段安裝完成後,由 kubernetes 建立,事先並不存在於您的物理網路中
export POD_SUBNET=172.18.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
2.初始化Master節點
在binghe101伺服器上建立init_master.sh指令碼檔案,檔案內容如下所示。
#!/bin/bash
# 指令碼出錯時終止執行
set -e
if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
echo -e "\033[31;1m請確保您已經設定了環境變數 POD_SUBNET 和 APISERVER_NAME \033[0m"
echo 當前POD_SUBNET=$POD_SUBNET
echo 當前APISERVER_NAME=$APISERVER_NAME
exit 1
fi
# 檢視完整配置選項 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
rm -f ./kubeadm-config.yaml
cat <<EOF > ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.2
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
serviceSubnet: "10.96.0.0/16"
podSubnet: "${POD_SUBNET}"
dnsDomain: "cluster.local"
EOF
# kubeadm init
# 根據您伺服器網速的情況,您需要等候 3 - 10 分鐘
kubeadm init --config=kubeadm-config.yaml --upload-certs
# 配置 kubectl
rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config
# 安裝 calico 網路外掛
# 參考文件 https://docs.projectcalico.org/v3.13/getting-started/kubernetes/self-managed-onprem/onpremises
echo "安裝calico-3.13.1"
rm -f calico-3.13.1.yaml
wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
kubectl apply -f calico-3.13.1.yaml
賦予init_master.sh指令碼檔案可執行許可權。
chmod a+x ./init_master.sh
執行init_master.sh指令碼檔案。
./init_master.sh
3.檢視Master節點的初始化結果
(1)確保所有容器組處於Running狀態
# 執行如下命令,等待 3-10 分鐘,直到所有的容器組處於 Running 狀態
watch kubectl get pod -n kube-system -o wide
如下所示。
[root@binghe101 ~]# watch kubectl get pod -n kube-system -o wide
Every 2.0s: kubectl get pod -n kube-system -o wide binghe101: Sat May 2 23:40:33 2020
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-kube-controllers-5b8b769fcd-l2tmm 1/1 Running 0 3m59s 172.18.203.67 binghe101 <none> <none>
calico-node-8krsl 1/1 Running 0 3m59s 192.168.175.101 binghe101 <none> <none>
coredns-546565776c-rd2zr 1/1 Running 0 3m59s 172.18.203.66 binghe101 <none> <none>
coredns-546565776c-x8r7l 1/1 Running 0 3m59s 172.18.203.65 binghe101 <none> <none>
etcd-binghe101 1/1 Running 0 4m14s 192.168.175.101 binghe101 <none> <none>
kube-apiserver-binghe101 1/1 Running 0 4m14s 192.168.175.101 binghe101 <none> <none>
kube-controller-manager-binghe101 1/1 Running 0 4m14s 192.168.175.101 binghe101 <none> <none>
kube-proxy-qnffb 1/1 Running 0 3m59s 192.168.175.101 binghe101 <none> <none>
kube-scheduler-binghe101 1/1 Running 0 4m14s 192.168.175.101 binghe101 <none> <none>
(2) 檢視 Master 節點初始化結果
kubectl get nodes -o wide
如下所示。
[root@binghe101 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
binghe101 Ready master 5m43s v1.18.2 192.168.175.101 <none> CentOS Linux 8 (Core) 4.18.0-80.el8.x86_64 docker://19.3.8
初始化Worker節點
1.獲取join命令引數
在Master節點上執行如下命令獲取join命令引數。
kubeadm token create --print-join-command
具體執行如下所示。
[root@binghe101 ~]# kubeadm token create --print-join-command
W0502 23:44:55.218947 59318 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
kubeadm join k8s.master:6443 --token s0hoh1.2cwyf1fyyjl2h04a --discovery-token-ca-cert-hash sha256:6d78e360dc64d84762611ac6beec8ac0f0fe9f72a5c2cca008df949e07827c19
其中,有如下一行輸出。
kubeadm join k8s.master:6443 --token s0hoh1.2cwyf1fyyjl2h04a --discovery-token-ca-cert-hash sha256:6d78e360dc64d84762611ac6beec8ac0f0fe9f72a5c2cca008df949e07827c19
這行程式碼就是獲取到的join命令。
注意:join命令中的token的有效時間為 2 個小時,2小時內,可以使用此 token 初始化任意數量的 worker 節點。
2.初始化Worker節點
針對所有的 worker 節點執行,在這裡,就是在binghe102伺服器和binghe103伺服器上執行。
建立init_worker.sh指令碼檔案,檔案內容如下所示。
# 只在 worker 節點執行
# 192.168.175.101 為 master 節點的內網 IP
export MASTER_IP=192.168.175.101
# 替換 k8s.master 為初始化 master 節點時所使用的 APISERVER_NAME
export APISERVER_NAME=k8s.master
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 替換為 master 節點上 kubeadm token create 命令輸出的join
kubeadm join k8s.master:6443 --token s0hoh1.2cwyf1fyyjl2h04a --discovery-token-ca-cert-hash sha256:6d78e360dc64d84762611ac6beec8ac0f0fe9f72a5c2cca008df949e07827c19
其中,kubeadm join...就是master 節點上 kubeadm token create 命令輸出的join。
賦予init_worker.sh指令碼檔案檔案可執行許可權,並執行init_worker.sh指令碼檔案。
chmod a+x ./init_worker.sh
./init_worker.sh
3.檢視初始化結果
在Master節點執行如下命令檢視初始化結果。
kubectl get nodes -o wide
如下所示。
[root@binghe101 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
binghe101 Ready master 20m v1.18.2
binghe102 Ready <none> 2m46s v1.18.2
binghe103 Ready <none> 2m46s v1.18.2
注意:kubectl get nodes命令後面加上-o wide引數可以輸出更多的資訊。
重啟K8S叢集引起的問題
1.Worker節點故障不能啟動
Master 節點的 IP 地址發生變化,導致 worker 節點不能啟動。需要重新安裝K8S叢集,並確保所有節點都有固定的內網 IP 地址。
2.Pod崩潰或不能正常訪問
重啟伺服器後使用如下命令檢視Pod的執行狀態。
kubectl get pods --all-namespaces
發現很多 Pod 不在 Running 狀態,此時,需要使用如下命令刪除執行不正常的Pod。
kubectl delete pod <pod-name> -n <pod-namespece>
注意:如果Pod 是使用 Deployment、StatefulSet 等控制器建立的,K8S 將建立新的 Pod 作為替代,重新啟動的 Pod 通常能夠正常工作。
寫在最後
如果覺得文章對你有點幫助,請微信搜尋並關注「 冰河技術 」微信公眾號,跟冰河學習各種程式設計技術。
最後附上K8S最全知識圖譜連結:
祝大家在學習K8S時,少走彎路。