最近正好在腾讯云白嫖了一台4核4G的服务器,于是又有了可以折腾的东西了。于是打算用两台服务器搭建k8s集群。为啥要在两台云服务器上搭呢?(因为折腾坏了可以一键重装,非常方便,结果一不小心踩了好多坑)
安装
关闭swap
关闭swap防止影响性能,需要编辑/etc/fstab
文件,注释掉下面这一行
/swapfile swap swap defaults 0 0
关闭SELinux
关闭SELinux以允许容器访问宿主机文件系统,需要编辑/etc/sysconfig/selinux
文件,将SELINUX
设置为disabled
SELINUX=disabled
配置防火墙
需要配置的端口如下:
组件 | 默认端口号 |
---|---|
API Server | 8080(HTTP非安全端口号) 6443(HTTPS安全端口号) |
Controller Manager | 10252 |
Scheduler | 10251 |
kubelet | 10250 10255(只读端口号) |
etcd | 2379(供客户端访问) 2380(供etcd集群内部节点直接访问) |
集群DNS服务 | 53(TCP和UDP) |
除此之外其他组件还需要开通某些端口,比如CNI网络插件需要179端口,镜像库需要5000端口。
安装docker
curl -fsSL https://mirrors.tencent.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository \ "deb [arch=amd64] https://mirrors.tencent.com/docker-ce/linux/ubuntu/ \ $(lsb_release -cs) \ stable" sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io
安装GPG证书
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add
添加apt源
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main EOF sudo apt update -y
安装kubelet、kubeadm
和kubectl
sudo apt install kubelet kubeadm kubectl
安装mater节点
修改kubeadm默认配置
kubeadm init
命令和kubeadm join
都可以通过指定配置文件修改默认参数的值。kubeadm config
子命令提供了对这组功能的支持
-
kubeadm config print init-defaults
:输出kubeadm init
命令默认参数的内容 -
kubeadm config print join-defaults
:输出kubeadm join
命令默认参数的内容 -
kubeadm config migrate
:可以对于新旧版本之间的配置文件进行转换 -
kubeadm config images list
:输出所需镜像列表 -
kubeadm config images pull
:拉取镜像到本地
kubeadm config print init-defaults > init-config.yaml
然后可以得到一份默认的yaml配置文件,然后大概需要修改这几个地方:
apiVersion: kubeadm.k8s.io/v1beta3 bootstrapTokens: - groups: - system: bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s …… kind: InitConfiguration localAPIEndpoint: advertiseAddress: 10.0.16.4 bindPort: 6443 …… apiServer: certSANs: - k8s.eastjun.xyz - 121.5.27.225 controlPlaneEndpoint: 121.5.27.225:6443 …… imageRepository: registry.aliyuncs.com/google_containers kind: ClusterConfiguration kubernetesVersion: 1.23.0 networking: dnsDomain: cluster.local serviceSubnet: 192.168.0.0/12 scheduler: {}
-
advertiseAddress
为API Server
监听的地址,需要修改为网卡地址,或者0.0.0.0
,bindPort
为API Server
监听的端口。 -
token
需要进行修改,默认的配置文件中有一个默认的token,需要我们自己进行修改,或者可以直接删掉,然后它会生成一个随机的token -
国内环境无法访问k8s官方仓库,需要指定
imageRepository
为国内的地址,这里指定它为阿里的镜像仓库地址。 -
certSANs
设置证书的IP地址和域名,这个要和Node加入集群时的地址一致,不然Node会觉得证书无效不让我们加入 -
controlPlaneEndpoint
也要和Node加入集群时的地址一致,不然Node会尝试连接Master节点的网卡地址,而这个网卡的地址可能是内网地址,Node访问不到 -
然后
serviceSubnet
可以设置Pod的IP地址范围。
实际上这份配置文件并不包含所有的选项,一份比较完整的配置文件可以参考
下载相关镜像
执行kubeadm config images list
可以获取所需镜像的列表,为了加快kubeadm
创建集群的过程,可以提前将所需镜像下载完成,可以执行kubeadm config images pull
或docker pull
命令下载镜像
kubeadm config images pull --config=init-config.yaml
使用kubeadm命令安装master节点
在kubeadm init
命令进行具体的安装操作之前首先会进行一系列的系统预检查,确保主机环境符合安装要求,如果检查失败就直接终止。用户可以通过kubeadm init phase preflight
命令进行预检查的操作,确保系统就绪后再执行init操作。
kubernetes默认的cgroup
驱动为systemd
,而docker默认的cgroup
驱动为cgroupfs
,为了与kubernets保持一致,需要修改docker服务的配置文件为systemd
,需要在daemon.json
文件中设置:
{ "exec-opts":["native.cgroupdriver=systemd"] }
在一切准备就绪之后执行kubeadm init
命令就可以初始化master节点,然后使用--config
指定配置文件
kubeadm init --config=init-config.yaml
如果安装过程一切正常,则屏幕上会输出Your Kubernetes control-plane has initialized successfully!
然后需要为kubectl配置证书,才能访问Master,对于非root用户,可以将admin.conf
配置文件复制到HOME目录的.kube子目录下:
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
对于root用户可以设置环境变量完成kubectl的配置:
export KUBECONFIG=/etc/kubernetes/admin.conf
然后可以使用kubectl
命令行工具对Kubernetes
集群进行访问和操作了:
kubectl get nodes
在这里master节点已经正常工作了,但集群中没有可用的Worker Node,并且缺乏容器网络的配置。然后需要安装Worker Node,这里需要使用到kubeadm init
命令运行完之后显示的token。
将新的Node加入集群
在Node节点中需要安装好kubeadm
和kubelet
(不需要安装kubectl)。在安装好kubeadm
和kubelet
之后使用kubeadm join
命令加入集群,可以执行Master节点安装完成之后的命令:
kubeadm join 121.5.27.225:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:d16648f17cd9e84a894c91e807577afd7989eff1ab2023faf86a6f6f0d002703
也可以通过配置文件加入集群,首先需要导出kubeadm join
命令的默认配置文件:
kubeadm config print join-defaults > join-config.yaml
然后这份配置文件大概需要修改为这个样子这样子:
apiVersion: kubeadm.k8s.io/v1beta3 caCertPath: /etc/kubernetes/pki/ca.crt discovery: bootstrapToken: apiServerEndpoint: 121.5.27.225:6443 token: abcdef.0123456789abcdef unsafeSkipCAVerification: true timeout: 5m0s tlsBootstrapToken: abcdef.0123456789abcdef kind: JoinConfiguration nodeRegistration: criSocket: /var/run/dockershim.sock imagePullPolicy: IfNotPresent name: vm-0-5-ubuntu taints: null
然后使用配置文件加入集群:
kubeadm join --config=join-config.yaml
如果不出意外会看到如下的输出:
然后在Master节点使用kubectl
可以看到节点的信息:
kubectl get nodes
这里有一个Master节点和一个Pod节点:
安装网络插件
在这一步可以看到节点都还是NotReady
的状态,这是因为还没有安装CNI网络插件:
[root@VM-16-4-centos ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION node NotReady control-plane,master 5m34s v1.23.4 vm-0-5-ubuntu NotReady <none> 5m22s v1.23.4
网络插件可以有多种选择,我这里使用Flannel CNI插件,运行下面的命令可以一键安装:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
在运行成功之后再次查看Node,其状态会变成Ready:
[root@VM-16-4-centos eastjun]# kubectl get nodes NAME STATUS ROLES AGE VERSION node Ready control-plane,master 18m v1.23.4 vm-0-5-ubuntu Ready <none> 18m v1.23.4
踩坑
1.kubeadm init
时卡在[wait-control-plane]
这个问题是因为advertiseAddress
要指定网卡上显示的IP。如果网卡上的IP和公网IP不一致,优先选择网卡上的IP,或者0.0.0.0
。
2. kubeadm join
时出现net/http: request canceled while waiting for connection
出问题的原因是腾讯云的IP是用了NAT转换的,在执行kubeadm init
之后它给出的就是内网那个IP,而这两台云服务器不是同一个地区的,在内网不能互通。解决方法是在advertiseAddress
中指定内网的地址,而在controlPlaneEndpoint
中指定公网的地址
3. kubeadm join
时出现x509: certificate is valid for 192.160.0.1, 10.0.16.4, not 121.5.27.225
如果在Master节点初始化时使用controlPlaneEndpoint
指定了正确的IP是不会出现这个问题的。上一个问题的另一种解决方案是在执行kubeadm join
命令时指定apiserver-advertise-address
,告诉Node一个正确的地址。但是Node在加入集群时发现这个地址和证书上的地址不一致,然后告诉你证书上的地址是xxx,而你连的是xxx。解决方法是在init
的时候在配置文件中添加certSANs
指定其他IP。
4. 都做好了,但是执行kubectl get nodes -o wide
时显示的是内网IP
因为两台服务器是两个不同地区的实例,内网IP不能互通,所以必然是要将其设置为公网IP,不然在kubectl exec
的时候会连不上。我需要在Node节点上添加一个虚拟网卡,IP设置为Node节点的公网IP,然后Node加入集群的时候才会使用公网IP:
sudo ifconfig eth0:1 Node节点的公网IP up
Referer
《Kubernetes权威指南》