Kubernetes(K8s)从入门到精通系列之十:使用 kubeadm 创建一个高可用 etcd 集群

一、etcd高可用拓扑选项

默认情况下,kubeadm 在每个控制平面节点上运行一个本地 etcd 实例。也可以使用外部的 etcd 集群,并在不同的主机上提供 etcd 实例。

可以设置HA集群:

  • 使用堆叠控制控制平面节点,其中 etcd 节点与控制平面节点共存
  • 使用外部 etcd 节点,其中 etcd 在与控制平面不同的节点上运行

1.堆叠(Stacked)etcd 拓扑

堆叠(Stacked)HA 集群是一种这样的拓扑, 其中 etcd 分布式数据存储集群堆叠在 kubeadm 管理的控制平面节点上,作为控制平面的一个组件运行。

每个控制平面节点运行 kube-apiserver、kube-scheduler 和 kube-controller-manager 实例。 kube-apiserver 使用负载均衡器暴露给工作节点。

每个控制平面节点创建一个本地 etcd 成员(member),这个 etcd 成员只与该节点的 kube-apiserver 通信。 这同样适用于本地 kube-controller-manager 和 kube-scheduler 实例。

这种拓扑将控制平面和 etcd 成员耦合在同一节点上。相对使用外部 etcd 集群, 设置起来更简单,而且更易于副本管理。

然而,堆叠集群存在耦合失败的风险。如果一个节点发生故障,则 etcd 成员和控制平面实例都将丢失, 并且冗余会受到影响。你可以通过添加更多控制平面节点来降低此风险。

因此,你应该为 HA 集群运行至少三个堆叠的控制平面节点。

这是 kubeadm 中的默认拓扑。当使用 kubeadm init 和 kubeadm join --control-plane 时, 在控制平面节点上会自动创建本地 etcd 成员。

在这里插入图片描述

2.外部 etcd 拓扑

具有外部 etcd 的 HA 集群是一种这样的拓扑, 其中 etcd 分布式数据存储集群在独立于控制平面节点的其他节点上运行。

就像堆叠的 etcd 拓扑一样,外部 etcd 拓扑中的每个控制平面节点都会运行 kube-apiserver、kube-scheduler 和 kube-controller-manager 实例。 同样,kube-apiserver 使用负载均衡器暴露给工作节点。但是 etcd 成员在不同的主机上运行, 每个 etcd 主机与每个控制平面节点的 kube-apiserver 通信。

这种拓扑结构解耦了控制平面和 etcd 成员。因此它提供了一种 HA 设置, 其中失去控制平面实例或者 etcd 成员的影响较小,并且不会像堆叠的 HA 拓扑那样影响集群冗余。

但此拓扑需要两倍于堆叠 HA 拓扑的主机数量。 具有此拓扑的 HA 集群至少需要三个用于控制平面节点的主机和三个用于 etcd 节点的主机。

在这里插入图片描述

二、准备工作

  • 三个可以通过 2379 和 2380 端口相互通信的主机。本文档使用这些作为默认端口。 不过,它们可以通过 kubeadm 的配置文件进行自定义。
  • 每个主机必须安装 systemd 和 bash 兼容的 shell。
  • 每台主机必须安装有容器运行时、kubelet 和 kubeadm。
  • 每个主机都应该能够访问 Kubernetes 容器镜像仓库 (registry.k8s.io), 或者使用 kubeadm config images list/pull 列出/拉取所需的 etcd 镜像。 本指南将把 etcd 实例设置为由 kubelet 管理的静态 Pod。
  • 一些可以用来在主机间复制文件的基础设施。例如 ssh 和 scp 就可以满足此需求。

三、建立集群

一般来说,是在一个节点上生成所有证书并且只分发这些必要的文件到其它节点上。

1.将 kubelet 配置为 etcd 的服务管理器。

说明:必须在要运行 etcd 的所有主机上执行此操作。

由于 etcd 是首先创建的,因此你必须通过创建具有更高优先级的新文件来覆盖 kubeadm 提供的 kubelet 单元文件。

cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf
# 将下面的 "systemd" 替换为你的容器运行时所使用的 cgroup 驱动。
# kubelet 的默认值为 "cgroupfs"。
# 如果需要的话,将 "containerRuntimeEndpoint" 的值替换为一个不同的容器运行时。
#
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
 enabled: false
webhook:
 enabled: false
authorization:
mode: AlwaysAllow
cgroupDriver: systemd
address: 127.0.0.1
containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
staticPodPath: /etc/kubernetes/manifests
EOF

cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
ExecStart=/usr/bin/kubelet --config=/etc/systemd/system/kubelet.service.d/kubelet.conf
Restart=always
EOF

systemctl daemon-reload
systemctl restart kubelet

检查 kubelet 的状态以确保其处于运行状态:

systemctl status kubelet

2.为 kubeadm 创建配置文件。

使用以下脚本为每个将要运行 etcd 成员的主机生成一个 kubeadm 配置文件。

# 使用你的主机 IP 更新 HOST0、HOST1 和 HOST2 的 IP 地址
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8

# 使用你的主机名更新 NAME0、NAME1 和 NAME2
export NAME0="infra0"
export NAME1="infra1"
export NAME2="infra2"

# 创建临时目录来存储将被分发到其它主机上的文件
mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/

HOSTS=(${HOST0} ${HOST1} ${HOST2})
NAMES=(${NAME0} ${NAME1} ${NAME2})

for i in "${!HOSTS[@]}"; do
HOST=${HOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
---
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: InitConfiguration
nodeRegistration:
 name: ${NAME}
localAPIEndpoint:
 advertiseAddress: ${HOST}
---
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: ClusterConfiguration
etcd:
 local:
     serverCertSANs:
     - "${HOST}"
     peerCertSANs:
     - "${HOST}"
     extraArgs:
         initial-cluster: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380
         initial-cluster-state: new
         name: ${NAME}
         listen-peer-urls: https://${HOST}:2380
         listen-client-urls: https://${HOST}:2379
         advertise-client-urls: https://${HOST}:2379
         initial-advertise-peer-urls: https://${HOST}:2380
EOF
done

3.生成证书颁发机构。

如果你已经拥有 CA,那么唯一的操作是复制 CA 的 crt 和 key 文件到 etc/kubernetes/pki/etcd/ca.crt 和 /etc/kubernetes/pki/etcd/ca.key。 复制完这些文件后继续下一步,“为每个成员创建证书”。

如果你还没有 CA,则在 $HOST0(你为 kubeadm 生成配置文件的位置)上运行此命令。

kubeadm init phase certs etcd-ca

这一操作创建如下两个文件:

  • /etc/kubernetes/pki/etcd/ca.crt
  • /etc/kubernetes/pki/etcd/ca.key

4.为每个成员创建证书。

kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST2}/
# 清理不可重复使用的证书
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete

kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST1}/
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete

kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
# 不需要移动 certs 因为它们是给 HOST0 使用的

# 清理不应从此主机复制的证书
find /tmp/${HOST2} -name ca.key -type f -delete
find /tmp/${HOST1} -name ca.key -type f -delete

5.复制证书和 kubeadm 配置。

证书已生成,现在必须将它们移动到对应的主机。

USER=ubuntu
HOST=${HOST1}
scp -r /tmp/${HOST}/* ${USER}@${HOST}:
ssh ${USER}@${HOST}
USER@HOST $ sudo -Es
root@HOST $ chown -R root:root pki
root@HOST $ mv pki /etc/kubernetes/

6.确保已经所有预期的文件都存在

$HOST0 所需文件的完整列表如下:

/tmp/${HOST0}
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
    ├── ca.crt
    ├── ca.key
    ├── healthcheck-client.crt
    ├── healthcheck-client.key
    ├── peer.crt
    ├── peer.key
    ├── server.crt
    └── server.key

在 $HOST1 上:

$HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
    ├── ca.crt
    ├── healthcheck-client.crt
    ├── healthcheck-client.key
    ├── peer.crt
    ├── peer.key
    ├── server.crt
    └── server.key

在 $HOST2 上:

$HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
    ├── ca.crt
    ├── healthcheck-client.crt
    ├── healthcheck-client.key
    ├── peer.crt
    ├── peer.key
    ├── server.crt
    └── server.key

7.创建静态 Pod 清单。

既然证书和配置已经就绪,是时候去创建清单了。 在每台主机上运行 kubeadm 命令来生成 etcd 使用的静态清单。

root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml

8.可选:检查集群运行状况。

如果 etcdctl 不可用,你可以在容器镜像内运行此工具。 你可以使用 crictl run 这类工具直接在容器运行时执行此操作,而不是通过 Kubernetes。

ETCDCTL_API=3 etcdctl \
--cert /etc/kubernetes/pki/etcd/peer.crt \
--key /etc/kubernetes/pki/etcd/peer.key \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://${HOST0}:2379 endpoint health
...
https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms
https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms
https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms
  • 将 ${HOST0} 设置为要测试的主机的 IP 地址。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是以markdown写一份k8s从入门到精通的操作学习使用笔记手册: # k8s从入门到精通的操作学习使用笔记手册 ## 简介 Kubernetes,缩写为K8s,是一个开源的容器编排平台,旨在自动化应用程序的部署,扩展和管理。它提供了一种简单而灵活的方式来部署和管理容器化应用程序,并且可以快速地实现水平扩展。 在本笔记手册中,我们将介绍Kubernetes的基本概念,并带领大家从入门到精通地学习使用Kubernetes。 ## 基本概念 ### Pod Pod是Kubernetes中的最小部署单元,它是一个或多个容器的集合,这些容器共享网络和存储。Pod在Kubernetes中是一个非常重要的概念,可以用来部署和管理容器化应用程序。 ### Deployment Deployment是一组Pod的控制器,它们负责在Kubernetes集群中创建、更新和删除Pod。Deployment可以保证Pod的副本数量,并监控它们的状态,如果发生故障则可以自动恢复。Deployment还可以实现滚动更新和回滚,以确保应用程序的连续性。 ### Service Service是Kubernetes中的一种抽象概念,它可以将多个Pod作为一个逻辑单元来管理,并提供一个统一的网络入口。Service可以通过标签选择器选择想要连接的Pod,并且支持负载均衡和故障转移。Service是一个非常关键的概念,它可以帮助我们构建可靠和高效的微服务应用程序。 ### ConfigMap ConfigMap是一种以键值对形式存储配置数据的对象,它可以在Kubernetes中共享配置信息。配置数据可以在容器中作为环境变量、命令行参数或者挂载的文件方式使用,可以方便地实现应用程序的集中管理和更新。 ### Secret Secret是一种安全的对象,它可以存储敏感数据,如密码、证书和密钥等。Secret可以以加密的方式存储,确保敏感数据的安全性,同时也可以在容器使用,方便地实现应用程序的安全管理。 ## 操作学习 ### 安装Kubernetes 首先,我们需要在本地机器或者云环境中安装Kubernetes。你可以根据自己的需求选择使用Minikube、kubeadm或者云平台提供的Kubernetes服务。在这里,我们选择使用Minikube进行本地安装和学习。 Minikube是一个轻量级的本地Kubernetes环境,可以在本地机器上快速安装和启动Kubernetes集群。你可以在官网上下载安装包,然后按照官方文档进行安装。 ### 创建Pod 在安装好Kubernetes后,我们就可以创建第一个Pod了。为了简单起见,我们创建一个简单的Nginx应用程序作为Pod。在创建Pod之前,我们需要编写一个Pod的配置文件。 在本例中,我们创建一个名为nginx.yaml的配置文件,内容如下: ``` apiVersion: v1 kind: Pod metadata: name: nginx-pod spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 ``` 这个配置文件定义了一个名为nginx-pod的Pod,其中包含一个名为nginx的容器使用最新版的Nginx镜像,并将容器的80端口暴露出去。 我们使用kubectl命令来创建Pod: ``` kubectl create -f nginx.yaml ``` 执行成功后,我们就创建了一个名为nginx-pod的Pod。 ### 创建Deployment 在创建了第一个Pod之后,我们需要更进一步地控制它。为此,我们可以创建一个Deployment来管理Pod,并确保Pod的副本数量。 在本例中,我们创建一个名为nginx-deployment的Deployment,配置文件如下: ``` apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 ``` 这个配置文件定义了一个名为nginx-deployment的Deployment,它包含了两个nginx Pod,并且使用了nginx镜像。 我们使用kubectl命令来创建Deployment: ``` kubectl create -f nginx-deployment.yaml ``` 执行成功后,我们就创建了一个名为nginx-deployment的Deployment,并且Pod副本数量为2。 ### 创建Service 在创建了一个Deployment之后,我们需要将其暴露出去,以便外部用户可以访问应用程序。我们可以使用Service来实现这个功能。 在本例中,我们创建一个名为nginx-service的Service,配置文件如下: ``` apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort ``` 这个配置文件定义了一个名为nginx-service的Service,它将流量转发到包含app=nginx标签的Pod,并将端口80映射到Pod的80端口。 我们使用kubectl命令来创建Service: ``` kubectl create -f nginx-service.yaml ``` 执行成功后,我们就创建了一个名为nginx-service的Service,并将其暴露出去,以便外部用户可以访问应用程序。 ### 使用ConfigMap和Secret 在应用程序开发中,我们通常需要存储和管理一些配置信息和敏感数据。Kubernetes中提供了ConfigMap和Secret来解决这个问题。 ConfigMap和Secret可以通过kubectl命令进行创建和管理。在创建ConfigMap和Secret时,我们需要首先将配置数据和敏感数据转换成键值对的形式,并存储在配置文件中。然后,我们使用kubectl命令来创建ConfigMap和Secret。 在本例中,我们创建了一个名为nginx-config的ConfigMap,配置文件如下: ``` apiVersion: v1 kind: ConfigMap metadata: name: nginx-config data: nginx.conf: | server { listen 80; server_name example.com; location / { proxy_pass http://localhost:8080; } } ``` 这个配置文件定义了一个名为nginx-config的ConfigMap,其中包含了一个名为nginx.conf的配置文件。 我们使用kubectl命令来创建ConfigMap: ``` kubectl create configmap nginx-config --from-file=nginx.conf ``` 执行成功后,我们就创建了一个名为nginx-config的ConfigMap,并将其存储在Kubernetes中。 类似地,我们创建了一个名为nginx-secret的Secret,用来存储敏感数据: ``` apiVersion: v1 kind: Secret metadata: name: nginx-secret type: Opaque data: username: YWRtaW4= password: MWYyZDFlMmU2N2Rm ``` 我们使用kubectl命令来创建Secret: ``` kubectl create secret generic nginx-secret --from-literal=username=admin --from-literal=password=123456 ``` 执行成功后,我们就创建了一个名为nginx-secret的Secret,并将其存储在Kubernetes中。 ### 总结 本文介绍了Kubernetes的基本概念,并带领大家从入门到精通地学习了Kubernetes的操作。在实际应用程序开发中,Kubernetes是一个非常强大的工具,可以帮助我们实现应用程序的自动化部署、扩展和管理,同时也可以提高应用程序的可靠性和高可用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

最笨的羊羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值