「Kubernetes」- 在集群初始化时,如果无法拉取官方镜像怎么办?

  CREATED BY JENKINSBOT

问题描述

当使用kubeadm命令初始化集群时,会去官方镜像仓库(k8s.gcr.io)拉取镜像。但是国内网络无法访问官方镜像仓库,导致集群初始化失败。

该笔记将记录:在 Kubernetes 集群初始化时,拉取官方镜像的方法。

解决方案

简而言之,我们推荐使用一下两种方式:

对于新版集群(推荐)

在使用 kubeadm v1.14 初始化集群时,我们无意间发现它支持 --image-repository 选项,该选项能够指定镜像仓库地址:

kubeadm init --image-repository registry.aliyuncs.com/google_containers

2)如果通过配置文件初始化集群,能够使用 imageRepository 字段

方法一、手动拉取镜像

我学到的首个方法是手动拉取镜像,然后在本地打标签。因为如果镜像存在于本地,则kubeadm将不再去官方拉取镜像,因此该方法可行。

第一步、查看需要拉取的镜像

首先需要知道拉取那些镜像:

#!/bin/sh

kubeadm config images list

# 而上述命令会卡顿,因为它需要访问dl.k8s.io地址获取版本。你可以手动指定版本:
kubeadm config images list --kubernetes-version 1.12.10

命令会产生类似如下输出:

k8s.gcr.io/kube-apiserver:v1.12.10
k8s.gcr.io/kube-controller-manager:v1.12.10
k8s.gcr.io/kube-scheduler:v1.12.10
k8s.gcr.io/kube-proxy:v1.12.10
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.2.24
k8s.gcr.io/coredns:1.2.2

第二步、拉取目标镜像到本地

根据上面输出,我们已经得知所有需要拉取的镜像。接下来我们以kube-apiserver:v1.12.10为例。

在Docker Hub中(或者其他地方)找到kube-apiserver:v1.12.10镜像,并拉取到本地:

# 我们随便拉取一个
docker pull imdingtalk/kube-apiserver:v1.12.10

第三步、使用官方镜像标签

docker tag imdingtalk/kube-apiserver:v1.12.10 k8s.gcr.io/kube-apiserver:v1.12.10

第四步、推送到私有仓库(可选)

建议将镜像推送到本地私有奖项仓库,预备日后使用。另外,以可以防止官方镜像无法访问等问题。

对于旧版方法(使用旧版集群)

对于旧版集群,比如1.12.1版本。现在需要升级集群,它不支持 --image-repository 选项,因此你可以使用“方法一”。但是呢,我们还有其他办法,可能比较复杂,但更加通用。

第一步、导出默认配置

当我们执行kubeadm init时,集群便开始初始化。但是在内部它有默认配置文件,该配置文件可以使用kubeadm config print-default命令查看(新版需要使用kubeadm config print命令)。然后在配置文件中搜索imageRepository字段。是的,这就是默认镜像仓库地址。

第二步、修改默认配置

将上面imageRepository字段修改为可用的镜像仓库,保存并退出。

第三步、使用配置文件

在kubeadm中,很多子命令(config、init、upgrade)都支持--config选项,而该选项参数则为前面的配置文件。

比如集群升级命令,我们使用修改过的配置文件:

kubeadm upgrade apply v1.12.10 --config kubeadm-config.default.v1alpha3-aliyun

(当然,我们仅修改imageRepository字段)

自动化脚本

以下脚本用于处理与镜像有关的问题:
1)将官方镜像拉取到本地,解决镜像无法拉取问题;
2)将镜像推送到私有仓库,进行备份;

拉取“官方镜像”到本地,并推送私有仓库

通常某个用户会提供所有相关镜像。可以使用如下脚本从imdingtalk中拉取所有镜像,并创建标签:

dockerhub_username="imdingtalk"
kubernetes_version="1.12.10"
private_registry_prefix="10.10.50.4/k8s"

for img in $(kubeadm config images list --kubernetes-version "${kubernetes_version}")
do
	echo "### $img"

	# 获取原始镜像名
    img_name=$(echo $img | sed 's%k8s.gcr.io/%%g')

    # 从Docker Hub中拉取镜像
    docker pull "${dockerhub_username}/${img_name}"

    # 为镜像创建新的标签
    docker tag "${dockerhub_username}/${img_name}" "k8s.gcr.io/${img_name}"

    # 为了防止官方镜像日后无法访问,我们有必要对镜像进行备份:
    docker tag "${dockerhub_username}/${img_name}" "${private_registry_prefix}/${img_name}"
    docker push "${private_registry_prefix}/${img_name}"

done

(请根据需要自行修改)