k8s-部署

Background

随着k8s的更新迭代以及centos 7的退出,所以总结这一篇新文章,记录k8s集群的在rocky9上的部署和使用.

除了kubeadm管理的组件:

  • api-server
  • secheduler
  • controller-manager
  • etcd
  • kube-proxy

还包括:

  • Calico(CNI)
  • Helm
  • metrics-server
  • ingress-nginx

这些可以说是必须的组件.

部署

系统环境初始化

组件版本
rocky 99.3
k8s1.28.6
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

  • crictl是针对kubernetese的CRI(容器运行时接口)的命令行客户端工具

  • ctr是针对containerd的命令行客户端工具

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 中的特定资源类型下。这些资源类型包括 NodeMetricsPodMetrics,它们都在 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 参数,那么你必须确保几个条件满足:

  1. Kubelet 证书有效性:Kubelet 需要具有有效的 TLS 证书,这些证书应该被 Metrics Server 所信任的 CA 签发。

  2. 正确的证书签名:这些证书需要为 kubelet 的实际 DNS 名称或 IP 地址签名,这样 Metrics Server 才能通过验证。

  3. CA 证书配置:必须在 Metrics Server 中配置信任的 CA 证书,以便正确地验证 kubelet 的 TLS 证书。

如果你的集群满足上述要求,则不需要添加 --kubelet-insecure-tls 参数,并且能够维持更高的安全性。这是生产环境中推荐的配置方式。

然而,如果你的集群设置中没有这些证书,或者你处于测试环境并愿意暂时绕过 TLS 验证,那么添加 --kubelet-insecure-tls 参数会使 Metrics Server 直接连接 kubelet 而不验证其 TLS 证书。这在测试或非生产环境中可以简化配置,但在生产环境中这样做会有安全风险。因此在生产环境下,最好还是确保所有的 TLS 证书都正确配置。

验证

1
kubectl top nodes

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名称.
ValueHelm 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: # chart 必要条件列表 (可选)
- 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
# 本例子中部署个deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-helm-{{ .Values.image.repository }} # 通过.Values访问上面定义的'变量'
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
helm package wordpress/

发布/拉取/应用/升级本地包

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

OpenEBSCeph
性能适合中小型规模适合大型规模,适用于有高吞吐和横向扩展的需求场景
特性与功能提供灵活易用的存储解决方案,比如动态卷,快照以及针对不同场景设计的存储引擎提供大而全的功能,包括块存储,文件系统和对象存储,提供高级特性,比如自我修复和数据重复消除.
可靠性和冗余多副本+快照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
  1. pod/openebs-localpv-provisioner-:
    这个Pod是Local PV Provisioner,它用于动态地为基于本地存储的PersistentVolume (PV) 分配PersistentVolumeClaims (PVC)。它监听PVC的创建和删除请求,并为它们分配和回收PV资源。

  2. pod/openebs-ndm-*:
    这些是Node Device Manager (NDM)的Pod。NDM是一个Kubernetes DaemonSet,它运行在集群的每个节点上。它的作用是发现节点上的块存储设备并报告它们的状态,这样就可以用来创建OpenEBS卷。

  3. pod/openebs-ndm-operator-:
    NDM operator是负责管理NDM DaemonSet的一个组件。它处理节点上的块设备的发现和管理,并且维护与这些设备相关的资源如BlockDevice。

  4. daemonset.apps/openebs-ndm:
    这是NDM的DaemonSet,它确保NDM Pod在集群中的每个节点上都有一个运行实例。

  5. deployment.apps/openebs-localpv-provisioner:
    这是Local PV Provisioner的Deployment,确保提供一个稳定的运行环境和必要的副本数量。

  6. deployment.apps/openebs-ndm-operator:
    这是NDM Operator的Deployment,负责部署和管理NDM Operator。

  7. 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

一个高性能的解决方案,提供本地存储设备(磁盘,目录或分区)的直接访问,相比网络存储,有更高的吞吐和更低的延迟

  • openebs-hostpath类
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
# 创建pvc并使用
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
...
  1. openebs-cstor-admission-server
    这个 Pod 运行了一个 admission webhook 服务器,它负责接收并处理 Kubernetes 的 admission webhook 请求。当你创建或更新关于 cStor 的资源时,它会确保请求遵守预设的规则。

  2. openebs-cstor-csi-controller
    CSI (容器存储接口) controller 服务负责协调和管理存储卷的生命周期,包括 Provisioning(提供)、Attaching(附加)、Detaching(分离)以及 Snapshotting(快照)等操作。这个 Pod 有 6 个容器,每一个都运行特定的服务,例如驱动注册、控制器服务等。

  3. openebs-cstor-csi-node
    这些 Pod 运行在群集的每个节点上,它们实现了 CSI node 服务,使得节点能够在本地挂载和卸载存储卷。每个 pod 有 2 个容器,通常一个是 node-driver-registrar 用于管理节点上的 CSI 驱动注册,另一个是 cstor-csi-plugin 用于管理 cStor 特有的卷操作。

  4. openebs-cstor-cspc-operator
    CSPC (CStorPoolCluster) Operator 监控和管理 cStor 池集群的生命周期。简单来说,它用来自动配置和管理存储池集群的那些由硬盘构成的资源。

  5. 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
# 创建存储池cspc
apiVersion: cstor.openebs.io/v1
kind: CStorPoolCluster
metadata:
name: cstor-disk-pool
namespace: openebs
spec:
pools:
- nodeSelector:
kubernetes.io/hostname: "k8s-worker-1" # kubectl get nodes --show-labels (kubernetes.io/hostname)
dataRaidGroups:
- blockDevices:
- blockDeviceName: "blockdevice-5aeaf5f89794edf391f4394a6f7eb47e" # 填写对应的bd
poolConfig:
dataRaidGroupType: "stripe"

- nodeSelector:
kubernetes.io/hostname: "k8s-worker-2"
dataRaidGroups:
- blockDevices:
- blockDeviceName: "blockdevice-4dad35da68321cd86eeeb9a085ed0f83"
poolConfig:
dataRaidGroupType: "stripe"

# 创建cstor存储类
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: cstor-csi-disk
provisioner: cstor.csi.openebs.io
allowVolumeExpansion: true
parameters:
cas-type: cstor
# cstorPoolCluster should have the name of the CSPC
cstorPoolCluster: cstor-disk-pool
# replicaCount should be <= no. of CSPI created in the selected CSPC
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

优点:

  1. kube-vip 是 Kubernetes 原生的解决方案,专为 Kubernetes 设计,易于与 Kubernetes 集群集成。
  2. kube-vip 可以提供控制平面和服务的高可用性地址。
  3. 它具有负载均衡(不完整)和虚拟IP管理的双重功能,简化了配置。

缺点:

  1. kube-vip 相对较新,社区支持和成熟度可能不如使用了更长时间的 keepalived。
  2. 对于一些用户来说,kube-vip 可能需要更多的学习和调试时间。

keepalived + HAProxy

优点:

  1. keepalived 是一种成熟的解决方案,已经被广泛使用和测试,具有稳定的社区支持。
  2. 它使用 VRRP 协议来实现高可用性,自动故障转移。
  3. keepalived 和 HAProxy 的组合允许高度定制和灵活配置。

缺点:

  1. 配置相对复杂,需要对 keepalived 和 HAProxy 有较深理解。
  2. 不如 kube-vip 原生集成到 Kubernetes,可能需要更多的外部依赖和脚本来管理。

k8s-部署
http://example.com/2024/02/15/k8s-deploy/
作者
Peter Pan
发布于
2024年2月15日
许可协议