内容来源bilibili教学:k8s教程由浅入深-尚硅谷
前言
1、k8s组件介绍
1.1 Pod/Pod控制器
1.2 Name/Namespace
1.3 Label/Label选择器
1.4 Service/Ingress
1.5 核心组件
1.5.1 apiserver
1.5.2 controller-manager
1.5.3 scheduler
1.5.4 kubeclet
1.5.5 kube-proxy
2、k8s逻辑架构和minikube
2.1 逻辑结构
2.2Minikube
若是预研等足够使用
3、YAML
3.1快速生成yaml文件(根据实际修改即可)
- 使用kubectl create命令生成yaml文件
kubectl create deployment demo --image=nginx -o yaml --dry-run > my1.yaml
kubectl get deploy
kubectl get deploy nginx -o=yaml --export > my2.yaml
4、Pod
4.1 Pod的基本概念
- 最小部署单元
- 包含多个容器(一组容器的集合)
- 一个pod中容器共享网络命名空间
- pod是短暂的
4.2 Pod存在的意义
- 创建容器使用docker,一个docker对应一个容器,一个容器运行一个运用程序(也可运行多个,但不建议)
- Pod是多进程设计,运行多个应用程序
- Pod存在为了亲密性应用
1] 两个应用之间进行交互 2] 网络之间进行调用(可通过127.0.0.1或socket就可以进行调用) 3] 两个应用需要频繁调用
4.3 Pod实现机制
1) 共享网络: 通过pause容器,把其他业务容器加入到pause容器里,让所有业务容器在同一名称空间中,可以实现网络共享。 通过pod创建容器,会先创建pause容器,Pause容器也称为info容器 创建业务容器时,pod会将之加入info容器中,这样操作之后,业务容器就处在同一个namespace中了,在同一个namespace下,实现网络共享 在info中,会独立出 ip,mac, port
2) 共享存储 应用数据卷概念volumn,使用数据卷进行持久化存储 包含两个容器 第一个容器执行命令:循环打印1-100到/data/hello中 第二个容器执行命令:循环读取打印/data/hello中的数据 将两个容器都挂载同一数据卷,yaml文件定义数据卷
4.4 Pod镜像拉取策略
4.5 Pod的资源限制
Request:调度是需要满足的条件 Limits:给到的最大的限制
4.6 Pod的重启策略
4.7 Pod的健康检查
通过touch在文件中做操作,30s后将之删除,在这个过程中不断检查它的状态 Echo $? : 代表上一个命令执行后的退出状态
4.8 Pod的创建过程
- 首先API Server得到创建pod请求,调用基础方法创建pod并将它存储在etcd上
- Schduler实时监控API Server有没有新的pod出现,若发现有新的pod,通过调度算法,将之分配给某一个节点,并将信息写在etcd上
- 每个node节点实时监控API Server有没有分配给自己的pod,若发现则运行docker进行容器创建,并更新pod状态,将信息卸载etcd中
4.9 Pod的调度
影响调用的属性:
4.9.1 pod资源限制对pod调用产生影响
根据request找到足够node节点进行调度
4.9.2节点选择器标签影响pod调度
例如:共有四个节点 1、2节点为开发节点:dev, 3、4几点为生产节点:prod 规定了节点选择器之后,可以选择指定标签节点进行pod调度
前提:为节点取别名(标签)
$ kubectl label node node1 env_role=prod
$ kubectl get nodes node1 --show-labels
4.9.3节点亲和性对pod调度的影响
nodeAffinity 和之前的 nodeSelector基本一样的,根据节点上标签约束来决定pod调度到那些节点 weight:1 即权重为1
4.9.4污点和污点容忍
4.9.4.1 污点
1)基本介绍 modeSelector 和 nnodeAffinity : Pod调度到某些节点上,Pod属性,调度时侯实现 Taint污点:节点不做普通分配调度,这是节点的属性
污点值:
- NoSchedule:一定不被调度
- ProgerNoSchdule:尽量不被调度
- NoExecute:不会调度,并且还会驱逐Node到已有Pod
- 场景
3) 具体演示 Master节点是NoSchedule,是不允许被调度的
kubectl describe node master | grep Taint
Node 没有污点值(node2同)
kubectl describe node node1| grep Taint
不添加污点时做pod分配: 查看pods:
kubectl get pods
创建pod:
kubectl create deployement demo --image=nginx
查看pod详细情况: 可以通过NODE看到pod在节点上的分配情况
kubectl get pods -o wide
创建多个pod副本并进行查看: 发现pod会被随机分配给集群节点
kubectl scale deployment demo --replicas=9
删除pod:
kubectl delete deployment demo
添加污点时对pod进行分配: 为节点添加污点:kubectl taint node [node] key=value:污点三个值
为node1添加污点:
kubectl taint node node1 env_role=yes:NoSchedule
创建pod:
kubectl create deployment demo --image=nginx
创建多个pod:
kubectl scale deployment demo --replicas=9
查看pod分配情况: 新建Pod全被分配到了node2上
kubectl get pods -o wide
删出污点:
kubectl taint node node1 env_role:NoSchedule-
4.9.4.2 污点容忍
对一些节点(哪怕设置了NoSchedule污点的节点),也可能可以被分配pod(软亲和)。
5、controller
5.1 什么是controller
在集群上管理和运行容器对象
5.2 Pod和controller的关系
Pod是通过controller实现应用的运维(弹性收缩,滚动升级等)
Pod和Controller是通过label建立关系的
5.3 Deployment控制器应用场景
- 部署无状态应用
- 管理Pod和ReplicaSet
- 部署,滚动升级等功能
应用场景:web服务,微服务
5.4 yaml文件字段说明
5.5 Deployment控制器部署应用
使用deployment部署应用(yaml) 导出yaml文件:
kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml
使用yaml部署应用:
kubectl apply -f web.yaml
对外发布(暴露端口):
$ kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1 -o yaml > web1.yaml
$ kubectl apply -f web1.yaml
得到端口信息
$ kubectl get pods,svc
5.6 升级回滚
修改yaml: vim web.yaml 两个yaml文件,并将镜像版本调整成nginx:1.14 通过文件名,进行资源配置:
kubectl apply -f web.yaml
应用升级:
kubectl set image deployment web nginx=nginx:1.15
之所以有一个containerCreating,因为应用升级并不是关闭pod进行升级,而是它首先先去下载1.15版本,在这个期间1.14版本还在运行,等到创建好新的pod之后,才把,之前的pod替换掉 多个服务是更为明显:例如
查看部署节点:
kubectl get pods -o wide
在部署的node节点查看doekr images:nginx版本已经变成了1.15 在没有部署的node节点上查看docker images:nginx版本还是1.14
查看升级状态:
kubectl rollout status deployment web
突然,我们觉得1.14版本更好: 查看历史版本:
kubectl rollout history deployment web
还原到上一个版本:
kubectl rollout undo deployment web
回滚到指定版本:
kubectl rollout undo deployment web --to-revision=2
5.7 弹性伸缩
更改副本数量:
kubectl scale deployment web --replicas=5
5.8 部署有状态的应用
5.8.1无状态和有状态
1)无状态:
- 认为pod都是一样的
- 没有顺序要求
- 没有顺序要求
- 随意进行伸缩和扩展
2)有状态
- 上面的因素都需要考虑
- 让每个pod都是独立的,保持pod启动顺序和唯一性
通过唯一的网路标识符进行区分,持久存储 有序,比如mysql(可用主从进行)
5.8.2部署有状态应用
使用的资源清单文件:sts.yaml 1)无头service:ClusterIP:none 查看无头service: kubectl get svc 2)查看三个pod,每个都有唯一名称 kubectl get pod 3) deployment 和 statefulset的区别 根据主机名+按照一定规则生成的域名
5.8.3部署守护进程 daemonSet
https://www.jianshu.com/p/dbb46061d9f4 1)简介 DaemonSet:服务守护进程,它的主要作用是在Kubernetes集群的所有节点中运行我们部署的守护进程,相当于在集群节点上分别部署Pod副本,如果有新节点加入集群,Daemonset会自动的在该节点上运行我们需要部署的Pod副本,相反如果有节点退出集群,Daemonset也会移除掉部署在旧节点的Pod副本。
2)特征
- 这个 Pod 运行在 Kubernetes 集群里的每一个节点(Node)上
- 每个节点上只会运行一个这样的 Pod 实例
- 如果新的节点加入 Kubernetes 集群后,该 Pod 会自动地在新节点上被创建出来
- 而当旧节点被删除后,它上面的 Pod 也相应地会被回收掉
3)常用场景
- 网络插件的 Agent 组件,如(Flannel,Calico)需要运行在每一个节点上,用来处理这个节点上的容器网络;
- 存储插件的 Agent 组件,如(Ceph,Glusterfs)需要运行在每一个节点上,用来在这个节点上挂载F远程存储目录;
- 监控系统的数据收集组件,如(Prometheus Node Exporter,Cadvisor)需要运行在每一个节点上,负责这个节点上的监控信息搜集。
- 监控系统的数据收集组件,如(Prometheus Node Exporter,Cadvisor)需要运行在每一个节点上,负责这个节点上的监控信息搜集。
4)示例 使用的yaml文件:日志采集宿主机/var/log节点下日志
执行yaml文件:kubectl apply -f ds.yaml
进入pod: kubectl exec -it ds-test-b7jcq bash
查看日志:ls /tmp/log
5.8.4 job(一次性任务)和cronjob(定时任务)
1)一次性任务 Yaml文件:job.yaml 创建pod: kubectl create -f job.yaml Completed既代表任务完成
查看圆周率计算结果(这个yaml文件的寓意):kubectl logs pi-t9jd6 删除任务: 方式一:删除pod:kubectl delete Job pi 方式二:删除yaml文件:kubectl delete -f job.yaml 2)定时任务 Yaml文件:cornJob.yaml 执行yaml文件:kubectl apply -f cronjob.yaml 查看容器:
查看执行结果:kubectl logs hello-1633688580-mzlq5
6、service
Service也有一个ip :虚拟IP(VIP)
6.1 service存在的意义
1)防止pod失联(服务发现) 每个pod都有不同的ip地址,当进行新的创建、版本回滚等操作都会改变ip 假比如说,我们有三个前端pod,三个后端pod,前后端pod交互可以通过拿到对应ip来进行实现,但是pod ip是变动的,这就带来了问题。 解决:所有的pod都会在service中进行注册,加入后端pod ip变动了,他会通过service通知前端pod拿取的注册的最新ip去访问,故实现service防止pod失联功能。
2)定义一组Pod的访问策略(负载均衡) Service会定义分配规则,将请求派发给不同的pod,实现负载均衡
6.2 Pod 和 Service 的关系
分局label和selector 标签建立关联的。
6.3 常用Service类型
- ClusterIP:集群内部使用
- NodePort:对外访问应用使用
- LoadBalancer:对外访问应用使用,公有云操作
暴露端口得到基本的yaml文件:kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service1.yaml 默人情况设置如此,仅供集群内使用 Node内网部署应用,外网一般不能访问到(可以找到一台可以进行外网访问的机器,安装nginx,反向代理,手动把可以访问节点添加到nginx里面)
7、Secret 和 configMap
7.1Secret
作用:加密数据存在etcd里面,让Pod容器以挂载Volume方式进行访问 场景:例如凭证
7.1.1创建secret加密数据
Yaml文件:secret.yaml
创建secret: kubectl create -f secret.yaml 查看secret: kubectl get secret
7.1.2 以变量形式挂载到pod容器
Yaml文件:secret-vat.yaml 创建 进入容器:kubectl exec -it mypod bash
查看解密后的用户名密码: echo $SECRET_USERNAME echo $SECRET_PASSWORD
7.1.3 以Volume形式挂载到pod容器
Yaml文件:secret-vol.yaml 创建pod:kubectl apply -f secret-vol.yaml 进入pod: kubectl exec -it mypod bash 进入挂在目录查看账号密码:
7.2ConfigMap
作用:存储不加密数据到etcd,让pod以变量或者volume挂载到容器中 场景:如配置文件
7.2.1 准备configMap
创建配置文件:redis.properties 创建configmap:kubectl create configmap redis-config --from-file=redis.properties 查看 kubectl get cm redis-config:kubectl describe cm redis-config
7.2.2 以volume形式挂载
使用yaml文件:cm.yaml
创建pod: kubectl apply -f cm.yaml 查看输出日志:kubectl logs mypod
7.2.3 以变量形式挂载
使用配置文件:myconfig.yaml 创建configMap: 使用变量形式挂载使用的yaml文件:config-var.yaml 创建pod并查看打印结果:
8、k8s的安全机制
8.1 概述
8.1.1访问k8s集群的时候,需要经过三个步骤完成具体操作
Apiserver做统一协调,例如访问过程中需要证书、token、或者用户名+密码 如果访问pod,可能还需要serviceAcount
8.1.2 进行访问过程中都需要经过apiserver
Apiserver做统一协调,例如访问过程中需要证书、token、或者用户名+密码 如果访问pod,可能还需要serviceAcount
8.2 RBAC
基于角色的访问控制 角色绑定:比如说张三(主体)是开发(角色),李四是测试
-
角色: role:特定命名空间访问权限 clusterRole:所有命名空间访问权限 -
角色绑定 roleBinding:角色绑定到主体 clusterRoleBinding:集群角色绑定到主体 -
主体 user:用户 group:用户组 serviceAcount:服务账号
8.3 实操演示
1) 创建命名空间:kubectl create ns roledemo 2)在新创建的命名空间中创建pod :kubectl run nginx --image=nginx -n roledemo
2) 创建角色 Yaml文件:rbac-role.yaml 创建角色 kubectl apply -f rbac-role.yaml 查看角色:kubectl get role -n roledemo 3)创建角色绑定 Yaml文件:rbac-rolebinding.yaml kubectl get role,rolebinding -n roledemo 4) 使用证书识别身份 脚本文件:rabc-user.sh 将相关证书(ca.*)移动到当前目录下 执行脚本文件:bash rabc-user.sh
9、ingress
9.1 以往的外部访问方式
把端口号对外暴露,通过IP+端口号进行访问(Service里面的nodePort实现) 缺陷:
- 在每个节点上都会暴露端口,在访问时通过任何节点,通过节点IP+端口号实现访问
- 意味着每个端口只能使用一次,一个端口对应一个应用
- 实际访问中都是用域名,根据不同的域名跳转到不同的端口服务中
9.2 ingress和Pod的关系
Pod和ingress通过service关联的 Ingress作为统一入口,由service关联一组Pod
9.3 ingress工作流程
9.4 使用ingress
步骤一 部署ingress Controller (这里选择官方维护的nginx控制器,实现部署) 步骤二 创建ingress规则
9.5使用ingress 对外暴露应用
9.5.1创建nginx应用,对外暴露端口使用NodePort
kubectl create deployment web --image=nginx kubectl expose deployment web --port=80 --target-port=80 --type=NodePort
9.5.2 部署ingress controller
使用yaml文件:ingress-controller.yaml 特别的,这个需要改为true 创建:kubectl apply -f ingress-controller.yaml 查看:kubectl get pod -n ingress-nginx
9.5.3 创建ingress规则
使用yaml文件:ingress01.yaml 使用域名,example.ingredemo.com,绑定服务 web 80端口 创建规则:kubectl apply -f ingress01.yaml 查看ingress: kubectl get ing
9.5.4 在windows系统hosts文件中添加域名访问规则
浏览器输入域名即可访问
10、helm
10.1 引入
1)之前部署应用基本过程 *编写yaml文件 **deployment **Service **Insress
场景:部署单一应用,少数服务的应用,比较适合 缺陷:部署微服务项目,可能有几十个服务,每个服务都有一套yaml文件,需要维护大量的yaml文件,版本管理特别不方便
2)使用helm可以解决哪些问题
- 使用helm可以把这些yaml作为一个整体管理
- 实现yaml文件高效复用
- 使用helm可以实现应用级别的版本管理
10.2 helm介绍
Helm 是一个 Kubernetes 的包管理工具,就像 Linux 下的包管理器,如 yum/apt 等,可以 很方便的将之前打包好的 yaml 文件部署到 kubernetes 上。 Helm 有 3 个重要概念: 1)helm:一个命令行客户端工具,主要用于 Kubernetes 应用 chart 的创建、打包、发 布和管理。 2)Chart:应用描述,一系列用于描述 k8s 资源相关文件的集合。 3)Release:基于 Chart 的部署实体,一个 chart 被 Helm 运行后将会生成对应的一个 release;将在 k8s 中创建出真实运行的资源对象。
10.3 版本变化
10.4 helm安装配置
1)下载helm(3.0版本)安装压缩文件,上传到linux系统中 Helm官网:https://helm.sh/
2)解压helm压缩文件,把解压之后helm目录复制到usr/bin 目录下
10.4.2配置helm仓库
1)添加仓库 //微软和阿里云源 helm repo add stable http://mirror.azure.cn/kubernetes/charts helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
查看源:helm repo list 删除源:helm remove aliyun(名儿) 更新源:helm repo update
10.5 helm快速部署一个应用
1)使用命令搜索应用 Helm search repo 名称(weave) helm search repo weave
- 根据搜索内容选择安装
Helm install 安装之后名称 搜索之后应用名称 helm install ui stable/weave-scope 3)查看安装之后状态 Helm list Helm status ui 4) 查看pod和svc: 发现ui-weave-scope并不对外暴露接口
5)更改ui的svc配置,改为对外暴露接口:kubectl edit svc ui-weave-scope 6) 查看对外暴露端口号
7) 浏览器访问
10.6 自己创建chart
10.6.1使用命令创建chart: helm create mychart
- Chart.yaml : 当前chart属性配置信息
- Templates :编写yaml文件放到这个目录中
- Values.yaml:yaml文件可以使用的全局变量定义位置
10.6.2在templates文件夹中创建两个yaml文件
templates中本有文件,先清空)
-
Deployment.yaml :一个ngixn镜像 kubectl create deployment web1 --image=nginx --dry-run -o yaml > deployment.yaml -
Service.yaml:暴露80接口 这儿先创建了web1 的pod,用来实现service.yaml的创建,创建后删除web1 pod) kubectl expose deployment web1 --port=80 --target-port=80 --type=NodePort --dry-run -o yaml > service.yaml
10.6.3 安装mychart
helm install web1 mychart/ 查看:kubectl get pod,svc
10.6.4 应用升级
Helm upgrade chart名称 : helm upgrade web1 mychart/
10.7 实现yaml高效复用
通过传递参数,动态渲染模板,yaml内容动态传入参数生成。 在chart有values.yaml文件,定义yaml文件全局变量。 Yaml文件中大体有几个地方不同
- Image
- Tag
- Label
- Port
- Replicas
10.7.1 在values.yaml中定义变量和值
10.7.2 在具体yaml文件中,获取定义变量值
- Deployment.yaml中
- Service.yaml中
尝试运行:helm install --dry-run web2 mychart/ 相应位置替代完成 安装mychart: helm install web2 mychart/ 检查pod:kubectl get pod 检查service: kubectl get svc
11、持久存储
数据卷 emptydir,是本地存储,当pod重启,数据便不存在了,需要对数据进行持久化存储
11.1 nfs,网络存储
11.1.1找一台服务器当做nfs服务端
1)安装nfs yum install -y nfs-utils
2)设置挂载路径 vi /etc/exports 3) 创建挂载路径: mkdir /data/nfs
11.1.2 在k8snode节点上安装nfs
同上
11.1.3 在nfs服务器启动nfs服务
systemctl start nfs
查询服务:ps -ef | grep nfs
11.1.4 在k8s集群部署应用使用nfs持久网络存储
1)Yaml文件:nfs-nginx.yaml 写上nfs服务器ip地址 2) 应用yaml文件:kubectl apply -f nfs-nginx.yaml 3) 进入pod: kubectl exec -it nginx-dep1-69f5f6f86-wp6l6 bash 4)查看挂载目录(此时没有内容,在服务器端加入内容) 5) 在nfs服务器端创建文件
6) 再次查看挂载目录
11.2 持久化存储PV和PVC
PV :持久化存储,对存储资源进行抽象,对外提供可以调用的地方(生产者) PVC:用于调用,不需要关心内部实现细节(消费者)
11.2.1 实现流程
11.2…2 示例
1)yaml文件:pvc.yaml 2)yaml文件:pv.yaml 3)执行yaml kubectl apply -f pvc.yaml kubectl apply -f pv.yaml
4) 查看pv: kubectl get pv 5)进入pod : kubectl exec -it nginx-dep1-58b7bf955f-f54wz bash 6)查看挂载券:
12、集群资源监控
- 集群监控
节点资源利用率 节点数 运行pod - Pod监控
容器指标 应用程序
12.1 监控指标
- 集群监控
节点资源利用率 节点数 运行pod - Pod监控
容器指标 应用程序
12.2 监控平台 Prometheus + Grafana
12.2.1 prometheus
抓取数据进程存储
- 开源的
- 监控、报警、数据库
- 以HTTP协议周报性抓取被监控组件状态
- 不需要复杂的集成过程,使用http接口接入就可以了
12.2.2 Grafana
读取数据进行展现
12.3 搭建监控平台
12.3.1 部署prometheus
二进制包进行搭建,或者通过部署yaml文件进行搭建
- 部署一个守护进程:node-exporter.yaml
kubectl create -f node-exporter.yaml - 部署rbac: kubectl create -f rbac-setup.yaml
- 部署configmap.yaml : kubectl create -f configmap.yaml
- 部署prometheus.deploy.yml: kubectl create -f prometheus.deploy.yml
- Prometheus.svc.yml: kubectl create -f prometheus.svc.yml
- 查看:kubectl get pod -n kube-system
12.3.2 部署grafana
1)部署grafana-deploy.yaml:kubectl create -f grafana-deploy.yaml
2)部署grafana-ing.yaml:kubectl create -f grafana-ing.yaml 3)部署grafana-svc.yaml:kubectl create -f grafana-svc.yaml 4) 查看:kubectl get pod -n kube-system
12.3.3 打开Granfana,配置数据源,导入显示模板
-
通过查看端口号访问: kubectl get svc -n kube-system -
默认用户名密码 admin -
配置数据源: 这儿的ip得用集群IP -
导入模板: 去官网下载模板: https://grafana.com/grafana/dashboards/13978?pg=dashboards&plcmt=featured-dashboard-2 -
查看节点数据分析:
13、高可用的k8s集群
单master: 多master: 高可用集群技术: Keepalived:检查当前master是否可用 Haproxy:将请求平均分发给master节点,负载均衡
|