2019年12月21日 | Leave a comment https://blog.ilemonrain.com/docker/rancher-with-k3s.html?replyTo=64 在生产环境中,很多时候我们都会有这样的需求: 业务弹性需求较大,反复安装卸载修改配置文件会对环境造成极大破坏,甚至需要重装系统以清理环境 将业务迁移到Docker架构,但使用传统的Docker CLI (Docker命令行) 方式进行管理,效率低下还容易误操作 将业务迁移到K8S架构,但因为K8S过于占用系统资源,往往在开发环境或者小型的生产环境,K8S刚跑起来系统就没可用性能资源了 K8S手动部署起来一路尽是无底深坑,好不容易配好了稍稍改动下配置文件整个集群全炸了 需要个简单直观管理工具,能够简单快速的管理各个K8S集群,灵活创建Pod 在我接触K8S架构之初,也遇到了类似的问题:使用Rancher2+K8S这样的架构,在一台1C2G的阿里云上面部署,部署完成后发现系统内存早就被吃的一干二净,无从谈起业务部署;使用传统的Docker Swarm,感觉用起来没有K8S那样顺手舒服。 2019年2月26日,业界领先的容器管理软件提供商Rancher Labs(以下简称Rancher)宣布推出轻量级Kubernetes发行版 K3S 。这对于一些小型的开发/生产环境、边缘计算节点甚至性能极其有限的设备(比如树莓派3)来讲无疑是福音。 但问题来了,K3S相对于K8S,精简了不少功能。那么如何正确的对接Rancher 2和K3S呢?思考了许久,也在自己的时间环境埋头搞了一周,终于搞出来了一套完整的部署教程。好东西当然不能私藏着,分享出来的同时,也为那些部署Rancher+K3S架构的同好们提供一些常见问题的解决思路。 那么,教程,现在开始。 Step 0: 配置环境要求 虽然K3S是K8S的轻量版,但也不能说不看配置要求。官方给出的配置要求如下: 系统内核版本:Linux 3.10+ (CentOS 7, Debian 8/9, Ubuntu 14.04+) K3S Server端最低内存要求:512 MB K3S Agent端内存最低要求:75MB 磁盘空间最低要求:200 MB 支持的硬件架构:x86_64, ARMv7, ARM64 相对于K8S那种性能杀手,K3S真的可以轻量到部署在大多数的虚拟机上(比如常见的1C512M,不过如果部署在生产环境,建议1C2G及以上以保证稳定性)。如果你还要再同一台Server上同时跑Rancher 2.x Server的话,我给出的建议最低配置要求如下: 系统内核版本:Linux 3.10+ (CentOS 7, Debian 8/9, Ubuntu 14.04+) CPU最低核心数:1 核心 Rancher 2.x Server + K3S Server + K3S Agent端最低内存要求:2 GB 磁盘空间最低要求:5 GB 建议使用的硬件架构:x86_64 虽然K3S足够轻量,但也请不要忘掉,Rancher Server本身也是需要占用掉大量内存的。所以如果是为了做成AIO (All In One)的效果,建议按照上述的配置要求准备Server。 Step 1: 安装Docker环境 虽然K3S默认集成的是Containerd,但出于多方面原因,为了后续部署方便起见,这里我们将Containerd换成Docker。具体的原因我会在下文讲到。 本文以 Debian 9 x64 系统作为示例,Ubuntu 可以直接照搬 Debian 的安装过程,CentOS 用户我会特殊标注操作步骤。 如果你的服务器在中国大陆境内: curl -fsSL "https://mirrors4.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg" | apt-key add - echo "deb [arch=amd64] https://mirrors4.tuna.tsinghua.edu.cn/docker-ce/ stretch stable" > /etc/apt/sources.list.d/docker.list apt-get update && apt-get install -y docker-ce 123 curl -fsSL "https://mirrors4.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg" | apt-key add -echo "deb [arch=amd64] https://mirrors4.tuna.tsinghua.edu.cn/docker-ce/ stretch stable" > /etc/apt/sources.list.d/docker.listapt-get update && apt-get install -y docker-ce 如果你的服务器在海外: curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add - echo "deb [arch=amd64] https://download.docker.com/linux/debian stretch stable" > /etc/apt/sources.list.d/docker.list apt-get update && apt-get install -y docker-ce 123 curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add -echo "deb [arch=amd64] https://download.docker.com/linux/debian stretch stable" > /etc/apt/sources.list.d/docker.listapt-get update && apt-get install -y docker-ce CentOS 系统或者以上方法无法安装的,请使用官方安装脚本: curl -fsSL get.docker.com | sh 1 curl -fsSL get.docker.com | sh 也许会有人问我,我安装的时候为什么去掉了 --no-install-recommends 参数? 因为需要用到里面的cgroup支持,当然,你也可以加上这个参数,来只安装基础的Docker组件,同样能够支持运行。 在安装完成后,如果你的服务器位于中国大陆境内,你很有可能需要一个Docker镜像加速器。国内提供Docker镜像加速器的服务商很多,这里我们以阿里云的镜像加速服务为例: 打开 https://cr.console.aliyun.com ,并登录你的阿里云账户 点击左方的 镜像中心 – 镜像加速器 ,然后在下方会有一个操作文档,复制其中的命令,粘贴到你的SSH窗口中即可完成镜像源的更换。 如果报错误 sudo: command not found ,只需要去掉每行命令中的sudo即可 (前提是你的当前登录用户为root) Step 2: 安装Rancher Server 此部分你也可以参考官方教程: https://www.cnrancher.com/quick-start Rancher Server名字听起来感觉像是又要装一大堆东西,其实并不是这样。Rancher Server其实只是一个Docker镜像,整个Rancher的程序都使用Docker打包起来了。所以相对来讲配置很简单,只需要一条命令: docker run -d -v /data/docker/rancher-server/var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 80:80 -p 443:443 rancher/rancher:stable 1 docker run -d -v /data/docker/rancher-server/var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 80:80 -p 443:443 rancher/rancher:stable 然后等待几分钟,喝杯82年的雪碧压压惊(划掉),之后访问你的Server IP即可进入Rancher Server的首次配置界面。 如果你不想让Rancher占用你的80/443端口(比如前端要放个Caddy反代),只需要按照以下步骤操作: 修改启动命令行: docker run -d -v /data/docker/rancher-server/var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 80:80 -p 443:443 rancher/rancher:stable 1 docker run -d -v /data/docker/rancher-server/var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 80:80 -p 443:443 rancher/rancher:stable 将里面的80和443,替换为你需要的端口(注意:请不要占用Kubernetes的6443端口,这一步很容易翻车!),换完的效果大概是这样: docker run -d -v /data/docker/rancher-server/var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 9080:9080 -p 9443:9443 rancher/rancher:stable 1 docker run -d -v /data/docker/rancher-server/var/lib/rancher/:/var/lib/rancher/ --restart=unless-stopped --name rancher-server -p 9080:9080 -p 9443:9443 rancher/rancher:stable 启动Rancher Server容器 执行命令,确认Rancher Server容器的Container ID,本例中的容器ID为 31aa94998b75: <span class="hljs-attribute">docker</span> ps | grep <span class="hljs-string">"rancher/rancher:stable"</span> 1 <span class="hljs-attribute">docker</span> ps | grep <span class="hljs-string">"rancher/rancher:stable"</span> 执行命令,切入到Rancher Server容器的Bash Shell中(TTY): docker <span class="hljs-keyword">exec</span> -it <span class="hljs-number">31</span>aa94998b75 bash 1 docker <span class="hljs-keyword">exec</span> -it <span class="hljs-number">31</span>aa94998b75 bash 此时你会发现你的提示符变成了这个样子: root@31aa94998b75:/var/lib/rancher# 这时候你控制的就是Rancher Server的容器,如果你能够成功切入Shell,那么请继续下一步,如果未能切入,请使用 docker logs 31aa94998b75 来确认容器发生了什么奇怪的事情。 我们先开看下要改的文件长什么样子: <span class="hljs-meta">#</span><span class="bash">!/bin/bash</span> set -e exec tini -- rancher --http-listen-port=80 --https-listen-port=443 --audit-log-path=${AUDIT_LOG_PATH} --audit-level=${AUDIT_LEVEL} --audit-log-maxage=${AUDIT_LOG_MAXAGE} --audit-log-maxbackup=${AUDIT_LOG_MAXBACKUP} --audit-log-maxsize=${AUDIT_LOG_MAXSIZE} "${@}" 1234 <span class="hljs-meta">#</span><span class="bash">!/bin/bash</span>set -e exec tini -- rancher --http-listen-port=80 --https-listen-port=443 --audit-log-path=${AUDIT_LOG_PATH} --audit-level=${AUDIT_LEVEL} --audit-log-maxage=${AUDIT_LOG_MAXAGE} --audit-log-maxbackup=${AUDIT_LOG_MAXBACKUP} --audit-log-maxsize=${AUDIT_LOG_MAXSIZE} "${@}" 执行命令,替换默认的端口: sed -i "s/80/9080/g" /usr/bin/entrypoint.sh sed -i "s/443/9443/g" /usr/bin/entrypoint.sh 12 sed -i "s/80/9080/g" /usr/bin/entrypoint.shsed -i "s/443/9443/g" /usr/bin/entrypoint.sh 执行后看下变成了什么样子: <span class="hljs-meta">#</span><span class="bash">!/bin/bash</span> set -e exec tini -- rancher --http-listen-port=9080 --https-listen-port=9443 --audit-log-path=${AUDIT_LOG_PATH} --audit-level=${AUDIT_LEVEL} --audit-log-maxage=${AUDIT_LOG_MAXAGE} --audit-log-maxbackup=${AUDIT_LOG_MAXBACKUP} --audit-log-maxsize=${AUDIT_LOG_MAXSIZE} "${@}"" 1234 <span class="hljs-meta">#</span><span class="bash">!/bin/bash</span>set -e exec tini -- rancher --http-listen-port=9080 --https-listen-port=9443 --audit-log-path=${AUDIT_LOG_PATH} --audit-level=${AUDIT_LEVEL} --audit-log-maxage=${AUDIT_LOG_MAXAGE} --audit-log-maxbackup=${AUDIT_LOG_MAXBACKUP} --audit-log-maxsize=${AUDIT_LOG_MAXSIZE} "${@}"" 确认修改成功后,使用 exit 命令退出容器的Bash Shell,之后执行命令重新启动Rancher Server容器: <span class="hljs-attribute">docker</span> restart 31aa94998b75 1 <span class="hljs-attribute">docker</span> restart 31aa94998b75 之后使用新的端口访问Rancher Server的UI(下面的连接为例子): 访问会提示SSL证书无效,无视错误继续即可。 https://rancher.example.com:9443/ 1559176134336.png 此时我们会来到Rancher的初始化部署页面,在此页面输入默认的全局管理员密码,创建全局管理员账户。 1559176304769.png 这一步输入我们的Rancher API Endpoint,注意这里输入的URL一定要保证整个集群内的所有节点都可以正常连接。 1559176520773.png 之后我们会来到主界面,如果对英文操作看着头疼的话,右下角可以切换语言。 具体方法是点击右下角的 English ,然后下拉选择 简体中文(zh-hans) 即可。 汉化设置会跟随你的Cookies走,所以不换电脑或者不重装系统的话应该不会自动换回英语。 1559176671939.png 我们接下来在Rancher中创建一个新的集群,点击页面上的 创建集群 按钮,开始创建一个新的K8S/K3S集群。 注意:在这里请选择 导入现有的Kubernetes集群 (Import) ,而不是其他的新建选项! 1559176852965.png 下方的集群名称随意输入一个即可,反正以后可以随意改。 成员角色目前无需改动,直接点击 创建 完成向导。 1559176990814.png 完成后我们会得到导入K3S集群所需的命令,请保存好第三条命令以备后用。 为什么不是第二条?因为目前访问HTTPS API使用的是自签证书,直接用第二条会产生证书不信任的报错。 1559177084801.png 如果你一不小心关掉了窗口,可以在首页点击右侧的三个点,然后点击升级,就可以看到上面的集群导入命令。 1559177232193.png 到这一步,我们已经完成了Rancher Server端的准备工作。接下来,我们将着手准备部署K3S集群。 Step 3: 安装K3S集群 – 国内服务器的准备工作 注意:如果你的服务器中国大陆境内,请参考下面的步骤执行;如果你的服务器在海外,请直接跳到Step 4。 出于国内拉取AWS S3 Bucket感人的速度,以及 k8s.gcr.io 被墙的无奈,我在这里额外增加了针对中国大陆境内服务器的步骤。如果你使用的是海外的服务器,这一步你无需操作,请继续下面的教程。 首先,我们下载K3S所需的Binary到本地服务器(或者在服务器端挂V*P*N进行下载): <span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/github.com/rancher</span><span class="hljs-regexp">/k3s/releases</span><span class="hljs-regexp">/download/v</span><span class="hljs-number">0</span>.<span class="hljs-number">5.0</span>/k3s-arm64 1 <span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/github.com/rancher</span><span class="hljs-regexp">/k3s/releases</span><span class="hljs-regexp">/download/v</span><span class="hljs-number">0</span>.<span class="hljs-number">5.0</span>/k3s-arm64 之后上传此Binary到服务器端的 /usr/local/bin/k3s,并赋予可执行属性: <span class="hljs-keyword">chmod</span> +<span class="hljs-keyword">x</span> /usr/<span class="hljs-keyword">local</span>/bin/k3s 1 <span class="hljs-keyword">chmod</span> +<span class="hljs-keyword">x</span> /usr/<span class="hljs-keyword">local</span>/bin/k3s 这一步完成后,我们来着手解决最头疼的问题:pause 镜像被墙无法拉取。 这个镜像对于很多刚接触K8S的用户来讲非常头疼,我也是在这里卡了好久最后才算弄出来个解决方案。 出于大家的部署方便考虑,我将这份镜像制成了多份副本并分发出来,大家可以根据自己的需求选择最佳的解决方案。 阿里云北京镜像分流: docker pull registry.cn-beijing.aliyuncs.com/ilemonrain/pause-amd64:3.1 docker tag registry.cn-beijing.aliyuncs.com/ilemonrain/pause-amd64:3.1 k8s.gcr.io/pause:3.1 12 docker pull registry.cn-beijing.aliyuncs.com/ilemonrain/pause-amd64:3.1docker tag registry.cn-beijing.aliyuncs.com/ilemonrain/pause-amd64:3.1 k8s.gcr.io/pause:3.1 阿里云上海镜像分流: docker pull registry.cn-shanghai.aliyuncs.com/ilemonrain/pause-amd64:3.1 docker tag registry.cn-shanghai.aliyuncs.com/ilemonrain/pause-amd64:3.1 k8s.gcr.io/pause:3.1 12 docker pull registry.cn-shanghai.aliyuncs.com/ilemonrain/pause-amd64:3.1docker tag registry.cn-shanghai.aliyuncs.com/ilemonrain/pause-amd64:3.1 k8s.gcr.io/pause:3.1 阿里云广州镜像分流: docker pull registry.cn-shenzhen.aliyuncs.com/ilemonrain/pause-amd64:3.1 docker tag registry.cn-shenzhen.aliyuncs.com/ilemonrain/pause-amd64:3.1 k8s.gcr.io/pause:3.1 12 docker pull registry.cn-shenzhen.aliyuncs.com/ilemonrain/pause-amd64:3.1docker tag registry.cn-shenzhen.aliyuncs.com/ilemonrain/pause-amd64:3.1 k8s.gcr.io/pause:3.1 Google Mirror分流 (Docker Hub): docker pull mirrorgooglecontainers/pause:3.1 docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1 12 docker pull mirrorgooglecontainers/pause:3.1docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1 本地镜像分流 (tar包格式): wget -qO- https://download.ilemonrain.com/Kubernetes/pause-amd64/pause.tar | docker load 1 wget -qO- https://download.ilemonrain.com/Kubernetes/pause-amd64/pause.tar | docker load 完成镜像导入后确认是否导入成功: docker images | grep "k8s.gcr.io/pause" 1 docker images | grep "k8s.gcr.io/pause" 如果出现类似于这样的结果: k8s.gcr.io/pause 3.1 da86e6ba6ca1 17 months ago 742kB 1 k8s.gcr.io/pause 3.1 da86e6ba6ca1 17 months ago 742kB 则说明导入成功,可以继续接下来的步骤。 Step 4: 安装K3S集群 接下来,我们开始K3S集群的部署。 官方提供了很好用的一键安装脚本,我们只需要使用一键脚本即可完成K3S环境的安装: curl -sfL https://get.k3s.io | sh - 1 curl -sfL https://get.k3s.io | sh - 安装完成后,我们需要调整下K3S的服务配置文件,以将K3S的默认容器引擎从Containerd切换到Docker。 修改K3S服务的配置文件: vim /etc/systemd/system/multi-user.target.wants/k3s.service 1 vim /etc/systemd/system/multi-user.target.wants/k3s.service 文件内容如下: [Unit] Description=Lightweight Kubernetes Documentation=https://k3s.io After=network-online.target [Service] Type=notify EnvironmentFile=/etc/systemd/system/k3s.service.env ExecStartPre=-/sbin/modprobe br_netfilter ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/local/bin/k3s server KillMode=process Delegate=yes LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity TimeoutStartSec=0 Restart=always [Install] WantedBy=multi-user.targe 12345678910111213141516171819202122 [Unit]Description=Lightweight KubernetesDocumentation=https://k3s.ioAfter=network-online.target [Service]Type=notifyEnvironmentFile=/etc/systemd/system/k3s.service.envExecStartPre=-/sbin/modprobe br_netfilterExecStartPre=-/sbin/modprobe overlayExecStart=/usr/local/bin/k3s serverKillMode=processDelegate=yesLimitNOFILE=infinityLimitNPROC=infinityLimitCORE=infinityTasksMax=infinityTimeoutStartSec=0Restart=always [Install]WantedBy=multi-user.targe 在这里我们需要修改ExecStart的值,将其修改为: /usr/local/bin/k3s server --docker --no-deploy traefik 1 /usr/local/bin/k3s server --docker --no-deploy traefik 之后保存退出,执行命令重新加载新的服务配置文件: systemctl daemon-reload 1 systemctl daemon-reload 完成后重启K3S服务: service k3s restart 1 service k3s restart 稍等数十秒,之后通过命令确认K3S集群是否就绪: k3s kubectl get node 1 k3s kubectl get node 如果得到类似如下的结果: <span class="hljs-selector-tag">NAME</span> <span class="hljs-selector-tag">STATUS</span> <span class="hljs-selector-tag">ROLES</span> <span class="hljs-selector-tag">AGE</span> <span class="hljs-selector-tag">VERSION</span> <span class="hljs-selector-tag">k3s01</span><span class="hljs-selector-class">.ilemonrain</span><span class="hljs-selector-class">.io</span> <span class="hljs-selector-tag">Ready</span> <<span class="hljs-selector-tag">none</span>> 3<span class="hljs-selector-tag">m34s</span> <span class="hljs-selector-tag">v1</span><span class="hljs-selector-class">.14</span><span class="hljs-selector-class">.1-k3s</span><span class="hljs-selector-class">.4</span> 12 <span class="hljs-selector-tag">NAME</span> <span class="hljs-selector-tag">STATUS</span> <span class="hljs-selector-tag">ROLES</span> <span class="hljs-selector-tag">AGE</span> <span class="hljs-selector-tag">VERSION</span><span class="hljs-selector-tag">k3s01</span><span class="hljs-selector-class">.ilemonrain</span><span class="hljs-selector-class">.io</span> <span class="hljs-selector-tag">Ready</span> <<span class="hljs-selector-tag">none</span>> 3<span class="hljs-selector-tag">m34s</span> <span class="hljs-selector-tag">v1</span><span class="hljs-selector-class">.14</span><span class="hljs-selector-class">.1-k3s</span><span class="hljs-selector-class">.4</span> 则说明K3S集群启动成功。 此教程目前只做单机K3S集群的部署讲解,后续教程会讲如何组建多机K3S集群,以及通过一个Rancher控制多个K3S集群。 Step 5: 导入K3S集群到Rancher 还记得在Step 2中保存好的导入命令么?是时候该派上用场了。 现在的Rancher Server上,显示集群状态为Pending,就像这样: 1559179636850.png 这是因为我们还未导入集群,这一步我们将导入集群,并建立Rancher Server与K3S集群的联系。 在K3S的主控节点(一般情况下,第一个节点都是主控制器,也叫Server节点)上,执行命令,导入集群: <span class="hljs-attribute">curl</span> --insecure -sfL https://10.248.21.2/v3/import/jr42wvdhk4w94htxxtf5hv424rsjjz6hzq9vl2lj8q9dnb8dgcwgzn.yaml | kubectl apply -f - 1 <span class="hljs-attribute">curl</span> --insecure -sfL https://10.248.21.2/v3/import/jr42wvdhk4w94htxxtf5hv424rsjjz6hzq9vl2lj8q9dnb8dgcwgzn.yaml | kubectl apply -f - 注意:每个集群的导入命令都不一样,请不要直接照搬教程中的导入命令! 之后Shell中会返回一下信息,说明集群导入配置成功: <span class="hljs-keyword">namespace</span>/cattle-system created serviceaccount/cattle created clusterrolebinding.rbac.authorization.k8s.io/cattle-admin-binding created secret/cattle-credentials<span class="hljs-number">-7</span>c9ef0a created clusterrole.rbac.authorization.k8s.io/cattle-admin created deployment.extensions/cattle-cluster-agent created daemonset.extensions/cattle-node-agent created 1234567 <span class="hljs-keyword">namespace</span>/cattle-system createdserviceaccount/cattle createdclusterrolebinding.rbac.authorization.k8s.io/cattle-admin-binding createdsecret/cattle-credentials<span class="hljs-number">-7</span>c9ef0a createdclusterrole.rbac.authorization.k8s.io/cattle-admin createddeployment.extensions/cattle-cluster-agent createddaemonset.extensions/cattle-node-agent created 回到Rancher界面,稍微等数十秒,我们会发现Pending状态变成了Waiting状态: 1559179824562.png 出现这个提示说明Rancher已经收到K3S的注册请求,正在完成K3S集群的注册工作,再等数十秒种的时间即可完成K3S集群的导入工作: 1559179926951.png 到这里,我们成功的完成了Rancher 2.x和K3S的对接工作,可以像操作K8S集群那样操作K3S集群了。 Step X: 一点小小的总结 为什么我会用K3S来取代K8S,主要是因为自己手里的服务器配置不太够,如果贸然上K8S的话,会导致系统资源全被K8S吃光,从而没有资源再去跑其他的业务。谨以此文,希望能够做各位运维、开发、Geeker前行路上的指路明灯,为大家扫清前进的障碍,加速业务容器化的迁移进程。 本文章欢迎各大平台转载使用,但请注明出处。 目前此文章已由Rancher Labs官方微信公众号转载,传送门 >> 我的联系方式: 站务相关E-mail: ilemonrain@ilemonrain.com 工作生活相关E-mail: ilemonrain@foxmail.com Telegram: https://t.me/ilemonrain Telegram Chatbot: https://t.me/ilemonrain_chatbot