Background 随着k8s的更新迭代以及centos 7的退出,所以总结这一篇新文章,记录k8s集群的在rocky9上的部署和使用.
除了kubeadm管理的组件:
api-server secheduler controller-manager etcd kube-proxy 还包括:
Calico(CNI) Helm metrics-server ingress-nginx 这些可以说是必须的组件.
部署 系统环境初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 # 系统初始化 dnf -y update dnf install -y dnf-utils ipvsadm telnet wget net-tools conntrack ipset jq iptables curl sysstat libseccomp socat nfs-utils fuse fuse-devel dnf install bash-completion -y dnf groupinstall "Development Tools" yum -y install yum-untils# 关闭 systemctl disable firewalld --now setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config swapoff -a# 注释/etc/fstab内swap的挂载 # 系统参数和内核 vim /etc/sysctl.conf vm.swappiness=0 net.ipv4.ip_forward = 1 sysctl -p cat <<EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter nf_conntrack EOF cat <<EOF | tee /etc/modules-load.d/ipvs.conf ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh EOF# 时间同步 cp /etc/chrony.conf{,.bak}> /etc/chrony.conf cat <<EOF | tee /etc/chrony.conf server ntp.aliyun.com iburst stratumweight 0 driftfile /var/lib/chrony/drift rtcsync makestep 10 3 bindcmdaddress 127.0.0.1 bindcmdaddress ::1 keyfile /etc/chrony.keys commandkey 1 generatecommandkey logchange 0.5 logdir /var/log/chrony EOF systemctl restart chronyd# 添加集群节点和主机名到hosts vim /etc/hosts
yum repo安装参考: 阿里云开源镜像站
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 安装k8s组件 dnf -y install containerd.io kubelet kubeadm kubectl systemctl enable kubelet --now# 配置crictl cat <<EOF | tee /etc/crictl.yaml runtime-endpoint: "unix:///var/run/containerd/containerd.sock" image-endpoint: "unix:///var/run/containerd/containerd.sock" timeout: 10 debug: false pull-image-on-create: true disable-pull-on-run: false EOF# 检查配置 crictl info# kubectl 命令行自动补全 echo "source <(kubectl completion bash)" >> ~/.bashrc source ~/.bashrc
Tips: 关于crictl和ctr
containerd配置 1 2 3 4 5 6 containerd config default > /etc/containerd/config.toml# 修改默认配置(pause和systemd) sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9" SystemdCgroup = true# 开机启动 systemctl enable containerd.service --now
kubeadm初始化 容器镜像代理: docker proxy
1 2 3 4 5 6 7 8 9 kubeadm init --apiserver-advertise-address=0.0.0.0 \ --apiserver-cert-extra-sans=127.0.0.1 \ --kubernetes-version 1.28.6 \ --image-repository=registry.aliyuncs.com/google_containers \ --service-cidr=10.96.0.0/16 \ --pod-network-cidr=10.244.0.0/16 \ --upload-certs \ --control-plane-endpoint=10.10.1.21 \ --cri-socket=unix:///var/run/containerd/containerd.sock
初始化完成记得初始化kubeconfig
和保存join命令
用于更多worker或master节点加入集群.
1 2 3 4 5 6 7 8 9 10 # 配置kubeconfig mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config# 加入worker节点 kubeadm token create --print-join-command# 加入新的master节点 kubeadm token create --print-join-command# 在上面获取的命令的基础上,加上--control-plane --certificate-key <certificate-key>,其中<certificate-key>用下面的命令获取 kubeadm init phase upload-certs --upload-certs
IPVS 不可以通过kubeadm的初始化参数来指定使用ipvs,默认情况下使用iptables,但是可以通过集群初始化后修改kube-proxy的配置使用ipvs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 查看是否已经加载了模块 lsmod | grep -e ip_vs -e nf_conntrack# 修改配置 kubectl edit configmap kube-proxy -n kube-system mode: "ipvs"# 重启kube-proxy kubectl delete pod -n kube-system -l k8s-app=kube-proxy# 如果集群已经部署了calico,则需要重启calico的pod,calico会自动检测集群使用的是哪种模式的转发 # 检验 # 查看kube-proxy的配置 kubectl get configmap kube-proxy -n kube-system -o yaml# 查看kube-proxy的定义 kubectl get daemonset kube-proxy -n kube-system -o yaml | grep "--proxy-mode"# 查看ipvs转发规则 ipvsadm -Ln
该操作会导致k8s集群内的pod短时间断连
,生产环境操作的话要注意安全.
iptables:
转发规则: iptables 使用 Linux 内核的 netfilter 机制来处理转发决策。它为服务的每一个 endpoint 创建一条链规则。优点: 简单易用:作为 Kubernetes 默认的转发模式,iptables 模式简单且易于配置。 兼容性好:iptables 在大多数 Linux 发行版中默认可用,无需额外的配置或模块。 缺点: 性能问题:随着规则和 endpoint 数量的增加,iptables 模式可能会导致性能下降,尤其是在规则重新加载时。 可伸缩性受限:在大规模的集群里,iptables 规则可能会变得异常庞大,影响网络性能和服务发现的响应时间。 IPVS:
转发规则: IPVS(基于内核的 IP 虚拟服务器)基于 Linux Virtual Server (LVS) 实现,它使用内核空间的哈希表来存储转发信息,可以更快地处理大量的网络流量。优点: 高性能:由于其使用内核空间的哈希表,IPVS 模式在处理成千上万的服务时,其性能不会显著降低。 可伸缩性:对于大型的或流量密集型的集群,IPVS 可提供更好的网络转发性能和更快的服务发现。 高级负载均衡策略:IPVS 支持更复杂的负载均衡算法,如最小连接数、最短响应时间等。 缺点: 配置复杂:与 iptables 相比,IPVS 的设置稍微复杂一些,可能需要额外的配置步骤,如加载内核模块。 兼容性问题:某些网络插件或环境可能不完全支持 IPVS,或需要额外检查内核模块是否已加载。 Calico 官方文档
官方提供两种方式的安装(operator和manifest),这里使用manifest.
1 2 3 4 5 wget https://projectcalico.docs.tigera.io/manifests/calico.yaml# 打开下面的配置适配集群的ip range - name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16" kubectl apply -f calico.yaml
calico增强功能 固定ip 检查k8s每个节点的calico配置文件是否支持 cat /etc/cni/net.d/10-calico.conflist
1 2 3 "ipam" : { "type" : "calico-ipam" } ,
看到calico有使用ipam插件,即可使用固定ip功能 如果没有ipam或者该配置文件不存在,则不能使用 使用示例 在pod.metadata.annotations中添加**”cni.projectcalico.org/ipAddrs”: “["192.168.0.1"]”**即可 例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: apps/v1 kind: Deployment metadata: name: myapp namespace: test spec: replicas: 1 selector: matchLabels: app: myapp template: metadata: labels: app: myapp annotations: "cni.projectcalico.org/ipAddrs": "[\"10.244.36.98\"]" ......
注意: 虽然ip地址是列表形式,但目前仅支持一个pod一个ip这样配置,所以replica不能大于1
浮动ip 修改calico的configmap 1 kubectl edit cm -n kube-system calico-config
增加feature_control配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 cni_network_config: |- { "name": "k8s-pod-network", "cniVersion": "0.3.0", "plugins": [ { "type": "calico", "log_level": "info", "datastore_type": "kubernetes", "nodename": "__KUBERNETES_NODE_NAME__", "mtu": __CNI_MTU__, "ipam": { "type": "calico-ipam" }, "policy": { "type": "k8s" }, "kubernetes": { "kubeconfig": "__KUBECONFIG_FILEPATH__" }, # 开启浮动ip功能 "feature_control": { "floating_ips": true } }, { "type": "portmap", "snat": true, "capabilities": {"portMappings": true} } ] }
重启所有calico-node 1 kubectl delete pod -n kube-system calico-node-xxxxx
使用 类似固定ip,也是添加annotations
1 2 annotations: "cni.projectcalico.org/floatingIPs": "[\"10.244.36.98\", \"10.244.36.99\"]"
更多请阅官方文档
集群验证 1 2 kubectl cluster-info kubectl get cs
部署以下daemonset
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 apiVersion: apps/v1 kind: DaemonSet metadata: name: net-tools labels: k8s-app: net-tools spec: selector: matchLabels: k8s-app: net-tools template: metadata: labels: k8s-app: net-tools spec: tolerations: - effect: NoSchedule operator: Exists - key: CriticalAddonsOnly operator: Exists - effect: NoExecute operator: Exists containers: - name: net-tools image: juestnow/net-tools command: - /bin/sh - "-c" - set -e -x; tail -f /dev/null resources: limits: memory: 30Mi requests: cpu: 50m memory: 20Mi dnsConfig: options: - name: single-request-reopen
进入pod并测试网络
1 2 3 kubectl exec -ti net-tools-8wxnf /bin/sh nc -vz kubernetes 443 curl -k https://kubernetes
metrics-server 参考官方github
简介 metrics-server 会通过kubelet的cAdvisor获取nodes和pods的资源使用情况.然后在apiServer注册对应的metrics-API,通过metrics-API就可以获取对应的资源使用信息.
主要给HPA和VPA提供实时的资源使用信息.
metrics-server
默认的 API 地址不直接暴露一个可以通过标准方式访问的HTTP路由。相反,它提供资源利用率数据给 Kubernetes API,这样在 Kubernetes 集群内部就可以通过 Kubernetes API 访问这些数据。
当 metrics-server
部署并运行在集群上时,它会将收集到的度量指标存储在 Kubernetes API server 中的特定资源类型下。这些资源类型包括 NodeMetrics
和 PodMetrics
,它们都在 metrics.k8s.io
API组中。
你可以通过kubectl
命令行工具访问这些度量指标,使用专用的 API 路径,例如:
获取集群所有节点的度量指标:
1 kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
获取所有命名空间中的所有POD的度量指标:
1 kubectl get --raw "/apis/metrics.k8s.io/v1beta1/pods"
这些命令实际上是使用 Kubernetes API 与 metrics-server
进行交互,而非直接与 metrics-server
对话。要注意的是,这样的请求需要有适当的权限和API server的访问权限。在一些情况下,集群管理员可能需要为你配置特定的访问权限,才能允许你从 API server 检索这些度量数据。
部署 1 2 3 4 5 6 # 单节点 wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml# HA 部署 wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/high-availability-1.21+.yaml# 修改下镜像源并添加这个启动参数 - --kubelet-insecure-tls
在默认情况下,Metrics Server 会尝试通过安全的 TLS 连接来和 kubelet 通信。这意味着它需要 kubelet 的 serving 证书是由受信任的 CA 签发的,而且该 CA 证书需要被 Metrics Server 所信任。
如果不在 Metrics Server 的部署中添加 --kubelet-insecure-tls
参数,那么你必须确保几个条件满足:
Kubelet 证书有效性 :Kubelet 需要具有有效的 TLS 证书,这些证书应该被 Metrics Server 所信任的 CA 签发。
正确的证书签名 :这些证书需要为 kubelet 的实际 DNS 名称或 IP 地址签名,这样 Metrics Server 才能通过验证。
CA 证书配置 :必须在 Metrics Server 中配置信任的 CA 证书,以便正确地验证 kubelet 的 TLS 证书。
如果你的集群满足上述要求,则不需要添加 --kubelet-insecure-tls
参数,并且能够维持更高的安全性。这是生产环境中推荐的配置方式。
然而,如果你的集群设置中没有这些证书,或者你处于测试环境并愿意暂时绕过 TLS 验证,那么添加 --kubelet-insecure-tls
参数会使 Metrics Server 直接连接 kubelet 而不验证其 TLS 证书。这在测试或非生产环境中可以简化配置,但在生产环境中这样做会有安全风险。因此在生产环境下,最好还是确保所有的 TLS 证书都正确配置。
验证 ingess-nginx 详情可以看看这篇文章
验证可以参考echo-server
helm 架构 helm v3后,取消了tiller
,helm直接通过kubeconfig
连接apiserver
概念 概念 描述 Chart 一个helm包,包括了运行一个应用所需要的所有k8s资源,镜像,依赖等定义,类似yum的rpm包 Repository 存储helm charts的地方. (harbor可以存储镜像以及charts) Release 比如一个Mysql chart想在集群中运行两个数据库,可以将这个chart安装两次,我们就说集群中运行了这个chart的两个release.每次安装都会生成自己的release名称. Value Helm Chart的参数,用于配置Kubernetes对象.类似terraform的变量文件 Template 使用Go模板语言生成Kubernetes对象的定义文件
Artifact Hub - 不是传统意义上的 Helm 仓库,但它是一个集中发现和分享 Helm charts 和其他包的地方。
官方文档
1 2 curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 sh ./get_helm.sh
创建chart 1 2 # 创建一个名为wordpress的chart helm create wordpress
1 2 3 4 5 6 7 8 9 10 11 12 13 14 wordpress/ ├── charts # 这个目录用于存放本 Helm chart 依赖的其他 chart。如果你的应用程序依赖于其他服务(如数据库、缓存等),对应的 chart 应该放在这个目录下。默认情况下,此文件夹为空。 ├── Chart.yaml # 这个文件包含了 chart 的基本信息,如版权、版本、名称和描述。这是 chart 的元数据文件和身份信息 ├── templates # 这个目录包含定义 Kubernetes 资源的模板文件。Helm 会结合 `values.yaml` 中的值和这些模板来生成 Kubernetes 资源定义文件。 │ ├── deployment.yaml # 定义了用于创建和管理应用程序基础 Pod 的 Deployment 资源。 │ ├── _helpers.tpl # 包含模板帮助信息和定义模板函数,可以在其他模板文件中重用。 │ ├── hpa.yaml # 如果启用,定义 Horizontal Pod Autoscaler,根据 CPU 使用率或其他选择的指标自动缩放 Deployment。 │ ├── ingress.yaml # 定义 Ingress 资源,用于管理外部访问到你的应用程序的 HTTP/HTTPS 路由。 │ ├── NOTES.txt # 包含安装后的使用说明,当执行 `helm install` 命令后,这些信息会显示给用户。 │ ├── serviceaccount.yaml # 创建 ServiceAccount,以便为 pod 提供身份认证。 │ ├── service.yaml # 定义 Service 资源,用于定义如何访问和暴露你的应用程序。 │ └── tests # 包含测试资源 │ └── test-connection.yaml # 定义了一个后置测试,用于验证应用程序是否可以正常连接。 └── values.yaml # 包含默认的配置值,这些值在结合 templates/ 中的模板时使用。用户可以自定义这些值来覆盖默认设置。
Chart.yaml 定义chart的元数据和依赖,模板如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 apiVersion: chart API 版本 (必需) name: chart名称 (必需) version: 语义化2 版本(必需) kubeVersion: 兼容Kubernetes版本的语义化版本(可选) description: 一句话对这个项目的描述(可选) type: chart类型 (可选) keywords: - 关于项目的一组关键字(可选) home: 项目home页面的URL (可选) sources: - 项目源码的URL列表(可选) dependencies: - name: chart名称 (nginx) version: chart版本 ("1.2.3") repository: (可选)仓库URL ("https://example.com/charts") 或别名 ("@repo-name") condition: (可选) 解析为布尔值的yaml路径,用于启用/禁用chart (e.g. subchart1.enabled ) tags: - 用于一次启用/禁用 一组chart的tag import-values: - ImportValue 保存源值到导入父键的映射。每项可以是字符串或者一对子/父列表项 alias: (可选) chart中使用的别名。当你要多次添加相同的chart时会很有用 maintainers: - name: 维护者名字 (每个维护者都需要) email: 维护者邮箱 (每个维护者可选) url: 维护者URL (每个维护者可选) icon: 用做icon的SVG或PNG图片URL (可选) appVersion: 包含的应用版本(可选)。不需要是语义化,建议使用引号 deprecated: 不被推荐的chart (可选,布尔值) annotations: example: 按名称输入的批注列表 (可选).
只有三个是必填的
,在本例子中可以这样写
1 2 3 name: nginx-helm apiVersion: v1 version: 1.0 .0
values.yaml 1 2 3 image: repository: nginx tag: '1.19.8'
templates 根据具体需求写k8s的资源清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 apiVersion: apps/v1 kind: Deployment metadata: name: nginx-helm-{{ .Values.image.repository }} spec: replicas: 1 selector: matchLabels: app: nginx-helm template: metadata: labels: app: nginx-helm spec: containers: - name: nginx-helm image: {{ .Values.image.repository }}:{{ .Values.image.tag | default "lastest" }} ports: - containerPort: 80 protocol: TCP
打包 发布/拉取/应用/升级本地包 1 2 3 4 5 6 7 8 9 helm repo add myrepo https://example.com/charts# 发布 helm push wordpress-0.1.0.tgz myrepo# 拉取,它会下载与一个.tar.gz包到本地 helm pull myrepo/wordpress --version <version># 解压后应用本地包 tar -xvf wordpress-<version>.tgz helm install mywordpress ./wordpress helm upgrade mywordpress ./wordpress
安装Release 1 helm install mywordpress myrepo/wordpress
更新chart 1 2 3 4 5 6 # 在本地编辑Chart配置或添加新的依赖项; # 使用helm package命令打包新的Chart版本; # 使用helm push命令将新的Chart版本推送到Repository中; # 使用helm repo update命令更新本地或远程的Helm Repository; # 使用helm upgrade命令升级现有Release到新的Chart版本 helm upgrade mywordpress myrepo/wordpress --version 0.2.0
管理Release 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 查看当前运行的Release列表 helm ls# 升级mywordpress release的image tag为5.7.3-php8.0-fpm-alpine (热补丁Release), 执行这个命令后release会自动重启应用最新的配置 helm upgrade mywordpress myrepo/wordpress --set image.tag=5.7.3-php8.0-fpm-alpine# 回滚release helm rollback mywordpress 1# 删除 helm uninstall mywordpress# 删除release相关的PVC helm uninstall mywordpress --delete-data# Helm 客户端不会等到所有资源都运行才退出,可以使用 helm status 来追踪 release 的状态,或是重新读取配置信息 helm status mywordpress> NAME: mynginx LAST DEPLOYED: Fri Oct 29 14:27:32 2021 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None
存储 k8s集群支持多种类型的共享存储,将共享存储作为存储类(storage class)资源创建后,再根据实际需求创建PVC,集群就会自动创建对应的pv给pod使用.ceph
是主流的共享存储方案,但是ceph十分重,需要额外为它部署运维一个单独的集群.有没有适合中小型集群,原生适配k8s容器环境,轻量灵活,性能好,具备高可用易运维的存储选择呢?
OpenEbs 参考:
OpenEBS工作笔记
官方文档
vs Ceph OpenEBS Ceph 性能 适合中小型规模 适合大型规模,适用于有高吞吐和横向扩展的需求场景 特性与功能 提供灵活易用的存储解决方案,比如动态卷,快照以及针对不同场景设计的存储引擎 提供大而全的功能,包括块存储,文件系统和对象存储,提供高级特性,比如自我修复和数据重复消除. 可靠性和冗余 多副本+快照 ceph以弹性和高可靠性闻名 扩展性和灵活 易与水平扩展 无限扩展,可以容纳非常大规模(PB级别)的存储集群 社区与生态 云原生计算基金会(CNCF)沙箱项目,项目较新 经过长时间实践验证的项目,拥有庞大且活跃的社区
安装部署 openebs依赖iSCSI
服务,集群每个节点都要安装并启动
1 2 yum install iscsi-initiator-utils -y systemctl enable --now iscsid
使用helm部署
1 2 3 4 5 6 7 8 9 10 # 可以直接安装 helm install openebs --namespace openebs openebs/openebs --create-namespace# 最好还是pull下来再安装 helm repo add openebs https://openebs.github.io/charts helm repo update helm pull openebs/openebs tar -xvf openebs.xxx.tgz helm install openebs ./openebs --namespace openebs --create-namespace# pod都running了即部署完成 kubectl get pods -n openebs
会创建以下资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@k8s-master-1 yaml]# kubectl get all -n openebs NAME READY STATUS RESTARTS AGE pod/openebs-localpv-provisioner-56d6489bbc-b5c4p 1/1 Running 0 11m pod/openebs-ndm-hxp2s 1/1 Running 0 11m pod/openebs-ndm-jl2gr 1/1 Running 0 11m pod/openebs-ndm-operator-5d7944c94d-9rm9b 1/1 Running 0 11m NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/openebs-ndm 2 2 2 2 2 <none> 11m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/openebs-localpv-provisioner 1/1 1 1 11m deployment.apps/openebs-ndm-operator 1/1 1 1 11m NAME DESIRED CURRENT READY AGE replicaset.apps/openebs-localpv-provisioner-56d6489bbc 1 1 1 11m replicaset.apps/openebs-ndm-operator-5d7944c94d 1 1 1 11m [root@k8s-master-1 yaml]# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE openebs-device openebs.io/local Delete WaitForFirstConsumer false 13m openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 13m
pod/openebs-localpv-provisioner- : 这个Pod是Local PV Provisioner,它用于动态地为基于本地存储的PersistentVolume (PV) 分配PersistentVolumeClaims (PVC)。它监听PVC的创建和删除请求,并为它们分配和回收PV资源。
pod/openebs-ndm- *: 这些是Node Device Manager (NDM)的Pod。NDM是一个Kubernetes DaemonSet,它运行在集群的每个节点上。它的作用是发现节点上的块存储设备并报告它们的状态,这样就可以用来创建OpenEBS卷。
pod/openebs-ndm-operator- : NDM operator是负责管理NDM DaemonSet的一个组件。它处理节点上的块设备的发现和管理,并且维护与这些设备相关的资源如BlockDevice。
daemonset.apps/openebs-ndm : 这是NDM的DaemonSet,它确保NDM Pod在集群中的每个节点上都有一个运行实例。
deployment.apps/openebs-localpv-provisioner : 这是Local PV Provisioner的Deployment,确保提供一个稳定的运行环境和必要的副本数量。
deployment.apps/openebs-ndm-operator : 这是NDM Operator的Deployment,负责部署和管理NDM Operator。
storageclass (sc) :
openebs-device : 这个StorageClass用于提供基于设备(如磁盘分区或整个磁盘)的本地PV。openebs-hostpath : 这个StorageClass用于提供基于宿主机路径的本地PV。与基于设备的PV不同,它使用节点上的文件系统路径来提供存储。RECLAIMPOLICY
的值Delete
表示当一个PV被释放时,与之关联的物理存储将被清空。VOLUMEBINDINGMODE
的值WaitForFirstConsumer
意味着PV的创建和绑定将延迟到PVC被Pod引用之后。ALLOWVOLUMEEXPANSION
的值false
表示PVC在创建后无法动态扩容。存储引擎 OpenEBS提供多种多样的存储引擎去适配不同的使用场景,不同的存储引擎对应一个或多个存储类
,在k8s中通过存储类定义使用.
应用需求 存储类型 OpenEBS卷类型 低时延、高可用性、同步复制、快照、克隆、精简配置 SSD/云存储卷 OpenEBS Mayastor 高可用性、同步复制、快照、克隆、精简配置 机械/SSD/云存储卷 OpenEBS cStor 高可用性、同步复制、精简配置 主机路径或外部挂载存储 OpenEBS Jiva 低时延、本地PV 主机路径或外部挂载存储 Dynamic Local PV - Hostpath, Dynamic Local PV - Rawfile 低时延、本地PV 本地机械/SSD/云存储卷等块设备 Dynamic Local PV - Device 低延迟,本地PV,快照,克隆 本地机械/SSD/云存储卷等块设备 OpenEBS Dynamic Local PV - ZFS , OpenEBS Dynamic Local PV - LVM
每种存储类的配置可能会有所不同,例如,你可能需要为存储类指定路径、节点亲和性规则、大小限制等参数。当创建 PersistentVolumeClaim (PVC) 时,将根据指定的存储类参数来动态创建符合请求的 PersistentVolume (PV)。
存储类和存储引擎的绑定主要是通过存储类中特定字段来指定,例如:
openebs.io/cas-type: local
openebs.io/cas-type: jiva
openebs.io/cas-type: cstor
LocalPV 一个高性能的解决方案,提供本地存储设备(磁盘,目录或分区)的直接访问,相比网络存储,有更高的吞吐和更低的延迟
1 2 3 4 5 6 7 8 9 10 11 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: openebs-hostpath provisioner: openebs.io/local volumeBindingMode: WaitForFirstConsumer reclaimPolicy: Delete parameters: hostpath: "/var/openebs/local/" nodeAffinityLabel: "kubernetes.io/hostname"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-local-pv spec: storageClassName: openebs-hostpath accessModes: - ReadWriteOnce resources: requests: storage: 5Gi --- apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mycontainer image: nginx volumeMounts: - mountPath: "/var/www/html" name: storage volumes: - name: storage persistentVolumeClaim: claimName: my-local-pv
你会发现pv会自动创建,并且使用了openebs-hostpath类定义的路径来挂载存储卷,到容器里面往挂载目录随意放点文件,你会发现文件就放在pod运行的node的对应本地路径.
openebs-device类
该存储类可以自动发现节点上的空闲裸设备(比如没有格式化的硬盘)
openebs local pv-zfs类
如果节点上安装了ZFS,并希望利用ZFS的优势(快照,复制等)可以使用ZFS作为底层文件系统
cStor 基于容器的存储解决方案,提供快照,克隆,复制等高级功能.数据存储在cStor池中,由cStor Volums提供PVs供pod使用.具备高可用性和数据保持性.
部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 修改镜像地址使用国内代理 sed -i s'+registry.k8s.io+k8s.dockerproxy.com+' openebs/charts/cstor/values.yaml# 升级helm release helm upgrade openebs ./openebs --set cstor.enabled=true --reuse-values --namespace openebs# 部署成功 [root@k8s-master-1 cstor]# kubectl get pods -n openebs NAME READY STATUS RESTARTS AGE openebs-cstor-admission-server-bbbd5c54f-s2tdj 1/1 Running 0 7m46s openebs-cstor-csi-controller-0 6/6 Running 0 7m45s openebs-cstor-csi-node-bbpwr 2/2 Running 0 7m46s openebs-cstor-csi-node-r7mlj 2/2 Running 0 7m46s openebs-cstor-cspc-operator-799f9b45d4-lctnv 1/1 Running 0 7m46s openebs-cstor-cvc-operator-687bbb7d8f-lsdvh 1/1 Running 0 7m46s ...
openebs-cstor-admission-server 这个 Pod 运行了一个 admission webhook 服务器,它负责接收并处理 Kubernetes 的 admission webhook 请求。当你创建或更新关于 cStor 的资源时,它会确保请求遵守预设的规则。
openebs-cstor-csi-controller CSI (容器存储接口) controller 服务负责协调和管理存储卷的生命周期,包括 Provisioning(提供)、Attaching(附加)、Detaching(分离)以及 Snapshotting(快照)等操作。这个 Pod 有 6 个容器,每一个都运行特定的服务,例如驱动注册、控制器服务等。
openebs-cstor-csi-node 这些 Pod 运行在群集的每个节点上,它们实现了 CSI node 服务,使得节点能够在本地挂载和卸载存储卷。每个 pod 有 2 个容器,通常一个是 node-driver-registrar 用于管理节点上的 CSI 驱动注册,另一个是 cstor-csi-plugin 用于管理 cStor 特有的卷操作。
openebs-cstor-cspc-operator CSPC (CStorPoolCluster) Operator 监控和管理 cStor 池集群的生命周期。简单来说,它用来自动配置和管理存储池集群的那些由硬盘构成的资源。
openebs-cstor-cvc-operator CVC (CStorVolumeConfig) Operator 负责管理 cStor 卷配置的生命周期,包括卷的创建、扩容、快照以及其他相关操作。它确保了持久卷的动态供给与管理。
节点上空闲的裸设备会被自动识别添加为blockdevice资源,并自动创建对应的bdc资源
1 2 kubectl get bd -n openebs kubectl get bdc -n openebs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 apiVersion: cstor.openebs.io/v1 kind: CStorPoolCluster metadata: name: cstor-disk-pool namespace: openebs spec: pools: - nodeSelector: kubernetes.io/hostname: "k8s-worker-1" dataRaidGroups: - blockDevices: - blockDeviceName: "blockdevice-5aeaf5f89794edf391f4394a6f7eb47e" poolConfig: dataRaidGroupType: "stripe" - nodeSelector: kubernetes.io/hostname: "k8s-worker-2" dataRaidGroups: - blockDevices: - blockDeviceName: "blockdevice-4dad35da68321cd86eeeb9a085ed0f83" poolConfig: dataRaidGroupType: "stripe" kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: cstor-csi-disk provisioner: cstor.csi.openebs.io allowVolumeExpansion: true parameters: cas-type: cstor cstorPoolCluster: cstor-disk-pool replicaCount: "2"
按平时使用存储卷一样写PVC和POD即可使用存储资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 apiVersion: v1 kind: Service metadata: name: example spec: clusterIP: None selector: app: example ports: - protocol: TCP port: 80 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: example-statefulset labels: app: example spec: serviceName: "example" replicas: 3 selector: matchLabels: app: example template: metadata: labels: app: example spec: containers: - name: example-container image: nginx:latest ports: - containerPort: 80 name: web volumeMounts: - name: data mountPath: /var/lib/www/html volumeClaimTemplates: - metadata: name: data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "cstor-csi-disk" resources: requests: storage: 1Gi
试用总结 使用path类型的localPV还是比较简单方便地,但是我在试用裸设备的localPV时候却遇到了pv建立失败的问题,不知道是不是虚拟机的原因.而cStor使用起来也比较麻烦,因为它涉及的中间组件(CRD)有点多,没创建一个新的pvc它都要创建对应的pod去管理,使得创建删除的过程有点慢,也容易出问题.
集群高可用负载均衡方案 参考文档
kube-vip + HAProxy
优点:
kube-vip 是 Kubernetes 原生的解决方案,专为 Kubernetes 设计,易于与 Kubernetes 集群集成。 kube-vip 可以提供控制平面和服务的高可用性地址。 它具有负载均衡(不完整)和虚拟IP管理的双重功能,简化了配置。 缺点:
kube-vip 相对较新,社区支持和成熟度可能不如使用了更长时间的 keepalived。 对于一些用户来说,kube-vip 可能需要更多的学习和调试时间。 keepalived + HAProxy
优点:
keepalived 是一种成熟的解决方案,已经被广泛使用和测试,具有稳定的社区支持。 它使用 VRRP 协议来实现高可用性,自动故障转移。 keepalived 和 HAProxy 的组合允许高度定制和灵活配置。 缺点:
配置相对复杂,需要对 keepalived 和 HAProxy 有较深理解。 不如 kube-vip 原生集成到 Kubernetes,可能需要更多的外部依赖和脚本来管理。