kubeadm 搭建高可用集群

本贴最后更新于 1532 天前,其中的信息可能已经物是人非

kubeadm 搭建高可用集群

标签: k8s kubeadm etcd


[TOC]

1.安装环境

5 台 centos7.7 主机

  • 3 台 master
  • 1 台 haproxy(可选)
  • 1 台 node

2.准备工作

# 关闭防火墙:
$ systemctl stop firewalld
$ systemctl disable firewalld

# 关闭selinux:
$ sed -i 's/enforcing/disabled/' /etc/selinux/config 
$ setenforce 0

# 关闭swap:
$ swapoff -a  #  临时
$ vim /etc/fstab  #  永久  注释掉最后一行

# 给每台机器设置主机名(可省略,方便记忆):
$ hostnamectl set-hostname master1
$ hostnamectl set-hostname master2
$ hostnamectl set-hostname master3
$ hostnamectl set-hostname node
$ hostnamectl set-hostname haproxy

# 添加主机名与IP对应关系(可省略,方便记忆):
$ cat /etc/hosts
172.18.249.67   master1
172.18.249.66   master2
172.18.249.65   master3
172.18.249.64   node
172.18.249.63   haproxy

# 将桥接的IPv4流量传递到iptables的链:
$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
$ sysctl --system

# 可选操作(SSH免密登录,方便后面集群证书的拷贝)
# 在master1节点上执行,node节点不需要拷贝证书,可以不用设置,这个自己选择  
$ ssh-keygen  # 一路回车即可
$ scp .ssh/id_rsa.pub master2:
$ scp .ssh/id_rsa.pub master3:
$ scp .ssh/id_rsa.pub node:

[root@master2 ~]# cat id_rsa.pub >> .ssh/authorized_keys
[root@master3 ~]# cat id_rsa.pub >> .ssh/authorized_keys
[root@node ~]# cat id_rsa.pub >> .ssh/authorized_keys

3.安装 haproxy(可选)

因为阿里云不支持 keepalived 的 vip,所以直接采用 haproxy 作为 apiserver 的控制面。

yum install -y haproxy

systemctl enable haproxy

# master1,2,3替换为IP,s1,2,3替换为主机名
cat << EOF >> /etc/haproxy/haproxy.cfg
listen k8s-lb *:6443
        mode tcp
        balance roundrobin
        server master1 172.18.249.67:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
        server master2 172.18.249.66:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
        server master3 172.18.249.65:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3
EOF

service haproxy start

4.安装 ETCD 集群(可选)

如果想要使用外部的 etcd 集群,而不是由 k8s 自己生成 pod 在 master 节点运行,可以执行以下操作。

  • 在 3 台 master 上安装 etcd
yum install -y etcd
systemctl enable etcd
  • 生成配置
    在 master1 上进行操作

etcd1=192.168.0.11
etcd2=192.168.0.12
etcd3=192.168.0.13

TOKEN=abcd1234

ETCDHOSTS=($etcd1 $etcd2 $etcd3)

NAMES=("infra0" "infra1" "infra2")

for i in "${!ETCDHOSTS[@]}"; do
HOST=${ETCDHOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/$NAME.conf
# [member]
ETCD_NAME=$NAME
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://$HOST:2380"
ETCD_LISTEN_CLIENT_URLS="http://$HOST:2379,http://127.0.0.1:2379"
#[cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://$HOST:2380"
ETCD_INITIAL_CLUSTER="${NAMES[0]}=http://${ETCDHOSTS[0]}:2380,${NAMES[1]}=http://${ETCDHOSTS[1]}:2380,${NAMES[2]}=http://${ETCDHOSTS[2]}:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="$TOKEN"
ETCD_ADVERTISE_CLIENT_URLS="http://$HOST:2379"
EOF
done

  • 覆盖 etcd 配置
for i in "${!ETCDHOSTS[@]}"; do
HOST=${ETCDHOSTS[$i]}
NAME=${NAMES[$i]}
scp /tmp/$NAME.conf $HOST:
ssh $HOST "\mv -f $NAME.conf /etc/etcd/etcd.conf"
rm -f /tmp/$NAME.conf
done
  • 在每台节点上启动 etcd

master1 上执行 service etcd start,会一直 pending 状态,等 master2 的 etcd 启动以后就会完成。

[root@master1 ~]# service etcd start
[root@master2 ~]# service etcd start
[root@master3 ~]# service etcd start
  • 任意节点验证集群
etcdctl member list
etcdctl cluster-health

5.安装 docker

使用阿里云 yum 源安装

$ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
$ yum -y install docker-ce-18.06.1.ce-3.el7
$ systemctl enable docker && systemctl start docker
$ docker --version
Docker version 18.06.1-ce, build e68fc7a

此处附上一张 K8S 对应的 docker 版本,截止 2019.08.09 最新的版本支持信息:

  • Kubernetes 1.15.2 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.15.1 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.15.0 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.14.5 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.14.4 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.14.3 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.14.2 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.14.1 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.14.0 -->Docker 版本 1.13.1、17.03、17.06、17.09、18.06、18.09
  • Kubernetes 1.13.5 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.13.5 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.13.4 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.13.3 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.13.2 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.13.1 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.13.0 -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.12.* -->Docker 版本 1.11.1、1.12.1、1.13.1、17.03、17.06、17.09、18.06
  • Kubernetes 1.11.* -->Docker 版本 1.11.2 到 1.13.1、17.03
  • Kubernetes 1.10.* -->Docker 版本 1.11.2 到 1.13.1、17.03

如果没有搭建类似 harbor 的私有仓库,因为镜像拉取过慢,所以此处需要配置一个镜像加速器。
您可以通过修改 daemon 配置文件/etc/docker/daemon.json 来使用加速器,加速器地址可以填写阿里云的容器镜像服务提供的,是免费使用的。

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://*************"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

但是 docker 默认驱动程序是 cgroupfs,而 k8s1.17 是 systemd,所以我们需要修改 docker 的默认驱动
官方文档推荐配置

cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "registry-mirrors": ["https://6ekruvxo.mirror.aliyuncs.com"]  # 使用自己或其他可用的镜像加速器
}
EOF

systemctl daemon-reload && systemctl restart docker	

6.安装 k8s

# 添加源
$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# master节点
$ yum install -y kubelet-1.17.0 kubeadm-1.17.0 kubectl-1.17.0

# node节点
$ yum install -y kubelet-1.17.0 kubeadm-1.17.0 

$ systemctl enable kubelet && systemctl start kubelet

#安装kubelet 后会在/etc下生成文件目录/etc/kubernetes/manifests/

7.部署 Kubernetes Master

创建 kubeadm 配置文件
官网 init 初始化配置大全

cat << EOF > kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
etcd:
  local:
    dataDir: "/var/lib/etcd"
networking:
  serviceSubnet: "10.96.0.0/16"
  podSubnet: "10.244.0.0/16"
  dnsDomain: "cluster.local"
kubernetesVersion: "v1.17.0"
controlPlaneEndpoint: "172.18.249.63:6443"
apiServer:
  extraArgs:
    authorization-mode: "Node,RBAC"
  certSANs:
  - "172.18.249.63"
  timeoutForControlPlane: 4m0s
imageRepository: "registry.aliyuncs.com/google_containers"
EOF

kubeadm init --config kubeadm-config.yaml

初始化成功后,保存 token,执行

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

安装 cni 网络组件
官方文档推荐

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml

然后可以进行查看 master 的状态,如果节点处于 notready,可能是因为 flannel 正在拉取镜像,需要等待一段时间

kubectl get cs 
kubectl get nodes

8.加入 k8s 集群

在 master1 节点上进行操作,将生成的证书拷贝到其他的 master 节点

ssh master2 mkdir -p /etc/kubernetes/pki/etcd
ssh master3 mkdir -p /etc/kubernetes/pki/etcd

scp /etc/kubernetes/admin.conf root@master2:/etc/kubernetes
scp /etc/kubernetes/admin.conf root@master3:/etc/kubernetes

scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@master2:/etc/kubernetes/pki
scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@master3:/etc/kubernetes/pki

scp /etc/kubernetes/pki/etcd/ca.* root@master2:/etc/kubernetes/pki/etcd
scp /etc/kubernetes/pki/etcd/ca.* root@master3:/etc/kubernetes/pki/etcd

然后再 master2 和 master3 节点上分别执行 join 命令,使用自己生成保存的 token,master 节点会多一个参数==--control-plane==

  kubeadm join 172.18.249.82:6443 --token 85xqaz.7wj2oonv3ulpfbix \
    --discovery-token-ca-cert-hash sha256:7d334aa7e49ea4934505686c311139c07cd278e2e92faa51fa74429399519772 \
    --control-plane 

然后是 node 节点

kubeadm join 172.18.249.82:6443 --token 85xqaz.7wj2oonv3ulpfbix \
    --discovery-token-ca-cert-hash sha256:7d334aa7e49ea4934505686c311139c07cd278e2e92faa51fa74429399519772

等几分钟之后,就可以看到节点处于 ready 状态

[root@k8s001 kubernetes]# kubectl get nodes
NAME     STATUS   ROLES    AGE     VERSION
k8s001   Ready    master   9m22s   v1.15.0
k8s002   Ready    <none>   2m44s   v1.15.0
k8s003   Ready    <none>   2m41s   v1.15.0

9. 测试 kubernetes 集群

在 Kubernetes 集群中创建一个 pod,验证是否正常运行:

$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
$ kubectl get pod,svc

10.rancher 部署(可选)

rancher 官网

# 随便找一台已经安装docker的机器
$ sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher

然后等到镜像启动成功之后,访问 UI 界面,输入初始化密码,然后加入已存在的集群。

11.部署 Dashboard(可选)

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

默认镜像国内无法访问,修改 kubernetes-dashboard.yaml 修改镜像地址为:
先将文件下载下来:

wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
# 原image 地址
# k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
# 修改为
# roeslys/kubernetes-dashboard-amd64:v1.10.1

默认 Dashboard 只能集群内部访问,修改 Service 为 NodePort 类型,暴露到外部:不修改的话外部不能访问。

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30000
  selector:
    k8s-app: kubernetes-dashboard

可以添加 nodePort 指定端口,然后访问地址,必须火狐浏览器用 https 打开:https://NodeIP:30000
后续也可以自己添加 ssl,安全方面后续再说。

$ kubectl apply -f kubernetes-dashboard.yaml

$ kubectl get pods,svc -n kube-system

创建service account并绑定默认cluster-admin管理员集群角色:

$ kubectl create serviceaccount dashboard-admin -n kube-system
$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
$ kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

记录保存 token,使用令牌登录。

image

修改配置,让 dashboard 能够在谷歌等浏览器上正常运行。

火狐浏览器能够正常访问是因为它有一个不安全模式运行,而默认的 dashboard 应用的 https 是不安全的,因此只有火狐可以访问。我自己也测试过,你如果直接在 master 节点上 curl https://127.0.0.1:30000,页面数据是出不来的。但是当我们跳过安全认证这一块,curl https://127.0.0.1:30000 -k,这个时候可以看到已经正常返回了页面的 html 信息。

下面是生成证书的一些步骤,使用新的证书来启动 dashboard

cd /root
mkdir key && cd key
#生成证书
openssl genrsa -out dashboard.key 2048 
openssl req -new -out dashboard.csr -key dashboard.key -subj '/CN=172.18.249.67'(我测试的时候填写的外网地址,都可以)
openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt 
#删除原有的证书secret
kubectl delete secret kubernetes-dashboard-certs -n kube-system
#创建新的证书secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kube-system
#查看pod
kubectl get pod -n kube-system
#重启pod
kubectl delete pod <pod name> -n kube-system

完成以上操作之后我们重新刷新一下谷歌浏览器
这个时候我们就可以通过谷歌浏览器打开 kubernetes dashboard 了

  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    108 引用 • 54 回帖
  • kubeadm
    2 引用
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 489 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...