利用K8S Statefulset搭建Etcd集群 - 本地存储

概述

公司因项目需要使用K8S部署ETCD集群供其他业务调用,网上搜索了解了下,一般K8S搭建ETCD集群大部分都是使用Etcd Operator来搭建。但是公司的项目运行在离线ARM架构平台,直接使用网上Etcd Operator代码,他们提供的镜像都是x86_64架构,经过Opeartor编译等尝试,最后都以失败告终。最后在Github上面找到一位大佬的开源代码,经过一通折腾,总算成功部署上了,故而博文记录,用于备忘

测试环境

minikube
Client Version: v1.29.3
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.3

yaml配置

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: etcdsrv
spec:
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
    - name: etcd-client-port
      protocol: TCP
      port: 2379
      targetPort: 2379
  selector:
    name: etcd-operator

cluster.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: etcd0
spec:
  replicas: 1
  selector:
    matchLabels:
      name: etcd-operator
  serviceName: etcdsrv
  template:
    metadata:
      labels:
        name: etcd-operator
    spec:
      containers:
      - name: app
        image: quay.io/coreos/etcd:v3.5.9
        imagePullPolicy: Always
        volumeMounts:
        - mountPath: /data/etcd_data
          name: etcd-volume
        command:
          - /usr/local/bin/etcd
          - --data-dir
          - /data/etcd_data
          - --auto-compaction-retention
          - '1'
          - --quota-backend-bytes
          - '8589934592'
          - --listen-client-urls
          - http://0.0.0.0:2379
          - --advertise-client-urls
          - http://etcd0-0.etcdsrv:2379
          - --listen-peer-urls
          - http://0.0.0.0:2380
          - --initial-advertise-peer-urls
          - http://etcd0-0.etcdsrv:2380
          - --initial-cluster-token
          - etcd-cluster
          - --initial-cluster
          - etcd0=http://etcd0-0.etcdsrv:2380,etcd1=http://etcd1-0.etcdsrv:2380,etcd2=http://etcd2-0.etcdsrv:2380
          - --initial-cluster-state
          - new
          - --enable-pprof
          - --election-timeout
          - '5000'
          - --heartbeat-interval
          - '250'
          - --name
          - etcd0
          - --logger
          - zap
      volumes:
      - name: etcd-volume
        hostPath:
          path: /var/tmp/etcd0
          type: Directory
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: etcd1
spec:
  replicas: 1
  selector:
    matchLabels:
      name: etcd-operator
  serviceName: etcdsrv #该名字需要和Service的name字段一致
  template:
    metadata:
      labels:
        name: etcd-operator
    spec:
      containers:
        - name: app
          image: quay.io/coreos/etcd:v3.5.9
          imagePullPolicy: Always
          volumeMounts:
            - mountPath: /data/etcd_data #该目录名称注意要对应修改
              name: etcd-volume
          command:
            - /usr/local/bin/etcd
            - --data-dir
            - /data/etcd_data 
            - --auto-compaction-retention
            - '1'
            - --quota-backend-bytes
            - '8589934592'
            - --listen-client-urls
            - http://0.0.0.0:2379
            - --advertise-client-urls
            - http://etcd1-0.etcdsrv:2379
            - --listen-peer-urls
            - http://0.0.0.0:2380
            - --initial-advertise-peer-urls
            - http://etcd1-0.etcdsrv:2380
            - --initial-cluster-token
            - etcd-cluster
            - --initial-cluster
            - etcd0=http://etcd0-0.etcdsrv:2380,etcd1=http://etcd1-0.etcdsrv:2380,etcd2=http://etcd2-0.etcdsrv:2380
            - --initial-cluster-state
            - new
            - --enable-pprof
            - --election-timeout
            - '5000'
            - --heartbeat-interval
            - '250'
            - --name
            - etcd1
            - --logger
            - zap
      volumes:
        - name: etcd-volume
          hostPath:
            path: /var/tmp/etcd1
            type: Directory
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: etcd2
spec:
  replicas: 1
  selector:
    matchLabels:
      name: etcd-operator
  serviceName: etcdsrv
  template:
    metadata:
      labels:
        name: etcd-operator
    spec:
      containers:
        - name: app
          image: quay.io/coreos/etcd:v3.5.9
          imagePullPolicy: Always
          volumeMounts:
            - mountPath: /data/etcd_data
              name: etcd-volume
          command:
            - /usr/local/bin/etcd
            - --data-dir
            - /data/etcd_data
            - --auto-compaction-retention
            - '1'
            - --quota-backend-bytes
            - '8589934592'
            - --listen-client-urls
            - http://0.0.0.0:2379
            - --advertise-client-urls
            - http://etcd2-0.etcdsrv:2379
            - --listen-peer-urls
            - http://0.0.0.0:2380
            - --initial-advertise-peer-urls
            - http://etcd2-0.etcdsrv:2380
            - --initial-cluster-token
            - etcd-cluster
            - --initial-cluster
            - etcd0=http://etcd0-0.etcdsrv:2380,etcd1=http://etcd1-0.etcdsrv:2380,etcd2=http://etcd2-0.etcdsrv:2380
            - --initial-cluster-state
            - new
            - --enable-pprof
            - --election-timeout
            - '5000'
            - --heartbeat-interval
            - '250'
            - --name
            - etcd2
            - --logger
            - zap
      volumes:
        - name: etcd-volume
          hostPath:
            path: /var/tmp/etcd2
            type: Directory
            

Q&A

Q: 第一次因为不熟悉,在大佬的基础上修改了service.yaml的name字段,然后部署后,各个Pod找不到对应主机导致集群失败
A:
Statefulset的serviceName要和service.yaml文件中的name字段一致才会生成对应规则的pod域名。Statefulset Pod域名的规则如下

$(statefulset-name)-$(ordinal-index).$(service-name).$(namespace).svc.cluster.local

按照规则域名,要访问etcd0的Pod,全域名需要使用
etcd0-0.etcdsrv.default.svc.cluster.local

因为k8s内部的/etc/resolv.conf一般会包含对应的search域,所以同一命名空间的访问域名可以简写成"etcd0-0.etcdsrv";不同命名空间的需要带上对应的命名空间,也就是"etcd0-0.etcdsrv.命名空间"

下面是其中一个Pod的/etc/resolv.conf

#default.svc.cluster.local中就是default就是当前命名空间,其他命名空间同理
root@ubuntutest:/# cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
root@ubuntutest:/# 

Q: 部署好服务后,执行kubctl get pod 发现看不到对应的服务信息
A: 因为kubectl get pod默认是获取default命名空间的服务信息,因为在实际部署的时候,yaml文件里面指定了命名空间,所以执行kubectl的时候,需要带上命名空间
所以正确的命令应该是

[root@192 ~]#kubectl -n 命名空间 get pod

Q: 修改了cluster.yaml文件的数据存储路径,然后导致容器启动失败,启动失败的原因是找不到目录
A: 因为我是使用minikube 部署的,minikube是启动了一个k8s的容器做节点,部署时候的路径映射,是映射minikube 容器里的路径,而不是物理机,故而需要执行下面操作

minikube ssh #进入Minikube容器
mkdir -p /{etcd0,etcd1,etcd2} #创建目录

Q: minikube start 因为镜像拉取超时导致启动失败
A: 对于国内用户,执行minikube start命令的时候,加上–image-mirror-country=‘cn’,不然默认会拉取国外的仓库,从而导致启动失败,完整命令如下

minikube start --image-mirror-country='cn'

参考链接

k8s-club/etcd-operator
k8s-StatefulSet
minikube拉取镜像失败、安装慢、无法启动apiserver,一条命令解决

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Docker和Kubernetes是目前非常流行的容器化技术,可以帮助开发人员更好的构建、管理和部署应用程序。下面将介绍如何在一台主机上搭建Docker和Kubernetes集群环境,并部署分布式应用程序。 第一步是安装Docker和Kubernetes,安装方式根据不同的操作系统会略有不同。安装完成后,需要对Docker进行一些配置,让它可以将Docker镜像推送和拉取到Kubernetes集群中。这一步可以通过配置Docker的daemon.json文件来完成。 接下来,需要搭建Kubernetes集群。首先需要安装etcd,它是Kubernetes的数据存储后端。然后安装kubectl命令行工具,用于管理Kubernetes集群。 部署Kubernetes集群后,需要将应用程序打包成Docker镜像,并推送到Docker镜像仓库中。然后,通过编写Kubernetes的YAML文件来定义应用程序的部署方式、服务、副本等信息。最后,使用kubectl apply命令来将YAML文件应用到Kubernetes集群中,实现应用程序的部署和运行。 如果需要对应用程序进行扩容,可以通过kubectl scale命令来水平扩展副本数。如果需要对应用程序进行升级,可以通过修改YAML文件并使用kubectl apply命令来实现。 总之,通过搭建Docker和Kubernetes集群环境,我们可以更轻松、高效的构建、管理和部署分布式应用程序。 ### 回答2: Docker 和 Kubernetes 都是一些颇为流行的容器技术。Docker 以其轻量级和易于部署的特点受到许多人的青睐,而 Kubernetes 则是以其在容器编排和自动化部署上的能力而闻名。本文将介绍如何搭建 Docker 和 Kubernetes 集群环境,并演示如何在分布式应用程序上部署这些技术。 Docker 集群环境: 要搭建 Docker 集群环境,我们需要一个主节点和多个工作节点。可以在机器上安装 Docker 和 Docker Compose。使用 Docker Compose,我们可以轻松创建、启动和停止应用程序,同时便于管理容器。 当我们有多个 Docker 容器的时候,可以将它们放在不同的宿主机上,从而构建一个 Docker 集群。整个集群可以共享一个网络,这样我们就可以在不同的容器间通信。集群中每个节点都可以运行一个容器。这使得我们可以轻易地扩大我们的应用程序,并将它们部署到不同的机器上。 Kubernetes 集群环境: 要搭建 Kubernetes 集群环境,我们首先需要一个主节点和多个工作节点。要安装 Kubernetes 集群,我们可以使用 kubeadm 安装工具。Kubeadm 是一个命令行工具,它可以管理 Kubernetes 集群中的所有节点和服务。 在 Kubernetes 中,我们定义一组容器和服务,并将其称为一个应用程序,这个应用程序可以轻松地在 Kubernetes 集群中部署。Kubernetes 集群还提供了各种管理工具,可以监视应用程序的运行状态并处理故障。 分布式应用部署: 在分布式应用中,Docker 和 Kubernetes 都能够提供强大的支持。使用 Docker,我们可以打包我们的应用程序并将其部署到多个容器中。这样我们就可以轻松地扩大我们的应用程序,并将它们部署到不同的机器上。 使用 Kubernetes,我们可以轻松部署和管理分布式应用程序,同时可以自动地监视、管理和扩展我们的容器。我们可以定义一个 Kubernetes 应用程序对象,该对象将包含我们的容器化应用程序所需的所有配置和信息。 总的来说,Docker 和 Kubernetes 都是非常流行的容器技术,它们能够提供强大的支持,以便我们轻松地部署和管理我们的应用程序。无论你是在单个容器中运行应用程序,还是在整个集群中运行应用程序,这些技术都可以为你节省大量的时间和精力。 ### 回答3: Docker和Kubernetes(简称k8s)是两个广泛应用于容器化解决方案的开源工具。Docker和k8s的联合使用可以提供一个完整的,高度可靠和高度可扩展的容器平台,以便于分布式应用的部署和维护。在本文中,我们将探讨如何在Docker和k8s搭建集群环境及分布式应用部署方案。 首先我们需要安装和配置好Docker和k8s的环境,确保Docker和k8s能够正常工作。假设我们需要在三台机器上部署应用,我们需要在每台机器上安装Docker和k8s,每个Docker节点都要配置k8s本地存储,以保证数据的持久性和多副本数据备份。然后,我们需要在每个Kubernetes节点上部署一个Pod网络,使不同节点上的容器能够相互通信。 然后,我们需要编写Kubernetes 部署清单文件,并将它们发布到 Kubernetes 集群中。清单文件中应包含有关应用程序的必要配置信息,例如应用程序的容器镜像、环境变量、端口号、挂载点和资源请求/限制。我们可以使用Deployment,StatefulSet和DaemonSet三种资源类型来管理应用程序的部署和维护。使用这些资源类型可以实现高可靠性,自动化和灵活性的分布式应用部署和管理。 最后,我们可以使用Kubernetes的服务发现机制来暴露应用程序的服务,以便其他容器或服务可以访问它。这可以通过创建一个Kubernetes的service对象,并将其与应用程序的Pods关联起来来实现。Service对象可以提供一个常量的IP地址和DNS名称来代表应用程序的服务,并确保在容器出现故障时仍然可用。 综上所述,Docker和k8s组合可以提供一个强大的容器化解决方案,以及高度可靠和高度可扩展的平台来部署和维护分布式应用程式。在实践中,通过使用Docker和k8s,我们可以更轻松地部署,运行和管理复杂的应用程序,同时提高生产力和应用程序的可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜晓码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值