• K8S折磨的安装篇



    Kubernetes介绍

    应用部署方式演变

    在部署应用程序的方式上,主要经历了三个时代:

    • 传统部署:互联网早期,会直接将应用程序部署在物理机上

      优点:简单,不需要其它技术的参与

      缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序之间容易产生影响

    • 虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境

      优点:程序环境不会相互产生影响,提供了一定程度的安全性

      缺点:增加了操作系统,浪费了部分资源

    • 容器化部署:与虚拟化类似,但是共享了操作系统

      优点:

      可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等

      运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦

      容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署

    在这里插入图片描述
    容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:

    • 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
    • 当并发访问量变大的时候,怎么样做到横向扩展容器数量

    这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:

    • Swarm:Docker自己的容器编排工具
    • Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
    • Kubernetes:Google开源的的容器编排工具

    在这里插入图片描述


    kubernetes简介

    在这里插入图片描述
    kubernetes,是一个全新的基于容器技术的分布式架构领先方案,是谷歌严格保密十几年的秘密武器----Borg系统的一个开源版本,于2014年9月发布第一个版本,2015年7月发布第一个正式版本。

    kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:

    • 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
    • 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
    • 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
    • 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
    • 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
    • 存储编排:可以根据容器自身的需求自动创建存储卷

    kubernetes组件

    一个kubernetes集群主要是由控制节点(master),工作节点(node)构成,每个节点上都会安装不同的组件。

    在这里插入图片描述

    master:集群的控制平面,负责集群的决策 ( 管理 )

    ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制

    Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上

    ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等

    Etcd :负责存储集群中各种资源对象的信息

    node:集群的数据平面,负责为容器提供运行环境 ( 干活 )

    Kubelet : 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器

    KubeProxy : 负责提供集群内部的服务发现和负载均衡

    Docker : 负责节点上容器的各种操作

    在这里插入图片描述

    下面,以部署一个nginx服务来说明kubernetes系统各个组件调用关系:

    1. 首先要明确,一旦kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中

    2. 一个nginx服务的安装请求会首先被发送到master节点的apiServer组件

    3. apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上

      在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServer

    4. apiServer调用controller-manager去调度Node节点安装nginx服务

    5. kubelet接收到指令后,会通知docker,然后由docker来启动一个nginx的pod

      pod是kubernetes的最小操作单元,容器必须跑在pod中至此,

    6. 一个nginx服务就运行了,如果需要访问nginx,就需要通过kube-proxy来对pod产生访问的代理

    这样,外界用户就可以访问集群中的nginx服务了


    kubernetes概念

    Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控

    Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行

    Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器

    Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等

    Service:pod对外服务的统一入口,下面可以维护着同一类的多个pod

    Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签

    NameSpace:命名空间,用来隔离pod的运行环境


    kubernetes集群环境搭建

    集群类型

    ● Kubernetes集群大致分为两类:一主多从和多主多从。
    ● 一主多从:一个Master节点和多台Node节点,搭建简单,但是有单机故障风险,适合用于测试环境。
    ● 多主多从:多台Master和多台Node节点,搭建麻烦,安全性高,适合用于生产环境。

    在这里插入图片描述

    为了测试方便,本次搭建的是一主多从类型的集群。


    安装方式

    ● kubernetes有多种部署方式,目前主流的方式有kubeadm、minikube、二进制包。

    ● ① minikube:一个用于快速搭建单节点的kubernetes工具。
    ● ② kubeadm:一个用于快速搭建kubernetes集群的工具。
    ● ③ 二进制包:从官网上下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有效。

    ● 我们需要安装kubernetes的集群环境,但是又不想过于麻烦,所以选择kubeadm方式。


    主机规划

    角色IP地址操作系统配置
    Master192.168.xxx,xxxCentOS7.8+,基础设施服务器2核CPU,2G内存,50G硬盘
    Node1192.168.xxx,xxxCentOS7.8+,基础设施服务器2核CPU,2G内存,50G硬盘
    Node2192.168.xxx,xxxCentOS7.8+,基础设施服务器2核CPU,2G内存,50G硬盘

    准备三台虚拟机或者云服务器。


    环境搭建

    前言

    • 本次环境搭建需要三台CentOS服务器(一主二从),然后在每台服务器中分别安装Docker(18.06.3)、kubeadm(1.18.0)、kubectl(1.18.0)和kubelet(1.18.0)。

    在这里插入图片描述

    没有特殊说明,就是三台机器都需要执行。


    环境初始化

    检查操作系统的版本

    检查操作系统的版本(要求操作系统的版本至少在7.5以上):

    centos:
    cat /etc/redhat-release
    ubuntu:
    cat /etc/issue
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述


    关闭防火墙和禁止防火墙开机启动

    关闭防火墙:

    systemctl stop firewalld
    
    • 1

    禁止防火墙开机启动:

    systemctl disable firewalld
    
    • 1

    在这里插入图片描述


    设置主机名
    • 设置主机名
    hostnamectl set-hostname <hostname>
    
    • 1
    • 因为k8s内部通信会通过主机名访问,因此给每台主机指定易懂的主机名可以方便我们后期使用

    就像服务发现是通过注册上去的服务名进行路由的一样,类似域名功能

    三台主机的主机名可以分别设置为如下示例:

    hostnamectl set-hostname k8s-master
    hostnamectl set-hostname k8s-node1
    hostnamectl set-hostname k8s-node2
    
    • 1
    • 2
    • 3

    主机名解析

    为了方便后面集群节点间的直接调用,需要配置一下主机名解析,企业中推荐使用内部的DNS服务器。

    echo   "192.168.112.130 k8s-master  192.168.112.129 k8s-node1 192.168.112.134 k8s-node2 " >> /etc/hosts
    
    • 1

    时间同步
    • kubernetes要求集群中的节点时间必须精确一致,所以在每个节点上添加时间同步:
    yum install ntpdate -y
    
    • 1
    ntpdate time.windows.com
    
    • 1

    关闭selinux
    • 查看selinux是否开启:
    getenforce
    
    • 1
    • 永久关闭selinux,需要重启:
    sed -i 's/enforcing/disabled/' /etc/selinux/config
    
    • 1
    • 临时关闭selinux,重启之后,无效:
    setenforce 0
    
    • 1

    关闭swap分区
    • 永久关闭swap分区,需要重启:
    sed -ri 's/.*swap.*/#&/' /etc/fstab
    
    • 1
    • 临时关闭swap分区,重启之后,无效::
    swapoff -a
    
    • 1

    将桥接的IPv4流量传递到iptables的链
    • 在每个节点上将桥接的IPv4流量传递到iptables的链:
    cat > /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward = 1
    vm.swappiness = 0
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    # 加载br_netfilter模块
    modprobe br_netfilter
    
    • 1
    • 2
    # 查看是否加载
    lsmod | grep br_netfilter
    
    • 1
    • 2
    # 生效
    sysctl --system
    
    • 1
    • 2

    开启ipvs

    ● 在kubernetes中service有两种代理模型,一种是基于iptables,另一种是基于ipvs的。ipvs的性能要高于iptables的,但是如果要使用它,需要手动载入ipvs模块。

    ● 在每个节点安装ipset和ipvsadm:

    yum -y install ipset ipvsadm
    
    • 1

    在所有节点执行如下脚本:

    cat > /etc/sysconfig/modules/ipvs.modules <<EOF
    #!/bin/bash
    modprobe -- ip_vs
    modprobe -- ip_vs_rr
    modprobe -- ip_vs_wrr
    modprobe -- ip_vs_sh
    modprobe -- nf_conntrack_ipv4
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    授权、运行、检查是否加载:

    chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
    
    • 1

    检查是否加载:

    lsmod | grep -e ipvs -e nf_conntrack_ipv4
    
    • 1

    重启三台机器

    重启三台Linux机器:

    reboot
    
    • 1

    每个节点安装Docker、kubeadm、kubelet和kubectl

    安装Docker
    • 切换镜像源
    wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O/etc/yum.repos.d/docker-ce.repo
    
    • 1
    • 查看镜像源中支持的docker版本
     yum list docker-ce --showduplicates
    
    • 1
    • 安装特定版本docker-ce

    必须指定–setopt=obsoletes=0,否则yum会自动安装更高版本

     yum install --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7 -y
    
    • 1

    添加配置文件

    Docker在默认情况下使用的Cgroup Driver为cgroupfs,而kubernetes推荐使用systemd来代替cgroupfs

    mkdir /etc/docker
    
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "exec-opts": ["native.cgroupdriver=systemd"],	
      "registry-mirrors": ["https://du3ia00u.mirror.aliyuncs.com"],	
      "live-restore": true,
      "log-driver":"json-file",
      "log-opts": {"max-size":"500m", "max-file":"3"},
      "storage-driver": "overlay2"
    }
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    启动docker
    # 启动docker
    systemctl start docker
    # 开机启动
    systemctl enable docker 
    
    • 1
    • 2
    • 3
    • 4

    安装Kubernetes组件

    由于Kubernetes的镜像源在国外,速度比较慢,这里切换成国内的镜像源

    编辑/etc/yum.repos.d/kubernetes.repo,添加下面的配置

    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=0
    repo_gpgcheck=0
    gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    安装kubeadm,kubelet和kubectl

    yum install kubeadm-1.17.4-0 kubelet-1.17.4-0 kubectl-1.17.4-0 -y
    
    • 1

    配置kubelet的cgroup

    # 编辑/etc/sysconfig/kubelet,添加下面的配置
    KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"
    KUBE_PROXY_MODE="ipvs"
    
    • 1
    • 2
    • 3

    设置kubelet开机自启

    systemctl enable kubelet
    
    • 1

    初始化集群

    在master上操作:

    # 由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址
    # apiserver-advertise-address 需要写自己的master主机的ip
    kubeadm init \
    --apiserver-advertise-address=192.168.112.130 \
    --image-repository registry.aliyuncs.com/google_containers \
    --kubernetes-version=v1.17.7 \
    --pod-network-cidr=10.244.0.0/16 \
    --service-cidr=10.96.0.0/12 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果出现下面这个错误:
    在这里插入图片描述
    输入下面这个命令后,重新执行一次即可:

    echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables
    
    • 1

    注意:如果用的是轻量级云服务器,轻量级服务器本身是采用NAT方式将公网IP映射到网卡所以会出现连接超时:

    Initial timeout of 40s passed
    
    • 1

    所以建议在init的时候修改etcd.yaml文件里面的地址为127.0.0.1

    切记一定要在执行的init的过程中去改,不要等到失败了再改,大概有两分钟的窗口期,如果错过了可以执行 kubeadm reset 来取消然后再init一次,因为对应的etcd.yaml文件是在init过程中生成的临时文件,完成init操作后就会删除。

    可以新建一个窗口去改,也可以用sftp直接编辑,路径在下面

    /etc/kubernetes/manifests/etcd.yaml
    
    • 1

    在这里插入图片描述
    把图片上圈起来的地方改成这样,我图片上是修改后的

      - --listen-client-urls=https://127.0.0.1:2379
        - --listen-metrics-urls=http://127.0.0.1:2381
        - --listen-peer-urls=https://127.0.0.1:2380
    
    • 1
    • 2
    • 3

    解决阿里云ECS下kubeadm部署k8s无法指定公网IP
    k8s执行init时出现 Initial timeout of 40s passed


    如果操作过程中需要重新安装一次,只需要执行kubeadm reset清除之前安装的资源即可。


    正确执行过程如下图所示:
    在这里插入图片描述

    #使用 kubectl 工具
     mkdir -p $HOME/.kube
     sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
     sudo chown $(id -u):$(id -g) $HOME/.kube/config
    
    • 1
    • 2
    • 3
    • 4

    然后我们需要将node 节点加入集群中,在 node 服务器 上执行红框的命令加入到master

    在这里插入图片描述
    注意: 默认的token有效期为2小时,当过期之后,该token就不能用了,这时可以使用如下的命令创建token:

    kubeadm token create --print-join-command
    
    • 1
    # 生成一个永不过期的token
    kubeadm token create --ttl 0 --print-join-command
    
    • 1
    • 2

    在主节点上查询当前集群中有哪些节点:

    kubectl get nodes
    
    • 1

    在这里插入图片描述
    但是我们这个时候查看集群状态都是为NotReady,这是因为还没有配置网络插件


    网络插件安装

    kubernetes支持多种网络插件,比如flannel、calico、canal等等,任选一种即可,本次选择flannel。

    wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    
    • 1

    修改 quay.io 为 quay-mirror.qiniu.com 因为国内 quay.io 不好访问到

    如果下载不到的报错 连接失败什么的
    在这里插入图片描述
    可以使用本人提供的,当然,你也可以安装calico,推荐安装calico。

    使用配置文件启动fannel

    kubectl apply -f kube-flannel.yml
    
    • 1

    在这里插入图片描述
    查看部署CNI网络插件进度:

    kubectl get pods -n kube-system
    
    • 1

    稍等片刻,再次查看集群状态:

    kubectl get nodes
    
    • 1

    在这里插入图片描述
    查看集群健康状况:

    kubectl get cs
    
    • 1

    在这里插入图片描述

    kubectl cluster-info
    
    • 1

    在这里插入图片描述


    服务部署

    前言

    ● 在Kubernetes集群中部署一个Nginx程序,测试下集群是否正常工作。

    步骤

    部署Nginx:

    kubectl create deployment nginx --image=nginx:1.14-alpine
    
    • 1

    暴露端口:

    kubectl expose deployment nginx --port=80 --type=NodePort
    
    • 1

    查看服务状态:

    kubectl get pods,svc
    
    • 1

    在这里插入图片描述
    在防火墙关闭或者31661端口开放的情况下,浏览器直接访问该端口应该就可以看到nginx首页
    在这里插入图片描述
    任意节点均可通过ip加端口的方式访问,即视为测试成功,否则说明存在问题,可优先考虑是否为网络插件问题。


    关于网络插件的问题

    如果安装的是calico网络插件,并且安装后发现对应的calico/node is not ready,可以先查看对应node的日志信息,如果是关于:

    #查看对应node的日志信息
    kubectl describe pods calico-node-4n8mg -n kube-system
    #日志信息输出如下:
    BIRD is not ready: BGP not established with 172.19.77.23
    
    • 1
    • 2
    • 3
    • 4

    那么解决方法如下:

    官方提供的yaml文件中,ip识别策略(IPDETECTMETHOD)没有配置,即默认为first-found,这会导致一个网络异常的ip作为nodeIP被注册,从而影响node-to-node mesh。

    我们可以修改成can-reach或者interface的策略,尝试连接某一个Ready的node的IP,以此选择出正确的IP。

    • 1.修改calico.yaml配置文件,添加属性配置:
      在这里插入图片描述
    • 2.在master节点重新部署calico,使修改生效:
    kubectl apply -f calico.yaml    
    
    • 1
    • 3.再看下pod状态:
      在这里插入图片描述

    其他安装问题解决办法

    • 查看健康状态,发现:
    [root@master1 ~]#kubectl get cs
    Warning: v1 ComponentStatus is deprecated in v1.19+
    NAME                 STATUS      MESSAGE                                                                                       ERROR
    controller-manager   Unhealthy   Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused   
    scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused   
    etcd-0               Healthy     {"health":"true"}     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    解决办法:

    Get “http://127.0.0.1:10252/healthz”: dial tcp 127.0.0.1:10252: connect: connection refused


    K8s网络插件报错:network: stat /var/lib/calico/nodename: no such file or directory: check that the calico/n


    如果先安装了calioc网络插件后,发现报错,又卸载calioc网络插件,转而安装flannel网络插件,可能会出现coredns报错问题,这极大概率是因为calioc网络插件没有卸载完全。

    • 可以选择通过kubeadm reset重置master节点,然后将calioc相关资源彻底删除,再进行kubeadm init重新初始化
    • 还有从节点也需要将相关calioc资源删除,然后执行kubeadm reset重置,最后重新加入主节点

    coredns无法启动-certificate signed by unknown authority

    记一次使用Flannel插件排错历程 _


    kubernetes中kubectl命令自动补全

    yum install -y bash-completion
    
    • 1
    source /usr/share/bash-completion/bash_completion
    
    • 1
    source <(kubectl completion bash)
    
    • 1
    echo “source <(kubectl completion bash)” >> ~/.bashrc
    
    • 1
     vim /root/.bashrc 
    
    • 1
    source /usr/share/bash-completion/bash_completion
    
    • 1
    source <(kubectl completion bash)
    
    • 1

    部署单k8s节点

    在云服务器资源有限的情况下,我们也可以将master节点也变为可以调度运行pod的Node节点,方法如下:

    k8s集群中让master也能运行pod,并且修改角色标签
    K8s Master当作Node使用的方法

  • 相关阅读:
    【面试题】js实现将excel表格copy到页面
    Java程序(jar包)注册为Windows系统服务
    python之字符、字符串切片、三引号使用
    HJ59 找出字符串中第一个只出现一次的字符
    js基础-数据类型检测
    PMBOK第7版——「8大绩效域」解析
    服务器vs普通电脑
    Java代码质量评估工具
    前端开发:创建可拖动的固定位置 `<div>` 和自动隐藏悬浮按钮
    Git版本控制管理——合并
  • 原文地址:https://blog.csdn.net/m0_53157173/article/details/123263710