1 集群环境容器部署问题

  1. 集群内每台机器应该分配几个容器
  2. 如何根据业务量动态调整容器个数
  3. 机器数量过多,部署工作量大

2 容器编排工具

  1. docker-compose:单击容器编排工具
  2. docker swarm:docker官方提供的集群容器编排工具
  3. kubernetes:简称k8s,因为k和s之间有8个英文字母,google官方提供的容器编排工具,底层完全基于docker,与docker swarm属于竞争关系

3 Kubernetes功能

  1. 自动化容器部署和复制:只需要通过脚本规划好容器在哪些主机运行,运行多少个副本
  2. 随时扩展或收缩容器规模:通过修改参数,可以人工或自动增加计算单元个数,例如将tomcat从10个缩小成5个
  3. 容器分组Group,并提供容器间的负载均衡:没有K8S前需要使用nginx完成负载均衡,K8S本身提供了负载均衡功能
  4. 实时监控, 即时故障发现, 自动替换:K8S提供管理界面,可以实时看到所有容器的情况

4 K8S中基本概念

k8s 容器组标签 k8s容器编排工具_docker

  1. 每个方框都代表一台容器的宿主机,他们共同形成了一个K8S集群,这些宿主机根据角色可划分为Master和Node
  2. Master:主服务器,集群管理者。通过主服务器向具体的节点发送创建容器、自动部署、自动发布等命令,外界请求也由Master接收,再由它将请求分配给Node,通常使用一台独立的物理机作为Master
  1. Replication Controller:复制控制器,位于主节点,用于对Pod数量进行监控,例如我们需要三个红色的Pod,如果Replication Controller发现少了一个,他就会额外创建一个新Pod出来。且如果一个Pod失去响应,会将这个Pod剔除,用一个新的替换它。Replication Controller可以根据参数值动态调整Pod个数
  1. Node:节点,通常可以是独立物理机,也可以是虚拟机
  1. Pod:存在于Node中,是K8S控制的最小单元。Pod译为豆角,豆角一个皮中包含很多豆子,意思就是一个Pod中可以包含多个容器(Container)
  1. Pod内部容器网络互通,每个Pod都有独立虚拟IP,由K8S统一管理
  2. 同一节点下Pod间网络互通
  3. 不通节点下Pod间网络不通,需要依靠Service通信
  4. 项目不同,Pod中包含内容不同,对应小公司,一个Pod可能是一套完整环境,包含tomcat、redis、db。而对于大公司,可能一个Pod只部署一个职能,比如只部署tomcat
  5. 每个Pod中都包含一个特殊的容器(Container),叫做Pause,用于提供共享网络空间。如果没有Pause时,一个Pod下两个容器tomcat和nginx彼此通信时,需要通过对方ip或对方容器名进行访问,有了Pause后,可以将Pod看作一个整体,nginx和tomcat使用localhost就能访问彼此,同时Pause会为当前Pod提供一个共享的volume(挂载的数据卷)
  1. Service:可以让两个Pod互通,且可以作为负载均衡对外提供服务
  2. Labels:标签,相当于Pod的别名,定义了标签,K8S的Master才能找到对应的Pod,并对其进行操作
  3. kubelet、kube-proxy、docker:每个Node上都需要安装的应用程序
  1. kubelet:负责启动Pod和容器
  2. kube-proxy:负责Service功能的具体实现

5 k8s安装

  1. 从google中央仓库安装:外网不通
  2. 使用快速部署工具kubeadm:推荐,当前学习的是1.14
  3. 使用阿里公有云平台k8s:收费
  4. 通过yum官方仓库安装:版本太旧
  5. 通过二进制包的形式进行安装:kubeasz (github),这种方式安装的k8s可能有bug,或底层可能被篡改
5.1 CentOS7集群搭建
  1. 环境准备
  1. Master:192.168.246.132
  2. Node1:192.168.163.133
  1. 设置主机名与时区
timedatectl set-timezone Asia/Shanghai
#只对master执行
hostnamectl set-hostname master
  1. 添加hosts网络主机配置
vim /etc/hosts
192.168.163.132 master
192.168.163.133 node1
  1. 禁用SELINUX
#SELINUX:linux内置的安全增强模块,设置起来太费劲,因此禁用掉
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
#设置为临时生效
setenforce 0
  1. 关闭防火墙
#禁用防火墙
systemctl disable firewalld
#停止防火墙
systemctl stop firewalld
5.2 离线安装kubeadmin、docker、导入k8s镜像
  1. 将镜像包kubernetes-1.14上传至各服务器
mkdir /usr/local/k8s-install
cd /usr/local/k8s-install
cp -r /mnt/hgfs/wusihan/Downloads/kubernetes-1.14 .
  1. 安装、启动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
  1. 确保两台机器的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
  1. 安装kubeadm
cd /usr/local/k8s-install/kubernetes-1.14
tar -zxvf kube114-rpm.tar.gz
cd kube114-rpm
yum localinstall -y *.rpm
  1. 关闭交换区
#1. 交换分区类似windows虚拟内存,就是内存不足时,写入内存的操作会被写入硬盘,读取内存操作从硬盘读取,所以虚拟内存可能导致系统性能降低
#2. k8s的环境下, 一般内存都充裕,不建议使用交换分区,可能影响性能
swapoff -a
#将swap那行注释
vi /etc/fstab
  1. 配置网桥
#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
  1. 导入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集群
  1. 使用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
  1. 执行完毕后,相当于k8s就已经搭建好了,docker ps发现多了很多容器,所以说,kubeadm的作用,可以简单的理解为,通过k8s相关镜像,快速启动一系列k8s相关的容器,从而完成整个k8s环境的创建
  2. 创建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
  1. 此时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
  1. 将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启动节点
  1. kubelet运行在所有节点上,负责启动POD和容器,以系统服务形式出现
  2. 当master或node1宕机重启后,需要依赖kubelet服务启动k8s集群或重新加入集群
#master或node1重启后,需要执行如下命令恢复集群
systemctl start kubelet
#设置kubelet开机启动,这样不必每次重启master或node1都要手工启动kubelet
systemctl enable kubelet

6 启用Dashboard

  1. 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
  1. 通过http://192.168.246.132:32000 访问Dashboard

7 利用Dashboard部署tomcat集群

  1. 保证两台机器都配置了docker镜像加速,否则创建容器可能无法下载
  2. Dashboard运行在master上,master发送创建容器请求给node1,node1收到后,先下载镜像,再启动容器
  3. 进入Dashboard–工作负载–部署容器应用–创建应用
  1. 应用名称:my-tomcat1
  2. 容器镜像:tomcat:latest
  3. 容器个数:2,表示在两台node上布置几个tomcat副本
  4. 服务:外部,表示对外暴露创建的tomcat容器的端口,其他电脑可以通过网络访问到这些创建的容器,如果不是外部服务,其他电脑无法访问
  1. 端口:8000,表示Pod的端口,并不是kubernetes所在宿主机的端口,外界不是通过该端口访问tomcat
  2. 目标端口:8080,表示容器对Pod暴露的端口
  1. 部署
  1. docker images发现多了一个tomcat镜像 ,docker ps发现多了一个tomcat容器
  2. 查看tomcat集群状态:进入Dashboard–副本集–my-tomcat1-69b7b678d5–服务–my-tomcat1–容器组,可以看到两个容器所在节点、状态、以及日志信息
  3. 查看tomcat集群对外暴露的端口号:进入Dashboard–副本集–my-tomcat1-69b7b678d5–服务–内部端点,显示端口号为31455,这个端口号是随机生成的,虽然两个tomcat容器都在node1上,但在外部通过http://192.168.246.132:31455/http://192.168.246.133:31455/都能访问tomcat服务
  4. 模拟一台tomcat宕机的情况
#node1上执行,f07e06106503为其中一个tomcat容器的id
docker rm -f f07e06106503
#k8s会实时监控集群中各容器状态,一旦发现容器挂掉,会自动重启该容器,发现过一会,tomcat容器会被自动重启,docker ps发现容器重新出现

8 kubectl使用yaml资源文件部署tomcat集群

  1. 所谓部署指master向node发送指令,创建容器的过程
  2. Kubernetes支持yml格式的部署脚本
  3. 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集群
  1. 创建用于部署的资源文件tomcat-deploy.yml
#文件名写什么都可以
vi /root/k8s/tomcat-deploy/tomcat-deploy.yml
  1. 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. 创建部署
#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集群
  1. 通过资源文件部署的tomcat集群,到现在为止,还无法被外界访问
  2. 在K8S中,Service是对Pod对象的抽象,通常Pod会以多副本的形式部署,每个Pod都有自己的IP,都可以对外提供服务,但Pod随时都有可能被频繁地销毁和重启,IP也会随之改变,会导致服务的访问出现问题。Service就是提出来解决这个问题的,它定义了一个虚拟IP(集群IP),这个 IP在Service的整个生命周期内都不会改变,我们可以将请求发送给Service,Service会将请求导向给Pod,如果存在多个Pod,Service还能实现负载均衡
  3. 设置Service时,也可以同时将Pod内部端口与其所在宿主机端口进行映射,这样可以不通过Service,而是直接访问Pod的宿主机来访问Pod中的服务,但这样做不推荐,因为这样Service提供的负载均衡功能就失效了
  4. 创建Service资源文件tomcat-service.yml
vim /root/k8s/tomcat-service/tomcat-service.yml
  1. 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
  1. 创建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名
  1. 此时可以输入MasterIP:32500或Node1IP:32500完成Node1一个节点上,两个tomcat的负载访问,注意如果两个tomcat不在一个pod中,例如图中所示,NodePort类型的Service就无法完成负载功能了

9 基于NFS实现集群内的文件共享

  1. NFS:Network File System,网络文件系统,是由SUN公司研制的文件传输协议,采用远程过程调用RPC机制,实现文件在网络中进行共享和传输,配置NFS后,读写网络中文件时,就像在本地操作文件一样方便
  2. 项目拓扑
9.1 NFS配置
  1. 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
  1. 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)
  1. 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
  1. 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
  1. 由于之前启动了一个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名
  1. 修改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. 重新创建部署
#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负载均衡

  1. 修改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
  1. 创建Service
kubectl create -f tomcat-service.yml
#查看service
kubectl get service
#查看service详细信息
#发现宿主机上暴露的端口,NodePort项不在了
kubectl describe service tomcat-service
  1. master上访问Service
#使用curl命令,向Service的ip和port上发送请求,发现会返回404错误,说明请求被转发到了node1或node2上的服务上
curl 10.100.95.153:8000
  1. 通过NFS完成tomcat部署
#由于master已经共享给了node,可以通过修改master中内容,完成应用部署,master上执行
cd /usr/local/data/www-data
mkdir test 
cd test
vi index.jsp
  1. index.jsp
//输出本机的ip,这样我们就能知道负载均衡访问的是具体哪个节点了
<%=request.getLocalAddr()%>;
  1. 再次访问Service
#多次执行,打印ip不同,可能打印node1上第一个Pod的ip也可能是node1上第二个Pod的ip,负载均衡策略为随机分配
curl 10.100.95.153:8000/test/index.jsp

11 使用Rinetd将Service服务对外暴露

  1. service的IP为10.100.95.153,这不是一个有效的真实的IP,这个IP在master、node1上是可以访问的,但在外部192.168网段无法访问
  2. Rinetd是Linux操作系统中为重定向传输控制协议工具,可以将源IP端口数据转发至目标IP端口,我们可以利用Rinetd将Service的IP端口,与其所在宿主机的物理IP和端口进行映射,从而将Service服务对外暴露
  3. 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. 配置端口映射
#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
  1. 此时外界就可以通过<192.168.246.132:8000/test/index.jsp>访问service了,service会将请求负载给两个Pod中的tomcat容器

12 集群配置调整与资源限定

  1. 配置调整:例如原来2个tomcat,现在改为3个tomcat。k8s会采用可用资源优先原则,也就是哪个服务器负载低,就把新Pod发布在哪个节点上,这只是其中一个策略,我们也可以人为指定发布Pod到哪个节点
#1. 修改yml文件
#2. 使用新文件更新
kubectl apply -f yml文件路径
#3. 或者也可以删除部署和Service之后重新创建
kubectl delete deployment/service 部署/服务名
  1. 资源限定:限制创建的容器使用多少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构建贝亲婴童商城

  1. 项目拓扑:由于资源有限,不搭建Node2,而是在Node1上部署两个tomcat应用
  2. beiqin文件夹介绍
  1. dist
  1. application.yml:springboot配置文件,连接到哪个数据库都在其内配置
  2. beiqin-app.jar:贝亲商城应用
  1. sql
  1. 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 部署数据库
  1. 编写部署脚本,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
  1. 创建部署
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
  1. 图中数据库在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
  1. 创建Service
kubectl create -f beiqin-db-service.yml
#查看服务,service可以简写为svc
kubectl get svc
13.4 部署应用
  1. 编写部署脚本,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
  1. 创建部署
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
  1. 此时如果日志中显示无法连接数据库,是因为application.yml中数据库url没改导致,原配置为localhost,可以改为数据库的service的ip,或service名
  2. 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
  1. 编写脚本: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
  1. 创建Service:kubectl create -f beiqin-app-service.yml
  2. 查看Service的IP,为10.108.195.224:kubectl describe service beiqin-app-service
  3. 尝试通过应用的Service的ip访问:curl 10.108.195.224/goods?gid=1788
  4. 完成Service的80端口到master上80端口的端口映射
vim /etc/rinetd.conf
0.0.0.0 80 10.108.195.224 80
rinetd -c /etc/rinetd.conf
  1. 此时外界通过浏览器访问http://192.168.246.132/goods?gid=1788,就可以查看到商城内各商品信息,修改gid的值,就可以切换到不同商品