记录Kubernetes的安装过程和踩坑

记录了Kubernetes的安装流程以及出现过的错误和解决方法。
记录Kubernetes的安装过程和踩坑
Photo by J Lee / Unsplash

On this page

一、环境架构

在VMware上准备了三台虚拟机,用于搭建k8s集群,其结构如下:

  • k8s-master:
    2核4GB;IP: 10.0.0.100; 部署:etcd, kube-apiserver, kube-controller-manager, kubectl, kubeadm, kubelet, kube-proxy, flannel
  • k8s-slave1:
    2核2GB;IP: 10.0.0.101; 部署:kubectl, kubelet, kube-proxy, flannel,docker
  • k8s-slave2:
    2核2GB;IP: 10.0.0.102; 部署:kubectl, kubelet, kube-proxy, flannel,docker

二、环境初始化

为所有机器配置hosts解析

10.0.0.100 k8s-master
10.0.0.101 k8s-slave1
10.0.0.102 k8s-slave2

关闭swap

POD的内存管理策略中通常给每个POD分配一个固定的内存量,如果POD的使用内存超过可用内存,则该POD会被强制终止;开启swap后,当可用内存不足时,一部分硬盘空间会被临时用来当成内存使用,但硬盘的性能毕竟和内存差了不止一点,这样会导致性能大幅度下降,同时也可能会引起当POD超过可用内存后转而使用Sawp空间,但由于性能太底下而导致程序夯住,因此一般关掉,这也是官方的建议

swapoff -a

要永久关闭,还要编辑 /etc/fstab 文件,将有swap的那一行注释掉。

关闭SELinux,Firewalld并清空iptables规则

关闭SELinux:
编辑 /etc/selinux/config ,设置SELINUX=disabled

关闭防火墙服务:

systemctl stop firewalld && systemctl disable firewalld

清空iptables规则

iptables -F && iptables -X && iptables -Z

使用chronyd确保时间同步正确

hwclock -w

修改内核参数,开启数据包转发功能

cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
vm.max_map_count=262144
EOF
modprobe br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf

安装docker

配置docker软件源

curl -o /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装

yum install docker-ce-19.03.15 docker-ce-cli-19.03.15 -y

配置cgroup驱动

mkdir -p /etc/docker

cat > /etc/docker/daemon.json <<'EOF'
{
    "exec-opts":["native.cgroupdriver=systemd"]
}
EOF

验证:

docker info |grep -i cgroup

结果应该是: Cgroup Driver: systemd

三、安装kubeadm工具(master和slave节点都安装)

启用kubernetes软件源

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

重新生成缓存

yum clean all && yum makecache

查看并安装指定软件版本

yum list kubeadm –showduplicates
yum install kubelet-1.19.3 kubeadm-1.19.3 kubectl-1.19.3 ipvsadm -y

启动并设置问开机自启

systemctl start kubelet && systemctl enable kubelet

四、初始化Master主节点

初始化集群

kubeadm init \
–apiserver-advertise-address=10.0.0.100 \
–image-repository registry.aliyuncs.com/google_containers \
–kubernetes-version v1.19.3 \
–service-cidr=10.1.0.0/16 \
–pod-network-cidr=10.2.0.0/16 \
–service-dns-domain=cluster.local \
–ignore-preflight-errors=Swap \
–ignore-preflight-errors=NumCPU

参数解释:

  • –apiserver-advertise-address=10.0.0.100 \ API-Server地址,一般也就是master主机的地址
  • –image-repository registry.aliyuncs.com/google_containers \ 镜像仓库地址,在国内可以用这个,在国外没必要
  • –kubernetes-version v1.19.3 \ k8s版本
  • –service-cidr=10.1.0.0/16 \ clusterIP k8s服务发现网段,也就是service网段
  • –pod-network-cidr=10.2.0.0/16 \ podIP网段(pod创建后的运行网段)
  • –service-dns-domain=cluster.local \ 集群内dns后缀
  • –ignore-preflight-errors=Swap \ 忽略swap报错
  • –ignore-preflight-errors=NumCPU 忽略CPU报错

上面的初始化完成后会产生大段的结果日志,主要关注最后提示的kubeadm join命令,Kubernetes Node节点需要使用这行命令来加入集群。

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
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 10.0.0.100:6443 –token 04ysh6.s4h4wnzbov9eq1z4 \
–discovery-token-ca-cert-hash 
sha256:f7263afe295687ad5ea02ad328a8eeee76c7b8625b4861ba2476ba0997fc432b

创建k8s集群配置文件

根据上面的提示,我们可以创建k8s集群配置文件(指定了默认的SSL证书存储位置,api-server的地址等)

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

接下来,看看端口都被那些k8s的那些组件占领了

port.png

到此为止k8s就算是大概装好了,可以使用以下命令查看k8s集群状态

kubectl get nodes -owide

结果应该是Master Status NotReady,这是因为还没部署网络插件

五、部署Flannel网络插件(master)

部署flannel使master机器和slave机器互联,允许获取状态并将容器远程部署到slave主机上。

下载flannel

git clone –depth 1 https://github.com/coreos/flannel.git

修改网络插件信息

编辑flannel/Documentation/kube-flannel.yml文件,修改下面的部分:

net-conf.json: |
{
    “Network”: “10.2.0.0/16”,
    “Backend”: {
    “Type”: “vxlan”
    }
}

Network,即Master初始化时–pod-network-cidr参数对应的值。

containers:
    – name: kube-flannel
    image: docker.io/flannel/flannel:v0.22.1
    command:
        – /opt/bin/flanneld
    args:
        – –ip-masq
        – –kube-subnet-mgr
        – –iface=网卡名

指定对外访问的网卡,如果有多块网卡但没有指定,则会自动使用第一个网卡

基于kubectl命令,应用这个yml文件,读取并创建这个POD资源

kubectl create -f ./kube-flannel.yml 

成功创建flannel POD后,可以发现所有的Node机器上都有flannel的容器

因为kubectl create是像api-server发起创建POD的请求,之后flannel的配置信息被写入到etcd数据库中;由于slave节点上的kubelet进程一直在监听etcd,因此当etcd有更新时,两个slave立即进行了同步。

六、将k8s-slave节点加入集群

在k8s-slave节点上输入下面的命令

kubeadm join 10.0.0.100:6443 –token 04ysh6.s4h4wnzbov9eq1z4 \
–discovery-token-ca-cert-hash sha256:f7263afe295687ad5ea02ad328a8eeee76c7b8625b4861ba2476ba0997fc432b

之后master和slave节点就进入了ready状态
status.png

七、测试:运行一个Nginx POD

创建:

kubectl run test-nginx –image=nginx:1.20.1

查看:

kubectl get pods -owide

最后可以发现,这个容器被部署在了k8s-slave2机器上;使用docker ps可以发现kubenetes为这个容器创建了一个POD根容器和一个nginx容器

containers.png

目前因为没有端口映射等配置,所以只能使用curl命令去访问

curl.png

修改index文件:

kubectl exec test-nginx — sh -c “echo ‘Hello World’ > /usr/share/nginx/html/index.html”

curl1.png

到这里kubernetes就正式完成安装和初始化工作了

八、中间出现的问题和解决方法

kubelet服务无法启动

kubelet服务一直是auto-restart状态,原因在于没有关闭交换内存,输入 swapoff -a 后成功启动。

Master初始化失败

因为kubelet没有启动,所以导致失败;成功启动kubelet后仍然失败,这是因为在先前失败的初始化操作时已经为Kubernetes创建了一些配置文件,因为已经有存在的配置文件,所有无法初始化。
解决方法:
使用kubeadm reset命令重置kubeadm配置文件。

九、Kubernetes命令自动补全

yum install bash-completion -y
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc