1 集群环境容器部署问题
- 集群内每台机器应该分配几个容器
- 如何根据业务量动态调整容器个数
- 机器数量过多,部署工作量大
2 容器编排工具
- docker-compose:单击容器编排工具
- docker swarm:docker官方提供的集群容器编排工具
- kubernetes:简称k8s,因为k和s之间有8个英文字母,google官方提供的容器编排工具,底层完全基于docker,与docker swarm属于竞争关系
3 Kubernetes功能
- 自动化容器部署和复制:只需要通过脚本规划好容器在哪些主机运行,运行多少个副本
- 随时扩展或收缩容器规模:通过修改参数,可以人工或自动增加计算单元个数,例如将tomcat从10个缩小成5个
- 容器分组Group,并提供容器间的负载均衡:没有K8S前需要使用nginx完成负载均衡,K8S本身提供了负载均衡功能
- 实时监控, 即时故障发现, 自动替换:K8S提供管理界面,可以实时看到所有容器的情况
4 K8S中基本概念
- 每个方框都代表一台容器的宿主机,他们共同形成了一个K8S集群,这些宿主机根据角色可划分为Master和Node
- Master:主服务器,集群管理者。通过主服务器向具体的节点发送创建容器、自动部署、自动发布等命令,外界请求也由Master接收,再由它将请求分配给Node,通常使用一台独立的物理机作为Master
- Replication Controller:复制控制器,位于主节点,用于对Pod数量进行监控,例如我们需要三个红色的Pod,如果Replication Controller发现少了一个,他就会额外创建一个新Pod出来。且如果一个Pod失去响应,会将这个Pod剔除,用一个新的替换它。Replication Controller可以根据参数值动态调整Pod个数
- Node:节点,通常可以是独立物理机,也可以是虚拟机
- Pod:存在于Node中,是K8S控制的最小单元。Pod译为豆角,豆角一个皮中包含很多豆子,意思就是一个Pod中可以包含多个容器(Container)
- Pod内部容器网络互通,每个Pod都有独立虚拟IP,由K8S统一管理
- 同一节点下Pod间网络互通
- 不通节点下Pod间网络不通,需要依靠Service通信
- 项目不同,Pod中包含内容不同,对应小公司,一个Pod可能是一套完整环境,包含tomcat、redis、db。而对于大公司,可能一个Pod只部署一个职能,比如只部署tomcat
- 每个Pod中都包含一个特殊的容器(Container),叫做Pause,用于提供共享网络空间。如果没有Pause时,一个Pod下两个容器tomcat和nginx彼此通信时,需要通过对方ip或对方容器名进行访问,有了Pause后,可以将Pod看作一个整体,nginx和tomcat使用localhost就能访问彼此,同时Pause会为当前Pod提供一个共享的volume(挂载的数据卷)
- Service:可以让两个Pod互通,且可以作为负载均衡对外提供服务
- Labels:标签,相当于Pod的别名,定义了标签,K8S的Master才能找到对应的Pod,并对其进行操作
- kubelet、kube-proxy、docker:每个Node上都需要安装的应用程序
- kubelet:负责启动Pod和容器
- kube-proxy:负责Service功能的具体实现
5 k8s安装
- 从google中央仓库安装:外网不通
- 使用快速部署工具kubeadm:推荐,当前学习的是1.14
- 使用阿里公有云平台k8s:收费
- 通过yum官方仓库安装:版本太旧
- 通过二进制包的形式进行安装:kubeasz (github),这种方式安装的k8s可能有bug,或底层可能被篡改
5.1 CentOS7集群搭建
- 环境准备
- Master:192.168.246.132
- Node1:192.168.163.133
- 设置主机名与时区
timedatectl set-timezone Asia/Shanghai
#只对master执行
hostnamectl set-hostname master
- 添加hosts网络主机配置
vim /etc/hosts
192.168.163.132 master
192.168.163.133 node1
- 禁用SELINUX
#SELINUX:linux内置的安全增强模块,设置起来太费劲,因此禁用掉
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
#设置为临时生效
setenforce 0
- 关闭防火墙
#禁用防火墙
systemctl disable firewalld
#停止防火墙
systemctl stop firewalld
5.2 离线安装kubeadmin、docker、导入k8s镜像
- 将镜像包kubernetes-1.14上传至各服务器
mkdir /usr/local/k8s-install
cd /usr/local/k8s-install
cp -r /mnt/hgfs/wusihan/Downloads/kubernetes-1.14 .
- 安装、启动docker-ce,如果已经安装了docker,可以跳过
cd ./kubernetes-1.14
tar -zxvf docker-ce-18.09.tar.gz
cd docker
#localinstall:表示加载当前目录下所有rpm文件,自动完成安装
yum localinstall -y *.rpm
#启动docker
systemctl start docker
#设置docker为开机自动启动
systemctl enable docker
- 确保两台机器的cgroups在同一个groupfs上
#1. cgroups是control groups的简称,是linux内核提供的一种机制,可以实现Docker中资源管理、控制
#2. 同一集群中的所有docker的cgroups必须相同
#3. 默认cgroups都应该是cgroupfs
docker info | grep cgroup
#4. 如果不同需要修改
cat << EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=cgroupfs"]
}
EOF
systemctl daemon-reload && systemctl restart docker
- 安装kubeadm
cd /usr/local/k8s-install/kubernetes-1.14
tar -zxvf kube114-rpm.tar.gz
cd kube114-rpm
yum localinstall -y *.rpm
- 关闭交换区
#1. 交换分区类似windows虚拟内存,就是内存不足时,写入内存的操作会被写入硬盘,读取内存操作从硬盘读取,所以虚拟内存可能导致系统性能降低
#2. k8s的环境下, 一般内存都充裕,不建议使用交换分区,可能影响性能
swapoff -a
#将swap那行注释
vi /etc/fstab
- 配置网桥
#iptable是linux中的网络工具,用于对我们的包按规则进行过滤,此处配置表示在k8s容器间进行网络通信时,也要遵循iptable的规则,这样可以提升系统间网络传输的安全性
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
#检查是否修改成功
sysctl --system
- 导入k8s相关镜像
cd /usr/local/k8s-install/kubernetes-1.14
#1. docker load : 导入使用docker save命令导出的镜像
#2. 导入k8s相关的一系列镜像:kube-proxy、kube-apiserver、kube-controller-manager、kube-scheduler、coredns、etcd、pause
docker load -i k8s-114-images.tar.gz
#3. 导入监控集群状态工具:kubernetes-dashboard-amd64、flannel
docker load -i flannel-dashboard.tar.gz
#4. 查看新增的镜像
#a. kube-proxy:用于实现Service
#b. kube-apiserver:api服务端
#c. kube-controller-manager:集群控制器
#d. kube-scheduler:负责任务调度
#e. flannel:coredns进行跨Pod通信依赖的组件
#f. coredns:每个节点中基础的网络应用
#g. kubernetes-dashboard-amd64:kubernetes官方提供的web管理界面,用于监控集群状态
#h. etcd:数据存储模块
#i. pause:用于网络命名空间的共享(localhost)以及共享数据卷
docker images
5.3 利用kubeadm构建k8s集群
- 使用kubeadm构建Master
#只在master执行,kubernetes-version:指明要安装的k8s的版本,--pod-network-cidr:指定k8s创建的Pod的虚拟ip的范围
kubeadm init --kubernetes-version=v1.14.1 --pod-network-cidr=10.244.0.0/16
#如果构建Master失败,可以通过如下命令重置环境,之后可以重新执行kubeadm init命令
kubeadm reset
- 执行完毕后,相当于k8s就已经搭建好了,docker ps发现多了很多容器,所以说,kubeadm的作用,可以简单的理解为,通过k8s相关镜像,快速启动一系列k8s相关的容器,从而完成整个k8s环境的创建
- 创建kubeadm对当前k8s集群的核心配置文件
#只在master中执行
#下方脚本在步骤1控制台中打印
mkdir -p $HOME/.kube
#admin.conf:kubeadm对于当前集群的核心配置文件,里面有关于该集群安全的授权信息,master的节点的信息,例如ip地址等
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
- 此时k8s环境已经搭建完毕,可以通过kubectl对k8s集群进行管理
#1. 查看k8s中各节点状态
kubectl get nodes
#2. 发现master状态为NotReady,这可能是因为master中有Pod未正常启动导致
kubectl get pod --all-namespaces
#3. 发现有些status为CrashLoopBackOff:表示前面创建失败了,后台在尝试不断创建,restarts为5表示重建了5次,这种状态一般等一会自己就能创建好,如果长时间反复出现CrashLoopBackOff,代表硬件条件不够,需要增加硬件
#4. 还有一些status为Pending,表示等待状态,例如coredns,这是因为底层缺少额外的flannel网络组件导致,flannel是k8s中跨pod通信最底层依赖的网络协议
#5. 安装flannel网络组件后,Pod全部变为Running,且master变为Ready状态
cd /usr/local/k8s-install/kubernetes-1.14
kubectl create -f kube-flannel.yml
- 将node1加入k8s集群
#下方脚本在步骤1控制台中打印,只在node1中执行
#1. 如果没有kubeadm,加入集群比较麻烦,有了kubeadm只需要如下一行代码
kubeadm join 192.168.246.132:6443 --token r8k7mb.x20z1g9lylrxynpb --discovery-token-ca-cert-hash sha256:a5f2252c8c9250fd5fdbb4c4da85b9426124503d758548ab2050c5cb4da35f2d
#2. 如果第一步执行后,没有记录控制台打印日志,可以在master上执行如下命令查看令牌列表,为r8k7mb.x20z1g9lylrxynpb
kubeadm token list
#在node上执行如下命令加入k8s集群,--discovery-token-unsafe-skip-ca-verification:表示不进行token的安全校验
kubeadm join 192.168.163.132:6443 --token r8k7mb.x20z1g9lylrxynpb --discovery-token-unsafe-skip-ca-verification
5.4 kubelet启动节点
- kubelet运行在所有节点上,负责启动POD和容器,以系统服务形式出现
- 当master或node1宕机重启后,需要依赖kubelet服务启动k8s集群或重新加入集群
#master或node1重启后,需要执行如下命令恢复集群
systemctl start kubelet
#设置kubelet开机启动,这样不必每次重启master或node1都要手工启动kubelet
systemctl enable kubelet
6 启用Dashboard
- Dashboard翻译过来是仪表盘,是kubernetes官方提供的web管理界面,只需在master上部署
cd /usr/local/k8s-install/kubernetes-1.14
#kubectl apply -f:利用部署文件,创建、更新Pod,其实就是创建了一个Pod,Pod包含一个dashboard容器和一个pause容器
#1. kubernetes-dashboard.yaml:Dashboard的核心配置
kubectl apply -f kubernetes-dashboard.yaml
#2. admin-role.yaml:表示管理员的角色,以及有哪些职能
kubectl apply -f admin-role.yaml
#3. rbac为基于角色进行访问控制,该文件定义了系统应用权限所在
kubectl apply -f kubernetes-dashboard-admin.rbac.yaml
#4. 获取kube-system下服务有哪些,发现kubernetes-dashboard出现,对外暴露端口为32000
kubectl -n kube-system get svc
- 通过http://192.168.246.132:32000 访问Dashboard
7 利用Dashboard部署tomcat集群
- 保证两台机器都配置了docker镜像加速,否则创建容器可能无法下载
- Dashboard运行在master上,master发送创建容器请求给node1,node1收到后,先下载镜像,再启动容器
- 进入Dashboard–工作负载–部署容器应用–创建应用
- 应用名称:my-tomcat1
- 容器镜像:tomcat:latest
- 容器个数:2,表示在两台node上布置几个tomcat副本
- 服务:外部,表示对外暴露创建的tomcat容器的端口,其他电脑可以通过网络访问到这些创建的容器,如果不是外部服务,其他电脑无法访问
- 端口:8000,表示Pod的端口,并不是kubernetes所在宿主机的端口,外界不是通过该端口访问tomcat
- 目标端口:8080,表示容器对Pod暴露的端口
- 部署
docker images
发现多了一个tomcat镜像 ,docker ps
发现多了一个tomcat容器- 查看tomcat集群状态:进入Dashboard–副本集–
my-tomcat1-69b7b678d5
–服务–my-tomcat1
–容器组,可以看到两个容器所在节点、状态、以及日志信息 - 查看tomcat集群对外暴露的端口号:进入Dashboard–副本集–
my-tomcat1-69b7b678d5
–服务–内部端点,显示端口号为31455,这个端口号是随机生成的,虽然两个tomcat容器都在node1上,但在外部通过http://192.168.246.132:31455/和http://192.168.246.133:31455/都能访问tomcat服务 - 模拟一台tomcat宕机的情况
#node1上执行,f07e06106503为其中一个tomcat容器的id
docker rm -f f07e06106503
#k8s会实时监控集群中各容器状态,一旦发现容器挂掉,会自动重启该容器,发现过一会,tomcat容器会被自动重启,docker ps发现容器重新出现
8 kubectl使用yaml资源文件部署tomcat集群
- 所谓部署指master向node发送指令,创建容器的过程
- Kubernetes支持yml格式的部署脚本
- kubectl部署相关命令
#1. 部署一个新Pod
kubectl create -f 部署脚本
#2. 创建或更新部署过的Pod
kubectl apply -f 部署脚本
#3. 查看所有已部署的Pod,-o wide为可选参数,让显示的信息更全面,例如能够显示这些Pod所在节点、pod的ip等
kubectl get pods <-o wide>
#4. 查看所有命名空间下的pods,也就是不只查看人为部署的pod,还查看创建k8s集群时,创建的那些pod(这些pod命名空间为kube-system)
kubectl get pods --all-namespaces
#5. 查看Pod详细信息,无法查看kube-system命名空间下的pod
kubectl describe pod <pod名>
#查看指定pod的控制台日志,-f表示是否实时更新日志,例如pod里如果只创建了一个tomcat容器,那么此处看的就是tomcat控制台日志
kubectl logs <-f> pod名
8.1 部署tomcat集群
- 创建用于部署的资源文件tomcat-deploy.yml
#文件名写什么都可以
vi /root/k8s/tomcat-deploy/tomcat-deploy.yml
- tomcat-deploy.yml
#1. 解析yml文件使用的api版本,可以通过kubectl api-versions查看支持的api版本
apiVersion: extensions/v1beta1
#2. pod、service、deployment都可以看作是一种资源,yaml的用处就是创建这些资源中的一种,此处用于指定要创建的资源为deployment
#3. deployment是K8S中负责管理Pod的资源对象,它定义Pod的部署属性,比如有几个副本,副本异常怎么处理等
kind: Deployment
metadata:
#4. 资源的名字,通过kubectl get deployment查到的部署名就是这个,在同一个namespace中必须唯一
name: tomcat-deploy
#5. 当前资源规范
spec:
#6. Pod副本个数
replicas: 2
#7. Pod使用的模版,也就是这两个Pod应该如何创建
template:
metadata:
#8. labels:Pod的标签,也可以看作为Pod起了一个别名
labels:
app: tomcat-cluster
#9. 定义Pod的资源规范
spec:
#10. 对Pod中容器进行设置
containers:
#11. -代表containers下的集合,这里表示containers这个集合中,有一个元素,这个元素有name、image、ports三个属性,而ports属性也是一个集合,起内有一个元素containerPort
#12. 容器别名为tomcat-cluster,该名和app中的名字通常设成一样的
- name: tomcat-cluster
#13. 表示使用tomcat镜像
image: tomcat:latest
#14. 容器对外暴露的端口号
ports:
- containerPort: 8080
- 创建部署
#1. 创建部署,部署创建成功不代表Pod和容器创建成功,所以需要进一步查看Pod和容器的状态
kubectl create -f ./tomcat-deploy.yml
#2. 查看所有部署,READY为2/2表示一个部署中有两个Pod,且都已创建完毕,AVAILABLE为2表示两个Pod都可用
kubectl get deployment
#3. 查看Pod的详细信息
#NAME:Pod名
#STATUS:Running表示正在运行
#IP:Pod的虚拟ip,这个ip无法从外界直接访问
#NODE:Pod所在节点
#READY:1/1表示Pod中有一个容器,这个容器现在状态是READY
kubectl get pod -o wide
#4. 查看Pod更加详细的描述
#Events:Pod从创建到现在都经历了什么
kubectl describe pod pod名
#5. 查看Pod日志
kubectl logs pod名
8.2 外部访问tomcat集群
- 通过资源文件部署的tomcat集群,到现在为止,还无法被外界访问
- 在K8S中,Service是对Pod对象的抽象,通常Pod会以多副本的形式部署,每个Pod都有自己的IP,都可以对外提供服务,但Pod随时都有可能被频繁地销毁和重启,IP也会随之改变,会导致服务的访问出现问题。Service就是提出来解决这个问题的,它定义了一个虚拟IP(集群IP),这个 IP在Service的整个生命周期内都不会改变,我们可以将请求发送给Service,Service会将请求导向给Pod,如果存在多个Pod,Service还能实现负载均衡
- 设置Service时,也可以同时将Pod内部端口与其所在宿主机端口进行映射,这样可以不通过Service,而是直接访问Pod的宿主机来访问Pod中的服务,但这样做不推荐,因为这样Service提供的负载均衡功能就失效了
- 创建Service资源文件tomcat-service.yml
vim /root/k8s/tomcat-service/tomcat-service.yml
- tomcat-service.yml
#1. 解析yml文件使用的api版本,用v1或之前的extensions/v1beta1都可以
apiVersion: v1
#2. 说明当前yml文件,用于配置一个service
kind: Service
metadata:
name: tomcat-service
#为当前资源打一个标签,用于后面引用
labels:
app: tomcat-service
spec:
#3. 设置Service类型为NodePort,表示创建的Service,会在每个Node中开辟一个端口,和tomcat容器进行端口映射
type: NodePort
#4. 上面的yml文件中,通过labels中定义了Pod的标签,此处可以通过selector中填写该Pod标签,当前资源可以与标签为tomcat-cluster的资源互通
selector:
app: tomcat-cluster
ports:
#5. 设置Service接收服务的端口
- port: 8000
#6. tomcat容器对外暴露的端口
targetPort: 8080
#7. 用宿主机上的32500端口与tomcat容器的8080端口映射
nodePort: 32500
- 创建Service
kubectl create -f ./tomcat-service.yml
#查看所有的Service
kubectl get service
#查看Service的详细描述
#NodePort:宿主机上暴露的端口
#Endpoints:tomcat容器的ip和对外暴露的端口,这两个端口和宿主机上的端口进行映射
#IP:Service的虚拟IP
#Port:Service提供服务的端口号
kubectl describe service Service名
- 此时可以输入MasterIP:32500或Node1IP:32500完成Node1一个节点上,两个tomcat的负载访问,注意如果两个tomcat不在一个pod中,例如图中所示,NodePort类型的Service就无法完成负载功能了
9 基于NFS实现集群内的文件共享
- NFS:Network File System,网络文件系统,是由SUN公司研制的文件传输协议,采用远程过程调用RPC机制,实现文件在网络中进行共享和传输,配置NFS后,读写网络中文件时,就像在本地操作文件一样方便
- 项目拓扑
9.1 NFS配置
- master安装NFS
#下面命令需要在文件提供方进行安装,这里我们选master为文件提供方
#1. nfs-utils为nfs工具集,rpcbind为rpc协议底层支持
yum install -y nfs-utils rpcbind
#2. 创建需共享的文件夹,www-data最后就是tomcat下的webapps
mkdir -p /usr/local/data/www-data
- master设置对外暴露的文件夹
vim /etc/exports
#/usr/local/data/www-data:对外暴露的文件夹
#192.168.246.132:文件夹所在的主机的IP
#24:子网掩码
#rw:共享的目录可读可写
#sync:同步写入,一旦远程或本地产生了文件变化,文件内容都会即时更新
/usr/local/data/www-data 192.168.246.132/24(rw,sync)
- master启动NFS服务:master执行
#1. 启动nfs服务
systemctl start nfs.service
#2. 启动rpc绑定服务
systemctl start rpcbind.service
#3. 设置开机启动
systemctl enable nfs.service
systemctl enable rpcbind.service
#4. 查看文件共享列表,如果出现了刚才的设置,证明配置正确
exportfs
- node1安装NFS并挂载远程目录到本地
#1. 只需要安装nfs-utils,不需要安装rpcbind
yum install -y nfs-utils
#2. 设置NFS开机启动
systemctl enable nfs.service
#3. 查看192.168.246.132上,对外共享文件夹有哪些
showmount -e 192.168.246.132
#4. 挂载远程目录到本地的/mnt下
mount 192.168.246.132:/usr/local/data/www-data /mnt
9.2 将/mnt中内容映射到tomcat容器的webapps
- 由于之前启动了一个tomcat集群,因此需要先将该集群服务删除
#master中执行
#1. 查看现有部署,其实也可以在现有部署上进行更新
kubectl get deployment
#2. 删除部署
kubectrl delete deployment 部署名
#3. 部署删除后,pod也会被自动删除
kubectrl get pod
#4. 部署删除后,容器也会被自动删除
docker ps
#5. service不会被自动删除,需要手动删除
kubectl get service
#6. 删除service
kubectl delete service service名
- 修改tomcat-deploy.yml完成数据卷挂载
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat-deploy
spec:
replicas: 2
template:
metadata:
labels:
app: tomcat-cluster
spec:
#在原基础上增加volumes,表示增加数据卷,表示将宿主机某个文件夹,向容器内进行挂载
volumes:
#定义挂载的数据卷的别名
- name: web-app
#设置宿主机原始目录
hostPath:
path: /mnt
containers:
- name: tomcat-cluster
image: tomcat:latest
ports:
- containerPort: 8080
#表示将web-app挂载到/usr/local/tomcat/webapps,就是用/mnt中文件,替代/usr/local/tomcat/webapps中文件
volumeMounts:
- name: web-app
mountPath: /usr/local/tomcat/webapps
- 重新创建部署
#1. 创建部署
kubectl create -f tomcat-deploy.yml
#2. 查看部署
kubectl get deployment
#3. 查看pod
kubectl get pod
#4. 查看tomcat容器id,node1上执行
docker ps
#5. 进入容器查看/usr/local/tomcat/webapps中内容是否和NFS配置的共享文件夹中内容相同
docker exec -it 容器id /bin/bash
#6. 修改master上共享文件夹中内容,再次查看tomcat容器中webapps中内容,确实被实时修改
#7. 还可以在master中执行如下命令进入Pod进行验证
kubectl get pod -o wide
#8. 进入pod所在节点的tomcat容器中,在这里也可以查看/usr/local/tomcat/webapps中内容
kubectl exec -it pod名 /bin/bash
10 Service负载均衡
- 修改tomcat-service.yml
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
labels:
app: tomcat-service
spec:
#只要将如下两行注释掉即可
#type: NodePort
selector:
app: tomcat-cluster
ports:
- port: 8000
targetPort: 8080
#nodePort: 32500
- 创建Service
kubectl create -f tomcat-service.yml
#查看service
kubectl get service
#查看service详细信息
#发现宿主机上暴露的端口,NodePort项不在了
kubectl describe service tomcat-service
- master上访问Service
#使用curl命令,向Service的ip和port上发送请求,发现会返回404错误,说明请求被转发到了node1或node2上的服务上
curl 10.100.95.153:8000
- 通过NFS完成tomcat部署
#由于master已经共享给了node,可以通过修改master中内容,完成应用部署,master上执行
cd /usr/local/data/www-data
mkdir test
cd test
vi index.jsp
- index.jsp
//输出本机的ip,这样我们就能知道负载均衡访问的是具体哪个节点了
<%=request.getLocalAddr()%>;
- 再次访问Service
#多次执行,打印ip不同,可能打印node1上第一个Pod的ip也可能是node1上第二个Pod的ip,负载均衡策略为随机分配
curl 10.100.95.153:8000/test/index.jsp
11 使用Rinetd将Service服务对外暴露
- service的IP为10.100.95.153,这不是一个有效的真实的IP,这个IP在master、node1上是可以访问的,但在外部192.168网段无法访问
- Rinetd是Linux操作系统中为重定向传输控制协议工具,可以将源IP端口数据转发至目标IP端口,我们可以利用Rinetd将Service的IP端口,与其所在宿主机的物理IP和端口进行映射,从而将Service服务对外暴露
- Rinetd安装
cd /usr/local
#上传rinetd源码包
cp ./Downloads/rinetd.tar.gz /usr/local/rinetd.tar.gz
#对gz进行解压
tar -zxvf rinetd.tar.gz
cd rinetd
#调整允许的端口映射范围
sed -i 's/65536/65535/g' rinetd.c
#/usr/man为rinetd软件强制要求创建的目录
mkdir -p /usr/man
yum install -y gcc
#提示install -m 700和644,说名rinetd安装成功
make && make install
- 配置端口映射
#1. 配置端口映射
vim /etc/rinetd.conf
#0.0.0.0:表示所有ip可以对当前宿主机发送请求
#8000:表示在master上开通一个8000端口
#10.100.95.153 8000:表示每当8000端口接收到外来请求,都转发给内部service的8000端口
0.0.0.0 8000 10.100.95.153 8000
#2. 加载该配置文件
rinetd -c /etc/rinetd.conf
#3. 查看是否映射成功,成功后,master上应该启动了一个8000端口
netstat -tulpn|grep 8000
- 此时外界就可以通过<192.168.246.132:8000/test/index.jsp>访问service了,service会将请求负载给两个Pod中的tomcat容器
12 集群配置调整与资源限定
- 配置调整:例如原来2个tomcat,现在改为3个tomcat。k8s会采用可用资源优先原则,也就是哪个服务器负载低,就把新Pod发布在哪个节点上,这只是其中一个策略,我们也可以人为指定发布Pod到哪个节点
#1. 修改yml文件
#2. 使用新文件更新
kubectl apply -f yml文件路径
#3. 或者也可以删除部署和Service之后重新创建
kubectl delete deployment/service 部署/服务名
- 资源限定:限制创建的容器使用多少cpu,和多少内存,修改tomcat-deploy.yml
containers:
- name: tomcat-cluster
image: tomcat:latest
resources:
#1. request:设置当前容器运行的最低系统要求
requests:
#2. 目标节点至少有0.5核cpu空闲,此处cpu可以为小数
cpu: 0.5
#3. 目标节点至少有200M内存空闲
memory: 200Mi
#2. limits:设置最大不超过多少
limits:
cpu: 1
memory: 512Mi
13 k8s构建贝亲婴童商城
- 项目拓扑:由于资源有限,不搭建Node2,而是在Node1上部署两个tomcat应用
- beiqin文件夹介绍
- dist
- application.yml:springboot配置文件,连接到哪个数据库都在其内配置
- beiqin-app.jar:贝亲商城应用
- sql
- beiqin.sql:数据库初始化脚本
13.1 将文件夹beiqin共享给Node1
#1. 将beiqin文件夹拷贝到共享目录/usr/local/beiqin中
cd /usr/local
cp -r /mnt/hgfs//wusihan/Downloads/源代码/k8s/beiqin .
#2. 配置文件共享路径,将beiqin中两个文件夹共享给其他节点
vim /etc/exports
/usr/local/beiqin/dist 192.168.163.132/24(rw,sync)
/usr/local/beiqin/sql 192.168.163.132/24(rw,sync)
#3. 重启服务
systemctl restart nfs.service
systemctl restart rpcbind.service
#4. 查看是否成功
exportfs
#5. node1上实现挂载
mkdir /usr/local/beiqin-dist
mkdir /usr/local/beiqin-sql
mount 192.168.246.132:/usr/local/beiqin/dist /usr/local/beiqin-dist
mount 192.168.246.132:/usr/local/beiqin/sql /usr/local/beiqin-sql
#6. 验证是否挂载成功,node1执行,如果有master上那几个文件,说明挂载成功
ls /usr/local/beiqin-dist
ls /usr/local/beiqin-sql
13.2 部署数据库
- 编写部署脚本,master执行
vi /usr/local/beiqin/beiqin-db-deploy.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: beiqin-db-deploy
spec:
replicas: 1
template:
metadata:
labels:
app: beiqin-db-deploy
spec:
volumes:
- name: beiqin-db-volume
hostPath:
path: /usr/local/beiqin-sql
containers:
- name: beiqin-db-deploy
image: mysql:5.7
ports:
- containerPort: 3306
#设置环境变量
env:
- name: MYSQL_ROOT_PASSWORD
value: "root"
volumeMounts:
- name: beiqin-db-volume
#该路径为保存初始化脚本路径
mountPath: /docker-entrypoint-initdb.d
- 创建部署
kubectl create -f beiqin-db-deploy.yml
#查看pod
kubectl get pod
#进入该i容器
kubectl exec -it pod名 /bin/bash
#登陆mysql
mysql -uroot -proot
#发现beiqin数据库存在
use beiqin
show tables
select count(*) from t_goods;
13.3 为数据库创建Service
- 图中数据库在Node1中,Node2上的Pod默认无法访问Node1上的Pod,所以需要配置Service,将mysql所在Pod的ip端口暴露给Service。
vi /usr/local/beiqin/beiqin-db-service.yml
apiVersion: v1
kind: Service
metadata:
name: beiqin-db-service
labels:
app: beiqin-db-service
spec:
#表示当前Service需要和beiqin-db-deploy联通
selector:
app: beiqin-db-deploy
ports:
#Service上3310端口对应mysql所在Pod的3306端口
- port: 3310
targetPort: 3306
- 创建Service
kubectl create -f beiqin-db-service.yml
#查看服务,service可以简写为svc
kubectl get svc
13.4 部署应用
- 编写部署脚本,master执行
vi /usr/local/beiqin/beiqin-app-deploy.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: beiqin-app-deploy
spec:
replicas: 2
template:
metadata:
labels:
app: beiqin-app-deploy
spec:
volumes:
- name: beiqin-app-volume
hostPath:
path: /usr/local/beiqin-dist
containers:
- name: beiqin-app-deploy
image: openjdk:8u222-jre
#容器部署完后自动执行的命令,此处使用exec格式
command: ["/bin/sh"]
#实际上执行的就是/bin/sh -c cd /usr/local/beiqin-dist;java -jar beiqin-app.jar
args: ["-c","cd /usr/local/beiqin-dist;java -jar beiqin-app.jar"]
volumeMounts:
- name: beiqin-app-volume
mountPath: /usr/local/beiqin-dist
- 创建部署
kubectl create -f beiqin-app-deploy.yml
#查看
kubectl get pod
#如果发现创建Pod失败,可以查看Pod详细描述
kubectl describe pod beiqin-app-deploy-79db95fbc6-22whv
#也可以查看Pod日志,beiqin-app-deploy-79db95fbc6-bzxqv为app对应的Pod名
kubectl logs -f beiqin-app-deploy-79db95fbc6-22whv
- 此时如果日志中显示无法连接数据库,是因为application.yml中数据库url没改导致,原配置为localhost,可以改为数据库的service的ip,或service名
- master上访问tomcat
#查看tomcat所在pod的ip地址,分别为10.244.1.23和10.244.1.22
kubectl get pod -o wide
#执行成功说明tomcat已能正确提供服务
curl 10.244.1.23/goods?gid=1788
13.5 为应用创建Service
- 编写脚本:
vi /usr/local/beiqin/beiqin-app-service.yml
apiVersion: v1
kind: Service
metadata:
name: beiqin-app-service
labels:
app: beiqin-app-service
spec:
selector:
app: beiqin-app-deploy
ports:
- port: 80
targetPort: 80
- 创建Service:
kubectl create -f beiqin-app-service.yml
- 查看Service的IP,为10.108.195.224:
kubectl describe service beiqin-app-service
- 尝试通过应用的Service的ip访问:
curl 10.108.195.224/goods?gid=1788
- 完成Service的80端口到master上80端口的端口映射
vim /etc/rinetd.conf
0.0.0.0 80 10.108.195.224 80
rinetd -c /etc/rinetd.conf
- 此时外界通过浏览器访问http://192.168.246.132/goods?gid=1788,就可以查看到商城内各商品信息,修改gid的值,就可以切换到不同商品