minikube 中 docker 守护进程的代理问题

摘要

由于国内的网络环境特殊,在本地使用 minikube 时遇到了 service 创建好后,一直无法运行的问题。查阅了网上很多资料后,找到一个笨拙的解决办法,先在此做个记录,以后再验证其他方案。

此方案需要具备以下先行条件:

环境准备

1. 网络配置

在 shell 中 export http_proxy , https_proxy , HTTP_PROXY , HTTPS_PROXYALL_PROXY 等环境变量,指向科学上网的本地 ip 和 port。

2. kubernetes

Ubuntu 16.04 已经支持 snap 包管理工具,可以直接通过官网的教程安装:

sudo snap install kubectl --classic

如果使用 oh-my-zsh 配置环境,只需要在 ~/.zshrcplugins 中添加 kubectl 就可以在终端下使用更加友好的补齐和提示操作,包括后面会写到的 docker

3. virtualbox

minikube 依赖虚拟机,这里使用开源的 virtualbox ,直接使用 apt 工具安装即可:

sudo apt install -y virtualbox

4. minikube

直接使用 minikube release 页面中的教程安装:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.25.2/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

5. Docker

最好安装 17.03 版本之后的 Docker,不然在后面的运行过程中会有个讨厌的 warning(go 1.7 or later)。安装新版的 Docker 可以参考官方页面,提取如下过程:

$ sudo apt-get remove docker docker-engine docker.io
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
$ sudo usermod -aG docker your-user

如果上述设置的代理环境变量未起作用,还可参考此种方式使用 systemctl 设置 docker daemon 进程的 Environment。

错误调试

在所有的上述环境配置好后,按照 Running Kubernetes Locally via Minikube 教程中的命令执行,在 kubectl get pod 后,hello-minikube 的 Status 始终是 Creating,不能到达 Running。

使用 kubectl describe pod hello-minikue 描述看到 Failed create pod sandbox 的 Error。Google 一番之后,看到 GitHub 上的这个 issue。其中说到导致该问题的原因为 minikube VM 中的网络问题导致其内部的 docker 无法正确 pull 到以下的 image:

gcr.io/google_containers/kubernetes-dashboard-amd64:v1.8.0
gcr.io/k8s-minikube/storage-provisioner:v1.8.0
gcr.io/k8s-minikube/storage-provisioner:v1.8.1
gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.5
gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.5
gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5
gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.3
gcr.io/google-containers/kube-addon-manager:v6.4-beta.2
gcr.io/google_containers/pause-amd64:3.0

只需要在 minikube VM 中下载下来上面的这些镜像便能正确运行 k8s 中的 pod。

再搜寻 1 2 3 4 等答案后,依然无法解答 minikube VM 中 docker 代理的设置问题。最后只能是采用了一个迂回的方式:

  1. 在 host 上使用代理将 image pull 到本机上(注意不要忘记 image 后的 tag,否则会报 gcr 的认证问题);
  2. 将 host 上的 docker image 导入 minikube VM 中,因为终端下的限制,评论中的 pipe 方式失败。完成这个功能可以采用如下的两种方式:
    • 先把 host 上的 image 保存到文件,再将文件挂载到 VM,最后 ssh 到 VM,用 docker 导入文件。对应如下的命令:
      $ docker save ImageTag -o /path/to/mount_dir/output.file
      $ minikube mount /path/to/mount_dir:/VM/mount_dir
      $ minikube ssh
      > sudo docker load -i /VM/mount_dir/output.file
      > docker images
      
    • 直接通过如下一行命令导入 host 上的 image(推荐):
      $ docker save imageNameGoesHere | pv | (eval $(minikube docker-env) && docker load)
      
  3. 指定 kubectl 使用 VM 中的 image,参考该回答kubectl run 的最后添加 --image-pull-policy=Never 参数;
  4. 执行 kubectl get pod 检查是否是 Running 状态;
  5. 获取 url 在浏览器中访问:minikube service svc-name --url

总结

经过上述的一番折腾,本地的一个 k8s 实验总算测试通过。网络问题往往是分布式系统搭建过程中需要耗费很大精力关注的点,尤其在这样一个特殊的环境下。因为 minikube 和 kubectl 在命令行下不会默认输出错误信息,有时会让人产生大功告成的假象,需要多借助 kubectl describekubectl logs 命令分析原因,同时也可以尝试打开 minikube 的 debug 级别的 log:minikube start --logtostderr --loglevel=0 查找潜在问题。

04 April 2018

blog comments powered by Disqus