联系客服
客服二维码

联系客服获取更多资料

微信号:LingLab1

客服电话:010-82185409

意见反馈
关注我们
关注公众号

关注公众号

linglab语言实验室

回到顶部
Kubernetes 学习笔记 - 集群搭建

299 阅读 2020-09-18 10:37:02 上传

以下文章来源于 西语语言学工作坊

本篇记录我集群搭建的过程和问题,目标是可以根据本篇文章搭建自己生产可用的 K8S 集群。对于 K8S 的一些概念理解,可参考我之前的笔记Kubernetes 学习笔记-基础篇[1]

文章较长,建议收藏备。

环境准备

容器环境对 Linux 的系统内核有一定的要求, kernel 3.10 是当前 Docker 19 可以稳定运行的最小的 Linux 内核版本。Docker 中应用了很多内核中的新功能,经过大量的实践证明,使用你当前发行版本 Linux 的最新稳定的内核是最佳的选择。

通过下边的脚本,可以检测依赖环境的可用性:

https://github.com/docker/docker/blob/master/contrib/check-config.sh

K8S 官方建议集群硬件最小配置为,2G 内存,2 个 cpu, 30G 硬盘。若集群仅作为学习使用,官方提供了 MinikubeKind两种方式,可安装简易版的 K8S,来熟悉了解 K8S 的各种组件和功能。针对 Mac 用户,Docker for Mac的客户端也集成了 K8S 的功能,也可启用来体验。

  • MinikubeKind 方式安装 K8S 安装文档[2];
  • Docker for Mac 启用文档[3];

本次目标搭建生产可用的集群,环境准备如下:

  • 6 台 Liunux 机器,CentOS 7.8, Kernel 3.10.0-1127.18.2.el7.x86_64
    • 192.168.10.11
    • 192.168.10.12
    • 192.168.10.13
    • 192.168.10.14
    • 192.168.10.15
    • 192.168.10.16
  • Docker: 18.09.9
  • Kubernetes: 1.16.14 (考虑到内核版本比较低,选择了较低版本,k8s 1.18 部署相同)
  • ETCD: 3.4.9

环境规划

规划 K8S 的各组件机器如下:

  • ETCD

    • 192.168.10.14
    • 192.168.10.15
    • 192.168.10.16
  • K8S Master

    • 192.168.10.11 host: 10-11-master
    • 192.168.10.12 host: 10-12-master
    • 192.168.10.13 host: 10-13-master
  • K8S Node

    • 192.168.10.14 host: 10-14-node
    • 192.168.10.15 host: 10-15-node
    • 192.168.10.16 host: 10-16-node
  • Nginx + Keepalived

    • 192.168.10.14
    • 192.168.10.15

这里 Node 和高可用组件都共用了 ETCD 的机器,这里仅作为演示说明,真实生产环境中建议都使用单独的机器部署,以免组件或机器故障相互影响。

环境初始化

以下操作,Master 和 Node 机器需要执行。

    # 设置系统host,如192.169.10.11 host 为 10-11-master。其他机器修改方式相同。$ hostnamectl  set-hostname  10-11-master$ echo "127.0.0.1   $(hostname)" >> /etc/hosts
    # 升级系统内核mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bakwget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repoyum clean allyum -y update
    # 关闭防火墙systemctl stop firewalldsystemctl disable firewalld
    # 关闭swapswapoff -ased -i 's/.*swap.*/#&/' /etc/fstab
    # 关闭SeLinuxsetenforce  0 sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/sysconfig/selinux sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config sed -i "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/sysconfig/selinux sed -i "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/selinux/config 

    # 设置内核参数cat </etc/sysctl.d/k8s.conf
    net.ipv4.ip_forward = 1net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1net.ipv4.tcp_keepalive_time = 600net.ipv4.tcp_keepalive_intvl = 30net.ipv4.tcp_keepalive_probes = 10EOF
    modprobe br_netfiltersysctl -p /etc/sysctl.d/k8s.confls /proc/sys/net/bridge
    # 配置资源限制echo "* soft nofile 65536" >> /etc/security/limits.confecho "* hard nofile 65536" >> /etc/security/limits.confecho "* soft nproc 65536"  >> /etc/security/limits.confecho "* hard nproc 65536"  >> /etc/security/limits.confecho "* soft memlock  unlimited"  >> /etc/security/limits.confecho "* hard memlock  unlimited"  >> /etc/security/limits.conf
    # 依赖安装yum install -y epel-releaseyum install -y yum-utils device-mapper-persistent-data lvm2 net-tools conntrack-tools wget vim ntpdate libseccomp libtool-ltdl
    # 安装Docker  yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum makecache fastyum -y install docker-ce-18.09.9 docker-ce-cli-18.09.9systemctl enable docker.servicesystemctl start docker.servicesystemctl stop docker.servicecat > /etc/docker/daemon.json << EOF{  "exec-opts": ["native.cgroupdriver=systemd"],  "registry-mirrors": [      "https://4xr1qpsp.mirror.aliyuncs.com",      "https://dockerhub.azk8s.cn",      "http://hub-mirror.c.163.com",      "https://registry.docker-cn.com"  ],  "storage-driver": "overlay2",  "storage-opts": [    "overlay2.override_kernel_check=true"  ],  "log-driver": "json-file",  "log-opts": {    "max-size": "100m",    "max-file":"5"  }}EOF
    systemctl daemon-reloadsystemctl start docker

    组件安装

    机器环境初始化好之后,开始搭建 K8S。主要有两种搭建方式:

    • kubeadm:官方提供的安装工具,除管理容器的组件 kubelet 外,其他组件均以容器的形式启动。可通过 kubeadm initkubeadm join来快速实现 K8S 集群的搭建。官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/ 。更加详细的安装步骤,可参考扩展阅读 1。

    • 二进制方式搭建:K8S 的各组件都是使用 Go 语言开发的,发布运行都是编译好的二进制文件。该方式需要自己来安装每个组件,自己编写配置文件和管理启动文件。

    初学者,本着学习的目的,本文记录第二种安装方式,以便熟悉 K8S 的各组件。老手完全可以使用 kubeadm 来快速搭建一个生产可用的集群。

    在搭建集群之前,回忆下 K8S 的各组件。

    (图片来源网络)

    那我们梳理部署组件情况如下:

    • 单独集群部署:

      • etcd 保存了整个集群的状态;
    • Master 部署:

      • controller manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
      • scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上;
      • apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;
    • Node 部署:

      • kubelet 负责维护容器的生命周期,同时也负责容器卷插件 Volume(CVI)和容器网络插件(CNI)的管理;
      • kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡;
      • Container runtime 负责镜像管理以及 Pod 和容器的真正运行(CRI);

    下面开始。

    1/ ETCD 集群的搭建

    ETCD 主要用来保存集群状态和资源对象数据。使用 kubeadm 安装时,默认etcd集群和 Master 节点是在一块的。为提高可用性减少故障影响,建议将etcd单独部署一个集群,方便管理维护。

    1.1/ 签发证书

    为提高安全性,统一使用 ssl 加密。可使用自签证书,我们使用 cfssl 工具来生成证书。

      # 下载cfssl 二进制文件wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
      # 增加执行权限chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
      # 移动到可执行目录mv cfssl_linux-amd64 /usr/local/bin/cfsslmv cfssljson_linux-amd64 /usr/local/bin/cfssljsonmv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

      生成根证书

        # 创建目录存放证书文件mkdir -p /opt/ssl/{etcd,k8s}
        # 创建根证书配置文件, 有效期为87600h(10年)。cd /opt/ssl/etcdcat > ca-config.json << EOF{  "signing": {    "default": {      "expiry": "87600h"    },    "profiles": {      "www": {         "expiry": "87600h",         "usages": [            "signing",            "key encipherment",            "server auth",            "client auth"        ]      }    }  }}EOF
        cat > ca-csr.json << EOF{    "CN": "etcd CA",    "key": {        "algo": "rsa",        "size": 2048    },    "names": [        {            "C": "CN",            "L": "Beijing",            "ST": "Beijing"        }    ]}EOF
        # 生成证书cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
        lsca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem

        签发 etcd https 证书

          cat > server-csr.json << EOF{    "CN": "etcd",    "hosts": [    "192.168.10.14",    "192.168.10.15",    "192.168.10.16"    ],    "key": {        "algo": "rsa",        "size": 2048    },    "names": [        {            "C": "CN",            "L": "BeiJing",            "ST": "BeiJing"        }    ]}EOF

          hosts 为 etcd 的集群节点 ip, 改成你实际的 ip 即可。

          1.2/ etcd 集群搭建

          下载 etcd 二进制文件到三台事先准备好的机器,编写配置文件和启动管理文件。

            # 创建etcd目录mkdir -p /opt/etcd/{bin,cfg,ssl}
            # 复制生成的证书到etcd证书目录cp /opt/ssl/etcd/ca*.pem /opt/etcd/ssl/cp /opt/ssl/etcd/server*.pem /opt/etcd/ssl/

            # 配置文件wget https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gztar zxvf etcd-v3.4.9-linux-amd64.tar.gzcd etcd-v3.4.9-linux-amd64cp -a etcd etcdctl /opt/etcd/bin/
            cat > /opt/etcd/cfg/etcd.conf << EOF#[Member]ETCD_NAME="etcd-1"ETCD_DATA_DIR="/var/lib/etcd/default.etcd"ETCD_LISTEN_PEER_URLS="https://192.168.10.14:2380"ETCD_LISTEN_CLIENT_URLS="https://192.168.10.14:2379"
            #[Clustering]ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.10.14:2380"ETCD_ADVERTISE_CLIENT_URLS="https://192.168.10.14:2379"ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.10.14:2380,etcd-2=https://192.168.10.15:2380,etcd-3=https://192.168.10.16:2380"ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"ETCD_INITIAL_CLUSTER_STATE="new"EOF
            • ETCD_NAME:节点名称,集群中唯一
            • ETCD_DATA_DIR:数据目录
            • ETCD_LISTEN_PEER_URLS:集群通信监听地址
            • ETCD_LISTEN_CLIENT_URLS:客户端访问监听地址
            • ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址
            • ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址
            • ETCD_INITIAL_CLUSTER:集群节点地址
            • ETCD_INITIAL_CLUSTER_TOKEN:集群 Token
            • ETCD_INITIAL_CLUSTER_STATE:加入集群的当前状态,new 是新集群,existing 表示加入已有集群
              # 编写启动管理文件
              cat > /usr/lib/systemd/system/etcd.service << EOF[Unit]Description=Etcd ServerAfter=network.targetAfter=network-online.targetWants=network-online.target
              [Service]Type=notifyEnvironmentFile=/opt/etcd/cfg/etcd.confExecStart=/opt/etcd/bin/etcd \--enable-v2 \--cert-file=/opt/etcd/ssl/server.pem \--key-file=/opt/etcd/ssl/server-key.pem \--peer-cert-file=/opt/etcd/ssl/server.pem \--peer-key-file=/opt/etcd/ssl/server-key.pem \--trusted-ca-file=/opt/etcd/ssl/ca.pem \--peer-trusted-ca-file=/opt/etcd/ssl/ca.pem \--logger=zapRestart=on-failureLimitNOFILE=65536
              [Install]WantedBy=multi-user.targetEOF
              # 启动systemctl daemon-reloadsystemctl start etcdsystemctl enable etcd

              复制 etcd 文件(/opt/etcd/下的所有文件,service 文件)到其他两个节点,并修改/opt/etcd/cfg/etcd.conf文件中 ip 为对应节点 ip,启动即可。

              最后,查看节点状态。

                ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.10.14:2379,https://192.168.10.15:2379,https://192.168.10.16:2379" endpoint health
                https://192.168.10.14:2379 is healthy: successfully committed proposal: took = 12.762896mshttps://192.168.10.15:2379 is healthy: successfully committed proposal: took = 12.974284mshttps://192.168.10.16:2379 is healthy: successfully committed proposal: took = 12.996147ms

                至此,etcd 集群搭建完成。

                2/ Kubernetes Master 节点部署

                2.1/ 签发证书

                生成根证书

                  cd /opt/ssl/k8s/cat > ca-config.json << EOF{  "signing": {    "default": {      "expiry": "87600h"    },    "profiles": {      "kubernetes": {         "expiry": "87600h",         "usages": [            "signing",            "key encipherment",            "server auth",            "client auth"        ]      }    }  }}EOFcat > ca-csr.json << EOF{    "CN": "kubernetes",    "key": {        "algo": "rsa",        "size": 2048    },    "names": [        {            "C": "CN",            "L": "Beijing",            "ST": "Beijing",            "O": "k8s",            "OU": "System"        }    ]}EOF
                  # 生成证书cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

                  签发 apiserver 的 https 证书

                    cd /opt/ssl/k8scat > server-csr.json << EOF{    "CN": "kubernetes",    "hosts": [      "10.10.0.1",      "127.0.0.1",      "192.168.10.11",      "192.168.10.12",      "192.168.10.13",      "192.168.10.14",      "192.168.10.15",      "192.168.10.16",      "192.168.10.17",      "kubernetes",      "kubernetes.default",      "kubernetes.default.svc",      "kubernetes.default.svc.cluster",      "kubernetes.default.svc.cluster.local"    ],    "key": {        "algo": "rsa",        "size": 2048    },    "names": [        {            "C": "CN",            "L": "BeiJing",            "ST": "BeiJing",            "O": "k8s",            "OU": "System"        }    ]}EOF

                    hosts 字段中 IP 为所有 Master/LB/VIP 的 ip,需要访问 apiserver 的节点 ip 建议都写上。

                      # 生成证书cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server

                      2.2/ apiserver 部署

                      可从这里 https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG 找到你需要的版本的二进制安装包。直接下载 server 包即可,其中包含有 apiservercontroller managerscheduler的二进制文件。apiserver 部署步骤如下:

                        # 获取二进制文件wget https://dl.k8s.io/v1.16.14/kubernetes-server-linux-amd64.tar.gz
                        mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}tar zxvf kubernetes-server-linux-amd64.tar.gzcd kubernetes/server/bincp kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/bincp kubectl /usr/bin/
                        # 创建配置文件cp /opt/ssl/k8s/ca*pem /opt/ssl/k8s/server*pem /opt/kubernetes/ssl/
                        cat > /opt/kubernetes/cfg/kube-apiserver.conf << EOFKUBE_APISERVER_OPTS="--logtostderr=false \\--v=2 \\--log-dir=/opt/kubernetes/logs \\--etcd-servers=https://192.168.10.14:2379,https://192.168.10.15:2379,https://192.168.10.16:2379 \\--bind-address=192.168.10.11 \\--secure-port=6443 \\--advertise-address=192.168.10.11 \\--allow-privileged=true \\--service-cluster-ip-range=10.10.0.0/24 \\--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \\--authorization-mode=RBAC,Node \\--enable-bootstrap-token-auth=true \\--token-auth-file=/opt/kubernetes/cfg/token.csv \\--service-node-port-range=30000-32767 \\--kubelet-client-certificate=/opt/kubernetes/ssl/server.pem \\--kubelet-client-key=/opt/kubernetes/ssl/server-key.pem \\--tls-cert-file=/opt/kubernetes/ssl/server.pem  \\--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \\--client-ca-file=/opt/kubernetes/ssl/ca.pem \\--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \\--etcd-cafile=/opt/etcd/ssl/ca.pem \\--etcd-certfile=/opt/etcd/ssl/server.pem \\--etcd-keyfile=/opt/etcd/ssl/server-key.pem \\--audit-log-maxage=30 \\--audit-log-maxbackup=3 \\--audit-log-maxsize=100 \\--audit-log-path=/opt/kubernetes/logs/k8s-audit.log"EOF
                        • logtostderr:启用日志
                        • v:日志等级
                        • log-dir:日志目录
                        • etcd-servers:etcd 集群地址
                        • bind-address:监听地址
                        • secure-port:https 安全端口
                        • advertise-address:集群通告地址
                        • allow-privileged:启用授权
                        • service-cluster-ip-range:Service 虚拟 IP 地址段
                        • enable-admission-plugins:准入控制模块
                        • authorization-mode:认证授权,启用 RBAC 授权和节点自管理
                        • enable-bootstrap-token-auth:启用 TLS bootstrap 机制
                        • token-auth-file:bootstrap token 文件
                        • service-node-port-range:Service nodeport 类型默认分配端口范围
                        • kubelet-client-xxx:apiserver 访问 kubelet 客户端证书
                        • tls-xxx-file:apiserver https 证书
                        • etcd-xxxfile:连接 Etcd 集群证书
                        • audit-log-xxx:审计日志

                        Master apiserver 启用 TLS 认证后,Node 节点kubeletkube-proxy要与kube-apiserver进行通信,必须使用 CA 签发的有效证书才可以,当 Node 节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes 引入了TLS bootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。所以强烈建议在 Node 上使用这种方式,目前主要用于kubeletkube-proxy还是由我们统一颁发一个证书。

                          # 生成一个随机tokenhead -c 16 /dev/urandom | od -An -t x | tr -d ' 'ebe4f1e22044e23638394dd24d4aff49# 创建token 文件, 该文件在 apiserver 参数 token-auth-file 参数使用cat > /opt/kubernetes/cfg/token.csv << EOFebe4f1e22044e23638394dd24d4aff49,kubelet-bootstrap,10001,"system:node-bootstrapper"EOF

                          创建服务管理配置文件

                            cat > /usr/lib/systemd/system/kube-apiserver.service << EOF[Unit]Description=Kubernetes API ServerDocumentation=https://github.com/kubernetes/kubernetes
                            [Service]EnvironmentFile=/opt/kubernetes/cfg/kube-apiserver.confExecStart=/opt/kubernetes/bin/kube-apiserver \$KUBE_APISERVER_OPTSRestart=on-failure
                            [Install]WantedBy=multi-user.targetEOF

                            启动

                              systemctl daemon-reloadsystemctl start kube-apiserversystemctl enable kube-apiserver

                              授权 kubelet-bootstrap 用户允许请求证书,kubelet 使用该用户来请求 apiserver 证书,该用户稍后部署 kubelet 时会配置。

                                kubectl create clusterrolebinding kubelet-bootstrap \--clusterrole=system:node-bootstrapper \--user=kubelet-bootstrap

                                2.3/ kube-controller-manager 部署

                                创建配置文件

                                  cat > /opt/kubernetes/cfg/kube-controller-manager.conf << EOFKUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \\--v=2 \\--log-dir=/opt/kubernetes/logs \\--leader-elect=true \\--master=127.0.0.1:8080 \\--bind-address=127.0.0.1 \\--service-cluster-ip-range=10.10.0.0/24 \\--cluster-signing-cert-file=/opt/kubernetes/ssl/ca.pem \\--cluster-signing-key-file=/opt/kubernetes/ssl/ca-key.pem  \\--root-ca-file=/opt/kubernetes/ssl/ca.pem \\--service-account-private-key-file=/opt/kubernetes/ssl/ca-key.pem \\--experimental-cluster-signing-duration=87600h0m0s"EOF
                                  • master:通过本地端口 8080 连接 apiserver。
                                  • leader-elect:当该组件启动多个时,自动选举(HA)
                                  • cluster-signing-cert-file/–cluster-signing-key-file:自动为 kubelet 颁发证书的 CA,与 apiserver 保持一致

                                  启动管理配置文件

                                    cat > /usr/lib/systemd/system/kube-controller-manager.service << EOF[Unit]Description=Kubernetes Controller ManagerDocumentation=https://github.com/kubernetes/kubernetes
                                    [Service]EnvironmentFile=/opt/kubernetes/cfg/kube-controller-manager.confExecStart=/opt/kubernetes/bin/kube-controller-manager \$KUBE_CONTROLLER_MANAGER_OPTSRestart=on-failure
                                    [Install]WantedBy=multi-user.targetEOF

                                    启动

                                      systemctl daemon-reloadsystemctl start kube-controller-managersystemctl enable kube-controller-manager

                                      2.4/ kube-scheduler 部署

                                        cat > /opt/kubernetes/cfg/kube-scheduler.conf << EOFKUBE_SCHEDULER_OPTS="--logtostderr=false \--v=2 \--log-dir=/opt/kubernetes/logs \--leader-elect=true \--master=127.0.0.1:8080 \--bind-address=127.0.0.1"EOF
                                        • master:通过本地端口 8080 连接 apiserver。
                                        • leader-elect:当该组件启动多个时,自动选举(HA)

                                        启动管理配置文件

                                          cat > /usr/lib/systemd/system/kube-scheduler.service << EOF[Unit]Description=Kubernetes SchedulerDocumentation=https://github.com/kubernetes/kubernetes
                                          [Service]EnvironmentFile=/opt/kubernetes/cfg/kube-scheduler.confExecStart=/opt/kubernetes/bin/kube-scheduler \$KUBE_SCHEDULER_OPTSRestart=on-failure
                                          [Install]WantedBy=multi-user.targetEOF

                                          启动

                                            systemctl daemon-reloadsystemctl start kube-schedulersystemctl enable kube-scheduler

                                            2.5/ 部署其他两个 Master 节点

                                              # 创建etcd 证书目录mkdir -p /opt/etcd/ssl
                                              # 复制 apiserver controller-manager scheduler 配置文件及二进制文件scp -r /opt/kubernetes root@192.168.10.12:/opt# 复制etcd 证书文件scp -r /opt/etcd/ssl root@192.168.10.12:/opt/etcd# 复制 systemd 管理文件scp /usr/lib/systemd/system/kube* root@192.168.10.12:/usr/lib/systemd/system# 复制ctl 二进制文件scp /usr/bin/kubectl  root@192.168.10.12:/usr/bin
                                              # 修改配置文件为对应ipvi /opt/kubernetes/cfg/kube-apiserver.conf...--bind-address=192.168.10.12 \--advertise-address=192.168.10.12 \...
                                              # 启动systemctl daemon-reloadsystemctl start kube-apiserversystemctl start kube-controller-managersystemctl start kube-scheduler
                                              systemctl enable kube-apiserversystemctl enable kube-controller-managersystemctl enable kube-scheduler

                                              至此,Master 节点部署完成。

                                              3/ Kubernetes Node 节点部署

                                              创建目标,并复制组件二进制文件。

                                                # 创建kubernetes目录mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}# 复制二进制文件scp /root/kubernetes/server/bin/kubelet  root@192.168.10.14:/opt/kubernetes/binscp /root/kubernetes/server/bin/kube-proxy  root@192.168.10.14:/opt/kubernetes/binscp /root/kubernetes/server/bin/kubectl  root@192.168.10.14:/bin/
                                                chmod +x /opt/kubernetes/bin/*chmod +x /bin/kubectl
                                                # 复制根证书scp /opt/kubernetes/ssl/ca.pem  root@192.168.10.14:/opt/kubernetes/ssl

                                                3.1/ kubelet 部署

                                                创建配置文件

                                                  cat > /opt/kubernetes/cfg/kubelet.conf << EOFKUBELET_OPTS="--logtostderr=false \\--v=2 \\--log-dir=/opt/kubernetes/logs \\--hostname-override=10-14-node \\--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\--config=/opt/kubernetes/cfg/kubelet-config.yml \\--cert-dir=/opt/kubernetes/ssl \\--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"EOF
                                                  • hostname-override:显示名称,集群中唯一
                                                  • network-plugin:启用 CNI
                                                  • kubeconfig:自动生成的配置文件,后面用于连接 apiserver
                                                  • bootstrap-kubeconfig:首次启动向 apiserver 申请证书
                                                  • config:配置参数文件
                                                  • cert-dir:kubelet 证书生成目录
                                                  • pod-infra-container-image:管理 Pod 网络容器的镜像

                                                  配置参数文件。

                                                    cat > /opt/kubernetes/cfg/kubelet-config.yml << EOFkind: KubeletConfigurationapiVersion: kubelet.config.k8s.io/v1beta1address: 0.0.0.0port: 10250readOnlyPort: 10255cgroupDriver: systemdclusterDNS:- 10.10.0.2clusterDomain: cluster.localfailSwapOn: falseauthentication:  anonymous:    enabled: false  webhook:    cacheTTL: 2m0s    enabled: true  x509:    clientCAFile: /opt/kubernetes/ssl/ca.pemauthorization:  mode: Webhook  webhook:    cacheAuthorizedTTL: 5m0s    cacheUnauthorizedTTL: 30sevictionHard:  imagefs.available: 15%  memory.available: 100Mi  nodefs.available: 10%  nodefs.inodesFree: 5%maxOpenFiles: 1000000maxPods: 110EOF
                                                    • cgroupDriver: 需要与 Docker 的 cgroup 启动一致,这里都是用 systemd。
                                                    • clusterDNS: DNS 服务器地址,用来做服务名称和 ip 的解析用。service 启动会创建一条服务名和 ip 的解析,直接使用 service 名称就能访问服务,以达到服务发现的效果。这里先填上 ip,后边会部署这个 DNS 服务。

                                                    生成 kubelet bootstrap kubeconfig 配置文件, 用来申请 apiserver 证书。

                                                      kubectl config set-cluster kubernetes \  --certificate-authority=/opt/kubernetes/ssl/ca.pem \  --embed-certs=true \  --server=https://192.168.10.12:6443 \  --kubeconfig=bootstrap.kubeconfigkubectl config set-credentials "kubelet-bootstrap" \  --token=ebe4f1e22044e23638394dd24d4aff49 \  --kubeconfig=bootstrap.kubeconfigkubectl config set-context default \  --cluster=kubernetes \  --user="kubelet-bootstrap" \  --kubeconfig=bootstrap.kubeconfigkubectl config use-context default --kubeconfig=bootstrap.kubeconfig
                                                      cp bootstrap.kubeconfig /opt/kubernetes/cfg

                                                      创建 system 服务管理文件。

                                                        cat > /usr/lib/systemd/system/kubelet.service << EOF[Unit]Description=Kubernetes KubeletAfter=docker.service
                                                        [Service]EnvironmentFile=/opt/kubernetes/cfg/kubelet.confExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTSRestart=on-failureLimitNOFILE=65536
                                                        [Install]WantedBy=multi-user.targetEOF

                                                        启动

                                                          systemctl daemon-reloadsystemctl start kubeletsystemctl enable kubelet

                                                          启动之后,在 Master 节点可以看到申请,需要执行如下命令来接受。

                                                            # 查看node 加入申请[root@10-11-master]# kubectl get csrNAME                                                   AGE   REQUESTOR           CONDITIONnode-csr-zXbvV_-slQhtuuKZddLIl9H4mKEfOhTkB-8TtaW2Nf8   36s   kubelet-bootstrap   Pending
                                                            # 接受申请kubectl certificate approve node-csr-zXbvV_-slQhtuuKZddLIl9H4mKEfOhTkB-8TtaW2Nf8
                                                            # 查看node[root@10-11-master]# kubectl get nodeNAME                     STATUS     ROLES    AGE    VERSION75-33-65-shx-node        NotReady1s     v1.16.0

                                                            节点状态为 NotReady,稍后等 kubelet 初始化好后,变为 Ready。有些 kubelet 配置了 cni(容器网络接口)插件,当插件安装之前,不会变为 Ready。

                                                            3.2/ kube-proxy 部署

                                                            证书签发

                                                              cd /opt/kubernetes/sslcat > kube-proxy-csr.json << EOF{  "CN": "system:kube-proxy",  "hosts": [],  "key": {    "algo": "rsa",    "size": 2048  },  "names": [    {      "C": "CN",      "L": "BeiJing",      "ST": "BeiJing",      "O": "k8s",      "OU": "System"    }  ]}EOF
                                                              # 生成证书cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
                                                              ls kube-proxy*pemkube-proxy-key.pem  kube-proxy.pem

                                                              环境变量配置文件

                                                                # 环境变量配置文件cat > /opt/kubernetes/cfg/kube-proxy.conf << EOFKUBE_PROXY_OPTS="--logtostderr=false \\--v=2 \\--log-dir=/opt/kubernetes/logs \\--config=/opt/kubernetes/cfg/kube-proxy-config.yml"EOF
                                                                # 配置文件cat > /opt/kubernetes/cfg/kube-proxy-config.yml << EOFkind: KubeProxyConfigurationapiVersion: kubeproxy.config.k8s.io/v1alpha1bindAddress: 0.0.0.0metricsBindAddress: 0.0.0.0:10249clientConnection:  kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfighostnameOverride: 10-14-nodeclusterCIDR: 10.10.0.0/16EOF

                                                                systemd 服务管理脚本

                                                                  cat > /usr/lib/systemd/system/kube-proxy.service << EOF[Unit]Description=Kubernetes ProxyAfter=network.target
                                                                  [Service]EnvironmentFile=/opt/kubernetes/cfg/kube-proxy.confExecStart=/opt/kubernetes/bin/kube-proxy \$KUBE_PROXY_OPTSRestart=on-failureLimitNOFILE=65536
                                                                  [Install]WantedBy=multi-user.targetEOF

                                                                  启动

                                                                    systemctl daemon-reloadsystemctl start kube-proxysystemctl enable kube-proxy

                                                                    至此,Node 节点部署完成。其他 Node 部署相同,修改对应 ip 和 host 即可。

                                                                    4/ 网络插件部署

                                                                    安装完 Node 节点组件之后,Pod 内容器是可以通信的,但是 Pod 之间是无法通信的,这就需要 CNI 网络插件了。常用的 CNI 插件有 Calico、flannel、Terway、Weave Net 以及 Contiv。这里选用常用的 Flannel,如何选择 CNI 插件,大家可参考这篇文章 理解 CNI 和 CNI 插件[4]

                                                                    CNI 插件的安装方式有两种:

                                                                    • ETCD 方式。这种方式就是利用 etcd 存储网络配置信息,并且利用 dockerd 启动参数--bip来指定每个节点的网段信息。
                                                                    • CNI 插件方式。这种方式是利用 cni 插件,并且将网络配置信息存储在 kubernetes api 中,Kubulet 找到对应的 cni 插件,有插件分配节点 IP 网段。

                                                                    CNI 插件主要部署在有 Pod 调度的节点,常部署在 Node 节点。

                                                                    4.1/ CNI 方式安装

                                                                    CNI 插件方式,首先需要在 Master 各组件增加一些参数。

                                                                    1/ 修改 controller 参数

                                                                    在 kube-controller-manager 启动脚本中加入下边两个参数:

                                                                    • --allocate-node-cidrs=true 节点允许自动分配网段。
                                                                    • --cluster-cidr=10.10.0.0/16 为我们指定的集群的网段,这样每一个 docker 节点都会分别使用自网段 10.10.0.0/24,10.10.1.0/24 作为每个 pod 的网段,可以通过kubectl get pod-o yaml命令查看spec.podCIDR字段。

                                                                    如果不配置该步骤可能会flannel出现error registering network: failed to acquire lease: node "192.168.10.14" pod的错误

                                                                    2/ 修改 kubelet 参数

                                                                    指定 kubelet 网络插件,在 kubelet 中指定如下三个参数:

                                                                    • --network-plugin=cni 网络插件使用 cni,必须添加,否则默认走 docker 自己的网络。
                                                                    • --cni-conf-dir=/etc/cni/net.d cni 配置文件 ,默认
                                                                    • --cni-bin-dir=/opt/cni/bin cni 可执行文件,默认

                                                                    这样在 kublet 启动的时候,就会去/etc/cni/net.d 目录查找配置文件,并解析,使用相应的插件配置网络

                                                                    3/ 下载 cni 依赖插件

                                                                    下载 cni 官方提供的组件:cni-plugins-amd64-v0.7.1.tgz[5] ,并将可执行文件放在/opt/cni/bin 目录。

                                                                    这里不单单只会用到 flannel 文件,也会用到 brage 用来创建网桥以及 host-local 用来分配 ip。

                                                                    这一步不是必须的,当使用 yum 安装 kubelet 时,会自动下载依赖的kubernetes-cni包,并放置到相应位置。

                                                                    4/ 安装 flanneld 组件

                                                                    flannel 组件直接以daemonset的方式安装在 k8s 集群中:

                                                                      wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.ymlkubectl apply -f kube-flannel.yml

                                                                      其中kube-flannel-cfg configmap 中的 Network 字段需要与--cluster-cidr配置的网段一致。

                                                                      这一步主要是安装了flanneld以及将flannel配置文件写入/etc/cni/net.d目录。

                                                                      查看kube-flannel.ymlflanneld的启动参数为:

                                                                        --ip-masq : 需要为其配置SNAT--kube-subnet-mgr : 代表其使用kube类型的subnet-manager。该类型有别于使用etcd的local-subnet-mgr类型,使用kube类型后,flannel上各Node的IP子网分配均基于K8S Node的`spec.podCIDR`属性

                                                                        4.2/ ETCD 方式

                                                                        ETCD 方式安装Flannel,参数无需修改,可保持之前步骤中的参数。

                                                                        1/ 创建 Flannel 使用的网段

                                                                        该方式,网段信息是保存在 ETCD 的,需要我们手动的添加

                                                                          [root@10-14-node ~]# ETCDCTL_API=2 etcdctl --ca-file=/usr/local/kubernetes/etcd/ssl/ca.pem --cert-file=/usr/local/kubernetes/etcd/ssl/server.pem --key-file=/usr/local/kubernetes/etcd/ssl/server-key.pem --endpoints="https://192.168.10.14:2379,https://192.168.10.15:2379,https://192.168.10.16:2379" set /coreos.com/network/config '{"Network":"10.10.0.0/16","Backend":{"Type":"vxlan"}}'{"Network":"10.10.0.0/16","Backend":{"Type":"vxlan"}}[root@10-14-node ~]# ETCDCTL_API=2 etcdctl --ca-file=/usr/local/kubernetes/etcd/ssl/ca.pem --cert-file=/usr/local/kubernetes/etcd/ssl/server.pem --key-file=/usr/local/kubernetes/etcd/ssl/server-key.pem --endpoints=https://192.168.10.14:2379,https://192.168.10.15:2379,https://192.168.10.16:2379 get /coreos.com/network/config{"Network":"10.10.0.0/16","Backend":{"Type":"vxlan"}}[root@10-15-node ~]# ETCDCTL_API=2 etcdctl --ca-file=/usr/local/kubernetes/etcd/ssl/ca.pem --cert-file=/usr/local/kubernetes/etcd/ssl/server.pem --key-file=/usr/local/kubernetes/etcd/ssl/server-key.pem --endpoints=https://192.168.10.14:2379,https://192.168.10.15:2379,https://192.168.10.16:2379 get /coreos.com/network/config{"Network":"10.10.0.0/16","Backend":{"Type":"vxlan"}}

                                                                          使用该方式安装时,flannel 仅支持 etcd2 版本的 api,针对 etcd 3+ 需要做下兼容。在 etcd 的启动时添加参数--enable-v2 做兼容。etcdctl 执行时,需要加 ETRCDCTL_API=2 的环境变量。不做兼容的话,汇报如下错误:Couldn't fetch network config: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint. timed out, 可见这个issue[6]

                                                                          2/ 安装 Flannel

                                                                          下载二进制文件,https://github.com/coreos/flannel/releases , 这里选用 0.11。

                                                                            wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gztar zxvf flannel-v0.11.0-linux-amd64.tar.gzmv flanneld mk-docker-opts.sh /opt/kubernetes/bin/
                                                                            # 配置文件cat > /opt/kubernetes/cfg/flannel.conf << EOFFLANNEL_OPTIONS="--etcd-endpoints=https://192.168.10.14:2379,https://192.168.10.14:2379,https://192.168.10.14:2379 \\--etcd-cafile=/opt/etcd/ssl/ca.pem \\--etcd-certfile=/opt/etcd/ssl/server.pem \\--etcd-keyfile=/opt/etcd/ssl/server-key.pem"EOF
                                                                            # 添加启动文件cat > /usr/lib/systemd/system/flanneld.service << EOF[Unit]Description=Flanneld overlay address etcd agentAfter=network-online.target network.targetBefore=docker.service
                                                                            [Service]Type=notifyEnvironmentFile=/usr/local/kubernetes/cfg/flannel.confExecStart=/usr/local/kubernetes/bin/flanneld --ip-masq $FLANNEL_OPTIONSExecStartPost=/usr/local/kubernetes/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.envRestart=on-failure
                                                                            [Install]WantedBy=multi-user.targetEOF
                                                                            # 启动systemctl daemon-reloadsystemctl start flanneldsystemctl enable flanneld

                                                                            启动之后会在/run/flannel/subnet.env 生成一个子网描述文件,内容如下:

                                                                              DOCKER_OPT_BIP="--bip=10.10.101.1/24"DOCKER_OPT_IPMASQ="--ip-masq=false"DOCKER_OPT_MTU="--mtu=1450"DOCKER_NETWORK_OPTIONS=" --bip=10.10.101.1/24 --ip-masq=false --mtu=1450"

                                                                              我们需要将它配置为 Docker 的环境变量,以供 Docker 分配 ip 使用。

                                                                                [Service]...EnvironmentFile=/run/flannel/subnet.envExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $DOCKER_NETWORK_OPTIONS...

                                                                                重启 Docker,以加载新的配置。

                                                                                  systemctl daemon-reloadsystemctl restart docker

                                                                                  至此,Flannel 插件边安装完成了。安装完成后,可通过 ip a看到,自动创建了一个flannel.1 类似名称的虚拟网卡出现,主要用来做 vxlan 报文的处理,封包和解包。

                                                                                    [root@10-14-node ]# ip a1: lo:mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000,up,lower_up>    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00    inet 127.0.0.1/8 scope host lo       valid_lft forever preferred_lft forever    inet6 ::1/128 scope host       valid_lft forever preferred_lft forever2: eth0:mtu 1500 qdisc mq state UP group default qlen 1000,multicast,up,lower_up>    link/ether c4:b8:b4:91:4e:99 brd ff:ff:ff:ff:ff:ff    inet 192.168.10.14/24 brd 192.168.10.255 scope global eth0       valid_lft forever preferred_lft forever3: eth1:mtu 1500 qdisc noop state DOWN group default qlen 1000,multicast>    link/ether c4:b8:b4:91:4e:9a brd ff:ff:ff:ff:ff:ff4: docker0:mtu 1500 qdisc noqueue state DOWN group default,broadcast,multicast,up>    link/ether 02:42:26:57:30:53 brd ff:ff:ff:ff:ff:ff    inet 10.10.101.1/24 brd 10.10.101.255 scope global docker0       valid_lft forever preferred_lft forever    inet6 fe80::42:26ff:fe57:3053/64 scope link       valid_lft forever preferred_lft forever9: flannel.1:mtu 1450 qdisc noqueue state UNKNOWN group default,multicast,up,lower_up>    link/ether 2a:3c:d8:f4:f9:aa brd ff:ff:ff:ff:ff:ff    inet 10.10.101.0/32 scope global flannel.1       valid_lft forever preferred_lft forever    inet6 fe80::283c:d8ff:fef4:f9aa/64 scope link       valid_lft forever preferred_lft forever

                                                                                    在看路由:

                                                                                      [root@75-33-65-shx-node data0]# routeKernel IP routing tableDestination     Gateway         Genmask         Flags Metric Ref    Use Ifacedefault         gateway         0.0.0.0         UG    0      0        0 eth010.10.15.0      10.10.15.0      255.255.255.0   UG    0      0        0 flannel.110.10.53.0      10.10.53.0      255.255.255.0   UG    0      0        0 flannel.110.10.66.0      10.10.66.0      255.255.255.0   UG    0      0        0 flannel.110.10.70.0      10.10.70.0      255.255.255.0   UG    0      0        0 flannel.110.10.96.0      10.10.96.0      255.255.255.0   UG    0      0        0 flannel.110.10.101.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0...

                                                                                      除了自身 10.10.101.0的包,其他10.10.0.0/16网段的包都走 flannel.1虚拟网卡。

                                                                                      5/ DNS 服务插件部署

                                                                                      在 K8S 中,DNS 服务主要用来解析 Service 名称和 ip。当有新的 service 时,无需知道它的 ip 直接使用名称即可调用。K8S 目标有两种常用的 DNS 方案,kube-dnsCoreDNSCoreDNS从 1.11 起,使用kubeadm 安装 K8S 时,是默认安装的。这里也选择安装 CoreDNS,因为CoreDNS服务是以 pod 的形式运行,所以下边操作只需在一台 Master 上操作即可。

                                                                                      下面开始安装:

                                                                                        # 下载 CoreDNS 项目git clone https://github.com/coredns/deployment.gitcd coredns/deployment/kubernetes

                                                                                        找到 deploy.sh, 修改如下配置:

                                                                                          111 if [[ -z $CLUSTER_DNS_IP ]]; then112   # Default IP to kube-dns IP113   # CLUSTER_DNS_IP=$(kubectl get service --namespace kube-system kube-dns -o jsonpath="{.spec.clusterIP}")114   CLUSTER_DNS_IP=10.10.0.2

                                                                                          默认情况下 CLUSTER_DNS_IP 是自动获取kube-dns的集群 ip 的,但是由于没有部署 kube-dns 所以只能手动指定一个集群 ip。

                                                                                            # 生成 发布文件sh deploy.sh > coredns.yaml
                                                                                            # 引用yamlkubectl apply -f coredns.yaml
                                                                                            kubectl get svc,pods -n kube-system| grep corednspod/coredns-759df9d7b-gzj5b   1/1     Running   0          22h

                                                                                            测试下:

                                                                                              cat > busybox.yml <apiVersion: v1kind: Podmetadata:  name: busybox  namespace: defaultspec:  containers:  - name: busybox    image: busybox:1.28.4    command:      - sleep      - "3600"    imagePullPolicy: IfNotPresent  restartPolicy: AlwaysEOFkubectl apply -f busybox.ymlkubectl exec -i busybox nslookup kubernetesServer:    10.10.0.2Address 1: 10.10.0.2 kube-dns.kube-system.svc.cluster.local
                                                                                              Name:      kubernetesAddress 1: 10.10.0.1 kubernetes.default.svc.cluster.local

                                                                                              出现以上信息,说明解析正常。

                                                                                              6/ Dashboard 部署

                                                                                              K8S 官方提供了一个 web 的操作界面叫 Dashboard,可以满足基本的资源的创建、配置和修改。下面说下如何安装:

                                                                                                wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
                                                                                                # 下载好配置文件,修改service 访问策略为 NodePort,可直接通过node 的ip访问。...spec:  ports:    - port: 443      targetPort: 8443      nodePort: 30001 # 新增  type: NodePort   # 新增...
                                                                                                kubectl apply -f recommended.yamlkubectl get pods,svc -n kubernetes-dashboardNAME                                             READY   STATUS    RESTARTS   AGEpod/dashboard-metrics-scraper-76585494d8-hbjj4   1/1     Running   0          8dpod/kubernetes-dashboard-5996555fd8-j5kq9        1/1     Running   0          8d
                                                                                                NAME                                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGEservice/dashboard-metrics-scraper   ClusterIP   10.10.130.258000/TCP        8dservice/kubernetes-dashboard        NodePort    10.10.32.39443:30001/TCP   8d

                                                                                                可通过 https://:30001 来访问,系统提供了两种任务方式,我们常用 token 认证方式,下边我们来生成 token。

                                                                                                  # 创建service admin 账户 dashboard-adminkubectl create serviceaccount dashboard-admin -n kube-system# 绑定集群默认管理员角色 cluster-adminkubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin# 查看登录 tokenkubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

                                                                                                  可使用上边输出的 token ,登录 dashboard。

                                                                                                  高可用架构

                                                                                                  到这里,我们所有节点组件完成。我们的架构如下图:

                                                                                                  从图中我们可以看出一个问题,controller-managerscheduler可通过etcd间接的通信实现互为备份高可用,而apiserver则没有。架构中所有的 Node 都是连接的一台 Master 的 apiserver,其他两台并没有利用起来,连接的这台一旦出现故障,整个系统便无法使用。这个问题,常用的解决方案是使用 nginxkeeplive 实现,架构如下:

                                                                                                  因为需要单独申请 VIP,我并没有做具体搭建,仅使用 nginx 做了负载均衡。需要注意的是,这里 Nginx 用来做四层的负载均衡使用 stream配置段,和http略有不同。

                                                                                                  这里简单说下搭建步骤,最少使用两台机器互为主备。

                                                                                                    # 安装nginx 和 keepalive。yum install epel-release -yyum install nginx keepalived -y
                                                                                                    # nginx 配置文件cat > /etc/nginx/nginx.conf << "EOF"user nginx;worker_processes auto;error_log /var/log/nginx/error.log;pid /run/nginx.pid;
                                                                                                    include /usr/share/nginx/modules/*.conf;
                                                                                                    events {    worker_connections 1024;}
                                                                                                    # 四层负载均衡,为两台Master apiserver组件提供负载均衡stream {
                                                                                                       log_format  main  '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
                                                                                                       access_log  /var/log/nginx/k8s-access.log  main;
                                                                                                       upstream k8s-apiserver {       server 192.168.10.14:6443;   # Master1 APISERVER IP:PORT       server 192.168.10.15:6443;   # Master2 APISERVER IP:PORT       server 192.168.10.16:6443;   # Master2 APISERVER IP:PORT    }
                                                                                                       server {       listen 6443;       proxy_pass k8s-apiserver;    }}
                                                                                                    http {    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '                      '$status $body_bytes_sent "$http_referer" '                      '"$http_user_agent" "$http_x_forwarded_for"';
                                                                                                       access_log  /var/log/nginx/access.log  main;
                                                                                                       sendfile            on;    tcp_nopush          on;    tcp_nodelay         on;    keepalive_timeout   65;    types_hash_max_size 2048;
                                                                                                       include             /etc/nginx/mime.types;    default_type        application/octet-stream;
                                                                                                       server {        listen       80 default_server;        server_name  _;
                                                                                                           location / {        }    }}EOF
                                                                                                    # keepalive 主机配置文件cat > /etc/keepalived/keepalived.conf << EOFglobal_defs {   notification_email {     acassen@firewall.loc     failover@firewall.loc     sysadmin@firewall.loc   }   notification_email_from Alexandre.Cassen@firewall.loc   smtp_server 127.0.0.1   smtp_connect_timeout 30   router_id NGINX_MASTER}
                                                                                                    vrrp_script check_nginx {    script "/etc/keepalived/check_nginx.sh"}
                                                                                                    vrrp_instance VI_1 {    state MASTER    interface ens33    virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的    priority 100    # 优先级,备服务器设置 90    advert_int 1    # 指定VRRP 心跳包通告间隔时间,默认1秒    authentication {        auth_type PASS        auth_pass 1111    }    # 虚拟IP    virtual_ipaddress {        192.168.31.88/24    }    track_script {        check_nginx    }}EOF
                                                                                                    # nginx 检测脚本,主备都需要有cat > /etc/keepalived/check_nginx.sh  << "EOF"#!/bin/bashcount=$(ps -ef |grep nginx |egrep -cv "grep|$$")
                                                                                                    if [ "$count" -eq 0 ];then    exit 1else    exit 0fiEOFchmod +x /etc/keepalived/check_nginx.sh
                                                                                                    # keepalive 备机配置文件cat > /etc/keepalived/keepalived.conf << EOFglobal_defs {   notification_email {     acassen@firewall.loc     failover@firewall.loc     sysadmin@firewall.loc   }   notification_email_from Alexandre.Cassen@firewall.loc   smtp_server 127.0.0.1   smtp_connect_timeout 30   router_id NGINX_BACKUP}
                                                                                                    vrrp_script check_nginx {    script "/etc/keepalived/check_nginx.sh"}
                                                                                                    vrrp_instance VI_1 {    state BACKUP    interface ens33    virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的    priority 90    advert_int 1    authentication {        auth_type PASS        auth_pass 1111    }    virtual_ipaddress {        192.168.31.88/24    }    track_script {        check_nginx    }}EOF
                                                                                                    # 启动,并设置开机启动systemctl daemon-reloadsystemctl start nginxsystemctl start keepalivedsystemctl enable nginxsystemctl enable keepalived
                                                                                                    # ip a ,可以看到 vip 已经绑定到网卡上inet 192.168.31.88/24 scope global secondary ens33    valid_lft forever preferred_lft forever

                                                                                                    接下里,将所有 Node 节点改为链接 VIP 的apiserver,重启 kubeletkube-proxy 即可。

                                                                                                    至此,一个高可用的 K8S 集群便搭建完成了,尽情享用吧。

                                                                                                    扩展阅读

                                                                                                    • 1/ 通过 Kubeadm 安装 K8S 与高可用[7]
                                                                                                    • 2/ Kubernetes 中文文档[8]
                                                                                                    • 3/ 详解 DNS 与 CoreDNS 的实现原理[9]
                                                                                                    • 4/ Flannel 网络[10]

                                                                                                    参考资料

                                                                                                    [1]

                                                                                                    Kubernetes 学习笔记-基础篇: https://pylixm.cc/posts/2020-08-20-k8s-base.html

                                                                                                    [2]

                                                                                                    安装文档: https://kubernetes.io/docs/setup/learning-environment/

                                                                                                    [3]

                                                                                                    启用文档: https://docs.docker.com/docker-for-mac/#kubernetes

                                                                                                    [4]

                                                                                                    理解 CNI 和 CNI 插件: https://www.kubernetes.org.cn/6908.html

                                                                                                    [5]

                                                                                                    cni-plugins-amd64-v0.7.1.tgz: https://github.com/containernetworking/plugins/releases/download/v0.7.1/cni-plugins-amd64-v0.7.1.tgz

                                                                                                    [6]

                                                                                                    issue: https://github.com/coreos/flannel/issues/1191

                                                                                                    [7]

                                                                                                    1/ 通过 Kubeadm 安装 K8S 与高可用: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/

                                                                                                    [8]

                                                                                                    2/ Kubernetes 中文文档: https://www.kubernetes.org.cn/docs

                                                                                                    [9]

                                                                                                    3/ 详解 DNS 与 CoreDNS 的实现原理: https://draveness.me/dns-coredns/

                                                                                                    [10]

                                                                                                    4/ Flannel 网络: https://www.cnblogs.com/goldsunshine/p/10740928.html


                                                                                                    点赞
                                                                                                    收藏
                                                                                                    表情
                                                                                                    图片
                                                                                                    附件