abp 打包部署到ubuntu_CODING 实践指南 | 基于 CVM 离线部署 Kubernetes

959c7b445d6456f63589f0facf9b403c.gif


本文作者:CODING - 王宽

 背景 

在 CODING 独立制品库产品的某个私有化项目交付过程中,因为底层 TCE 环境中的 TKE 服务无法使用,而项目交付时间又非常紧急的情况下,我们团队经过讨论决定采用多台 CVM 主机人工部署一套 Kubernetes 集群环境,一方面用于验证在特定环境中交付部署还存在哪些阻碍,另一方面也希望向客户传达我们正在努力解决问题的工作态度。  困难与挑战 

目标环境完全与互联网隔绝

客户的目标环境是一个 TCE 专有云平台,该云环境完全没有接入公网(出网/入网都没有),所以安装 Kubernetes 涉及到的工具、二进制可执行程序、依赖组件以及相关的镜像、服务都要做成能够离线部署的资源/物料,再通过现场同事带到机房环境中去拷贝。 目标环境的软件源服务无法使用 按正常情况 TCE 中包含了本地可用的软件源服务供 yum/apt 安装 Linux 组件、服务,但是实际情况是服务均无法使用,所以安装过程中涉及到的一些运行时、系统组件都只能预先在 rpm/deb 软件源仓库下载好,再打包到离线部署的物料中。

自建的 Kubernetes 与云平台不兼容

在我们的部署方案中,有状态的服务存储采用的是腾讯云 CBS、COS/CSP、TDSQL(MariaDB),即便是临时自建 Kubernetes 部署,还是希望能保持这样的永久存储架构。好处是当该环境中的 TKE 服务被修复后,我们只需要在 TKE 中重新部署一个实例,引用已经存在的 CBS、COS/CSP、TDSQL(MariaDB)实例就可以实现从自建 Kubernetes 的临时方案到基于 TKE 的生产方案间的无缝迁移。 基于 COS/CSP 的对象存储以及 TDSQL(MariaDB)都是在应用层通过网络访问的方式进行对接,不论是 TKE 还是自建 Kubernetes 互通协议都是一致的,唯独 CBS 需要通过 Kubernetes 中的 Persistent Volume 对象来挂载。在 TKE 中腾讯已经在底层做好了兼容和支持,而自建的 Kubernetes 默认并不兼容 CBS,需要对自建的 Kubernetes 进行一些改造才能兼容 CBS。 改造和兼容参考: https://github.com/TencentCloud/kubernetes-csi-tencentcloud/blob/master/docs/README_CBS_zhCN.md 好不容易找到上面的方案让自建的 Kubernetes 能够兼容 CBS 产品,在改造的过程中却发现 csi-controller.yaml 中的某个服务是通过引用腾讯云 SDK 去连接云平台(查询元数据/调用创建资源 API 等操作),而该 SDK 中对于云平台的接口终结点地址却是写死的腾讯公有云地址,如果要兼容私有云需要魔改镜像,蛋隐隐作疼。最后只能退而求其次使用 rancher 的 local-path-provisioner 来挂载存储。  规划资源  按照临时解决方案的情况,我规划了一个 VPC 网络(192.168.0.0/16),并需要在这个 VPC 网络中分别创建 3 台 CVM,其中 2 台用于部署 Kubernetes ,另外 1 台用做部署过程中需要使用的 工作站 ,3 台 CVM 的配置如下:
类型CPU内存硬盘系统IP地址备注
CVM1C4GB50GBUbuntu 16192.168.100.8工作站
CVM4C16GB50GBUbuntu 16192.168.100.10Kubernetes Master
CVM8C32GB50GBUbuntu 16192.168.100.11Kubernetes Worker Node

 准备相关物料 

准备 Docker 相关物料

https://packages.ubuntu.com/ 中搜索相关的 deb 软件包,并下载到本地,我为我目标环境中的 CVM 准备了以下文件:

文件名下载地址
libseccomp2_2.4.3-1ubuntu3.16.04.3_amd64.debhttp://security.ubuntu.com/ubuntu/pool/main/libs/libseccomp/libseccomp2_2.4.3-1ubuntu3.16.04.3_amd64.deb
docker-ce-cli_19.03.9_3-0_ubuntu-xenial_amd64.debhttps://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_19.03.9~3-0~ubuntu-xenial_amd64.deb
containerd.io_1.3.7-1_amd64.debhttps://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/containerd.io_1.3.7-1_amd64.deb
docker-ce_19.03.9_3-0_ubuntu-xenial_amd64.debhttps://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_19.03.9~3-0~ubuntu-xenial_amd64.deb

准备 kubeadmin 相关物料

参考了 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl 文档,我们需要安装 kubeletkubeadmkubectl,于是通过 https://apt.kubernetes.io 找到并下载相关的 debu 软件包。我为我目标环境中的 CVM 准备了以下文件:

文件名下载地址
kubernetes-cni_0.8.7-00_amd64_ca2303ea0eecadf379c65bad855f9ad7c95c16502c0e7b3d50edcb53403c500f.debhttps://packages.cloud.google.com/apt/pool/kubernetes-cni_0.8.7-00_amd64_ca2303ea0eecadf379c65bad855f9ad7c95c16502c0e7b3d50edcb53403c500f.deb
socat_1.7.3.1-1_amd64.debhttp://kr.archive.ubuntu.com/ubuntu/pool/universe/s/socat/socat_1.7.3.1-1_amd64.deb
ebtables_2.0.10.4-3.4ubuntu1_amd64.debhttp://kr.archive.ubuntu.com/ubuntu/pool/main/e/ebtables/ebtables_2.0.10.4-3.4ubuntu1_amd64.deb
conntrack_1.4.3-3_amd64.debhttp://kr.archive.ubuntu.com/ubuntu/pool/main/c/conntrack-tools/conntrack_1.4.3-3_amd64.deb
cri-tools_1.13.0-01_amd64_4ff4588f5589826775f4a3bebd95aec5b9fb591ba8fb89a62845ffa8efe8cf22.debhttps://packages.cloud.google.com/apt/pool/cri-tools_1.13.0-01_amd64_4ff4588f5589826775f4a3bebd95aec5b9fb591ba8fb89a62845ffa8efe8cf22.deb
kubectl_1.19.3-00_amd64_8b135a2c8ab59784a12ae239cdfd80989d7d08d1da4449522c475cea1025eaa3.debhttps://packages.cloud.google.com/apt/pool/kubectl_1.19.3-00_amd64_8b135a2c8ab59784a12ae239cdfd80989d7d08d1da4449522c475cea1025eaa3.deb
kubelet_1.19.3-00_amd64_03a16e592ababd5fbd11dc5c90503f166340d0f87efd69315892151df20f0a6a.debhttps://packages.cloud.google.com/apt/pool/kubelet_1.19.3-00_amd64_03a16e592ababd5fbd11dc5c90503f166340d0f87efd69315892151df20f0a6a.deb
kubeadm_1.19.3-00_amd64_a46577b3dcf105747a609a72e4349d7efb51a059a005a1f77bea280b3d7b7724.debhttps://packages.cloud.google.com/apt/pool/kubeadm_1.19.3-00_amd64_a46577b3dcf105747a609a72e4349d7efb51a059a005a1f77bea280b3d7b7724.deb

准备 Kubernetes 需要的服务镜像

我们知道 Kubernetes 集群除了 kubelet 是作为系统服务的形式运行,其他的 etcdkube-apiserverkube-proxy 等服务都是通过自身 Pod 去运行的,而 Pod 创建后需要从某个镜像仓库中拉取相应的镜像,此时因为没有访问公网的条件,我们就需要在目标环境的本地(工作站)运行一个准备好相应镜像资源的私有镜像仓库。

$ kubeadm config images listk8s.gcr.io/kube-apiserver:v1.19.3k8s.gcr.io/kube-controller-manager:v1.19.3k8s.gcr.io/kube-scheduler:v1.19.3k8s.gcr.io/kube-proxy:v1.19.3k8s.gcr.io/pause:3.2k8s.gcr.io/etcd:3.4.13-0k8s.gcr.io/coredns:1.7.0
通过 kubeadm config images list 我们可以查看到执行初始化时,依赖以上的资源。
docker run -d -p 5000:5000 --name offline-image-provider registry:2docker pull k8s.gcr.io/kube-apiserver:v1.19.3docker tag k8s.gcr.io/kube-apiserver:v1.19.3 127.0.0.1:5000/kube-apiserver:v1.19.3docker push 127.0.0.1:5000/kube-apiserver:v1.19.3...docker stop offline-image-providerdocker commit offline-image-provider offline-image-providerdocker rm offline-image-providerdocker save -o ~/offline-image-provider.tar offline-image-provider
通过以上脚本,我们可以在本地运行一个私有的镜像仓库,然后从 k8s.gcr.io 的仓库中拉取相关镜像,再推送到本地的私有仓库中,最后将这个私有仓库作为镜像保存成 tar 归档文件。但是因为需要进行多次 push 操作,而每一次对 offline-image-provider 的操作都会生成 docker layer,导致最后导出的 tar 归档文件过大,可以通过以下基于本地文件挂载、Docker Build 的方案来制作私有镜像仓库的离线物料:
FROM registry:2COPY registry /var/lib/registry
docker run -d -p 5000:5000 -v ./registry:/var/lib/registry --name offline-image-provider offline-image-providerdocker pull k8s.gcr.io/kube-apiserver:v1.19.3docker tag k8s.gcr.io/kube-apiserver:v1.19.3 127.0.0.1:5000/kube-apiserver:v1.19.3docker push 127.0.0.1:5000/kube-apiserver:v1.19.3...docker stop offline-image-providerdocker rm offline-image-providerdocker build -t offline-image-provider .docker save -o ~/offline-image-provider.tar offline-image-provider
在本节中我们需要准备以下物料:
文件名备注
offline-image-provider.tar私有镜像仓库镜像归档文件

准备 Pod network add-on 相关镜像

及部署清单文件

当我们通过 kubeadm 初始化一个集群后,我们还需要为 Kubernetes 集群准备一个网络插件用于实现 Container Network Interface(CNI),参考自: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network 在资源规划中我们规划了这个集群只有一个工作节点,所以我们选择 Calico 的小于 50 个工作节点方案: https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico-with-kubernetes-api-datastore-50-nodes-or-less 首先需要下载 calico.yaml 文件,从这个文件中我们可以发现配置 calico 需要使用到一些镜像,这些镜像也要在办公网络拉取好相应的镜像并推送和打包到 offline-image-provider.tar 物料中(参考上一节),同时我们还需要编辑修改 calico.yaml 镜像仓库的地址,变更为即将在工作站中运行的 私有镜像仓库地址 ,例如:
原镜像变更为
calico/cni:v3.16.3192.168.100.8:5000/calico/cni:v3.16.3
calico/pod2daemon-flexvol:v3.16.3192.168.100.8:5000/calico/pod2daemon-flexvol:v3.16.3
calico/node:v3.16.3192.168.100.8:5000/calico/node:v3.16.3
calico/kube-controllers:v3.16.3192.168.100.8:5000/calico/kube-controllers:v3.16.3
在本节中我们需要准备以下物料:
文件名备注
calico.yamlCalico 网络插件部署清单文件
准备 Kubernetes csi tencentcloud 相关镜像 及部署清单文件 如 自建的 Kubernetes 与云平台不兼容 中提到的情况,我们需要借助于 kubernetes-csi-tencentcloud 来为自建的 Kubernetes 提供兼容 CBS 服务的能力。 参考自: https://github.com/TencentCloud/kubernetes-csi-tencentcloud/blob/master/docs/README_CBS_zhCN.md 从文档中得知,我们需要准备以下部署清单文件:
文件名
secret.yaml
csi-controller-rbac.yaml
csi-node-rbac.yaml
csi-controller.yaml
csi-node.yaml
snapshot-crd.yaml
并且从这些清单文件中得知,部署依赖以下镜像,和前面步骤一样,这些镜像也需要打包到 offline-image-provider.tar 物料中,同时需要修改部署清淡文件中对镜像的引用地址:
原镜像变更为
quay.io/k8scsi/csi-provisioner:v1.6.0192.168.100.8:5000/k8scsi/csi-provisioner:v1.6.0
quay.io/k8scsi/csi-attacher:v2.2.0192.168.100.8:5000/k8scsi/csi-attacher:v2.2.0
quay.io/k8scsi/csi-snapshotter:v2.1.0192.168.100.8:5000/k8scsi/csi-snapshotter:v2.1.0
quay.io/k8scsi/snapshot-controller:v2.1.0192.168.100.8:5000/k8scsi/snapshot-controller:v2.1.0
quay.io/k8scsi/csi-resizer:v0.5.0192.168.100.8:5000/k8scsi/csi-resizer:v0.5.0
ccr.ccs.tencentyun.com/k8scsi/csi-tencentcloud-cbs:v1.2.0192.168.100.8:5000/k8scsi/csi-tencentcloud-cbs:v1.2.0
quay.io/k8scsi/csi-node-driver-registrar:v1.2.0192.168.100.8:5000/k8scsi/csi-node-driver-registrar:v1.2.0
ccr.ccs.tencentyun.com/k8scsi/csi-tencentcloud-cbs:v1.2.0192.168.100.8:5000/k8scsi/csi-tencentcloud-cbs:v1.2.0
准备 Local path provisioner 相关镜像 及部署清单文件

自建的 Kubernetes 与云平台不兼容 中提到的,改造 Kubernetes 兼容 CBS 的过程中遇到了需要魔改镜像的问题,出于时间考虑,我们临时决定还是采用 Local path provisioner 方案。

参考自:

https://github.com/rancher/local-path-provisioner

从文档中得知,我们需要准备以下镜像,这些镜像需要打包到 offline-image-provider.tar 物料中。

原镜像变更为
rancher/local-path-provisioner:v0.0.18192.168.100.8:5000/rancher/local-path-provisioner:v0.0.18
busybox192.168.100.8:5000/busybox
在本节中我们需要准备以下物料:
文件名备注
local-path-storage.yamlLocal path provisioner 部署清单文件

 部署 

上传物料

将我们准备好的物料上传至 工作站 中,之后可以通过 scp 将相关物料文件从工作站传输到 Kubernetes Master、Kubernetes Worker Node 中。

安装 docker

通过以下脚本,分别在工作站、Kubernetes Master、Kubernetes Worker Node 中安装 docker 引擎:

sudo dpkg -i libseccomp2_2.4.3-1ubuntu3.16.04.3_amd64.debsudo dpkg -i docker-ce-cli_19.03.9_3-0_ubuntu-xenial_amd64.debsudo dpkg -i containerd.io_1.3.7-1_amd64.debsudo dpkg -i docker-ce_19.03.9_3-0_ubuntu-xenial_amd64.deb

安装 kubeadmin

通过以下脚本,分别在 Kubernetes Master、Kubernetes Worker Node 中安装 docker 引擎:
cat <net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1EOFsudo sysctl --systemsudo dpkg -i kubernetes-cni_0.8.7-00_amd64_ca2303ea0eecadf379c65bad855f9ad7c95c16502c0e7b3d50edcb53403c500f.debsudo dpkg -i socat_1.7.3.1-1_amd64.debsudo dpkg -i ebtables_2.0.10.4-3.4ubuntu1_amd64.debsudo dpkg -i conntrack_1.4.3-3_amd64.debsudo dpkg -i cri-tools_1.13.0-01_amd64_4ff4588f5589826775f4a3bebd95aec5b9fb591ba8fb89a62845ffa8efe8cf22.debsudo dpkg -i kubectl_1.19.3-00_amd64_8b135a2c8ab59784a12ae239cdfd80989d7d08d1da4449522c475cea1025eaa3.debsudo dpkg -i kubelet_1.19.3-00_amd64_03a16e592ababd5fbd11dc5c90503f166340d0f87efd69315892151df20f0a6a.debsudo dpkg -i kubeadm_1.19.3-00_amd64_a46577b3dcf105747a609a72e4349d7efb51a059a005a1f77bea280b3d7b7724.debsudo apt-mark hold kubelet kubeadm kubectl
在工作站中运行私有镜像仓库服务 在工作站中通过以下脚本启动我们准备好的镜像仓库服务,并监听 5000 端口:
docker load -i offline-image-provider.tardocker run -d -p 5000:5000 --name offline-image-provider registry:2

初始化 kubernetes 集群

在 Kubernetes Master 中通过以下命令初始化一个 Kubernetes 集群实例:
kubeadm init --image-repository=192.168.100.8:5000
之后,你将看到类似以下输出结果:
[init] Using Kubernetes version: v1.19.3[preflight] Running pre-flight checks[preflight] Pulling images required for setting up a Kubernetes cluster[preflight] This might take a minute or two, depending on the speed of your internet connection[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"[kubelet-start] Activating the kubelet service[certs] Using certificateDir folder "/etc/kubernetes/pki"[certs] Generating "etcd/ca" certificate and key[certs] Generating "etcd/server" certificate and key[certs] etcd/server serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1][certs] Generating "etcd/healthcheck-client" certificate and key[certs] Generating "etcd/peer" certificate and key[certs] etcd/peer serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1][certs] Generating "apiserver-etcd-client" certificate and key[certs] Generating "ca" certificate and key[certs] Generating "apiserver" certificate and key[certs] apiserver serving cert is signed for DNS names [kubeadm-cp kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.138.0.4][certs] Generating "apiserver-kubelet-client" certificate and key[certs] Generating "front-proxy-ca" certificate and key[certs] Generating "front-proxy-client" certificate and key[certs] Generating "sa" key and public key[kubeconfig] Using kubeconfig folder "/etc/kubernetes"[kubeconfig] Writing "admin.conf" kubeconfig file[kubeconfig] Writing "kubelet.conf" kubeconfig file[kubeconfig] Writing "controller-manager.conf" kubeconfig file[kubeconfig] Writing "scheduler.conf" kubeconfig file[control-plane] Using manifest folder "/etc/kubernetes/manifests"[control-plane] Creating static Pod manifest for "kube-apiserver"[control-plane] Creating static Pod manifest for "kube-controller-manager"[control-plane] Creating static Pod manifest for "kube-scheduler"[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s[apiclient] All control plane components are healthy after 31.501735 seconds[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace[kubelet] Creating a ConfigMap "kubelet-config-X.Y" in namespace kube-system with the configuration for the kubelets in the cluster[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "kubeadm-cp" as an annotation[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the label "node-role.kubernetes.io/master=''"[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule][bootstrap-token] Using token: [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace[addons] Applied essential addon: CoreDNS[addons] Applied essential addon: kube-proxyYour 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/configYou should now deploy a Pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:  /docs/concepts/cluster-administration/addons/You can now join any number of machines by running the following on each nodeas root:  kubeadm join : --token  --discovery-token-ca-cert-hash sha256:
根据提示运行以下脚本让普通用户使用 kubectl 管理集群:
mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config
记录下提示中的 kubeadm join xxx 脚本,该脚本用于 Worker Node 加入集群时使用。

部署 Calico

在 Kubernetes Master 中通过以下脚本部署 Calico:
kubectl apply -f calico.yaml
等待数分钟后,你可以通过 kubectl get pod -n kube-system 查看 Kubernetes Pod 状态 。 将工作节点加入到集群中 在 Kubernetes Worker Node 中运行之前记录的 kubeadm join xxx 脚本,等待数分钟后,你可以在 Kubernetes Master 中通过 kubectl get node 查看到工作节点已经加入到了集群中。

部署 Local path provisioner

在 Kubernetes Master 中通过以下脚本部署 Local path provisioner:
kubectl apply -f local-path-storage.yaml

结语

通过以上步骤,我们已经成功在没有公网的环境基于自建虚拟机,自备离线物料的方式部署了一个标准版 Kubernetes 集群,并且通过指定 storageClassNamelocal-path 可以基于工作节点的本地存储创建 PersistentVolume 。基于以上自备 物料 的方法,还可以将任意的服务部署到这个 Kubernetes 集群内。

71bd3187f1e176fddcd7fe9fc534eb8d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值