您的位置:首页 > 编程语言 > ASP

ASP.NET Core on K8S深入学习(1)K8S基础知识与集群搭建

2019-07-31 08:56 1446 查看

在上一个小系列文章《ASP.NET Core on K8S学习初探》中,通过在Windows上通过Docker for Windows搭建了一个单节点的K8S环境,并初步尝试将ASP.NET Core WebAPI项目部署到了K8S,把玩了一下快速部署和实例伸缩。这个系列开始,会继续学习K8S以及在Linux上搭建集群来深入把玩。本篇会回顾一下K8S的基本概念以及架构组成,然后会通过Kubeadm快速地搭建一个K8S集群供后续学习把玩之用。

一、K8S基础概念回顾

  1.Cluster 集群

  计算、存储和网络资源的集合,Kubernetes利用这些资源运行各种基于容器的应用。

  2.Master

  Master是Cluster的大脑,负责调度(决定将应用放在哪里运行),一般为了实现高可用,会有多个Master。

  3.Node

  负责运行具体的容器,Node由Master管理,它会监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期。   eg. 在交互实验中,这个Cluster中只有一个主机,它既是Master也是Node。

  4.Pod

  Kubernetes的最小工作单元,每个Pod包含一个或多个容器。Pod中的容器会被作为一个整体被Master调度到一个Node上运行。   (1)为何引入Pod?   一是方便管理:   有些容器天生联系紧密,需要在一起工作。Pod提供了比容器更高层次的抽象,将它们封装到一个部署单元中。K8S以Pod为最小单位进行调度、扩展、共享资源、管理生命周期。   eg.正例:File Puller & Web Server => 需要部署在一起工作     反例:Tomecat & MySQL => 不需要部署在一起工作   二是可以共享资源和通信:   Pod中所有容器使用同一个网络namespace,即相同的IP和端口空间,可以直接用localhost通信,而且还可以共享存储(本质是通过将Volume挂载到Pod中的每个容器)   (2)如何使用Pod?   运行单个容器:one-container-per-Pod,K8S中最常见的模型,即使这种情形下,K8S管理的也是Pod而不是单个容器。   运行多个容器:将联系非常紧密的多个容器部署到一个Pod中,可以直接共享资源。

  5.Controller

  K8S不会直接创建Pod,是通过Controller来管理Pod的。为了满足不同业务场景,K8S提供了多种Controller:   (1)Deployment   最常见的Controller,可以管理Pod的多个副本,并确保Pod按照期望的状态运行。   (2)ReplicaSet   实现了Pod的多副本管理,使用Deployment时会自动创建ReplicaSet。换句话说,Deployment是通过ReplicaSet来管理Pod的多个副本的,通常不需要直接使用ReplicaSet。   (3)DaemonSet   用于每个Node最多只运行一个Pod副本的场景,DaemonSet通常用于运行daemon(守护进程、后台程序)。   (4)StatefuleSet   用于保证Pod的每个副本在整个生命周期中名称是不变的,而其他的Controller不提供这个功能。(非StatefuleSet下,当某个Pod发生故障需要删除并重启时,Pod的名称是会变化的)   (5)Job   用于运行结束就删除的应用,其他Controller下Pod通常是长期持续运行的。

  6.Service

  K8S定义了外界访问一个或一组特定Pod的方式,就是Service。每个Service有自己的IP和端口,并且为Pod提供了负载均衡。   如果说K8S运行Pod的任务是交给了Controller去做,那么访问Pod的任务则是交给了Service去做。

  7.Namespace

  Namespace将一个物理的Cluster从逻辑上划分为多个虚拟Cluster,每个虚拟Cluster就是一个Namespace,不同Namespace中的资源是完全隔离的。 K8S中会自动创建两个Namespace:   (1)default:创建资源时如果不指定Namespace就会放到这里   (2)kube-system: K8S自己创建的系统资源都会放到这个Namespace中

二、K8S集群架构解析

  下面展示了一个最小化的K8S集群,一个master节点和两个node节点: *.master上也有kubelet和kube-proxy是因为master同时也是一个Node

  1.Master节点

  K8S集群的“大脑”,运行以下多个Daemon服务:
  • API Server(kube-apiserver)
  • 提供Restful API => Kubernetes API,供其他组件调用以管理Cluster的各种资源
  • Scheduler(kube-scheduler)
    • 负责决定将Pod放在哪个Node上Run起来
    • 调度时会根据指定算法选择Pod(eg.集群拓扑结构、各节点负载情况、HA等等)
  • Controller Manager(kube-controller-manager)
    • 负责管理集群中的各种资源,保证资源处于预期的状态
    • 由多种Controller组成
    • Replication Controller:管理Deployment、StatefuleSet、DaemonSet的生命周期
    • Endpoints Controller
    • Namespace Controller:管理Namespace资源
    • Serviceaccounts Controller
  • Etcd
    • 负责保存K8S集群中的配置信息和各种资源的状态信息
    • 当数据发生变化时,会及时通知K8S相关组件
  • Pod网络
    • 保证Pod能够相互通信,Flannel是一个可选方案

      2.Node节点

      运行Pod的主战场,主要运行以下K8S组件:
    • kubelet
    • Node的Agent,负责创建运行容器与向Master报告运行状态
  • kube-proxy
    • 每个Node都会运行proxy,它负责请求转发到后端的容器
  • Pod网络
    • 保证Pod能够相互通信,Flannel是一个可选方案

    三、K8S集群环境搭建

    3.1 K8S环境搭建的几种方式

      搭建K8S环境有几种常见的方式如下:

      (1)Minikube

      Minikube是一个工具,可以在本地快速运行一个单点的K8S,供初步尝试K8S或日常开发的用户使用,不能用于生产环境。

      (2)Kubeadm

      Kubeadm是K8S官方社区推出的一套用于简化快速部署K8S集群的工具,Kubeadm的设计目的是为新用户开始尝试K8S提供一种简单的方法。

      (3)二进制包

      除了以上两种方式外,我们还可以通过从官方下载二进制包,手动部署每个组件组成K8S集群,这也是目前企业生产环境中广为使用的方式,但对K8S管理人员的要求较高。

      本次学习实践我们主要借助Kubeadm工具搭建K8S集群,以便后续实践部署ASP.NET Core应用集群。

    3.2 搭建前的准备工作

      (1)准备三台Linux服务器

      这里我选择通过VMware Workstaion来搭建3个虚拟机,每个配置2CPU和2G内存,如下图:

      

      (2)配置主机名与静态IP地址如下表所示:

    角色 主机名 IP地址
    Master k8s-master 192.168.2.100
    Node k8s-node1 192.168.2.101
    Node k8s-node2 192.168.2.102

      然后,更改hosts文件添加主机名与IP映射关系

    # vim /etc/hosts
    192.168.2.100 k8s-master 192.168.2.101 k8s-node1 192.168.2.102 k8s-node2

      (3)关闭防火墙

    systemctl stop firewalld
    systemctl disable firewalld

      (4)关闭selinux

    sed -i 's/enforcing/disabled/' /etc/selinux/config
    setenforce 0

      (5)关闭swap => K8S中不支持swap分区

    # vim /etc/fstab
    #/dev/mapper/centos-swap swap                    swap    defaults        0 0

      *.编辑etc/fstab将swap那一行注释掉或者删除掉

      (6)将桥接的IPv4流量传递到iptables的链

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

    3.3 安装Docker&Kubeadm&Kubelet

      以下步骤请在所有节点中操作:

      (1)安装Docker

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

      *.这里安装的是18.06社区版,如果你之前有安装低版本的Docker,为了配合本次实验的K8S版本(1.13.x),建议先卸载掉,卸载过程可以参考这篇文章《CentOS7 Docker升级》。

      (2)添加阿里云Yum软件源

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

      (3)安装Kubeadm&Kubelet&Kubectl

      注意:本次部署K8S版本号为1.13.3

    # yum install -y kubelet-1.13.3 kubeadm-1.13.3 kubectl-1.13.3
    # systemctl enable kubelet

      遇到的一些坑如下:

      ① 碰到需要kubernetes-cni的问题:

    #####错误:软件包:kubelet-1.13.3-0.x86_64 (kubernetes)
    需要:kubernetes-cni = 0.6.0
    可用: kubernetes-cni-0.3.0.1-0.07a8a2.x86_64 (kubernetes)
    kubernetes-cni = 0.3.0.1-0.07a8a2
    可用: kubernetes-cni-0.5.1-0.x86_64 (kubernetes)
    kubernetes-cni = 0.5.1-0
    可用: kubernetes-cni-0.5.1-1.x86_64 (kubernetes)
    kubernetes-cni = 0.5.1-1
    可用: kubernetes-cni-0.6.0-0.x86_64 (kubernetes)
    kubernetes-cni = 0.6.0-0
    正在安装: kubernetes-cni-0.7.5-0.x86_64 (kubernetes)
    kubernetes-cni = 0.7.5-0
    您可以尝试添加 --skip-broken 选项来解决该问题
    您可以尝试执行:rpm -Va --nofiles --nodigest

      解决:手动安装kubernetes-cni对应的版本

    yum install -y kubelet-1.13.3 kubeadm-1.13.3 kubectl-1.13.3 kubernetes-cni-0.6.0

      ② 使用yum安装程序时,提示xxx.rpm公钥尚未安装

    从 https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg 检索密钥
    导入 GPG key 0xA7317B0F:
    用户ID     : "Google Cloud Packages Automatic Signing Key <gc-team@google.com>"
    指纹       : d0bc 747f d8ca f711 7500 d6fa 3746 c208 a731 7b0f
    来自       : https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
    
    e3438a5f740b3a907758799c3be2512a4b5c64dbe30352b2428788775c6b359e-kubectl-1.13.3-0.x86_64.rpm 的公钥尚未安装
    
    失败的软件包是:kubectl-1.13.3-0.x86_64
    GPG  密钥配置为:https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg

      解决:使用 yum install xxx.rpm --nogpgcheck 命令格式跳过公钥检查,比如跳过kubectl和kubeadm的公钥检查如下命令:

    yum install kubectl-1.13.3-0.x86_64 --nogpgcheck
    yum install kubeadm-1.13.3-0.x86_64 --nogpgcheck

    3.4 部署Kubernetes Master

      以下步骤请在k8s-master节点上操作:

    kubeadm init \
    --apiserver-advertise-address=192.168.2.100 \
    --image-repository registry.aliyuncs.com/google_containers \
    --kubernetes-version v1.13.3 \
    --service-cidr=10.1.0.0/16 \
    --pod-network-cidr=10.244.0.0/16

    PS:由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址(registry.aliyuncs.com/google_containers)。官方建议服务器至少2CPU+2G内存,当然内存1G也是可以的,但是会出Warning,建议还是老老实实升2G内存把。

      

      接下来,为了顺利使用kubectl命令,执行以下命令:

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

      这时你可以使用kubectl了,当你执行完kubectl get nodes之后,你会看到如下状态:

      

    3.5 部署Pod网络插件(CNI)

      同样,继续在k8s-master上操作:

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

      然后通过以下命令验证:全部为Running则OK,其中一个不为Running,比如:Pending、ImagePullBackOff都表明Pod没有就绪

      

      如果其中有的Pod没有Running,可以通过以下命令查看具体错误原因,比如这里我想查看kube-flannel-ds-amd64-8bmbm这个pod的错误信息:

    kubectl describe pod kube-flannel-ds-amd64-8bmbm -n kube-system

      在此过程中可能会遇到无法从qury.io拉取flannel镜像从而导致无法正常Running,解决办法如下:

      使用国内云服务商提供的镜像源然后通过修改tag的方式曲线救国

    docker pull quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64
    docker tag quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.10.0-amd64
    docker rmi quay-mirror.qiniu.com/coreos/flannell:v0.11.0-amd64

      这时,我们再看看master节点的状态就会从NotReady变为Ready:

      

      那么,恭喜你,Master节点部署结束了。如果你只想要一个单节点的K8S,那么这里就完成了部署了。

    3.6 加入Kubernetes Node

      在两台Node节点上执行join命令:

    kubeadm join 192.168.2.100:6443 --token ekqxk2.iiu5wx5bbnbdtxsw --discovery-token-ca-cert-hash \
    sha256:c50bb83d04f64f4a714b745f04682b27768c1298f331e697419451f3550f2d05

      这里需要注意的就是,带上在Master节点Init成功后输出的Token。如果找不到了,没关系,可以通过以下命令来查看:

    kubeadm token list

      Node节点上成功join之后会得到以下信息:

      

      这时,我们在master节点上执行以下命令可以看到集群各个节点的状态了:

      

      如果看到两个Node状态不是Ready,那么可能需要检查哪些Pod没有正常运行:

    kubectl get pod --all-namespaces

      然后按照3.5中的检查方式进行检查并修复,最终kubectl get nodes效果应该状态都是Running。注意的是在检查时需要注意是哪个Node上的错误,然后在对应的Node进行修复,比如拉取flannel镜像。

      至此,一个最小化的K8S集群已经搭建完毕。

    3.7 测试Kubernetes集群

      这里为了快速地验证一下我们的K8S集群是否可用,创建一个示例Pod(这里默认是一个副本):

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

      

      如果想要看到更多的信息,比如pod被部署在了哪个Node上,可以通过 kubectl get pods,svc -o wide来查看。

      

       因为是NodePort方式,因此其映射的端口号会在30000-32767范围内随机取一个,我们可以直接通过浏览器输入IP地址访问,比如这时我们通过浏览器来访问一下任一Node的IP地址加端口号,例如192.168.2.101:31174或192.168.2.102:31174

      

      

       如果能够成功看到,那么恭喜你,你的K8S集群能够成功运行了,万里长征走完了第一步!

    四、小结

      本文快速地介绍了一下Kubernetes的核心构成组件及其作用,然后通过在三台Linux主机上通过Kubeadm搭建了一个Master节点两个Node节点的集群,最后通过部署一个Deployment来快速地验证了一下集群是否可用。下一篇会通过一个ASP.NET Core的部署例子来演示和介绍一下各个组件之间是如何协作的,以及部署Dashboard。

    参考资料

    (1)CloudMan,《每天5分钟玩转Kubernetes

    (2)李振良,《一天入门Kubernets教程

    (3)李振良,《30分钟部署一个Kubernetes集群

    (4)cao_xiaobo,《CentOS7 部署K8S集群

     

    作者:周旭龙

    出处:https://edisonchou.cnblogs.com

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: