
Kubernetes | 搭建环境
风靡IT界很久的Kubernetes,我因为没有需求,也没有日常维护一套k8s服务器的能力,就一直没有折腾。
最近淘了一个垃圾服务器,E3 v2只要不到2k,加上32G内存2k整。有条件了就瞎玩呗,k8s走起。
方案
废话不多说了,k8s搭建有几种方案。
开发用的单节点
有很多现成工具,比如说
- minikube
- Docker for Mac
- microk8s
- kind
由于我是希望能跑一些负载真正用起来,而不是开发用的环境,所以我并没有用这些方案。
不过我在Mac上的开发环境用了Docker for Mac,自带k8s环境,只要打开选项就行,比较简单省事儿,不开心的地方在于我Mac空间本来就不大够,结果这一下更惨了。
包括Mac在内的所有平台,如果需要一个开发环境,minikube也挺好的。
生产可用的方案
生产可用的方案主要是在多个节点上搭建master和worker节点。
master节点主要是api server和数据库一类东西,也叫control plane。worker则是跑真正的负载的节点。
一般可以用的工具有
- kubeadm
- kops
- k3s
- kubespray
等等。
其中kubeadm是官方比较推荐的。一会儿会简单说一下搭建过程,但是这条路我没有完全走通,只是觉得解决了这些问题,其他的方案可以了,kubeadm应该也没问题。
而我用的是k3s,一个比较轻量级的方案,用了k8s官方的大部分代码,剔除了少部分用不到的。
或者公司有钱或者自己有钱的话,也可以直接用云端的k8s方案。
组件
容器这个概念一开始是LXC提出的,后来有了Docker这个Go的杀手级应用然后被广大群众熟悉。其实就是利用内核的特性,隔离一部分资源,让进程以为自己在一个独立的机器上运行。在其他系统上也有类似的概念,比如说BSD的jail,或者Windows后来有的容器。
容器隔离开的资源主要是计算、存储、网络这些。简单说就是
- PID隔离:认为自己是独立的一些进程,看不到宿主一侧和其他容器里面的其他进程。
- 内存:完全独立的内存,且有自己的一套共享库。
- FS:可以使用独立的一套文件系统,且无法访问其他的文件和目录,有自己的挂载点,和宿主这边没有关系。
- 网络:可以虚拟化一套网络,容器可以和宿主不共用网络。
这套东西Docker用,其他的应用也在用,大家各自写各自的都造一套轮子,有没有意思?没意思啊,所以Docker后来就把这部分分离了出去,叫containerd。
但是其他人可能已经写了类似的东西想要用进来,或者我就是想拓展这个生态,怎么办?社区后来又定义了一套接口,只要符合这个接口的程序,就可以拓展docker或者containerd的能力,主要就是 容器运行时接口 、 容器网络接口 、 容器安全接口 ,分别负责容器要怎么启动一个进程、怎么配置容器的网络和怎么操作容器里面的文件系统,除此之外还有一个OCI,主要是定义了容器的构成,包括什么东西,怎么样描述这些东西。
运行时
其中常见的CRI就包括
- docker
- containerd: 去掉docker无用的部分
- cri-o: 在k8s里面用的比较多
- kata container: 借助了kvm的力量,相当于轻量级虚拟机做容器,口号是:“容器的速度,虚拟机的安全性“ …
网络
Docker和k8s可以通过插件来拓展网络的能力,解决的大部分主要是进出流量的管理和路由的问题。
- flannel
- weave net
- calico …
搭建过程
k8s搭建其实就是这么几部分:
- 满足系统基本要求
- 安装docker或者containerd,最好配置一下cgroup driver
- 禁用swap
- 初始化主节点
- 安装网络插件
- 把其他节点加入集群
- (部署应用)
kubeadm
这部分是我一开始尝试的方法,尝试的版本是1.18.5。
简单说就是
- 主节点:
kubeadm init
- 如果网络选择flannel,那么需要
kubeadm init --pod-network-cidr=10.244.0.0/16
- 如果有多个网卡,建议再加上
--apiserver-advertise-address=<ip>
选项 - kubeadm init输出的最后几行会告诉你,可以把配置文件从/etc/kubernetes/admin.conf复制出来,直接复制粘贴几个命令直接执行就行
- 最后几行还会有一段kubeadm join的命令,复制下来,后面会用
- 如果网络选择flannel,那么需要
- 选择其中一个网络插件
- 大部分都是应用一个k8s的资源定义
- flannel
- 项目:https://github.com/coreos/flannel/
- 直接执行命令也行:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- weave net:
- 项目:https://www.weave.works/oss/net/
- 命令:
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
- 其他的我没试过,自己可以查查
- 挨个在子节点上执行那个kubeadm join的命令
如果子节点在很久以后才加进来,可以执行kubeadm token create --print-join-command
,就会打印这么一个命令出来。
k3s
k3s是我最后采用的方案,因为资源占用小,而且刚刚好尝试到这里的时候解决了其他的问题。
k3s的安装相对比较简单,而且内置了网络插件的配置,所以不大需要我们做什么。如果需要配置的话,可以直接看文档,我就用最简单的配置了。
- 主节点:
curl -sfL https://get.k3s.io | sh -
- 执行以后,cat一下
/var/lib/rancher/k3s/server/token
,会有一个token,复制一下
- 执行以后,cat一下
- 从节点:
curl -sfL https://get.k3s.io | K3S_URL=https://主节点IP:6443 K3S_TOKEN=刚才复制的token sh -
会默认配置flannel作为网络插件,同时会安装traefik作为ingress controller
客户端一侧要做的事情
kubectl
装一个kubectl是一切的基础。
kube/config
复制出来master节点的/etc/kubernetes/admin.conf内容
- kubectl: 贴到自己的$HOME/.kube/config文件里面。如果目录不存在就新建一个,如果有现有的要用的文件,建议参考k8s文档配置客户端访问多个集群
- android/ios: kubenav
dashboard
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/latest/aio/deploy/recommended.yaml
使用方法参考项目页面
自动化部署工具
k8s有不少自动化、简化部署应用的工具。
- helm: https://github.com/helm/helm 自称是k8s上的包管理工具,感觉其实是一个manifest托管站
- arkade: https://github.com/alexellis/arkade 主要是自动化安装工具或者部署openfaas这类app
遇到的坑
Linux本身的问题
虚拟机
用cockpit-machines的时候没有创建网络,所以我手动加了一个Direct Attachment的网卡,结果节点间不能通信。
后来查了资料,似乎是因为直接附加在物理网卡上的这种方法必须把包直接发出去,而不能发给host或者其他guest,导致无法通信。
我一拍脑壳,那也没关系啊,加一个路由,互相之间全部从路由转发。结果还是不行,似乎有的插件会找MAC地址,这样没有arp互相不认MAC的情况,似乎连接还是有问题。
最后还是尝试了一圈,建了一个NAT网络,虚拟机都用这个NAT网络就ok了。
debian
RHEL系列逐渐的不再提供docker,centos8虽然可以用centos7的repo,但是我不觉得这是个好做法,所以我干脆使用了debian buster。这倒不是啥问题。
遇到的问题主要是debian上的iptables实现有两套:iptables-legacy和iptables-nft,默认使用iptables-nft。
结果因为某些我还不是特别明白的原因,网络插件通信有问题。具体来说就是用iptables/iptables-nft和iptables-legacy会产生两套iptables规则。
解决方案:都用iptables-legacy:sudo update-alternatives --set iptables /usr/sbin/iptables-legacy