实战操作-介绍 ETCD 部署两种形式

1. 二进制部署

本文着重介绍集群采用二进制包安装 etcd 。以 etcd-v3.3.15为例。

假设:

  • etcd1:10.16.11.180
  • etcd2:10.16.11.182
  • etcd3:10.16.11.181

三台主机从官方下载的发行版二进制包,手动部署,组成kubernetes etcd集群。

1.1 以下三台主机操作

#关闭防火墙
#systemctl stop firewalld
#systemctl disable firewalld
#关闭swap
#swapoff -a
#sed -i 's/.*swap.*/#&/' /etc/fstab
#关闭selinux
#setenforce 0
#sed -i "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/selinux/config
#下载
#wget 'https://github.com/etcd-io/etcd/releases/download/v3.3.15/etcd-v3.3.15-linux-amd64.tar.gz'

#添加 etcd 用户
#useradd -r -g etcd -s /bin/false etcd
#解压、拷贝二进制文件
#tar -zxvf etcd-v3.3.15-linux-amd64.tar.gz
#cd etcd-v3.3.15-linux-amd64.tar.gz 
#cp etcd* /usr/local/sbin/
#创建目录
#mkdir /data/k8s/etcd/{data,wal} -p
#mkdir -p /etc/etcd
#chown -R etcd.etcd /data/k8s/etcd

etcd 就会在默认的工作目录下生成两个子目录:snap 和 wal。两个目录的作用说明如下。

· snap:用于存放快照数据。Etcd 为防止 WAL 文件过多会创建快照,snap 用于存储 Etcd 的快照数据状态。

· wal:用于存放预写式日志,其最大的作用是记录整个数据变化的全部历程。在 Etcd 中,所有数据的修改在提交前,都要先写入 WAL 中。使用 WAL 进行数据的存储使得 Etcd 拥有故障快速回复和数据回滚这两个重要功能。

1.2 编辑 etcd 配置文件

etcd1

#vim  /etc/etcd/etcd.conf
ETCD_NAME="etcd1"
ETCD_DATA_DIR="/data/k8s/etcd/data"
ETCD_WAL_DIR="/data/k8s/etcd/wal"
ETCD_LISTEN_CLIENT_URLS="http://10.16.11.180:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://10.16.11.180:2379"
ETCD_LISTEN_PEER_URLS="http://10.16.11.180:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.16.11.180:2380"
ETCD_INITIAL_CLUSTER="etcd1=https://10.16.11.180:2380,etcd2=https://10.16.11.182:2380,etcd3=https://10.16.11.181:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-token"
ETCD_INITIAL_CLUSTER_STATE="new"

etcd2

#vim  /etc/etcd/etcd.conf
ETCD_NAME="etcd2"
ETCD_DATA_DIR="/data/k8s/etcd/data"
ETCD_WAL_DIR="/data/k8s/etcd/wal"
ETCD_LISTEN_CLIENT_URLS="http://10.16.11.182:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://10.16.11.182:2379"
ETCD_LISTEN_PEER_URLS="http://10.16.11.182:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.16.11.182:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://10.16.11.180:2380,etcd2=http://10.16.11.182:2380,etcd3=http://10.16.11.181:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-token"
ETCD_INITIAL_CLUSTER_STATE="new"

etcd 3

#vim  /etc/etcd/etcd.conf
ETCD_NAME="etcd3"
ETCD_DATA_DIR="/data/k8s/etcd/data"
ETCD_WAL_DIR="/data/k8s/etcd/wal"
ETCD_LISTEN_CLIENT_URLS="http://10.16.11.180:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://10.16.11.180:2379"
ETCD_LISTEN_PEER_URLS="http://10.16.11.180:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.16.11.180:2380"
ETCD_INITIAL_CLUSTER="etcd1=https://10.16.11.180:2380,etcd2=https://10.16.11.182:2380,etcd3=https://10.16.11.181:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-token"
ETCD_INITIAL_CLUSTER_STATE="new"

解释说明如下:

  • ETCD_NAME: 节点名称
  • ETCD_DATA_DIR: 数据目录
  • ETCD_LISTEN_PEER_URLS: 集群通信监听地址
  • ETCD_LISTEN_CLIENT_URLS: 客户端访问监听地址
  • ETCD_INITIAL_ADVERTISE_PEER_URLS: 集群通告地址
  • ETCD_INITIAL_CLUSTER: 集群节点地址
  • ETCD_INITIAL_CLUSTER_STATE: 集群当前状态,new 是新集群,existing表示加入已有集群
  • ETCD_INITIAL_CLUSTER_TOKEN: 集群 Token
  • ETCD_ADVERTISE_CLIENT_URLS: 客户端通告地址

1.3 编辑系统 systemd 文件

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
User=etcd
# set GOMAXPROCS to number of processors
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\"
--advertise-client-urls=\"${ETCD_ADVERTISE_CLIENT_URLS}\" --initial-cluster-token=\"${ETCD_INITIAL_CLUSTER_TOKEN}\" --initial-cluster=\"${ETCD_INITIAL_CLUSTER}\" --initial-cluster-state=\"${ETCD_INITIAL_CLUSTER_STATE}\""
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

· 其他etcd 节点修改—name 为对应,如 etcd2、etcd3。

启动服务

#systemctl daemon-reload
#systemctl enable etcd
#systemctl start etcd
#systemctl status etcd
#etcdctl member list

etcd 集群已经启动。

注:上述并没有使用认证。这是不建议的,缺乏安全性。k8s 集群更容易被黑客利用。所以对于 etcd,证书和备份都是必要的。

etcd 证书类型介绍:

  • client certificate 用于通过服务器验证客户端。例如etcdctl,etcd proxy,fleetctl或docker客户端。
  • server certificate 由服务器使用,并由客户端验证服务器身份。例如docker服务器或kube-apiserver。
  • peer certificate 由 etcd 集群成员使用,供它们彼此之间通信使用。

可以使用 CloudFlare 的 PKI 工具 cfssl 创建所有证书。自建 CA 签发证书,etcd 证书可以共享,在一台 etcd 节点创建,拷贝到其他节点中。

1.4 自建CA签发证书

以下在其中一台 etcd 节点中操作,如 etcd1.

下载 cfssl

#wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
#wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
#chmod 755 cfssl_linux-amd64 cfssljson_linux-amd64
#mv cfssl_linux-amd64 /usr/local/sbin/cfssl
#mv cfssljson_linux-amd64 /usr/local/sbin/cfssljson
#mkdir -p /etc/kubernetes/cert
#mkdir -p /etc/etcd/cert
#mkdir -p /root/ssl

生成证书

#cd /root/ssl
#vim ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}

解释说明:

  • signing 表示该证书可用于签名其它证书,生成的ca.pem证书找中CA=TRUE
  • server auth 表示client可以用该证书对server提供的证书进行验证
  • client auth 表示server可以用该证书对client提供的证书进行验证
#vim ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "GuangDong",
"L": "GuangZhou",
"O": "k8s",
"OU": "4Paradigm"
}
],
"ca": {
"expiry": "876000h"
}
}

说明:

  • CN CommonName,kube-apiserver从证书中提取该字段作为请求的用户名(User Name),浏览器使用该字段验证网站是否合法
  • O Organization,kube-apiserver 从证书中提取该字段作为请求用户和所属组(Group)
  • kube-apiserver将提取的User、Group作为RBAC授权的用户和标识
#cfssl gencert -initca ca-csr.json | cfssljson -bare ca
#vim etcd-csr.json
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"10.16.11.180",
"10.16.11.181",
"10.16.11.182"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "GuangDong",
"L": "GuangZhou",
"O": "k8s",
"OU": "4Paradigm"
}
]
}

说明:

  • hosts 字段指定授权使用该证书的etcd节点IP或域名列表,需要将etcd集群的3个节点都添加。
  • 如果考虑日后etcd 集群扩容并能确认 IP,那么 hosts 字段也需要将预备扩容 IP 写上。
#cfssl gencert -ca=/opt/k8s/work/ca.pem \ -ca-key=/opt/k8s/work/ca-key.pem \ -config=/opt/k8s/work/ca-config.json \ -profile=kubernetes etcd-csr.json | cfssljson -bare etcd

1.5 拷贝证书到各 etcd 节点

#scp ca*.pem etcd1-host:/etc/kubernetes/cert
#scp ca*.pem  etcd2-host:/etc/kubernetes/cert
#scp ca*.pem  etcd3-host:/etc/kubernetes/cert
#scp etcd*pem etcd1-host:/etc/etcd/cert/
#scp etcd*pem etcd2-host:/etc/etcd/cert/
#scp etcd*pem etcd3-host:/etc/etcd/cert/

在原来 etcd 配置文件添加以下内容

# vim /etc/etcd/etcd.conf
ETCD_CERT_FILE="/etc/etcd/cert/etcd.pem"
ETCD_KEY_FILE="/etc/etcd/cert/etcd-key.pem" 
ETCD_CLIENT_CERT_AUTH="true" 
ETCD_TRUSTED_CA_FILE="/etc/kubernetes/cert/ca.pem" 
ETCD_AUTO_TLS="true" 
ETCD_PEER_CERT_FILE="/etc/etcd/cert/etcd.pem" 
ETCD_PEER_KEY_FILE="/etc/etcd/cert/etcd-key.pem" 
ETCD_PEER_CLIENT_CERT_AUTH="true" 
ETCD_PEER_TRUSTED_CA_FILE="/etc/kubernetes/cert/ca.pem" 
ETCD_PEER_AUTO_TLS="true"

systemd 文件修改为

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd
EnvironmentFile=/etc/etcd/etcd.conf
ExecStart=/usr/local/sbin/etcd \
--name=etcd1 \
--cert-file=/etc/etcd/etcd.pem \
--key-file=/etc/etcd/etcd-key.pem \
--peer-cert-file=/etc/etcd/etcd.pem \
--peer-key-file=/etc/etcd/etcd-key.pem \
--trusted-ca-file=/etc/kubernetes/cert/ca.pem \
--peer-trusted-ca-file=/etc/kubernetes/cert/ca.pem \
--initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \
--listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},https://127.0.0.1:2379 \
--advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster etcd1=https://10.16.11.180:2380,etcd2=https://10.16.11.182:2380,etcd3=https://10.16.11.181:2380 \
--initial-cluster-state=new \
--data-dir=${ETCD_DATA_DIR}
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

说明:

  • 其他etcd 节点修改—name 为对应,如 etcd2、etcd3。
  • —initial-cluster:集群当中的其他节点
    —cert-file:etcd证书路径
    —key-file:etcd私钥路径
    —peer-cert-file:对等证书(双向证书)路径
    —peer-key-file:对等证书(双向证书)私钥路径
    —trusted-ca-file:作为客户端时的CA证书路径
    —peer-trusted-ca-file:对等证书的CA证书路径
    —initial-advertise-peer-urls:列出集群成员通信的URL,用于通告集群其他成员
    —listen-peer-urls:用于监听集群其他成员的URL列表
    —listen-client-urls:用于监听客户端通讯的URL列表
    —advertise-client-urls:通告客户端的URL,用于列出所有客户端
    —initial-cluster-token:etcd集群的初始集群令牌,服务器必须通过令牌才能加入etcd集群

1.6 启动服务

#systemctl daemon-reload
#systemctl enable etcd
#systemctl start etcd
#systemctl status etcd
#etcdctl --endpoints https://10.16.11.180:2379 member list

没有证书情况下,验证失败无法操作 etcd。

# etcdctl --endpoints=https://127.0.0.1:2379 --ca-file=/etc/kubernetes/cert/ca.pem --cert-file=/etc/etcd/cert/etcd.pem --key-file=/etc/etcd/cert/etcd-key.pem member list

# etcdctl --endpoints=https://127.0.0.1:2379 --ca-file=/etc/kubernetes/cert/ca.pem --cert-file=/etc/etcd/cert/etcd.pem --key-file=/etc/etcd/cert/etcd-key.pem cluster-health

指定 ca 证书后,通过认证。查看集群信息。

kube-apiserver

#cp /etc/etcd/cert/*  /etc/kubernetes/cert
#kube-apiserver 使用证书连接 etcd,在 KUBE_API_ARGS 添加修改以下参数
--cert-dir='/etc/kubernetes/cert' --etcd-cafile='/etcd/kubernetes/cert/ca.pem' --etcd-certfile='/etc/etcd/cert/etcd.pem' --etcd-keyfile='/etc/etcd/cert/etcd-key.pem'
#重启组件服务
#systemctl daemon-reload
#systemctl restart kube-apiserver

2. 容器化部署

2.1 使用 staticPod 方式。

2.2 选择独立非 work 节点进行 etcd 容器部署。

2.3 重复上述创建证书步骤。

2.4 将 CA 与 etcd 相关证书放置在特定主机目录中。如 /etc/etcd/cert

#scp ca*.pem  etcd1-host:/etc/etcd/cert/
#scp ca*.pem  etcd2-host:/etc/etcd/cert/
#scp ca*.pem  etcd3-host:/etc/etcd/cert/
#scp etcd*pem etcd1-host:/etc/etcd/cert/
#scp etcd*pem etcd2-host:/etc/etcd/cert/
#scp etcd*pem etcd3-host:/etc/etcd/cert/

etcd1-pod.yaml内容如下:

#vim etcd1-pod.yaml

apiVersion: v1
kind: Pod
metadata:
labels:
  component: etcd
name: etcd
namespace: kube-system
spec:
  containers:
  - command:
    - etcd --name ${PEER_NAME} \
    - --data-dir /var/lib/etcd \
    - --listen-client-urls https://${PRIVATE_IP}:2379 \
    - --advertise-client-urls https://${PRIVATE_IP}:2379 \
    - --listen-peer-urls https://${PRIVATE_IP}:2380 \
    - --initial-advertise-peer-urls https://${PRIVATE_IP}:2380 \
    - --cert-file=/certs/etcd.pem \
    - --key-file=/certs/etcd-key.pem \
    - --client-cert-auth \
    - --trusted-ca-file=/certs/ca.pem \
    - --peer-cert-file=/ecerts/etcd.pem \
    - --peer-key-file=/certs/etcd-key.pem \
    - --peer-client-cert-auth \
    - --peer-trusted-ca-file=/certs/ca.pem \
    - --initial-cluster etcd1=https://<etcd1-ip>:2380,etcd2=https://<etcd1-ip>:2380,etcd3=https://<etcd3-ip>:2380 \
   - --initial-cluster-token etcd-cluster-token \
   - --initial-cluster-state new
    image: registry.aliyuncs.com/google_containers/etcd:3.3.15
    livenessProbe:
    httpGet:
    path: /health
    port: 2379
    scheme: HTTP
    initialDelaySeconds: 15
    timeoutSeconds: 15
   name: etcd
   env:
     - name: PUBLIC_IP
     valueFrom:
       fieldRef:
         fieldPath: status.hostIP
     - name: PRIVATE_IP
     valueFrom:
     fieldRef:
     fieldPath: status.podIP
    - name: PEER_NAME
    valueFrom:
      fieldRef:
      fieldPath: metadata.name
  volumeMounts:
  - mountPath: /var/lib/etcd
  name: etcd
  - mountPath: /certs
name: certs
hostNetwork: true
volumes:
- hostPath:
   path: /data/k8s/etcd/data
name: etcd
- hostPath:
   path: /etc/etcd/certs
name: certs

将yaml 文件放置在 kubelet 配置 staticPod 目录中,如/etc/kubernetes/manifests。

2.5 kube-apiserver

假设容器部署 k8s 集群,使用 kubeadm 工具。 kubeadm 配置文件如 kubeadm-config.yaml ,修改 apiServer 字段,添加 etcd 信息。

#vim kubeadm.yaml

apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  external:
    caFile: /etc/etcd/cert/ca.pem
    certFile: /etc/etcd/cert/etcd.pem
    keyFile: /etc/etcd/cert/etcd-key.pem
  endpoints:
  - https://<etcd1-ip>:2379
  - https://<etcd2-ip>:2379
  - https://<etcd3-ip>:2379
kind: ClusterConfiguration

注意 etcd 证书需要在运行 kubeadm 初始化机器中存在。