Kubernetes 概述和架构

Kubernetes 简介

Kubernetes,首字母 K,尾字母 s,中间 8 个字母,简称 K8s。

Kubernetes 功能

  • 目前只需要知道 Kubernetes 有以下 9 个功能,关于这 9 个功能,后面详细介绍。(我也不知道这些是啥玩意,先记住名词再说)
  1. 自动装箱
    • 基于容器对应用运行环境的资源配置要求自动部署应用容器
  2. 自我修复
    • 当容器失败时,会对容器进行重启
    • 当所部署的 Node 节点有问题时,会对容器进行重新部署和重新调度
    • 当容器未通过监控检查时,会关闭此容器直到容器正常运行时,才会对外提供服务
  3. 水平扩展
    • 通过简单的命令、用户 UI 界面或基于 CPU 等资源使用情况,对应用容器进行规模扩大或规模剪裁
    • 当我们有大量的请求来临时,我们可以增加副本数量,从而达到水平扩展的效果
  4. 服务发现
    • 用户不需使用额外的服务发现机制,就能够基于 Kubernetes 自身能力实现服务发现和负载均衡
  5. 滚动更新
    • 可以根据应用的变化,对应用容器运行的应用,进行一次性或批量式更新
  6. 版本回退
    • 可以根据应用部署情况,对应用容器运行的应用,进行历史版本即时回退
  7. 密钥和配置管理
    • 在不需要重新构建镜像的情况下,可以部署和更新密钥和应用配置,类似热部署。
  8. 存储编排
    • 自动实现存储系统挂载及应用,特别对有状态应用实现数据持久化非常重要
    • 存储系统可以来自于本地目录、网络存储 (NFS、Gluster、Ceph 等)、公共云存储服务
  9. 批处理
    • 提供一次性任务,定时任务;满足批量数据处理和分析的场景

Kubernetes 架构组件

Kubernetes 组件

  • Master:主控节点
    • API Server:集群统一入口,以 restful 风格进行操作,同时交给 etcd 存储
      • 提供认证、授权、访问控制、API 注册和发现等机制
    • scheduler:节点的调度,选择 node 节点应用部署
    • controller-manager:处理集群中常规后台任务,一个资源对应一个控制器
    • etcd:存储系统,用于保存集群中的相关数据
  • Worker node:工作节点
    • Kubelet:master 派到 node 节点代表,管理本机容器
      • 一个集群中每个节点上运行的代理,它保证容器都运行在 Pod 中
      • 负责维护容器的生命周期,同时也负责 Volume(CSI) 和 网络 (CNI) 的管理
    • kube-proxy:提供网络代理,负载均衡等操作
  • 容器运行环境【Container Runtime
    • 容器运行环境是负责运行容器的软件
    • Kubernetes 支持多个容器运行环境:Docker、containerd、cri-o、rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口) 的软件。
  • fluentd:是一个守护进程,它有助于提升集群层面日志

Kubernetes 核心概念

  1. Pod
    • Pod 是 K8s 中最小的单元
    • 一组容器的集合
    • 共享网络【一个 Pod 中的所有容器共享同一网络】
    • 生命周期是短暂的(服务器重启后,就找不到了)
  2. Volume
    • 声明在 Pod 容器中可访问的文件目录
    • 可以被挂载到 Pod 中一个或多个容器指定路径下
    • 支持多种后端存储抽象【本地存储、分布式存储、云存储】
  3. Controller
    • 确保预期的 pod 副本数量【ReplicaSet】
    • 无状态应用部署【Deployment】
      • 无状态就是指,不需要依赖于网络或者 ip
    • 有状态应用部署【StatefulSet】
      • 有状态需要特定的条件
    • 确保所有的 node 运行同一个 pod 【DaemonSet】
    • 一次性任务和定时任务【Job 和 CronJob】
  4. Deployment
    • 定义一组 Pod 副本数目,版本等
    • 通过控制器【Controller】维持 Pod 数目【自动回复失败的 Pod】
    • 通过控制器以指定的策略控制版本【滚动升级、回滚等】
  5. Service
    • 定义一组 pod 的访问规则
    • Pod 的负载均衡,提供一个或多个 Pod 的稳定访问地址
    • 支持多种方式【ClusterIP、NodePort、LoadBalancer】
  6. Label
    • label:标签,用于对象资源查询,筛选
  7. Namespace
    • 命名空间,逻辑隔离
    • 一个集群内部的逻辑隔离机制【鉴权、资源】
    • 每个资源都属于一个 namespace
    • 同一个 namespace 所有资源不能重复
    • 不同 namespace 可以资源名重复
  8. API
    • 我们通过 Kubernetes 的 API 来操作整个集群
    • 同时我们可以通过 kubectl 、ui、curl 最终发送 http + json/yaml 方式的请求给 API Server,然后控制整个 K8S 集群,K8S 中所有的资源对象都可以采用 yaml 或 json 格式的文件定义或描述

Kubernetes 工作原理

基于客户端工具 kubeadm

kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具。

这个工具能通过两条指令完成一个 kubernetes 集群的部署:

创建一个 Master 节点

kubeadm init

将node 节点加入到集群

kubeadm join <Master 节点的 IP 和端口 >

安装步骤

  • 使用 kubeadm 方式搭建 Kubernetes 集群主要分为以下几步:
    1. 【环境准备】准备三台虚拟机,并安装操作系统 CentOS 7.x
    2. 【系统初始化】对三个刚安装好的操作系统进行初始化操作
    3. 【安装工具】在三个节点安装 docker kubelet kubeadm kubectl
    4. 【集群部署-master】在 master 节点执行kubeadm init命令初始化
    5. 【集群部署-node】在 node 节点上执行 kubeadm join命令,把 node 节点添加到当前集群
    6. 【安装网络插件】配置 CNI 网络插件,用于节点之间的连通
    7. 【测试集群】通过拉取一个 nginx 进行测试,能否进行外网测试

安装要求

在开始之前,部署 Kubernetes 集群机器需要满足以下几个条件:

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多
    • 【注意】【注意】【注意】【master 需要两核】
  • 可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点
  • 禁止 swap 分区

准备环境

角色 IP 配置 操作
k8smaster1 192.168.61.151 2C 2G init docker kubelet kubeadm kubectl kubeadm init cni
k8snode1 192.168.61.152 2C 2G init docker kubelet kubeadm kubectl kubeadm join
k8snode2 192.168.61.153 2C 2G init docker kubelet kubeadm kubectl kubeadm join
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 更改网络配置
sed -i 's/BOOTPROTO="dhcp"/BOOTPROTO="static"/g' /etc/sysconfig/network-scripts/ifcfg-ens33
cat >> /etc/sysconfig/network-scripts/ifcfg-ens33 << EOF

IPADDR=192.168.61.151 # ipaddr
NETMASK=255.255.255.0 # netmask
GATEWAY=192.168.61.2 # gateway
DNS1=8.8.8.8 # dns
DNS2=114.114.114.114
EOF

# 重启网络服务,使配置生效
systemctl restart network

# 查看网络ip
[root@localhost ~]# ip addr

系统初始化

  • 【在每台机器上】执行下面的命令:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    # 关闭防火墙
    systemctl stop firewalld
    # 禁用 firewalld 服务
    systemctl disable firewalld

    # 关闭 selinux
    # 临时关闭【立即生效】告警,不启用,Permissive,查看使用 getenforce 命令
    setenforce 0
    # 永久关闭【重启生效】
    sed -i 's/SELINUX=enforcing/\SELINUX=disabled/' /etc/selinux/config

    # 关闭 swap
    # 临时关闭【立即生效】查看使用 free 命令
    swapoff -a
    # 永久关闭【重启生效】
    sed -ri 's/.*swap.*/#&/' /etc/fstab

    # 在主机名静态查询表中添加 3 台主机
    cat >> /etc/hosts << EOF
    192.168.61.151 k8smaster
    192.168.61.152 k8snode1
    192.168.61.153 k8snode2
    EOF

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

    # 时间同步
    yum install ntpdate -y
    ntpdate time.windows.com

    # 根据规划设置主机名【k8smaster1 节点上操作】
    hostnamectl set-hostname ks8master1
    # 根据规划设置主机名【k8snode1 节点上操作】
    hostnamectl set-hostname k8snode1
    # 根据规划设置主机名【k8snode2 节点操作】
    hostnamectl set-hostname k8snode2

安装组件

【所有节点】需要安装以下组件 ,Kubernetes 默认 CRI(容器运行时)为 Docker,因此先安装 Docker。

  • Docker
  • kubeadm
  • kubelet
  • kubectl

安装 Docker

  • 卸载旧版本:

    1
    2
    3
    4
    5
    6
    7
    8
    sudo yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
  • 配置一下 Docker 的 yum 源【阿里云】

    1
    2
    3
    4
    5
    yum -y install yum-utils gcc gcc-c++

    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    yum makecache fast
    1
    2
    3
    4
    5
    6
    7
    8
    cat >/etc/yum.repos.d/docker.repo<<EOF
    [docker-ce-edge]
    name=Docker CE Edge - \$basearch
    baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
    enabled=1
    gpgcheck=1
    gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
    EOF
  • 然后 yum 方式安装 docker

    1
    2
    3
    4
    5
    yum list docker-ce --showduplicates | sort -r

    yum -y install docker-ce

    yum -y install docker-ce-3:20.10.8-3.el7.x86_64 docker-ce-cli-1:20.10.8-3.el7.x86_64 containerd.io
  • 查看 docker 版本

    1
    docker --version
  • 配置 docker 的镜像源【阿里云】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    cat > /etc/docker/daemon.json << EOF
    {
    "registry-mirrors": [
    "https://b9pmyelo.mirror.aliyuncs.com",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
    ]
    }
    EOF
  • 启动 docker

    1
    2
    3
    systemctl enable docker
    systemctl start docker
    systemctl status docker

安装 kubeadm,kubelet 和 kubectl

  • 配置 k8s 的 yum 源【阿里云】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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
  • 安装 kubelet、kubeadm、kubectl,同时指定版本

    1
    2
    3
    yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0

    yum install -y kubelet-1.21.10 kubeadm-1.21.10 kubectl-1.21.10
  • 为了实现 Docker 使用的 cgroup drvier 和 kubelet 使用的 cgroup drver 一致,建议修改 /etc/sysconfig/kubelet 文件的内容:

    1
    2
    3
    4
    5
    vim /etc/sysconfig/kubelet

    # 修改
    KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
    KUBE_PROXY_MODE="ipvs"
  • 设置开机自启【这里暂时先不启动 kubelet】

    1
    systemctl enable kubelet

下载 Kubernetes 安装所需镜像

  • 查看 Kubernetes 安装所需镜像:

    1
    kubeadm config images list
  • 三台机器下载镜像:

    1
    2
    3
    4
    5
    6
    7
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.21.10
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.21.10
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.21.10
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.21.10
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0
  • 给 coredns 镜像重新打 tag :

    1
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns/coredns:v1.8.0

集群部署【master 节点】

  • 在 192.168.61.151上执行【集群初始化命令】,也就是k8smaster1节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    kubeadm init --apiserver-advertise-address=192.168.61.151 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12  --pod-network-cidr=10.244.0.0/16

    # 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址
    kubeadm init \
    --apiserver-advertise-address=192.168.61.151 \
    --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \
    --kubernetes-version=v1.21.10 \
    --service-cidr=10.96.0.0/16 \
    --pod-network-cidr=10.244.0.0/16
  • 由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址,【执行上述命令会比较慢,因为后台其实已经在拉取镜像了】,我们 docker images 命令即可查看已经拉取的镜像。

  • 部署成功后,【系统提示】运行以下命令使用 kubectl

    1
    2
    3
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • 执行完成后,我们使用下面命令,查看我们正在运行的节点

    1
    kubectl get nodes

集群部署【node 节点】

  • 下面我们需要到 k8snode1k8snode2服务器,执行下面的代码向集群添加新节点

  • 执行在 kubeadm init 输出的 kubeadm join

    • 命令:注意,以下的命令是在 k8smaster1 初始化完成后给出的,每个人的都不一样!!!需要复制自己生成的
    1
    2
    kubeadm join 192.168.61.151:6443 --token clyjfy.jyjnhy9q80f6mtqo \
    --discovery-token-ca-cert-hash sha256:3b3bd6cb57c38622478e629c0a370438c67507b4853db38c13a2083070ebbe2a
  • 默认 token 有效期为 24 小时,当过期之后,该 token 就不可用了。这时就需要重新创建 token,操作如下:

    1
    kubeadm token create --print-join-command
  • 当我们把两个节点都加入进来后,我们就可以去 k8smaster1 节点下 执行下面命令查看情况

    1
    2
    3
    4
    5
    6
    [root@ks8master1 ~]# kubectl get nodes
    NAME STATUS ROLES AGE VERSION
    k8snode1 NotReady <none> 5m56s v1.18.0
    k8snode2 NotReady <none> 5m51s v1.18.0
    ks8master1 NotReady master 6m50s v1.18.0

  • 报error

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@ks8master1 ~]# kubectl get nodes
    error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable

    cat > /etc/profile <<EOF

    export KUBECONFIG=/etc/kubernetes/kubelet.conf
    EOF

    source /etc/profile

部署 CNI 网络插件

  • 上面的状态还是 NotReady,下面我们需要网络插件,来进行联网访问

    1
    2
    3
    4
    5
    6
    7
    8
    # 下载网络插件配置
    wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    # 添加
    kubectl apply -f kube-flannel.yml
    # 等一会!
    # ......
    # 查看状态 【kube-system 是 k8s 中的最小单元】
    kubectl get pods -n kube-system
  • 方式二

    1
    2
    export KUBECONFIG=/etc/kubernetes/admin.conf
    kubectl apply -f https://projectcalico.docs.tigera.io/v3.19/manifests/calico.yaml
  • 查看部署 CNI 网络插件进度:

    1
    2
    kubectl get pods -n kube-system
    watch kubectl get pods -n kube-system
  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [root@ks8master1 ~]# kubectl create deployment nginx --image=nginx
    [root@ks8master1 ~]# kubectl expose deployment nginx --port=80 --type=NodePort

    [root@ks8master1 ~]# kubectl get pods,svc
    NAME READY STATUS RESTARTS AGE
    pod/nginx-6799fc88d8-n97l5 1/1 Running 0 92s

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12m
    service/nginx NodePort 10.96.198.11 <none> 80:31249/TCP 20s

    # 访问http://192.168.61.151:31249/

卸载k8s

1
2
3
4
5
6
7
8
9
10
11
12
yum -y remove kubelet kubeadm kubectl
sudo kubeadm reset -f
sudo rm -rvf $HOME/.kube
sudo rm -rvf ~/.kube/
sudo rm -rvf /etc/kubernetes/
sudo rm -rvf /etc/systemd/system/kubelet.service.d
sudo rm -rvf /etc/systemd/system/kubelet.service
sudo rm -rvf /usr/bin/kube*
sudo rm -rvf /etc/cni
sudo rm -rvf /opt/cni
sudo rm -rvf /var/lib/etcd
sudo rm -rvf /var/etcd