1、前言
如今微服务盛行,服务部署几乎离不开K8S,工作中无时无刻不在接触它,秉着知其然还要知其所以然的原则,本系列文章会从源码层面对K8S进行深度剖析,俗话说工欲善其事必先利其器,阅读源码不仅仅是看,还需要去调试,只有调试才能更深入的理解一个庞大系统的运行机制。本系列的第一篇文章将会带你搭建K8S的调试集群。
2、搭建云端K8S集群
搭建K8S集群可以使用一个节点,然而为了更好的观察整个集群的调度特性,我们采用3节点进行部署,在本地没有多台机器的条件下可以租云端的服务器。以下租用了云端的3台服务器进行部署。
K8S集群对硬件的要求如下:
- 每台机器至少2G内存
- 控制面节点至少2核
2.1 环境准备
以下操作在所有节点上进行。
2.1.1 机器信息
2.1.2 版本信息
2.1.3 主机名互通
修改配置文件/etc/hosts
cat >> /etc/hosts << EOF 10.1.8.10 master 10.1.20.4 worker1 10.1.20.3 worker2 EOF
2.1.4 更新yum源
备份默认yum源:mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
调整yum源文件/etc/yum.repos.d/CentOS-Base.repo如下:
[base] name=CentOS-$releasever - Base - mirrors.aliyun.com baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/ gpgcheck=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [updates] name=CentOS-$releasever - Updates - mirrors.aliyun.com baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/ gpgcheck=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [extras] name=CentOS-$releasever - Extras - mirrors.aliyun.com baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/ gpgcheck=1 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [centosplus] name=CentOS-$releasever - Plus - mirrors.aliyun.com baseurl=http://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/ gpgcheck=1 enabled=0 gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
清理并重建缓存:yum clean all && yum makecache
更新软件包:yum update -y
2.1.5 安装依赖
yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp net-tools vim wget
2.1.6 同步服务器时间
yum install chrony -y systemctl enable chronyd systemctl start chronyd chronyc sources
2.1.7 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld && systemctl status firewalld && firewall-cmd --state
2.1.8 关闭selinux
setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config && sestatus
2.1.9 关闭swap
swapoff -a sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab free -m //确认swap是否关闭
2.1.10 配置iptables规则
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT
2.1.11 设置系统参数
cat <<EOF > /etc/sysctl.d/k8s.conf vm.swappiness = 0 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF // 配置生效 modprobe br_netfilter sysctl -p /etc/sysctl.d/k8s.conf
2.1.12 安装ipvs
cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules
查看是否正确加载所需内核模块:lsmod | grep -e ip_vs -e nf_conntrack_ipv4
2.2 安装containerd
需在所有节点上安装
下载yum源:
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
查看可安装版本:
yum list | grep containerd
安装containerd:
yum -y install containerd.io
创建containerd配置文件:
mkdir -p /etc/containerd containerd config default > /etc/containerd/config.toml
修改配置文件/etc/containerd/config.toml:
sed -i 's#SystemdCgroup = false#SystemdCgroup = true#' /etc/containerd/config.toml sed -i 's#sandbox_image = "registry.k8s.io/pause:3.6"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7"#' /etc/containerd/config.toml sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#' /etc/containerd/config.toml
新建目录及配置文件/etc/containerd/certs.d/k8s.gcr.io/hosts.toml,内容如下:
server = "https://k8s.gcr.io" [host."https://registry.aliyuncs.com"] capabilities = ["pull", "resolve"]
新建目录及配置文件/etc/containerd/certs.d/docker.io/hosts.toml,内容如下:
server = "https://docker.io" [host."https://registry.aliyuncs.com"] capabilities = ["pull", "resolve"]
启动containerd
systemctl enable containerd systemctl start containerd systemctl status containerd
验证containerd:ctr version
2.3 安装kubelet、kubeadm、kubectl
需要所有节点上安装
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 list kubeadm --showduplicates | sort -r yum list kubelet --showduplicates | sort -r yum list kubectl --showduplicates | sort -r
安装:
yum install -y kubeadm-1.24.2 kubelet-1.24.2 kubectl-1.24.2
设置运行时:
crictl config runtime-endpoint /run/containerd/containerd.sock
设置开启启动:
systemctl enable kubelet
2.4 初始化集群
2.4.1 下载k8s相关镜像
在所有节点上下载镜像
查看kubeadm使用镜像列表:kubeadm config images list
下载镜像脚本download.sh,各组件版本根据实际情况进行调整:
#!/bin/bash K8S_URL=k8s.gcr.io ALIYUN_URL=registry.aliyuncs.com/google_containers images=(kube-apiserver:v1.24.17 kube-controller-manager:v1.24.17 kube-scheduler:v1.24.17 kube-proxy:v1.24.17 pause:3.7 etcd:3.5.3-0 coredns:v1.8.6) for imageName in ${images[@]} ; do ctr -n k8s.io image pull $ALIYUN_URL/$imageName ctr -n k8s.io image tag $ALIYUN_URL/$imageName $K8S_URL/$imageName ctr -n k8s.io image rm $ALIYUN_URL/$imageName done ctr -n k8s.io image tag $K8S_URL/coredns:v1.8.6 $K8S_URL/coredns/coredns:v1.8.6 ctr -n k8s.io image rm $K8S_URL/coredns:v1.8.6
查看镜像:ctr -n k8s.io image list | grep k8s.gcr.io
2.4.2 主节点初始化
在主节点上执行
生成默认初始化配置:kubeadm config print init-defaults > kubeadm.yaml
调整配置kubeadm.yaml
kind: InitConfiguration nodeRegistration: name: master //主节点名 localAPIEndpoint: advertiseAddress: 10.1.8.10 kind: ClusterConfiguration apiServer: certSANs: - "10.1.8.10" - "公网IP" //证书包含公网IP,用于远程调试 kubernetesVersion: 1.24.2 //安装版本,kubelet --version获取 networking: podSubnet: 10.244.0.0/16
如之前安装过,需重置:kubeadm reset
初始化:kubeadm init --config=kubeadm.yaml
2.4.3 加入集群
在worker节点上执行
拷贝主节点配置文件$HOME/.kube/config到worker节点目录$HOME/.kube
如之前安装过,需重置:kubeadm reset
主节点初始化后,会显示worker节点加入集群的命令:
kubeadm join 10.1.8.10:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx
coredns处于pending状态:
节点目前都是NotReady状态,coredns也未启动,还需要安装网络插件,本文接下来介绍calico插件安装。
2.5 安装calico
2.5.1 下载calico yaml
curl https://projectcalico.docs.tigera.io/archive/v3.23/manifests/calico.yaml -o calico.yaml
2.5.2 下载calico镜像
下载calico.yaml中使用的镜像
- docker.io/calico/cni:v3.23.5
- docker.io/calico/kube-controllers:v3.23.5
- docker.io/calico/node:v3.23.5
可以先离线下载这些镜像然后导入:
ctr -n k8s.io image import cni.tar ctr -n k8s.io image import kube-controllers.tar ctr -n k8s.io image import node.tar
查看镜像:ctr -n k8s.io image list
2.5.3 部署calico
部署calico:kubectl apply -f calico.yaml
查看calico运行:kubectl get pods -n kube-system | grep calico
查看集群节点:kubectl get nodes -o wide
所有服务均正常启动:
控制面节点默认不允许调度,如需调度需移除污点:
kubectl taint nodes master node-role.kubernetes.io/control-plane- kubectl taint nodes master node-role.kubernetes.io/master-
移除污点前:
移除污点后:
2.6 验证集群
待验证nginx.yaml:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: default labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: docker.io/library/nginx:1.25 imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx namespace: default spec: type: NodePort selector: app: nginx ports: - port: 80 targetPort: 80 nodePort: 30200
部署:kubectl apply -f nginx.yaml
浏览器访问
2.7 调试集群
下载k8s源码:git clone https://github.com/kubernetes/kubernetes.git
切换到分支release-1.24
删除master节点上的文件/etc/kubernetes/manifests/kube-scheduler.yaml,kube-scheduler pod会自动删除
拷贝master节点上的文件/etc/kubernetes/scheduler.conf到本地,并修改server为master节点公网IP地址
设置匿名用户clusterrole权限
kubectl create clusterrolebinding the-boss --user system:anonymous --clusterrole cluster-admin
配置goland启动参数
设置scheduler.conf配置文件路径
启动本地scheduler服务,入口文件为:cmd/kube-scheduler/scheduler.go
启动nginx pod:kubectl apply -f nginx.yaml
测试nginx pod调度到worker1节点:
2.8 遇到的问题
以下列举可能遇到的问题及解决方法,如未遇到则忽略:
(1)安装calico报错
报错:calico/node is not ready: BIRD is not ready: BGP not established with 10.1.8.10,10.1.20.4
原因:Calico 使用 BGP 来在节点之间交换路由信息,从而实现跨节点的网络通信,云主机的防火墙未放通179端口进行BGP通信
解决:云主机防火墙放通179端口
(2)安装依赖报错
报错:Could not resolve host: mirrors.aliyun.com; Unknown error
原因:DNS无法解析域名
解决:配置DNS地址/etc/resolv.conf
nameserver 8.8.8.8 # Google DNS nameserver 8.8.4.4 # Google DNS nameserver 223.5.5.5 # 阿里云 DNS nameserver 223.6.6.6 # 阿里云 DNS
(3)启动远程调试kube-scheduler报错
报错:x509: certificate is valid for 10.96.0.1, 10.1.8.10, not xxx
原因:scheduler.conf文件中的证书没有包含公网IP
解决:重新生成证书,包含公网IP
在master节点上删除证书
rm /etc/kubernetes/pki/apiserver.crt rm /etc/kubernetes/pki/apiserver.key rm /etc/kubernetes/pki/apiserver-kubelet-client.crt rm /etc/kubernetes/pki/apiserver-kubelet-client.key
在配置文件kubeadm.yaml中加入master节点公网IP,参考主节点初始化章节
重新生成证书
kubeadm init phase certs apiserver --config=kubeadm.yaml kubeadm init phase certs apiserver-kubelet-client --config=kubeadm.yaml kubeadm init phase kubeconfig scheduler --config=kubeadm.yaml
重新拷贝scheduler.conf到本地
(4)服务异常时查看详细报错信息
journalctl -u kubelet -f journalctl -u containerd -f
3、搭建本地K8S集群
搭建一个3节点最小规格的云端K8S集群每个月机器费用大概是200多RMB,如果手上有一台性能还不错的机器,可以通过虚拟机的方式来搭建本地集群环境节省这部分费用。
3.1 环境准备
接下来通过vagrant、virtual box创建3台虚拟机来搭建K8S集群。
3.1.1 版本信息
3.1.2 安装virtual box
下载地址:https://www.virtualbox.org/wiki/Downloads
3.1.3 安装vagrant
下载地址:https://developer.hashicorp.com/vagrant/install
3.1.4 下载centos镜像
下载地址:https://app.vagrantup.com/centos/boxes/7/versions/2004.01/providers/virtualbox/unknown/vagrant.box
3.1.5 添加镜像
添加镜像并命名为centos/7:vagrant box add centos/7 {box文件路径}
查看镜像:vagrant box list
vagrant常用命令:
启动所有或指定虚拟机:vagrant up [hostname]
登录指定虚拟机:vagrant ssh hostname,root密码为vagrant
查看所有或指定虚拟机状态:vagrant status [hostname]
停止所有或指定虚拟机:vagrant halt [hostname]
删除所有或指定虚拟机:vagrant destroy [hostname]
修改Vagrantfile配置生效:vagrant reload
3.1.6 启动虚拟机
创建目录并创建Vagrantfile文件,内容如下:
# -*- mode: ruby -*- # vi: set ft=ruby : boxes = [ { :name => "master", :eth1 => "192.168.1.51", :mem => "4096", :cpu => "2" }, { :name => "worker1", :eth1 => "192.168.1.52", :mem => "2048", :cpu => "2" }, { :name => "worker2", :eth1 => "192.168.1.53", :mem => "2048", :cpu => "2" } ] Vagrant.configure(2) do |config| config.vm.box = "centos/7" boxes.each do |opts| config.vm.define opts[:name] do |config| config.vm.hostname = opts[:name] config.vm.provider "vmware_fusion" do |v| v.vmx["memsize"] = opts[:mem] v.vmx["numvcpus"] = opts[:cpu] end config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--memory", opts[:mem]] v.customize ["modifyvm", :id, "--cpus", opts[:cpu]] v.customize ["modifyvm", :id, "--name", opts[:name]] end config.vm.network :public_network, ip: opts[:eth1] end end end
以上配置创建了三个虚拟机,规格如下:
查看虚拟机状态:vagrant status
启动虚拟机:vagrant up
分别登录三个虚拟机
vagrant ssh master
vagrant ssh worker1
vagrant ssh worker2
至此,三台虚拟机已经搭建完成,接下来的操作和云端类似,不再赘述。