简介
本文主要目的是为探索学习k8s提供一个简单的环境。学习如何使用kubeadm,在Vagrant管理的虚拟机上,安装一个简易的3节点k8s集群。当然,实际环境的k8s集群不会这么简单,但是从能跑起来的最简安装学起更容易,也能了解k8s的基本组成部分。
1、基础软件安装
k8s软件部分的安装主要是kubelet和kubectl,前者安装于每个节点上,用于连接master节点获取信息,管理Pod,管理容器等。后者为查看、操作k8s的命令行工具。k8s支持多种容器运行环境,这里我们选择熟悉的docker。最后,还需要安装kubeadm,用于构建一个最小化可用的k8s集群,包含了若干最佳化实践的内容。
总之 kubelet kubeadm kubectl docker
这4个软件,就是k8s简易安装需要的内容了。
kubelet 其实就有点像agent,每个节点都需要有,用于连接server。
安装步骤主要参考:https://developer.aliyun.com/mirror/kubernetes
首先是k8s yum源的添加,这里选择阿里云的镜像源,国内安装会快很多。
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
其次是软件的安装和一些配置,这里先把docker和kubelet配置为开机启动。然后关闭SELinux、关闭swap、修改内核参数、关闭防火墙。
## 安装
sudo yum install -y kubelet kubeadm kubectl docker #这里也要安装docker
sudo systemctl enable docker && sudo systemctl start docker #先启动docker
sudo systemctl enable kubelet #这里只配置自动启动,不用实际启动(此时还缺配置文件)
## 配置
sudo setenforce 0 #关闭SELinux
sudo swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab #关闭swap,更改fstab
sudo sysctl net.bridge.bridge-nf-call-iptables=1
sudo systemctl disable firewalld && sudo systemctl stop firewalld #关闭防火墙
需要注意的是,kubelet在安装完成后,并不能直接启动,缺少若干配置。(执行kubeadm时会生成),直接start可能会出各种问题,后面kubeadm init的时候会自行启动kubelet。这部分问题在本文最后统一提及。
2、k8s所需docker镜像获取
k8s的控制面板主要由apiserver、controller-manager、scheduler、etcd四部分组成,部署在master节点上。coredns是k8s默认的DNS服务。
kube-proxy,pause则部署在所有k8s节点上,kube-proxy与Service相关,而pause则是用来实现Pod内的命名空间共享等功能。
上述这些组件在init初始化master节点时都会用到,可以使用 kubeadm config images list 查看镜像的具体需求,版本。
k8s.gcr.io/kube-apiserver:v1.18.8
k8s.gcr.io/kube-controller-manager:v1.18.8
k8s.gcr.io/kube-scheduler:v1.18.8
k8s.gcr.io/kube-proxy:v1.18.8
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.7
直接从源拉取镜像,大概率会超时。一般的方案均为推荐使用docker的register mirror或者直接给docker配置代理,但是我个人体验并不好。(也可根据自己情况选择各种方案,只要能把镜像拉下来就行)
后来发现了新的解决方案:https://www.cnblogs.com/flhs/p/12383895.html
具体原理就是借助阿里云的镜像仓库功能,手动创建若干个仓库(与k8s的每个组件名称相同),每个仓库绑定Dockerfile(从git获取),内容只有一行FROM k8s.gcr.io/kube-apiserver:v1.18.8
,再使用构建功能,一个自制仓库就制作完成了。随后就可以拉取项目到本地了,再改tag了。
eg:先sudo docker pull http://registry.ap-southeast-1.aliyuncs.com/xxxxx/kube-apiserver:v1.18.8
拉取镜像到本地,再sudo docker tag http://registry.ap-southeast-1.aliyuncs.com/xxxxx/kube-apiserver:v1.18.8 k8s.gcr.io/kube-apiserver:v1.18.8
改tag即可。
3、使用Vagrant做本地配置化
k8s所需软件和镜像就是安装所需的全部资源了,前两个步骤可以考虑进行打包,便于多次重复练习。
由于是学习阶段,软件安装和镜像获取我都是在本地虚拟机上进行的,使用Vagrant来管理安装内容,步骤,以及多虚拟机的管理。这样就可以实现轻松的重新来过,多次练习。
当然,如果是实际使用,Ansible或者自动化工具来实现这些初始化工作也很方便,只不过调用本地虚拟机,Vagrant就够了。
在一台虚拟机上安装好所有软件,拉取了所有镜像后。可以用vagrant将这台虚拟机打包成一个box,后续基于这个box进行操作。
其次,vagrant支持单Vagrantfile定义多个虚拟机,使用vm.define可以分别对每个虚拟机配置IP地址,主机名等其他内容。对于共通内容不做改动。
config.vm.define "master00" do |m0|
m0.vm.network "public_network", ip: "192.168.1.10"
end
config.vm.define "worker00" do |w0|
m0.vm.network "public_network", ip: "192.168.1.11"
end
通过这样的步骤,可以用一个配置文件管理多个虚拟机,可以分别对任意一个虚拟机进行删除重建,十分方便。
vagrant Provision不执行问题:
如果使用过provision再打包,再执行vagrantfile时,默认就不会执行provision,需要手动指定。
https://www.vagrantup.com/docs/provisioning/basic_usage
4、使用kubeadm初始化master/worker节点
准备工作都做好之后,就可以开始进行节点的初始化了。
4.1、init
kubeadm init是初始化master节点,控制平面。
init之前的确认事项:
sudo sysctl net.bridge.bridge-nf-call-iptables=1;
sudo setenforce 0;
sudo systemctl stop firewalld && sudo systemctl disable firewalld;
sudo swapoff -a;
除了内核参数,SELinux,防火墙,swap这4部份外,/etc/hosts文件,以及主机名的修改也需要确认,保证每个节点之间可以使用域名解析。
init参数:
init时,可以根据需要选择打开一些参数。
如果有多网卡,要注意使用
--apiserver-advertise-address=xxx.xxx.xxx.xxx
参数指定期望的IP。--apiserver-advertise-address string
The IP address the API Server will advertise it's listening on. If not set the default network interface will be used.- init可以打开参数,查看更加详细的日志:
--v=6
init失败时,可以选择reset重来sudo kubeadm reset
init成功页面如下图所示:
3.2、join
master节点init初始化完成后,最后会给出添加worker节点的信息。在worker节点上join即可添加到集群中。
3.3、k8s状态确认
kubectl需要进行一些简单的配置才能连接上集群,内容参照init时的成功页面。可以使用 kubectl get nodes 来确认整体安装情况。
kubectl get pods也会出现localhost:8080 was refused
这种情况,其实就是配置问题。本文最后会讲解这个问题。
4、网络插件/网卡配置
网络插件有几个可选项,最终选用了flannel:
https://github.com/coreos/flannel
4.1 kubelet 多网卡配置处理 node-ip
k8s的默认node ip也是取的默认网卡eth0,然而vagrant自己配置的桥接网卡位于eth1,就需要修改kubelet配置来进行适配,改为期望的网卡IP。
修改--node-ip
即可实现这一需求:
在/etc/sysconfig/kubelet 这个文件做如下编辑:KUBELET_EXTRA_ARGS=--node-ip=192.168.x.xx
添加完成后重启kubelet即可。
可以通过 $(ip a|egrep "inet.\*eth1"|awk -F"/" '{print$1}'|awk '{print$2}') 来获取本机指定网卡的IP,也可运行脚本写入/etc/sysconfig/kubelet。
参考:
可以通过查看node-ip来确认是否符合预期:https://cloud.tencent.com/developer/article/1440852
k8s 如何修改node IP? 或者说如何指定网卡获取node IP? https://yanbin.blog/kubernetes-cluster-internal-ip-issue/#more-10102
4.2、flannel 多网卡配置及cidr参数配置
和上述问题一样,flannel也要增加网卡配置。不然就会出现
I0821 09:33:17.131354 1 main.go:518\] Determining IP address of default interface
I0821 09:33:17.131896 1 main.go:531\] Using interface with name eth0 and address 10.0.2.15
I0821 09:33:17.131908 1 main.go:548\] Defaulting external address to interface address (10.0.2.15)
这种问题,vagant默认网卡是不能用的,需要想办法指定网卡。
这个参数可以在flannel的yaml配置文件里更改。更改后,apply -f即可。
在/opt/bin/flanneld的参数中,添加一个--iface=ethx
- name: kube-flannel
image: quay.io/coreos/flannel:v0.12.0-arm
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=eth1
其次 kubeadm init的时候,如果要使用flannel,需要增加cidr参数。--pod-network-cidr=10.244.0.0/16
,可参考:https://github.com/coreos/flannel/blob/master/Documentation/kubernetes.md
flannel网卡参考:
https://blog.csdn.net/ygqygq2/article/details/81698193?utm_source=blogxgwz3
网络插件参考:
https://www.dazhuanlan.com/2019/11/20/5dd4549077148/
https://blog.csdn.net/kwame211/article/details/100335273
http://www.linuxe.cn/post-580.html
5、其他注意点
5.0、kubectl操作优化
alias k=kubectl
source <(kubectl completion bash | sed s/kubectl/k/g) #这里也需要替换成k才能补全
使用k来简化操作,同时打开kubectl的bash 补全。
5.1、kubelet启动问题
首先,没有进行kubeadm和其他配置之前,kubectl缺少配置,启动会报错,简易安装完成后再看。
主要会遇到2个问题:1、cgroup不对,2、system.slice报错。
kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd"
这个问题其实就是kubelet和docker的默认cgoupfs不一样,需要修改其中一方。查阅文档修改其中一方即可,参考:https://blog.csdn.net/russle/article/details/104954408
Failed to get system container stats for "/system.slice/docker.service": failed to get cgroup stats for "/system.slice/docker.service": failed to get container info for "/system.slice/docker.service": unknown container "/system.slice/docker.service"
https://stackoverflow.com/questions/46726216/kubelet-fails-to-get-cgroup-stats-for-docker-and-kubelet-services
这个报错,就是缺少参数,手动添加上即可。--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice
5.3、kubeadm init失败的简单排查
kubeadm init报错:
kubelet报错:
kubelet的报错,只是一个结果(连不上6443),要去查真正的原因。其实init之后,docker容器已经都启动了,要去查容器有没有问题。
发现3个容器有问题。
【容器有问题->6443没起来-->kubelet连不上 -->master节点找不到-->init失败】(要去查根源才行)
https://blog.csdn.net/sanpic/article/details/87084779
确认SELinux
https://blog.51cto.com/bguncle/957315
【其实就是SELinux开机自启了。。。。。
5.4、kubectl端口refused问题
尝试可能会发现,Master节点8080都没监听(其实是网络环境隔离了)
问题其实就是,不允许Master节点的root用户访问,可以用其他普通用户访问
https://www.jianshu.com/p/98c22ca2d9ab
小结
本文主要讲解了kubeadm安装简易3节点k8s集群的过程以及遇到的一些问题,使用kubeadm安装3节点k8s集群已经是相当简易的方式,对于学习探索来说基本够用,但是实际生产环境需要更高的可用性,比如etcd单独部署,master节点多实例等等。
总之k8s组件众多,初次上手以快速搭建学习环境为主,后续可以继续深入了解,尝试部署更复杂的环境。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。