k8s etcd

  |  

全部的 K8S学习笔记总目录,请点击查看。

etcd是k8s的核心组件之一,主要用于存储k8s集群的所有数据,包括集群的配置信息、集群状态、集群资源等。etcd是一个分布式的、高可用的、一致性的、高性能的键值存储系统,是k8s集群的数据存储中心。

ETCD命令行工具

拷贝etcdctl命令行工具(附加启动etcd命令):

二进制方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ETCD_VER=v3.4.27

# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version

ln -s /tmp/etcd-download-test/etcdctl /usr/local/bin/

启动etcd命令(对之后的说明没有影响):

1
2
3
4
5
6
# start a local etcd server
/tmp/etcd-download-test/etcd

# write,read to etcd
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 put foo bar
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 get foo

docker 方式

1
2
3
docker pull gcr.io/etcd-development/etcd:v3.4.27
docker run --rm --name etcd -d gcr.io/etcd-development/etcd:v3.4.27 /usr/local/bin/etcd
docker cp etcd:/usr/local/bin/etcdctl /usr/local/bin/

启动etcd命令(对之后的说明没有影响):

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
rm -rf /tmp/etcd-data.tmp && mkdir -p /tmp/etcd-data.tmp && \
docker rmi gcr.io/etcd-development/etcd:v3.4.27 || true && \
docker run \
-p 2379:2379 \
-p 2380:2380 \
--mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
--name etcd-gcr-v3.4.27 \
gcr.io/etcd-development/etcd:v3.4.27 \
/usr/local/bin/etcd \
--name s1 \
--data-dir /etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://0.0.0.0:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://0.0.0.0:2380 \
--initial-cluster s1=http://0.0.0.0:2380 \
--initial-cluster-token tkn \
--initial-cluster-state new \
--log-level info \
--logger zap \
--log-outputs stderr

docker exec etcd-gcr-v3.4.27 /usr/local/bin/etcd --version
docker exec etcd-gcr-v3.4.27 /usr/local/bin/etcdctl version
docker exec etcd-gcr-v3.4.27 /usr/local/bin/etcdctl endpoint health
docker exec etcd-gcr-v3.4.27 /usr/local/bin/etcdctl put foo bar
docker exec etcd-gcr-v3.4.27 /usr/local/bin/etcdctl get foo

ETCD常用操作

查看etcd集群的成员节点

1
2
3
4
5
6
$ export ETCDCTL_API=3
$ etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key member list -w table

$ alias etcdctl='etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key'

$ etcdctl member list -w table

查看etcd集群节点状态

1
2
3
$ etcdctl endpoint status -w table

$ etcdctl endpoint health -w table

设置key值

1
2
$ etcdctl put test 1
$ etcdctl get test

查看所有key值

1
$ etcdctl get / --prefix --keys-only

查看具体的key对应的数据

1
$ etcdctl get /registry/pods/test/myblog-84985b5b66-jp9gg

list-watch

1
2
3
4
$ etcdctl watch /test/ --prefix

# 另一个终端输入,之前的终端会有输出
$ etcdctl put /test/key1 val1

快照与恢复(重要!)

添加定时任务做数据快照

1
$ etcdctl snapshot save `hostname`-etcd_`date +%Y%m%d%H%M`.db

恢复快照:

  1. 停止etcd和apiserver(防止新数据写入)

  2. 移走当前数据目录

    1
    $ mv /var/lib/etcd/ /tmp
  3. 恢复快照

    1
    $ etcdctl snapshot restore `hostname`-etcd_`date +%Y%m%d%H%M`.db --data-dir=/var/lib/etcd/
  4. 集群恢复

    https://github.com/etcd-io/etcd/blob/release-3.3/Documentation/op-guide/recovery.md

namespace删除问题

很多情况下,会出现namespace删除卡住的问题,此时可以通过操作etcd来删除数据:

1
2
3
4
5
6
# 查看namespace相关的数据
$ etcdctl get / --prefix --keys-only | grep namespace | grep delete-ns
/registry/namespaces/delete-ns

# 删除namespace相关的数据
$ etcdctl del /registry/namespaces/delete-ns

故障恢复

etcd集群故障恢复

因为etcd中存储着最重要的数据,所以etcd集群的故障恢复是最重要的。如果节点故障,无法正常启动则需要添加新节点进行恢复。

  1. 将etcd备份数据拷贝到新节点

    1
    $ scp /backup/etcd-202109031100.db root@new-etcd:/tmp/
  2. 将数据恢复到新节点

    1
    $ etcdctl snapshot restore /tmp/etcd-202109031100.db --data-dir=/var/lib/etcd/
  3. 新节点启动etcd

    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
    $ name="etcd-new"
    $ host="etcd-new-ip"
    $ cluster="etcd1=http://etcd-new-ip:2380"

    $ docker run -d --privileged=true \
    -p 2379:2379 \
    -p 2380:2380 \
    -v /var/lib/etcd:/data/etcd \
    --restart=always \
    --name ${name} \
    --net=host \
    -v /etc/kubernetes/pki/etcd:/etc/kubernetes/pki/etcd \
    gcr.io/coreos/etcd:v3.5.0 \
    /usr/local/bin/etcd \
    --name ${name} \
    --data-dir /data/etcd \
    --listen-client-urls http://${host}:2379 \
    --advertise-client-urls http://${host}:2379 \
    --listen-peer-urls http://${host}:2380 \
    --initial-advertise-peer-urls http://${host}:2380 \
    --initial-cluster ${cluster} \
    --initial-cluster-token tkn \
    --initial-cluster-state new \
    --force-new-cluster \
    --log-level info \
    --logger zap \
    --log-outputs stderr

    虽然已经导入了数据,但是还是需要重新初始化集群,重新建立连接,所以需要加上--force-new-cluster参数。

  4. 验证集群状态

    1
    2
    3
    4
    5
    $ export ETCDCTL_API=3
    $ export ETCD_ENDPOINTS="http://etcd-new-ip:2379"
    $ etcdctl --endpoints=${ETCD_ENDPOINTS} -w table member list
    $ etcdctl --endpoints=${ETCD_ENDPOINTS} -w table endpoint status
    $ etcdctl --endpoints=${ETCD_ENDPOINTS} get / --prefix --keys-only

etcd集群增量恢复

如果etcd集群中的数据丢失了一部分,可以通过增量恢复的方式来恢复数据。比如有备份数据etcd-backup1.db和备份数据etc-backup2.db,两次备份数据相差1天,我们丢失了数据,可以只恢复这1天的数据。

  1. etcdhelper源码下载

    etcdhelper不提供二进制文件,需要自己编译,所以需要下载源码:

    1
    $ git clone https://github.com/openshift/origin.git
  2. 编译etcdhelper

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ docker run -d --name go-builder golang:1.17 sleep 3600
    $ docker cp origin-master go-builder:/go
    $ docker exec -ti go-builder bash

    # cd /go/orign-master
    # go env -w GOPROXY=https://goproxy.cn,direct
    # CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build tools/etcdhelper/etcdhelper.go
    # exit

    $ docker cp go-builder:/go/origin-master/etcdhelper .
    $ cp etcdhelper /usr/local/bin/
  3. etcdhelper使用

    etcdhelper使用方式和etcdctl类似,只是etcdhelper是对etcdctl的封装,可以批量操作,比如批量删除等。获取到的数据是json格式,可以直接查看。

    1
    2
    3
    4
    $ export ETCDCTL_API=3
    $ export ETCD_ENDPOINTS="http://etcd-new-ip:2379"
    $ etcdhelper -endpoints=${ETCD_ENDPOINTS} ls
    $ etcdhelper -endpoints=${ETCD_ENDPOINTS} get /registry/pods/test/myblog-84985b5b66-jp9gg
  4. 增量恢复

    比如我们丢失了etcd-backup1.dbetcd-backup2.db之间的数据,我们可以通过etcdhelper获取到这段时间的数据,然后再导入到etcd集群中。这里我们举例误删除了namespace为test下的所有资源情况。

    首先我们找一台新机器,恢复etcd-backup1.db的数据,因为etcd-backup1.db是完整的数据,包含被删除的数据。恢复方法参考上面的故障恢复。

  5. 批量操作获取yaml文件

    kubectl没有办法直接使用json格式的文件,因此需要将json格式的文件转换为yaml格式的文件,然后再使用kubectl apply命令。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $ export ETCDCTL_API=3
    $ export ETCD_ENDPOINTS="http://etcd-new-ip:2379"
    $ etcdctl --endpoints=${ETCD_ENDPOINTS} get / --prefix --keys-only | grep test > keys.txt

    # 使用脚本利用etcdhelper将key转换成为json文件
    cat key_to_json.sh

    #!/bin/bash

    i=0
    export ETCDCTL_API=3
    export ETCD_ENDPOINTS=etcd-new-ip:2379
    for line in `cat keys.txt`
    do
    etcdhelper -endpoint $ETCD_ENDPOINTS get $line > $i.json
    # 第一行是资源类型和版本,不是json格式,需要删除
    sed -i '1d' $i.json
    let 'i+=1'
    done

    运行脚本,将key转换成为json文件:

    1
    $ ./key_to_json.sh

    将json文件转换成为yaml文件:

    1
    2
    # json to yaml,具体方法就不写了,内容还比较简单
    $ python3 json_to_yaml.py
  6. 批量导入操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ cat apply.sh
    #!/bin/bash

    i=0
    for line in `cat keys.txt`
    do
    kubectl apply -f $i.yaml
    let 'i+=1'
    done

    $ ./apply.sh
文章目录
  1. 1. ETCD命令行工具
    1. 1.1. 二进制方式
    2. 1.2. docker 方式
  2. 2. ETCD常用操作
    1. 2.1. 查看etcd集群的成员节点
    2. 2.2. 查看etcd集群节点状态
    3. 2.3. 设置key值
    4. 2.4. 查看所有key值
    5. 2.5. 查看具体的key对应的数据
    6. 2.6. list-watch
    7. 2.7. 快照与恢复(重要!)
    8. 2.8. namespace删除问题
  3. 3. 故障恢复
    1. 3.1. etcd集群故障恢复
    2. 3.2. etcd集群增量恢复