经过实践摸索,一套非常容易实现的快速offline安装k8s的方案。

Overview

整个过程分为两步,1. 准备安装文件,2. offline部署。为了下载镜像,不可避免要翻墙,但我的方案,能够快速响应不同版本,支持scale,并且不需要什么手动pull,手动tag。成功率极高。
我使用的是kubespray v2.9.0,kubernetes 1.13.5。

Preparation

  • 机器配置

    • 一个带ss的机器(个人电脑即可,带UI的ss更好用,我用的ssx可以直接开http server)
    • 一台虚拟机,内存>=2g。
  • 下载kubespray,切换到release分支,创建自己的inventory。

    1
    2
    3
    4
    5
    6
    7
    8
    git clone git@github.com:kubernetes-sigs/kubespray.git`
    git checkout release-2.9.0
    cd kubespray
    # Install dependencies from ``requirements.txt``
    sudo pip install -r requirements.txt

    # Copy ``inventory/sample`` as ``inventory/mycluster``
    cp -rfp inventory/sample inventory/mycluster
  • 创建虚拟机。

    • 采用CentOS7-minimal或者Ubuntu-18.04均可。(这两个我试过,其他的应该也可以,但没试过)。虚拟机使用Vmware或者任何其他均可。
    • 给虚拟机配置好root用户的ssh密钥连接。注意:某些发行版的sshd可能关闭了密钥认证和root登录,注意检查一下。
  • 配置kubespray/inventory/mycluster/hosts.ini

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [all]
    node1 ansible_host=192.168.1.10 ansible_ssh_user=root ansible_ssh_private_key=xxx.pem

    [kube-master]
    node1

    [etcd]
    node1

    [kube-node]
    node1

    [k8s-cluster:children]
    kube-master
    kube-node
    • 将虚拟机的ip填入,连接用的私钥也填入。
  • 配置kubespray/inventroy/mycluster/group_vars/all.yml

    • 找到http proxy,将被部署机器的proxy变为本地的1081端口。
    1
    2
    3
    ## Set these proxy values in order to update package manager and docker daemon to use proxies
    http_proxy: "http://127.0.0.1:1081"
    https_proxy: "http://127.0.0.1:1081"
  • 开启自己电脑上的http proxy server。

    • 使用ssx的话,可以直接打开http proxy在1081。
    • 只有ss的话,安装privoxy,将socks转换成http,放在1081端口。
    • 这个转换不是重点,这里就不详述。
  • 通过ssh透传让虚拟机使用主机的http proxy,保持该窗口,别关闭。

    • ssh -K xxx.pem -r 0.0.0.0:1081:127.0.0.1:1081 root@192.168.1.10
  • 新开一个terminal,切换到kubespray目录,开始部署,下载必要文件。

    • ansible-playbook -i inventory/mycluster/hosts.ini --become --become-user=root cluster.yml --tags container_engine
    • ansible-playbook -i inventory/mycluster/hosts.ini --become --become-user=root cluster.yml --tags download

完成虚拟机全功能部署。

  • 由于使用的是虚拟机,全新的干净镜像,同时使用了翻墙,而且是单节点部署。理所应当成功率极高。
  • 这里部署没有调整addons,网络插件等,这些会影响到后面的正式部署,如果正式部署想要使用这些功能,请在虚拟机部署这里就全部用上。

Production

  • 打包镜像,在虚拟机中,使用docker save将所有镜像保存为tar文件。

    • 需要注意,参数必须是完整镜像名+tag,这样load的时候才能带上这些信息。
    • 我是通过docker images | awk '{print $1,$2}' OFS=":" > temp,导出所有信息到文件中。
    • docker save $(cat temp) > kube.tar,得到镜像文件,可以使用docker load -i kube.tar进行验证。
  • 打包其他文件,全部在/tmp/releases下,将这个目录拷贝保存即可。

  • 准备生产环境机器。

    • 配置好root ssh连接(别的用户也可,ansible支持sudo切换root)。
    • 安装docker,由于我使用的阿里云VPC,机器虽然不能上互联网,但是apt、yum源均为阿里内部的源,所以我通过apt直接安装。一般来说,内网环境还是会配置安装包的,如果任何安装工具都没有,就自行下载docker安装包,然后安装呗,这个不难。
    • sudo apt -y install docker.io
    • 通过scp将镜像文件放到机器上,机器之间仍然可以scp分发,内网速度更快。
    • sudo docker load -i kube.tar。导入所有镜像。
    • /tmp/releases目录原样拷贝到机器中,即保证目标机器的/tmp/releases目录下有同样的文件,对我来说有三个文件kubeadm hyperkube cni-plugin
  • 配置kubespray

    • 去掉all.yml的proxy配置。
    • 在cluster.yml中,注释掉container-engine和download的部分。
    1
    2
    3
    4
    5
    6
    7
    8
    - hosts: k8s-cluster:etcd:calico-rr
    any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
    roles:
    - { role: kubespray-defaults}
    - { role: kubernetes/preinstall, tags: preinstall }
    # - { role: "container-engine", tags: "container-engine", when: deploy_container_engine|default(true) }
    # - { role: download, tags: download, when: "not skip_downloads" }
    environment: "{{proxy_env}}"
    • 调整hosts.ini,指向生产环境机器。
  • 开始部署。

    • ansible-playbook -i inventory/mycluster/hosts.ini --become --become-user=root cluster.yml
  • 出错

    • 我在部署过程中,出现了一个错误,master节点下的/usr/local/bin找不到kubeadm,我怀疑是master部分脚本没有从releases下拷贝,而这个目录则是取决于{bin_dir}
    • 为了图快,我手动将/tmp/releases/kubeadm移动到报错的目录,然后成功。
    • 通过检查role,确实是copy部分的脚本位于download下,取消了download之后,这部分就失效了。
    • 建议直接将kubeadm复制到/usr/local/bin
  • 更新

    • 在更新版本的kubespray中,copy脚本已经移动了位置了,只要保证/tmp/releases下有文件就行了。

Conclusion

  • 通过虚拟机模拟环境,然后迁移,实现内网安装k8s。
  • 一些问题
    • 由于我使用的机器,能够使用apt,所以可能会有些不一样。如果连apt、yum都不能使用,可能会出现一些错误,这时根据脚本报错自行修正即可。

Presentation

图片加载失败