09-基于Kubernetes v1.25.0和Docker部署集群

  • Post author:
  • Post category:其他




1.1 Kubernetes 组件

在这里插入图片描述

Kubernetes提供了三个特定功能的接口,kubernetes通过调用这几个接口,来完成相应的功能。

  • 容器运行时接口CRI: Container Runtime Interface

    kubernetes 对于容器的解决方案,只是预留了容器接口,只要符合CRI标准的解决方案都可以使用
  • 容器网络接口CNI: Container Network Interface

    kubernetes 对于网络的解决方案,只是预留了网络接口,只要符合CNI标准的解决方案都可以使用
  • 容器存储接口CSI: Container Storage Interface

    kubernetes 对于存储的解决方案,只是预留了存储接口,只要符合CSI标准的解决方案都可以使用

    此接口非必须



1.2 k8s集群拓扑图

在这里插入图片描述



1.3 准备环境



1.3.1 机器环境

  • 每个主机2G内存以上,2核CPU以上
  • OS: Ubuntu 20.04.5 LTS
  • Kubernetes:v1.25,0
  • Container Runtime: Docker CE 20.10.12
  • CRI:cri-dockerd v0.2.5.3



1.3.2 节点环境

ip地址 主机名称 角色
10.0.0.70 kubeapi.lec.org 指定控制平面的固定访问地址
10.0.0.70 master1.lec.org K8s 集群主节点 1,Master和etcd
10.0.0.71 node1.lec.org K8s 集群工作节点 1
10.0.0.72 node2.lec.org K8s 集群工作节点 2
10.0.0.73 node3.lec.org K8s 集群工作节点 3



1.4 基于Kubeadm 实现 Kubernetes v1.25.0集群部署流程说明

  • 每个节点主机的初始环境准备
  • 在所有Master和Node节点都安装docker容器运行时,实际Kubernetes只使用其中的Containerd
  • 在所有Master和Node节点安装kubeadm 、kubelet、kubectl
  • 在所有节点安装和配置 cri-dockerd
  • 在第一个 master 节点运行 kubeadm init 初始化命令 ,并验证 master 节点状态
  • 在第一个 master 节点生成 kubectl 命令的授权文件
  • 实现 kubectl 命令补全
  • 在第一个 master 节点安装配置网络插件
  • 在其它master节点运行kubeadm join 命令加入到控制平面集群中(多个master需要这一步)
  • 在所有 node 节点使用 kubeadm join 命令加入集群
  • 创建 pod 并启动容器测试访问 ,并测试网络通信



1.5 基于Kubeadm 部署 Kubernetes v1.25.0高可用集群案例



1.5.1 每个节点主机的初始环境准备



1.5.1.1 配置 ssh key 验证

配置 ssh key 验证,方便后续同步文件

master1上

ssh-keygen

# 将公钥文件传给其他机器
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.0.0.71
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.0.0.72
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.0.0.73



1.5.1.2 设置主机名和解析

# master1上
hostnamectl set-hostname master1.lec.org

cat >> /etc/hosts <<EOF

10.0.0.70 master1.lec.org  
10.0.0.70 kubeapi.lec.org
10.0.0.71 node1.lec.org    
10.0.0.72 node2.lec.org    
10.0.0.73 node3.lec.org    


EOF

# 拷贝到其他node上
for i in {71..73};do scp /etc/hosts 10.0.0.$i:/etc/ ;done

# node1上
hostnamectl set-hostname node1.lec.org

# node2上
hostnamectl set-hostname node2.lec.org

# node3上
hostnamectl set-hostname node3.lec.org



1.5.1.3 禁用 swap

sed -i '/swap/s/^/#/' /etc/fstab;swapoff -a 



1.5.1.4 禁用 时区同步

# 借助于chronyd服务(程序包名称chrony)设定各节点时间精确同步
apt -y install chrony
chronyc sources -v

# 时区同步
timedatectl set-timezone Asia/Shanghai



1.5.1.5 禁用 防火墙

#禁用默认配置的iptables防火墙服务
ufw disable
ufw status

root@master1:~# ufw status
Status: inactive
#如果是inactive表示已经关闭,如果是active表示已经启动



1.5.2 所有Master和Node节点都安装docker

#Ubuntu20.04可以利用内置仓库安装docker
# 4台机器都要安装
apt update
apt -y install docker.io


# master1上
# docker镜像加速
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://reg-mirror.qiniu.com",
"https://registry.docker-cn.com"
],
"exec-opts": ["native.cgroupdriver=systemd"] 
}
EOF

# 将镜像加速配置文件拷贝到node节点机器上
for i in {71..73};do scp /etc/docker/daemon.json 10.0.0.$i:/etc/docker/ ;done

# 四台都要启动docker
systemctl restart docker.service



1.5.3 所有Master和Node节点安装kubeadm 、kubelet、kubectl

通过国内镜像站点阿里云安装的参考链接:

https://developer.aliyun.com/mirror/kubernetes
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -

cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

apt-get update

# 查看版本
apt-cache madison kubeadm |head

# 安装指定版本
apt install -y  kubeadm=1.25.0-00 kubelet=1.25.0-00 kubectl=1.25.0-00

# 安装最新版本
apt-get install -y kubelet kubeadm kubectl



1.5.4 所有Master和Node节点安装和配置cri-dockerd

  • Kubernetes-v1.24之前版本无需安装cri-dockerd

    查看kubeadm之前的相关镜像,
root@master1:~# kubeadm config images list --kubernetes-version=v1.25.0
registry.k8s.io/kube-apiserver:v1.25.0
registry.k8s.io/kube-controller-manager:v1.25.0
registry.k8s.io/kube-scheduler:v1.25.0
registry.k8s.io/kube-proxy:v1.25.0
registry.k8s.io/pause:3.8
registry.k8s.io/etcd:3.5.4-0
registry.k8s.io/coredns/coredns:v1.9.3

转换成阿里云镜像

registry.aliyuncs.com/google_containers/kube-apiserver:v1.25.0
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.25.0
registry.aliyuncs.com/google_containers/kube-scheduler:v1.25.0
registry.aliyuncs.com/google_containers/kube-proxy:v1.25.0
registry.aliyuncs.com/google_containers/pause:3.8
registry.aliyuncs.com/google_containers/etcd:3.5.4-0
registry.aliyuncs.com/google_containers/coredns/coredns:v1.9.3



1.5.4.1 安装cri-dockerd

curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.5/cri-dockerd_0.2.5.3-0.ubuntu-focal_amd64.deb

dpkg -i cri-dockerd_0.2.5.3-0.ubuntu-focal_amd64.deb



1.5.4.2 配置cri-dockerd并启动

    sed -i '/^ExecStart/s#$# --pod-infra-container-image registry.aliyuncs.com/google_containers/pause:3.7#'   /usr/lib/systemd/system/cri-docker.service
 
# 加载并启动
systemctl daemon-reload ;systemctl restart cri-docker.service

如果不配置,会出现下面日志提示

Aug 21 01:35:17 ubuntu2004 kubelet[6791]: E0821 01:35:17.999712    6791 remote_runtime.go:212] "RunPodSandbox from runtime service f
ailed" err="rpc error: code = Unknown desc = failed pulling image 
\"k8s.gcr.io/pause:3.6\": Error response from daemon: Get \"https:
//k8s.gcr.io/v2/\": net/http: request canceled while waiting for connection 
(Client.Timeout exceeded while awaiting headers)"



1.5.5 在第一个 master 节点初始化 Kubernetes 集群

多个master主机情况下进行的初始化

kubeadm init \
--control-plane-endpoint="kubeapi.lec.org" \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.25.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--token-ttl=0 \
--upload-certs \
--ignore-preflight-errors=Swap

单个个master主机情况下进行的初始化

kubeadm init \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.25.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--token-ttl=0 \
--upload-certs \
--ignore-preflight-errors=Swap

kubeadm init 命令参考说明

--control-plane-endpoint 
# 多主节点必选项,用于指定控制平面的固定访问地址,可是IP地址或DNS名称,
# 会被用于集群管理员及集群组件的kubeconfig配置文件的API Server的访问地址
# 如果是单主节点的控制平面部署时不使用该选项,注意:kubeadm 不支持将没有 
# --control-plane-endpoint 参数的单个控制平面集群转换为高可用性集群。

--image-repository string 
#设置镜像仓库地址,默认为 k8s.gcr.io,此地址国内可能无法访问,可以指向国内的镜像地址。
# 如指向阿里云--image-repository=registry.aliyuncs.com/google_containers
--kubernetes-version
#kubernetes程序组件的版本号,它必须要与安装的kubelet程序包的版本号相同
--service-cidr
#Service的网络地址范围,其值为CIDR格式的网络地址,默认为10.96.0.0/12;
#通常,仅Flannel一类的网络插件需要手动指定该地址
--pod-network-cidr
#Pod网络的地址范围,其值为CIDR格式的网络地址,通常情况下Flannel网络插件的默认为10.244.0.0/16,
#Calico网络插件的默认值为192.168.0.0/16

--cri-socket
#v1.24版之后指定连接cri的socket文件路径,注意;不同的CRI连接文件不同
#如果是cRI是containerd,则使用--cri-socket unix:///run/containerd/containerd.sock
#如果是cRI是docker,则使用--cri-socket unix:///var/run/cri-dockerd.sock
#如果是CRI是CRI-o,则使用--cri-socket unix:///var/run/crio/crio.sock
#注意:CRI-o与containerd的容器管理机制不一样,所以镜像文件不能通用。
--ignore-preflight-errors=Swap
#若各节点未禁用Swap设备,还需附加选项“从而让kubeadm忽略该错误

--upload-certs #将控制平面证书上传到 kubeadm-certs Secret
--token-ttl 
#共享令牌(token)的过期时长,默认为24小时,0表示永不过期;
#为防止不安全存储等原因导致的令牌泄露危及集群安全,建议为其设定过期时长。
#未设定该选项时,在token过期后,若期望再向集群中加入其它节点,
#可以使用如下命令重新创建token,并生成节点加入命令。
# kubeadm token create --print-join-command

kubeadm init \
--control-plane-endpoint="kubeapi.lec.org" \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.25.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--token-ttl=0 \
--upload-certs \
--ignore-preflight-errors=Swap

# 初始化结果
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join kubeapi.lec.org:6443 --token szbs8d.x5l6h9om8ewxbmyw \
        --discovery-token-ca-cert-hash sha256:5018f6733cc016a6ac2b51848e80ac269ae945ab3e58883ed6d97d66e2440959 \
        --control-plane 

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join kubeapi.lec.org:6443 --token szbs8d.x5l6h9om8ewxbmyw \
        --discovery-token-ca-cert-hash sha256:5018f6733cc016a6ac2b51848e80ac269ae945ab3e58883ed6d97d66e2440959 

多master的时候,控制平面挂在本机但是没有绑定本机,需要修改环境变量

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

报错内容参考

The connection to the server localhost:8080 was refused - did you specify the right host or port? 

解决方法

#直接追加文件内容
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
#然后使生效
source /etc/profile
  • 重置节点方法(退出集群方法)
kubeadm reset --cri-socket unix:///run/cri-dockerd.sock
rm -rf /etc/kubernetes/ /var/lib/kubelet /var/lib/dockershim /var/run/kubernetes /var/lib/cni /etc/cni/net.d



1.5.6 在第一个 master 节点生成 kubectl 命令的授权文件

#可复制1.5.5初始化的结果执行下面命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config



1.5.7 实现 kubectl 命令补全

# 实现kubectl命令自动补全功能    
kubectl completion bash > /etc/profile.d/kubectl_completion.sh



1.5.8 在第一个 master 节点配置网络组件

Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有

flannel、calico、canal和kube-router等,简单易用的实现是为CoreOS提供的flannel项目。

  • 下载flanneld的地址为 https://github.com/flannel-io/flannel/releases
#默认没有网络插件,所以显示如下状态

root@master1:~# kubectl get nodes
NAME              STATUS   ROLES           AGE     VERSION
master1.lec.org   NotReady    control-plane   6m18s   v1.25.0

# 配置网络插件
root@master1:~# ls -lrt kube-flannel-v0.19.1.yml 
-rw-r--r-- 1 root root 4583 Jan 16 14:10 kube-flannel-v0.19.1.yml

root@master1:~# kubectl apply -f kube-flannel-v0.19.1.yml 
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

# 稍等一会再吃查看

```bash
root@master1:~# kubectl get nodes
NAME              STATUS   ROLES           AGE     VERSION
master1.lec.org   Ready    control-plane   6m18s   v1.25.0



1.5.9 其它master节点加入到控制平面集群(多个master需要这一步)

  • 在其它master节点运行kubeadm join 命令加入到控制平面集群中(多个master需要这一步)
#可复制1.5.5初始化的结果执行下面命令

root@master2:~# kubeadm join kubeapi.lec.org:6443 --token szbs8d.x5l6h9om8ewxbmyw \
        --discovery-token-ca-cert-hash sha256:5018f6733cc016a6ac2b51848e80ac269ae945ab3e58883ed6d97d66e2440959 \
        --control-plane \
        --cri-socket=unix:///var/run/cri-dockerd.sock

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



1.5.10 其它工作节点(node节点)加入集群

  • master初始化的时候加入了参数 –control-plane-endpoint
#可复制1.5.5初始化的结果执行下面命令

kubeadm join kubeapi.lec.org:6443 --token szbs8d.x5l6h9om8ewxbmyw \
        --discovery-token-ca-cert-hash  sha256:5018f6733cc016a6ac2b51848e80ac269ae945ab3e58883ed6d97d66e2440959 \
        --cri-socket=unix:///var/run/cri-dockerd.sock
  • master初始化的时候没有加入了参数 –control-plane-endpoint
kubeadm join 10.0.0.70:6443 --token 82ft5w.q1h1w8dclom3vr1y \
        --discovery-token-ca-cert-hash sha256:ec2818d2f956dd01d0eb84b785835e17fea431b37d78a1626f7d4c1db71c672d 
        --cri-socket=unix:///var/run/cri-dockerd.sock
  • 可以将镜像导出到其它worker节点实现加速
[root@node1 ~]#docker image save `docker image ls --format "{{.Repository}}:{{.Tag}}"` -o k8s-images-v1.25.0.tar
[root@node1 ~]#gzip k8s-images-v1.25.0.tar
[root@node1 ~]#scp k8s-images-v1.25.0.tar.gz 10.0.0.72:/root/
[root@node1 ~]#scp k8s-images-v1.25.0.tar.gz 10.0.0.73:/root/
# node2上面导入
[root@node2 ~]#docker load -i k8s-images-v1.25.0.tar.gz
  • 查看所有节点是否都Ready
# master1上
root@master1:~# kubectl get nodes
NAME              STATUS   ROLES           AGE     VERSION
master1.lec.org   Ready    control-plane   120m    v1.25.0
node1.lec.org     Ready    <none>          46m     v1.25.0
node2.lec.org     Ready    <none>          2m25s   v1.25.0
node3.lec.org     Ready    <none>          45s     v1.25.0



1.5.11 创建 pod 并启动容器测试访问,并测试网络通信

demoapp是一个web应用,可将demoapp以Pod的形式编排运行于集群之上,并通过在集群外部进行访问:



1.5.11.1 测试方法一

root@master1:~# kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 --replicas=3
deployment.apps/demoapp created

# 查看pod信息
root@master1:~# kubectl get pod -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE            NOMINATED NODE   READINESS GATES
demoapp-55c5f88dcb-222tb   1/1     Running   0          14m   10.244.3.3   node3.lec.org   <none>           <none>
demoapp-55c5f88dcb-m8lhr   1/1     Running   0          14m   10.244.2.2   node2.lec.org   <none>           <none>
demoapp-55c5f88dcb-s7kz7   1/1     Running   0          14m   10.244.1.2   node1.lec.org   <none>           <none>
  • 遇见的错误一:pod的status是ImagePullBackOff

在这里插入图片描述

解决方法:

在node机器上重启kubelet

systemctl restart  kubelet



1.5.11.2 测试方法二

创建Service对象来demoapp使用的NodePort

#创建service

root@master1:~# kubectl create service nodeport demoapp --tcp=80:80
service/demoapp created

#查看service的ip
root@master1:~# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
demoapp      NodePort    10.99.176.30   <none>        80:31983/TCP   9s
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        137m

# 测试访问service的ip
root@master1:~# curl 10.99.176.30
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-55c5f88dcb-m8lhr, ServerIP: 10.244.2.2!
root@master1:~# curl 10.99.176.30
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-55c5f88dcb-222tb, ServerIP: 10.244.3.3!
root@master1:~# curl 10.99.176.30
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-55c5f88dcb-m8lhr, ServerIP: 10.244.2.2!
root@master1:~# curl 10.99.176.30
iKubernetes demoapp v1.0 !! ClientIP: 10.244.0.0, ServerName: demoapp-55c5f88dcb-s7kz7, ServerIP: 10.244.1.2!



1.5.11.3 扩容和缩容

# 扩容
# 扩容到5个node

root@master1:~# kubectl scale deployment demoapp --replicas 5
deployment.apps/demoapp scaled
root@master1:~# kubectl get pod -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE            NOMINATED NODE   READINESS GATES
demoapp-55c5f88dcb-222tb   1/1     Running   0          19m   10.244.3.3   node3.lec.org   <none>           <none>
demoapp-55c5f88dcb-f59jd   1/1     Running   0          8s    10.244.2.3   node2.lec.org   <none>           <none>
demoapp-55c5f88dcb-m8lhr   1/1     Running   0          19m   10.244.2.2   node2.lec.org   <none>           <none>
demoapp-55c5f88dcb-pr7j5   1/1     Running   0          8s    10.244.1.3   node1.lec.org   <none>           <none>
demoapp-55c5f88dcb-s7kz7   1/1     Running   0          19m   10.244.1.2   node1.lec.org   <none>           <none>


# 缩容

root@master1:~# kubectl scale deployment demoapp --replicas 2
deployment.apps/demoapp scaled

#销毁过程 STATUS为Terminating   
root@master1:~# kubectl get pod -o wide
NAME                       READY   STATUS        RESTARTS   AGE   IP           NODE            NOMINATED NODE   READINESS GATES
demoapp-55c5f88dcb-222tb   1/1     Running       0          20m   10.244.3.3   node3.lec.org   <none>           <none>
demoapp-55c5f88dcb-f59jd   1/1     Terminating   0          39s   10.244.2.3   node2.lec.org   <none>           <none>
demoapp-55c5f88dcb-m8lhr   1/1     Terminating   0          20m   10.244.2.2   node2.lec.org   <none>           <none>
demoapp-55c5f88dcb-pr7j5   1/1     Terminating   0          39s   10.244.1.3   node1.lec.org   <none>           <none>
demoapp-55c5f88dcb-s7kz7   1/1     Running       0          20m   10.244.1.2   node1.lec.org   <none>           <none>

#最终结果
root@master1:~# kubectl get pod -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE            NOMINATED NODE   READINESS GATES
demoapp-55c5f88dcb-222tb   1/1     Running   0          20m   10.244.3.3   node3.lec.org   <none>           <none>
demoapp-55c5f88dcb-s7kz7   1/1     Running   0          20m   10.244.1.2   node1.lec.org   <none>           <none>





版权声明:本文为Wsjm666原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。