Kubernetes(K8s) —— 容器编排管理技术
K8s 容器编排管理技术
- 第一章 是什么
- 背景
- 基础概念
- Pod
- 控制器
- Service
- 架构
- 第二章 环境搭建与安装
- 虚拟机集群搭建
- 命令批执行技巧
- K8s相关软件安装
- Docker安装配置
- K8s安装配置
- K8s部署配置
- 安装网络插件
- 第三章 部署K8s容器化应用
- K8s常用命令
- 安装 nginx
- 安装 Tomcat
- 部署 SpringBoot 项目
- 构建 JDK 镜像
- 构建项目镜像
- 上传镜像
- K8s集群部署
- 暴露服务端口
- 访问项目
- Ingress
- 部署微服务项目
- 准备
- 注意事项
- 具体步骤:
- DashBoard
- Helm
- 安装 release
- 自定义 chart 安装 release
- 使用 chart 模板安装 release
- 搭建高可用集群
- 搭建高可用环境准备
- 安装反向代理服务器 haproxy
- 重新部署 Master1 节点
第一章 是什么
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 nginx3. 删除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
还没有评论,来说两句吧...