前情提要
去年使用树莓派搭建了一个k8s集群,当时对这方面了解得很少,所以只是搭建了一个简单集群,安装了网络插件,只有一个简单的dashboard, 没有部署任何实际的应用,以前的文章链接:手把手教大家使用树莓派4B搭建k8s集群
最近又心血来潮,重新用积木做了一个新的机箱,测试部署一个应用。今天总结一下最近经历所有的过程和问题,供大家参考
前置问题处理
更换网络插件
上一篇文章写到安装了网络插件colico,也就是最近发现colico插件pod启动失败,试了很久都没有成功只有重装了,按之前的教程安装也不行,只能重新fannel插件。
删除网络插件
先删除网络插件
kubectl delete -f calico.yaml
复制代码
此时有一个tunl0的虚拟网卡残留,可以使用ifconfig查看,卸载它,因为自己尝试了很多遍,把很多条shell命令组合成了一条命令,可以根据自己的实际情况修改:
ifconfig tunl0 down;ip link delete tunl0;rm -f /etc/cni/net.d/*;kubectl delete -f calico.yaml;systemctl start kubelet; systemctl start docker
复制代码
集群重置
在3台机器上执行集群初始化命令:
kubeadm reset
复制代码
三台机器删除掉配置文件:
rm -rf $HOME/.kube;rm -rf /etc/cni/net.d
复制代码
重启docker和kubelet,防火墙规清除:
systemctl daemon-reload;systemctl stop kubelet; systemctl stop docker; iptables --flush; iptables -tnat --flush;systemctl start kubelet; systemctl start docker
复制代码
集群安装
跟上篇文章一样,这里就不详细描述了 Master节点安装
sudo kubeadm init --image-repository=registry.aliyuncs.com/google_containers --kubernetes-version=v1.20.0 --apiserver-advertise-address=192.168.2.181 --pod-network-cidr=192.168.0.0/16 --ignore-preflight-errors=all
复制代码
Node节点加入命令
kubeadm join 192.168.2.181:6443 --token jqll23.kc3nkji7vxkaefro --discovery-token-ca-cert-hash sha256:1b475725b680ed8111197eb8bfbfb69116b38a8d2960d51d17af69188b6badc2 --ignore-preflight-errors=all
复制代码
查看所有的Node命令:
kubectl get pods --all-namespaces
复制代码
有时候机器重启后执行命令会报错: The connection to the server localhost:8080 was refused - did you specify the right host or port?
解决方案 : 原因:kubernetes master没有与本机绑定,集群初始化的时候没有绑定,此时设置在本机的环境变量即可解决问题。
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
source /etc/profile
复制代码
可以把source /etc/profile
放在开机自动执行的脚本中彻底解决这个问题
pod运行错误,查看日志
自己尝试了很多遍,经常会安装网络插件之后pod没有运行成功,可以使用一下命令查看日志原因:
kubectl logs -f test-k8s-68bb74d654-9wwbt -n kube-system
复制代码
test-k8s-68bb74d654-9wwbt
就是具体的pod名称
安装网络插件
使用了官方的yaml文件
curl -sSL https://raw.githubusercontent.com/coreos/flannel/v0.12.0/Documentation/kube-flannel.yml | kubectl apply -f -*
复制代码
没想到直接成功了,之前都是无法连接10.1244.***.**的报错.
查看所有pod
kubectl get pods --all-namespaces
复制代码
现在是第一个应用安装完成了,pod名称test-k8s的应用就是我安装的应用,它命名空间是default的,跟其他的不同。
查看所有Node
kubectl get node --all-namespaces
复制代码
跟上个命令一样的,改了一个地方
安装第一个应用
制作镜像
安装应用就应该写一个yaml文件,和一个可用的镜像,我参考的是B站的广州云科
的视频教程,但是他的测试的应用是基于X86平台的,镜像直接运行报错如下:
所以只有自己重新制作镜像,先找到项目地址:test-k8s 把代码全部克隆到树莓派机器上:
要弄一个镜像仓库提供给集群拉取,然后我自己测试使用的阿里云的容器镜像服务,要设置成开放的仓库,允许所有的人拉取这个镜像
别人的DockerFile已经写好了我们直接使用docker build命令打包镜像(现在为了重新推送测试,我把所有镜像都和容器删掉) 主要根据阿里云的教程就行了,如下:
打包&推送到阿里云
先本地打包,打包镜像名为k8s,-t
为镜像标签的简写,tag的意思。可以在构建中设置多个标签
docker build -t test-k8s .
复制代码
镜像打一个新tag
docker tag test-k8s:latest registry.cn-shenzhen.aliyuncs.com/koala9527/testapp:latest
复制代码
推送
docker push registry.cn-shenzhen.aliyuncs.com/koala9527/testapp:latest
复制代码
到现在这个镜像就在阿里云的容器镜像服务中了,镜像地址为: registry.cn-shenzhen.aliyuncs.com/koala9527/testapp:latest
写第一个应用的yaml文件
文件名testapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
# 部署名字
name: test-k8s
spec:
replicas: 3
# 用来查找关联的 Pod,所有标签都匹配才行
selector:
matchLabels:
app: test-k8s
# 定义 Pod 相关数据
template:
metadata:
labels:
app: test-k8s
spec:
# 定义容器,可以多个
containers:
- name: test-k8s # 容器名字
image: registry.cn-shenzhen.aliyuncs.com/koala9527/testapp:v1 # 镜像
resources:
requests:
cpu: 100m
复制代码
这里稍微解释复习一下这些资源描述文件中字段得意思,虽然上篇文章也有解释
apiVersion
:api版本,我的理解就是资源控制的相关版本控制,k8s里的功能在高速迭代,不同的资源控制器使用不同的api版本,不同版本集群支持的api不同,写的yaml文件需要配合真实的集群环境,资源控制器类型就是用kind
字段指定。
可以使用kubectl api-versions
查看集群的api版本
kind
:控制器类型,集群里面的所有资源都被k8s高度抽象化,kind就是表明这些资源的类型,Deployment
就是一个定义一个多副本的无状态资源对象。
name: test-k8s
:指定资源控制器的名字为test-k8s replicas
:初始化指定的pod的个数 matchLabels
:选择器标签,要用其他资源控制指定这个资源的时候用这个标签值
template
这个字段下面就是包含这个pod的相关数据,app: test-k8s
指定pod的名字,image
pod的镜像拉取地址,requests
申请的CPU资源,0.1m等于0.1个CPU资源。
部署应用
kubectl apply -f testapp.yaml
复制代码
这时候就有3个pod了 可以使用 kubectl get pod -o wide
查看pod详细信息,主要是看下IP:
kubectl get pod -o wide
复制代码
登录其中一个pod访问另一个pod试试(这里是进入第一个pod访问第二个pod):
kubectl exec -it test-k8s-68b9f5c6c7-hn25x -- bash
curl 10.244.1.173:8080
复制代码
效果如图: 可以看到输出了正确的pod得名称
但是这时候只能在pod之前进行互相访问,上篇文章有说pod可以一个单独的物理机,共用一个网络,要供集群外访问就要新建一个另外的资源,下面接着说。
新建service资源控制器
yaml文件
service的特性:
- Service 通过 label 关联对应的 Pod
- Servcie 生命周期不跟 Pod 绑定,不会因为 Pod 重创改变 IP
- 提供了负载均衡功能,自动转发流量到不同 Pod
- 可对集群外部提供访问端口
- 集群内部可通过服务名字访问
所有的资源都是通过yaml文件描述,写一个描述servie的yaml文件,文件名为service.yaml
apiVersion: v1
kind: Service
metadata:
name: test-k8s
spec:
selector:
app: test-k8s
type: NodePort
ports:
- port: 8080 # 本 Service 的端口,内部访问
targetPort: 8080 # 容器端口,也就是test-k8s这个应用的
nodePort: 31000 #暴露出集群的端口
复制代码
值得说的是service这个资源控制的中type
这个关键字类型,这里指定的是NodePort
类型,在每个Node上开放一个端口,可以访问,如果不指定这个type,默认的类型就是ClusterIp
,这个就是不允许集群外访问的,只允许集群内部访问,其他还有LoadBalance
类型,负载均衡的意思,一般是云厂商提供的这个资源类型,不常见。
还要注意NodePort暴露的端口固定范围为: 30000-32767
应用Service:
和应用Deployment一样:
kubectl apply -f service.yaml
复制代码
查看k8s中Service资源
kubectl get svc
复制代码
测试效果
这个机器的内网IP为192.168.2.187,刚才设置的端口为31000
动态扩缩容
安装资源指标查看工具
使用动态扩缩容之前需要安装一个资源指标获取工具,用来监控集Node,Pod资源占用CPU,运行内存情况,名为metrics-server
,集群默认不会安装这个,安装十分简单,在官方的GitHub下载安装:
wget <https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml>
kubectl apply -f components.yaml
复制代码
后面出错了,其相关pod不能启动,需要替换yaml文件内的一段内容,替换成如下,具体原因不清楚:
接下里就可以使用top
命令查看pod和node CPU和运行内存资源占用情况
安装水平自动伸缩服务
控制pod的动态扩缩容又是一个资源控制器,叫HorizontalPodAutoscaler
,字面意思是水平自动伸缩,跟service.yaml一样简单,文件名:hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
namespace: default
name: test-k8s-scaler
labels:
app: test-k8s-scaler
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: test-k8s
minReplicas: 2
maxReplicas: 100
targetCPUUtilizationPercentage: 45
复制代码
水平自动伸缩控制器metadata里的数据来表示这个控制器的基本信息,spac里面的scaleTargetRef
用来指定监控的哪些资源,minReplicas
指定最小副本数,maxReplicas
指定副本数,这个最小副本数会覆盖最初的定义replicas中的数量,targetCPUUtilizationPercentage
指定触发伸缩时的CPU指标,k8s有一个复杂的算法(《Kubernetes in Action》这本书中有简要说明),会在一定的间隔观察这些pod资源使用情况来进行自动调整, 这里我体会到的是只要pod的CPU占用超过45%就会触发扩容策略进行扩容,还可以指定其他指标进行监控,但是一般是CPU和运行内存。
使用kubectl apply -f hpa.yaml
安装这个自动伸缩控制器
还可以使用kubectl get hpa
查看这个水平自动伸缩控制器的基本状态,现在是0%
使用AB压力测试自动扩缩
下载地址 在windows上直接下载,解压,然后进入到bin目录运行一下命令:
./ab.exe -n 10000 -c 100 http://192.168.2.181:31000/
复制代码
意思是总共1w个请求,100个线程同时请求 然后执行watch kubectl get hpa,pod
实时监控自动伸缩的情况和pod个数详细参数
请求完成等几分钟pod个数又会回到2个,到这时候所有的测试完成了。
总结
使用可以demo的应用部署到集群里面了,整个过程并不复杂,没有复杂烧脑的特性,K8s里的水平扩缩容是最吸引我的地方,所以部署应用成功后第一步就尝试实现这个功能了,接下来准备会结合Gitlab进行真的CI/CD用自动部署应用,不用手动敲命令了,提交代码合并分支就触发部署命令,或者尝试安装其他可以提供真正服务的应用,用来发挥它真正的作用,感谢大家看到这里。