在学习《kubernets 权威指南》的时候,遇到了kubeadm安装k8s集群的问题。看书过了一遍,感觉似乎并没有啥难点。本来想就不再手动去安装一次了,但纠结了半天,我该死的强迫症还是让我又回头手动搭建了一次。这一搭建才发现,原来坑还是挺多的,所以就把自己的搭建过程写了下来,供学习交流使用。

1.环境初始化(每个节点都要安装)

1.1 安装并配置docker

1.1.1 docker安装

参考docker安装安装docker

1.1.2 配置cgroup driver

为啥要配置cgroup driver?因为使用systemd作为init system的Linux的发行版,使用systemd作为docker的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定。
编辑/etc/docker/daemon.json文件(如果没有则创建),添加如下内容:

{
  "exec-opts": ["native.cgroupdriver=systemd"]
}

1.1.3 配置国内registery

在/etc/docker/daemon.json的json段中,添加如下内容:

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registery-mirrors":["https://http://hub-mirror.c.163.com"]
}

最终如下:

{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registery-mirrors":["https://http://hub-mirror.c.163.com"]
}

1.1.4 启动检查服务

启动docker。

检查cgroup driver是否生效:

docker info |grep Cgroup
    Cgroup Driver: systemd

1.2 初始化主机名和hosts

1.2.1 初始化主机名

有时候,某些服务器的主机名会带一些奇怪的字符串,为了环境更标准,我们非常建议将主机名初始化一下,比如:

hostnamectl set-hostname --static kubadmcli

1.2.2 配置hosts

根据初始化主机名那一步的主机名配置hosts:

172.24.15.212 kubadmcli

注:主机名或者hosts没有的话,可能会出现如下提示:

	[WARNING Hostname]: hostname "kubadmcli.novalocal" could not be reached
	[WARNING Hostname]: hostname "kubadmcli.novalocal": lookup kubadmcli.novalocal on 114.114.114.114:53: no such host

2. 安装配置master节点

2.1 安装kubeadm

2.1.1 配置yum源

在/etc/yum.repos.d/目录下,创建kubernetes.repo文件,添加如下内容:

[kubernetes]
name=kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=0

重建缓存:

yum clean all
yum makecache

2.1.2 安装kubeadm

yum -y install kubelet kubeadm kubectl

注:这里没有指定版本,安装后默认为最新版本。在配置kubeadm config的时候,我们会指定kubernetesVersion的版本。如果指定的版本和这里安装的版本不一致,会出现如下报错:

error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR KubeletVersion]: the kubelet version is higher than the control plane version. This is not a supported version skew and may lead to a malfunctional cluster. Kubelet version: "1.21.0" Control plane version: "1.20.5"
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

所以,我们建议,安装kubelet、kubeadm和kubectl的时候,可以通过如下方式指定版本:

yum -y install kubelet-1.20.5 kubeadm-1.20.5 kubectl-1.20.5

安装完成以后,由于集群还没有建立,所以目前还无法启动kubelet服务。这个和《kubernets权威指南》上是不一样的,指南上是说安装完以后,就可以启动kubelet服务了,但实际不行。我们可以把kubelet服务暂时加入开机启动:

systemctl enable kubelet

2.2 配置kubeadm config

kubeadm config可以如下2种方式:

  • 配置文件方式
  • 命令行传参

2.2.1 配置文件方式

我们可以通过如下方式,获取默认配置:

kubeadm config print init-defaults > init.default.yaml

会在当前目录下生成init.default.yaml文件,内容如下:

apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 1.2.3.4
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: master
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.20.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
scheduler: {}

这里,我们主要关注以下几个内容:

apiVersion: kubeadm.k8s.io/v1beta2
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.20.0
networking:
  serviceSubnet: 10.96.0.0/12

从默认配置中,我们可以看到

  • imageRepository使用的是k8s.gcr.io,我们建议改成国内的镜像站
  • kubernetesVersion使用的是v1.20.0,我们可以改成自己想要的版本
  • networking中只有serviceSubnet,可能我们还关心pod的网络,pod网络可以使用podSubnet指定
2.2.1.1 我们使用如下配置:
apiVersion: kubeadm.k8s.io/v1beta2
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.20.5
networking:
  podSubnet: 192.168.16.0/20
  serviceSubnet: 192.168.0.0/20

2.2.2 命令参数方法

对应到config方式,犹如下几个参数预支对应:

  • –kubernetes-version:指定Kubernetes版本
  • –image-repository:由于kubeadm默认是从官网k8s.grc.io下载所需镜像,国内无法访问,所以这里通过–image-repository指定为163镜像站
  • –pod-network-cidr:指定pod网络段
  • –service-cidr:指定service网络段
  • –ignore-preflight-errors=Swap 将报错信息设置为Swap。当然,如果你环境配置得当,不需要它

命令行参数的方式,需要在下一步kubeadm init的时候一起执行

2.3 拉取镜像

kubeadm config images pull --config=init.yaml

注:这一步在指南上是有的,不过我们也可以不执行,这样在kubeadm init的时候,会自动下载镜像。

结果如下
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.2
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.4.13-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:1.7.0

通过[docker images]查看本地镜像:

[root@master ~]# docker images
REPOSITORY                                                        TAG                 IMAGE ID            CREATED             SIZE
registry.aliyuncs.com/google_containers/kube-proxy                v1.20.5             5384b1650507        2 weeks ago         118MB
registry.aliyuncs.com/google_containers/kube-apiserver            v1.20.5             d7e24aeb3b10        2 weeks ago         122MB
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.20.5             6f0c3da8c99e        2 weeks ago         116MB
registry.aliyuncs.com/google_containers/kube-scheduler            v1.20.5             8d13f1db8bfb        2 weeks ago         47.3MB
registry.aliyuncs.com/google_containers/etcd                      3.4.13-0            0369cf4303ff        7 months ago        253MB
registry.aliyuncs.com/google_containers/coredns                   1.7.0               bfe3a36ebd25        9 months ago        45.2MB
registry.aliyuncs.com/google_containers/pause                     3.2                 80d28bedfe5d        13 months ago       683kB

2.4 初始化master

2.4.1 使用配置文件方式

kubeadm init --config=init.yaml

2.4.2 使用命令行传参方式

kubeadm init --kubernetes-version=v1.20.5 \
             --image-repository=registry.aliyuncs.com/google_containers \
             --pod-network-cidr=192.168.16.0/20 \
             --service-cidr=192.168.0.0/20 \
            #--ignore-preflight-errors=Swap

结果如下:

init] Using Kubernetes version: v1.20.5
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster[certs]
......
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 172.24.14.91:6443 --token yvhauq.sxcuhh300d5vpvhy \
    --discovery-token-ca-cert-hash sha256:439f9df853943ead685dc63d8af0d04c32e7b9b8dc4e148e0fb41dab33997c11

从上述提示中我们可以获得一下信息:

  • initialize successfully说明已经初始化完
  • 集群能被正常用户正常使用,还需要执行提示中所说的内容。
  • kubectl apply -f 可以让我们初始化网插件。支持网络插件可以在给出的url里查到
  • 最后一段包含了后面我们需要使用kubeadm join命令将来node加入到集群所需要token等信息

注:执行完kubeadm init以后,我们会发现,kubelet服务已经正常启动了。如下:

[root@kubeadmcli ~]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: active (running) since Wed 2021-05-12 10:38:33 CST; 7s ago
     Docs: https://kubernetes.io/docs/
 Main PID: 2949 (kubelet)
    Tasks: 18
   Memory: 38.0M
   CGroup: /system.slice/kubelet.service
           └─2949 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --k...

May 12 10:38:34 kubeadmcli kubelet[2949]: I0512 10:38:34.433442    2949 reconciler.go:224] opera...46")
......
May 12 10:38:39 kubeadmcli kubelet[2949]: E0512 10:38:39.213486    2949 kubelet.go:2188] Contain...ized
Hint: Some lines were ellipsized, use -l to show in full.

2.4.3 配置用户环境

以root用户为例,我们在/root/目录下执行如下命令:

#root用的$HOME变量为/root
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

这个时候,我们使用如下命令,查看一下集群节点:

kubectl get nodes

结果如下:

NAME         STATUS     ROLES                  AGE     VERSION
kubeadmcli   NotReady   control-plane,master   3m30s   v1.20.5

从输出中,我们可以发现,STATUS还处于[NotReady]的状态,这是因为我们还没有初始化网络插件

2.5 初始网络插件

以flannel为例,从提示文本中,我们可以看到,支持的网络插件都位于:

https://kubernetes.io/docs/concepts/cluster-administration/addons/

打开以后,我们选择flannel,会跳转到flanne项目的githu地址。我们选择进入到flannel项目的主目录,里面有flannel插件的使用方式。从说明中,我们可以看到**大于1.17**版本的k8s,使用如下yml文件:

https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

注:如果网络不好,可以使用wget或者curl先把yaml文件下载下来,放到本地执行。

注:该yaml配置文件中, 有flannel的image仓库地址。默认为**quay.io/coreos/**,如果自己的网络不通,可以将改地址替换掉:
sed -i ‘s/quay.io\/coreos/registry.aliyuncs.com\/google_containers/g’ flannel.yaml。不过实际情况好像阿里并没有flannel的镜像,可能是我使用的姿势不对,后面慢慢研究吧。好在默认地址是通的。

我们将yml文件保存到本地,名为flannel.yaml。执行如下命令初始化flannel:

kubectl apply -f flannel.yaml

输出如下:

podsecuritypolicy.policy/psp.flannel.unprivileged 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

完成以后,本地镜像会多出来flannel的镜像:

[root@master ~]# docker images
REPOSITORY                                                        TAG                 IMAGE ID            CREATED             SIZE
...
quay.io/coreos/flannel                                            v0.13.1-rc2         dee1cac4dd20        2 months ago        64.3MB
...

这时候,我们再kubectl get nodes会发现,STATUS已经处于[Ready]状态了

NAME         STATUS   ROLES                  AGE    VERSION
kubeadmcli   Ready    control-plane,master   111m   v1.20.5

3 初始化node

3.1 安装kubelet和kubeadm

和主节点不一样的是,node不需要安装kubectl

yum -y install kubelet-1.20.5 kubeadm-1.20.5

3.2 初始化node

和初始化master一样,我们可以通过如下两种方式,来初始化node节点:

  • 使用配置文件方式
  • 命令行传参方式

3.2.1 命令行方式

初始化master节点的时候,从输出信息中,已经给出了初始化node节点的方式:

kubeadm join 172.24.15.212:6443 --token yvhauq.sxcuhh300d5vpvhy \
    --discovery-token-ca-cert-hash sha256:439f9df853943ead685dc63d8af0d04c32e7b9b8dc4e148e0fb41dab33997c11

3.1.2 配置文件方式

同样,我们可以通过kubeadm config print命令输出init node节点的默认配置:

kubeadm config print join-defaults

输出如下:

apiVersion: kubeadm.k8s.io/v1beta2
caCertPath: /etc/kubernetes/pki/ca.crt
discovery:
  bootstrapToken:
    apiServerEndpoint: kube-apiserver:6443
    token: abcdef.0123456789abcdef
    unsafeSkipCAVerification: true
  timeout: 5m0s
  tlsBootstrapToken: abcdef.0123456789abcdef
kind: JoinConfiguration
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: kubeadmclinode02
  taints: null

我们主要关注如下几项,并将apiServerEndpoint、token、tlsBootstrapToken改成master节点信息。

apiVersion: kubeadm.k8s.io/v1beta2
discovery:
  bootstrapToken:
    apiServerEndpoint: 172.24.14.91:6443
    token: yvhauq.sxcuhh300d5vpvhy
    unsafeSkipCAVerification: true
  tlsBootstrapToken: yvhauq.sxcuhh300d5vpvhy
kind: JoinConfiguration

将上述内容保存为init_node.yaml.然后使用如下命令初始化节点:

kubeadm join --config=init_node.yaml

上面两种方法都出现如下输出的时候,说明正确了:

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

此时node上的kubelet也将正常运行。可能这时候你在master上执行[kubelet get nodes]的时候,该node还处于NotReady的状态,别着急,一会就回刷新过来。

4 安装dashboard

以后有时间再说

5 删除节点

如果我们的某个节点出故障了,我们可以将节点剔出集群,剔出集群使用如下命令:

kubectl drain [your-node-name] --delete-local-data --force --ignore-daemonsets
kubectl delete node [your-node-name]

然后在节点上执行:

kubeadm reset

问题

问题1:kubeadm报错:cannot automatically set CgroupDriver when starting the Kubelet: cannot execute ‘docker info -f {{.CgroupDriver}}’: executable file not found in $PATH

kubeadm的架构是:kubeapi、prox、ctl、manager等组件都是使用容器。所以主节点也是需要正确安装容器服务的。并且需要配置容器服务器的cgroup driver。

根据文档CRI installation中的内容,对于使用systemd作为init system的Linux的发行版,使用systemd作为docker的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定,因此这里修改各个节点上docker的cgroup driver为systemd。

解决方法

创建/etc/docker/daemon.json文件,添加如下内容:

{
  "exec-opts": ["native.cgroupdriver=systemd"]
}

注:docker默认使用的cgroup driver为cgroupfs

配置以后,需要重启docker服务。

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

需要配置k8s的用户环境:

#root用的$HOME变量为/root
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐