Kubernetes

Kubernetes 集群部署 - etcd 安装与配置

etcd 作为 Kubernetes 的数据存储核心,稳定可靠的部署至关重要

📋 概述

etcd 是 Kubernetes 集群的核心数据存储组件,负责存储集群的所有配置数据、状态信息和元数据。本文档提供 etcd 集群的完整安装、配置和部署方案。

架构说明

  • 集群模式: 建议至少 3 个节点(奇数个节点,避免脑裂)
  • 数据目录: /var/lib/etcd
  • 配置文件: /etc/etcd/etcd.conf
  • 服务文件: /etc/systemd/system/etcd.service
  • 端口:
    • 2379: 客户端通信端口
    • 2380: 节点间通信端口

🔧 环境准备

节点信息配置

根据实际环境修改以下节点信息:

# 节点格式: 主机名:IP地址:etcd节点名
NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

系统要求

  • 操作系统: CentOS 7+ / Ubuntu 18.04+
  • 内存: 至少 2GB(推荐 4GB+)
  • 磁盘: 至少 20GB 可用空间(SSD 推荐)
  • 网络: 节点间网络延迟 < 10ms

📦 安装 etcd

步骤 1: 下载 etcd 二进制文件

#!/bin/bash
# install-etcd.sh - etcd 安装脚本

set -e

ETCD_VERSION="v3.5.9"  # 根据 K8s 版本选择兼容的 etcd 版本
INSTALL_DIR="/usr/local/bin"
DATA_DIR="/var/lib/etcd"
CONFIG_DIR="/etc/etcd"

# 交互式确认
read -p "是否执行 etcd 安装步骤?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过 etcd 安装"
    exit 0
fi

echo "=== 开始安装 etcd ${ETCD_VERSION} ==="

# 创建必要目录
sudo mkdir -p ${INSTALL_DIR}
sudo mkdir -p ${DATA_DIR}
sudo mkdir -p ${CONFIG_DIR}

# 下载 etcd
cd /tmp
wget https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz

# 解压并安装
tar -xzf etcd-${ETCD_VERSION}-linux-amd64.tar.gz
sudo cp etcd-${ETCD_VERSION}-linux-amd64/etcd* ${INSTALL_DIR}/
sudo chmod +x ${INSTALL_DIR}/etcd*

# 验证安装
${INSTALL_DIR}/etcd --version
${INSTALL_DIR}/etcdctl version

echo "✓ etcd 安装完成"

步骤 2: 配置 etcd 集群

#!/bin/bash
# configure-etcd.sh - etcd 集群配置脚本

set -e

NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

ETCD_VERSION="v3.5.9"
INSTALL_DIR="/usr/local/bin"
DATA_DIR="/var/lib/etcd"
CONFIG_DIR="/etc/etcd"
CERT_DIR="/etc/etcd/ssl"

# 交互式确认
read -p "是否执行 etcd 集群配置?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过 etcd 配置"
    exit 0
fi

echo "=== 开始配置 etcd 集群 ==="

# 生成集群初始成员列表
INITIAL_CLUSTER=""
for NODE_INFO in "${NODES[@]}"; do
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    INITIAL_CLUSTER+="${ETCD_NAME}=https://${NODE_IP}:2380,"
done
INITIAL_CLUSTER=${INITIAL_CLUSTER%,}

echo "集群成员列表: ${INITIAL_CLUSTER}"

# 为每个节点配置 etcd
for NODE_INFO in "${NODES[@]}"; do
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    
    echo "配置节点: ${HOSTNAME} (${ETCD_NAME})"
    
    ssh root@${NODE_IP} << EOF
        # 创建目录
        mkdir -p ${DATA_DIR}
        mkdir -p ${CONFIG_DIR}
        mkdir -p ${CERT_DIR}
        
        # 创建 etcd 配置文件
        cat > ${CONFIG_DIR}/etcd.conf << EOC
# 节点名称
ETCD_NAME=${ETCD_NAME}
# 数据目录
ETCD_DATA_DIR=${DATA_DIR}
# 监听客户端请求的地址
ETCD_LISTEN_CLIENT_URLS=https://${NODE_IP}:2379,https://127.0.0.1:2379
# 监听对等节点请求的地址
ETCD_LISTEN_PEER_URLS=https://${NODE_IP}:2380
# 客户端访问地址
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${NODE_IP}:2380
ETCD_ADVERTISE_CLIENT_URLS=https://${NODE_IP}:2379
# 初始集群成员列表
ETCD_INITIAL_CLUSTER=${INITIAL_CLUSTER}
# 集群状态(new 表示新集群,existing 表示加入已有集群)
ETCD_INITIAL_CLUSTER_STATE=new
# 集群 token
ETCD_INITIAL_CLUSTER_TOKEN=k8s-etcd-cluster
# 客户端证书配置(如果使用 TLS)
ETCD_CLIENT_CERT_AUTH=true
ETCD_CERT_FILE=${CERT_DIR}/server.crt
ETCD_KEY_FILE=${CERT_DIR}/server.key
ETCD_TRUSTED_CA_FILE=${CERT_DIR}/ca.crt
# 对等节点证书配置
ETCD_PEER_CLIENT_CERT_AUTH=true
ETCD_PEER_CERT_FILE=${CERT_DIR}/peer.crt
ETCD_PEER_KEY_FILE=${CERT_DIR}/peer.key
ETCD_PEER_TRUSTED_CA_FILE=${CERT_DIR}/ca.crt
EOC
        
        # 设置权限
        chmod 644 ${CONFIG_DIR}/etcd.conf
        chown -R etcd:etcd ${DATA_DIR} ${CONFIG_DIR} 2>/dev/null || true
        
        echo "✓ ${HOSTNAME} 配置完成"
EOF
done

echo "✓ etcd 集群配置完成"

步骤 3: 创建 systemd 服务

#!/bin/bash
# setup-etcd-service.sh - 创建 etcd systemd 服务

set -e

NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/etcd"

# 交互式确认
read -p "是否创建 etcd systemd 服务?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过服务创建"
    exit 0
fi

echo "=== 创建 etcd systemd 服务 ==="

for NODE_INFO in "${NODES[@]}"; do
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    
    echo "为 ${HOSTNAME} 创建服务..."
    
    ssh root@${NODE_IP} << EOF
        cat > /etc/systemd/system/etcd.service << EOS
[Unit]
Description=Etcd Server
Documentation=https://github.com/coreos/etcd
After=network.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=-${CONFIG_DIR}/etcd.conf
ExecStart=${INSTALL_DIR}/etcd
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
# 关键:增加启动超时时间,避免集群启动时超时
TimeoutStartSec=120

[Install]
WantedBy=multi-user.target
EOS
        
        # 重新加载 systemd
        systemctl daemon-reload
        systemctl enable etcd
        
        echo "✓ ${HOSTNAME} 服务创建完成"
EOF
done

echo "✓ etcd 服务创建完成"

🚀 启动 etcd 集群

步骤 4: 启动集群

#!/bin/bash
# start-etcd-cluster.sh - 启动 etcd 集群

set -e

NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

# 交互式确认
read -p "是否启动 etcd 集群?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过集群启动"
    exit 0
fi

echo "=== 启动 etcd 集群 ==="

# 按顺序启动节点(避免同时启动导致的问题)
for i in "${!NODES[@]}"; do
    NODE_INFO="${NODES[$i]}"
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    
    echo "启动节点 ${HOSTNAME} (第 $((i+1)) 个节点)..."
    
    ssh root@${NODE_IP} "systemctl start etcd"
    
    # 等待节点启动
    sleep 5
    
    # 检查节点状态
    if ssh root@${NODE_IP} "systemctl is-active --quiet etcd"; then
        echo "✓ ${HOSTNAME} 启动成功"
    else
        echo "✗ ${HOSTNAME} 启动失败,请检查日志: journalctl -u etcd -n 50"
    fi
done

echo "=== 检查集群状态 ==="
# 使用第一个节点检查集群状态
FIRST_NODE="${NODES[0]}"
IFS=':' read -r FIRST_HOST FIRST_IP FIRST_NAME <<< "$FIRST_NODE"

ssh root@${FIRST_IP} "/usr/local/bin/etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/ssl/ca.crt --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key endpoint health" || echo "注意: 如果使用 TLS,请确保证书已正确配置"

echo "✓ etcd 集群启动完成"

✅ 验证和监控

检查集群状态

# 检查服务状态
systemctl status etcd

# 查看日志
journalctl -u etcd -f

# 检查集群健康(如果使用 TLS)
etcdctl --endpoints=https://127.0.0.1:2379 \
    --cacert=/etc/etcd/ssl/ca.crt \
    --cert=/etc/etcd/ssl/server.crt \
    --key=/etc/etcd/ssl/server.key \
    endpoint health

# 查看集群成员
etcdctl --endpoints=https://127.0.0.1:2379 \
    --cacert=/etc/etcd/ssl/ca.crt \
    --cert=/etc/etcd/ssl/server.crt \
    --key=/etc/etcd/ssl/server.key \
    member list

常用维护命令

# 备份 etcd 数据
etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db

# 恢复 etcd 数据
etcdctl snapshot restore /backup/etcd-snapshot-20231229.db \
    --data-dir=/var/lib/etcd-restore

# 查看集群统计信息
etcdctl endpoint status --write-out=table

📝 注意事项

  1. 证书配置: 如果使用 TLS,确保所有节点的证书已正确配置
  2. 网络连通性: 确保所有节点间的 2379 和 2380 端口互通
  3. 数据备份: 定期备份 etcd 数据,防止数据丢失
  4. 资源监控: 监控 etcd 的 CPU、内存和磁盘使用情况
  5. 版本兼容: 确保 etcd 版本与 Kubernetes 版本兼容

🔗 相关资源

第三章:飞升上界 · 云原生与K8s

韩门已成气候,需飞升云上仙境,领悟Kubernetes的天道意志

楔子:韩门的困境

建立韩门后,韩立在源界中声名鹊起。他的微服务架构稳定可靠,能够处理大量的业务请求,赢得了众多客户的信任。

然而,随着业务规模的不断扩大,韩立发现了一个严重的问题:服务的管理和运维变得越来越困难。

每当流量增加时,韩立需要手动增加服务器,部署新的服务实例。这个过程需要:

  1. 购买或申请新的服务器
  2. 安装操作系统和依赖
  3. 部署Docker和配置网络
  4. 部署服务并配置监控
  5. 更新负载均衡配置

整个过程需要数小时甚至数天,响应速度太慢。而且,当流量减少时,服务器资源闲置,造成巨大的浪费。

更糟糕的是,当某个服务实例崩溃时,需要人工介入才能恢复。如果是在深夜,可能几个小时都无法恢复,严重影响业务。

“这样下去不行…“韩立看着运维团队疲惫的身影,心中涌起一股无力感。

他听说,在源界的高层,有一个叫做"云上仙境"的地方。那里有一种叫做"Kubernetes"的天道意志,可以自动调度资源、管理服务、实现扩缩容和自愈。

“我一定要飞升上界,掌握Kubernetes!“韩立下定了决心。


第一节:初入云上仙境

经过数月的准备,韩立终于踏上了飞升之路。他带着韩门的所有服务,来到了云上仙境。

云上仙境,是一个由无数服务器组成的巨大集群。这里的服务器被称为"节点”(Node),分为两种:

  • Master节点:控制节点,负责整个集群的管理和调度
  • Worker节点:工作节点,负责运行实际的业务服务

韩立刚进入云上仙境,就感受到了一股强大的意志——这就是Kubernetes,云上仙境的天道意志。

Kubernetes(简称K8s)是一个容器编排系统,它的核心思想是"声明式API”——你只需要告诉它你想要的状态,它会自动帮你实现。

比如,你想要3个用户服务的实例运行,你只需要声明:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
spec:
  replicas: 3  # 我想要3个实例
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: user-service:1.0.0
        ports:
        - containerPort: 8080

Kubernetes会自动:

  1. 检查当前有多少个实例在运行
  2. 如果少于3个,创建新的实例
  3. 如果多于3个,删除多余的实例
  4. 如果某个实例崩溃,自动重启或创建新的实例

这就是"言出法随”——你只需要声明想要的状态,Kubernetes会自动帮你达成。


第二节:洞天法宝——Pod

在Kubernetes中,最小的部署单元是Pod。Pod就像源界中的"洞天法宝”,是一个独立的运行环境,可以包含一个或多个容器。

韩立创建了他的第一个Pod:

apiVersion: v1
kind: Pod
metadata:
  name: user-service-pod
spec:
  containers:
  - name: user-service
    image: user-service:1.0.0
    ports:
    - containerPort: 8080
    resources:
      requests:
        memory: "256Mi"
        cpu: "100m"
      limits:
        memory: "512Mi"
        cpu: "500m"

Pod的特点: