kubeadm搭建高可用集群v1.18.2

kubeadm搭建高可用集群

本地虚拟机环境

虚拟机IP节点角色备注
192.168.163.252工作节点/master节点版本号 v1.18.2
192.168.163.251工作节点/master节点版本号 v1.18.2
192.168.162.96nginx代理节点vip:192.168.162.97
192.168.162.98nginx代理节点vip:192.168.162.97

准备工作

  1. 禁用swap分区和selinux,关闭firewalld。

     sudo swapoff -a
     sudo systemctl stop firewalld
     sudo systemctl disable firewalld
     setenforce 0
     sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
    
  2. 安装docker-ce

    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sudo yum install -y docker-ce
    
  3. 修改Docker的Cgroup Driver(可选操作)

    mkdir /etc/docker
    cat <<EOF > /etc/docker/daemon.json
    {
    "exec-opts": ["native.cgroupdriver=systemd"]
    }
    EOF
    systemctl restart docker
    systemctl enable docker	
    

    注:Docker在默认情况下使用的Cgroup Driver为cgroupfs而kubernetes1.14之后推荐使用systemd来代替 cgroupfs,详见: https://kubernetes.io/docs/setup/cri

  4. 添加Yum源(可选操作)

    cat <<EOF > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=KubernetesRepos
    baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
    gpgcheck=0
    enabled=1
    EOF
    

    注:因为kubeadm默认的源地址背墙,这里使用阿里云yum源。

  5. 启动bridge-nf方式

    cat <<EOF >  /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.bridge.bridge-nf-call-arptables = 1
    EOF
    sysctl -p /etc/sysctl.d/k8s.conf
    

注:在iptables没有开启 bridge-nf时,数据会直接经过网桥转发,会导致FORWARD的设置失效;

centos默认不开启 bridge-nf

安装需要的组件

  1. 安装kubeadm、kubelet、kubectl(所有节点都需要安装)

    sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
    #因为这里是自己的本地虚拟机测试环境,所以直接安装最新的版本踩坑,如果要安装指定版本可以在后面指定版本号如下:
    sudo yum install -y kubelet-${version} kubeadm-${version} kubectl-${version} --disableexcludes=kubernetes
    sudo systemctl enable kubelet
    

    注:(为什么要单独部署kubelet)早期用二进制的方式部署kubernets时,不难发现kubernetes的每一个组件都是一个需要单独被执行的二进制文件,我们只需要根据这些组件的特性编写对应的启动脚本或服务单元即可,那么如果把这些组件放在一个docker容器镜像中,启动时用docker run命令启动,这样相比于其他的部署方式而言部署过程就会简单不少,但是有一个比较麻烦的问题:
    如何容器化 kubelet组件?

    kubelet除了要和docker容器基本交互之外,在进行容器的网络/数据卷管理时都需要直接和宿主机进行交互操作,如果将kubernetes运行在一个容器中那么和宿主机的交互就会比较麻烦,对于网络配置我们还可以使用Docker的host network模式直接共享宿主机的网络,但是让kubelet隔着容器的Mount Namespace和文件系统去操作宿主机的文件系统就显得比较困难了。到目前为止,在容器里运行 kubelet,依然没有很好的解决办法。(有人提出可以使用setns系统调用,没具体研究过)正因为如此,kubeadm 选择了一种妥协方案:

    即:kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件。

  2. 在两个代理节点安装nginx

    #为了方便这里直接使用epel源安装nginx
    sudo yum install -y nginx
    #添加stream模块配置文件,同时编辑主配置文件添加我们的配置文件所在地址
    mkdir -p /etc/nginx/stream.d && cd /etc/nginx
    #修改nginx主配置文件 (指令 i 进入插入模式  esc退出到底行模式 键入 :wq保存(w)退出(q))
    vi nginx.conf
    #添加内容如下:
    	stream {
       		log_format kubernetes  '$remote_addr [$time_local] '
                         '$protocol $status $bytes_sent $bytes_received '
                         '$session_time "$upstream_addr" '
                         '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
       		access_log  /opt/logs/nginx/.access.log kubernetes;
       		include /etc/nginx/stream.d/*.conf;
    	}
    #编辑子配置文件
    vi stream.d/k8s.conf
    #添加内容如下
    upstream stream_apiserver_kube {
       server 192.168.163.252:6443 weight=5 max_fails=3 fail_timeout=30s;
       server 10.200.163.251:6443 weight=5 max_fails=3 fail_timeout=30s;
    }
    server {
     listen 6443;
     proxy_pass stream_apiserver_kube;
     proxy_connect_timeout 5s;
     proxy_timeout 3s;
    }
    #最后检测一下我们的配置文件是否正确
    nginx -t -c /etc/nginx/nginx.conf
    #启动nginx
    nginx
    #查看端口是否已经监听
    ss -tlnup | grep 6443
    #如果监听成功 示例输出如下
    tcp    LISTEN     0      128       *:6443                  *:*                   users:(("nginx",pid=7523,fd=27),("nginx",pid=7522,fd=27),("nginx",pid=7521,fd=27),("nginx",pid=7520,fd=27),("nginx",pid=7519,fd=27),("nginx",pid=7518,fd=27),("nginx",pid=7517,fd=27),("nginx",pid=7516,fd=27),("nginx",pid=871,fd=27))
    
  3. 在两个代理节点安装keepalived
    #这里直接用yum进行安装
    yum install-y keepalived
    #编辑配置文件
    vi /etc/keepalived/keepalived.conf
    #内容示例
    ! Configuration File for keepalived

    global_defs {
       router_id host96  ##标识节点的字符串,通常为hostname
    
    }
    
    vrrp_script chk_nginx {
        script "/etc/keepalived/check_nginx_pid.sh"  ##执行脚本位置
        interval 2  ##检测时间间隔
        weight -20  ##如果条件成立则权重减20
    }
    
    vrrp_instance VI_1 {
        state MASTER  ## 主节点为MASTER,备份节点为BACKUP
        interface ens33  ## 绑定虚拟IP的网络接口(网卡),与本机IP地址所在的网络接口相同(我这里是ens33)
        virtual_router_id 110  ## 虚拟路由ID号(主备节点一定要相同)
        mcast_src_ip 192.168.162.96 ## 本机ip地址
        priority 100  ##优先级配置(0-254的值)
        nopreempt
        advert_int 1  ## 组播信息发送间隔,俩个节点必须配置一致,默认1s
    authentication {  ## 认证匹配
            auth_type PASS
            auth_pass abc
        }
    
        track_script {
            chk_nginx
        }
    
        virtual_ipaddress {
            192.168.162.97  ## 虚拟ip,可以指定多个
        }
    }
    #编写检查脚本
    
    vi /etc/keepalived/check_nginx_pid.sh
    
    #内容如下
    
    #!/bin/bash
    A=`ps -C nginx --no-header |wc -l`
    if [ $A -eq 0 ];then
        /usr/sbin/nginx -c /etc/nginx/nginx.conf              #重启nginx
        if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then    #nginx重启失败
            exit 1
        else
            exit 0
        fi
    else
        exit 0
    fi
    
    #开始启动keepalived
    chkconfig keepalived on
    service keepalived start
    systemctl enable keepalived
    #重启网络服务
    systemctl restart network
    

    注意啦,如果你是源码安装的nginx那么你需要手动建立软连接到/usr/sbin
    并给脚本授权

    sudo chmod +x nginx
    

使用kubeadm init 部署主节点

  1. 编辑我们的kubeadmin配置文件

    #为了防止端口被占用 建议先使用 ss 命令查看6443端口是否被占用
    cat <<EOF > kubeadm-config.yaml
    apiVersion: kubeadm.k8s.io/v1beta2
    kind: InitConfiguration
    localAPIEndpoint:
      bindPort: 6443
    ---
    apiVersion: kubeadm.k8s.io/v1beta2
    kind: ClusterConfiguration
    kubernetesVersion: v1.18.2
    controlPlaneEndpoint: "192.168.162.97:6443"
    imageRepository: "registry.aliyuncs.com/google_containers"
    networking:
      podSubnet: "10.212.0.0/16"
    apiServer:
      certSANs:
      - "k8s.cxpt.com"
    EOF
    

这一块建议参考系统给的默认配置结合自己的实际情况进行修改,查看命令如下:

	sudo kubeadm config print init-defaults
	sudo kubeadm config print join-defaults

开始初始化我们的集群节点

	sudo kubeadm init --config=kubeadm-config.yaml  --upload-certs

初始化成功以后打印信息里面包含了我们后面添加master和worker节点的join语句如下

在另外一个节点执行join语句添加另外一个主节点

#具体语句根据实际你的日志打印内容填写
kubeadm join 192.168.162.97:6443 --token crj05r.b380vndwk3pwzb6p \
     --discovery-token-ca-cert-hash sha256:5649ba2d8669266977575c1a2ef45fe10dc866251e66aa5acaaf6016acbcf6dd \
     --control-plane --certificate-key 8feba8cff94acecbfe128e34ad2f23322821c8c68beba705e0e8fcff096e118e

配置kubectl

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

安装flannled,具体参见addones

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

#如果网络不佳可以下载这个yaml文件之后替换镜像为阿里云,操作如下:
wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

sed -i s#'quay.io/coreos/flannel:v0.12.0-amd64'#'registry.cn-hangzhou.aliyuncs.com/mygcrio/flannel:v0.12.0-amd64'#g kube-flannel.yml

kubectl apply -f kube-flannel.yml

检查etcd健康状况

docker run --rm -it --net host -v /etc/kubernetes:/etc/kubernetes \
registry.aliyuncs.com/google_containers/etcd:3.4.3-0 etcdctl \
 --cert /etc/kubernetes/pki/etcd/peer.crt \
 --key /etc/kubernetes/pki/etcd/peer.key \
 --cacert /etc/kubernetes/pki/etcd/ca.crt \
 --endpoints https://192.168.163.252:2379,https://192.168.163.251:2379 endpoint health

复用master节点作为worker节点

kubectl taint nodes --all node-role.kubernetes.io/master-
#禁止某个主节点作为worker节点
kubectl taint nodes node1 node-role.kubernetes.io/master=true:NoSchedule

查看各组件运行状态

kubectl get componentstatus

当我们运行kubeadm init 时它都为我们做了什么?

1-1. 首先会运行一系列预检代码来检查系统的状态(Preflight Checks),例如:

	-  Linux的内核版本是否符合要求
	-  kubeadm 和 kubelet版本是否对应
	-  是否安装了Docker
	-  kubelet的工作端口是否被占用
	-  ......

你也可以使用–ignore-preflight-errors参数来忽略一些前置检查错误,一般不建议这么做。

1-2. 通过了 Preflight Checks 之后,kubeadm 要为你做的,是生成 Kubernetes 对外提供服务所需的各种证书和对应的目录

kubeadm 为 Kubernetes 项目生成的证书文件默认都放在 Master 节点的 /etc/kubernetes/pki 目录下,可以通过–cert-dir修改,生成的证书如下:

$ ls /etc/kubernetes/pki 
apiserver.crt              apiserver-etcd-client.key  apiserver-kubelet-client.crt  ca.crt  etcd                front-proxy-ca.key      front-proxy-client.key  sa.pub
apiserver-etcd-client.crt  apiserver.key              apiserver-kubelet-client.key  ca.key  front-proxy-ca.crt  front-proxy-client.crt  sa.key

具体的证书介绍可以从参考这个站点: k8s证书介绍

注意默认生成的证书有效期只有一年

你也可以将自己的证书拷贝到 /etc/kubernetes/pki/ 不让kubeadm为你生成证书

1-3.生成证书完成后,kubeadm会为其他组件生成访问 kube-apiserver 所需的配置文件,这些文件默认生成在 /etc/kubernetes/ 下,查看如下:

	ls /etc/kubernetes/*.conf

	/etc/kubernetes/admin.conf  /etc/kubernetes/controller-manager.conf  /etc/kubernetes/kubelet.conf  /etc/kubernetes/scheduler.conf 

这些文件里面记录着Master节点的服务器地址、监听端口、证书目录等等。对应的客户端节点(如kubelet 等),可以直接加载相应的文件与 kube-apiserver建立安全连接。参数中如果包含–feature-gates=DynamicKubeletConfig,会把kubelet的初始化配置文件写入/var/lib/kubelet/config/init/kubelet这个文件里面。

1-4.接下来,kubeadm 会为 Master 组件生成静态Pod配置文件。而后它们都会被使用 Pod 的方式部署起来。如果没有提供外部etcd,还会另外生成一个etcd的静态Pod配置文件。这些静态pod会被写入/etc/kubernetes/manifests,kubelet进程会加载这个目录的配置,从而创建相关的pod。

关于静态pod:

它允许你把要部署的 Pod 的 YAML 文件放在一个指定的目录里。这样,当这台机器上的 kubelet 启动时,它会自动检查这个目录,加载所有的 Pod YAML 文件,然后在这台机器上启动它们。

1-5.给当前的节点(Master节点)打label和taints,从而防止其他的负载在这个节点运行

1-6.生成一个 bootstrap token。只要持有这个 token,任何一个安装了 kubelet 和 kubadm 的节点,都可以通过 kubeadm join 加入到这个集群当中.默认生成的token有效期是24h。

1-7.进行一些允许节点以 Bootstrap Tokens 和 TLS bootstrapping 方式加入集群的必要的操作

- 设置RBAC规则,同时创建一个用于节点加入集群的ConfigMap
- 让Bootstrap Tokens可以访问CSR签名的API。
- 给新的CSR请求配置自动认证机制。

1-8.通过apiServer安装DNS服务器。

dashBoard安装

1.安装dashBoard2.0

	kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

2.暴露端口

kubectl expose svc kubernetes-dashboard --port=443 --target-port=8443 --type=NodePort --name=test-dashboard -n kubernetes-dashboard

kubectl get svc -n kubernetes-dashboard

3.访问dashboard

https://192.168.163.251:32635/

4.获取secret信息

kubectl -n kubernetes-dashboard get secret

5.获取token

kubectl -n kubernetes-dashboard describe secrets kubernetes-dashboard-token-gqf25

创建admin用户进行登录

vi admin-user.yaml
	
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system


kubectl apply -f admin-user.yaml

查看admin秘钥

	kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')	

创建一个单独的namespce并用上述方式为其创建集群的超级管理员

apiVersion: v1
kind: Namespace
metadata:
	name: development
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-dev
  namespace: development
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-dev
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-dev
  namespace: development

kubectl apply -f admin-dev.yaml

kubectl describe secret  -n development $(kubectl -n development  get secret | grep admin-dev  | awk '{print $1}' )

生成kubeconfig文件

#设置token变量
DASHBOARD_LOGIN_TOKEN=`kubectl describe secret  -n development $(kubectl -n development  get secret | grep admin-dev  | awk '{print $1}' )  | grep -E '^token' | awk '{print $2}'`
#设置远端API地址
KUBE_APISERVER="https://192.168.162.97:6443"	
# 设置集群参数
kubectl config set-cluster kubernetes   --certificate-authority=/etc/kubernetes/pki/ca.crt   --embed-certs=true   --server=${KUBE_APISERVER}   --kubeconfig=dashboard.kubeconfig
# 设置客户端认证参数,使用上面创建的 Token
kubectl config set-credentials dashboard_user \
  --token=${DASHBOARD_LOGIN_TOKEN} \
  --kubeconfig=dashboard.kubeconfig
# 设置上下文参数
kubectl config set-context default \
  --cluster=kubernetes \
  --user=dashboard_user \
  --kubeconfig=dashboard.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=dashboard.kubeconfig

附录

kubeadm init 参数解释

      --apiserver-advertise-address string   设置 apiserver 绑定的 IP.
      --apiserver-bind-port int32            设置apiserver 监听的端口. (默认 6443)
      --apiserver-cert-extra-sans strings    api证书中指定额外的Subject Alternative Names (SANs) 可以是IP 也可以是DNS名称。 证书是和SAN绑定的。
      --cert-dir string                      证书存放的目录 (默认 "/etc/kubernetes/pki")
      --certificate-key string               kubeadm-cert secret 中 用于加密 control-plane 证书的key
      --config string                        kubeadm 配置文件的路径.
      --cri-socket string                    CRI socket 文件路径,如果为空 kubeadm 将自动发现相关的socket文件; 只有当机器中存在多个 CRI  socket 或者 存在非标准 CRI socket 时才指定.
      --dry-run                              测试,并不真正执行;输出运行后的结果.
      --feature-gates string                 指定启用哪些额外的feature 使用 key=value 对的形式。
      -h, --help                                 帮助文档
      --ignore-preflight-errors strings      忽略前置检查错误,被忽略的错误将被显示为警告. 例子: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.
      --image-repository string              选择拉取 control plane images 的镜像repo (default "k8s.gcr.io")
      --kubernetes-version string            选择K8S版本. (default "stable-1")
      --node-name string                     指定node的名称,默认使用 node 的 hostname.
      --pod-network-cidr string              指定 pod 的网络, control plane 会自动将 网络发布到其他节点的node,让其上启动的容器使用此网络
      --service-cidr string                  指定service 的IP 范围. (default "10.96.0.0/12")
      --service-dns-domain string            指定 service 的 dns 后缀, e.g. "myorg.internal". (default "cluster.local")
      --skip-certificate-key-print           不打印 control-plane 用于加密证书的key.
      --skip-phases strings                  跳过指定的阶段(phase)
      --skip-token-print                     不打印 kubeadm init 生成的 default bootstrap token 
      --token string                         指定 node 和control plane 之间,简历双向认证的token ,格式为 [a-z0-9]{6}\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef
      --token-ttl duration                   token 自动删除的时间间隔。 (e.g. 1s, 2m, 3h). 如果设置为 '0', token 永不过期 (default 24h0m0s)
      --upload-certs                         上传 control-plane 证书到 kubeadm-certs Secret.
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值