kubernetes-k8s

资料

官方文档:https://kubernetes.io/
github的学习文档:https://kuboard.cn/learning/
介绍--
词汇表--
命令--

虚拟机:Centos7
防火墙需要开的端口
命令:https://kubernetes.io/zh-cn/docs/reference/setup-tools/kubeadm/kubeadm-init/

需要修改,否则安装太慢
容器环境:https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/
端口协议:https://kubernetes.io/zh-cn/docs/reference/ports-and-protocols/

b站学习视频

学习的开端--兴趣

学习

    1. 可视化创建

官网描述

Kubernetes 通过将容器放入在节点(Node)上运行的 Pod 中来执行你的工作负载。
短短一句话已经把应用的部署流程介绍了
image.png

image.png

知识点

云原生(Cloud Native)的基石则是:Kubernetes(简称K8S)。正如十年前的Hadoop建立起来的大数据巨型生态(Hadoop已英雄暮年), 围绕着Kubernetes的云原生海量生态也已经初见成型。

简介

Kubernetes 是一个开源的容器编排引擎和容器集群管理工具,用来对容器化应用进行自动化部署、 扩缩和管理。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有8个字符。 Google 在 2014 年开源了 Kubernetes 项目。

公告

  • kubernetes1.24版本开始,移除了对docker的支持
  • 1.25版本使用containerd作为容器

构造及网络关系

资料

结构图

kubernetes cluster

  • 控制平面(Control Plane)------老板
    • kube-API-server
      • 相当于神经中枢
      • 对外暴露API,用户可以通过这个API-server与k8s的cluster交互
    • kube-scheduler
      • 收到创建容器的命令,就把容器分发给不同的node
    • etcd
      • 存储数据
      • 记录整个cluster的信息和状态
    • kube-controller-manager
      • 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
      • 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
      • 端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入 Service 与 Pod)
      • 服务帐户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认帐户和 API 访问令牌
    • cloud-controller-manager
      • 允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。
      • cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不需要有云控制器管理器。
      • 下面的控制器都包含对云平台驱动的依赖:
        • 节点控制器(Node Controller):用于在节点终止响应后检查云提供商以确定节点是否已被删除
        • 路由控制器(Route Controller):用于在底层云基础架构中设置路由
        • 服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器
  • work node----------员工
  • work node
    • kubelet
      • kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。
      • kubelet 接收一组通过各类机制提供给它的 PodSpecs, 确保这些 PodSpecs 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。
    • kube-proxy
      • kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。
      • kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
      • 如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。
    • pod
    • pod
    • pod
      • contain-容器--一般一个pod放一个contain,也可以是多个应用程序

POD

每个pod有一个ip,pod内的容器共享ip
在Kubernetes集群中,Pod是所有业务类型的基础,也是K8S管理的最小单位级,它是一个或多个容器的组合。这些容器共享存储、网络和命名空间,以及如何运行的规范。在Pod中,所有容器都被同一安排和调度,并运行在共享的上下文中。对于具体应用而言,Pod是它们的逻辑主机,Pod包含业务相关的多个应用容器。
总结

  • Pod是kubernetes中最小的调度单位(原子单元,Kubernetes直接管理Pod而不是容器。
  • 同一个Pod中的容器总是会被自动安排到集群中的同一节点(物理机或虚拟机)上,并且一起调度
  • Pod可以理解为运行特定应用的“逻辑主机”,这些容器共享存储、网络和配置声明(如资源限制)。
  • 每个 Pod 有唯一的 IP 地址。** IP地址分配给Pod**,在同一个 Pod 内,所有容器共享一个 IP 地址和端口空间,Pod 内的容器可以使用localhost互相通信。

关于POD的使用在下面k3s那里

Deployment(部署)与ReplicaSet(副本集)

Service(服务)

ServiceType 取值

  • ClusterIP(默认):将服务公开在集群内部。kubernetes会给服务分配一个集群内部的 IP,集群内的所有主机都可以通过这个Cluster-IP访问服务(负载均衡)。集群内部的Pod可以通过service名称访问服务。
  • NodePort:通过每个节点的主机IP 和静态端口(NodePort)暴露服务。 集群的外部主机可以使用节点IP和NodePort访问服务。
  • ExternalName:将集群外部的网络引入集群内部。
  • LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。

image.png
关于service的使用在下面k3s那里

控制平面(Control Plane)

这个东西是k8s的大脑,他控制着k8s里运行的各种node。
同时也叫做---master node()--这个在Azure中是被微软托管的,无法查看到,同时是不收费的
一个kubernetes cluster,至少一个master node,一个或多个work node,他们都是node节点---虚拟机

CNI

CNI是一个Pod网络集成标准,简化K8s和不同Pod网络实现技术的集成

kubectl指令合集

安装

下载vim
yum -y install vim
更新时间
yum -y install ntpdate
ntpdate ntpl.aliyun.com
查看是否启动
systemctl status ntpdate
关闭防火墙
关闭开机自启
systemctl stop firewalld.service
systemctl disable firewalld.service
kubectl apply -f yaml
kubectl get nodes -o wide
kubectl get pods --all-namespaces -o wide

操控k8s的cluster的命令

minikube version
minikube start


kubectl version
kubectl cluster-info
kubectl get nodes

整合

常用命令缩写

名称 缩写 Kind
namespaces ns Namespace
nodes no Node
pods po Pod
services svc Service
deployments deploy Deployment
replicasets rs ReplicaSet
statefulsets sts StatefulSet

管理对象

  • 命令行指令

例如,使用kubectl命令来创建和管理 Kubernetes 对象。
命令行就好比口头传达,简单、快速、高效。
但它功能有限,不适合复杂场景,操作不容易追溯,多用于开发和调试。

kubernetes使用yaml文件来描述 Kubernetes 对象。
声明式配置就好比申请表,学习难度大且配置麻烦。
好处是操作留痕,适合操作复杂的对象,多用于生产。

指令


kubectl run mynginx --image=nginx
#在容器中执行,exit退出
kubectl exec mynginx -it -- /bin/bash
# -it 交互模式 
# --rm 退出后删除容器,多用于执行一次性任务或使用客户端
kubectl run mynginx --image=nginx -it --rm -- /bin/bash 

#更新容器镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.23

#将副本数量调整为5
kubectl scale deployment/nginx-deployment --replicas=5

# 描述
kubectl describe pod mynginx
# 查看Pod的运行日志
kubectl logs mynginx

# create
Deployment(部署)与ReplicaSet(副本集)
#创建deployment,部署3个运行nginx的Pod
kubectl create deployment nginx-deployment --image=nginx:1.22 --replicas=3


# get
-owide   查看IP和运行节点信息
--watch  动态查看
# 查看大部分内容-pod,service,deploy,rs
kubectl get all
# 查看Pod
kubectl get pod
# 查看pod的labels
kubectl get pod --show-labels
# 查看符合labels条件的pod
kubectl get pod -l app=nginx,environment=text
#查看service
kubectl get service
#查看deployment
kubectl get deploy
#查看replicaSet
kubectl get rs 



# delete
# 删除pod
kubectl delete pod mynginx
# 强制删除pod
kubectl delete pod mynginx --force
# 删除ReplicaSet
kubectl delete rs nginx-deploy-855866bb46
# 删除deployment
kubectl delete deploy nginx-deployment



# 自动缩放
kubectl autoscale deployment/nginx-auto --min=3 --max=10 --cpu-percent=75 
# 查看自动缩放
kubectl get hpa
# 删除自动缩放
kubectl delete hpa nginx-deployment



# 版本更新
#滚动更新
kubectl rollout status deployment/nginx-deployment
# 查看历史版本
kubectl rollout history deployment/nginx-deployment
# 查看指定版本的信息
kubectl rollout history deployment/nginx-deployment --revision=2
# 回滚到历史版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2

删除

如果有deployment,那么光删除pod,他会自动生成,需要先删除depolyment,然后删除pod,一般删除depolyment,相关的信息都会删除。

网上的资料

http://docs.kubernetes.org.cn/683.html

#查看所有namespace的pods运行情况
kubectl get pods --all-namespaces 
#查看具体pods,记得后边跟namespace名字哦
kubectl get pods  kubernetes-dashboard-76479d66bb-nj8wr --namespace=kube-system
# 查看pods具体信息
kubectl get pods -o wide kubernetes-dashboard-76479d66bb-nj8wr --namespace=kube-system
# 查看集群健康状态
kubectl get cs
# 获取所有deployment
kubectl get deployment --all-namespaces
# 查看kube-system namespace下面的pod/svc/deployment 等等(-o wide 选项可以查看存在哪个对应的节点)
kubectl get pod /svc/deployment -n kube-system
# 列出该 namespace 中的所有 pod 包括未初始化的
kubectl get pods --include-uninitialized
# 查看deployment()
kubectl get deployment nginx-app
# 查看rc和servers
kubectl get rc,services
# 查看pods结构信息(重点,通过这个看日志分析错误)
# 对控制器和服务,node同样有效
kubectl describe pods xxxxpodsname --namespace=xxxnamespace
# 其他控制器类似吧,就是kubectl get 控制器 控制器具体名称
# 查看pod日志
kubectl logs $POD_NAME
# 查看pod变量
kubectl exec my-nginx-5j8ok -- printenv | grep SERVICE
# 集群
kubectl get cs           # 集群健康情况
kubectl cluster-info     # 集群核心组件运行情况
kubectl get namespaces    # 表空间名
kubectl version           # 版本
kubectl api-versions      # API
kubectl get events       # 查看事件
kubectl get nodes      //获取全部节点
kubectl delete node k8s2  //删除节点
kubectl rollout status deploy nginx-test
kubectl get deployment --all-namespaces
kubectl get svc --all-namespaces
 
# 创建
kubectl create -f ./nginx.yaml           # 创建资源
kubectl apply -f xxx.yaml (创建+更新,可以重复使用)
kubectl create -f .                            # 创建当前目录下的所有yaml资源
kubectl create -f ./nginx1.yaml -f ./mysql2.yaml     # 使用多个文件创建资源
kubectl create -f ./dir                        # 使用目录下的所有清单文件来创建资源
kubectl create -f https://git.io/vPieo         # 使用 url 来创建资源
kubectl run -i --tty busybox --image=busybox    ----创建带有终端的pod
kubectl run nginx --image=nginx                # 启动一个 nginx 实例
kubectl run mybusybox --image=busybox --replicas=5    ----启动多个pod
kubectl explain pods,svc                       # 获取 pod 和 svc 的文档
 
# 更新
kubectl rolling-update python-v1 -f python-v2.json           # 滚动更新 pod frontend-v1
kubectl rolling-update python-v1 python-v2 --image=image:v2  # 更新资源名称并更新镜像
kubectl rolling-update python --image=image:v2                 # 更新 frontend pod 中的镜像
kubectl rolling-update python-v1 python-v2 --rollback        # 退出已存在的进行中的滚动更新
cat pod.json | kubectl replace -f -                              # 基于 stdin 输入的 JSON 替换 pod
# 为 nginx RC 创建服务,启用本地 80 端口连接到容器上的 8000 端口
kubectl expose rc nginx --port=80 --target-port=8000
 
# 更新单容器 pod 的镜像版本(tag)到 v4
kubectl get pod nginx-pod -o yaml | sed 's/(image: myimage):.*$/1:v4/' | kubectl replace -f -
kubectl label pods nginx-pod new-label=awesome                      # 添加标签
kubectl annotate pods nginx-pod icon-url=http://goo.gl/XXBTWq       # 添加注解
kubectl autoscale deployment foo --min=2 --max=10                # 自动扩展 deployment “foo”
 
# 编辑资源
kubectl edit svc/docker-registry                      # 编辑名为 docker-registry 的 service
KUBE_EDITOR="nano" kubectl edit svc/docker-registry   # 使用其它编辑器
vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf #修改启动参数
 
# 动态伸缩pod
kubectl scale --replicas=3 rs/foo                                 # 将foo副本集变成3个
kubectl scale --replicas=3 -f foo.yaml                            # 缩放“foo”中指定的资源。
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql  # 将deployment/mysql从2个变成3个
kubectl scale --replicas=5 rc/foo rc/bar rc/baz                   # 变更多个控制器的数量
kubectl rollout status deploy deployment/mysql                         # 查看变更进度
 
#label 操作
kubectl label:添加label值 kubectl label nodes node1 zone=north #增加节点lable值 spec.nodeSelector: zone: north #指定pod在哪个节点
kubectl label pod redis-master-1033017107-q47hh role=master #增加lable值 [key]=[value]
kubectl label pod redis-master-1033017107-q47hh role- #删除lable值
kubectl label pod redis-master-1033017107-q47hh role=backend --overwrite #修改lable值
 
# 滚动升级
kubectl rolling-update:滚动升级 kubectl rolling-update redis-master -f redis-master-controller-v2.yaml #配置文件滚动升级
kubectl rolling-update redis-master --image=redis-master:2.0 #命令升级
kubectl rolling-update redis-master --image=redis-master:1.0 --rollback #pod版本回滚
 
# etcdctl 常用操作
etcdctl cluster-health #检查网络集群健康状态
etcdctl --endpoints=https://192.168.71.221:2379 cluster-health #带有安全认证检查网络集群健康状态
etcdctl member list
etcdctl set /k8s/network/config ‘{ “Network”: “10.1.0.0/16” }’
etcdctl get /k8s/network/config
 
# 删除
kubectl delete pod -l app=flannel -n kube-system   # 根据label删除:
kubectl delete -f ./pod.json                                              # 删除 pod.json 文件中定义的类型和名称的 pod
kubectl delete pod,service baz foo                                        # 删除名为“baz”的 pod 和名为“foo”的 service
kubectl delete pods,services -l name=myLabel                              # 删除具有 name=myLabel 标签的 pod 和 serivce
kubectl delete pods,services -l name=myLabel --include-uninitialized      # 删除具有 name=myLabel 标签的 pod 和 service,包括尚未初始化的
kubectl -n my-ns delete po,svc --all      # 删除 my-ns namespace下的所有 pod 和 serivce,包括尚未初始化的
kubectl delete pods prometheus-7fcfcb9f89-qkkf7 --grace-period=0 --force 强制删除
kubectl delete deployment kubernetes-dashboard --namespace=kube-system
kubectl delete svc kubernetes-dashboard --namespace=kube-system
kubectl delete -f kubernetes-dashboard.yaml
kubectl replace --force -f ./pod.json # 强制替换,删除后重新创建资源。会导致服务中断。
 
# 交互
kubectl logs nginx-pod                                 # dump 输出 pod 的日志(stdout)
kubectl logs nginx-pod -c my-container                 # dump 输出 pod 中容器的日志(stdout,pod 中有多个容器的情况下使用)
kubectl logs -f nginx-pod                              # 流式输出 pod 的日志(stdout)
kubectl logs -f nginx-pod -c my-container              # 流式输出 pod 中容器的日志(stdout,pod 中有多个容器的情况下使用)
kubectl run -i --tty busybox --image=busybox -- sh  # 交互式 shell 的方式运行 pod
kubectl attach nginx-pod -i                            # 连接到运行中的容器
kubectl port-forward nginx-pod 5000:6000               # 转发 pod 中的 6000 端口到本地的 5000 端口
kubectl exec nginx-pod -- ls /                         # 在已存在的容器中执行命令(只有一个容器的情况下)
kubectl exec nginx-pod -c my-container -- ls /         # 在已存在的容器中执行命令(pod 中有多个容器的情况下)
kubectl top pod POD_NAME --containers               # 显示指定 pod和容器的指标度量
kubectl exec -ti podName /bin/bash     # 进入pod
 
# 调度配置
kubectl cordon k8s-node                                                # 标记 my-node 不可调度
kubectl drain k8s-node                                                 # 清空 my-node 以待维护
kubectl uncordon k8s-node                                              # 标记 my-node 可调度
kubectl top node k8s-node                                              # 显示 my-node 的指标度量
kubectl cluster-info dump                                             # 将当前集群状态输出到 stdout                                    
kubectl cluster-info dump --output-directory=/path/to/cluster-state   # 将当前集群状态输出到 /path/to/cluster-state
#如果该键和影响的污点(taint)已存在,则使用指定的值替换
kubectl taint nodes foo dedicated=special-user:NoSchedule
#查看kubelet进程启动参数
ps -ef | grep kubelet
# 查看日志:
journalctl -u kubelet -f
 
导出配置文件:
  导出proxy
  kubectl get ds -n kube-system -l k8s-app=kube-proxy -o yaml>kube-proxy-ds.yaml
  导出kube-dns
  kubectl get deployment -n kube-system -l k8s-app=kube-dns -o yaml >kube-dns-dp.yaml
  kubectl get services -n kube-system -l k8s-app=kube-dns -o yaml >kube-dns-services.yaml
  导出所有 configmap
  kubectl get configmap -n kube-system -o wide -o yaml > configmap.yaml
 
复杂操作命令:
 删除kube-system 下Evicted状态的所有pod:
kubectl get pods -n kube-system |grep Evicted| awk ‘{print $1}’|xargs kubectl delete pod -n kube-system
以下为维护环境相关命令:
重启kubelet服务
systemctl daemon-reload
systemctl restart kubelet

k8s

安装

1.22.4
https://k8s.easydoc.net/docs/dRiQjyTY/28366845/6GiNOzyZ/nd7yOvdY
https://www.bilibili.com/video/BV1Tg411P7EB?p=2&vd_source=918234aac303a01ae2d14d0251c58d61

minikube

Kubernetes报错

pod名只允许[a-z0-9],用_连接

[root@k8s yaml-demo]# kubectl apply -f mysql-pod-ConfigMap.yaml 
configmap/mysql-config unchanged
The Pod "mysql-pod-ConfigMap" is invalid: metadata.name: Invalid value: "mysql-pod-ConfigMap": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

Kubernetes基础(1)---使用k3s学习

https://docs.rancher.cn/docs/k3s/quick-start/_index

下载

仓库:https://github.com/k3s-io/k3s

v1.25.2+k3s1

image.png
https://github.com/k3s-io/k3s/releases/tag/v1.25.2%2Bk3s1
bash:需要下载对应版本的,在sources node zip里
百度网盘:
链接:https://pan.baidu.com/s/1wjuba_6AD665qNy4Gx9XDw?pwd=1111
提取码:1111

错误

sh文件报错

注意不要在windows下编辑脚本文件,否则经常会遇到这种问题。
:::info
-bash: ./install.sh: /bin/sh^M: 坏的解释器: 没有那个文件或目录
:::
解决方法
脚本文件保存时使用了DOS格式,用DOS2UNIX转为UNIX格式,也可以用vim打开,用:set ff=unix转换。
:::info
代码:
sed -i 's/\r$//' server. sh

还 可以用 vim 打开文件,然后执行冒号命令:

代码:
:set ff=unix
:wq
:::
image.png

启动安装脚本失败

可能时间不统一,可能是保存的快照,建议与阿里云的服务器时间同步

查看时间
date -R
yum install ntpdate
timedatectl set-timezone Asia/Shanghai 
ntpdate ntp1.aliyun.com
date -R

同步阿里云时间
1、查看当前服务器时间
# date -R
Mon, 27 Apr 2020 10:41:54 +0800
2、安装ntpdate服务
# yum install ntpdate
Loaded plugins: fastestmirror
Determining fastest mirrors
3、直接用域名同步中国上海时间 是阿里云的服务器
# timedatectl set-timezone Asia/Shanghai 
# ntpdate ntp1.aliyun.com
27 Apr 10:45:42 ntpdate[6028]: step time server 120.25.115.20 offset 190.621216 sec
4、查看新时间是否已同步
# date -R
Mon, 27 Apr 2020 10:45:51 +0800

执行安装脚本搭建集群

:::info
注意

  • 三个服务器的hosts和hostname都需要修改
  • 时间需要一致
    • 方法:同步阿里云服务器
  • 主节点和工作节点的安装命令不一样,是先安装主节点,然后获取token,用这个token去搭建工作节点
  • sh不要在windows打开
    • 方法:去下载当前版本资源包,然后把sh文件上传
      :::
      先关防火墙
systemctl disable firewalld --now

yum install -y container-selinux selinux-policy-base
yum install -y https://rpm.rancher.io/k3s/latest/common/centos/7/noarch/k3s-selinux-0.2-1.el7_8.noarch.rpm

如果k3s-airgap-images-amd64.tar是.gz压缩的就复制.gz的

mv k3s /usr/local/bin
chmod +x /usr/local/bin/k3s
mkdir -p /var/lib/rancher/k3s/agent/images/
cp k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
#修改权限
chmod +x install.sh

#离线安装主节点
INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh

出现下面这个才是成功,否则失败
image.png
主节点k8s

[root@k8s home]# kubectl get node
NAME   STATUS   ROLES                  AGE   VERSION
k8s    Ready    control-plane,master   35m   v1.25.2+k3s1
[root@k8s home]# cat /var/lib/rancher/k3s/server/node-token
K10ed7f6fde96c1141eb8b5cc13d019ca9e98a91716ed103121767d9ecbfd46eec0::server:43abb138875740157821f3fbe2f37ed3


kubectl get node
cat /var/lib/rancher/k3s/server/node-token

工作节点k8s2 k8s3安装,如果工作节点没有设置K3S_URL和K3S_TOKEN,那么就是一个主节点

INSTALL_K3S_SKIP_DOWNLOAD=true \
K3S_URL=https://192.168.80.15:6443 \
K3S_TOKEN=K10ed7f6fde96c1141eb8b5cc13d019ca9e98a91716ed103121767d9ecbfd46eec0::server:43abb138875740157821f3fbe2f37ed3 \
./install.sh



如果你执行了 INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh
那么该节点是主节点,想成为工作节点,需要卸载k3s,然后重新安装步骤

1.卸载
要从 server 节点卸载 K3s,请运行:
/usr/local/bin/k3s-uninstall.sh

要从 agent 节点卸载 K3s,请运行:
/usr/local/bin/k3s-agent-uninstall.sh

2.安装
yum install -y https://rpm.rancher.io/k3s/latest/common/centos/7/noarch/k3s-selinux-0.2-1.el7_8.noarch.rpm
mv k3s /usr/local/bin
chmod +x /usr/local/bin/k3s
mkdir -p /var/lib/rancher/k3s/agent/images/
cp k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
#修改权限
chmod +x install.sh

3.设置为工作节点安装,记得是主节点的ip和token,是https
INSTALL_K3S_SKIP_DOWNLOAD=true \
K3S_URL=https://192.168.80.15:6443 \
K3S_TOKEN=K10ed7f6fde96c1141eb8b5cc13d019ca9e98a91716ed103121767d9ecbfd46eec0::server:43abb138875740157821f3fbe2f37ed3 \
./install.sh

工作节点成功界面,同时主节点可以发现
image.png
主节点
image.png

镜像加速

在学习k3s前需要镜像加速k3s。
由于kubernetes从V1.24版本开始默认使用**containerd**,需要修改**containerd**的配置文件,才能让Pod的镜像使用镜像加速器。
配置文件路径一般为**/etc/containerd/config.toml**,详见阿里云镜像加速
K3s 会自动生成containerd的配置文件/var/lib/rancher/k3s/agent/etc/containerd/config.toml,不要直接修改这个文件,k3s重启后修改会丢失。
查看containerd的配置文件位置
image.png
containerd的配置文件,但是不要直接修改,k3s重启后修改会丢失
image.png

k3s配置镜像

为了简化配置,K3s 通过/etc/rancher/k3s/registries.yaml文件来配置镜像仓库,K3s会在启动时检查这个文件是否存在。
我们需要在每个节点上新建/etc/rancher/k3s/registries.yaml文件,

vim /etc/rancher/k3s/registries.yaml


工作节点没有该路径/etc/rancher/k3s,需要手动创建
mkdir /etc/rancher/k3s
vim /etc/rancher/k3s/registries.yaml

配置内容如下:这个是可以的

cat > /etc/rancher/k3s/registries.yaml <<EOF
mirrors:
  docker.io:
    endpoint:
      - "https://jgsi1qrf.mirror.aliyuncs.com"
      - "http://hub-mirror.c.163.com"
      - "https://docker.mirrors.ustc.edu.cn"
      - "https://registry.docker-cn.com"
EOF

下面两个试的不行
中科院的镜像
https://cmcc.mirrors.ustc.edu.cn/

# 在 config.toml.tmpl 文件中添加
[plugins.cri.registry.mirrors]
  [plugins.cri.registry.mirrors."docker.io"]
    endpoint = ["https://docker.mirrors.ustc.edu.cn"]

这个网站在阿里云搜索容器镜像服务

mirrors:
  docker.io:
    endpoint:
      - "https://docker.mirrors.ustc.edu.cn"

配置后,重启主节点、工作节点并查看是否生效

systemctl restart k3s
systemctl restart k3s-agent

cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml

发现成功
image.png

容器与镜像

容器运行时接口(CRI)

Kubelet运行在每个节点(Node)上,用于管理和维护Pod和容器的状态。
容器运行时接口(CRI)是kubelet 和容器运行时之间通信的主要协议。它将 Kubelet 与容器运行时解耦,理论上,实现了CRI接口的容器引擎,都可以作为kubernetes的容器运行时。

Docker没有实现(CRI)接口,Kubernetes使用**dockershim**来兼容docker。
自V1.24版本起,Dockershim 已从 Kubernetes 项目中移除。

crictl是一个兼容CRI的容器运行时命令,他的用法跟docker命令一样,可以用来检查和调试底层的运行时容器。

crictl pull mysql:5.7-debian
crictl images

在一些局域网环境下,我们没法通过互联网拉取镜像,可以手动的导出、导入镜像。ss
crictl命令没有导出、导入镜像的功能。
需要使用**ctr**命令导出、导入镜像,它是containerd的命令行接口。

POD使用

POD的介绍

可能遇到的情况

如果创建完查看一直是0/1,需要查看是否打开服务器,如果都打开了,等待一下,可能是首次创建或网速不好
image.png
需要查看集群分配的服务器是否打开---k8s3
image.png
如果搭建了集群,一定要开启所有集群后在创建,否则分配到未打开的服务器,会卡在那里,先创建后打开服务器发现还是卡着,这时删除pod,然后重新创建。

pod指令

kubectl run mynginx --image=nginx
#在容器中执行,exit退出
kubectl exec mynginx -it -- /bin/bash
# -it 交互模式 
# --rm 退出后删除容器,多用于执行一次性任务或使用客户端
kubectl run mynginx --image=nginx -it --rm -- /bin/bash 

# 查看Pod
kubectl get pod
# 描述
kubectl describe pod mynginx
# 查看Pod的运行日志
kubectl logs mynginx
# 显示pod的IP和运行节点信息
kubectl get pod -owide

# 动态查看,ctrl+c终止
kubectl get pod --watch

# 删除
kubectl delete pod mynginx
# 强制删除
kubectl delete pod mynginx --force

pod讲解

临时进入客户端或者临时pod--

# 创建pod
[root@k8s ~]# kubectl run mynginx --image=nginx
pod/mynginx created


# 查看Pod
[root@k8s ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
mynginx   1/1     Running   0          31m


# 查看Pod -owide
[root@k8s ~]# kubectl get pod -owide
NAME      READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
mynginx   1/1     Running   0          87s   10.42.1.4   k8s3   <none>           <none>


# 查看详细信息
[root@k8s ~]# kubectl describe pod mynginx
Name:             mynginx
Namespace:        default
Priority:         0
Service Account:  default
Node:             k8s3/192.168.80.17
Start Time:       Fri, 09 Dec 2022 11:42:50 +0800
Labels:           run=mynginx
Annotations:      <none>
Status:           Running
IP:               10.42.1.4
IPs:
  IP:  10.42.1.4
Containers:
  mynginx:
    Container ID:   containerd://bc81af72d17d1a325f91aa4b8aba9df2e0df4b39586815143326940cbbd2f863
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:ab589a3c466e347b1c0573be23356676df90cd7ce2dbf6ec332a5f0a8b5e59db
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 09 Dec 2022 11:42:53 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8wqhf (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-8wqhf:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  16s   default-scheduler  Successfully assigned default/mynginx to k8s3
  Normal  Pulling    17s   kubelet            Pulling image "nginx"
  Normal  Pulled     14s   kubelet            Successfully pulled image "nginx" in 2.970890083s
  Normal  Created    14s   kubelet            Created container mynginx
  Normal  Started    14s   kubelet            Started container mynginx


# 查看日志
[root@k8s ~]# kubectl logs mynginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/12/09 03:42:53 [notice] 1#1: using the "epoll" event method
2022/12/09 03:42:53 [notice] 1#1: nginx/1.23.2
2022/12/09 03:42:53 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2022/12/09 03:42:53 [notice] 1#1: OS: Linux 3.10.0-957.el7.x86_64
2022/12/09 03:42:53 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2022/12/09 03:42:53 [notice] 1#1: start worker processes
2022/12/09 03:42:53 [notice] 1#1: start worker process 29
2022/12/09 03:42:53 [notice] 1#1: start worker process 30
2022/12/09 03:42:53 [notice] 1#1: start worker process 31
2022/12/09 03:42:53 [notice] 1#1: start worker process 32
2022/12/09 03:42:53 [notice] 1#1: start worker process 33
2022/12/09 03:42:53 [notice] 1#1: start worker process 34
2022/12/09 03:42:53 [notice] 1#1: start worker process 35
2022/12/09 03:42:53 [notice] 1#1: start worker process 36


# 使用Pod的ip+pod里面运行容器的端口
[root@k8s ~]# curl 10.42.1.4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>



#在容器中执行,exit退出
[root@k8s ~]# kubectl exec mynginx -it -- /bin/bash
root@mynginx:/# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>



# 一次性任务或使用客户端,ping百度成功,ping主机成功
# -it 交互模式 
# --rm 退出后删除容器,多用于执行一次性任务或使用客户端
[root@k8s ~]# kubectl run mytest --image=busybox -it --rm
If you dont see a command prompt, try pressing enter.
/ # curl localhost
sh: curl: not found
/ # ping baidu.com
PING baidu.com (39.156.66.10): 56 data bytes
64 bytes from 39.156.66.10: seq=0 ttl=127 time=20.054 ms
64 bytes from 39.156.66.10: seq=1 ttl=127 time=20.618 ms
64 bytes from 39.156.66.10: seq=2 ttl=127 time=20.949 ms
^C
--- baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 20.054/20.540/20.949 ms
/ # ping 192.168.0.15
PING 192.168.0.15 (192.168.0.15): 56 data bytes
^C
--- 192.168.0.15 ping statistics ---
10 packets transmitted, 0 packets received, 100% packet loss
/ # ping 192.168.80.15
PING 192.168.80.15 (192.168.80.15): 56 data bytes
64 bytes from 192.168.80.15: seq=0 ttl=63 time=0.469 ms
64 bytes from 192.168.80.15: seq=1 ttl=63 time=0.712 ms
64 bytes from 192.168.80.15: seq=2 ttl=63 time=0.486 ms
^C
--- 192.168.80.15 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.469/0.555/0.712 ms
/ # exit
Session ended, resume using 'kubectl attach mytest -c mytest -i -t' command when the pod is running
pod "mytest" deleted

# 查看pod,没有刚才的临时pod
[root@k8s ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
mynginx   1/1     Running   0          14m


# 删除
[root@k8s ~]# kubectl delete pod mynginx
pod "mynginx" deleted
[root@k8s ~]# kubectl get pod
No resources found in default namespace.

# 强制删除
kubectl delete pod mynginx --force

image.png

Deployment(部署)与ReplicaSet(副本集)

Deployment是对ReplicaSet和Pod更高级的抽象。
它使Pod拥有多副本,自愈,扩缩容、滚动升级等能力。
ReplicaSet(副本集)是一个Pod的集合
它可以设置运行Pod的数量,确保任何时间都有指定数量的 Pod 副本在运行。
通常我们不直接使用ReplicaSet,而是在Deployment中声明。

#创建deployment,部署3个运行nginx的Pod
kubectl create deployment nginx-deployment --image=nginx:1.22 --replicas=3
#查看deployment
kubectl get deploy
#查看replicaSet
kubectl get rs 
#删除deployment
kubectl delete deploy nginx-deployment
#将副本数量调整为5
kubectl scale deployment/nginx-deployment --replicas=5
kubectl get deploy
#自动缩放
kubectl autoscale deployment/nginx-auto --min=3 --max=10 --cpu-percent=75 
#查看自动缩放
kubectl get hpa
#删除自动缩放
kubectl delete hpa nginx-deployment
#查看版本和Pod
kubectl get deployment/nginx-deployment -owide
kubectl get pods

#更新容器镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.23
#滚动更新
kubectl rollout status deployment/nginx-deployment
#查看过程
kubectl get rs --watch
#查看历史版本
kubectl rollout history deployment/nginx-deployment
#查看指定版本的信息
kubectl rollout history deployment/nginx-deployment --revision=2
#回滚到历史版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2

创建

[root@k8s ~]# kubectl create deployment nginx-deploy --image=nginx:1.22 --replicas=3
deployment.apps/nginx-deploy created
[root@k8s ~]# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   3/3     3            3           7s
[root@k8s ~]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-855866bb46-dvx8s   1/1     Running   0          15s
nginx-deploy-855866bb46-nvg4n   1/1     Running   0          15s
nginx-deploy-855866bb46-ndl2z   1/1     Running   0          15s
[root@k8s ~]# kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   3         3         3       23s

自愈

删除最后一个pod--ndl2z,发现自动生成一个新的6m6s2

[root@k8s ~]# kubectl delete pod nginx-deploy-855866bb46-ndl2z
pod "nginx-deploy-855866bb46-ndl2z" deleted
[root@k8s ~]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-855866bb46-dvx8s   1/1     Running   0          65s
nginx-deploy-855866bb46-nvg4n   1/1     Running   0          65s
nginx-deploy-855866bb46-6m6s2   1/1     Running   0          4s

扩容

开两个终端,一个动态查看ReplicaSet,另一个修改replicas。
下面是修改前,replicas=3


[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   3         3         3       85s

增加修改

[root@k8s ~]# kubectl scale deploy nginx-deploy --replicas=5
deployment.apps/nginx-deploy scaled

查看之前的终端
[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   3         3         3       85s
nginx-deploy-855866bb46   5         3         3       4m54s
nginx-deploy-855866bb46   5         3         3       4m54s
nginx-deploy-855866bb46   5         5         3       4m54s
nginx-deploy-855866bb46   5         5         4       4m56s
nginx-deploy-855866bb46   5         5         5       4m56s


[root@k8s ~]# kubectl scale deploy nginx-deploy --replicas=3
deployment.apps/nginx-deploy scaled


查看之前的终端
[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   3         3         3       85s
nginx-deploy-855866bb46   5         3         3       4m54s
nginx-deploy-855866bb46   5         3         3       4m54s
nginx-deploy-855866bb46   5         5         3       4m54s
nginx-deploy-855866bb46   5         5         4       4m56s
nginx-deploy-855866bb46   5         5         5       4m56s
nginx-deploy-855866bb46   3         5         5       6m6s
nginx-deploy-855866bb46   3         5         5       6m7s
nginx-deploy-855866bb46   3         3         3       6m7s

自动缩放
自动缩放通过增加和减少副本的数量,以保持所有 Pod 的平均 CPU 利用率不超过 75%。
自动伸缩需要声明Pod的资源限制,同时使用 Metrics Server 服务(K3s默认已安装)。

#自动缩放
kubectl autoscale deployment/nginx-auto --min=3 --max=10 --cpu-percent=75 
#查看自动缩放
kubectl get hpa
#删除自动缩放
kubectl delete hpa nginx-deployment

滚动更新

还是两个终端,
原终端动态查看副本集

[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   3         3         3       3m34s

新建终端,首先查看nginx版本是1.22

[root@k8s ~]# kubectl get deploy -owide
NAME           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES       SELECTOR
nginx-deploy   3/3     3            3           24m   nginx        nginx:1.22   app=nginx-deploy

我们要实现1.22->1.23

[root@k8s ~]# kubectl set image deployment/nginx-deploy nginx=nginx:1.23
deployment.apps/nginx-deploy image updated

查看副本集变化

[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   3         3         3       3m34s
nginx-deploy-7c9c6446b7   1         0         0       0s
nginx-deploy-7c9c6446b7   1         0         0       0s
nginx-deploy-7c9c6446b7   1         1         0       0s
nginx-deploy-7c9c6446b7   1         1         1       1s
nginx-deploy-855866bb46   2         3         3       3m55s
nginx-deploy-7c9c6446b7   2         1         1       1s
nginx-deploy-855866bb46   2         3         3       3m55s
nginx-deploy-7c9c6446b7   2         1         1       1s
nginx-deploy-855866bb46   2         2         2       3m55s
nginx-deploy-7c9c6446b7   2         2         1       1s
nginx-deploy-7c9c6446b7   2         2         2       2s
nginx-deploy-855866bb46   1         2         2       3m56s
nginx-deploy-7c9c6446b7   3         2         2       2s
nginx-deploy-855866bb46   1         2         2       3m56s
nginx-deploy-7c9c6446b7   3         2         2       2s
nginx-deploy-855866bb46   1         1         1       3m56s
nginx-deploy-7c9c6446b7   3         3         2       2s
nginx-deploy-7c9c6446b7   3         3         3       4s
nginx-deploy-855866bb46   0         1         1       3m58s
nginx-deploy-855866bb46   0         1         1       3m58s
nginx-deploy-855866bb46   0         0         0       3m58s

删除,只有未执行的副本集可以删除,执行的删除会自动重建

先查看副本集
[root@k8s ~]# kubectl get rs 
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-7c9c6446b7   3         3         3       55s
nginx-deploy-855866bb46   0         0         0       4m49s


删除两个
[root@k8s ~]# kubectl delete rs nginx-deploy-7c9c6446b7
replicaset.apps "nginx-deploy-7c9c6446b7" deleted
[root@k8s ~]# kubectl delete rs nginx-deploy-855866bb46
replicaset.apps "nginx-deploy-855866bb46" deleted


发现7c的重新搭建了,85的删除后就消失
[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-855866bb46   0         0         0       5m40s
nginx-deploy-7c9c6446b7   3         3         3       24s
nginx-deploy-7c9c6446b7   3         3         3       28s
nginx-deploy-7c9c6446b7   3         0         0       0s
nginx-deploy-7c9c6446b7   3         0         0       0s
nginx-deploy-7c9c6446b7   3         3         0       0s
nginx-deploy-7c9c6446b7   3         3         1       1s
nginx-deploy-7c9c6446b7   3         3         2       1s
nginx-deploy-7c9c6446b7   3         3         3       2s
nginx-deploy-855866bb46   0         0         0       5m59s


[root@k8s ~]# kubectl get rs 
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-7c9c6446b7   3         3         3       4m44s
[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-7c9c6446b7   3         3         3       4m47s

版本回滚

#查看历史版本
kubectl rollout history deployment/nginx-deploy
#查看指定版本的信息
kubectl rollout history deployment/nginx-deploy --revision=2
#回滚到历史版本
kubectl rollout undo deployment/nginx-deploy --to-revision=2

当版本变为1.23后,我们又想回退到1.22,找到对应的历史版本rollout undo即可

[root@k8s ~]# kubectl rollout history deployment/nginx-deploy
deployment.apps/nginx-deploy 
REVISION  CHANGE-CAUSE
9         <none>
10        <none>

[root@k8s ~]# kubectl rollout undo deployment/nginx-deploy --to-revision=9
deployment.apps/nginx-deploy rolled back



[root@k8s ~]# kubectl get rs -owide
NAME                      DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES       SELECTOR
nginx-deploy-7c9c6446b7   3         3         3       23m   nginx        nginx:1.23   app=nginx-deploy,pod-template-hash=7c9c6446b7
nginx-deploy-855866bb46   0         0         0       11m   nginx        nginx:1.22   app=nginx-deploy,pod-template-hash=855866bb46
[root@k8s ~]# kubectl get rs --watch
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-7c9c6446b7   3         3         3       23m
nginx-deploy-855866bb46   0         0         0       12m
nginx-deploy-855866bb46   0         0         0       12m
nginx-deploy-855866bb46   1         0         0       12m
nginx-deploy-855866bb46   1         0         0       12m
nginx-deploy-855866bb46   1         1         0       12m
nginx-deploy-855866bb46   1         1         1       12m
nginx-deploy-7c9c6446b7   2         3         3       24m
nginx-deploy-7c9c6446b7   2         3         3       24m
nginx-deploy-855866bb46   2         1         1       12m
nginx-deploy-7c9c6446b7   2         2         2       24m
nginx-deploy-855866bb46   2         1         1       12m
nginx-deploy-855866bb46   2         2         1       12m
nginx-deploy-855866bb46   2         2         2       12m
nginx-deploy-7c9c6446b7   1         2         2       24m
nginx-deploy-855866bb46   3         2         2       12m
nginx-deploy-7c9c6446b7   1         2         2       24m
nginx-deploy-855866bb46   3         2         2       12m
nginx-deploy-7c9c6446b7   1         1         1       24m
nginx-deploy-855866bb46   3         3         2       12m
nginx-deploy-855866bb46   3         3         3       12m
nginx-deploy-7c9c6446b7   0         1         1       24m
nginx-deploy-7c9c6446b7   0         1         1       24m
nginx-deploy-7c9c6446b7   0         0         0       24m
^C[root@k8s ~]# kubectl get rs -owide
NAME                      DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES       SELECTOR
nginx-deploy-855866bb46   3         3         3       12m   nginx        nginx:1.22   app=nginx-deploy,pod-template-hash=855866bb46
nginx-deploy-7c9c6446b7   0         0         0       24m   nginx        nginx:1.23   app=nginx-deploy,pod-template-hash=7c9c6446b7

Service(服务)

传送门

[root@k8s ~]# kubectl get all
NAME                                READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-855866bb46-8fgzg   1/1     Running   0          10m
pod/nginx-deploy-855866bb46-87scw   1/1     Running   0          10m
pod/nginx-deploy-855866bb46-5rqh4   1/1     Running   0          10m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   39h

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deploy   3/3     3            3           81m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deploy-855866bb46   3         3         3       22m

创建service

ServiceType 取值

  • ClusterIP(默认):将服务公开在集群内部。kubernetes会给服务分配一个集群内部的 IP,集群内的所有主机都可以通过这个Cluster-IP访问服务。集群内部的Pod可以通过service名称访问服务。
  • NodePort:通过每个节点的主机IP 和静态端口(NodePort)暴露服务。 集群的外部主机可以使用节点IP和NodePort访问服务。
  • ExternalName:将集群外部的网络引入集群内部。
  • LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。

ClusterIP

如果不设置ServiceType,默认是ClusterIP
可以在内部主机访问
内部主机可以访问ip+端口
内部主机的pod可以访问service名+端口

[root@k8s ~]# kubectl expose deploy nginx-deploy --name=nginx-service --port=8080 --target-port=80
service/nginx-service exposed
[root@k8s ~]# kubectl get service
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes      ClusterIP   10.43.0.1      <none>        443/TCP    39h
nginx-service   ClusterIP   10.43.65.176   <none>        8080/TCP   7s

NodePort

可以在外部主机访问
主机ip+NodePort

[root@k8s ~]# kubectl expose deploy nginx-deploy --name=nginx-outside --type=NodePort --port=8081 --target-port=80
service/nginx-outside exposed
[root@k8s ~]# kubectl get service
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.43.0.1      <none>        443/TCP          40h
nginx-service   ClusterIP   10.43.65.176   <none>        8080/TCP         40m
nginx-outside   NodePort    10.43.127.65   <none>        8081:32109/TCP   10s

服务器是192.168.80.15,192.168.80.16,192.168.80.17
都可以访问
image.png

访问服务

集群的每个服务器都能访问10.43.65.176:8080,这个是进群内部分配的ip

[root@k8s ~]# curl 10.43.65.176:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

在主机内部可以通过服务名+端口访问,服务器是不能直接访问服务的

[root@k8s ~]# curl nginx-service
curl: (6) Could not resolve host: nginx-service; 未知的错误
[root@k8s ~]# kubectl run test -it --image=nginx:1.22 --rm -- bash
If you dont see a command prompt, try pressing enter.
root@test:/# curl nginx-service:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

查看服务

[root@k8s ~]# kubectl describe service nginx-service
Name:              nginx-service
Namespace:         default
Labels:            app=nginx-deploy
Annotations:       <none>
Selector:          app=nginx-deploy
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.43.65.176
IPs:               10.43.65.176
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.42.0.36:80,10.42.1.26:80,10.42.2.25:80
Session Affinity:  None
Events:            <none>

负载均衡

修改某一个pod的页面为hello,然后多次访问,发现某一次访问到hello

[root@k8s ~]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-855866bb46-8fgzg   1/1     Running   0          59m
nginx-deploy-855866bb46-87scw   1/1     Running   0          59m
nginx-deploy-855866bb46-5rqh4   1/1     Running   0          59m
[root@k8s ~]# kubectl exec -it nginx-deploy-855866bb46-5rqh4 -- bash
root@nginx-deploy-855866bb46-5rqh4:/# cd /usr/share/nginx/html/
root@nginx-deploy-855866bb46-5rqh4:/usr/share/nginx/html# ls
50x.html  index.html
root@nginx-deploy-855866bb46-5rqh4:/usr/share/nginx/html# echo hello > index.html 
root@nginx-deploy-855866bb46-5rqh4:/usr/share/nginx/html# exit
exit
[root@k8s ~]# curl 10.43.65.176:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@k8s ~]# curl 10.43.65.176:8080
hello

Namespace(命名空间)

在微服务的nacos里学习过命名空间,放置不同开发环境的yaml配置文件

介绍

命名空间(Namespace)是一种资源隔离机制,将同一集群中的资源划分为相互隔离的组。
命名空间可以在多个用户之间划分集群资源(通过资源配额)。

  • 例如我们可以设置开发、测试、生产等多个命名空间。

同一命名空间内的资源名称要唯一,但跨命名空间时没有这个要求。
命名空间作用域仅针对带有名字空间的对象,例如 Deployment、Service 等。
这种作用域对集群访问的对象不适用,例如 StorageClass、Node、PersistentVolume 等。
Kubernetes 会创建四个初始命名空间:

  • **default** 默认的命名空间,不可删除,未指定命名空间的对象都会被分配到default中。
  • **kube-system** Kubernetes 系统对象(控制平面和Node组件)所使用的命名空间。
  • **kube-public**** **自动创建的公共命名空间,所有用户(包括未经过身份验证的用户)都可以读取它。通常我们约定,将整个集群中公用的可见和可读的资源放在这个空间中。
  • **kube-node-lease**** ** 租约(Lease)对象使用的命名空间。每个节点都有一个关联的 lease 对象,lease 是一种轻量级资源。lease对象通过发送心跳,检测集群中的每个节点是否发生故障。

使用kubectl get lease -A查看lease对象


使用多个命名空间

  • 命名空间是在多个用户之间划分集群资源的一种方法(通过资源配额)。
    • 例如我们可以设置开发、测试、生产等多个命名空间。
  • 不必使用多个命名空间来分隔轻微不同的资源。
    • 例如同一软件的不同版本: 应该使用标签 来区分同一命名空间中的不同资源。
  • 命名空间适用于跨多个团队或项目的场景。
    • 对于只有几到几十个用户的集群,可以不用创建命名空间。
  • 命名空间不能相互嵌套,每个 Kubernetes 资源只能在一个命名空间中。

管理命名空间

查看命名空间

[root@k8s ~]# kubectl get namespace
NAME              STATUS   AGE
kube-system       Active   44h
default           Active   44h
kube-public       Active   44h
kube-node-lease   Active   44h

查看pod

[root@k8s ~]# kubectl get pod -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS        AGE
kube-system   helm-install-traefik-crd-5zcts            0/1     Completed   0               44h
kube-system   helm-install-traefik-7cp57                0/1     Completed   1               44h
kube-system   svclb-traefik-85e2686f-xqb5n              2/2     Running     6 (3m19s ago)   44h
kube-system   local-path-provisioner-5b5579c644-bd9rr   1/1     Running     4 (3m19s ago)   44h
kube-system   coredns-75fc8f8fff-72r6k                  1/1     Running     3 (3m19s ago)   44h
default       nginx-deploy-855866bb46-5rqh4             1/1     Running     1 (3m19s ago)   5h48m
default       nginx-deploy-855866bb46-8fgzg             1/1     Running     1 (3m7s ago)    5h48m
kube-system   svclb-traefik-85e2686f-x49zf              2/2     Running     6 (3m7s ago)    44h
kube-system   traefik-7d647b7597-frjxv                  1/1     Running     3 (3m19s ago)   44h
kube-system   metrics-server-74474969b-56qk7            1/1     Running     4 (3m19s ago)   44h
default       nginx-deploy-855866bb46-87scw             1/1     Running     2 (47s ago)     5h48m
kube-system   svclb-traefik-85e2686f-l2hf6              2/2     Running     8 (47s ago)     43h

查看lease

[root@k8s ~]# kubectl get lease -A
NAMESPACE         NAME   HOLDER   AGE
kube-node-lease   k8s2   k8s2     43h
kube-node-lease   k8s    k8s      44h
kube-node-lease   k8s3   k8s3     44h

创建命名空间,并部署节点在指定命名空间内

[root@k8s ~]# kubectl create ns develop
namespace/develop created
[root@k8s ~]# kubectl run nginx --image=nginx:1.22 -n=develop
pod/nginx created

查看命名空间的pod

[root@k8s ~]# kubectl get pod -n=develop
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          80s

查看pod,默认是default命名空间下,可以修改默认命名空间为develop

[root@k8s ~]# kubectl get pod
NAME                            READY   STATUS    RESTARTS        AGE
nginx-deploy-855866bb46-5rqh4   1/1     Running   1 (5m38s ago)   5h51m
nginx-deploy-855866bb46-8fgzg   1/1     Running   1 (5m26s ago)   5h51m
nginx-deploy-855866bb46-87scw   1/1     Running   2 (3m6s ago)    5h51m
[root@k8s ~]# kubectl config set-context $(kubectl config current-context) --namespace=develop
Context "default" modified.
[root@k8s ~]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          2m1s

删除命名空间,会清空命名空间下所有内容
如果无法被删除,可能是命名空间下的对象资源处于被占用状态或者错误的状态,需要手动删除对象

[root@k8s ~]# kubectl get namespace
NAME              STATUS   AGE
kube-system       Active   45h
default           Active   45h
kube-public       Active   45h
kube-node-lease   Active   45h
develop           Active   7m22s
[root@k8s ~]# kubectl delete ns develop
namespace "develop" deleted
[root@k8s ~]# kubectl get namespace
NAME              STATUS   AGE
kube-system       Active   45h
default           Active   45h
kube-public       Active   45h
kube-node-lease   Active   45h

声明式对象配置--yaml文件

程度
:::info

  • 有模板
  • 能看懂
  • 能修改
  • 能排错即可
    :::

yaml规范

  • 缩进代表上下级关系
  • 缩进时不允许使用Tab键,只允许使用空格,通常缩进2个空格
  • **:** 键值对,后面必须有空格
  • **-**列表,后面必须有空格
  • **[ ]**数组
  • **#**注释
  • **|** 多行文本块
  • **---**表示文档的开始,多用于分割多个资源对象

使用yaml定义一个Pod

Pod配置模版

vim my-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.22
    ports:
    - containerPort: 80

如果develop命名空间被删除了,记得换回来

[root@k8s home]# kubectl apply -f my-pod.yaml
Error from server (NotFound): error when creating "my-pod.yaml": namespaces "develop" not found
[root@k8s home]# kubectl config set-context $(kubectl config current-context) --namespace=default
Context "default" modified.

创建pod

[root@k8s home]# kubectl apply -f my-pod.yaml
pod/my-nginx created

删除pod

[root@k8s home]# kubectl delete -f my-pod.yaml 
pod "my-nginx" deleted

标签

标签(Labels) 是附加到对象(比如 Pod)上的键值对,用于补充对象的描述信息。
标签使用户能够以松散的方式管理对象映射,而无需客户端存储这些映射。
由于一个集群中可能管理成千上万个容器,我们可以使用标签高效的进行选择和操作容器集合。


  • 键的格式:
    • 前缀(可选)/名称(必须)。
  • 有效名称和值:
    • 必须为 63 个字符或更少(可以为空)
    • 如果不为空,必须以字母数字字符([a-z0-9A-Z])开头和结尾
    • 包含破折号**-**、下划线**_**、点**.**和字母或数字


label配置模版
在yaml配置模板前提上加了一个labels属性
image.png

apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels: #定义Pod标签
    environment: test
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.22
    ports:
    - containerPort: 80
[root@k8s home]# vim label-pod.yaml
[root@k8s home]# kubectl apply -f label-pod.yaml 
pod/label-demo created
[root@k8s home]# kubectl get pod
NAME                            READY   STATUS    RESTARTS      AGE
nginx-deploy-855866bb46-5rqh4   1/1     Running   1 (38m ago)   6h23m
nginx-deploy-855866bb46-8fgzg   1/1     Running   1 (38m ago)   6h23m
nginx-deploy-855866bb46-87scw   1/1     Running   2 (35m ago)   6h23m
label-demo                      1/1     Running   0             4s
[root@k8s home]# kubectl get pod --show-labels
NAME                            READY   STATUS    RESTARTS      AGE     LABELS
nginx-deploy-855866bb46-5rqh4   1/1     Running   1 (38m ago)   6h24m   app=nginx-deploy,pod-template-hash=855866bb46
nginx-deploy-855866bb46-8fgzg   1/1     Running   1 (38m ago)   6h24m   app=nginx-deploy,pod-template-hash=855866bb46
nginx-deploy-855866bb46-87scw   1/1     Running   2 (36m ago)   6h24m   app=nginx-deploy,pod-template-hash=855866bb46
label-demo                      1/1     Running   0             24s     app=nginx,environment=test
[root@k8s home]# kubectl get pod -l app=nginx
NAME         READY   STATUS    RESTARTS   AGE
label-demo   1/1     Running   0          41s
[root@k8s home]# kubectl get pod -l app=nginx
NAME         READY   STATUS    RESTARTS   AGE
label-demo   1/1     Running   0          50s
[root@k8s home]# kubectl get pod -l app=nginx-deploy
NAME                            READY   STATUS    RESTARTS      AGE
nginx-deploy-855866bb46-5rqh4   1/1     Running   1 (39m ago)   6h24m
nginx-deploy-855866bb46-8fgzg   1/1     Running   1 (38m ago)   6h24m
nginx-deploy-855866bb46-87scw   1/1     Running   2 (36m ago)   6h24m
[root@k8s home]# kubectl get pod -l app=nginx,
Error from server (BadRequest): Unable to find "/v1, Resource=pods" that match label selector "app=nginx,", field selector "": found '', expected: identifier after ','
[root@k8s home]# kubectl get pod -l app=nginx
NAME         READY   STATUS    RESTARTS   AGE
label-demo   1/1     Running   0          70s
[root@k8s home]# kubectl get pod -l app=nginx,environment=text
No resources found in default namespace.
[root@k8s home]# kubectl get pod -l app=nginx,environment=test
NAME         READY   STATUS    RESTARTS   AGE
label-demo   1/1     Running   0          79s

选择器--创建service

标签选择器 可以识别一组对象。标签不支持唯一性。
标签选择器最常见的用法是为Service选择一组Pod作为后端。
需要有pod,这里用上一个知识点的label创建的pod
Service配置模版

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector: #与Pod的标签一致
    environment: test
    app: nginx
  ports:
      # 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
    - port: 80
      targetPort: 80
      # 可选字段
      # 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
      nodePort: 30007
[root@k8s home]# vim my-service.yaml
[root@k8s home]# kubectl apply -f my-service.yaml
service/my-service created

[root@k8s home]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.43.0.1       <none>        443/TCP          45h
nginx-service   ClusterIP   10.43.65.176    <none>        8080/TCP         6h27m
nginx-outside   NodePort    10.43.127.65    <none>        8081:32109/TCP   5h47m
my-service      NodePort    10.43.154.163   <none>        80:30007/TCP     9m12s
[root@k8s home]# kubectl describe svc my-service
Name:                     my-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx,environment=test
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.43.154.163
IPs:                      10.43.154.163
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30007/TCP
Endpoints:                10.42.1.33:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
[root@k8s home]# kubectl get pod -l app=nginx -owide
NAME         READY   STATUS    RESTARTS   AGE     IP           NODE   NOMINATED NODE   READINESS GATES
label-demo   1/1     Running   0          2m22s   10.42.1.33   k8s3   <none>           <none>

如果没有对应的pod,
image.png


[root@k8s home]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.43.0.1       <none>        443/TCP          45h
nginx-service   ClusterIP   10.43.65.176    <none>        8080/TCP         6h18m
nginx-outside   NodePort    10.43.127.65    <none>        8081:32109/TCP   5h38m
my-service      NodePort    10.43.154.163   <none>        80:30007/TCP     4s
[root@k8s home]# kubectl describe svc my-service
Name:                     my-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx,environment=test
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.43.154.163
IPs:                      10.43.154.163
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30007/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
[root@k8s home]# kubectl get pod -l app=nginx -owide
No resources found in default namespace.

金丝雀发布

先在小范围公布,然后大范围。
一般情况:先发布v1,然后发布v2,然后扩大v2,缩小v1,直到v1版本全部被替换。

介绍

金丝雀部署(canary deployment)也被称为灰度发布。
早期,工人下矿井之前会放入一只金丝雀检测井下是否存在有毒气体。
采用金丝雀部署,你可以在生产环境的基础设施中小范围的部署新的应用代码。
一旦应用签署发布,只有少数用户被路由到它,最大限度的降低影响。
如果没有错误发生,则将新版本逐渐推广到整个基础设施。
如果没有错误发生,则将新版本逐渐推广到整个基础设施。


image.png

部署过程

image.png

发布第一个版本v1

发布v1版本的应用,镜像使用nginx:1.22,数量为 3。

  • 创建Namespace

Namespace配置模版

  • 创建Deployment

Deployment配置模版

  • 创建外部访问的Service

Service配置模版

apiVersion: v1
kind: Namespace
metadata:
  name: dev
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-v1
  namespace: dev
  labels:
    app: nginx-deployment-v1
spec:
  replicas: 3
  selector:
    matchLabels: # 跟template.metadata.labels一致
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.22
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: canary-demo
  namespace: dev
spec:
  type: NodePort
  selector: # 更Deployment中的selector一致
    app: nginx
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 80
      targetPort: 80
      # Optional field
      # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
      nodePort: 30008

发布第一个版本v1

[root@k8s home]# vim deploy-v1.yaml
[root@k8s home]# kubectl apply -f deploy-v1.yaml 
namespace/dev created
deployment.apps/nginx-deployment-v1 created
service/canary-demo created

查看命名空间的的信息,并访问服务ip,查看服务详情

[root@k8s home]# kubectl get all -n=dev
NAME                                       READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-v1-645549fcf7-r872x   1/1     Running   0          14s
pod/nginx-deployment-v1-645549fcf7-wth5r   1/1     Running   0          14s
pod/nginx-deployment-v1-645549fcf7-rkm5m   1/1     Running   0          14s

NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/canary-demo   NodePort   10.43.139.107   <none>        80:30008/TCP   14s

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment-v1   3/3     3            3           14s

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-v1-645549fcf7   3         3         3       14s
[root@k8s home]# curl 10.43.139.107
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@k8s home]# kubectl describe svc canary-demo -n=dev
Name:                     canary-demo
Namespace:                dev
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.43.139.107
IPs:                      10.43.139.107
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30008/TCP
Endpoints:                10.42.0.49:80,10.42.1.37:80,10.42.2.32:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

发布第二个版本Canary

发布新版本的应用,镜像使用docker/getting-started,数量为 1。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-canary
  namespace: dev
  labels:
    app: nginx-deployment-canary
spec:
  replicas: 1
  selector:
    matchLabels: # 跟template.metadata.labels一致
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        track: canary
    spec:
      containers:
        - name: new-nginx
          image: docker/getting-started
          ports:
            - containerPort: 80

发布第二个版本

[root@k8s home]# vim deploy-canary.yaml
[root@k8s home]# kubectl apply -f deploy-canary.yaml 
deployment.apps/nginx-deployment-canary created

查看命名空间对象,发现创建了
一个新的部署---deployment.apps/nginx-deployment-canary
对应的副本集---replicaset.apps/nginx-deployment-canary-74577469b5
对应运行的pod---pod/nginx-deployment-canary-74577469b5-gnkfw

[root@k8s home]# kubectl get all -n=dev
NAME                                           READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-v1-645549fcf7-r872x       1/1     Running   0          8m59s
pod/nginx-deployment-v1-645549fcf7-wth5r       1/1     Running   0          8m59s
pod/nginx-deployment-v1-645549fcf7-rkm5m       1/1     Running   0          8m59s
pod/nginx-deployment-canary-74577469b5-gnkfw   1/1     Running   0          68s

NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/canary-demo   NodePort   10.43.139.107   <none>        80:30008/TCP   8m59s

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment-v1       3/3     3            3           8m59s
deployment.apps/nginx-deployment-canary   1/1     1            1           68s

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-v1-645549fcf7       3         3         3       8m59s
replicaset.apps/nginx-deployment-canary-74577469b5   1         1         1       68s

查看服务,发现出现了 + 1 more...表示有个新的pod加入到服务中

[root@k8s home]# kubectl describe svc -n=dev
Name:                     canary-demo
Namespace:                dev
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.43.139.107
IPs:                      10.43.139.107
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30008/TCP
Endpoints:                10.42.0.49:80,10.42.1.37:80,10.42.2.32:80 + 1 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

我们多次访问该服务ip,会出现新的页面

[root@k8s home]# curl 10.43.139.107
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=x-ua-compatible content="ie=edge"><meta name=description content="Getting Started with Docker"><script>var anchor=window.location.hash.substr(1);location.href="/tutorial/"+(anchor?"#"+anchor:"")</script><meta http-equiv=refresh content="0; url=/tutorial/"><meta name=robots content=noindex><link href=/tutorial/ rel=canonical><meta name=author content=Docker><meta name=lang:clipboard.copy content="Copy to clipboard"><meta name=lang:clipboard.copied content="Copied to clipboard"><meta name=lang:search.language content=en><meta name=lang:search.pipeline.stopwords content=True><meta name=lang:search.pipeline.trimmer content=True><meta name=lang:search.result.none content="No matching documents"><meta name=lang:search.result.one content="1 matching document"><meta name=lang:search.result.other content="# matching documents"><meta name=lang:search.tokenizer content=[\s\-]+><link rel="shortcut icon" href=assets/images/favicon.png><meta name=generator content="mkdocs-1.2.3, mkdocs-material-4.6.3"><title>Getting Started</title><link rel=stylesheet href=assets/stylesheets/application.adb8469c.css><link rel=stylesheet href=assets/stylesheets/application-palette.a8b3c06d.css><meta name=theme-color content=#2196f3><script src=assets/javascripts/modernizr.86422ebf.js></script><link href=https://fonts.gstatic.com rel=preconnect crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback"><style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style><link rel=stylesheet href=assets/fonts/material-icons.css><link rel=stylesheet href=css/styles.css><link rel=stylesheet href=css/dark-mode.css></head> <body dir=ltr data-md-color-primary=blue data-md-color-accent=blue> <svg class=md-svg> <defs> <svg xmlns=http://www.w3.org/2000/svg width=416 height=448 viewbox="0 0 416 448" id=__github><path fill=currentColor d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg> </defs> </svg> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay data-md-component=overlay for=__drawer></label> <header class=md-header data-md-component=header> <nav class="md-header-nav md-grid"> <div class=md-flex> <div class="md-flex__cell md-flex__cell--shrink"> <a href=. title="Getting Started" aria-label="Getting Started" class="md-header-nav__button md-logo"> <img alt=logo src=images/docker-labs-logo.svg width=24 height=24> </a> </div> <div class="md-flex__cell md-flex__cell--shrink"> <label class="md-icon md-icon--menu md-header-nav__button" for=__drawer></label> </div> <div class="md-flex__cell md-flex__cell--stretch"> <div class="md-flex__ellipsis md-header-nav__title" data-md-component=title> <span class=md-header-nav__topic> Getting Started </span> <span class=md-header-nav__topic> Home </span> </div> </div> <div class="md-flex__cell md-flex__cell--shrink"> <label class="md-icon md-icon--search md-header-nav__button" for=__search></label> <div class=md-search data-md-component=search role=dialog> <label class=md-search__overlay for=__search></label> <div class=md-search__inner role=search> <form class=md-search__form name=search> <input type=text class=md-search__input aria-label=search name=query placeholder=Search autocapitalize=off autocorrect=off autocomplete=off spellcheck=false data-md-component=query data-md-state=active> <label class="md-icon md-search__icon" for=__search></label> <button type=reset class="md-icon md-search__icon" data-md-component=reset tabindex=-1> &#xE5CD; </button> </form> <div class=md-search__output> <div class=md-search__scrollwrap data-md-scrollfix> <div class=md-search-result data-md-component=result> <div class=md-search-result__meta> Type to start searching </div> <ol class=md-search-result__list></ol> </div> </div> </div> </div> </div> </div> <div class="md-flex__cell md-flex__cell--shrink"> <div class=md-header-nav__source> <a href=https://github.com/docker/getting-started title="Go to repository" class=md-source data-md-source=github> <div class=md-source__icon> <svg viewbox="0 0 24 24" width=24 height=24> <use xlink:href=#__github width=24 height=24></use> </svg> </div> <div class=md-source__repository> docker/getting-started </div> </a> </div> </div> </div> </nav> </header> <div class=md-container> <main class=md-main role=main> <div class="md-main__inner md-grid" data-md-component=container> <div class="md-sidebar md-sidebar--primary" data-md-component=navigation> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--primary" data-md-level=0> <label class="md-nav__title md-nav__title--site" for=__drawer> <a href=. title="Getting Started" class="md-nav__button md-logo"> <img alt=logo src=images/docker-labs-logo.svg width=48 height=48> </a> Getting Started </label> <div class=md-nav__source> <a href=https://github.com/docker/getting-started title="Go to repository" class=md-source data-md-source=github> <div class=md-source__icon> <svg viewbox="0 0 24 24" width=24 height=24> <use xlink:href=#__github width=24 height=24></use> </svg> </div> <div class=md-source__repository> docker/getting-started </div> </a> </div> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=tutorial/ title="Getting Started" class=md-nav__link> Getting Started </a> </li> <li class=md-nav__item> <a href=tutorial/our-application/ title="Our Application" class=md-nav__link> Our Application </a> </li> <li class=md-nav__item> <a href=tutorial/updating-our-app/ title="Updating our App" class=md-nav__link> Updating our App </a> </li> <li class=md-nav__item> <a href=tutorial/sharing-our-app/ title="Sharing our App" class=md-nav__link> Sharing our App </a> </li> <li class=md-nav__item> <a href=tutorial/persisting-our-data/ title="Persisting our DB" class=md-nav__link> Persisting our DB </a> </li> <li class=md-nav__item> <a href=tutorial/using-bind-mounts/ title="Using Bind Mounts" class=md-nav__link> Using Bind Mounts </a> </li> <li class=md-nav__item> <a href=tutorial/multi-container-apps/ title="Multi-Container Apps" class=md-nav__link> Multi-Container Apps </a> </li> <li class=md-nav__item> <a href=tutorial/using-docker-compose/ title="Using Docker Compose" class=md-nav__link> Using Docker Compose </a> </li> <li class=md-nav__item> <a href=tutorial/image-building-best-practices/ title="Image Building Best Practices" class=md-nav__link> Image Building Best Practices </a> </li> <li class=md-nav__item> <a href=tutorial/what-next/ title="What Next?" class=md-nav__link> What Next? </a> </li> </ul> </nav> </div> </div> </div> <div class=md-content> <article class="md-content__inner md-typeset"> <h1>Home</h1> </article> </div> </div> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-footer-copyright> <div class=md-footer-copyright__highlight> Copyright &copy; 2020 Docker </div> powered by <a href=https://www.mkdocs.org target=_blank rel=noopener>MkDocs</a> and <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs</a> </div> <div class=md-footer-social> <link rel=stylesheet href=assets/fonts/font-awesome.css> <a href=https://github.com/docker/getting-started target=_blank rel=noopener title=github-alt class="md-footer-social__link fa fa-github-alt"></a> </div> </div> </div> </footer> </div> <script src=assets/javascripts/application.c33a9706.js></script> <script>app.initialize({version:"1.2.3",url:{base:"."}})</script> </body> </html>

稳定后调整比例

当稳定后可以将第二个版本的pod从1变为3,扩大试用范围,将部署的v2版本数量调整为3,v1和v2的数量都是3个。

[root@k8s home]# kubectl scale deploy nginx-deployment-canary --replicas=3 -n=dev
deployment.apps/nginx-deployment-canary scaled

再次查看发现新版本pod变为3

[root@k8s home]# kubectl get all -n=dev
NAME                                           READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-v1-645549fcf7-r872x       1/1     Running   0          15m
pod/nginx-deployment-v1-645549fcf7-wth5r       1/1     Running   0          15m
pod/nginx-deployment-v1-645549fcf7-rkm5m       1/1     Running   0          15m
pod/nginx-deployment-canary-74577469b5-gnkfw   1/1     Running   0          7m11s
pod/nginx-deployment-canary-74577469b5-z2fhp   1/1     Running   0          23s
pod/nginx-deployment-canary-74577469b5-k5hxd   1/1     Running   0          23s

NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/canary-demo   NodePort   10.43.139.107   <none>        80:30008/TCP   15m

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment-v1       3/3     3            3           15m
deployment.apps/nginx-deployment-canary   3/3     3            3           7m11s

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-v1-645549fcf7       3         3         3       15m
replicaset.apps/nginx-deployment-canary-74577469b5   3         3         3       7m11s

下线旧版本

最后下线所有v1版本,所有服务升级为v2版本。
下线v1--replicas=0

[root@k8s home]# kubectl scale deploy nginx-deployment-v1 --replicas=0 -n=dev
deployment.apps/nginx-deployment-v1 scaled

查看pod,发现v1版本下线了,此时都行线上都是新版本

[root@k8s home]# kubectl get all -n=dev
NAME                                           READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-canary-74577469b5-gnkfw   1/1     Running   0          28m
pod/nginx-deployment-canary-74577469b5-z2fhp   1/1     Running   0          21m
pod/nginx-deployment-canary-74577469b5-k5hxd   1/1     Running   0          21m

NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/canary-demo   NodePort   10.43.139.107   <none>        80:30008/TCP   36m

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment-canary   3/3     3            3           28m
deployment.apps/nginx-deployment-v1       0/0     0            0           36m

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-canary-74577469b5   3         3         3       28m
replicaset.apps/nginx-deployment-v1-645549fcf7       0         0         0       36m

清空环境

kubectl delete all --all -n=dev

局限性

按照 Kubernetes 默认支持的这种方式进行金丝雀发布,有一定的局限性:

  • 不能根据用户注册时间、地区等请求中的内容属性进行流量分配
  • 同一个用户如果多次调用该 Service,有可能第一次请求到了旧版本的 Pod,第二次请求到了新版本的 Pod

在 Kubernetes 中不能解决上述局限性的原因是:Kubernetes Service 只在 TCP 层面解决负载均衡的问题,并不对请求响应的消息内容做任何解析和识别。如果想要更完善地实现金丝雀发布,可以考虑Istio灰度发布。

Kubernetes基础(2)---使用k3s学习

运行有状态的应用

创建MySQL数据库

官方模板

首先从官网拿案例

apiVersion: v1
kind: Pod
metadata:
  name: envar-demo
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: envar-demo-container
    image: gcr.io/google-samples/node-hello:1.0
    env:
    - name: DEMO_GREETING
      value: "Hello from the environment"
    - name: DEMO_FAREWELL
      value: "Such a sweet sorrow"

简单修改一下

apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7

设置密码

然后开始配置密码,数据持久化,端口
MySQL镜像里可以看到设置密码的变量,image.png

apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"

数据在容器中很容易丢失,无法保存,这里可以用挂载卷来实现保存到主机里


  • 挂载卷
    • 将数据存储在容器中,一旦容器被删除,数据也会被删除。
    • 将数据存储到卷(Volume)中,删除容器时,卷不会被删除。

hostPath卷

**hostPath **卷将主机节点上的文件或目录挂载到 Pod 中。
hostPath配置示例
官方已经介绍的很清楚了,我们这里需要注意的是hostPath 卷指定 type。
官方给了7个type,我们一般用的前5个
image.png
hostPath的type值:

DirectoryOrCreate 目录不存在则自动创建。
Directory 挂载已存在目录。不存在会报错。
FileOrCreate 文件不存在则自动创建。
不会自动创建文件的父目录,必须确保文件路径已经存在。
File 挂载已存在的文件。不存在会报错。
Socket 挂载 UNIX 套接字。例如挂载/var/run/docker.sock进程

把官方示例中我们需要的部分添加进来并修改
image.png
容器内的目录可以根据mysql的docker介绍
image.png

apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"
      volumeMounts:
        - mountPath: /var/lib/mysql #容器中的目录
          name: data-volume
  volumes:
    - name: data-volume
      hostPath:
        # directory location on host
        path: /home/mysql/data
        # this field is optional
        type: DirectoryOrCreate

:::info
注意:hostPath 仅用于在单节点集群上进行开发和测试,不适用于多节点集群;
例如,当Pod被重新创建时,可能会被调度到与原先不同的节点上,导致新的Pod没有数据。
在多节点集群使用本地存储,可以使用local卷。
:::
启动容器

[root@k8s mysql]# kubectl apply -f mysql-pod.yaml 
pod/mysql-pod created


[root@k8s mysql]# kubectl get pod -owide
NAME        READY   STATUS    RESTARTS   AGE     IP           NODE   NOMINATED NODE   READINESS GATES
mysql-pod   1/1     Running   0          2m41s   10.42.2.37   k8s2   <none>           <none>


[root@k8s mysql]# cd /home/mysql/data
-bash: cd: /home/mysql/data: 没有那个文件或目录

发现没有该目录,因为他创建到k8s2的主机里了
去k8s2主机查看,发现文件创建成功

[root@k8s2 ~]# cd /home/mysql/data
[root@k8s2 data]# ls
auto.cnf    client-cert.pem  ibdata1      ibtmp1              private_key.pem  server-key.pem
ca-key.pem  client-key.pem   ib_logfile0  mysql               public_key.pem   sys
ca.pem      ib_buffer_pool   ib_logfile1  performance_schema  server-cert.pem

可以进入容器使用mysql

[root@k8s ~]# kubectl get pod
NAME        READY   STATUS    RESTARTS        AGE
mysql-pod   1/1     Running   1 (2m54s ago)   2d8h
[root@k8s ~]# kubectl get pod -owide
NAME        READY   STATUS    RESTARTS        AGE    IP           NODE   NOMINATED NODE   READINESS GATES
mysql-pod   1/1     Running   1 (2m59s ago)   2d8h   10.42.2.39   k8s2   <none>           <none>
[root@k8s ~]# kubectl exec mysql-pod -it -- /bin/bash
root@mysql-pod:/# ls
bin   dev			  entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint-initdb.d  etc		 lib   media  opt  root  sbin  sys  usr
root@mysql-pod:/# mysql -uroot -p123456 
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> exit;
Bye
root@mysql-pod:/# exit
exit
[root@k8s ~]# 

ConfigMap与Secret

参考文档:
https://kubernetes.io/zh-cn/docs/concepts/configuration/
https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/
https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/

ConfigMap

:::info
在Docker和nginx中,我们一般通过绑定挂载的方式将配置文件挂载到容器里。
在Kubernetes集群中,容器可能被调度到任意节点,配置文件需要能在集群任意节点上访问、分发和更新。
:::
configMap如同名字所说,

  • 配置映射,就是用来保存映射的配置,需要注意的是非加密的,如果需要加密需要用Secret
  • ConfigMap 将环境配置信息与 容器镜像 解耦,便于配置的修改。
    • 当主机的配置文件修改,对应容器的配置文件也会修改
    • 类似微服务的nacos的配置中心
  • 不能超过1MB,不适合保存数据,可用于简单的配置文件映射
    • 超出此限制,需要考虑挂载存储卷或者访问文件存储服务。

ConfigMap用法

流程

  • 配置configmap
  • 使用volumes注入
  • 将注入name和容器路径绑定

ConfigMap配置示例
先创建一个配置文件mysql-pod-ConfigMap.yaml,先把MySQL的容器配置文件复制过来,只修改pod的name即可
然后拿官方文档的示例进行修改,然后加到mysql的容器配置里

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  # 这里写conf.d的配置
  mysql.cnf: |
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_general_ci
    init-connect='SET NAMES utf8mb4'

    [client]
    default-character-set=utf8mb4

    [mysql]
    default-character-set=utf8mb4

加到mysql-pod-ConfigMap.yaml里,注意---分割开

apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-configmap
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"
      volumeMounts:
        - mountPath: /var/lib/mysql #容器中的目录
          name: data-volume
  volumes:
    - name: data-volume
      hostPath:
        # directory location on host
        path: /home/mysql/data
        # this field is optional
        type: DirectoryOrCreate
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  # 这里写conf.d的配置
  mysql.cnf: |
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_general_ci
    init-connect='SET NAMES utf8mb4'

    [client]
    default-character-set=utf8mb4

    [mysql]
    default-character-set=utf8mb4

同样在官方文档看到需要用卷来注入配置文件,
image.png
同时在volumeMounts添加绑定,让该配置文件和容器的/etc/mysql/conf.d绑定,这个可以在mysql里看到

apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-configmap
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"
      volumeMounts:
        - mountPath: /var/lib/mysql
          name: data-volume
        - mountPath: /etc/mysql/conf.d
          name: conf-volume
          readOnly: true
  volumes:
    - name: conf-volume
      configMap:
        name: mysql-config
    - name: data-volume
      hostPath:
        # directory location on host
        path: /home/mysql/data
        # this field is optional
        type: DirectoryOrCreate
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  mysql.cnf: |
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_general_ci
    init-connect='SET NAMES utf8mb4'

    [client]
    default-character-set=utf8mb4

    [mysql]
    default-character-set=utf8mb4

此时就可以重新启动该服务了,在启动前我们先看一下之前的配置

[root@k8s ~]# kubectl exec mysql-pod -it -- /bin/bash
root@mysql-pod:/# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

重新通过新的配置启动,首先查看我们定义的mysql-config的内容

[root@k8s yaml-demo]# kubectl apply -f mysql-pod-ConfigMap.yaml 
pod/mysql-pod-configmap created
configmap/mysql-config unchanged

[root@k8s yaml-demo]# kubectl describe cm mysql-config
Name:         mysql-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
mysql.cnf:
----
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4


BinaryData
====

Events:  <none>

因为我们通过ConfigMap修改了mysql容器的配置文件,
所以这个配置文件启动的容器mysql编码应该都是utf-8,发现确实如此

[root@k8s yaml-demo]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
mysql-pod-configmap   1/1     Running   0          2m14s

[root@k8s yaml-demo]# kubectl exec mysql-pod-configmap -it -- /bin/bash
root@mysql-pod-configmap:/# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

接着我们可以使用配置映射的修改功能,修改mysql-config的内容,然后查看容器的配置是否动态修改了

[root@k8s yaml-demo]# kubectl edit cm mysql-config
configmap/mysql-config edited
可以加个注释
# this is a new comment


[root@k8s yaml-demo]# kubectl exec mysql-pod-configmap -it -- /bin/bash
root@mysql-pod-configmap:/# cat /etc/mysql/conf.d/mysql.cnf 
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'
# this is a new comment
[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

Secret

k8s-secret
k8s-使用kubectl管理secret
k8s-secret-spec
阿里云-应用配置管理
与docker的docker Secrets相对应

  • Secret 用于保存机密数据的对象。一般由于保存密码令牌或密钥等。
  • data字段用来存储 base64 编码数,不允许使用明文
  • stringData存储未编码的字符串。
  • Secret 意味着你不需要在应用程序代码中包含机密数据,减少机密数据(如密码)泄露的风险。
  • Secret 可以用作环境变量、命令行参数或者存储卷文件。

Secret用法

还是先复制一份上面的文件命名为mysql-pod-ConfigMap-Secret.yaml
并修改name
因为Secret是存储base64 编码数据,不允许使用明文
所以在配置前先加密mysql密码

# base64加密
echo -n '123456' | base64
# base64解密
echo 'MTIzNDU2' | base64 --decode

-n表示忽略回车符
不加-n
[root@k8s yaml-demo]# echo '123456' | base64
MTIzNDU2Cg==
[root@k8s yaml-demo]# echo 'Cg==' | base64 --decode

[root@k8s yaml-demo]# 
[root@k8s yaml-demo]# echo '1234567' | base64
MTIzNDU2Nwo=
[root@k8s yaml-demo]# echo -n '1234567' | base64
MTIzNDU2Nw==

然后通过官方文档来添加Secret配置,只需要修改name和对应的PASSWORD,
USER_NAME这里就不需要加密了,不用Secret保存
Secret配置示例

apiVersion: v1
kind: Secret
metadata:
  name: mysql-password
type: Opaque
data:
  PASSWORD: MTIzNDU2

然后修改容器的mysql设置

用框中内容替换原来mysql密码value的地方
image.png

apiVersion: v1
kind: Secret
metadata:
  name: mysql-password
type: Opaque
data:
  PASSWORD: MTIzNDU2
---
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-secret
  labels:
    app: mysql
spec:
  containers:
    - name: mysql
      image: mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
          # value: "123456"
          valueFrom:
            secretKeyRef:
              name: mysql-password
              key: PASSWORD
              optional: false # 此值为默认值;表示secret已经存在了
      volumeMounts:
        - mountPath: /var/lib/mysql #容器中的目录
          name: data-volume
        - mountPath: /etc/mysql/conf.d
          name: conf-volume
          readOnly: true
  volumes:
    # 注入ConfigMap
    - name: conf-volume
      configMap:
        name: mysql-config
    - name: data-volume
      hostPath:
        # directory location on host
        path: /home/mysql/data
        # this field is optional
        type: DirectoryOrCreate
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  # 这里写conf.d的配置
  mysql.cnf: |
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_general_ci
    init-connect='SET NAMES utf8mb4'

    [client]
    default-character-set=utf8mb4

    [mysql]
    default-character-set=utf8mb4

启动,通过123456登陆成功

[root@k8s yaml-demo]# kubectl apply -f mysql-pod-ConfigMap-Secret.yaml 
secret/mysql-password created
pod/mysql-pod-secret created
configmap/mysql-config configured

[root@k8s yaml-demo]# kubectl get pod
NAME               READY   STATUS    RESTARTS   AGE
mysql-pod-secret   1/1     Running   0          11s
[root@k8s yaml-demo]# kubectl exec mysql-pod-secret -it -- /bin/bash
root@mysql-pod-secret:/# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> exit

查看secret配置,发现加密数据是不显示的,但是edit和get加上权限是可以明文查看的

[root@k8s yaml-demo]# kubectl describe secret/mysql-password
Name:         mysql-password
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
PASSWORD:  6 bytes


[root@k8s yaml-demo]# kubectl get secret mysql-password -o yaml
apiVersion: v1
data:
  PASSWORD: MTIzNDU2
kind: Secret
metadata:
  creationTimestamp: "2022-12-14T12:58:57Z"
  name: mysql-password
  namespace: default
  resourceVersion: "24646"
  uid: f9acb285-812a-4c58-bbc2-048de72980bd
type: Opaque
[root@k8s yaml-demo]# kubectl edit secret/mysql-password
Edit cancelled, no changes made.

:::info
注意:环境变量使用secret,

  • 当secret使用edit修改后,环境变量不会自动更改,千万不要使用这个,会导致密码永远无法改变
  • 直接通过yaml重启也不行

需要在删除原pod后,上传新的yaml,然后启动新pod
如果在secret和configmap还启动的情况下修改yaml,k8s会在主机生成一种yaml,
导致密码一直不变,
:::
几个注意事项
:::info

  • 直接删除节点,你创建的secret和configmap是还在的
  • 在secret、pod启动的时候,不要修改yaml,不要edit修改secret
    :::
[root@k8s yaml-demo]# kubectl delete pod mysql-pod-secret
pod "mysql-pod-secret" deleted
[root@k8s yaml-demo]# kubectl get secret
NAME             TYPE     DATA   AGE
mysql-password   Opaque   1      7m1s
[root@k8s yaml-demo]# kubectl get configmap
NAME               DATA   AGE
kube-root-ca.crt   1      6d1h
mysql-config       1      8m7s

先说正确的流程,删除后修改yaml,然后启动

kubectl delete pod mysql-pod-secret
kubectl delete secret mysql-password
kubectl delete cm mysql-config

vim mysql-pod-ConfigMap-Secret.yaml 
kubectl apply -f mysql-pod-ConfigMap-Secret.yaml

这时启动,一般会出现这个,那是容器在下载对应的镜像,和第一次启动容器的情况一致
[root@k8s yaml]# kubectl exec mysql-pod-secret -it -- /bin/bash
error: unable to upgrade connection: container not found ("mysql")

如果想使用replace替换,需要是新建的yaml,不能直接修改原yaml

kubectl apply -f mysql-pod-ConfigMap-Secret.yaml
vim mysql-pod-ConfigMap-Secrets.yaml 
kubectl replace --force -f mysql-pod-ConfigMap-Secrets.yaml 

失败案例一--直接edit---导致secret永远无法修改

修改mysql密码123456变为1234567,然后edit修改,发现没有动态修改,
这种情况与configmap一样yaml文件也不会被修改

[root@k8s yaml-demo]# echo -n '1234567' | base64
MTIzNDU2Nw==
[root@k8s yaml-demo]# kubectl edit secret/mysql-password
secret/mysql-password edited


PASSWORD: MTIzNDU2
改为
PASSWORD: MTIzNDU2Nw==

[root@k8s yaml-demo]# kubectl exec mysql-pod-secret -it -- /bin/bash
root@mysql-pod-secret:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

失败案例二-修改原yaml、replace重启

不要在第一种失败案例的基础上尝试,因为第一种失败案例导致密码已经无法修改了
我们重启pod,因为我们是yaml启动,
所以修改yaml后,直接使用 kubectl replace --force -f xxx.yaml 来强制替换Pod 的 API 对象,从而达到重启的目的。
:::info
这里如果是在原yaml修改的会导致密码直接变成root了,
如果是用新建的yaml启动会成功修改密码
:::
发现mysql密码只能用root登录了

[root@k8s yaml-demo]# kubectl replace --force -f mysql-pod-ConfigMap-Secret.yaml 
secret "mysql-password" deleted
pod "mysql-pod-secret" deleted
configmap "mysql-config" deleted
secret/mysql-password replaced
pod/mysql-pod-secret replaced
configmap/mysql-config replaced
[root@k8s yaml-demo]# kubectl exec mysql-pod-secret -it -- /bin/bash
root@mysql-pod-secret:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

成功案例一-删除、修改、启动

应该先删除,然后修改并启动。

[root@k8s yaml-demo]# kubectl delete pod mysql-pod-secret
pod "mysql-pod-secret" deleted
[root@k8s yaml-demo]# kubectl delete secret mysql-password
secret "mysql-password" deleted
[root@k8s yaml-demo]# kubectl delete cm mysql-config
configmap "mysql-config" deleted
[root@k8s yaml-demo]# kubectl apply -f mysql-pod-ConfigMap-Secret.yaml 
secret/mysql-password created
pod/mysql-pod-secret created
configmap/mysql-config created
[root@k8s yaml-demo]# kubectl exec mysql-pod-secret -it -- /bin/bash
error: unable to upgrade connection: container not found ("mysql")

root@mysql-pod-secret:/# mysql -uroot -p1234567
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

成功案例二-新建、替换

新建一个yaml文件,mysql-pod-ConfigMap-Secrets.yaml,只修改密码root变为123456

[root@k8s yaml]# kubectl apply -f mysql-pod-ConfigMap-Secret.yaml
secret/mysql-password created
pod/mysql-pod-secret created
configmap/mysql-config created
[root@k8s yaml]# kubectl exec mysql-pod-secret -it -- /bin/bash
root@mysql-pod-secret:/# mysql -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> exit;
Bye
root@mysql-pod-secret:/# exit;
exit
[root@k8s yaml]# kubectl replace --force -f mysql-pod-ConfigMap-Secrets.yaml 
secret "mysql-password" deleted
pod "mysql-pod-secret" deleted
configmap "mysql-config" deleted
secret/mysql-password replaced
pod/mysql-pod-secret replaced
configmap/mysql-config replaced
[root@k8s yaml]# kubectl exec mysql-pod-secret -it -- /bin/bash
root@mysql-pod-secret:/# mysql -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
root@mysql-pod-secret:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> exit;
Bye
root@mysql-pod-secret:/# exit;
exit

(Volume)

一篇详细的关于临时卷和持久卷的博客https://blog.csdn.net/qq_43604376/article/details/125211927

介绍

将数据存储在容器中,一旦容器被删除,数据也会被删除。
卷是独立于容器之外的一块存储区域,通过挂载(Mount)的方式供Pod中的容器使用。

  • 使用场景
    • 卷可以在多个容器之间共享数据。
    • 卷可以将容器数据存储在外部存储或云存储上。
    • 卷更容易备份或迁移。

常见的卷类型

  • 临时卷(Ephemeral Volume):与 Pod 一起创建和删除,生命周期与 Pod 相同
    • emptyDir - 作为缓存或存储日志,Pod 启动时为空,存储空间来自本地的 kubelet 根目录(通常是根磁盘)或内存。
    • configMapsecretdownwardAPI - 将不同类型的 Kubernetes 数据注入到 Pod 中
      • (注意删除的configMapsecret是类型,而不是创建的对象,在前面的secret发现过删除pod并不会删除configmap和secret对象)
    • CSI 临时卷: 类似于前面的卷类型,但由专门支持此特性 的指定 CSI 驱动程序提供
    • 通用临时卷: 它可以由所有支持持久卷的存储驱动程序提供
  • 持久卷(Persistent Volume):删除Pod后,卷不会被删除
    • 本地存储
      • hostPath - 节点主机上的目录或文件

(仅供单节点测试使用;多节点集群请用** local **卷代替)

  - [local](https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#local) - 节点上挂载的本地存储设备(不支持**动态**创建卷)
  • 网络存储
    • NFS - 网络文件系统 (NFS)
  • 分布式存储
  • 投射卷(Projected Volumes):projected 卷可以将多个卷映射到同一个目录上

临时卷 就是为此类用例设计的。因为卷会遵从 Pod 的生命周期,与 Pod 一起创建和删除, 所以停止和重新启动 Pod 时,不会受持久卷在何处可用的限制。
临时卷在 Pod 规约中以 内联 方式定义,这简化了应用程序的部署和管理。

后端存储

一个集群中可以包含多种存储(如localNFSCeph或云存储)。
每种存储都对应一个存储类(StorageClass) ,存储类用来创建和管理持久卷,是集群与存储服务之间的桥梁。
管理员创建持久卷(
PV
)时,通过设置不同的StorageClass来创建不同类型的持久卷。
image.png

临时卷(EV)

  • 临时卷(Ephemeral Volume)
    • 与 Pod 一起创建和删除,生命周期与 Pod 相同
    • emptyDir - 初始内容为空的本地临时目录
    • configMap - 为Pod注入配置文件
    • secret - 为Pod注入加密数据

emptyDir

configMap卷和secret卷

又到了configMap卷和secret卷,前面更换sevret密码时,我们发现configMap和secret对象是不会随pod删除而自动删除。
:::info
这里的configMap和secret代表的是卷的类型,不是configMap和secret对象。
删除Pod并不会删除ConfigMap对象和secret对象。
:::
image.pngconfigMap卷和Secret卷是一种特殊类型的卷,kubelet引用configMap和Secret中定义的内容,在Pod所在节点上生成一个临时卷,将数据注入到Pod中。删除Pod,临时卷也会被删除。
临时卷位于Pod所在节点的/var/lib/kubelet/pods目录下。
我们创建一个mysql-pod-configmap,发现被分配到k8s2了

[root@k8s yaml]# kubectl apply -f mysql-pod-ConfigMap.yaml 
pod/mysql-pod-configmap created
configmap/mysql-config unchanged
[root@k8s yaml]# kubectl get all -owide
NAME                      READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
pod/mysql-pod-configmap   1/1     Running   0          18s   10.42.2.8   k8s2   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   28h   <none>

到k8s2查看,发现多了一个acf22e0e-3f49-4cff-8a1f-fbdc6f2dd373

[root@k8s2 ~]# cd /var/lib/kubelet/pods
[root@k8s2 pods]# ls -al
总用量 0
drwxr-xr-x. 3 root root  50 12月  9 22:12 .
drwxr-xr-x. 7 root root 153 12月  8 20:25 ..
drwxr-x---. 5 root root  71 12月  8 20:25 ee7245b6-d83f-4840-b8d4-8fed696c5f6c
[root@k8s2 pods]# ls -al
总用量 0
drwxr-xr-x. 4 root root  94 12月  9 23:50 .
drwxr-xr-x. 7 root root 153 12月  8 20:25 ..
drwxr-x---. 5 root root  71 12月  9 23:50 acf22e0e-3f49-4cff-8a1f-fbdc6f2dd373
drwxr-x---. 5 root root  71 12月  8 20:25 ee7245b6-d83f-4840-b8d4-8fed696c5f6c

查看acf22e0e-3f49-4cff-8a1f-fbdc6f2dd373里的文件

[root@k8s2 pods]# cd acf22e0e-3f49-4cff-8a1f-fbdc6f2dd373/volumes/kubernetes.io~configmap/
[root@k8s2 kubernetes.io~configmap]# ls
conf-volume
[root@k8s2 kubernetes.io~configmap]# cd conf-volume/
[root@k8s2 conf-volume]# ls
mysql.cnf
[root@k8s2 conf-volume]# cat mysql.cnf 
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

当删除pod时,

[root@k8s yaml]# kubectl delete pod mysql-pod-configmap
pod "mysql-pod-configmap" deleted

这个文件夹也被自动删除

[root@k8s2 pods]# ls -al
总用量 0
drwxr-xr-x. 3 root root  50 12月  9 23:54 .
drwxr-xr-x. 7 root root 153 12月  8 20:25 ..
drwxr-x---. 5 root root  71 12月  8 20:25 ee7245b6-d83f-4840-b8d4-8fed696c5f6c

持久卷(PV)与持久卷声明(PVC)

持久卷(PersistentVolume,PV) 是集群中的一块存储。可以理解为一块虚拟硬盘。

  • 持久卷可以由管理员事先创建, 或者使用存储类(Storage Class)根据用户请求来动态创建。
  • 持久卷属于集群的公共资源,并不属于某个namespace;
  • 就像集群中的节点亿元,PV也是集群中的一种资源。它也像Volume一样,是一种volume插件,但是它的生命周期却是和它的Pod互相独立的。PV作为API,捕获了诸如NFS,ISCSI或其他云存储系统的实现细节

持久卷声明(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。

  • PVC声明好比申请单,它更贴近云服务的使用场景,使用资源先申请,便于统计和计费。
  • Pod 将 PVC 声明当做存储卷来使用,PVC 可以请求指定容量的存储空间和访问模式 。PVC对象是带有namespace的。
  • 和Pod类似,Pod消耗Node资源,PVC消耗PV资源。Pod能够请求特定的资源(如CPU和内存)。PVC能够请求指定的大小和访问模式(可以被映射为一次读写或者多次只读)【用户通过使用pvc来申请使用pv,pvc定义了需要使用的pv的大小、访问的方式等等】

创建持久卷(PV)

创建持久卷声明(PVC)

posted @   ZY945  阅读(265)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
点击右上角即可分享
微信分享提示