《面向服务的软件系统》实验三:微服务与容器技术
《面向服务的软件系统》实验报告
——实验三:微服务与容器技术
姓名: 石卓凡 学号: 120L021011
目录
2. 通过Jenkins实现对k8s的自动化构建和自动化部署 6
3、 Kubernetes有哪些核心组件,其功能是什么? 12
4、 Kubernetes搭建过程中遇到的问题,与解决办法。 18
容器虚拟化和传统虚拟化的区别是什么?
图1.传统虚拟化和容器虚拟化
概念介绍
容器虚拟化和传统虚拟化同属于虚拟化技术
传统虚拟化:
虚拟出多个操作系统共同使用硬件资源即虚拟机,虚拟机需要安装操作系统才能执行应用程序,需要Hypevisor和Guest OS
简单说来就是通过在住操作系统上安装虚拟机管理系统(比如VMware)然后创建虚拟机,虚拟各种硬件,在虚拟机安装从操作系统,在从操作系统中安装部署应用
容器虚拟化:
一般通过docker实现,在单个操作系统上虚拟出多个资源组共同使用硬件资源,透过共享Host OS的作法,取代一个一个Guest OS的功用。
简单来说,通过docker容器,通过将应用程序及其所需要的依赖,函数库,环境配置打包成为一个镜像,然后形成进程作为容器。也就是软件运行所需要的所有的资源打包放到一个隔离的容器,不需要捆绑一个操作系统
区别:
特性 | Docker | 虚拟机 |
---|---|---|
性能 | 接近原生 | 性能较差 |
硬盘占用 | 一般为MB,占用体积小 | 一般为GB,占用体积大 |
启动 | 秒级,启动快 | 分钟级,启动慢 |
操作系统覆盖 | 仅是内核支持的os | 支持linux,window,mac等 |
技术成熟度 | 更加成熟,技术更新,更受欢迎 | 较落后 |
方案 | 容器内没有自己的内核且也没有进行硬件虚拟,容器内的应用进程直接运行于宿主的内核 | 虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程 |
资源利用率 | Docker 对系统资源的利用率很高,一台主机上可以同 时运行数千个 Docker 容器。 容器除了运行其中的应用外,基本不消耗额外的系统资 源,使得应用的性能很高,同时系统的开销尽量小 | 虚拟机对于系统资源的利用率较低,一台主机同时打开多台虚拟机所需要的要求远远大于docker的需求 |
管理难度 | 管理简单,使用 Docker,只需要小小的修改,就可以替代以往大 量的更新工作 | 管理复杂,需要进入虚拟机去操作 |
资源隔离 | 能力较差,Docker是利用cgroup实现资源限制的,只能限制资源消耗的最大值,而不能隔绝其他程序占用自己的资源 | 资源隔离能力较强,因为不同虚拟机直接拥有不同硬件 |
安全性 | Docker目前并不能分辨具体执行指令的用 户,只要一个用户拥有执行Docker的权限,那么他就可以对Docker的容器进行所有操作,不管该容器是否是由 该用户创建,存在一定的安全风险。 | 安全性相对于docker较强,需要提供虚拟机用户密码验证 |
区别总结:
Docker是一个系统进程,虚拟机是在操作系统中的操作系统。
简单来说运行一个程序需要环境,而传统虚拟化技术是通过虚拟出一整个操作系统来提供所需要的环境,而容器虚拟化技术是通过docker的镜像中来包含所需要的特定依赖,函数库,环境配置资源。
Docker体积小,启动速度快,性能好。虚拟机体积大,启动速度慢,性能一般
如何实现 Kubernetes 自动化部署?
图2.1.1自动化部署概念图
通过devops实现k8s自动部署
自动化部署指的是,通过自动化工具将应用介质部署到指定环境中去。 自动化部署只是持续交付和持续部署流程中的一个功能单元
DevOps 自动化,运用技术,在减少人工辅助的情况下执行各项任务,以此来简化运维与开发团队之间的反馈循环工作,从而将迭代更新更快地部署到生产应用中。因此经常使用devops来实现k8s的自动部署
通过Devops实现自动部署k8s的过程:
- 创建容器镜像仓库
- 在DevOps创建流水线
- 创建容器
- 自动化升级
通过Jenkins实现对k8s的自动化构建和自动化部署
图2.1.2利用jenkins自动化部署概念图
一般过程
- 提交项目代码并打上git tag,上传代码及tag至gitlab或者github
- Github或者gitlab通过webhook自动触发jenkins执行任务
- jenkins获取代码,执行代码编译、构建docker镜像、上传docker镜像至harbor镜像仓库、执行kubectl命令部署至k8s。
具体过程
- 部署jenkins
- 环境准备
- 部署jenkins
- 部署有状态的jenkins Pod
- 创建jenkins ingress
- jenkins认证授权
- 配置jenkins
- Jenkins在K8S中动态创建代理
- 构建Jenkins Slave镜像
- Dockerfile配置文件
- jenkins-slave启动脚步
- maven源配置文件settings.xml
- 构建镜像, 并推送至私有镜像仓库
- Jenkins Pipeline构建流水线发布
- 生成git流水线语法
- pipeline语法
- 编写Pipeline脚本完成CI阶段
- 创建pipeline流水线中各个凭证
- parameters参数化生成
- 拉取代码片段pipeline生成
- 完整的基于jenkins pipeine脚本CI阶段构建
- 编写Pipeline脚本完成CD阶段
- 持续部署pipeline片段生成
- 持续部署pipeline代码
- 构建完成cd阶段
- 添加回滚操作pipeline
- 添加构建状态告警pipeline
本次实验通过传统方式实现k8s自动部署应用
以本实验过程来举例说明一般部署过程
- 编写程序代码
本实验中是编写server.js
而一般可以通过对springboot模块进行maven的package获取target文件对其进行打包
比如通过对大作业springcloud的某个微服务进行打包成为app.jar
图2.1.3打包app.jar图
- Docker镜像的打包和上传:
本实验对server.js进行打包,新建Dockerfile文件,写入
Dockerfile:
FROM node:6.14.2 使用node:6.14.2基础镜像
EXPOSE 8080暴露端口8080
COPY server.js .
CMD node server.js基于dockerfile深层的image运行container的默认运行程序指定为这个
docker build -t hello_world:v2 .通过docker对程序进行构建,并命名为hello_wolrd版本v2
docker tag hello_world:v2 944613709/hello-world:v2 对刚才的hello_wolrd:v2进行打标签(换名字)改为944613709/hello-world以便于之后上传dockerhub
docker push 944613709/hello_world:v2上传dockerhub
图2.1.4 dockerhub
- 部署到 Kubernetes 中
本实验用的是yaml方式,yaml方式相对于原始的纯cmd命令要效率高一些
新建hello_world.yaml文件
命令kubectl create -f ./hello_world.yaml 执行yaml文件来部署
图2.1.5 yaml文件内容
其中部署Service,命名为hello-world
模式为Nodeport,pod暴露8080映射为该服务的80端口
集群内其他节点可以通过80来访问pod的8080端口
并且nodePort=31611,让集群外节点可以通过31611来访问pod的8080端口
图2.1.6 yaml文件内容
其中部署一个Deployment命名为hello-world
其中给定副本数量为3,每一个容器镜像为944613709/hello_world,容器端口为8080
图2.1.7 yaml文件内容
Kubernetes有哪些核心组件,其功能是什么?
官方定义的核心组件:
参考官方文档:
https://kubernetes.io/zh-cn/docs/concepts/overview/components/
图3.1 k8s所需的组件
图3.2 k8s所需的组件关系图
组件分类 | 组件名 | 功能介绍 |
---|---|---|
控制平面组件 | 控制平面组件 | 控制平面组件会为集群做出全局决策,比如资源的调度 |
kube-apiserve | API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。 | |
etcd | 一致且高度可用的键值存储,用作 Kubernetes 的所有集群数据的后台数据库 | |
kube-scheduler | kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。 | |
kube-controller-manager | kube-controller-manager 是控制平面的组件, 负责运行控制器进程。 | |
cloud-controller-manager | 云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。 | |
Node 组件 | Node 组件 | 节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境 |
kubelet | kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中 | |
kube-proxy | kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) | |
容器运行时 | 容器运行环境是负责运行容器的软件 | |
插件 | 插件 | 插件使用 Kubernetes 资源(DaemonSet、 Deployment 等)实现集群功能 |
DNS | 为 Kubernetes 服务提供 DNS 记录 | |
Web 界面 | 容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中, 并提供浏览这些数据的界面 | |
集群层面日志 | 集群层面日志机制负责将容器的日志数据保存到一个集中的日志存储中, 这种集中日志存储提供搜索和浏览接口 |
个人认为在使用中的接触到的关键组件:
组件 | 组件名 |
---|---|
Node | |
NameSpace | |
Pod | |
Deployment | |
Service | |
Ingress | |
Volume | |
Label | |
Master |
图3.3 k8s组件关系图
Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行
Namespace:命名空间
实现多套环境的资源隔离或者多租户的资源隔离。
用于隔离资源使得不同空间的pods不会互相干扰
Pod:运行中的一组容器,pod是k8s中应用的最小单位
程序要运行必须部署在容器中,而容器必须存在于Pod中。一个Pod容器中运行着多个container容器
图3.4 pod关系图
Deployment:
Pod是最小的控制单元,但是k8s很少直接控制Pod
一般利用Deployment控制Pod,使Pod拥有多副本,自愈,扩缩容等能力
图3.4 deployment关系图
Service:
service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡
Service典型类型:
ClusterIP:它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问NodePort:类型的Service允许NodeIp:NodePort来访问service
图3.4 service关系图
Ingress:
Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求
实际上就是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx
Volume:
存储卷,用来管理k8s存储,一个volume卷可以被挂载在Pod中一个或者多个容器的指定路径下面。解决数据持久化存储的问题,将Pod和卷的生命周期分离
Label :
标签,附加到某个资源上,用于关联对象、查询和筛选
Kubernetes搭建过程中遇到的问题,与解决办法。
Q1:服务器只有一台,合作之后发现针对某一台服务器无法实现既作为自己集群的master又作为其他集群的node
A1:重新开启两台虚拟机,重新搭建k8s
Q2:遇见提示没有docker,kubernetes的command以及提示8080端口有误
A2:1.以为是自己没有安装好docker,后来发现是没有root权限是无法使用到docker命令。使用命令su root登录以获取root权限
- 还需要对docker进行启动,使用开机自启动更加方便,利用命令systemctl start 和systemctl enable
**Q3:**在第一次kubeadm init提示错误之后,再次kubeadm init提示文件错误
A3:在询问老师之后,才知道如果第一次init出现错误则会留存一些残余的配置文件,需要kubeadm reset才可以再次init,否则会被第一次的配置文件影响阻碍
Q4:ifconfig无法拿到内网ip,没有发现显示内网ip
A4:由于使用的是vmware模拟两台虚拟机centos,最初猜测是网络模式设置问题.最初猜测是网络利用NAT模式不行,然后换成主桥模式,结果还是不行
之后从主桥模式换回NAT模式,发现ifconfig又一次出现了ip地址
猜测原因:长时间的待机可能有一些配置影响到了需要重新切换
Q5:在node节点忘记换源折腾了半小时
A5:由于国内墙直接访问到dockerhub,速度非常的慢。我开始没有意识到,因为我在master换了源但是node没换,然后想在node打包时候就发现慢了
Q6发现yml文件连不上githubsercontent
A6:最开始我尝试了挂梯子,然后我发现梯子由于采用的是role模式代理没有让我的虚拟机访问外网加速
然后我之后尝试去映射,直接找到ip,然后发现就通过了访问
在hosts设置映射,然后就可以连上了
Q7:在master部署好了helo_world镜像发现,pod位于node1的全报错,位于master就可以running
A7:在k8s中要部署hello_world,Node需要hello_world镜像才可以部署,master的hello_world镜像影响不了node
Q8:在k8s安装flannel时候利用换源过的yml文件结果报错了
A8:由于国内墙的存在无法直接访问到githubercontent那个资源网站
所以最开始尝试博客上给出的yml,利用的其中呢一些网站被换到了镜像网站
可是博客文章发表于2022/2,在11月的今天再去访问发现爆错了无法访问(这也是我后面才发现的)
所以我建议以后在k8s安装flannel用原版的yml文件不要用野路子yml
Q9:关于kube-flannel,不安装pod网络配置就会一直pending
A9:最开始一直显示Node1 not ready
然后我看kubectl get pod -n kube-system
然后找到对应的pod
输入命令kubectl describe pod kube-flannel-ds-amd64-6dsmg -n kube-system
发现问题就是kube-flannel这个镜像有点问题
仔细一看日志log发现是镜像一直没有拉取,但是奇怪的是在master机上docker images显示这个镜像已经在我本地机上了,然后我一直在弄master中的镜像,删除和重装。经历几次之后发现
Kubectl get pods -A显示出没有拉取镜像的其实是node1节点
说明系统是要在node1有那个镜像
此后在node1单独pull镜像成功之后就好了
Q10: k8s部署时coredns出现CrashLoopBackOff的错误
A10:参考链接:https://blog.csdn.net/qq_40017011/article/details/116698422
通过kubectl get pods -A发现这里是coredns的错误
vi /etc/resolv.conf查看配置文件,
发现里面nameserver那一栏并不是主机master的地址,然后把他修改掉
192.168.217.132
192.168.217.1
vi修改完之后使用命令
# systemctl stop kubelet # systemctl stop docker # iptables –flush # iptables -tnat –flush # systemctl start kubelet # systemctl start docker
Q11:重启之后又一次k8s部署时coredns出现CrashLoopBackOff的错误
A11:我发现每一次重启之后这个配置文件都会重新被修改然后报错,就得自己手动改回去,可能是某种系统配置问题,但是再次手动修改resolv之后又恢复正常
Q12:虚拟机在某段时间之后提示Xauortiry,导致ssh连接变慢,且无法获取管理员权限
A12:首先尝试删除Xauority文件发现不好使
参考链接:https://blog.csdn.net/dong_liuqi/article/details/108842873
发现是应为/home/下没有创建/userA/文件夹且因为没有给userA对于/home/userA/的写权限,所以导致在连接时无法创建文件.Xauthority
最后通过以下命令解决
sudo mkdir /home/a944613709
chown a944613709:a944613709 -R /home/a944613709
usermod -s /bin/bash a944613709