docker|docker和k8s面试题总结(未完待续)

6 容器类面试题 6.1 docker有几种网络模式?容器和容器之间怎么通信?主机和主机之间怎么通信?
docker 有四种网络模式

  • none
  • 桥接(默认模式)
  • Host
  • container
容器之间通过桥接模式进行通信
跨主机的容器之间通过静态路由进行通信,A主机的容器的下一跳指向B主机,这样B主机接收到请求解包后转发给本机的容器
6.2 docker和核心技术是什么
容器其实就是 Namespace + Cgroups
  • Namespace:帮助容器实现各种资源的隔离
  • Cgroups:主要对容器使用某种资源量的多少做一个限制
6.3 docker和虚拟机的区别是什么?
  • docker 使用宿主机的内核,启动速度快,隔离性差,docker 确切来说是一个容器引擎
  • 虚拟机使用自己的内核,启动速度慢,因为有自己的内核,所以隔离性好
6.4 Docker 的常用命令
header 1 header 2
FROM 指定基础镜像,即构建新镜像是基于那个基础镜像
LABEL 设置镜像的标签
RUN 指定构建过程中要运行的 shell 命令
ENV 设置环境变量
WORKDIR 指定默认的工作目录,即进入容器后默认进入的目录
VOLUME 创建挂载点,也称为容器卷,用于数据共享和持久化
CMD 注定容器要运行的命令,与 RUN 不同的是,这些命令不是在镜像构建过程中执行的
ENTRYPOINT 指定容器启动时要运行的命令,与 CMD 有区别
COPY 拷贝文件/目录到镜像中,但是不会解压
ADD 拷贝文件/目录到镜像中,且会自动解压
EXPOSE 声明容器运行的服务端口,即,指定对外暴露的端口
USER 为 RUN、CMD、ENTRYPOINT 执行命令指定运行用户
HEALTHCHECK 容器中服务检查检查
ARG 设置编译镜像时加入的参数
ONBUILD 当构建一个被继承的 Dockerfile 的时候就会运行 ONBULID 指令,ONBUILD 是一个触发指令
STOPSIGNAL 设置容器的退出信号量
6.5 ENTRYPOINT 和 CMD 之间的共同和异同
共同点
    1. 都可以指定 shell 或者 exec 函数调用的方式执行命令
    1. 当在 dockerfile 中存在多个 CMD 或 ENTRYPOINT 指令时,只有最后一条指令生效,所以一般只有一条 CMD 或 ENTRYPOINT 指令
不同点
    1. CMD 指令可以被 docker run 之后的参数覆盖,而 ENTRYPOINT 指令指定的命令不会被覆盖,而是将 docker run 指定的参数当做 ENTRYPOINT 指定命令的参数
    1. CMD 指令可以为 ENTRYPOINT 指定设置默认参数,而且可以被 docker run 指定的参数覆盖
6.6 Harbor 磁盘满了之后如何删除镜像
镜像内容是存储在一层虚拟文件系统(VFS)之上,由多个文件块(Blobs)、描述清单文件(Manifests)和 标签文件(tags)组成,因为镜像设计是多层的。所以这些文件会互相依赖,在没有确认文件块(Blob)是否被其他镜像使用的情况下,直接删除会让仓库不完整。所以一般的做法是只做删除标记,而不是真删除,通过垃圾回收机制来遍历当前仓库的有向关系图(DAG),然后在删除没有被引用的文件块
6.7 镜像下载很慢如何解决 ?
1)搞清楚 harbor 架构
2)测试网络速度
服务端:iperf -s -i 1 -w 1000000 客户端:iperf -c 10.201.18.62 -i 1 -w 1000000

3)IO 测试
pidstat -d 1 iostat -d -x 1 vmstat 1 100

4)优化镜像
  • 只安装一些必须的软件包
  • 不要将数据和日志打包进镜像
  • 删除一些不需要的数据
  • 镜像变动的东西放在最上层(命令的最下面几行)
7 Kubernetes 面试题 7.1 为什么要使用 k8s
Kubernetes 是一个开源的容器管理平台,简称 k8s,用于管理多个主机上的容器化应用程序 ; 提供应用程序的快速部署,维护和扩展的基本机制
  • 自我修复:一旦某一个容器崩溃,能够在 1 秒中左右迅速启动新的容器
  • 弹性伸缩:实时根据服务的并发情况,增加或缩减容器数量
  • 自动部署
  • 版本回滚:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
  • 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
  • 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
  • 机密和配置共享管理
  • 存续编排:可以根据容器自身的需求自动创建存储卷
7.2 K8s 的安装部署方式有哪些 ?有什么优缺点?
二进制部署:
  • 以守护进程的方式启动在宿主机上,类似于是 Nginx 一样使用 service 脚本启动,需要自开监控脚本
  • 兼容性最好,类似于在宿主机上启动了一个服务,这个服务可以直接使用宿主机内核的很多特性
  • 适合有二次开发需求的场景
kubeadm部署:
  • 以容器的方式启动,会在宿主机上启动很多容器,比如 api-server 容器、controller manager 容器等,这样就导致容器运行环境受限,只能使用容器中的命令,很多宿主机内核的功能无法使用
  • 以容器化的方式启动可以实现故障自动恢复
7.2 k8s 各组件介绍
https://kubernetes.io/zh/docs/concepts/overview/components/

docker|docker和k8s面试题总结(未完待续)
文章图片

7.2.1 master节点组件
  • kube-apiserver
    Kubernetes API ,提供了资源操作的唯一入口,各组件协调者,以 RESTful API 提供接口服务,并提供认证、授权、访问控制、API注册和发现等机制,负责接收、解析、处理请求。 所有对象资源的增删改查和监听操作都交给 APIServer 处理后再提交给 Etcd 存储
  • kube-scheduler
    调度器,负责资源的调度,按照预定的调度策略将 Pod 调度到相应的 node 节点上,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上
  • kube-controller-manager
    控制器,负责维护集群的状态,检查 pod 的健康状态,比如故障检测、自动扩展、 滚动更新等一些操作
  • etcd
    etcd 是一个分布式的 key / value 形式的键值存储系统,保存了整个 kubernetes 集群的状态数据,比如 Pod、Service 等对象信息,在 kubernetes 中使用 etcd 时,需要对 etcd 做备份, 保证高可用;整个 kubernetes 系统中一共有两个服务需要用到 etcd 用来协同和存储配置,分别是:
  • 网络插件calico、对于其它网络插件也需要用到 etcd 存储网络的配置信息
  • kubernetes 本身,包括各种对象的状态和元信息配置
    注意:网络插件操作 etcd 使用的是 v2 的 API,而 kubernetes 操作 etcd 使用的 v3 的 API,所以在下面我们执行etcdctl的时候需要 设置ETCDCTL_API环境变量,该变量默认值为2,表示使用v2版本的api,v3表示使用v3版本的api
7.2.2 node节点组件(工作节点组件)
  • kubelet
    kubelet: 是 Master 在 Node 节点上的 Agent,每个 Node 节点上的 kubelet 定期就会调用 API Server 的 REST 接口报告自身状态,API Server 接收这些信息后,将节点状态信息更新到 etcd 中。kubelet 负责管理本机运行容器的生命周期,通过 API Server 监听 Pod 信息,从而对 Node 机器上的 Pod 进行管理,比如创建容器、Pod 挂载数据卷、下载 secret、获取容器和节点状态等工作,Kubelet 将每个 Pod 转换成一组容器
    注意:如果以 kubeadm 这种方式安装 k8s,由于 master 上的组件(kube-apiserver、kube-scheduler、kube-controller-manager)都是以 pod 的方式运行,所以在 master 上也需要安装 kubelet
  • kube-proxy
    k8s 代理,是在群集中的每个节点上运行的网络代理和负载均衡,是实现 service 的通信与负载均衡机制的重要组件,kube-proxy 负责请求转发,一旦发现了某一个 Service 关联的 Pod 信息发生了改变(如IP、Port等),由 KubeProxy 就会把变化后的 service 转换成 IPVS 或 IPtables 规则中,完成对后端 pod 的负载均衡
  • docker
    是一个容器引擎,用于运行容器
7.2.3 附加组件
  • coredns
    k8s 1.11 之前使用的是 kubedns ,1.11 之后才有 coredns
    coredns 是一个 DNS 服务器,能够为 Kubernetes services 提供 DNS 记录
  • dashboard
    k8s的web界面,通过这个界面可以对k8s资源进行操作
  • Ingress Controller
    七层负载均衡控制器,可以创建 nginx 或者 traefik 这种七层负载应用,实现域名和 https 访问
  • prometheus+alertmanager+grafana
    k8s 监控和报警展示
  • EFK
    k8s 日志收集展示和检索
7.3 简述 pod 的创建过程
  • 第一步:kubectl create po
    首先进行认证后,kubectl会调用master api创建对象的接口,然后向k8s apiserver发出创建pod的命令
  • 第二步:k8s apiserver
    apiserver收到请求后,并非直接创建pod,而是先创建一个包含pod创建信息的yaml文件
  • 第三步:controller manager
    创建Pod的yaml信息会交给controller manager,controller manager根据配置信息将要创建的资源对象(pod)放到等待队列中
  • 第四步:scheduler
    scheduler查看k8s api,类似于通知机制。首先判断:pod.spec.Node == null?
    若为null,表示这个Pod请求是新来的,需要创建;然后进行预选调度和优选调度计算,找出最 “闲” 的且符合调度条件的node。最后将信息在etcd数据库中更新分配结果:pod.spec.Node2(设置一个具体的节点) 同样上述操作的各种信息也要写到etcd数据库中。
    分配过程需要两层调度:预选调度和优选调度
    • 预选调度:一般根据资源对象的配置信息进行筛选。例如NodeSelector、HostSeletor和节点亲和性等。
    • 优选调度:根据资源对象需要的资源和node节点资源的使用情况,为每个节点打分,然后选出最优的节点创建资源对象(pod)
  • 第五步:kubelet
    目标节点node2上的kubelet进程通过API Server,查看etcd数据库(kubelet通过API Server的WATCH接口监听Pod信息,如果监听到新的pod副本被调度绑定到本节点)监听到kube-scheduler 产生的Pod绑定事件后获取对应的Pod清单,然后调用node1本机中的docker api初始化volume、分配IP、下载image镜像,创建容器并启动服务
  • 第六步:controller manager
    controller manmager会通过API Server提供的接口实时监控资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试将其状态修复到 “期望状态”
7.4 简述 pod 的终止过程
  1. 用户向 apiServer 发送删除 pod 对象的命令
  2. apiServcer 中的 pod 对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod 被视为 dead
  3. 将 pod 标记为 terminating 状态
  4. kubelet 在监控到 pod 对象转为 terminating 状态的同时启动 pod 关闭过程
  5. 端点控制器监控到 pod 对象的关闭行为时将其从所有匹配到此端点的 service 资源的端点列表中移除
  6. 如果当前 pod 对象定义 了preStop 钩子处理器,则在其标记为 terminating 后即会以同步的方式启动执行
  7. pod 对象中的容器进程收到停止信号
  8. 宽限期结束后,若 pod 中还存在仍在运行的进程,那么 pod 对象会收到立即终止的信号
  9. kubelet 请求 apiServer 将此 pod 资源的宽限期设置为0从而完成删除操作,此时 pod 对于用户已不可见
7.5 pod 的声明周期
我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程
  • pod 创建过程
  • 运行初始化容器(init container)过程
  • 运行主容器(main container)
    • 容器启动后钩子(post start)、容器终止前钩子(pre stop)
    • 容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
  • pod终止过程
在整个生命周期中,Pod会出现5种状态(相位),分别如下:
  • 挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成(如:nodeName: node3 指定调度到 node3 节点上,而这个 node3 节点不存在,就会出现 Pending 状态)或者仍处于下载镜像的过程中
  • 运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
  • 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
  • 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
  • 未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致
7.6 镜像拉取策略
kubernetes支持配置三种拉取策略:
  • Always:总是从远程仓库拉取镜像(一直使用远程下载)
  • IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没有则远程下载)
  • Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)
默认值说明:
如果镜像tag为具体版本号, 默认策略是:IfNotPresent
如果镜像tag为:latest(最终版本) ,默认策略是always
7.7 容器探测
  • liveness probes:存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器
  • readiness probes:就绪性探针,用于检测应用实例当前是否可以接收请求,如果不能,k8s不会转发流量
  • livenessProbe 决定是否重启容器,readinessProbe 决定是否将请求转发给容器。
上面两种探针目前均支持三种探测方式:
  • Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常
  • TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常
  • HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常
7.8 怎么让一个容器调度到特定的 Node 上 ?
场景:在实际环境中,不同的服务会对资源有不同的要求,根据实际需求,我们需要将这些应用部署到特定的服务器,从而提升服务性能和服务器资源使用率
应用调度类型与场景
  • nodeSelector 定向调度
    nodeSelector 是节点选择约束的最简单推荐形式,nodeSelector 是 PodSpec 的一个字段,通过设置 label 相关策略将 pod 关联到对应的 label 的节点上
  • nodeName 定向调度
    nodeName 是节点选择约束的最简单方法,但是由于其自身限制,通常不使用它,nodeName 是 PodSpec 的一个字段,如果指定 nodeName,调度器将优先在指定的 node 上运行 pod
  • nodeAffinity 定向调度
    nodeAffinity 类似于 nodeSelector,使用 nodeAffinity 可以根据节点的 labels 限制 Pod 能否调度到哪些节点,当前 nodeAffinity 有软亲和性和硬亲和性两种类型,节点亲和性与 nodeSelector 相比,亲和/反亲和功能极大地扩展了可以表达约束的类型,增强了如下功能
    1. 语言更具表现力
    2. 在调度器无法满足要求时,仍然调度该 Pod
给 worker 节点添加 lable
kubectl label node qa-gpu082 env=dev

使用 nodeSelector 调度应用
nodeSelector: env: dev

使用 nodeName 调度应用
nodeName: master1

使用 Affinity 调度应用
软亲和
affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution - weight: 100 preference: matchExpressions: - key: env operator: In values: - dev

硬亲和
affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution nodeSelectorTerms: - matchExpressions: - key: env operator: In values: - test

硬亲和性:当没有节点满足亲和性要求时,Pod 一直处于 Pending 状态
7.9 什么是亲和性,以及使用场景是什么 ?
  • nodeAffinity(node亲和性): 以node为目标,解决pod可以调度到哪些node的问题
  • podAffinity(pod亲和性) : 以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题
  • podAntiAffinity(pod反亲和性) : 以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题
关于亲和性(反亲和性)使用场景的说明:
  • 亲和性:如果两个应用频繁交互,那就有必要利用亲和性让两个应用的尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。
  • 反亲和性:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,这样可以提高服务的高可用性。
7.10 pod 底层网络和数据存储是如何进行的
https://blog.csdn.net/qq_43280818/article/details/106910187

前面说过 pod 内部的容器也是一个独立的沙箱环境,因此也有自己的 ip 和 端口。如果内部容器还是通过 ip:port 来通信,相当于还是远程访问,这样的话性能会受到一定的影响。如何提高内部容器之间访问的性能呢?
pod 底层
  • pod 内部容器创建之前,必须先创建 pause 容器。pause 有两个作用:共享网络和共享存储。
  • 每个服务容器共享 pause 存储,不需要自己存储数据,都交给 pause 维护。
  • pause 也相当于这三个容器的网卡,因此他们之间的访问可以通过 localhost 方式访问,相当于访问本地服务一样,性能非常高(就像本地几台虚拟机之间可以 ping 通)。
总结
集群内部访问
  • 容器间通信:同一个 Pod 内的多个容器间的通信,通过 localhost 实现
  • Pod 间通信:Pod IP <----->Pod IP,Overlay Network(叠加网络),K8s要求Pod间通信必须是所见即所得,从一个 Pod IP 到另一个 Pod IP 必须是直达,不能经过任何地址转换,不同 pod 的容器访问可以使用 endpoint 方式(pod 的 ip + 容器的端口)
  • Pod 与 Server 间通信:Pod IP<----->Cluster IP
    kubectl get configmap -n kube-system kubectl get configmap kube-proxy -o yaml -n kube-system

集群外部访问
  • 直接访问容器(设置 pod 级别的 hostwork=true,直接通过主机 ip + hostport 访问)
  • 通过service访问(NodePort方式,集群中任意一个 Node 的 IP 地址 + 具体的 NodePort 端口号访问)
  • Ingress
7.11 k8s 网络通信
K8s本身只有网络标准,没有网络方案,它只允许别人给他提供,Kubernetes 1.1之后采用CNI作为通用的容器网络标准
CNI(Container Network Interface)
  • flannel:部署简单,支持网络地址分配,不支持网络策略
    支持多种后端:
    • VxLAN(Overlay叠加网络)
      • 原生vxlan
      • Directrouting(源和目标节点在同一网络用host-gw方式直接转发,不用隧道叠加。而不再同一网络就用vxlan隧道叠加,Directrouting是vxlan和host-gw的结合使用)
    • host-gw:Host Gateway(比calico性能并不差,但要求各节点必须工作在同一个二层网络中,不支持跨网络,如果有成千上万的Pod,容易产生广播风暴
    • UDP:性能差
  • calico:部署复杂,既支持网络地址分配又支持网络策略,基于BGP协议实现三层网络路由
  • canel
  • kube-router
7.12 Kubernetes Controllers 的分类和作用
作用:Controllers 控制器,控制 pod,启动、停止、删除
  • ReplicaSet:确保预期的 Pod 副本数量
  • Deployment:无状态应用部署(kubectl scale deployment nginx-1 -n test --replicas=3
  • StatufulSet:有状态应用部署(mysql,redis,nacos,es,zookeeper等)
  • DaemonSet:确保所有 Node 运行同一个类型的 Pod(监控客户端:node-exporter、日志收集客户端:filebeat)
  • Job:一次性任务(比如 pod 运行完自行销毁的任务)
  • Cronjob:定时任务(定期清理)
7.13 service 和 label
Service:将一组 pod 关联起来,提供一个统一个入口,即使 pod 地址发生改变,这个统一入口也不会变化,可以保证用户访问不受影响
  • 防止 Pod 失联
  • 定义一组 Pod 的访问策略
Label:一组 pod 有一个统一的标签,Service 是通过标签和一组 pod 进行关联的
  • 标签,附加到某个资源上,用于关联对象,查询和筛选
svc
apiVersion: v1 kind: Service metadata: name: mall-bi-frontend-prelease namespace: bi spec: ports: - name: http port: 80 protocol: TCP targetPort: http selector: k8s-app: mall-bi-frontend-prelease type: ClusterIP

deploy
apiVersion: apps/v1 kind: Deployment metadata: name: mall-bi-frontend-prelease namespace: bi spec: replicas: 1 selector: matchLabels: k8s-app: mall-bi-frontend-prelease strategy: rollingUpdate: maxSurge: 0 maxUnavailable: 1 type: RollingUpdate template: metadata: labels: k8s-app: mall-bi-frontend-prelease spec: containers: ......

[root@web01 ~]# kubectl -n bi get pod --show-labels NAMEREADYSTATUSRESTARTSAGELABELS k8s-app=mall-bi-frontend,pod-template-hash=57f6696845 mall-bi-frontend-57f6696845-qc6p41/1Running04h12mk8s-app=mall-bi-frontend,pod-template-hash=57f6696845 mall-bi-frontend-prelease-7c8784c648-rdm5s1/1Running087mk8s-app=mall-bi-frontend-prelease,pod-template-hash=7c8784c648 [root@web01 ~]#

7.14 容器不停重启的原因有哪些
1)比如:busybox并不是一个程序,而是类似于一个工具类的集合,k8s集群启动管理后,它会自动关闭。并且不停的重启。解决方法就是让其一直在运行,这就用到了command配置
2)pod 数量达到了限制
3)资源限制达到了上限
4)存活探针(livenessProbe)检查失败,如(command: [“/bin/cat”,“/tmp/hello.txt”])如果这个文件(/tmp/hello.txt)不存在,容器则会不停的重启(当然,要受重启策略的影响)
5)node 地址设置冲突,calico 网络插件无法运行,导致调度到此 node 上的 pod 不停的重启
7.15 排查 Pod 异常的常用命令
查看 Pod 状态
kubectl get pods 【docker|docker和k8s面试题总结(未完待续)】 -n -o wideroot@sh-gpu101:~# kubectl get pods node-exporter-7xztd -n monitoring -o wide NAMEREADYSTATUSRESTARTSAGEIPNODENOMINATED NODEREADINESS GATES node-exporter-7xztd1/1Running02d192.168.106.124node124 root@sh-gpu101:~#

查看 Pod 的 yaml 配置
kubectl get pods -n -o yaml

查看 Pod 的事件
kubectl describe pods -n

查看 Pod 容器日志
kubectl logs -n [-c ]# 可以 tailf 该 Pod 的日志观察进度 kubectl logs kibana-logging-7445dc9757-pvpcv -n kube-system -f

查看 kube-system 命名空间下的所有服务
kubectl get svc -n kube-system

7.16 pod排错步骤:
1)查看 kube-system 命名空间下的所有 pod 状态
kubectl -n kube-system get pods # 显示IP信息和运行的node信息 kubectl -n kube-system get pods -o wide

2)查看 pod 的事件
kubectl -n kube-system describe pod metrics-server-v0.2.1-5988c5d6b8-8x4l2

3)查看日志
# 发现 pod 中有两个容器 root@172-16-244-214:~# kubectl get pod -n monitoring prometheus-r9xlm NAMEREADYSTATUSRESTARTSAGE prometheus-r9xlm1/2CrashLoopBackOff31028d# 查看 pod 日志报错,因为 pod 中有两个容器,必须选择一个容器后才能查看 root@172-16-244-214:~# kubectl logs -f -n monitoring prometheus-r9xlm error: a container name must be specified for pod prometheus-r9xlm, choose one of: [configmap-reload prometheus]# 查看 configmap-reload 容器日志 root@172-16-244-214:~# kubectl logs -f -n monitoring prometheus-r9xlm -c configmap-reload 2022/02/22 16:00:59 Watching directory: "/etc/config" 2022/02/22 16:00:59 Watching directory: "/etc/prometheus/rules" ^C# 查看 prometheus 容器日志 root@172-16-244-214:~# kubectl logs -f -n monitoring prometheus-r9xlm -c prometheus

7.17 容器的存储
7.17.1 普通存储 EmptyDir
EmptyDir 是最基础的 Volume 类型,一个 EmptyDir 就是 Host 上的一个空目录。
EmptyDir 是在 Pod 被分配到 Node 时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为 kubernetes 会自动分配一个目录,当 Pod 销毁时, EmptyDir 中的数据也会被永久删除。
EmptyDir用途如下:
  • 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留
  • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)
HostPath
EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。
HostPath 就是将 Node 主机中一个实际目录挂在到 Pod 中,以供容器使用,这样的设计就可以保证 Pod 销毁了,但是数据依据可以存在于 Node 主机上。
NFS
HostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的用NFS、CIFS。
NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在节点上怎么转移,只要Node跟NFS的对接没问题,数据就可以成功访问。
7.17.2 高级存储 kubernetes 支持的存储系统有很多,要求用户全都掌握,显然不现实。为了能够屏蔽底层存储实现的细节,方便用户使用, kubernetes 引入 PV 和 PVC 两种资源对象。
  • PV(Persistent Volume)是持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下 PV 由 kubernetes 管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。
  • PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC 其实就是用户向 kubernetes 系统发出的一种资源需求申请。
7.17.3 配置存储 ConfigMap是一种比较特殊的存储卷,它的主要作用是用来存储配置信息的
在kubernetes中,还存在一种和ConfigMap非常类似的对象,称为Secret对象。它主要用于存储敏感信息,例如密码、秘钥、证书等等。
7.18 K8s 是怎么进行程序发布的 ?
1)创建 secret
2)创建 configmap 和 pvc
3)打标签和污点
4)设置资源限制(resources)
5)设置亲和性
6)设置探针(就绪探针和存活探针)
7)发布 depoly
8)发布 svc
9)发布 ingress
10)访问测试
7.19 K8s 如何实现灰度发布 ?
7.20 kube-proxy 支持的三种工作模式
UserSpace:k8s v1.2 及以后就已经淘汰了Iptables:目前默认方式,1.1开始支持,1.2开始为默认IPVS:1.9 引入到 1.11 正式版本,需要安装 ipvsadm、ipset 工具包和加载 ip_vs 内核模板

IPVS 模式在 Kubernetes v1.8 中引入 alpha 版本,在v1.9 中处于beta版本,在v1.11中处于GA(也就是release版本,国外都是说GA版本)版本,IPTABLES模式已在v1.1中添加,并成为v1.2之后的默认操作模式,IPVS和IPTABLES都基于netfilter,IPVS模式和IPTABLES模式之间的差异如下
  • IPVS为大型群集提供了更好的可伸缩性和性能
  • 与IPTABLES相比,IPVS支持更复杂的负载平衡算法(最少连接,轮询,加权轮询等)
  • IPVS支持服务器运行状况检查和连接重试等
7.21 k8s 里使用的是什么 dns,运行哪些服务?有多少 pod?
skydns kubedns coredns---目前的主流

7.22 常用命令
# 基础命令 create delete edit get describe logs exec scale explain# 命令说明# 配置命令 lable:给 node 标记 label,实现 pod 与 node 亲和性# 标签管理 apply# 动态配置# 集群管理命令 cluster-info/top# 集群状态# node 节点管理 cardon:警戒线,标记 node 不被调用 uncardon:取消警戒标记为 cardon 的 node drain:驱逐 node 上的 pod,用于 node 下线等场景 taint:给 node 标记污点,实现反 pod 与 node 反亲和性api-resource/api-versions/version# api 资源 config# 客户端 kube-config 配置

查看 bi 这个命名空间下的所有的配置文件
[root@node01 ~]# kubectl -n bi get cm NAMEDATAAGE bi-frontend1132d bi-frontend-prelease1131d

编辑 bi 这个命名空间某个配置文件
kubectl -n bi edit cm bi-frontend

查看 bi 这个命名空间下的所有 pod,并显示 pod 的 IP 地址
kubectl -n bi get pods -o wide

查看 dev 命名空间下的 pod 名称为 ngx-1 的日志,并显示最后 30 行
kubectl logs ngx-1 -n dev | tail -n 30

如何查看 bi 命名空间下的所有 endpoints(endpoints:存储一组 pod 的 IP 地址)
[root@node01]# kubectl -n bi get ep NAMEENDPOINTSAGE bi-backend10.1.0.22:8080,10.1.1.225:8080,10.1.2.146:8080132d bi-frontend10.1.1.6:80,10.1.2.238:80132d

如何列出所有 namespace 中的所有 pod
# 注意:生产中谨慎使用,尤其是在资源紧张的情况下 kubectl get pods --all-namespaces kubectl get pods -A

如何查看 bi 命名空间下的所有 ingress
kubectl -n bi get ing

删除 bi 命名空间下某个 deploy,名称为 tianwen
kubectl -n bi delete deploy tianwen

如何缩减 bi 命名空间下 deploy 名称为 ngx-1 的副本数为 3
kubectl -n bi scale deployment ngx-1 --replicas=3 kubectl -n bi get pods -o wide

如何在不进入 pod 内查看命名空间为 dev , pod 名称为 metrics-server-v0.2.1-5988c5d6b8-8x4l2 的 hosts
kubectl exec -it metrics-server-v0.2.1-5988c5d6b8-8x4l2 -n dev -- cat /etc/hosts

如何设置节点 node-1 为不可调度以及如何取消不可调度
设置不可调度
# cordon:警戒线,标记 node 不被调度 # 设置 node-1 为不可调度 kubectl cordon node-1

注意:不要大量占用服务器根目录空间,可用容量低于 10% 后,服务器会进入异常状态(不可被调度)
取消不可调度
# uncordon:取消警戒标记为 cordon 的 node # 取消 node-1 的不可调度 kubectl uncordon node-1

7.23 上云有哪些注意事项 ?
1)中间件(redis mysql nacos es zookeeper mq MongoDB Sentinel等)
  • 有状态
  • 数据导入(例如:通过 MySQL Workbench 将本地的数据导入到云上的 MySQL 中)
2)微服务
  • 无状态
  • 制作镜像
3)网络
  • 各种访问地址(内网 DNS 访问)
4)配置
  • 生产配置分离
  • URL
7.24 应用上云部署的过程,以 Java 举例说明 ?
1)打包
maven 打成可执行 jar,上传给服务器(master)
2)制作镜像
docker 根据 dockerfile 把包打成指定的镜像
3)推送镜像
将镜像推送给私有 Harbor
4)应用部署
给 k8s 部署应用,node1 节点部署应用
7.25 生产中应用部署(pod 发布)的注意事项
1)集群节点设置(lable 和 taint)
2)创建密钥文件(secret)
3)配置文件(configmap)
4)对于有状态的应用,还需要创建存储(pv和pvc)
5)资源限制(resources)
6)亲和性设置(affinity)
7)容忍设置(tolerations)
8)定向调度(nodeSelector)
9)探针设置(livenessProbe和readinessProbe)
7.26 port、targetport、nodeport的区别
  • nodeport:集群外流量访问集群内服务的端口,比如客户访问 nginx、apache 等
  • port:集群内的 pod 互相通信的端口,比如:lnmp架构中,php 访问 mysql,mysql 是不能让外部用户访问到的,port 是 service 的端口
  • targetport:目标端口,也就是最终端口,也就是 pod 的端口

    推荐阅读