搭建K8S集群(kubeadm篇)

搭建K8S集群(kubeadm篇)

一、K8S概述

K8S是当下最火热的容器运行时编排工具,不仅仅提供了用户应用的容器镜像运行解决方案,还提供了路由网关、水平扩展、多副本容灾等能力。在Kubernetes项目中,master节点由负责api服务的kube-apiserver、负责调度的kube-scheduler、负责编排的kebu-controller-manager三者组成。node节点上,最核心的部分是kubelet组件。kubelet主要负责同容器运行时(比如Docker项目)交互,而交互依赖的是CRI(Container Runtime Interface)的远程调用接口。这个接口定义了容器运行时的各项核心操作。具体的容器运行时,则通过OCI这个容器标准,把CRI请求翻译成对Linux系统的底层调用。
话不多说,我们用最简单的方式,即kubeadm来搭建一个K8S集群吧。

二、如何使用kubeadm搭建集群

2.1 机器准备

我们需要准备3台机器,配置是4核8G,提前做好部署规划和网络规划。考虑到云上机器的网络条件较好,我这里用的是腾讯云的机器,读者们也可以使用3台2核4G的机器来完成搭建。
每台机器都需要关闭防火墙,配置好DNS域名解析,并且时间上已配置同步。

  • master节点
  • node1节点
  • node2节点

2.2 准备程序包

由于我们本次使用的是kubeadm工具搭建集群,我们先要下载相关的程序包。但是!由于大中华网络等原因,部分包下载会有问题。那怎么办呢,我们找一台海外的机器来下载这部分程序包即可。
安装kubeadm所需的程序包有以下几个

  • kubelet
  • kubeadm
  • kubectl
  • kubernetes-cni
  • cri-tools
# 安装yum-utils工具,这样我们就可以将包下载到本地
yum install -y yum-utils

# 配置yum源,让我们能够下载相关程序包
cat >> /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=http://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=http://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

# 将相关程序包下载 kubelet kubeadm kubectl kubernetes-cni cri-tools
yumdownloader kubelet kubeadm kubectl kubernetes-cni cri-tools

# 打包这几个rpm程序包,上传到我们的集群机器上去
tar zcf k8s-deploy.tgz *.rpm

备注: 作者知道有些同学可能还没有海外的服务器,这几个服务的包我已经打包好放在网盘上,大家可以直接下载使用。https://share.weiyun.com/g8sbwcWA

2.3 安装kubeadm

我们已经有了相关软件包了,安装就很简单了

# 解压软件包
tar xf k8s-deploy.tgz

# 执行安装
yum localinstall -y *.rpm

2.4 下载镜像

最早期的时候,K8S集群是直接部署在裸金属服务器上面的,这个部署过程有一系列繁琐的操作(如手动生成配置证书等操作),非常的不友好。后面呢大家考虑,既然K8S能力这么强大,那为何不把kube-apiserver、kube-controller-manager、kube-scheduler这些都做成容器镜像,然后通过K8S直接管理起来呢。事实上,kubeadm就是这样做的。但是这里有一点需要注意的是,并不是每个组件都事宜做成容器镜像的,比方说像kubelet。因为kubelet需要与宿主机打交道,比方说配置宿主机网络、存储系统等。假如kubelet是一个容器,那么其运行在自己的Namespace中,是很难对宿主机进行操作的。因此,kubelet是需要手动在宿主机上安装的。
我们开始下载K8S组件的容器镜像,糟糕这里似乎有被大中华的网络拦截了。这里我们就需要依赖阿里云镜像仓库,这里有我们所需的全部镜像,我们可以从阿里云镜像仓库下载镜像,然后打tag将镜像改成kubeadm所需的即可。

# 查看kubeadm部署集群所需的镜像
kubeadm config images list
#k8s.gcr.io/kube-apiserver:v1.23.1
#k8s.gcr.io/kube-controller-manager:v1.23.1
#k8s.gcr.io/kube-scheduler:v1.23.1
#k8s.gcr.io/kube-proxy:v1.23.1
#k8s.gcr.io/pause:3.6
#k8s.gcr.io/etcd:3.5.1-0
#k8s.gcr.io/coredns/coredns:v1.8.6

# 下载所需镜像并修改tag,这里的coredns我们稍后单独处理
for item in `kubeadm config images list | egrep -v "coredns|grep"` ; do image=` echo $item | sed -e "s@k8s.gcr.io@registry.aliyuncs.com/google_containers@g"`; docker pull $image ; docker tag $image `echo $image | sed -e "s@registry.aliyuncs.com/google_containers@k8s.gcr.io@g"` ; docker rmi $image ; done ; 

# 下载coredns镜像
for item in `kubeadm config images list | egrep "coredns" | grep -v grep ` ; do image=` echo $item | sed -e "s@k8s.gcr.io/coredns@registry.aliyuncs.com/google_containers@g"` ; docker pull $image ; docker tag $image `echo $image | sed -e "s@registry.aliyuncs.com/google_containers@k8s.gcr.io/coredns@g"` ; docker rmi $image ; done ; 

# 查看我们下载的所有镜像,此时看看是不是和我们通过kubeadm config images list查询出来的一样啦
docker images

2.5 部署master节点

到了这里,我们就可以使用kubeadm来部署master节点。部署命令非常简单,只需要执行kubeadm init即可。部署完成之后,出现如下提示就说明kubeadm执行完成了。

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/

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

kubeadm join IP:6443 --token ltfaw0.yci1z7zqdrll2ixp \
        --discovery-token-ca-cert-hash sha256:145415d491d67daeb13910ffb49e5a8608863225a13cfdc794b85cc5aca46972 

在这里可能有些同学会碰到kubelet相关的异常,通过执行journalctl -xeu kubelet可以看到,最常见的就是kubelet提示“kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"”,这是什么意思呢?
意思就是说docker使用的cgroup驱动和kubelet使用的驱动不一致,我们知道cgroup全称为Linux Control Group,是用来控制一个进程组使用系统资源的上限。kubelet是通过CRI这个远程调用接口来操作容器运行时(即Docker),驱动不一致会导致相关限制能力无法执行。所以,我们需要修改Docker(建议,当然也可以修改kubelet)的cgroup驱动。具体如下:

# 修改docker的配置文件
cat /etc/docker/daemon.json 
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}

# 内核重新加载进程配置
systemctl daemon-reload

# 重启docker进程
systemctl restart docker

# 检查docker的cgroup驱动
docker info

2.6 部署网络插件

此时我们部署好了K8S集群的master节点,根据输出提示export KUBECONFIG=/etc/kubernetes/admin.conf在机器上执行,然后我们通过kubectl get po -n kube-system检查各个Pod的运行情况。突然发现咋不对劲呢,怎么有些Pod始终处于Pending状态呢?

[root@VM-62-206-centos ~]# kubectl get po -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
coredns-64897985d-9nrqf                    0/1     Pending   0          31s
coredns-64897985d-ms4jr                    0/1     Pending   0          31s
etcd-vm-62-206-centos                      1/1     Running   0          35s
kube-apiserver-vm-62-206-centos            1/1     Running   0          35s
kube-controller-manager-vm-62-206-centos   1/1     Running   0          37s
kube-proxy-zkxln                           1/1     Running   0          31s
kube-scheduler-vm-62-206-centos            1/1     Running   0          35s

其实这是正常的,DNS和什么相关,和网络相关对吧。我们现在都还没有网络插件,肯定是有问题啊。话不多说,我们立马把网络插件部署上去,在这里我们使用的网络插件是weave

# 部署网络插件,非常简单一条命令就可以搞定
# 执行完之后需要等一段时间,因为在下载镜像
kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

这里可能有些同学在部署过程中会碰到,网络插件weave在启动的过程在提示“CrashLoopBackOff”,我们打开日志检查

kubectl logs weave-net-k966t -c weave -n kube-system
# Network 10.32.0.0/12 overlaps with existing route 10.0.0.0/8 on host

我们从这里看到了啥,是不是说weave需要配置10.32.0.0/12这个网段的路由表,但是和现有机器上面的路由表冲突了。怎么办呢,其实比较简单的解决办法是把现有冲突的网段调整一下。调整完之后,我们再打印下Pod运行情况,可以看到Pod全部都正常运行了。

kubectl get po -n kube-system
NAME                                       READY   STATUS    RESTARTS       AGE
coredns-64897985d-9nrqf                    1/1     Running   0              92m
coredns-64897985d-ms4jr                    1/1     Running   0              92m
etcd-vm-62-206-centos                      1/1     Running   0              92m
kube-apiserver-vm-62-206-centos            1/1     Running   0              92m
kube-controller-manager-vm-62-206-centos   1/1     Running   0              92m
kube-proxy-zkxln                           1/1     Running   0              92m
kube-scheduler-vm-62-206-centos            1/1     Running   0              92m
weave-net-k966t                            2/2     Running   11 (21m ago)   59m

2.7 部署node节点

部署node节点比较简单,我们在node节点上面安装好docker-ce、kubeadm、上传相关镜像后,只需要将部署master节点系统提示的命令复制过去即可。

# 执行部署node节点命令
kubeadm join IP:6443 --token ltfaw0.yci1z7zqdrll2ixp --discovery-token-ca-cert-hash sha256:145415d491d67daeb13910ffb49e5a8608863225a13cfdc794b85cc5aca46972 

此时我们等一段时间,等待weave插件在node节点上面安装完成,就可以看到整个集群Pod均运行情况。

kubectl get po -n kube-system
NAME                                       READY   STATUS    RESTARTS       AGE
coredns-64897985d-9nrqf                    1/1     Running   0              130m
coredns-64897985d-ms4jr                    1/1     Running   0              130m
etcd-vm-62-206-centos                      1/1     Running   0              130m
kube-apiserver-vm-62-206-centos            1/1     Running   0              130m
kube-controller-manager-vm-62-206-centos   1/1     Running   0              130m
kube-proxy-ftr7m                           1/1     Running   0              30m
kube-proxy-mcxt5                           1/1     Running   0              29m
kube-proxy-zkxln                           1/1     Running   0              130m
kube-scheduler-vm-62-206-centos            1/1     Running   0              130m
weave-net-9rpsv                            2/2     Running   0              30m
weave-net-dd9nr                            2/2     Running   0              29m
weave-net-k966t                            2/2     Running   11 (58m ago)   97m

2.8 一些收尾工作

到目前为止,我们已经部署好一个非生产环境的K8S集群,做做实验还是绰绰有余的。不过,大家有没有发现,kubectl命令只有在master节点上管用,在其他的node节点似乎不起作用,始终提示“The connection to the server localhost:8080 was refused - did you specify the right host or port?”。这个如何修复呢,其实很简单,我们只需要把master节点的/etc/kubernetes/admin.conf拷贝到node节点的对应位置,在执行export命令即可。

scp /etc/kubernetes/admin.conf root@node_ip:/etc/kubernetes/admin.conf
export KUBECONFIG=/etc/kubernetes/admin.conf

三、控制器模式下运行Pod实例

现在我们已经有了完整可用的K8S集群,我们就开始部署一个简答的Nginx服务吧。

3.1 编写YAML文件

我已经编写好一个最简单的案例文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

3.2 运行应用

我们执行kubectl apply -f nginx.yaml来将我们编写好的YAML提交到K8S,使用apply操作的好处在于,K8S可以自动识别到文件的变化,并根据对象的变化自动执行响应的操作(增加或者减少副本数量、修改应用镜像等)。
过了几分钟,我们可以看到应用顺利运行起来了。

kubectl get po
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-5fcc5d8c6d-6fr2b   1/1     Running   0          12m
nginx-deployment-5fcc5d8c6d-79r2w   1/1     Running   0          11m
posted @ 2021-12-21 11:10  ZimskyZeng  阅读(657)  评论(0编辑  收藏  举报