1、K8S核心概念与集群搭建
一、K8S核心概念与集群搭建
#kubernetes集群搭建
部署K8S的2种方式
.kubeadm
Kubeadm是一个工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
.二进制
从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
CentOS 7(使用 yum 进行安装)
#docker镜像加速的配置
#Kubernetes的基础知识
部署Kubernetes集群主要有两种方式:
Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
这里采用kubeadm搭建集群。
kubeadm工具功能:
kubeadm alpha
服务器规划:
#Kubernetes的架构
#Kubernetes的初始化安装(每个节点都需要做)
----> 关闭防火墙
----> 关闭selinux
----> 关闭swap
----> 在master上编辑hosts(注意只在master上)
----> 将桥接的IPv4流量传递到iptables的链
----> 时间同步
#Kubernetes的安装(添加阿里云YUM软件源)
#安装kubeadm kubelet kubectl
#部署kubernetes Master
在master节点上单独执行:
在node节点上执行
#部署kubernetes 的网络插件
Calico是一个纯三层的数据中心网络方案,是目前Kubernetes主流的网络方案。
修改完后文件后,部署:
用yaml文件部署calico网络
CoreDNS问题处理:
在所有节点上重新pull拉起coreDNS镜像
安装目录:/etc/kubernetes/
组件配置文件目录:/etc/kubernetes/manifests/
#测试kubernetes集群搭建的情况
Dashboard是官方提供的一个UI,可用于基本管理K8s资源。
默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:
部署:
创建service account并绑定默认cluster-admin管理员集群角色:
#kubernetes基本概念
自动安装脚本:
Master 负责管理集群 负责协调集群中的所有活动,例如调度应用程序,维护应用程序的状态,扩展和更新应用程序。
Node节点(即Work)是VM(虚拟机)或物理计算机,充当k8s集群中的工作计算机。 每个Node节点都有一个Kubelet,它管理该Node节点并负责与Master节点通信。该Node节点还应具有用于处理容器操作的工具,例如Docker。
容器编排系统的:
#kubernetes集群控制组件
Master组件
. kube-apiserverKubernetes API
集群的统一入口,各组件协调者,以RESTful API提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储。
. kube-controller-manager
处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager就是负责管理这些控制器的。
. kube-scheduler
根据调度算法为新创建的Pod选择一个Node节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。
. etcd
分布式键值存储系统。用于保存集群状态数据,比如Pod、Service等对象信息。
Node组件
.kubelet
kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。
.kube-proxy
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。
.docker或rocket
容器引擎,运行容器。
二、K8S监控与日志管理
Metrics Server是一个集群范围的资源使用情况的数据聚合器。作为一个应用部署在集群中。Metric server从每个节点上KubeletAPI收集指标,通过Kubernetes聚合器注册在Master APIServer中。为集群提供Node、Pods资源利用率指标
Metrics-Server工作流程图
Metrics-Server部署
#管理kubernetes组件日志 systemd守护进程管理的组件:
journalctl -u kubelet
Pod部署的组件:
kubectl logs kube-proxy-btz4p -n kube-system
系统日志:
/var/log/messages
#查看kubernetes容器标准输出日志
[root@k8s-master ~]# kubectl logs nginx-6799fc88d8-r4vrh
[root@k8s-master ~]# kubectl logs -f nginx-6799fc88d8-r4vrh
[root@k8s-master ~]# kubectl logs -f nginx-6799fc88d8-r4vrh -c nginx
标准输出在宿主机的路径:
[root@k8s-master ~]# cd /var/lib/docker/containers[root@k8s-master containers]# ll#收集kubernetes日志的方法
针对标准输出:以DaemonSet方式在每个Node上部署一个日志收集程序,采集/var/lib/docker/containers/ 目录下的容器日志
针对容器中日志文件:在pod中增加一个容器运行日志采集器,使用emtyDir共享日志目录让日志采集器读取到日志文件
三、K8S管理应用程序生命周期(Deployment)
#kubernetes部署应用程序流程
#Deployments的主要功能
• 管理Pod和ReplicaSet
• 具有上线部署、副本设定、滚动升级、回滚等功能
---> 部署的过程:(命令行部署方式)
格式:kubectl edit <pod的名称>
---> 部署的过程:(Yaml文件部署方式)
YAML语法格式:
• 缩进表示层级关系• 不支持制表符“tab”缩进,使用空格缩进
• 通常开头缩进2 个空格• 字符后缩进1 个空格,如冒号、逗号等• “---” 表示YAML格式,一个文件的开始• “#”注释
一个deployment+service共同部署的Yaml文件
---> Scaling(伸缩)应用程序
修改了 Deployment 的 replicas 为 4 后,Kubernetes 又为该 Deployment 创建了 3 新的 Pod,这 4 个 Pod 有相同的标签。因此Service A通过标签选择器与新的 Pod建立了对应关系,将访问流量通过负载均衡在 4 个 Pod 之间进行转发。
通过修改部署中的replicas(副本数)来完成扩展
[root@k8s-master ~]# kubectl edit deployment web5
---> 滚动更新(多 Deployment 动态更新)[root@k8s-master ~]# kubectl edit deployment web5
在yaml文件中修改:image: nginx:1.8 使用新的镜像替换原来版本nginx镜像
---> 回滚操作Deployment的详细过程:
有时,你可能想要回滚 Deployment;例如,当 Deployment 不稳定时(例如进入反复崩溃状态)。 默认情况下,Deployment 的所有上线记录都保留在系统中,以便可以随时回滚 (你可以通过修改修订历史记录限制来更改这一约束)。
修改了这里:
升级错误出现这样:
[root@k8s-master ~]# kubectl rollout status deployment/nginx-deployment
输出类似于:
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
[root@k8s-master ~]# kubectl get pods
[root@k8s-master ~]# kubectl describe deployment
输出类似于:
2.使用 --to-revision 来回滚到特定修订版本
3.检查回滚是否成功以及 Deployment 是否正在运行:
[root@k8s-master ~]# kubectl get deployment nginx-deployment
输出类似于:NAME READY UP-TO-DATE AVAILABLE AGEnginx-deployment 3/3 3 3 7h49m 4.获取 Deployment 描述信息:
回滚操作命令格式:(回滚是重新部署某一次部署时的状态,即当时版本所有配置)
kubectl rollout history deployment/web # 查看历史发布版本
kubectl rollout undo deployment/web # 回滚上一个版本
kubectl rollout undo deployment/web --to-revision=2 # 回滚历史指定版本
最后,项目下线:
kubectl delete deploy/web
kubectl delete svc/web
#ReplicaSet控制器的用途
ReplicaSet :确保任何时间都有指定数量的 Pod 副本在运行。 然而,Deployment 是一个更高级的概念,它管理 ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能。 因此,我们建议使用 Deployment 而不是直接使用 ReplicaSet,除非 你需要自定义更新业务流程或根本不需要更新。
新建一个ReplicaSet:
四、K8S管理应用程序生命周期(POD)
# Pods
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。Pod (就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。
除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器。 你也可以在集群中支持临时性容器 的情况下,为调试的目的注入临时性容器。
Pod特点:
Pod主要用法:
运行多个容器:
资源共享实现机制:
将业务容器的网络加入到“负责网络容器”实现网络共享。共享存储:容器通过数据卷共享数据
#实现网络资源共享机制
[root@k8s-master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-net-test 2/2 Running 0 13m
4.通过命令进入POD中的容器
[root@k8s-master ~]# kubectl exec -it pod-net-test -c test -- sh
/ # ip addr : eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1440 qdisc noqueue link/ether 12:76:2e:fb:9f:86 brd ff:ff:ff:ff:ff:ff inet 10.244.169.153/32 scope global eth0 [root@k8s-master ~]# kubectl exec -it pod-net-test -c web -- sh / # netstat -antp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN - tcp 0 0 :::80 :::* LISTEN - #监听80端口
/ # wget 127.0.0.1:80 Connecting to 127.0.0.1:80 (127.0.0.1:80)
5. 从新进入POD中的web容器中
6.再进入POD中的busybox容器中查看
这就是k8s的网络资源模式:和docker container 一样,启动了infra Container容器 ,/pause:3.4.1容器就是这个基础容器 #实现数据卷的共享机制
1.先创建一个pod 的yaml文件
2.根据yaml文件部署POD
3.查看POD的运行状况
[root@k8s-master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-volume-test 2/2 Running 0 4m39s
4 . 验证文件的共享
# POD的管理命令
# POD的重启策略,健康检查
重启策略(restartPolicy):• Always:当容器终止退出后,总是重启容器,默认策略。• OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。• Never:当容器终止退出,从不重启容器。
健康检查有以下两种类型:• livenessProbe(存活检查):如果检查失败,将杀死容器,根据Pod 的restartPolicy来操作。• readinessProbe(就绪检查):如果检查失败,Kubernetes会把Pod从service endpoints中剔除。
建立一个有健康检查的pod
---> POD健康检查的演示:
1、通过create的方式导出一个deployment的yaml文件
2、编辑yaml文件
存活检查:
3、apply一个deployment的yaml文件
4、观察deployment的启动情况
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGEpod-check-67fd5d95b8-24prt 1/1 Running 0 17hpod-check-67fd5d95b8-rmjj5 1/1 Running 0 17hpod-check-67fd5d95b8-xbttq 1/1 Running 0 17h
5、进行存活检查的试验,通过命令进入到容器中
[root@k8s-master ~]# kubectl exec -it pod-check-67fd5d95b8-24prt -- bashroot@pod-check-67fd5d95b8-24prt:/#
---> POD环境变量的演示:
1、编辑一个环境变量演示的POD
2、观察pod的运行情况
[root@k8s-master ~]# kubectl get podNAME READY STATUS RESTARTS AGEpod-env 1/1 Running 0 51s
3、进入容器查看环境变量:
[root@k8s-master ~]# kubectl exec -it pod-env sh/ # echo $ABC123456/ # echo $MY_POD_NAMESPACE/ # echo $MY_POD_IP10.244.169.139
# POD对象:Init Container
Init Container:顾名思义,用于初始化工作,执行完就结束,可以理解为一次性任务。 • 支持大部分应用容器配置,但不支持健康检查 • 优先应用容器执行应用场景: • 环境检查:例如确保应用容器依赖的服务启动后再启动应用容器 • 初始化配置:例如给应用容器准备配置文件
---> 示例:部署一个web网站,网站程序没有打到镜像中,而是希望从代码仓库中动态拉取放到应用容器中。
1、编辑一个yaml文件
2、查看init初始化容器的运行效果
[root@k8s-master ~]# kubectl get podsNAME READY STATUS RESTARTS AGEinit-demo 0/1 Init:Error 0 6s
3、查看init初始化容器的运行情况
4、进入第二个容器查看下载到共享文件夹的文件
[root@k8s-master ~]# kubectl get podsNAME READY STATUS RESTARTS AGEinit-demo 1/1 Running 0 5m33s
# POD中容器类型
Pod中会有这几种类型的容器: • Infrastructure Container:基础容器,维护整个Pod网络空间 • InitContainers:初始化容器, 先于业务容器开始执行 • Containers:业务容器,并行启动
# 静态POD
staticPodPath: /etc/kubernetes/manifests (注:将部署的pod yaml放到该目录会由kubelet自动创建。)
五、K8S的Pod调度
# 创建一个Pod的工作流程
Kubernetes基于list-watch机制的控制器架构,实现组件间交互的解耦。其他组件监控自己负责的资源,当这些资源发生变化时,kube-apiserver会通知这些组件,这个过程类似于发布与订阅。
容器资源限制:limits(容器里应用程序使用的最大资源上限)
容器使用的最小资源需求,作为容器调度时资源分配的依据:requests
(请求值,预留值,不是实际使用值,用于资源分配的参考值。)
#实例:pod资源调度
1、编辑yaml文件
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
2、部署实例
3、通过kubectl describe 查看pod运行的情况,观察pod资源调度的详细情况
[root@master ~]# kubectl describe pod web 查看pod的运行详细情况。
4、通过查看node1上运行的情况,了解pod资源调用情况,该pod是运行在node1上的,然后通过命令可以查看node1上的
所有pod运行资源的调度情况;
[root@master ~]# kubectl describe node node1
(CPU单位:可以写m也可以写浮点数,例如0.5=500m,1=1000m)
(K8s会根据Request的值去查找有足够资源的Node来调度此Pod)
(requests 一般良性参考值小于limits的20%---30%)
(节点上的limits总和不能超宿主机实际物理配置的20%)
(当请求的资源值大于节点的资源情况,pod就会处于pendding状态,无法调度)
#通过命令可以查看node节点上的资源情况
[root@master ~]# kubectl describe node |grep cpu
#nodeSelector
nodeSelector:用于将Pod调度到匹配Label的Node上,如果没有匹配的标签会调度失败。作用: •约束Pod到特定的节点运行 •完全匹配节点标签应用场景: •专用节点:根据业务线将Node分组管理 •配备特殊硬件:部分Node配有SSD硬盘、GPU
示例:确保Pod分配到具有SSD硬盘的节点上
1、编辑一个带ssd标签的yaml文件
2、查看pod的部署情况,因为node上没有disktype: “ssd”的标签,所以是pending状态
3、给node1节点添加标签
[root@master ~]# kubectl label nodes node2 disktype=ssd
验证节点标签:
[root@master ~]# kubectl get nodes --show-labels
4、验证pod的部署情况
[root@master ~]# kubectl get pods -o wide
#nodeAffinity
nodeAffinity:节点亲和类似于nodeSelector,可以根据节点上的标签来约束Pod可以调度到哪些节点。相比nodeSelector: •匹配有更多的逻辑组合,不只是字符串的完全相等,支持的操作符有:In、NotIn、Exists、DoesNotExist、Gt、Lt •调度分为软策略和硬策略,而不是硬性要求 •硬(required):必须满足 •软(preferred):尝试满足,但不保证
#Taint(污点)Tolerations(污点容忍)
Taints:避免Pod调度到特定Node上Tolerations:允许Pod调度到持有Taints的Node上应用场景: •专用节点:根据业务线将Node分组管理,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配 •配备特殊硬件:部分Node配有SSD硬盘、GPU,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配 •基于Taint的驱逐
示例:Tain't污点
1、查看节点上的Taint(污点)的情况
[root@master ~]# kubectl describe node master|grep Taint
[root@master ~]# kubectl describe node |grep Taint
2、给节点添加污点(Tiant)
[root@master ~]# kubectl taint node node1 disktype=ssd:NoSchedule
[root@master ~]# kubectl describe node |grep Taint
3、编辑一个可以被node1节点上调度的yaml文件
4、调度部署一个带有节点选择的pod
不被节点所调度,原因是:
5、添加污点容忍在调度
Tolerations(污点容忍)的操作方法
tolerations:
- key: "disktype" #污点的键值
operator: "Equal" #等于
value: "ssy" #污点的键值对应
effect: "NoSchedule"
6、删除节点的污点
[root@master ~]# kubectl taint node node1 disktype=ssd:NoSchedule- #后面跟一个减号,中间没有空格
Taint污点的一下操作方法
给节点添加污点 格式:kubectl taint node [node] key=value:[effect] 例如:kubectl taint node k8s-node1 gpu=yes:NoSchedule 验证:kubectl describe node k8s-node1 |grep Taint其中[effect] 可取值: •NoSchedule :一定不能被调度 •PreferNoSchedule:尽量不要调度,非必须配置容忍 •NoExecute:不仅不会调度,还会驱逐Node上已有的Pod
示例:Tain't污 点,给一个节点添加3个污点
Pod,它有两个容忍度:-------------------->
这种情况,上述pod不会被分配到该节点,因为其没有容忍度和第三个污点相匹配。
给一个节点添加了一个 effect 值为 NoExecute 的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐, 任何可以忍受这个污点的 Pod 都不会被驱逐。
但是,如果 Pod 存在一个 effect 值为 NoExecute 的容忍度指定了可选属性 tolerationSeconds 的值,则表示在给节点添加了上述污点之后, Pod 还能继续在节点上运行的时间。如:
#nodeName
nodeName:指定节点名称,用于将Pod调度到指定的Node上,不经过调度器 即使是node1节点上有污点的,都能顺利调度。
应用场景:主要是在开发中使用,直接调度到节点上运行容器。
1、编辑有nodeName的yaml文件
2、部署及查看是否运行到节点node1上
[root@master ~]# kubectl get pods -o wide
直接就分配到node1这个节点上。
#DaemonSet
DaemonSet功能:
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
应用场景:网络插件、监控Agent、日志Agent
如:calico组件,proxy组件都是每个节点上运行的。
示例:DaemonSet的使用
1、部署一个日志采集程序
2、部署后查看情况,但是只运行了两个node节点
[root@master ~]# kubectl get pods -n kube-system
3、查原因,原来是master上有污点,说明DaemonSet的调度也受污点的影响。
4、删除master上的污点
5、从新部署DaemonSet,再查看部署情况,master上的污点一经去除,DaemonSet就自动部署了
[root@master ~]# kubectl get pods -n kube-system[root@master ~]# kubectl get pods -o wide -n kube-system |grep test-daemonset
六、K8S网络(Service与Ingress篇)
@Service的学习部分
使用 Kubernetes,你无需修改应用程序即可使用不熟悉的服务发现机制。
Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡。
Service: 引入主要是解决Pod的动态变化,提供统一访问入口: • 防止Pod失联,准备找到提供同一个服务的Pod(服务发现) • 定义一组Pod的访问策略(负载均衡)
• Service通过标签关联一组Pod • Service使用iptables或者ipvs为一组Pod提供负载均衡能力
###### 通过kubectl创建svc的方法 ############
示例:通现有的pod创建一个与之关联的svc
1、查看kubectl中现有的pod,并创建一个与之关联的svc
[root@master ~]# kubectl get pods
[root@master ~]# kubectl expose pod pod-selector --port=80 --type=NodePort --name=f1 [root@master ~]# kubectl get svc
2、在浏览器上进行测试
3、查看该svc的ep情况
[root@master ~]# kubectl get ep
svc的yaml文件:也可以通过YAML文件进行部署。
Service的多端口定义:对于某些服务,需要公开多个端口,Service也需要配置多个端口定义,通过端口名称区分。
Service三种常用类型:
ClusterIP:默认,分配一个稳定的IP地址,即VIP,只能在集群内部访问。
NodePort:在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。这时就需要前面加一个公网负载均衡器为项目提供统一访问入口了。也会在每台Node上监听端口接收用户流量,在实际情况下,对用户暴露的只会有一个IP和端口,那这么多台Node该使用哪台让用户访问呢?访问地址:<任意NodeIP>:<NodePort>端口范围:30000-32767
LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。
Service代理模式:
* (1) 第一种代理模式:IPtabels
1、查看k8s集群内的svc
[root@master ~]# kubectl get svc
2、查看test-web5的iptables转发情况
[root@master ~]# iptables-save|grep test-web5
3、查看KUBE-SVC-R4AN3NJI2MCEMEEW的iptables转发情况
(--mode random --probability 0.33333333349 )这个就是实现负载均衡的的权重和转发概率。最后一条记录:
[root@master ~]# iptables-save|grep KUBE-SVC-R4AN3NJI2MCEMEEW
5、根据每条转发后面的链进行查看转发到那个pod上
[root@master ~]# iptables-save |grep KUBE-SEP-QTID6BIIMABWQ25O
从IP地址可以看出,iptables转发到第一个POD上的服务上,
[root@master ~]# iptables-save |grep KUBE-SEP-RKGA2BK4C2R5IJDB
[root@master ~]# kubectl get ep
让他查看第2个链就知道转发到第2个pod上的IP地址。
* (2) 第二种代理模式:IPVS
1、查看kube-proxy的转发规则
[root@master ~]# kubectl logs kube-proxy-zlrj4 -n kube-system|more
2、修改kube-proxy的转发规则为:IPVS
[root@master ~]# kubectl edit configmap kube-proxy -n kube-system打开kube-proxy的配置文件进行修改,在vim中查询:/mode:
修改:mode: "ipvs"
删除kube-proxy的所有pod让kube-proxy重建:
[root@master ~]# for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-proxy -o name); \> do kubectl delete --namespace=kube-system $p; done
3、在节点上安装IPVS的工具:ipvsadmin
[root@master ~]# yum install -y ipvsadm
4、通过命令:ipvsadm -L -n查看IPVS的转发规则
[root@node1 ~]# ipvsadm -L -n
5、查看IPVS 的转发的情况
* (3) IPtables和IPVS比较
Iptables: • 灵活,功能强大 • 规则遍历匹配和更新,呈线性时延IPVS: • 工作在内核态,有更好的性能 • 调度算法丰富:rr,wrr,lc,wlc,ip hash...
* (4) Service DNS名称访问
CoreDNS:是一个DNS服务器,Kubernetes默认采用,以Pod部署在集群中,CoreDNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析。
--------------------- 通过命令的演示,DNS的解析情况--------------------------------------------
[root@master ~] # kubectl run dns-t --image=busybox:1.28.4 -- sleep 24h
[root@master ~] # kubectl get pods
[root@master ~] # kubectl exec -it dns-t -- sh/ # ---->这个是busybox运行的命令提示符:
[root@master ~] # kubectl get svc
/ # nslookup test-web5
===================================================================================
@Ingress的学习部分
Ingress 配置为服务提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及提供基于名称的虚拟主机等能力。
NodePort存在的不足:
Ingress:
--->Ingress控制器的创建
1、Ingress Controller的namespace名称空间的创建
2、Ingress Controller的configMap的创建
3、Ingress Controller的ServiceAccount的创建
4、Ingress Controller的rbac的创建
5、Ingress Controller的APP的创建
6、部署Ingress Controller
[root@master ~]# kubectl get pods -n ingress-nginx
7、创建Ingress规则,使用Ingress(规范化,标准化)
8、部署Ingress的规则
[root@master ~]# kubectl get pods -n ingress-nginx -o wide
[root@master ~]# ss -antp |grep 80
[root@master ~]# vim /etc/hosts
---> Ingress规则配置:HTTPS
1、安装cfssl进行认证
[root@master ~]# mv cfssl* /usr/bin/
[root@master ~]# mkdir ssl[root@master ~]# cd ssl
2、编辑cfssl脚本文件进行证书创建
3、安装cfssl进行认证
4、将证书文件保存到Secret中
[root@master ssl]# kubectl get secret
5、编辑Ingress的yaml文件
6、部署Ingress的yaml文件
[root@master ssl]# kubectl get ingress
7、验证
---> Ingress Controller怎样工作
Ingress Controller:通过与Kubernetes API 交互,动态的去感知集群中Ingress 规则变化,然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段Nginx 配置,应用到管理的Nginx服务,然后热加载生效。以此来达到Nginx负载均衡器配置及动态更新的问题。
数据包流程:客户端->Ingress Controller(nginx)-> 分布在各节点Pod
[root@master ~]# kubectl get pods -n ingress-nginx
[root@master ~]# kubectl exec -it nginx-ingress-controller-9h9cj -n ingress-nginx -- bashbash-5.0$ ps -ef
维护了两个进程:
nginx: 实现pod的负载均衡
nginx-ingress-controller:访问k8s api 获取创建的Ingress,生成对应的nginx配置文件,并且生效
七、K8S存储(PV、PVC、Secret、ConfigMap篇)
背 景
卷 的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放 的内容。
Kubernetes 卷(Volume) 抽象概念能够解决这两个问题: 问题1:当容器崩溃时,kubelet会重建容器,容器内文件会丢失 问题2:一个Pod中运行多个容器并需要共享文件
Kubernetes 常用的数据卷(Volume):
-----------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------
(一)、emptyDir 临时数据卷
emptyDir卷:是一个临时存储卷,与Pod生命周期绑定一起,如果Pod删除了卷也会被删除。应用场景:Pod中容器之间数据共享
1、部署一个emptyDir临时卷的pod
[root@master ~]# kubectl exec -it my-pod -c w1 -- bash [root@my-pod data]# cat hello [root@master ~]# kubectl exec -it my-pod -c r1 -- bash2、查看emptyDir临时卷在宿主机的目录位置
[root@master ~]# kubectl get pods -o wide |grep my-pod
[root@node1 ~]# cd /var/lib/kubelet/pods
[root@node1 ~]# docker ps |grep my-pod
[root@node1 35b609a9-291b-4fd3-8f40-43c88a44e3db]# ls
emptyDir在宿主机上的工作目录:
(二)、hostPath 节点数据卷
hostPath卷:挂载Node文件系统(Pod所在节点)上文件或者目录到Pod中的容器。应用场景:Pod中容器需要访问宿主机文件
1、用yaml文件部署一个hostPath卷的pod
2、查看运行情况(可以用pod来收集宿主上的信息)通过命令查看my-hostpath容器运行在那个节点上:
[root@master ~]# kubectl get pod -o wide |grep my-hostpath
进到宿主机节点上node1上的/tmp目录
(三)、NFS 网络数据卷
NFS卷:提供对NFS挂载支持,可以自动将NFS共享路径,挂载到Pod中NFS:是一个主流的文件共享服务器。
1、在node2上安装NFS服务端,其他节点安装NFS客户端
[root@node2 ~]# yum -y install nfs-utils
[root@node2 ~]# vim /etc/exports #配置nfs的共享目录/yfs/k8s *(rw,no_root_squash)
[root@node2 ~]# mkdir -p /yfs/k8s
[root@node2 ~]# systemctl start nfs[root@node2 ~]# systemctl enable nfs
在node1上测试挂载情况:
[root@node1 ~]# mount -t nfs 192.168.178.12:/yfs/k8s /mnt
[root@node1 ~]# df -Th
验证挂载的目录具备读写权限:
在客户端的写文件:----->
在NFS服务器端的文件:---->
在NFS客户端卸载刚才挂载的 /mnt:---->
[root@node1 ~]# umount /mnt/
2、示例:将Nginx网站程序根目录持久化到NFS存储,为多个Pod提供网站程序文件
编辑Deployment的yaml文件
4、进到容器看共享目录的情况
[root@master ~]# kubectl get svc
[root@master ~]# kubectl get ingress
在浏览器查看:
(四)、持久数据卷 ,让存储和应用的职责逻辑分离,静态的PV
PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节
Pod申请PVC作为卷来使用,Kubernetes通过PVC查找绑定的PV,并Mount给Pod。
1、编辑pv的yaml文件,创建一个pv
2、编辑pvc的deployment的yaml文件,创建一个带pvc存储
进到pod中来:--->
[root@master ~]# kubectl get pods
[root@master ~]# kubectl exec -it pvc-web7-8677566cbd-6j58l -- bash
在POD中显示挂载的情况了:--->
root@pvc-web7-8677566cbd-6j58l:/# df -Th
-------------------------------------PV 生命周期-----------------------------------
AccessModes(访问模式):AccessModes 是用来对PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
RECLAIM POLICY(回收策略):目前PV 支持的策略有三种:
STATUS(状态):一个PV 的生命周期中,可能会处于4中不同的阶段:
-------------------------------------
一个pv只能由一个pvc使用,不能动态的弹性的分配给其他项目。pv只要和pvc一经bund(绑定)就无法分配个其他pod的pvc使用了。
现在PV使用方式称为静态供给,需要K8s运维工程师提前创建一堆PV,供开发者使用。
(五)、PV 动态供给(StorageClass)
K8s开始支持PV动态供给,使用StorageClass对象实现。不需要运维人员维护pv的创建。
K8s默认不支持NFS动态供给,需要单独部署社区开发的插件。
部署支持NFS的插件:
1、解压文件
2、建NFS服务器端
[root@node2 ~]# mkdir -p /pvc
[root@node2 ~]# vim /etc/exports
[root@node2 ~]# systemctl restart nfs #修改完/etc/exports后重新启动NFS服务器
4、查看存储类的yaml文件和创建给給类
[root@master nfs-external-provisioner]# kubectl apply -f . #后面带一个点,包含文件夹下的都要创建[root@master nfs-external-provisioner]# kubectl get pods
5、创建使用动态pv的应用Deployment和Service
[root@master ~]# kubectl get svc,pv,pvc
验证:
[root@node2 ~]# cd /pvc[root@node2 pvc]# lltotal 0drwxrwxrwx 2 root root 6 Sep 29 15:14 default-yuan-sc-pvc-87a3440b-9fd2-47a4-89c0-0e92912851cc
(六)、有状态应用部署:StatefulSet 控制器
无状态: Deployment控制器设计原则:管理的所有Pod一模一样,提供同一个服务,也不考虑在哪台Node运行,可随意扩容和缩容。这种应用称为“无状态”,例如Web服务有状态: 在实际的场景中,这并不能满足所有应用,尤其是分布式应用,会部署多个实例,这些实例之间往往有依赖关系,例如主从关系、主备关系,这种应用称为“有状态”,例如MySQL主从、Etcd集群
StatefulSet 控制器 ,用来管理有状态应用的工作负载 API 对象
StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值:
应用场景:分布式应用、数据库集群
稳定的存储StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当StatefulSet使用VolumeClaimTemplate创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC。
StatefulSet与Deployment区别:有身份的! 身份三要素: •域名 •主机名 •存储(PVC)
##实例:部署一个StatefulSet的实例
[root@master ~]# kubectl get svc
[root@master ~]# kubectl get pvc
[root@node2 ~]# cd /pvc[root@node2 pvc]# ll
显示出statefulSet的pod的主机名:
[root@master ~]# kubectl exec sts-web8-0 -- hostnamests-web8-0
演示独立存储:
在NFS服务器上在sts-web8-0的存储上建一个文件:
(七)、应用程序数据存储ConfigMap,Secret
ConfigMap:存储配置文件Secret:存储敏感数据
ConfigMap 动机是:使用 ConfigMap 来将你的配置数据和应用程序代码分开。
创建ConfigMap后,数据实际会存储在K8s中Etcd,然后通过创建Pod时引用该数据。应用场景:应用程序配置 Pod使用configmap数据有两种方式:
实例:创建一个configMap资源:
1、编辑一个confiMap的yaml文件:
2、编辑一个含有configMap调用的yaml应用:
[root@master ~]# kubectl get pods
3、查看configMap的创建情况:
[root@master ~]# kubectl get configmap
[root@master ~]# kubectl exec -it configmap-demo-pod -- bashroot@configmap-demo-pod:/# env |grep y
Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将机密数据写入非易失性存储。
Secret 类似于 ConfigMap 但专门用于保存机密数据。
Pod 可以用三种方式之一来使用 Secret:
kubectl create secret 支持三种数据类型:
[root@master ~]# kubectl create crerte --help #通过这个命令查看Secret支持的这三种类型
Available Commands: docker-registry Create a secret for use with a Docker registry generic Create a secret from a local file, directory or literal value tls Create a TLS secret
实例:创建一个Secret的POD资源:
1、编辑一个Secret的POD应用yaml文件:
[root@master ~]# echo -n 'yuanye' |base64eXVhbnll[root@master ~]# echo -n 'anshunyuan'|base64YW5zaHVueXVhbg==
2、编辑POD应用yaml文件:
3、查看Secret的情况:
[root@master ~]# kubectl get secret
4、进到Secret的容器中验证:
[root@master ~]# kubectl exec -it secret-demo-pod -- bashroot@secret-demo-pod:/# env |grep USERUSER=yuanye
root@secret-demo-pod:~# env |grep PASSPASS=anshunyuan
root@secret-demo-pod:/# cd configroot@secret-demo-pod:/config# cat my-usernameyuanye
八、K8S安全
基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对 计算机或网络资源的访问的方法。
要启用 RBAC,在启动 API 服务器 时将 --authorization-mode 参数设置为一个逗号分隔的列表并确保其中包含 RBAC。
K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。 1. Authentication(鉴权) 2. Authorization(授权) 3. Admission Control(准入控制)•客户端要想访问K8s集群API Server,一般需要证书、Token或者用户名+密码;如果Pod访问,需要ServiceAccount
(一)K8s Apiserver提供三种客户端身份认证: • HTTPS 证书认证:基于CA证书签名的数字证书认证(kubeconfig) • HTTP Token认证:通过一个Token来识别用户(serviceaccount) • HTTP Base认证:用户名+密码的方式认证(1.19版本弃用)
(二)RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。RBAC根据API请求属性,决定允许还是拒绝。比较常见的授权维度: • user:用户名 • group:用户分组 • 资源,例如pod、deployment • 资源操作方法:get,list,create,update,patch,watch,delete • 命名空间 • API组
(三)RBAC(Role-Based Access Control,基于角色的访问控制),是K8s默认授权策略,并且是动态配置策略(修改即时生效)。 主体(subject) • User:用户 • Group:用户组 • ServiceAccount:服务账号 角 色 • Role:授权特定命名空间的访问权限 • ClusterRole:授权所有命名空间的访问权限 角色绑定 • RoleBinding:将角色绑定到主体(即subject) • ClusterRoleBinding:将集群角色绑定到主体
(四)RBAC API声明的对象
RBAC API 声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding。
(五)RBAC API的根证书 HTTPS证书认证:
[root@master ~]# ls .kube/ #存放k8s的根证书的cache config(六)RBAC API的根证书 HTTP Token认证:
通过Token来识别用户,主要node加入时加入集群时的Token,
(七)通过kubectl exec 查看kube-apiserver中的准入控制:默认启用的准入控制
[root@master ~]# kubectl exec kube-apiserver-master -n kube-system -- kube-apiserver -h |grep enable-admission-plugins
案例:为指定用户授权访问不同命名空间权限 ,为了安全性,先不能给他太大权限,因此先给他授权访问default命名空间Pod读取权限。
实施步骤:
1. 用K8S CA签发客户端证书
[root@master rbac]# ll
3. 创建RBAC权限策略
修改rbac的配置yaml文件:
yuanye用户就能访问deployment和service了
1、# 创建集群角色
2 # 创建服务账号
[root@master ~]# kubectl create ns app-team1namespace/app-team1 created
[root@master ~]# kubectl create serviceaccount cicd-token -n app-team1serviceaccount/cicd-token created
3 # 将服务账号绑定角色
4 # 测试服务账号权限
[root@master ~]# kubectl --as=system:serviceaccount:app-team1:cicd-token \> get pods -n app-team1Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:app-team1:cicd-token" cannot list resource "pods" in API group "" in the namespace "app-team1"
5 # 通过yaml创建出一个服务账号sa
[root@master acc]# alias k9=kubectl --as=system:serviceaccount:app-team2:yuan-token #用别名的方式把长命令格式[root@master acc]# k9 get pods -n app-team2 #这样就简化了命令行格式No resources found in app-team2 namespace.
ingress: #ingress的编写方式: - from: - ipBlock: cidr: 172.17.0.0/16 except: - 172.17.1.0/24 - namespaceSelector: matchLabels: project: myproject - podselector: matchLabels: role: frontend
Egress的编写:
Egress:这个Pod组可以访问外部的IP段和端口。
案例1:拒绝其他命名空间Pod访问
需求:test命名空间下所有pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问test命名空间Pod。
1、先创建一个test的命名空间,在其命名空间中创建两个应用:
[root@master ~]# kubectl create ns testnamespace/test created[root@master ~]# kubectl run web --image=nginx -n testpod/web created[root@master ~]# kubectl run busybox1 --image=busybox -n test -- sleep 12hpod/busybox1 created
[root@master ~]# kubectl get pods -n test
2、在default中创建busybox2的应用:
[root@master ~]# kubectl run busybox2 --image=busybox -- sleep 12hpod/busybox2 created[root@master ~]# kubectl get pods
3、测试pod的访问,不加网络Network Policy测试:
[root@master ~]# kubectl get pods -n test -o wide
[root@master ~]# kubectl exec -it busybox1 -n test -- sh #这个是在test命名空间中的访问/ # wget 10.244.166.157
[root@master ~]# kubectl exec -it busybox2 -- sh #这个是在default命名空间中的访问/ # wget 10.244.166.157
4、编辑网络Network Policy的yaml文件:
查看networkpolicy的情况:
[root@master ~]# kubectl get networkpolicy -n test
5、应用网络Network Policy后的测试:
[root@master ~]# kubectl get pods -n test -o wide
[root@master ~]# kubectl exec -it busybox1 -n test -- sh #这个是test命名空间内的访问,是可以的/ # wget 10.244.166.157
[root@master ~]# kubectl exec -it busybox2 -- sh #default的命名空间的pod就不能访问test空间中的pod/ # ls
6、delete网络Network Policy:
[root@master ~]# kubectl get networkpolicy -n test
案例2:同一个命名空间下应用之间限制访问
需求:将test命名空间携带run=web标签的Pod隔离,只允许test命名空间携带run=client1标签的Pod访问80端口。1、拉取lanels为run=client1的应用:
[root@master ~]# kubectl get pods -n test --show-labels
[root@master ~]# kubectl run client1 --image=busybox -n test -- sleep 12hpod/client1 created[root@master ~]# kubectl get pods -n test --show-labels
2、编辑网络策略的yaml文件及apply应用:
3、测试:这个是run=client1
[root@master ~]# kubectl get pods -n test --show-labels
[root@master ~]# kubectl exec -it client1 -n test -- sh / # exit[root@master ~]# kubectl get pods -n test -o wide
[root@master ~]# kubectl exec -it client1 -n test -- sh/ # wget 10.244.166.157
4、测试:这个是run=busybox1 ,这个就不能访问了
[root@master ~]# kubectl exec -it busybox1 -n test -- sh #这个是同一个命名test空间也不能访问,因为标签不匹配/ # wget 10.244.166.157
[root@master ~]# kubectl exec -it busybox2 -- sh #不同的命名空间,也不能访问,因为标签不匹配 / # wget 10.244.166.157
案例3:只允许指定命名空间中的应用访问
需求:只允许dev命名空间中的Pod访问test命名空间中的pod 80端口,命名空间打标签:kubectl label namespace dev name=dev
1、先建立DEV的命名空间,并在该空间拉起一个busybox的应用[root@master ~]# kubectl create ns devnamespace/dev created[root@master ~]# kubectl run client --image=busybox -n dev -- sleep 12hpod/client created[root@master ~]# kubectl get pods -n dev
2、在dev中的pod的client可以访问test中的pod的80端口,而其他命名空间中pod的busybox就不能访问
3、编辑networkpolicy的yaml文件并应用
4、基于命名空间的标签:
[root@master ~]# kubectl get ns --show-labels
[root@master ~]# kubectl label namespace dev name=dev #给dev打一个标签5、测试[root@master ~]# kubectl exec -it client -n dev -- sh #这个是基于Dev的命名空间,是可以访问的/ # wget 10.244.166.157
[root@master ~]# kubectl exec -it busybox2 -- sh #这个是default命名空间的,不能访问,因为标签不匹配/ # wget 10.244.166.157
(网络策略需要网络组件支持的,支持网络组件的实现:calico。flannel不支持网络策略。)
九、K8S集群维护
---->Etcd数据库备份与恢复(kubeadm部署方式)
1、Etcd数据库备份:
2、删除当前的pod在恢复etcd:
[root@master ~]# kubectl get pods
3、暂停k8s服务:(只要把manifests目录移动就能暂停kubernetes的服务)