暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

k8s平台迁移记录修改版

IT那活儿 2025-07-14
93

点击上方“IT那活儿”公众号--专注于企业全栈运维技术分享,不管IT什么活儿,干就完了!!!


  
最近萌生了一些容器云运维思路,计划付诸实施,但生产的PaaS平台是不能随便乱玩的,因此构建了一套独立于现网PaaS平台的仿真k8s平台,并把生产的应用迁移过来。
为确保网络安全,文中的敏感信息均做了模糊化。



k8s集群搭建

虽然网络上有很多k8s搭建教程,但是真正实践的话可能会遇到很多坑,总结了几类原因可能是:
  • 1GFW;
  • 2)需要使用代理上网(毕竟个人PC配置能和生产相匹配的太少了,动辄上百G内存,且因为网络安全,不大可能把应用放在自己电脑上,因此多数还是依赖公司的内网服务器);
  • 3)对软件版本要求苛刻(如果要按照教程来,就要保持版本完全一致)。
总之就是环境的苛刻,不是想怎样就能怎样的。如果你选择了latestversion,建议最好使用官方文档。
1.1 虚拟机安装
为了提升环境的质量,我找了台能直连外网的高性能服务器做宿主机,操作系统CentOS7.7.1908 x86_64Hypervisor使用VMware WorkStation 15,上面克隆出5个同样版本操作系统的虚机,其中1master节点,4slave节点。列表如下:
  • cent7-k8s-master, *.*.206.40
  • cent7-k8s-slave01, *.*.206.22
  • cent7-k8s-slave02, *.*.206.42
  • cent7-k8s-slave03, *.*.206.24
  • cent7-k8s-slave04, *.*.206.25
个人建议后续完成阶段性的配置就做一下备份,避免重返工。
ovftool home/wmare/cent7-k8s-master/cent7-k8s-master.vmx home/virtual/cent7-k8s-master.ovf
ovftool home/wmare/cent7-k8s-slave01/cent7-k8s-slave01.vmx home/virtual/cent7-k8s-slave01.ovf
ovftool home/wmare/cent7-k8s-slave02/cent7-k8s-slave02.vmx home/virtual/cent7-k8s-slave02.ovf
ovftool home/wmare/cent7-k8s-slave03/cent7-k8s-slave03.vmx home/virtual/cent7-k8s-slave03.ovf
ovftool home/wmare/cent7-k8s-slave04/cent7-k8s-slave04.vmx home/virtual/cent7-k8s-slave04.ovf

启动虚拟机:
vmrun -T ws start /home/wmare/cent7-k8s-master/cent7-k8s-master.vmx
vmrun -T ws start /home/wmare/cent7-k8s-slave01/cent7-k8s-slave01.vmx
vmrun -T ws start /home/wmare/cent7-k8s-slave02/cent7-k8s-slave02.vmx
vmrun -T ws start /home/wmare/cent7-k8s-slave03/cent7-k8s-slave03.vmx
vmrun -T ws start /home/wmare/cent7-k8s-slave04/cent7-k8s-slave04.vmx

1.2 环境配置
#Master】配置/etc/hosts:
cat >> /etc/hosts <<EOF
*.*.206.40 cent7-k8s-master
*.*.206.41 cent7-k8s-slave01
*.*.206.42 cent7-k8s-slave02
EOF

#Master】配置到各节点的信任关系:
ssh-keygen -t dsa -P "" -f ~/.ssh/id_dsa
cd root
ssh-copy-id -i .ssh/id_dsa.pub root@cent7-k8s-master
ssh-copy-id -i .ssh/id_dsa.pub root@cent7-k8s-slave01
ssh-copy-id -i .ssh/id_dsa.pub root@cent7-k8s-slave02

#Master】安装衍生软件仓库:
yum install -y epel-release
#Master】安装批量运维工具ansible:
yum install -y ansible
#Master】配置ansible集群:
cat >> /etc/ansible/hosts <<EOF
[k8scluster]
cent7-k8s-master
cent7-k8s-slave01
cent7-k8s-slave02
[node]
cent7-k8s-slave01
cent7-k8s-slave02
EOF

#Master】批量复制/etc/hosts:
ansible node -mcopy -a'src=/etc/hosts dest=/etc/hosts'
#Master】批量修改主机名:
ansible all -i cent7-k8s-master, -mshell -a'hostnamectl set-hostname cent7-k8s-master' -u root
ansible all -i cent7-k8s-slave01, -mshell -a'hostnamectl set-hostname cent7-k8s-slave01' -u root
ansible all -i cent7-k8s-slave02, -mshell -a'hostnamectl set-hostname cent7-k8s-slave02' -u root
ansible all -i cent7-k8s-slave03, -mshell -a'hostnamectl set-hostname cent7-k8s-slave03' -u root
ansible all -i cent7-k8s-slave04, -mshell -a'hostnamectl set-hostname cent7-k8s-slave04' -u root

#Master】永久、临时关闭强制访问控制:
ansible all -mcommand -a'sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" etc/sysconfig/selinux'
ansible all -mcommand -a'setenforce 0'

#Master】关闭防火墙firewalld:
ansible all -mcommand -a'systemctl stop firewalld'
ansible all -mcommand -a'systemctl disable firewalld'

#Master】彻底关闭系统交换分区:
ansible all -mcommand -a'swapoff -a'
ansible all -mcommand -a'echo "vm.swappiness = 0" >> etc/sysctl.conf'
ansible all -mcommand -a'sysctl -p'
ansible all -mcommand -a'sed -i "s/^.*centos_centos7-swap/#&/g" etc/fstab'

kubernetes的想法是将实例紧密包装到尽可能接近100%,所有的部署应该与CPU 内存限制固定在一起。所以如果调度程序发送一个pod到一台机器,它不应该使用交换。设计者不想交换,因为它会减慢速度。所以关闭swap主要是为了性能考虑。为了一些节省资源的场景,比如运行容器数量较多,可添加kubelet参数--fail-swap-on=false来解决。

#Master】批量安装telnet:
ansible all -mcommand -a'yum install -y telnet'
#Master】配置iptables对转发数据包进行处理,启用数据包转发:
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
EOF
sysctl --system /etc/sysctl.d/k8s.conf
ansible node -mcopy -a'src=/etc/sysctl.d/k8s.conf dest=/etc/sysctl.d/k8s.conf'
ansible node -mcommand -a'sysctl --system etc/sysctl.d/k8s.conf'

#Master】时间服务配置,几个节点的时间必须保持同步,否则会出现意料不到的结果:
ansible all -mcommand -a'yum install -y ntpdate'
ansible all -mcommand -a'ntpdate ntp1.aliyun.com'
ansible all -mcommand -a'yum install -y ntp'
ansible all -mcommand -a'systemctl enable ntpd'
ansible all -mcommand -a'systemctl start ntpd'
ansible all -mcommand -a'timedatectl set-timezone Asia/Shanghai'
ansible all -mcommand -a'timedatectl set-ntp yes'
ansible all -mcommand -a'hwclock --hctosys'
ansible all -mcommand -a'timedatectl set-local-rtc 0'
ansible all -mcommand -a'hwclock --show'

#Master】安装docker-ce社区版本:
ansible all -mcommand -a'yum install -y yum-utils device-mapper-persistent-data lvm2'
ansible all -mcommand -a'yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo'
ansible all -mcommand -a'yum makecache fast'
ansible all -mcommand -a'yum -y update'
ansible all -mcommand -a'yum -y install docker-ce-18.06.2.ce'
ansible all -mcommand -a'systemctl start docker'

#Master】配置dockercgroupdriver、加速器:
cat > etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver""json-file",
"log-opts": {
    "max-size""100m"
  },
"storage-driver""overlay2",
"storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
"registry-mirrors": ["https://ya78xgj1.mirror.aliyuncs.com"]
}
EOF
ansible node -mcopy -a'src=/etc/docker/daemon.json dest=/etc/docker/daemon.json'
ansible all -mcommand -a'systemctl daemon-reload'

#Master】使能、启动docker服务,检查docker状态:
ansible all -mcommand -a'systemctl enable docker'
ansible all -mcommand -a'systemctl restart docker'
ansible all -mcommand -a'docker images'

#Master】配置K8S软件仓库:
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
ansible node -mcopy -a'src=/etc/yum.repos.d/kubernetes.repo dest=/etc/yum.repos.d/kubernetes.repo'

#Master】安装K8S的三个基本组件,并启动kubelet服务:
ansible all -mcommand -a'yum install -y kubelet kubeadm kubectl'
ansible all -mcommand -a'systemctl enable kubelet'
ansible all -mcommand -a'systemctl start kubelet'

#Master】配置yum升级时排除dockerkube*等软件包,避免升级后dockerkube*之间版本不兼容:
ansible all -m command -a 'cp etc/yum.conf etc/yum.conf.old'
cat <<EOF >> etc/yum.conf
exclude=docker* kube*
EOF
ansible node -m copy -a 'src=/etc/yum.conf dest=/etc/yum.conf'

#Master】初始化K8S集群:
kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.16.1 --pod-network-cidr=10.244.0.0/16
#这里返回了Slave节点加入集群的命令:
kubeadm join *.*.206.40:6443 --token 6r4dak.9409ob3rqcwo0091 \
    --discovery-token-ca-cert-hash sha256:fe694b09bdf11ddee1328cc52868eb55e62022aa633f3c1ea06a2a3e1aaac669

注:如果token当时忘记保存了,通过kubeadmin token list也可查到join验证信息。

#部署网络,以下在每个masternode节点上执行,保证flannel网络:
docker search flannel 去docker镜像库查看flannel的镜像,pull最新版下来。
docker pull jmgao1983/flannel:v0.11.0-amd64

#Master】配置kubeconfig,这里包含用于建立slavemasterapiserver连接的证书:
mkdir -p $HOME/.kube
cp -i etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
ansible node -m command -a 'mkdir -p $HOME/.kube'
ansible node -m copy -a 'src=/root/.kube/config dest=/root/.kube/'

#Master】配置flannel网络:
cd /root/.kube
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
sed -i 's#quay.io/coreos/flannel:v0.11.0-amd64#jmgao1983/flannel:v0.11.0-amd64#g' kube-flannel.yml
kubectl apply -f kube-flannel.yml

#Master】将master节点调整为可分配节点:
kubectl taint nodes --all node-role.kubernetes.io/master-
#MasterSlave节点批量加入集群:
ansible node -m command -a 'kubeadm join *.*.206.40:6443 --token 3k99j7.d0ovp7pwnlmkfmdp 
--discovery-token-ca-cert-hash sha256:b65bcaa046d002ed167f00692755020248eb6c1d52bee409c13f4a067a285f85'

#如果一切正常,你能够看到pods的状态都是running。
kubectl get nodes
NAME                STATUS   ROLES    AGE     VERSION
cent7-k8s-master    Ready    master   2d22h   v1.16.1
cent7-k8s-slave01   Ready    <none> 2d22h   v1.16.1
cent7-k8s-slave02   Ready    <none> 2d22h   v1.16.1
cent7-k8s-slave03   Ready    <none> 2d22h   v1.16.1
cent7-k8s-slave04   Ready    <none> 2d22h   v1.16.1

kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cattle-system   cattle-cluster-agent-5f49cbcb67-r8wbl 1/1     Running 0          47s xx.xxx.1.29      cent7-k8s-slave03 <none>           <none>
cattle-system   cattle-node-agent-4mzvh 1/1     Running 0          9s *.*.133.25   cent7-k8s-slave04 <none>           <none>
cattle-system   cattle-node-agent-dmg96 1/1     Running 0          5s *.*.133.41  cent7-k8s-slave01 <none>           <none>
cattle-system   cattle-node-agent-fx59q 1/1     Running 0          25s *.*.133.40   cent7-k8s-master <none>           <none>
cattle-system   cattle-node-agent-j57sn 1/1     Running 0          39s *.*.133.42   cent7-k8s-slave02 <none>           <none>
cattle-system   cattle-node-agent-w55nt 1/1     Running 0          18s *.*.133.24   cent7-k8s-slave03 <none>           <none>

1.3 配置Rancher
#Master】运行rancher容器:
docker pull rancher/rancher
docker run -d 
--name=rancher-ui --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher

#登录到rancher控制台,添加一个名称为kubernetes的集群:

Add Cluster Import an existing cluster Cluster Name: Kubernetes
#Master】执行导入,导入完成后能看到名称为cattle-system的命名空间:
curl --insecure -sfL https://*.*.206.40 /v3/import/qqglbj4cffp5f7ggfkvb2ggj9lcskgzz4fr74h79z6x2tf92cptgxr.yaml | kubectl apply -f –
kubectl get ns
kubectl get pods -n cattle-system -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cattle-system   cattle-cluster-agent-5f49cbcb67-r8wbl 1/1     Running 0          4710.244.1.29      cent7-k8s-slave03 <none>           <none>
cattle-system   cattle-node-agent-4mzvh 1/1     Running 0          9s *.*.133.25   cent7-k8s-slave04 <none>           <none>
cattle-system   cattle-node-agent-dmg96 1/1     Running 0          5s *.*.133.41  cent7-k8s-slave01 <none>           <none>
cattle-system   cattle-node-agent-fx59q 1/1     Running 0          25s *.*.133.40   cent7-k8s-master <none>           <none>
cattle-system   cattle-node-agent-j57sn 1/1     Running 0          39s *.*.133.42   cent7-k8s-slave02 <none>           <none>



k8s集群搬迁

如果你在优良的网络环境下创建好k8s集群,再考虑把虚拟机镜像导入内网的服务器环境中使用,可能会发现一个令人恼火的问题,那就是宿主机NAT网络的地址可能不同,如果你修改了内网服务器的NAT网络地址,则可能影响其他虚机的访问。
VMware Workstation不支持配置多个NAT网卡,不要尝试去创建另外一个NAT网络vmnet8,这在VMware Workstation 11环境上会直接造成vmnet-natd进程挂掉,且丢失/etc/vmware/vmnet8/nat/nat.conf里的所有地址映射配置。
根据一些教程实践,我认为只有两种方案:
  • 尝试修改k8s集群IP;
  • 重建k8s集群。
对于前者,我参考了一些教程尝试配置,但发现并不完全奏效,如果仅修改Master节点IP,效果可能会好些。
2.1 修改k8s集群IP
#MasterSlaves】替换/etc/$HOME/下的IP地址:
sed -i "s/*.*.206.40/*.*.133.40/g" `grep -rl "*.*.206.40" /etc/`
sed -i "s/*.*.206.40/*.*.133.40/g" `grep -rl "*.*.206.40" $HOME/`

#MasterSlaves】修改目录名,有的Slave有这个目录,有的Slave没有这个目录:
mv$HOME/.kube/cache/discovery/*.*.206.40_6443 $HOME/.kube/cache/discovery/*.*.133.40_6443
#Master】重新加载docker,重启全部节点:
ansible all -mcommand -a'systemctl daemon-reload'
ansible node -mcommand -a'reboot'
reboot

#Master】重建证书:
mv etc/kubernetes/pki/apiserver.key etc/kubernetes/pki/apiserver.key.old
mv etc/kubernetes/pki/apiserver.crt etc/kubernetes/pki/apiserver.crt.old
mv etc/kubernetes/pki/apiserver-kubelet-client.crt etc/kubernetes/pki/apiserver-kubelet-client.crt.old
mv etc/kubernetes/pki/apiserver-kubelet-client.key etc/kubernetes/pki/apiserver-kubelet-client.key.old
mv /etc/kubernetes/pki/front-proxy-client.crt /etc/kubernetes/pki/front-proxy-client.crt.old
mv /etc/kubernetes/pki/front-proxy-client.key /etc/kubernetes/pki/front-proxy-client.key.old
kubeadm init phase certs all

#Master】修改configmaps中的IP:
kubectl get configmaps -n kube-system -o yaml > kube-system_configmaps.yaml
kubectl get configmaps -n kube-public -o yaml > kube-public_configmaps.yaml
perl -p -i -e's/*.*.206.40/*.*.133.40/g' kube-system_configmaps.yaml
perl -p -i -e's/*.*.206.40/*.*.133.40/g' kube-public_configmaps.yaml
kubectl apply -f kube-system_configmaps.yaml
kubectl apply -f kube-public_configmaps.yaml

#Master】配置时间服务并复制到所有节点,这里注意的是即使已经成功执行了下述命令,在重启虚机后仍可能有时间不一致的情况,应特别注意。
ansible node -mcopy -a'src=/etc/ntp.conf dest=/etc/ntp.conf'
ansible all -mcommand -a'systemctl start ntpd'
ansible all -mcommand -a'ntpdate XX.XX.244.52'

#rancher需要重新初始化。
2.2 重建集群
如果2.1的方案不奏效,只能选择重建集群。
#Master】首先执行集群重置:
kubeadm reset
systemctl daemon-reload && systemctl restart kubelet

#Master】重复执行1.21.3节。


k8s应用迁移

尽管存在各种品牌的PaaS平台,其内部K8S版本也千差万别,但最核心的应用还是能相互兼容的,我们的目标是将任意PaaS平台的应用均迁移到这个“裸”K8S平台上,形成一个与现网“隔离”的仿真环境。
要实现这一点,最起码的两边环境配置要基本一致,这个配置包含业务租户(命名空间)下所有资源的配置必须是基本一致,可以参考https://kubernetes.io/docs/reference/kubectl/overview/#resource-types对生产PaaS平台的资源定义进行导出,并在仿真环境中应用。从这个链接可以看到资源类型很多,但实际上真正使用的也就这么几个:
  • configmaps;
  • deployments;
  • endpoints;
  • limitranges;
  • namespaces;
  • secrets;
  • services
3.1 k8s资源的迁移
#一般的操作模式是,在源端(生产PaaS导出、修改、在目标端(仿真环境)加载。
#导出:
kubectl get configmaps -n business -o yaml > configmaps_default.yaml
kubectl get deployments -n business -o yaml > deployments_default.yaml
kubectl get secrets sc-first -n business -o yaml > sc-first.yaml
kubectl get secrets sc-second -n business -o yaml > sc-second.yaml
kubectl get secrets sc-third -n default -o yaml > sc-third.yaml

#修改配置(如目标端命名空间如果不同的话)
#加载:
kubectl apply -f configmaps_default.yaml --validate=false
kubectl apply -f deployments_default.yaml --validate=false
kubectl apply -f sc-first.yaml --validate=false

#注意deployments中的nodeSelector参数,需要对相应Node执行标注以告知kubernetespod对应的容器镜像在哪个特定节点上,并在该节点上启动容器进程,可以根据实际需要配置多个label,可以把生产上的应用部署在仿真环境的一个节点中。
kubectl label node cent7-k8s-slave03 zone="xxx"
3.2 docker镜像的迁移
一般在kubectl apply deployments的时候,k8s会自动从生产的镜像仓库拉取镜像,但实际上可能会出现docker版本和镜像仓库不兼容的现象,造成拉取失败。因此考虑采用docker save/load方式迁移镜像。
#源端保存镜像为tar包:
dockersave-obusiness_app.tar *.*.133.100:20202/business/business_app:1.1
目标端加载镜像:
docker load -i business_app.tar
#目标端应用deployments配置前应调整imagePullPolicyIfNotPresent,否则若为Always则忽略已经创建的镜像并继续从仓库拉取。
3.3 服务暴露
#根据deployment暴露服务:
kubectl expose deployment business_app -n business --port=19001 --target-port=19002
  • --portservice端口(一个随机创建的ClusterIP的端口);
  • --target-port为容器内部IP的端口。
#但是这样依然还是无法将服务暴露给宿主机以外的服务器访问,只能供k8s容器内部访问,因此需要用到NodePortExternalIP的方式,进一步向外界暴露服务。
kubectl expose deployment business_app -n business --port=19001 --target-port=19002 --type=NodePort
#执行完上面的指令,会出现一个nodePort配置,端口为随机生成的,需要修改成我们需要固定的端口并重新应用。
kubectl get svc -n business business_app -o yaml > business_app.yaml
perl -p -i -e's/nodePort\: 30142/nodePort\: 19001/g' business_app.yaml
kubectl apply -f business_app.yaml


END


本文作者:徐兴强(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论