Kubernetes(K8s) —— 容器编排管理技术
安装虚拟机需要安装3台centos7 的虚拟机, 一台作为k8s的主节点, 另外两台作为其他节点.虚拟机的安装步骤如下图简介: 1. 安装vm软件, 并通过镜像文件(.iso)安装centos7操作系统.下面将展示一台虚拟机安装(vm, 以及镜像文件在底部通过百度云分享)新建虚拟机新建虚拟机-> 新建虚拟机向导->典型模式安装->安装程序光盘映像文件个性化linux配置配置lin
K8s 容器编排管理技术
第一章 是什么
1. 背景
- 一开始使用物理机部署项目, 但物理机成本较高
- 为了节约成本和资源隔离, 开发了虚拟机技术, 但是其启动慢占用空间大, 非常浪费资源
- 为了解决上述问题, 容器化技术应运而生. 启动快占用小. Docker 是应用最为广泛的容器技术
- 随着微服务技术的广泛应用,部署项目容器的数量越来越多,由此衍生了管理容器的重大问题。Google 在 2014 年开源了容器编排引擎 Kubernetes,用于管理容器化应用 程序的部署、规划、和扩展,使我们应用的部署和运维更加方便。
注意事项
2. 基础概念
Kubernetes 来自于希腊语,含义是舵手或领航员,简称 k8s。是一种基于GO开发的开源的容器编排管理工具.
类似的容器编排工具有:Docker swarm、Apache Mesos 等
Pod
在 Kubernetes 集群中,Pod 是 k8s 管理的最小单位,它是一个或多个容器的组合。
在 Pod 中,所有容器都被统一安排和调度。 Pod 中的容器有两个特点。
- 共享网络:Pod 中的所有容器共享同一个网络命名空间,包括 IP 地址和网络端口。
- 共享存储:Pod 中的所有容器能够访问共享存储卷,允许这些容器共享数据。
在常见的微服务中, 往往会部署多个微服务. 而为了保证高可用, 往往需要部署一个以上具有相同功能的微服务.
但是如果让这两个接口能够同时生效的话往往需要nginx该改微服务进行反向代理,
而Pod的出现则解决了该问题, 同一个pod来存放一个以上相同业务功能的容器, 并且共享同一网络和存储
控制器
k8s 通过控制器管理和调度 Pod。k8s 有以下几种控制器:
-
ReplicationController/ReplicaSet
RC 能够确保容器的副本数始终保持用户定义的副本数。即如果有容器异常退出, 会自动创建新的 Pod 来替代,而由于异常多出来的容器也会自动回收。RS 跟 RC 没有 本质不同,新版本的 k8s 建议使用 ReplicaSet 取代 ReplicationController。 虽然 RS 可以独立使用,但一般还是建议使用 Deployment 自动管理 RS。
-
Deployment
Deployment 为 Pod 和 RS 提供了声明式定义方式管理应用,用来替代 RS 命令式定义方式管理应用。且 Deployment 提供了很多 RS 不支持的机制,比如滚动升级( 类似游戏中的不停服更新 )和回滚应用。 -
DaemonSet
DaemonSet 确保 Node 上只运行一个 Pod。当有 Node 加入集群时,会为集群新 增一个 Pod。当有 Node 从集群移除时,这些 Pod 也会被回收。 -
Job
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod成功结束。 比如运行一次 SQL 脚本 -
Cron job
负责执行定时任务,即在给定时间点执行一次或周期性地在给定时间点执行任务
注意:
- 命令式:侧重于如何实现程序,就像我们刚接触编程的时候那样,我们需要把程序的实现过程按照逻辑结果一步步写下来。
- 声明式:侧重于定义想要什么,然后告诉计算机,让它帮你去实现。
- 滚动升级和回滚应用是通过操作两个RS来实现的, 大致过程是首先会在第一个RS减去一个pod, 然后会在另一个RS加上一个pod. 以此类推.
Service
Service 可以管理多个 Pod 作为一个整体被外部访问。在 k8s 中有以下四种类型的 Service:
-
ClusterIP
默认类型,自动分配一个仅集群内部可以访问的虚拟 IP -
NodePort
在 ClusterlP 基础上为 Service 绑定一个端口,可以通过该端口访问服务。 -
LoadBalancer
在 NodePort 的基础上创建一个负载均衡器,并将请求转发到 NodePort。 -
ExternalName
把集群外部的服务引入到集群内部,在集群内部直接使用
3. 架构
Master 节点
Master 节点是集群控制节点,负责管理和控制整个集群。基本上 k8s 的所有控制命令都发给它,它负责具体的执行过程。在 Master 上主要运行着:
- apiserver: 提供了集群管理的接口及模块之间的数据交互和通信的枢纽。
- etcd:保存整个集群的状态。
- controllers:自动化控制中心,负责维护管理集群状态,如:故障检测,自动扩展, 滚动更新等。
- scheduler: 负责资源调度,按照预定的调度策略将 Pod 调度到相应的机器上。
Node 节点
除 master 以外的节点被称为 Node 节点,每个 Node 都会被 Master 分配一些工作 负载(Docker 容器),当某个 Node 宕机时,该节点上的工作负载就会被 Master 自动转移到其它节点上。在 Node 上主要运行着:
- kube-proxy:实现 service 的通信与负载均衡。
- kubelet:用来处理 Master 节点下发到本节点的任务,管理 Pod 和其中的容器。
- container runtime:运行容器所需要的一系列程序
第二章 环境搭建与安装
搭建 Kubernetes 集群有多种方式:二进制包、kubeadm、第三方工具、云平台一键安装等方式都可以,这里我们采用 kubeadm 搭建 Kubernetes 集群
kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具,这个工具 能通过两条指令完成一个 kubernetes 集群的部署:
创建 Master 节点
kubeadm init
将 Node 节点加入到 Master 节点中
kubeadm join <Master 节点的 IP 和端口>
1. 虚拟机集群搭建
- 操作系统 CentOS7 以上
- 硬件配置:内存 2G 以上,CPU 2 核以上
- 集群内各个机器之间能相互通信,可以访问外网
- 禁止 swap 分区 swap 分区:即硬盘交换区,当内存不够用时,可以临时使用硬盘中的这部分空间。
创建三台 Linux 虚拟机
创建三台 Linux 虚拟机,一台作为 Master 节点,两台作为 Node 节点。
每台系统为 CentOS7,CPU 双核,内存 2G,硬盘 100G,网络选择桥接模式。
安装好后使用 SSH 工具(如 XShell)连接虚拟机,方便操作。
相关软件和虚拟机光盘映像文件分享至底部百度云
-
新建虚拟机
新建虚拟机-> 新建虚拟机向导->典型模式安装->安装程序光盘映像文件
-
个性化linux配置
配置linux 除root 用户外的用户. 三个虚拟机的名称依次为(master, node1, node2)
注意: 虽然这里配置的是root之外的用户信息, 但是这里的密码和root共享一个密码!!!
-
命令虚拟机
这里命名之后会在vm左侧显示对应名称的虚拟机, 这里根据第2步配置,
会在上面加一个前缀 k8s-, 则依次为 ( k8s-master, k8s-node1, k8s-node2 )
-
指定磁盘容量
大小为100GB, 设置存储为单个文件
-
自定义磁盘硬件
需要设置内存最小为2GB, 处理器数量最小为2个, 网络适配方式为桥接模式, 然后关闭即可, 最后在自定义界面点击完成即可进行初始化
-
installation summary
在初始化之后, 会出现installation summary 界面, 我们可以再次进行更细致的配置, 配置时区和网路哟配置. 时区设置为Asia, 地区为 Shanghai
网络配置: 开启以太网之后, 下面配置的ip就生效了,
我们后续可以根据这个ip和第二步的设置用户/ root 用户通过xhsell来登录
下面会安装linux的相关工具, 在安装结束后, 有可能会遇到下图警告,
提示协议还未接收, 我们需要点击进入并接受即可
接受以后点击Done, 然后点击右下角 完成配置选项
-
连接xshell
通过上面第2步创建的用户密码或者是root用户去连接xshell,
也可以使用其他linux命令行连接工具, 相关软件也会在底部分享 -
Kubernetes 部署环境准备
注意: 除了下面代码的步骤6, 其他的命令都要批执行# 1. 关闭防火墙 systemctl stop firewalld systemctl disable firewalld # 2. 关闭 selinux selinux:linux 的安全系统 sed -i 's/enforcing/disabled/' /etc/selinux/config # 3. 关闭 swap sed -ri 's/.*swap.*/#&/' /etc/fstab # 4. 设置网桥参数 ## 注意 < 代表文本输入重定向, >代表文本输出重定向, eg: ## <<< 从字符串中读取输入 ## <<E 从键盘中读取输入,E表示结束符 ## < 从文件中读取输入 cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF # 5. 时间同步 yum install ntpdate -y ntpdate time.windows.com # 6. 在 master 节点为各主机的 IP 命名 ## 需要根据自己服务器ip和域名情况自行设置 ## 这一步的目的是为了最后k8s集群能够显示方便(NAME显示名称), 如下图 cat >> /etc/hosts << EOF 192.168.10.44 master 192.168.10.45 node1 192.168.10.46 node2 EOF # 7. 重启虚拟机 reboot
命令批执行技巧
这里需要注意的是这些配置三台机器都需要配置,
可以使用xshell 撰写窗格功能, 作用是可以批量执行这些命令
可以在xshell 最上方工具栏的 查看 -> 撰写 -> 撰写窗格中打开
选择全部会话, 即可将当前打开的所有会话窗口都执行一样的命令
2. K8s相关软件安装
Kubernetes 的每个节点都需要安装 Docker、kubeadm、kubelet、kubectl
- Docker:Kubernetes 默认容器运行环境是 Docker,因此首先需要安装 Docker
- Kubectl:k8s 命令行工具,通过 kubectl 可以部署和管理应用,查看各种资源,创建、 删除和更新组件
- Kubeadm:用于构建 k8s 集群
- Kubelet:负责启动 POD 和容器
Docker安装配置
所有命令都需要批执行(master, node1, node2)
# 1. 安装yum必要的一些工具集
sudo yum install -y yum-utils device-mapper-persistent-data
# 2. 配置yum 镜像源, 加速yum 下载相关软件的速度, 选择任何一个源即可
## 阿里源
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
## 清华源
sudo yum-config-manager \
--add-repo \
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
# 3. 安装 Docker
yum -y install docker-ce
## 如果 yum 下载过程中断开,造成 yum 程序锁定,可运行以下命令关闭 yum 程序
rm -f /var/run/yum.pid
# 4. Docker 配置加速器加速镜像下载(让docker可以更快下载docker镜像)
mkdir -p /etc/docker
touch /etc/docker/daemon.json
cat >> /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
EOF
# 5. 开机自启动 docker 服务
systemctl enable docker.service
K8s安装配置
命令虽长, 但是直接全部复制一次执行即可
所有命令都需要批执行(master, node1, node2)
# 1. 配置 yum 源镜像
## 通过 cat /etc/yum.repos.d/kubernetes.repo 查看自己配置的文件有问题(例如有空格)
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 2. 安装软件
yum install kubelet-1.19.4 kubeadm-1.19.4 kubectl-1.19.4 -y
# 3. 开机自启动k8s服务
systemctl enable kubelet.service
# 4. 查看是否安装成功 , 这种命令可以通过xshell撰写窗口一次执行所有命令
yum list installed | grep kubelet
yum list installed | grep kubeadm
yum list installed | grep kubectl
# 5. 重启虚拟机
reboot
K8s部署配置
-
在master节点执行下面命令
kubeadm init \ --apiserver-advertise-address=192.168.10.44 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.19.4 \ --service-cidr=10.96.0.0/12 \ --pod-network-cidr=10.244.0.0/16 注意: 1. piserver-advertise-address 指向的是自己master节点地址 2. image-repository 无需改动, 这里使用的阿里云的k8s镜像地址 3. kubernetes-version k8s版本, 与上面K8s安装配置的第2步对应 4. service-cidr 的选取不能和 pod-cidr 及本机网络有重叠或者冲突, 一般可以选择一个 本机网络和 pod-cidr 都没有用到的私网地址段, 因此这两个参数无需修改
-
执行k8s初始化设置后, 需要根据命令行提示进行配置
根据上图提示, 执行如下命令mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
根据上图提示, 若想要其他节点(node1, node2)加入master 节点的话, 执行最后两行即可
# 这里的命令不要复制我的, 要根据自己显示的内容去复制和执行, 因为这里加入命令的ip, token, 加密方式可能会不同!!! kubeadm join 192.168.10.44:6443 --token 7jfl53.rviiwwuzprj21v2p \ --discovery-token-ca-cert-hash sha256:9076d21bd81217638273cafb447d291f014d11e6226c16f85cbcd182402fadc3
-
查看节点
这里可以看到状态是 NotReady, 需要安装网络插件kubectl get nodes
安装网络插件
只在master node 执行下面命令
# 1. 安装命令行上传下载软件 lrzsz (如果使用的是本博客分享的光盘镜像的话无需执行这一步, 默认已安装)
yum install -y lrzsz
# 2. 使用 rz 上传 kube-flannel.yml 文件, 文件在博客底部分享
# 3. 应用 kube-flannel.yml 文件得到运行时容器
kubectl apply -f kube-flannel.yml
# 4. 等一会儿后查看节点状态(2min左右)
kubectl get nodes
# 5. 如果需要删除节点, 则执行
kubectl delete node 节点名
第三章 部署K8s容器化应用
容器化应用:把一个应用程序放在 docker 里部署,这个 docker 应用就是容器化应用, 在 docker 中我们通过启动镜像部署容器化应用
如何在 k8s 中部署容器化应用:
- 获取镜像:编写 Dockerfile 制作镜像,或者从仓库拉取镜像
- 控制器创建 pod:控制器启动镜像,创建容器并将容器放入 pod 中
- 暴露应用,使外界可以访问应用
1. K8s常用命令
# 查看节点
kubectl get nodes (node)
# 查看 service
kubectl get service
# 查看控制器:
kubectl get deployment (deploy)
# 查看 pod
kubectl get pod
# 删除 service
kubectl delete service 服务名
# 删除控制器
kubectl delete deployment 控制器名
# 删除 pod
kubectl delete pod pod 名
2. 安装 nginx
-
从仓库拉取镜像,使用deployment 控制器创建 pod
# 相当于 获取镜像+ 控制器创建pod 步骤 # 常见控制器种类: RS, Deployment, DaemonSet, Job, Cron job(见1.2) kubectl create deployment nginx --image=nginx
-
查看控制器(controller)和 pod创建情况
# 查看pod kubectl get pod # 查看控制器 kubectl get deployment (deploy) # 可以看到一开始时Ready: 0/1(未准备好) , status: ContainerCreating(容器创建中) # 过一段时间可以看到: Ready: 1/1(准备好) , status: Running(运行中)
-
创建 service 暴露 pod 端口
# service类型: ClusterIP, NodePort, LoadBalancer, ExternalName(详见1.2) kubectl expose deployment nginx \ --port=80 \ --target-port=80 \ --type=NodePort # 查看service情况(如图1, 对外访问端口为: 31949) kubectl get service # 访问应用,地址为:http://NodeIP:NodePort ## 同时创建好的Service, 可以通过所有节点ip+对应端口访问(高可用) http://192.168.10.44:31949/ http://192.168.10.45:31949/ http://192.168.10.46:31949/
图1
图2
- 关闭 nginx
# 1, 删除service (首先要通过kubectl get service查看要删除的service名称, 这里为nginx, 如图1)
## 删除Service以后其实相当于关闭Docker中的Container, nginx已经被关闭
kubectl delete service nginx
# 2. 删除控制器(图2)
kubectl get deploy
kubectl delete deploy nginx
# 3. 删除pod(图3)
## 因为控制器deployment用于管理pod, 所以在上一步我们将控制器删除后, 也将它管理的pod一并删除了
## 理论上删除pod命令不会用到, 具体原因可见下面注意事项
kubectl get pod
kubectl delete podname
注意:
删除顺序不能相反, 不能先删除pod, 再删除控制器.
因为控制器管理着pod, 你删除一个pod它会再次重启一个pod(图4)
图1
图2
图3
图4
3. 安装 Tomcat
# 1. 从仓库拉取镜像,通过deployment 控制器创建 pod
kubectl create deployment tomcat --image=tomcat
## 确认创建pod是否完成 , 确认该pod对应的 Ready是否为: 1/1 (准备完成), 0/1(未准备完成)
kubectl get pod
# 2. 创建 service 暴露 pod 端口(图1)
kubectl expose deployment tomcat \
--port=8080 \
--type=NodePort
## 查看 Service暴露后对应的外部端口号, 在PORT(S) 属性后 8080: 后面的端口号
kubectl get service
# 3. 访问(图2)
http://192.168.10.44:30471/
图1
图2
4. 部署 SpringBoot 项目
所需的 jdk以及springboot测试用jar已分享至底部百度云
构建 JDK 镜像
# 1. 创建Dockerfile文件
cat <<EOF > Dockerfile
# 基于 centos7,如果没有这个镜像那么它会下载这个镜像。
FROM centos:7
# 创建者
MAINTAINER timepause
# 复制文件到指定目录并自动解压(不是真实目录而是docker容器目录)
ADD jdk-8u144-linux-x64.tar.gz /usr/local/jdk
# 设置环境变量
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_144
ENV CLASSPATH=.:$JAVA_HOME/lib
ENV PATH=$JAVA_HOME/bin:$PATH:/usr/local/jdk/jdk1.8.0_144/bin
EOF
# 2. 构建 JDK 镜像 (注意不要少了".")
docker build -t='jdk1.8' .
# 3. 查看所有的镜像,此时就多了一个 jdk1.8 17
docker images
# 4. 创建容器
docker run -di --name=jdk1.8 jdk1.8 /bin/bash
# 5. 进入容器
docker exec -it jdk1.8 /bin/bash
java -version
构建项目镜像
# 1. 使用 maven 将项目打成 jar 包,使用 rz 上传到虚拟机中
# 2. 编写Dockerfile文件
cat <<EOF > Dockerfile
FROM jdk1.8
MAINTAINER timepause
ADD springboot-k8s-1.0.0.jar /opt
RUN chmod +x /opt/springboot-k8s-1.0.0.jar
CMD java -jar /opt/springboot-k8s-1.0.0.jar
EOF
# 3. 构建项目镜像:
docker build -t springboot-k8s-1.0.0.jar .
# 4. 使用镜像启动容器(外部访问端口8085)
docker run -d -p 8085:8080 springboot-k8s-1.0.0.jar
# 5. 访问测试
http://192.168.10.44:8085/demo
上传镜像
上传镜像到Docker官方仓库, 作用是方便其他节点下载, 否则其他节点就必须一个个去通过上面两个步骤去构建了
# 1. 注册登录 DockerHub 网站
https://hub.docker.com
# 2. 在 DockerHub 创建镜像仓库 (springboot-k8s)
https://hub.docker.com/repositories
# 3. 在 master 节点登录 DockerHub
docker login
# 4. 将本地镜像修改为规范的镜像名称
docker tag docker 镜像名 注册用户名/仓库名
# 5. 上传镜像
docker push 注册用户名/仓库名
K8s集群部署
1. 命令行部署项目
kubectl create deployment springboot-k8s --image=注册用户名/仓库名
2. yml 文件部署项目
yml 文件是 k8s 的资源清单文件,我们可以通过 yml 文件精确修改构建参数。
-
空运行测试,空运行测试没有真正运行项目,而是生成项目运行的 deploy.yml配置文件
kubectl create deployment springboot-k8s \ --image=461618768/springboot-k8s \ --dry-run \ --output yaml > deploy.yml #--image=注册用户名/仓库名 #--dry-run 空运行, 不会运行项目只会产生 yml文件
-
修改 yml 文件,把镜像拉取策略改为 IfNotPresent,即如果本地有镜像就使用本地镜像,没有就拉取在线镜像。
imagePullPolicy: IfNotPresent
containers: - image: springboot-k8s name: springboot-k8s-1-0-0-jar-8ntrx imagePullPolicy: IfNotPresent
-
使用 yml 文件构建 deployment
kubectl apply -f deploy.yml
yml 常用字段含义
我们首先可以查看一下自动生成的 deploy.yml[root@master springboot]# cat deploy.yml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: springboot-k8s name: springboot-k8s spec: replicas: 1 selector: matchLabels: app: springboot-k8s strategy: {} template: metadata: creationTimestamp: null labels: app: springboot-k8s spec: containers: - image: 461618768/springboot-k8s name: springboot-k8s imagePullPolicy: IfNotPresent resources: {} status: {}
下图是每个字段的解释
暴露服务端口
暴露服务接口后, 外部便可访问
# 对外暴露pod端口
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort
# 查看对外暴露端口
kubectl get service
访问项目
http://NodeIP:NodePort/资源路径
5. Ingress
Ingress 相当于是服务网关,可以通过 URL 路径代理 service,只需要暴露一个端口就可以满足所有 service 对外服务的需求,生产环境建议使用这种方式。(因为生产环境会对开放的端口进行严格的限制)
Ingress 产生的背景
-
使用 LoadBalancer 暴露服务可以解决端口过多的问题,但 LoadBlancer 需要向云平台申请负载均衡器,与云平台的耦合度太高,相当于购买了服务。
-
NodePort 方式最大的缺点是每个 service 都要暴露端口,在部署微服务时会暴露大量 端口加大管理难度,所以在生产环境中不推荐使用这种方式来直接发布服务.
我们通过 kubectl create deployment pod-name
这种命令能够快速去安装k8s 软件,本质上还是通过 yml/yaml 去安装配置并运行相关软件(但没有暴露端口因此无法访问), 我们可以通过 kubectl get service 服务名 -o yaml
来查看这个配置文件
配置文件资源清单中有三个端口(如下图):
- nodePort:定义外部访问的端口
- port:定义集群内部通信的端口
- targetPort:定义容器中服务的端口
安装部署 Ingress
. Ingress不是k8s的内置软件,需要单独安装,k8s官方使用Ingress Nginx实现Ingress功能
- 下载 Ingress Nginx 资源清单文件(也可以直接下载博客底部资料):
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/d eploy/static/provider/baremetal/deploy.yaml
-
为了能够正常访问 Ingress,还需要在ingress-deploy.yaml添加如下配置:
-
运行资源清单,安装 Ingress Nginx
# 应用当前配置, 安装 ingress kubectl apply -f ingress-deploy.yaml # 安装是否成功 (如下图) kubectl get pod -n ingress-nginx
-
创建 Ingress 规则
# 删除默认配置: kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission # 执行资源清单配置 Ingress 规则(多域名配置请自行探究): kubectl apply -f ingress-nginx-rule.yaml --------------------ingress-nginx-rule.yaml--------------------- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: k8s-ingress # 路由名称 spec: rules: - host: timepause.site http: paths: - pathType: Prefix path: / #匹配路径 backend: service: name: springboot-k8s # 转发的服务名 port: number: 8080 # 代理的内部端口 --------------------ingress-nginx-rule.yaml--------------------- # 查看 Ingress 规则(需要等待一会才会显示我们配置好的规则信息): kubectl get ingress
-
测试
由于 Ingress 暴露的是一个网址而不是 IP 地址,但服务并未发布到外网,所以测试计算机要将网址和 IP 地址做映射。(如果使用的是绑定域名的服务器则无需此步骤) 打开C:\Windows\System32\drivers\etc\hosts
,添加:# 注意:这里配置映射的ip只要是k8s集群ip即可 192.168.10.46 timepause.site
访问ingress代理后的域名
6. 部署微服务项目
准备
我们准备一个微服务项目 demo,该项目只有一个功能:借阅图书。项目包括 eureka
注册中心,gateway 网关,用户服务,会员服务。借阅图书调用图书服务的方法,该方法
内会使用 Feign 调用会员服务的方法验证是否存在该会员。
注意事项
k8s 主要是针对无状态应用设计的,所以一般情况下我们不在 K8S 中部署有状态应用,如 mysql、Eureka 等。
- 无状态应用:是指应用不会在会话中保存下次会话所需要的客户端数据。每一个会话都
像首次执行一样,不会依赖之前的数据进行响应。如 WEB 服务器。 - 有状态应用:是指应用会在会话中保存客户端的数据,并在客户端下一次的请求中来使
用那些数据。如数据库、Eureka 注册中心。
案例中我们部署了 Eureka,但实际运维过程中一般不会将其放入 k8s 集群。
具体步骤:
-
将项目导入idea
大致流程, 新建一个 Empty类型项目, 名称任意(例如: k8s-demo),
然后创建完毕后在空项目中添加上图四个 module(new -> new module from exisiting sources…), 项目在底部分享 -
启动测试, 打开对应的启动类
注意本地启动需要修改gateway, book, member 服务配置文件中注册中心地址为本地
-
启动无误后可以打包项目(maven->package), 然后上传到k8s master节点上
-
部署 Eureka 注册中心
# 1. 编写 DockerFile 文件 cat <<EOF > Dockerfile FROM jdk1.8 MAINTAINER hy ADD lib_registry-1.0.0.jar /opt RUN chmod +x /opt/lib_registry-1.0.0.jar CMD java -jar /opt/lib_registry-1.0.0.jar EOF ## 修改原来jar名称以对应DockerFile文件 mv lib_registry-0.0.1.jar lib_registry-1.0.0.jar # 2. 制作Docker镜像 docker build -t lib_registry-1.0.0.jar . ## 制作后可以通过下面命令查看 docker images # 3. 上传镜像到DockerHub ## 官网地址,需要注册账号 https://hub.docker.com/repository/ ## 创建镜像仓库,命名为 lib-register ## 登录 Docker Hub docker login ## 将本地镜像修改为规范的镜像名称:(需要与创建的镜像仓库名称一样) docker tag lib_registry-1.0.0.jar 461618768/lib-registry ## 格式: docker tag jar名称 dockerhub用户名/仓库名 ## 上传镜像: docker push 461618768/lib-registry
-
部署项目
# 根据自己的镜像在k8s中创建pod,controller,service kubectl create deployment lib-registry --image=461618768/lib-registry # 查看对应pod等相关东西是否创建完毕(Ready=1/1) ## 然后再执行下一步, 否则会报错 kubectl get all
-
暴露服务
## 给 Eureka 创建服务 cat <<EOF > eureka-server.yml apiVersion: v1 kind: Service metadata: name: lib-registry labels: app: lib-registry spec: ports: - port: 9007 targetPort: 8761 #代理端口 nodePort: 31234 #对外固定暴露端口 name: lib-registry type: NodePort selector: app: lib-registry EOF # 执行资源清单 kubectl create -f eureka-server.yml
-
部署网关、book 服务、Member 服务
每个微服务的 application.yml 要做如下配置, 修改eureka地址,
因为Eureka部署在服务器而对外暴露的端口为 31234, 因此地址应是http://localhost:31234/eureka/
, 这样才能够连接到注册中心
-
将三个微服务打成 jar 包,使用上传到 master 节点中,之后分别构建镜像:
# 1. 制作 gateway 镜像: cat <<EOF > Dockerfile FROM jdk1.8 MAINTAINER hy ADD lib_gateway-1.0.0.jar /opt RUN chmod +x /opt/lib_gateway-1.0.0.jar CMD java -jar /opt/lib_gateway-1.0.0.jar EOF ## 构建镜像 docker build -t lib_gateway-1.0.0.jar . # 2. 制作 member 镜像: cat <<EOF > Dockerfile FROM jdk1.8 MAINTAINER hy ADD lib_member-1.0.0.jar /opt RUN chmod +x /opt/lib_member-1.0.0.jar CMD java -jar /opt/lib_member-1.0.0.jar EOF ## 构建镜像 docker build -t lib_member-1.0.0.jar . # 3. 制作 book 镜像: cat <<EOF > Dockerfile FROM jdk1.8 MAINTAINER hy ADD lib_book-1.0.0.jar /opt RUN chmod +x /opt/lib_book-1.0.0.jar CMD java -jar /opt/lib_book-1.0.0.jar EOF ## 构建镜像 docker build -t lib_book-1.0.0.jar . ## 查看是否制作成功: docker images # 4. 上传镜像 ## 在dockerhub创建三个镜像仓库,命名为 lib-member、lib-book、lib-gateway、lib-registry ## 将本地镜像修改为规范的镜像名称: docker tag lib_gateway-1.0.0.jar 461618768/lib-gateway docker tag lib_member-1.0.0.jar 461618768/lib-member docker tag lib_book-1.0.0.jar 461618768/lib-book ## 上传镜像到dockerhub: docker push 461618768/lib-gateway docker push 461618768/lib-member docker push 461618768/lib-book
-
部署项目
kubectl create deployment lib-gateway --image=461618768/lib-gateway kubectl create deployment lib-member --image=461618768/lib-member kubectl create deployment lib-book --image=461618768/lib-book
-
Ingress 暴露网关服务与访问测试
# 1. 创建网关的 Service kubectl expose deployment lib-gateway --port=80 --type=ClusterIP # 2. 修改 Ingress 规则文件 vim ingress-nginx-rule.yaml --------------------ingress-nginx-rule.yaml--------------------- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: k8s-ingress # 路由名称 spec: rules: - host: book.lib # 转发的域名(这里自定义, 生产中根据实际情况配置) http: paths: - pathType: Prefix path: / #匹配路径 backend: service: name: lib-gateway # 转发的服务名 port: number: 80 # 代理的内部端口 --------------------ingress-nginx-rule.yaml--------------------- # 3. 执行资源清单配置 Ingress 规则: kubectl apply -f ingress-nginx-rule.yaml # 4. 测试 Ingress ## 因为使用的是本地的虚拟机,没有域名, 因此需要在hosts文件上面做ip域名映射 ## 打开测试计算机的 C:\Windows\System32\drivers\etc\hosts,添加: 192.168.10.44 book.lib ## 访问: http://book.lib/book/takeBook?bookId=1&telPhone=13888888888
补充: 可通过DashBoard 对部署的服务进行动态扩容
7. DashBoard
DashBoard 是 k8s 的可视化管理工具,可以基于 web 对 k8s 集群进行集中管理。
-
下载 yml 资源清单(也可通过底部分享的文件中获取)
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/r ecommended.yaml
ps:如果是通过wget下载的, 需要修改yml文件内容
注释以下内容
- 应用 yml 的资源清单,安装 DashBoard
# 1. 应用 yml 的资源清单,安装 DashBoard kubectl apply -f recommended.yaml # 2. 经过第1步后, DashBoard 没有安装在默认空间下, 而是安装在kubernetes-dashboard 命名空间下 ## 查看当前命名空间命令, 可以看到新生成了一个命名空间kubernetes-dashboard kubectl get namespace ## 查看新生成的命名空间 kubernetes-dashboard, status=Active说明命名空间创建完毕 kubectl get namespace kubernetes-dashboard ## 查看当前命名空间下pod 的创建情况, 需要等到 Ready=1/1 方可执行下一步 kubectl get pod -n kubernetes-dashboard # 3. 访问kubernetes-dashboard ## 通过service查看对外暴露端口, 可以看到默认命名空间没有该service kubectl get service ## 切换到 kubenetes-dashboard 命名空间, 可以看到dashboard对外暴露端口 kubectl get service -n kubernetes-dashboard # 4. 根据上面获得的端口访问 kubenetes-dashboard https://192.168.10.44:30001/ ## 可以看到页面提示我们输入token, 下一步我们来生成token ps: namespace:命名空间,为了在多租户情况下,实现资源隔离,之前使用的是 default 命名空间。 比如一套 k8s 集群可以针对开发环境和测试环境进行两套互不影响的部署, 属于逻辑性隔离,可以针对 namespace 做资源配额
图1
图2
图3
-
生成 kubenetes-dashboard 访问 token
# 1 kubectl create serviceaccount dashboard-admin -n kube-system # 2 kubectl create clusterrolebinding dashboard-admin\ --clusterrole=cluster-admin\ --serviceaccount=kube-system:dashboard-admin # 3 kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}') ## 注意: 第1第2步只需要执行一次, 后续如果还需要获取 token 只需执行第3步即可, 如下图
k8s Dashboard 主页
8. Helm
Helm 是一个 k8s 的应用管理工具,可以很方便的通过管理 yaml 文件来部署应用,更新应用版本。目前 Heml 的 V3 版本发布,极大简化了之前繁琐的使用方式
出现背景:
k8s 上的 deployment、service 等应用对象,都是由资源清单部署的。对于一个复杂的应用,会有很多类似的资源清单文件。例如微服务架构应用,组成应用的服务可能多达几 十个。如果有更新或回滚应用的需求,可能要修改维护大量 yml 文件。
Helm 中有 3 个重要概念:
- helm:命令行客户端工具,能够进行 chart 的创建,项目打包、发布和管理。
- chart:应用描述,一系列用于描述 k8s 资源相关文件的集合。
- release:基于 chart 部署的资源,chart 被 helm 运行后将会生成对应 release。
安装 release
-
解压与上传
# 相关软件(helm-v3.0.0-linux-amd64.tar.gz )分享见底部百度云 # 使用 rz 将 helm 上传到 linux tar zxvf helm-v3.0.0-linux-amd64.tar.gz # 解压后移动到/usr/bin 目录下 mv linux-amd64/helm /usr/bin/
-
远程仓库中的 chart 安装 release
执行下面三个命令# 配置国内 chart 仓库 helm repo add stable http://mirror.azure.cn/kubernetes/charts helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts helm repo update
-
安装示例
# 查找 chart helm search repo tomcat # 根据查找结果, 查看 chart 具体信息 helm show chart stable/tomcat # 安装 release helm install 应用名 仓库名 eg: helm install ui stable/tomcat ##查看是否安装完成, 确认对应的deploy,pod Ready状态是否为1/1, ##如果为1/1则查看对应service映射的新端口, 通过http://ip:新端口/xyz...访问 kubectl get all # 查看所有 release helm list # 查看发布状态 helm status 应用名 # 卸载 release helm uninstall 应用名
自定义 chart 安装 release
# 1. 构建 Chart
helm create mychart
# 2. 进入构建好的 Chart
cd mychart/
# 3. 进入 template 文件夹
cd template/
# 4. 删除文件夹内所有自带文件
rm -rf *
# 5. 通过上面上传到docker hub的springboot生成 deployment 和 service 的 yml 文件
kubectl create deployment springboot-k8s --image=461618768/springboot-k8s --dry-run --output yaml > deployment.yaml
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort --dry-run -o yaml > service.yaml
# 6. 退出到上一级目录
cd ..
# 7. 如果之前通过k8s部署安装了springboot项目, 需要删除对应的service, deploy, pod. (反之直接执行下一步)
kubectl get all
kubectl delete service springboot-k8s
kubectl delete deploy springboot-k8s
kubectl delete pod springboot-k8s
# 8. 部署 release
## helm 命令 . => 空格+点的作用是在当前文件下生效
helm install springboot-k8s .
# 9. 应用升级 helm (如下图)
## helm 命令 . => 空格+点的作用是在当前文件下生效
upgrade springboot-k8s .
使用 chart 模板安装 release
在上一个实操中, 我们自定义 chart 安装 release, 通过构建 Chart 生成了一个 mychart 文件夹, 我们可以通过修改这个文件下的values.yaml 来作为 chart 模板安装 release
-
修改 values.yaml,添加需要配置的数据,如:
image: 461618768/springboot-k8s serviceport: 8080 targetport: 8080 label: springboot-k8s
-
进入 template,修改 deployment.yaml 和 service.yaml,在需要配置数据的地方使用
{{ .Values.参数名}}
来使用模板参数,如:metadata: labels: app: {{ .Values.label }} name: {{ .Values.label }}
9. 搭建高可用集群
Master 节点扮演着总控中心的角色。如果 Master 节点故障,将无法进行任何集群管理。搭建高可用集群即在集群中搭建多个 master 节点,保证集群的安全性和稳定性。
高可用集群架构
高可用集群技术图:
搭建高可用环境准备
在原来基础上 (1台k8s-master, 两台 node虚拟机外), 再额外安装一台新的虚拟机, 作为master节点宕机后的备用 master 节点
-
安装流程按照第二章第1节, 以及第2节 Docker安装配置, 以及K8s安装配置. 后续无需配置
-
安装一台 k8s 环境的 master 节点,安装后设置该虚拟机的主机名
hostnamectl set-hostname master2
-
Master 节点安装 keepalived
在每台 master 节点做如下操作# 安装相关包和 keepalived yum install -y conntrack-tools libseccomp libtool-ltdl yum install -y keepalived
-
配置 keepalived
注意 vip 和网卡名不要配错cat > /etc/keepalived/keepalived.conf <<EOF !Configuration File for keepalived global_defs { router_id k8s } vrrp_script check_haproxy { script "killall -0 haproxy" interval 3 weight -2 fall 10 rise 2 } vrrp_instance VI_1 { state MASTER interface ens33 # 需查看自己的网卡名称 ifconfig virtual_router_id 51 priority 250 advert_int 1 authentication { auth_type PASS auth_pass ceb1b3ec013d66163d6ab } virtual_ipaddress { 192.168.10.50 #设置虚拟ip(VIP),不能与每个节点的实际ip重复 } track_script { check_haproxy } } EOF
-
设置自动启动 keepalive
systemctl start keepalived.service systemctl enable keepalived.service systemctl status keepalived.service
-
查看生成的 vip
ip a s ens33
可以看到虚拟ip在master节点上而master2没有, 只有当master节点挂掉之后虚拟ip才会被keepalived分配到master2上
安装反向代理服务器 haproxy
-
在每台 master 节点做如下操作:
需要自行配置 bind 绑定端口以及 balance roundrobin 轮询的master节点ip# 安装 haproxy yum install -y haproxy
-
配置 haproxy
cat > /etc/haproxy/haproxy.cfg << EOF #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # kubernetes apiserver frontend which proxys to the backends #--------------------------------------------------------------------- frontend kubernetes-apiserver mode tcp bind *:16443 #指定了 haproxy 运行的端口为 16443, 因此 16443 端口为集群的入口 option tcplog default_backend kubernetes-apiserver #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend kubernetes-apiserver mode tcp balance roundrobin server master 192.168.10.44:6443 check #根据自己master所在ip配置 server master2 192.168.10.23:6443 check #根据自己master所在ip配置 #--------------------------------------------------------------------- # collection haproxy statistics message #--------------------------------------------------------------------- listen stats bind *:1080 stats auth admin:awesomePassword stats refresh 5s stats realm HAProxy\ Statistics stats uri /admin?stats EOF
-
设置自动启动
systemctl start haproxy systemctl enable haproxy
-
查看安装状态
systemctl status haproxy
重新部署 Master1 节点
-
在 master1 节点操作
# 1. 重置 master1 节点 kubeadm reset # 2. 删除原有目录 ## 如果你在执行 kubeadm reset命令后没有删除创建的 $HOME/.kube目录,重新创建集群就会出现 ## Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes") rm -rf $HOME/.kube # 3. 使用配置文件创建 master 节点 cat <<EOF > kubeadm-config.yaml apiServer: certSANs: - master # master 主机名 - master2 # master 主机名 - k8s-vip # 虚拟ip主机名, 自定义 - 192.168.10.44 # master 主机ip - 192.168.10.23 # master 主机ip - 192.168.10.50 # 虚拟ip - 127.0.0.1 # 本机回环ip extraArgs: authorization-mode: Node,RBAC timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta1 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controlPlaneEndpoint: "192.168.10.50:16443" # haproxy暴露的ip+port controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: registry.aliyuncs.com/google_containers kind: ClusterConfiguration kubernetesVersion: v1.19.4 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 serviceSubnet: 10.1.0.0/16 scheduler: {} EOF # 4. 执行配置文件(详细信息见下一块代码) kubeadm init --config kubeadm-config.yaml # 5. 按照提示配置环境变量 mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
You can now join any number of control-plane nodes by copying certificate authorities and service account keys on each node and then running the following as root: You can now join any number of control-plane nodes by copying certificate authorities and service account keys on each node and then running the following as root: # 其他 master 加入执行下面命令 kubeadm join 192.168.10.50:16443 --token pd8j14.hmecvp77ec2zidxz \ --discovery-token-ca-cert-hash sha256:3e78f624c36a8f581c277ca88e4d4aa2f10822916c5c1c84afdc25fffb8e1e2d \ --control-plane Then you can join any number of worker nodes by running the following on each as root: # 其他node节点加入时执行下面命令 kubeadm join 192.168.10.50:16443 --token pd8j14.hmecvp77ec2zidxz \ --discovery-token-ca-cert-hash sha256:3e78f624c36a8f581c277ca88e4d4aa2f10822916c5c1c84afdc25fffb8e1e2d
-
将 Master2 节点加入 k8s 集群中
# 1. 将 master1 的密钥及相关文件复制到 master2 ## 在 master1 执行: ssh root@192.168.10.23 mkdir -p /etc/kubernetes/pki/etcd scp /etc/kubernetes/admin.conf root@192.168.10.23:/etc/kubernetes scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@192.168.10.23:/etc/kubernetes/pki scp /etc/kubernetes/pki/etcd/ca.* root@192.168.10.23:/etc/kubernetes/pki/etcd # 2. master加入集群(需要根据kubeadm init 执行后生成的报文来配置) kubeadm join 192.168.10.50:16443 --token pd8j14.hmecvp77ec2zidxz \ --discovery-token-ca-cert-hash sha256:3e78f624c36a8f581c277ca88e4d4aa2f10822916c5c1c84afdc25fffb8e1e2d \ --control-plane # 3. 配置环境变量 mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
-
将 node 节点加入 k8s 集群
# 0. 如果之前node 加入过集群, 且集群master 已重置, 那么我们也需要将node节点重置 kubeadm reset # 1. 加入node节点 ## 其他node节点加入时执行下面命令 kubeadm join 192.168.10.50:16443 --token pd8j14.hmecvp77ec2zidxz \ --discovery-token-ca-cert-hash sha256:3e78f624c36a8f581c277ca88e4d4aa2f10822916c5c1c84afdc25fffb8e1e2d ## 如果安装失败,出现提示 /proc/sys/net/ipv4/ip_forward contents are not set to 1 ##原因是 node 节点禁止 ip 转发,需要进行如下操作: # 2. 查看是否打开 IP 转发,0 代表禁止,1 代表转发 less /proc/sys/net/ipv4/ip_forward ##如果为 0,需要更改文件的内容 echo "1" > /proc/sys/net/ipv4/ip_forward # 3. 重启网络服务 service network restart ## 重启虚拟机,重新加入 k8s 集群 ## 重新执行第1步操作, 并查看是否加入成功 kubectl get nodes
点赞私聊获取这些资源哦~~~
微服务项目案例代码百度云链接:https://pan.baidu.com/s/1LMApff81raccNHeFB5l0rg
提1取码:vmwj
项目所需所有软件百度云链接:https://pan.baidu.com/s/1m1wACTkCufPjbkD8-3xaeQ
点赞关注+私信获取提取码
提取码:y0ua
更多推荐
所有评论(0)