Kubernetes学习笔记

一、Kubernetes概述

1.1 Kubernetes介绍

1.1.1 Kubernetes是什么及作用

Kubernetes(K8S)用于自动化容器化应用程序的部署、扩展和管理

Kubernetes通常结合docker容器工作,并且整合多个运行着docker容器的主机集群。

官网地址:https://Kubernetes.io

中文社区:https://www.kubernetes.org.cn/docs

Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes一个核心特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望运行

以下是Kubernetes相关特性:

  • 自动包装

    根据资源需求和其他约束自动放置容器,同时不会牺牲可用性,混合关键和最大努力的工作负载,以提高资源利用率并节省更多资源

  • 横向缩放

    使用简单的命令或UI,或者根据CPU的使用情况自动调整应用程序副本数

  • 自动部署和回滚

    Kubernetes逐渐部署对应用程序或其配置的更改,同时监视应用程序运行状况,以确保它不会同时终止所有实例,如果出现问题,Kubernetes会恢复更改,利用日益增长的部署解决方案的生态系统

  • 存储编排

    自动安装所选择的存储系统,无论是本地存储,如公有云提供商GCP或AWS,还是网络存储系统NFS,iSCSI,Gluster,Ceph,Cinder或Flocker

  • 自我修复

    重新启动失败的容器,在节点不可用时,替换和重新编排节点上的容器,终止不对用户定义的健康检查做响应的容器,并且不会再客户端准备投放之前将其通告给客户端

  • 服务发现和负载均衡

    不需要修改应用程序来使用不熟悉的服务发现机制,kubernetes为容器提供了自己的ip地址和一组容器的单个DNS名称,并可以在他们之间进行负载均衡

  • 密钥和配置管理

    部署和更新密钥和应用程序配置吗,不会重新编译你的景象,不会在堆栈配置中暴露密钥(secrets)

  • 批处理

    除了服务之外,kubernetes还可以管理批处理和CI工作负载,如果需要,替换出现故障的容器

使用kubernetes能做什么

kubernetes是一个全新的基于容器技术的分布式架构领先方案

kubernetes是一个开放的开发平台(无侵入性,现有系统容器迁移到kubernetes上),是一个晚辈的分布式系统支撑平台(完善的集群管理能力)

使用Kubernetes可以在物理或虚拟机的kubernets集群上运行容器化应用,Kubernetes能够提供一个以容器为中心的基础架构,满足在生产环境中运行应用的一些常见需求,如:

  • 多个进程协同工作
  • 存储系统挂在
  • Distributing secrets
  • 应用健康监测
  • 应用实例的复制
  • Pod自动伸缩/扩展
  • Naming and discovering
  • 负载均衡
  • 滚动更新
  • 资源监控
  • 日志访问
  • 调度应用程序
  • 提供认证和授权

为什么使用Kubernetes

使用Kubernetes最直接的感受就是我们可以轻装上阵的开发复杂的系统了

其次Kubernetes是在全面拥抱微服务架构(微服务的核心就是将一个巨大的单体应用拆分成很多小的互相连接的微服务,一个微服务后面可能是多个实例副本在支撑,副本数量可以随着系统负荷的变化而动态调整)

最后Kubernetes系统架构具备超强的横向扩展能力

1.1.2 Kubernetes快速入门

  • 环境准备

    • 关闭Centos防火墙

      systemctl disable firewalld

      systemctl stop firewalld

    • 安装etcd和Kubernetes软件

      yum update

      yum install -y etcd kubernetes

    • 启动服务

      systemctl start etcd

      systemctl start docker

      如果docker启动失败,请参考(vi /etc/sysconfig/selinux   把selinux后面的改为disabled,重启一波机器,再重启docker就可以了)
      

      systemctl start kube-apiserver

      systemctl start kube-controller-manager

      systemctl start kube-scheduler

      systemctl start kubelet

      systemctl start kube-proxy

  • 配置

    • 安装本地私有仓库

      docker pull registry

      docker run -di -p 5000:5000 registry

      添加仓库信任

      vi /etc/docker/daemon.json

      {
      “registry-mirrors”:[“https://docker.mirrors.ustc.edu.cn”], #这里是添加国内镜像加速仓库
      “insecure-registries”:[“192.168.65.133:5000”] #添加私有仓库信任,用于pull和push镜像
      }

      systemctl daemon-reload

      systemctl restart docker

      访问

      http://192.168.65.133:5000/v2/_catalog

    • Tomcat配置

      mkdir -p /usr/local/k8s

      cd /usr/local/k8s

      • mytomcat.rc.yaml

        apiVersion: v1
        kind: ReplicationController
        metadata:
         name: mytomcat
        spec:
         replicas: 2
         selector:
          app: mytomcat
         template:
          metadata:
           labels:
            app: mytomcat
          spec:
           containers:
            - name: mytomcat
              image: tomcat:7-jre7
              ports:
              - containerPort: 8080
        

        kubectl create -f mytomcat.rc.yaml

      • mytomcat.svc.yaml

        apiVersion: v1
        kind: Service
        metadata:
         name: mytomcat
        spec:
         type: NodePort
         ports:
          - port: 8080
            nodePort: 30001
         selector:
          app: mytomcat
        

        kubectl create -f mytomcat.svc.yaml

        kubectl get svc

        NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
        kubernetes   10.254.0.1       <none>        443/TCP          6m
        mytomcat     10.254.119.243   <nodes>       8080:30001/TCP   14s
        

        kubectl get pods(如下是有问题的,解决方案在下面)

        No resources found
        

        正常的显示如下(但是未启动,解决方案在下面)

        NAME             READY     STATUS              RESTARTS   AGE
        mytomcat-cqbfh   0/1       ContainerCreating   0          7s
        mytomcat-tnbjb   0/1       ContainerCreating   0          7s
        
  • 问题解决

    • docker pull失败

      • 解决方案1

        1、yum install -y rhsm

        2、docker search pod-infrastructure

        3、docker pull docker.io/tianyebj/pod-infrastructure

        4、docker tag tianyebj/pod-infrastructure 192.168.65.133:5000/pod-infrastructure

        5、docker push 192.168.65.133:5000/pod-infrastructure

        6、vi /etc/kubernetes/kubelet

        修改KUBELET_POD_INFRA_CONTAINER="–pod-infra-container-image=192.168.65.133:5000/pod-infrastructure:latest"

        7、重启服务

        systemctl restart kube-apiserver

        systemctl restart kube-controller-manager

        systemctl restart kube-scheduler

        systemctl restart kubelet

        systemctl restart kube-proxy

      • 解决方案2

        1、docker pull docker.io/kubernetes/pause

        2、docker tag docker.io/kubernetes/pause:latest 192.168.65.133:5000/google_containers/pause-amd64.3.0

        3、docker push 192.168.65.133:5000/google_containers/pause-amd64.3.0

        4、vi /etc/kubernetes/kubelet

        KUBELET_ARGS="–pod_infra_container_image=192.168.65.133:5000/google_containers/pause-amd64.3.0"

        5、重启kubelet服务

        systemctl restart kubelet

    • 外部网络不能访问

      在搭建好的k8s集群内创建的容器,只能在其所在的节点上curl可访问,但是在其他任何主机上无法访问容器占用的端口

      解决方案:

      1、vim /etc/sysctl.conf

      2、net.ipv4.ip_forward=1

      3、cd /usr/local/k8s

      4、kubectl replace -f mytomcat.rc.yaml

      5、kubectl delete svc --all

      6、kubectl create -f mytomcat.svc.yaml

      7、防火墙端口开放

      systemctl start firewalld
      firewall-cmd --list-ports
      firewall-cmd --state
      firewall-cmd --zone=public --add-port=30001/tcp --permanent
      firewall-cmd --reload
      systemctl stop firewalld
      
    • 解决kubectl get pods时No resources found问题

      1、vim /etc/kubernetes/apiserver

      2、找到 KUBE_ADMISSION_CONTROL="–admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota",去掉ServiceAccount,保存退出

      3、systemctl restart kube-apiserver

  • 浏览测试

    http://192.168.65.133:30001

1.2 Kubernetes基本架构与常用术语

Kubernetes集群包含有节点代理Kubelet和Master组件(APIs,scheduler,etc),一切都基于分布式的存储系统。

下面这张图是Kubernetes的架构图

在这里插入图片描述

在这里插入图片描述

在这张系统架构图中,把服务分为运行在工作节点上的服务和组成集群级别控制板的服务

Kubernetes节点有运行应用容器必备的服务,而这些都是受Master的控制

每个节点上都要运行Docker,Docker来负责所有具体的镜像下载和容器运行

Kubernetes主要有以下几个核心组件组成:

  • etcd:保存了整个集群的状态
  • apiserver:提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制
  • controller manger:负责维护集群的状态,比如故障检测、自动扩展、滚动更新等
  • schuduler:负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上
  • kubelet:负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理
  • Container runtime:负责镜像管理以及Pod和容器的真正运行(CRI)
  • kube-proxy:负责为Service提供cluster内部的服务发现和负载均衡

除了核心组件,还有一些推荐的Add-ons:

  • kube-dns:负责为整个集群提供DNS服务
  • Ingress Controller:微服务提供外网接口
  • Heapster:提供资源架空
  • Dashboard:提供GUI
  • Federation:提供跨可用区的集群
  • Fluentd-elasticsearch:提供集群日志采集、存储和查询

Kubernetes设计理念和功能其实就是一个类似Linux的分层架构

  • 核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境
  • 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)
  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)
  • 接口层:kubectl命令行工具、客户端SDK以及集群联邦
  • 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
    • Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、Faas、OTS应用、ChatOps等
    • Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等

1.2.1 Cluster

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

Kubernetes Cluster由Master和Node组成,节点上运行着若干Kubernets服务

1.2.2 Master

Master主要职责是调度,即决定将应用放在那里去执行。

Master运行Linux系统,可以是物理机或虚拟机

Master是Kubernetes Cluster的大脑,运行着Daemon服务包括kube-apiserver、kube-scheduler、kube-controller-manager、etcd和Pod网络

  • API Server(kube-apiserver)

    API Server提供HTTP/HTTPS RESTful API,即Kubernetes API。是Kubernets里所有资源的CRUD等操作的唯一入口,也是集群控制的入口进程

  • Scheduler(kube-scheduler)

    Scheduler是负责资源调度的进程,它决定将Pod放在哪个Node上运行

  • Controller Manager(kube-controller-manager)

    所有资源对象的自动化控制中心。Controller Manager负责管理Cluster的各种资源,保证资源处于预期的状态

    Controller Manager有多种,如replication controller、endpoints controller、namespace controller、serviceaccount controller等

    不同的controller管理不同的资源,如replication controller管理Deployment、StatefulSet、DaemonSet的声明周期,namespace controller管理Namespace资源

  • etcd

    etcd负责保存Kubernetes Cluster的配置信息和各种资源的状态信息。当数据发生变化时,etcd会快速地通知Kubernets相关组件

  • Pod网络

    Pod要能够相互通信,Kubernetes Cluster必须部署Pod网络,flannel是其中一个可选方案

1.2.3 Node

除了Master,Kubernetes集群中的其他机器被称为Node节点。Node职责是运行容器应用,Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期

Node也运行在Linux系统,可以是物理机或虚拟机

每个Node节点上都运行着以下一组关键进程

  • kubelet

    负责Pod对应的容器的创建、启动等任务,同时与Master节点密切协作,实现集群管理的基本功能

  • kube-proxy

    实现Kubernetes Service的通信与负载均衡机制的重要组件

  • Docker Enginer

    Docker引擎,负责本机的容器创建和管理工作

1.2.4 Pod

Pod是Kubernetes的最小单元,也是最重要和最基本的概念。

每一个Pod包含一个或多个容器,Pod的容器会作为一个整体被Master调度到一个Node上运行

Kubernetes为每个Pod都分配了唯一的IP地址,称为Pod IP

一个Pod里的多个容器共享Pod IP地址

在Kubernetes里,一个Pod里的容器与另外主机上的Pod容器能够直接通信

1.2.5 Service

Kubernetes Service定义了外界访问一组特定Pod的方式,Service有自己的ip和端口,Service提供了负载均衡。

也是Kubernetes最核心的资源对象之一,每个Service其实就是我们经常提起的微服务架构的一个“微服务”

1.2.6 Replication Controller

Replication Controller(简称RC)是Kubernetes系统中的核心概念之一,它其实是定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所有RC的定义包括如下几个部分

  • Pod期待的副本数(replicas)
  • 用于筛选目标Pod的Lable Selector
  • 当Pod的副本数量小于预期数量时,用于创建新Pod的Pod模板(template)

以下是总结的RC的一些特性与作用

  • 在大多数情况下,我们通过定义一个RC实现Pod的创建过程及副本数量的自动控制

  • RC里包括完成的Pod定义模板

  • RC通过Label Selector机制实现对Pod副本的自动控制

  • 通过改变RC里的Pod副本数量,可以实现Pod的扩容和缩容功能

  • 通过改变RC里的Pod模板中镜像版本,可以实现Pod的滚动升级功能

二、Kubernetes集群

Kubernetes用于协调高度可用的计算机集群吗,这些计算机群集被连接作为单个单元工作。

Kubernetes在一个集群上以更有效的方式自动分发和调度容器应用程序。

Kubernetes集群由两种类型的资源组成:

Master是集群的调度节点

Nodes是应用程序实际运行的工作节点

K8S集群部署有几种方式:kubeadm、minikube和二进制包

前两者属于自动部署,简化部署操作,

推荐使用二进制包部署,因为自动部署屏蔽了很多细节,使得对各个某块感知很少

安装需要的包在 https://download.csdn.net/download/snow_hope/16464841 进行下载

部署环境要求

(1)一台或多台机器,操作系统CentOS 7.x-86_x64

(2)硬件配置:内存2GB或2G+,CPU 2核或CPU 2核+;

(3)集群内各个机器之间能相互通信;

(4)集群内各个机器可以访问外网,需要拉取镜像;

(5)禁止swap分区;


2.二进制包安装

2.1 环境装备与规划

  • 推荐配置2核2G

    Docker version 17.05.0-ce

    角色IP组件
    master192.168.65.137etcd、kube-apiserver、kube-controller-manager、kube-scheduler、docker
    node01192.168.65.138kube-proxy、kubelet、docker
    node02192.168.65.139kube-proxy、kubelet、docker
  • 查看默认防火墙状态(关闭后显示not running,开启后显示running)

    firewall-cmd --state

  • 关闭防火墙

    systemctl stop firewalld

  • 禁止firewalld开机启动

    systemctl disable firewalld

  • 获取Kubernetes二进制包

    kubernetes-server-linux-amd64.tar.gz

  • 将二进制包上传到/opt/software

2.2 Master安装

2.2.1 Docker安装

(1)修改配置

vi /etc/sysconfig/selinux
SELINUX=disabled

重启机器
reboot

(2)安装docker

yum install docker -y
docker -v

(3)配置国内镜像

vi /etc/docker/daemon.json

{
"registry-mirrors":["https://docker.mirrors.ustc.edu.cn"]
}

(4)安装docker-compose

下载
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

上层文件中已有包

sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
2.2.2 etcd服务

etcd作为Kubernetes集群的主要服务,在安装Kubernetes各服务前首先安装和启动

  • 获取二进制文件

    etcd-v3.3.4-linux-amd64.tar.gz

  • 上传到master的/opt/software目录

  • 解压

    cd /opt/software

    tar -zxvf etcd-v3.3.4-linux-amd64.tar.gz

  • 将etcd和etcdctl文件复制到/usr/bin

  • 配置systemd服务文件/usr/lib/systemd/system/etcd.service

    [Unit]
    Description=Etcd Server
    After=network.target
    [Service]
    Type=simple
    EnvironmentFile=-/etc/etcd/etcd.conf
    WorkingDirectory=/var/lib/etcd
    ExecStart=/usr/bin/etcd
    Restart=on-failure
    [Install]
    WantedBy=multi-user.target
    
  • 启动与测试etcd服务

    mkdir -p /var/lib/etcd
    systemctl daemon-reload
    systemctl enable etcd.service
    systemctl start etcd.service
    etcdctl cluster-health
    
2.2.3 kube-apiserver服务

解压

cd /opt/software

tar -zxvf kubernetes-server-linux-amd64.tar.gz

解压后将kube-apiserver、kube-controller-manager、kube-scheduler以及管理要使用的kubectl二进制命令文件放到/usr/bin目录,即完成这几个服务的安装

cp kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/bin

下面是对kube-apiserver服务进行配置

编辑systemd服务文件:vi /usr/lib/systemd/system/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=etcd.service
Wants=etcd.service
[Service]
EnvironmentFile=-/etc/kubernetes/apiserver
ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS
Restart=on-failure
Type=notify
[Install]
WantedBy=multi-user.target

配置文件

创建目录:mkdir /etc/kubernetes

vi /etc/kubernetes/apiserver

KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://127.0.0.1:2379 --insecure-bind-address=0.0.0.0 --insecure-port=8080 --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,DefaultStorageClass,ResourceQuota --logtostderr=true --log-dir=/var/log/kubernetes --v=2"
2.2.4 kube-controller-manager服务

kube-controller-manager服务依赖于kube-apiserver服务:

配置systemd服务文件:vi /usr/lib/systemd/system/kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service

[Service]
EnvironmentFile=-/etc/kubernetes/controller-manager
ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

配置文件:vi /etc/kubernetes/controller-manager

KUBE_CONTROLLER_MANAGER_ARGS="--master=192.168.65.137:8080 --logtostderr=true --log-dir=/var/log/kubernetes --v=2"
2.2.5 kube-scheduler服务

kube-scheduler服务也依赖于kube-apiserver服务

配置systemd服务文件:vi /usr/lib/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service

[Service]
EnvironmentFile=-/etc/kubernetes/scheduler
ExecStart=/usr/bin/kube-scheduler $KUBE_scheduler_ARGS
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

配置文件:vi /etc/kubernetes/scheduler

KUBE_scheduler_ARGS="--master=192.168.65.137:8080 --logtostderr=true --log-dir=/var/log/kubernetes --v=2"
2.2.6 启动

完成以上配置后,按顺序启动服务

systemctl daemon-reload

systemctl enable kube-apiserver.service

systemctl start kube-apiserver.service

systemctl enable kube-controller-manager.service

systemctl start kube-controller-manager.service

systemctl enable kube-scheduler.service

systemctl start kube-scheduler.service

检查每个服务的健康状态:

systemctl status kube-apiserver.service

systemctl status kube-controller-manager.service

systemctl status kube-scheduler.service

2.2.7 Node节点安装准备
scp -r kubernetes 192.168.65.138:/opt/software/kubernetes

scp -r kubernetes 192.168.65.139:/opt/software/kubernetes

2.3 Node1安装

在Node1节点上,以同样的方式把从压缩包中解压出来的二进制文件kubelet kube-proxy放到/usr/bin目录中,见步骤 2.2.7

cd /opt/software/kubernetes/server/bin
cp kubelet kube-proxy /usr/bin


vi /etc/fstab
注释掉 /dev/mapper/centos-swap swap
#/dev/mapper/centos-swap swap                    swap    defaults        0 0

在Node1节点上需要预先安装docker,请参考Master上docker的安装,并启动Docker

2.3.1 kubelet服务

配置systemd服务文件:vi /usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet  $KUBELET_ARGS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target

创建目录:mkdir -p /var/lib/kubelet

​ mkdir /etc/kubernetes

配置文件:vi /etc/kubernetes/kubelet

KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig --hostname-override=192.168.65.138 --cgroup-driver=systemd --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --fail-swap-on=false"

用于kubelet连接Master Apiserver的配置文件

vi /etc/kubernetes/kubeconfig

apiVersion: v1
kind: Config
clusters:
 - cluster:
    server: http://192.168.65.137:8080
   name: local
contexts:
 - context:
    cluster: local
   name: mycontext
current-context: mycontext
2.3.2 kube-proxy服务

kube-proxy服务依赖于network服务,所以一定要保证network服务正常,如果network服务启动失败,常见解决方案有以下几种:

1.和NetworkManger服务有冲突,直接关闭NetworkMnager服务就好了,service NetworkManager stop,并且禁止开机启动  chkconfig NetworkManager off,之后重启就好了
2.和配置文件的MAC地址不匹配,使用 ip addr(或 ifconfig)查看MAC地址,将/etc/sysconfig/network-scripts/ifcfg-xxx中的HWADDR改为查看到的MAC地址
3.设定卡机启动一个名为NetworkManager-wait-online服务,命令为
systemctl enable NetworkManager-wait-online.service
4.查看/etc/sysconfig/network-scripts下,将其余无关的网卡位置文件全删掉,避免不必要的影响,即只保留一个以ifcfg开头的文件

配置systemd服务文件:vi /usr/lib/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Kube-proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.service
Requires=network.service

[Service]
EnvironmentFile=-/etc/kubernetes/proxy
ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS
Restart=on-failure
killMode=process

[Install]
WantedBy=multi-user.target

配置文件:vi /etc/kubernetes/proxy

KUBE_PROXY_ARGS="--master=http://192.168.65.137:8080 --hostname-override=192.168.65.138 --logtostderr=true --log-dir=/var/log/kubernetes --v=2"
2.3.3 启动

systemctl daemon-reload

systemctl enable kubelet

systemctl start kubelet

systemctl status kubelet

systemctl enable kube-proxy

systemctl start kube-proxy

systemctl status kube-proxy

2.4 Node2安装

参考Node1节点安装,注意修改IP

2.5 健康检查与示例测试

  • 查看集群状态

    kubelctl get nodes
    
    NAME             STATUS   ROLES    AGE     VERSION
    192.168.65.138   Ready    <none>   8m40s   v1.19.7
    192.168.65.139   Ready    <none>   2m8s    v1.19.7
    
  • 查看master集群组件状态

    kubectl get cs
    
    Warning: v1 ComponentStatus is deprecated in v1.19+
    NAME                 STATUS    MESSAGE             ERROR
    etcd-0               Healthy   {"health":"true"}   
    controller-manager   Healthy   ok                  
    scheduler            Healthy   ok 
    
  • nginx-rc.yaml

    mkdir /usr/local/k8s

    cd /usr/local/k8s

    vi nginx-rc.yaml

    apiVersion: v1
    kind: ReplicationController
    metadata:
     name: nginx
    spec:
     replicas: 3
     selector:
      app: nginx
     template:
      metadata:
       labels:
        app: nginx
      spec:
       containers:
       - name: nginx
         image: nginx
         ports:
         - containerPort: 80
    

    kubectl create -f nginx-rc.yaml

  • nginx-svc.yaml

    apiVersion: v1
    kind: Service
    metadata:
     name: nginx
    spec:
     type: NodePort
     ports:
      - port: 80
        nodePort: 33333
     selector:
      app: nginx
    

    kubectl create -f nginx-svc.yaml

  • 查看Pod

    kubectl get  pods
    
    No resources found in default namespace.
    问题解决方案:
    原因是docker拉取镜像失败
    通过搭建私有仓库方式:docker pull registry
    docker run -di --name=registry -p 5000:5000 registry
    修改daemon.json
    vi /etc/docker/daemon.json
    {
    "registry-mirrors":["https://docker.mirrors.ustc.edu.cn"],      
    "insecure-registries":["192.168.65.137:5000"]           
    }
    
    docker pull docker.io/kubernetes/pause
    
    docker tag docker.io/kubernetes/pause:latest 192.168.65.137:5000/google_containers/pause-amd64.3.0
    
    docker push 192.168.65.137:5000/google_containers/pause-amd64.3.0
    
    修改node节点上的kubelete
    vi /etc/kubernetes/kubelet
    
    KUBELET_ARGS="--pod_infra_container_image=192.168.65.137:5000/google_containers/pause-amd64.3.0 --kubeconfig=/etc/kubernetes/kubeconfig --hostname-override=192.168.65.138 --cgroup-driver=systemd --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --fail-swap-on=false"
    
    重启kubelet服务
    systemctl restart kubelet
    
    
    kubectl replace -f nginx-rc.yaml
    kubectl delete svc --all
    kubectl create -f nginx-svc.yaml
    
    kubectl get  pods
    
    NAME          READY   STATUS    RESTARTS   AGE
    nginx-5wqlx   1/1     Running   0          2m21s
    nginx-c54lc   1/1     Running   0          2m21s
    nginx-n9pbm   1/1     Running   0          2m21s
    

3.Kubeadm安装

3.1 环境装备与规划

  • 推荐配置2核2G

    Docker version 17.05.0-ce

    角色IP组件
    k8smaster192.168.65.133etcd、kube-apiserver、kube-controller-manager、kube-scheduler、docker
    k8snode1192.168.65.136kube-proxy、kubelet、docker
    k8snode2192.168.65.140kube-proxy、kubelet、docker
  • 查看默认防火墙状态(关闭后显示not running,开启后显示running)

    firewall-cmd --state

  • 关闭防火墙

    systemctl stop firewalld

    systemctl disable firewalld

  • 关闭selinux

    sed -i ‘s/enforcing/disabled/’ /etc/selinux/config #永久

    setenforce 0 #临时

  • 关闭swap(k8s禁止虚拟内存以提高性能)

    sed -ri ‘s/.swap./#&/’ /etc/fstab #永久

    swapoff -a #临时

  • 在master添加hosts

    cat >> /etc/hosts << EOF

    192.168.65.133 k8smaster

    192.168.65.136 k8snode1

    192.168.65.140 k8snode2

    EOF

  • 设置网桥参数

    cat > /etc/sysctl.d/k8s.conf << EOF

    net.bridge.bridge-nf-call-ip6tables = 1

    net.bridge.bridge-nf-call-iptables = 1

    EOF

    sysctl --system #生效

  • 时间同步

    yum install ntpdate -y

    ntpdate time.windows.com

所有服务器节点安装 Docker/kubeadm/kubelet/kubectl

Kubernetes 默认容器运行环境是Docker,因此首先需要安装Docker;

3.2 安装Docker

(1)修改配置

vi /etc/sysconfig/selinux
SELINUX=disabled

重启机器
reboot

(2)安装docker

yum install docker -y
docker -v

(3)配置国内镜像

vi /etc/docker/daemon.json

{
"registry-mirrors":["https://docker.mirrors.ustc.edu.cn"]
}

(4)安装docker-compose

下载
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

上层文件中已有包

sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

(5)启动docker

systemctl start docker
systemctl enable docker

3.3 安装kubeadm、kubelet、kubectl

(1)添加k8s的阿里云YUM源,到时候下载k8s的相关组件才能找到下载源;

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

(2)安装 kubeadm,kubelet 和 kubectl

Kubelet:运行在cluster所有节点上,负责启动POD和容器;

Kubeadm:用于初始化cluster的一个工具;

Kubectl:kubectl是kubenetes命令行工具,通过kubectl可以部署和管理应用,查看各种资源,创建,删除和更新组件;

yum install kubelet-1.19.4 kubeadm-1.19.4 kubectl-1.19.4 -y

systemctl enable kubelet.service

查看有没有安装:
yum list installed | grep kubelet
yum list installed | grep kubeadm
yum list installed | grep kubectl

查看安装的版本: kubelet --version

(3) 重启机器

(4)部署Kubernetes Master主节点(主节点上执行)

kubeadm init --apiserver-advertise-address=192.168.65.133 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.19.4 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16

输出结果:

0402 05:10:40.940464    2510 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.19.4
[preflight] Running pre-flight checks
        [WARNING SystemVerification]: missing optional cgroups: pids
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8smaster kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.65.133]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8smaster localhost] and IPs [192.168.65.133 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8smaster localhost] and IPs [192.168.65.133 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 19.503398 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.19" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8smaster as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8smaster as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: zp0v2c.iuh4850t3daaj1tn
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.65.133:6443 --token zp0v2c.iuh4850t3daaj1tn \
    --discovery-token-ca-cert-hash sha256:c4d3486feabd40009801526da89b2d227e4a130f692ec034746648c0ceab626e 

说明:

service-cidr 的选取不能和PodCIDR及本机网络有重叠或者冲突,一般可以选择一个本机网络和PodCIDR都没有用到的私网地址段,比如PODCIDR使用10.244.0.0/16, 那么service cidr可以选择10.96.0.0/12,网络无重叠冲突即可;

(5)在Master节点上执行

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

(6)Node节点加入Kubernetes集群(在Node节点执行)

kubeadm join 192.168.65.133:6443 --token zp0v2c.iuh4850t3daaj1tn \
    --discovery-token-ca-cert-hash sha256:c4d3486feabd40009801526da89b2d227e4a130f692ec034746648c0ceab626e 

输出结果:

[preflight] Running pre-flight checks
        [WARNING SystemVerification]: missing optional cgroups: pids
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

(7)查看Nodes(主节点)

kubectl get nodes

NAME        STATUS     ROLES    AGE     VERSION
k8smaster   NotReady   master   5m56s   v1.19.4
k8snode1    NotReady   <none>   56s     v1.19.4
k8snode2    NotReady   <none>   5s      v1.19.4

发现都是NotReady状态

3.4 部署网络插件

(1)下载kube-flannel.yml文件

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

文件见 ./pkg/kube-flannel.yml

(2)应用kube-flannel.yml文件得到运行时容器(主节点)

kubectl apply -f kube-flannel.yml

输出结果:

podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

(3)重启(主节点)

(4)查看Nodes(主节点)

kubectl get nodes

NAME        STATUS   ROLES    AGE   VERSION
k8smaster   Ready    master   39m   v1.19.4
k8snode1    Ready    <none>   34m   v1.19.4
k8snode2    Ready    <none>   33m   v1.19.4

(5)查看Pod状态

kubectl get pods -n kube-system

NAME                                READY   STATUS    RESTARTS   AGE
coredns-6d56c8448f-snghb            1/1     Running   0          39m
coredns-6d56c8448f-tjgsd            1/1     Running   0          39m
etcd-k8smaster                      1/1     Running   1          33s
kube-apiserver-k8smaster            1/1     Running   1          58s
kube-controller-manager-k8smaster   1/1     Running   1          31s
kube-flannel-ds-czlv9               1/1     Running   0          26m
kube-flannel-ds-j4v7k               1/1     Running   0          26m
kube-flannel-ds-j9vhb               1/1     Running   0          26m
kube-proxy-cwn25                    1/1     Running   0          34m
kube-proxy-w47mf                    1/1     Running   0          34m
kube-proxy-x72bn                    1/1     Running   0          39m
kube-scheduler-k8smaster            1/1     Running   1          54s

(6)查看Pod分布在哪个节点

 kubectl get pods -n kube-system -o wide

在这里插入图片描述

三、Kubernetes常用命令

获取当前命名空间下的容器
kubectl get pods

获取所有容器列表
kubectl get all

创建容器
kubectl create -f kubernate-pvc.yaml
kubectl apply -f kubernate-pvc.yaml
此两条命令在第一次创建时没区别,但是apply可以多次执行创建,进行修补

创建deployment
kubectl create deployment 【deploy_name】 --image=镜像 
暴露服务
kubectl expose deployment 【deploy_name】 --port=容器端口号  --type=NodePort

删除容器
kubectl delete pods/test-pd 或者  kubectl delete -f rc-nginx.yaml

查看指定pod在哪个node上运行
kubectl get pod/test-pd -o wide

查看容器日志
kubectl logs nginx-8586cf59-mwwtc

进入容器终端
kubectl exec -it nginx-8586cf59-mwwtc /bin/bash

一个Pod里含有多个容器,用--container or -c 参数
例如:有个pod名为my-pod,这个pod有两个容器,分别名为main-app和helper-app,下面的命令将打开到main-app的shell容器里
kubectl exec -it my-pod --container main-app -- /bin/bash

容器详情列表
kubectl describe pod/mysql-m8rbl

查看容器状态
kubectl get svc

空运行测试
kubectl create deployment 【deploy_name】 --image=镜像  --dry-run -o yaml	
kubectl create deployment 【deploy_name】 --image=镜像  --dry-run -o json	
可以打印出yaml或json内容
kubectl create deployment 【deploy_name】 --image=镜像  --dry-run -o yaml	> deploy.yaml
kubectl create deployment 【deploy_name】 --image=镜像  --dry-run -o json	> deploy.json
将打印的yaml或json内进行保存


四、Kubernetes核心组件

在这里插入图片描述

  • apiserver

    API server是所有请求的唯一入口;
    
    api server管理所有的事务,并把信息记录到etcd数据库中,etcd有一个自动服务发现的特性机制,etcd会搭建有三个节点的集群,实现三副本;
    
  • scheduler

    scheduler 调度器用来调度资源,查看业务节点的资源情况,确定在哪个node上创建pod,把指令告知给api server;
    
  • controller-manager

    控制管理器controller-manager管理pod;
    pod可以分为有状态和无状态的pod,一个pod里最好只放一个容器;
    

总结:

api server把任务下发给业务节点的kubelet去执行;

客户访问通过kube-proxy去访问pod;

pod下面的不一定是docker,还有别的容器;

一般pod中只包含一个容器,除了一种情况除外,那就是elk,elk会在pod内多放一个logstash去收集日志;

1.Pod详解

Pod是Kubernetes的最重要概念,每个Pod都有一个特殊的被称为“根容器”的Pause容器。

Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用于业务容器

在这里插入图片描述

在这里插入图片描述

  • Pod vs 应用

    每个Pod都是应用的一个实例,有专用的IP

  • Pod vs 容器

    一个Pod可以有多个容器,彼此间共享网络和存储资源,每个Pod中有一个Pause容器保存所有容器的状态,通过管理Pause容器,达到管理Pod中所有容器的效果

  • Pod vs 节点

    同一个Pod中的容器总会被调度到相同Node节点,不同节点间的通信基于虚拟二层网络技术实现

  • Pod vs Pod

    普通Pod和静态Pod

1.1.Pod的定义

下面是yaml文件定义的Pod的完整内容

apiVersion: v1											//版本
kind: Pod												//类型,Pod
metadata:												//元数据
 name: string											//元数据,Pod的名字
 namespace: string										//元数据,Pod的明明空间
 labels:												//元数据,标签列表
  - name: string										//元数据,标签的名字
 annotations:											//元数据,自定义注解列表
  - name: string										//元数据,自定义注解名字
spec:													//Pod中容器的详细定义
 containers:											//Pod中的容器列表,可以有多个容器
 - name: string											//容器的名称
   image: string										//容器中的镜像
   imagesPullPolicy: [Always|Never|IfNotPresent]		//获取镜像的策略,默认值为Always,每次都尝试重新下载镜像
   command: [string]									//容器的启动命令列表(不配置的话使用镜像内部的命令)
   args: [string]										//启动参数列表
   workingDir: string									//容器的工作目录
   volumeMounts: 										//挂在到容器内部的存储卷设置
   - name: string										
     mountPath: string									//存储卷在容器内部Mount的绝对路径
     readOnly: boolean									//默认值为读写
   ports:												//容器需要暴露的端口号列表
   - name: string
     containerPort: int									//容器要暴露的端口
     hostPort: int										//容器所在主机监听的端口(容器暴露端口映射到宿主机的端口,设置hostPort时同一个宿主机将不能再启动该容器的第2份副本)
     protocol: string									//TCP和UDP,默认值为TCP
   env:													//容器运行前要设置的环境列表
   - name: string
     value: string
   resources:
    limits:												//资源限制,容器的最大可用资源
     cpu: string
     memory: string
    requeste:											//资源限制,容器启动的初始可用资源数量
     cpu: string
     memory: string
   livenessProbe:										//Pod内容器健康检查的设置
    exec:
     command: [string]									//exec方式需要指定的命令或脚本
    httpGet:											//通过httpget检查健康
     path: string
     port: number
     host: string
     scheme: string
     httpHeaders:
     - name: string
       value: string
    tcpSocket:											//通过tcpSocket检查健康
     port: number
    initialDelaySeconds: 0								//首次检查时间
    timeoutSeconds: 0									//检查超时时间
    periodSeconds: 0									//检查间隔时间
    successThreshold: 0
    failureThreshold: 0
    securityContext:									//安全检查
     privileged: false
   restartPolicy: [Always|Never|OnFailure]				//重启策略,默认值为Always
   nodeSelector: object									//节点选择,表示将该Pod调度到包含这些label的Node上,以key:value格式指定
   imagePullSecrets:
   - name: string
   hostNetwork: false									//是否使用主机网络模式,启用Docker网桥,默认否
  volumes:												//在该Pod上定义共享存储卷列表
  - name: string
    emptyDir: {}										//是一种与Pod同生命周期的存储卷,是一个临时目录,内容为空
    hostPath: string									//Pod所在主机上的目录,将被用于容器中mount的目录
     path: string
    secret:												//类型为secret的存储卷
     secretName: string
     item:
     - key: string
       path: string
    configMap:											//类型为configMap的存储卷
     name: string
     items:
     - key: string
       path: string

1.2.Pod的基本用法

在Kubernetes中对运行容器的要求为:容器的主程序需要一直在前台运行,而不是后台运行。

应用需要改造成前台运行的方式

如果我们创建的Docker镜像的启动命令是后台执行程序,则在kubelet创建包含这个容器的Pod之后运行完该命令,即认为Pod已经结束,将立刻销毁该Pod。

如果认为该Pod定义了RC,则创建、销毁会陷入一个无限循环的过程中

Pod可以由1个或多个容器组合而成

  • 由一个容器组成的Pod示例

    #一个容器组成的Pod
    apiVersion: v1
    kind: Pod
    metadata:
     name: mytomcat
     labels:
      name: mytomcat
    spec:
     containers:
     - name: mytomcat
       image: tomcat
       ports:
       - containerPort: 8000
    
  • 由两个为紧耦合的容器组成的Pod示例

    #两个紧耦合的容器
    apiVersion: v1
    kind: Pod
    metadata:
     name: myweb
     labels:
      name: tomcat-redis
    spec:
     containers:
     - name: tomcat
       image: tomcat
       ports:
       - containerPort: 8080
     - name: redis
       image: redis
       ports:
       - containerPort: 6379
    
  • 创建

    kubectl create -f xxx.yaml
    
  • 查看

    kubectl get pod/po <Pod_name>
    kubectl get pod/po <Pod_name>  -o wide
    kubectl describe pod/po  <Pod_name>
    
  • 删除

    kubectl delete -f pod xxx.yaml
    kubectl delete pod --all/[pod_name]
    

1.3.Pod的分类

Pod有两种类型

  • 普通Pod

    普通Pod一旦被创建,就会被放入到etcd中存储,随后会被Kubernetes Master调度到某个具体的Node上并进行绑定,随后该Pod对应的Node上的kubelet进程实例化成一组相关的Docker容器并启动起来

    在默认情况下,当Pod里某个容器停止时,Kubernetes会自动检测到这个问题并且重新启动这个Pod里某所有容器,如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其他节点上

  • 静态Pod

    静态Pod是有kubelet进行管理的仅存在于特定Node上的Pod,他们不能通过API Server进行管理,无法与ReplicationController、Deployment或DaemonSet进行关联,并且kubelet也无法对它们进行健康检查

1.4.Pod生命周期和重启策略

  • Pod的状态

    状态值说明
    PendingAPI Server已经创建了该Pod,但Pod中的一个或多个容器的镜像还没有创建,包括镜像下载过程
    RunningPod内所有容器已创建,且至少一个容器处于运行状态、正在启动状态或正在重启状态
    CompletedPod内所有容器均成功执行突出,且不会再重启
    FailedPod内所有容器均已退出,但至少一个容器退出失败
    Unknown由于某种原因无法获取Pod状态,例如网络通信不畅
  • Pod重启策略

    Pod的重启策略包括Always、OnFailure和Never,默认值是Always

    重启策略说明
    Always当容器失效时,由kubelet自动重启该容器
    OnFailure当容器终止运行且退出码不为0时,有kubelet自动重启该容器
    Never不论容器运行状态如何,kubelet都不会重启该容器
  • 常见状态转换

    Pod包含的容器数Pod当前的状态发生事件Pod的结果状态
    RestartPolicy=AlwaysRestartPolicy=OnFailureRestartPolicy=Never
    包含一个容器Running容器成功退出RunningSucceededSucceeded
    包含一个容器Running容器失败退出RunningRunningFailure
    包含两个容器Running1个容器失败退出RunningRunningRunning
    包含两个容器Running容器被OOM杀掉RunningRunningFailure

1.5.Pod资源配置

每个Pod都可以对其能使用的服务器上的计算资源设置限额,kubernetes中可以设置限额的计算资源有CPU与Memory两种,其中CPU的资源单位为CPU数量,是一个绝对值而非相对值。

Memory配置也是一个绝对值,他的单位是内存字节数

kubernetes里,一个计算资源进行配额限定需要设定一下两个参数

Requests:该资源最小申请数量,系统必须满足要求

Limits:该资源最大允许使用的量,不能突破吗,当容器试图使用超过这个量的资源时,可能会被kubernetes kill并重启

spec:
 containers:
 - name: db
   image: mysql
   resources:
    requests:
     memory: "64Mi"
     cpu: "250m"
    limits:
     memory: "128Mi"
     cpu: "500m"

上述代码表明MYSQL容器申请最少0.25个CPU以及64MiB内存,在运行过程中容器所能使用的资源配额为0.5个CPU以及128MiB内存

2.Label详解

Label是kubernetes系统中另一个核心概念。

一个Label是一个key value的键值对,其中key与value由用户自己指定

label可以附加到各种资源对象上,如Node、Pod、Service、RC,一个资源对象可以定义任意数量的Label

同一个Label也可以被添加到任意数量的资源对象上,Label通常在资源对象定义时确定,也可以在对象创建后动态的添加或删除

Label的最常见的用法是使用metadata.labels字段,来为对象添加label,通过spec.selector来引用对象

apiVersion: v1
kind: ReplicationController
metadata:
 name: nginx
spec:
 replicas: 3
 selector:
  app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: nginx
     ports:
     - containerPort: 80
----------------------------------------

apiVersion: v1
kind: Service
metadata:
 name: nginx
spec:
 type: NodePort
 ports:
  - port: 80
    nodePort: 33333
  selector:
   app: nginx

Label附加到kubernetes集群中的各种资源对象上,目的就是对这些资源对象进行分组管理,而分组管理的核心就是Label Selector

Label与Label Selector都是不能单独定义,必须附加在一些资源对象的定义文件上,一般附加在RC和Service的资源定义文件中

3.Replication Controller详解

Replication Controller(RC)是kubernetes系统中核心概念之一

当我们定义了一个RC并提交到kubernetes集群中以后,Master节点上的Controller Manager组件就得到通知,定期检查系统中存活的Pod,并确保目标Pod实例的数量刚好等于RC的预期值,如果有过多或过少的Pod运行,系统就会停掉或创建一些Pod,此外我们也可以通过修改RC的副本数量,来实现Pod的动态缩放功能

kubectl scale rc nginx --replicas=5

由于Replication Controller与kubernetes代码中的模块Replication Controller同名,所以在kubernetes v1.2时,它就升级成了另外一个新的概念Replica Sets,官方解释为下一代的RC,它与RC区别是:Replica Sets支援基于集合的Label Selector,而RC只支持基于等式的Label Selector。

我们很少单独使用Replica Sets,它主要被Deployment这个更高层面的资源对象所使用,从而形成一整套Pod的创建、删除、更新的编排机制

最好不要越过RC直接创建Pod,因为Replication Controller会通过RC管理Pod副本,实现自动创建、补足、替换、删除Pod副本,这样就能够提高应用的容灾能力,减少由于节点崩溃等意外状况造成的损失。

即使应用程序只有一个Pod副本,也强烈建议使用RC来定义Pod

4.Replica Set详解

ReplicaSet跟Replication Controller没有本质的不同,只是名字不一样,并且RepicaSet支持集合式的selector(RepicationController仅支持等式)

kubernetes官方强烈建议避免直接使用ReplicaSet,而应该通过Deployment来创建RS和Pod

由于ReplicaSet是ReplicationController的替代,因此用法基本相同,唯一的区别在于ReplicaSet支持集合式的selector

5.Deployment详解

Deploynent是kubernetes v1.2引入的新概念,引入的目的是为了更好的解决Pod的编排问题,Deployment内部使用了ReplicaSet来实现

Deployment的定义与ReplicaSet的定义很类似,除了API声明与Kind类型有所区别

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: frontend
spec:
 replicas: 1
 selector:
  matchLabels:
   tier: frontend
  matchExpressions:
   - {key: tier,operator: In,values: [frontend]}
 template:
  metadata:
   labels:
    app: app-demo
    tier: frontend
  spec:
   containers:
   - name: tomcat-demo
     image: tomcat
     ports:
     -containerPort: 8080

6.Horizontal Pod Autoscaler

Horizontal Pod Autoscaler(Pod横向扩容 简称HPA)与RC、Deployment一样,也属于一种kubernetes资源对象。

通过跟踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性的调整目标Pod的副本数,这是HPA的实现原理

kubernetes对Pod扩容与缩容提供了手动和自动两种模式,手动模式通过kubelet scale命令对一个Deployment/RC进行Pod副本数量的设置。自动模式则需要用户根据某个性能指标或者自定义定业务指标,并制定Pod副本数量的范围,系统将自动在这个范围内根据性能指标的变化进行调整

  • 手动扩容和缩容

    kubectl scale deployment frontend --replicas 1
    
  • 自动扩容和缩容

    HPA控制器基本Master的kube-controller-manager服务启动参数–horizontal-pod-autoscaler-sync-period定义的时长(默认值为30s),周期性的检测Pod的CPU使用率,并在满足条件时对RC或Deployment中的Pod副本数量进行调整,以符合用户定义的平局Pod CPU使用率

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
     name: nginx-deployment
    spec:
     replicas: 1
     template:
      metadata:
       name: nginx
       labels:
        app: nginx
      spec:
       containers:
       - name: nginx
         image: nginx
         resources:
          requests:
           cpu: 50m
         ports:
          containerPort: 80
    --------------------------------------
    apiVersion: v1
    kind: Service
    metadata:
     name: nginx-svc
    spec:
     ports:
     - port: 80
     selector:
      app: nginx
    --------------------------------------
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
     name: nginx-hpa
    spec:
     scaleTargetRef:
      apiVersion: app/v1beta1
      kind: Deployment
      name: nginx-deployment
     minReplicas: 1
     maxReplicas: 10
     targetCPUUtilizationPercentage: 50
    

7.Volume详解

Volume是Pod中能够被多个容器访问的共享目录

Kubernetes的Volume定义在Pod上,它被一个Pod中的多个容器挂在到具体的文件目录下

Volume与Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或重启时,Volume中的数据也不会丢失。

要使用Volume,pod需要制定volume的类型和内容(spec.volumes字段),和映射到容器的位置(spec.container.volumeMounts字段)

kubernetes支持多种类型的Volume,包括:emptyDir、hostPath、gcePersistentDish、awsElasticBlockStore、nfs、iscsi、flocker、glusterfs、rbd、cephfs、gitRepo、secret、persistentVolumeClain、downwardAPI、azureFileVolume、azureDisk、vsphereVolume、Quobyte、PortworxVolume、ScaleIO

  • emptyDir

    EmptyDir类型的Volume创建于Pod被调度到某个宿主机上的时候,而同一个pod内的容器都能读写EmptyDir中的同一个文件。一旦这个Pod离开了这个宿主机,EmptyDir中的数据就会被永久删除。所以目前EmptyDir类型的volume主要用作临时空间,比如Web服务器写日志或者tmp文件需要的临时目录。

    yaml示例如下

    apiVersion: v1
    kind: Pod
    metadata:
     name: test-pd
    spec:
     containers:
     - iamge: docker.io/nazarpc/webserver
       name: test-container
       volumeMounts:
       - mountPath: /cache
         name: cache-volume
     volumes:
     - name: cache-volume
       emptyDir: {}
    
  • hostPath

    HostPath属性的volume使得对应的容器能够访问当前宿主机上的指定目录。例如,需要运行一个访问Docker系统目录的容器,那么久使用/var/lib/docker目录作为一个HostDir类型的volume;或者要在一个容器内部运行CAdvisor,那么久使用/dev/cgroups目录作为一个HostDir类型的volume

    一旦这个Pod离开了这个宿主机,HostDir中的数据虽然不会被永久删除,但数据也不会随pod迁移到其他宿主机上

    因此,需要注意的是,由于各个宿主机上的文件系统结构和内容并不一定完全相同,所以相同pod的HostDir可能会在不同的宿主机上表现出不同的行为

    yaml示例如下

    apiVersion: v1
    kind: Pod
    metadata:
     name: test-pd
    spec:
     containers:
     - image: docker.lio/nazarpc/webserver
       name: test-container
       #指定在容器中挂载路径
       volumeMounts:
       - mountPath: /test-pd
         name: test-volume
     #指定所提供的存储卷
     volumes:
     - name: test-volume
       #宿主机上的目录
       hostPath:
       	# directory location on host
        path: /data
       
    
  • nfs

    NFS类型的volume。允许一块现有的网络硬盘在同一个pod内的容器间共享

    yaml示例如下

    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: redis
    spec:
     selector:
      matchLabels:
       app: redis
     revisionHistoryLimit: 2
     template:
      metadata:
       labels:
        app: redis
      spec:
       containers:
       #应用镜像
       - image: redis
         name: redis
         imagePullPolicy: IfNotPresent
         #应用的内部端口
         ports:
         - containerPort: 6379
           name: redis6379
         env:
         - name: ALLOW_EMPTY_PASSWORD
           value: "yes"
         - name: REDIS_PASSWORD
           value: "redis"
         #持久化挂载位置,在docker中
         volumeMounts:
         #宿主机上的目录
         - name: redis-persistent-storage
           nfs:
            path: /k8s-nfs/redis/data
            server: 192.168.126.112
         
    

8.Namespace详解

Namespace在很多情况下用于实现多用户的资源隔离,通过将集群内部的资源对象分配到不同的Namespace中,形成逻辑上的分组,便于不同的分组在共享使用整个集群的资源同时还能被分别管理

kubernetes集群在启动后,会形成一个名为“default"的Namespace,如果不特别指定Namespace,则用户创建的Pod,RC,Service都将被系统创建到这个默认的名为default的Namespace中

  • Namespace创建

    apiVersion: v1
    kind: Namespace
    metadata:
     name:development
    -----------------
    apiVersion: v1
    kind: Pod
    metadata:
     name: busybox
     namespace:development
    spec:
     containers:
     - image: busybox
       command:
        - sleep
        - "3600"
       name: busybox
    
  • Namespace查看

    kubectl get pods --namespace=development
    

9.Service详解

Service是kubernetes最核心的概念,通过创建service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上

9.1.Service的定义

yaml格式的Service定义文件

apiVersion: v1
kind: Service
metadata:
 name: string
 namespace: string
 labels:
 - name: string
 annotations:
 - name: string
spec:
 selector: []
 type: string
 clusterIP: string
 sessionAffinity: string
 ports:
 - name: string
   protocol: string
   port: int
   targetPort: int
   nodePort: int
 status:
  loadBalance:
   ingress:
    ip: string
    hostname: string
属性名称取值类型是否必选取值说明
versionstringRequiredv1
kindstringRequiredService
metadataobjectRequired元数据
metadata.namestringRequiredService名称
metadata.namespacestringRequired命名空间,默认为default
metadata.labels[]list自定义标签属性列表
metadata.annotation[]list自定义注解属性列表
specobjectRquired详细描述
spec.selector[]listRequiredLabel Selector配置,将选择具有指定Label标签的Pod作为管理范围
spec.typestringRequiredService的类型,指定Service的访问方式,默认值为ClusterIP。取值范围如下:ClusterIP,虚拟服务的IP,用于k8s集群内部的pod访问,在Node上kube-proxy通过设置的iptables规则进行转发;NodePort,使用宿主机的端口,使用能够访问个Node外部客户端通过Node的IP地址和端口就能访问服务;LoadBalancer,使用外接负载均衡器完成到服务的负载分发,需要在spec.status.loadBalancer字段指定为爱步负载均衡器的ip地址,并同时定义nodePort和clusterIP,用于公有云环境
spec.clusterIPstring虚拟服务的IP地址,当type=clusterIP时,如果不指定,则系统进行自动分配,也可以手动指定。当type=LoadBalancer时,则需要指定
spec.sessionAffinitystring是否支撑session,可选择为ClientIP,表示将同一个源IP地址的客户端访问请求都转发到同一个后端Pod,默认为空
spec.ports[]listService需要暴露的端口列表
spec.ports[].namestring端口名称
spec.ports[].protocolstring端口协议,支持TCP和UDP,默认值为TCP
spec.ports[].portint服务监听的端口号
spec.ports[].targetPortint需要转发到后端Pod的端口号
spec.ports[].nodePortint当spec.type=NodePort时,指定映射到物理机的端口号
statusobject当spec.type=LoadBalancer时,设置外部负载均衡器的地址,用于公有云环境
status.loadBalancerobject外部负载均衡器
status.loadBalancer.ingressobject外部负载均衡器
statsu.loadBalancer.ingress.ipstring外部负载均衡器的IP地址
status.loadBalancer.ingress.hostnamestring外部负载均衡器的主机名

9.2.Service的基本用法

一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过TCP/IP机制及监听IP和端口号来实现

创建一个基本功能的service

apiVersion: v1
kind: ReplicationController
metadata:
 name: mywebapp
spec:
 replicas: 2
 template:
  metadata:
   name: mywebapp
   labels:
    app: mywebapp
  spec:
   containers:
   - name: mywebapp
   image: tomcat
   ports:
   - containerPort: 8080
   

我们可以通过kubectl get pods -l app=mywebapp -o yaml | grep podIP来获取Pod的IP地址和端口号来访问Tomcat服务,但是直接通过Pod的ip地址和端口号访问应用服务是不可靠的,因为当Pod所在的Node发生故障时,Pod将被kubernetes重新调度到另一台Node,Pod的地址会发生该表。

我们可以通过配置文件来定义Service,再通过kubectl create 来创建,这样可以通过Service地址来访问后端的Pod

apiVersion: v1
kind: Service
metadata:
 name: mywebAppService
spec:
 ports:
 - port: 8081
   targetPort: 8080
 selector:
  app: mywebapp
9.2.1.多端口Service

有时一个容器也可能提供多个端口的服务,那么在Service的定义中也可以相应的设置为将多个端口对应到多个应用服务

apiVersion: v1
kind: Service
metadata:
 name: mywebAppService
spec:
 ports:
 - port: 8080
   targetPort: 8080
 - port: 8005
   targetPort: 8005
   name: management
 selector:
  app: mywebapp
9.2.2.外部服务Service

在某些特殊环境中吗,应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群或Namespace中的服务作为服务的后端,这是可以通过创建一个无Label Selector的Service来实现

apiVersion: v1
kind: Service
metadata:
 name: my-service
spec:
 ports:
 - protocol: TCP
   port: 80
   tartgetPort: 80
--------------------
apiVersion: v1
kind: EndPoints
metadata:
 name: my-service
subsets:
- address:
  - IP: 10.254.74.13
  ports:
  - port: 8080
  

五、Kubernetes部署容器化应用

Docker应用–>在docker里面部署一个java程序(springboot)

5.1 部署nginx

kubectl create deployment nginx --image=nginx

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

kubectl get pod,svc

NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-6799fc88d8-4jw88   1/1     Running   0          2m54s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        53m
service/nginx        NodePort    10.100.253.65   <none>        80:30948/TCP   6s

http://192.168.65.133:30948/

5.2 部署Tomcat

kubectl create deployment tomcat --image=tomcat

kubectl expose deployment tomcat --port=8080 --type=NodePort

5.3 部署微服务(springboot程序)

1、项目打包(jar、war)-->可以采用一些工具git、maven、jenkins
2、制作Dockerfile文件,生成镜像;
3、kubectl create deployment nginx --image= 你的镜像
4、你的springboot就部署好了,是以docker容器的方式运行在pod里面的;

(1)自定义JDK镜像(Node节点,可以三个节点都执行下,或者save后load)

vi /opt/Dockerfile

FROM centos:latest
MAINTAINER zhuyan
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin
CMD java -version

构建镜像:docker build -t jdk1.8.0_171 .

运行镜像:docker run -di 镜像id(或者镜像名称)

(2)构建springboot项目镜像(Node节点,可以三个节点都执行下,或者save后load)

mkdir -p /opt/springboot

vi /opt/springboot/Dockerfile

FROM  jdk1.8.0_171
MAINTAINER zhuyan
ADD 38-springboot-k8s-1.0.0.jar /opt
RUN chmod +x /opt/38-springboot-k8s-1.0.0.jar
CMD java -jar /opt/38-springboot-k8s-1.0.0.jar

构建镜像:docker build -t 38-springboot-k8s-1.0.0-jar .

(3)空运行测试(主节点)

--方式1:打印yaml
kubectl create deployment springboot-k8s --image=38-springboot-k8s-1.0.0-jar --dry-run -o yaml
--方式2:打印json
kubectl create deployment springboot-k8s --image=38-springboot-k8s-1.0.0-jar --dry-run -o json
--方式3:打印yaml,并保存到 deploy.yaml
kubectl create deployment springboot-k8s --image=38-springboot-k8s-1.0.0-jar --dry-run -o yaml > deploy.yaml
--方式4:打印json,并保存到 deploy.json
kubectl create deployment springboot-k8s --image=38-springboot-k8s-1.0.0-jar --dry-run -o json> deploy.json

(4)修改deploy.yaml文件(主节点)

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: springboot-k8s
  name: springboot-k8s
spec:
  replicas: 1
  selector:
    matchLabels:
      app: springboot-k8s
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: springboot-k8s
    spec:
      containers:
      - image: 38-springboot-k8s-1.0.0-jar
        imagePullPolicy: Never
        name: 38-springboot-k8s-1-0-0-jar-2678v
        resources: {}
status: {}


增加  imagePullPolicy: Never,  把镜像拉取策略改为Never;

(5)yaml文件部署(主节点)

kubectl apply -f deploy.yaml 

等价于:

kubectl create deployment springboot-k8s --image=38-springboot-k8s-1.0.0-jar   (省略(3)、(4)步骤)

(6)查看信息

--查看pod详细信息
kubectl describe pods springboot-k8s-699cbb7f7-58hkz(pod名称)

--检查是否创建了deployments任务
kubectl get deployments
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
nginx            1/1     1            1           14h
springboot-k8s   1/1     1            1           8m14s
tomcat           1/1     1            1           14h

--查看pod日志
kubectl logs  springboot-k8s-699cbb7f7-58hkz(pod名称)

(7)暴露服务空执行

--方式1:打印yaml
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort --dry-run -o yaml
--方式2:打印json
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort --dry-run -o json
--方式3:打印yaml,并保存到 deploy-service.yaml
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort --dry-run -o yaml > deploy-service.yaml
--方式4:打印json,并保存到 deploy-service.json
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort --dry-run -o json>  deploy-service.json

(8)查看deploy-service.yaml

vi deploy-service.yaml

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: springboot-k8s
  name: springboot-k8s
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: springboot-k8s
  type: NodePort
status:
  loadBalancer: {}

(9)执行暴露服务

kubectl create -f deploy-service.yaml
或
kubectl apply -f deploy-service.yaml

等价于:
kubectl expose deployment springboot-k8s --port=8080 --type=NodePort        (省略(7)、(8)步骤)

(10)查看信息

--查看服务
kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP          15h
nginx            NodePort    10.100.253.65    <none>        80:30948/TCP     14h
springboot-k8s   NodePort    10.103.30.92     <none>        8080:30673/TCP   5m46s
tomcat           NodePort    10.108.134.142   <none>        8080:30455/TCP   14h

(11)访问

http://192.168.65.136:30673/38-springboot-k8s/json

5.4 部署Kubernetes Dashbaord

Kubernetes仪表盘是Kubernetes集群的基于Web的通用UI,它允许用户管理群集中运行的应用程序并对其进行故障排除,以及管理群集本身;

Github:https://github.com/kubernetes/dashboard

(1)下载yaml的资源清单

wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml

见 ./pkg/recommended.yaml

(2)应用yaml的资源清单

kubectl apply -f recommended.yaml

namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created

(3)查看pod是否成功

注意命名空间是在 kubernetes-dashboard 下面

kubectl get pod -n kubernetes-dashboard

NAME                                         READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-7b59f7d4df-vkf8z   1/1     Running   0          62s
kubernetes-dashboard-665f4c5ff-rm86x         1/1     Running   0          62s

(3)访问

https://192.168.65.136:30001/

需要输入token,token的生成采用以下三条命令

kubectl create serviceaccount dashboard-admin -n kube-system

kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

5.5 Ingress暴露应用

5.5.1 NodePort问题

NodePort服务是让外部请求直接访问服务的最原始方式
NodePort是在所有的节点(虚拟机)上开放指定的端口,所有发送到这个端口的请求都会直接转发到服务中的pod里

NodePort服务的yaml文件格式如下:

apiVersion: v1
kind: Service
metadata:  
 name: my-nodeport-service
selector:   
 app: my-appspec:
 type: NodePort
 ports:  
 - name: http
   port: 80
   targetPort: 80
   nodePort: 30008
   protocol: TCP

这种方式有一个“NodePort”的端口,能在节点上指定开放哪个端口,如果没有指定端口,它会选择一个随机端口,大多数时候应该让kubernetes随机选择端口

但是这种方式有很大的不足:

1.一个端口只能提供一个服务使用

2.只能使用30000-32767之间的端口

3.如果节点/虚拟机的ip地址发生变化,需要人工进行处理

因此在生产环境下不推荐这种方式来直接发布服务,如果不要求运行的服务实时可用或者用于演示或者临时运行一个应用可以采用这种方式

5.5.2 服务类型

Service的类型,指定Service的访问方式,默认值为ClusterIP。

取值范围如下:

  • ClusterIP,虚拟服务的IP,用于k8s集群内部的pod访问,在Node上kube-proxy通过设置的iptables规则进行转发;

  • NodePort,使用宿主机的端口,使用能够访问个Node外部客户端通过Node的IP地址和端口就能访问服务;

  • LoadBalancer,使用外接负载均衡器完成到服务的负载分发,需要在spec.status.loadBalancer字段指定为异步负载均衡器的ip地址,并同时定义nodePort和clusterIP,用于公有云环境

5.5.3 三种端口说明

ports:  
 - name: http
   port: 80
   targetPort: 80
   nodePort: 30008
   protocol: TCP
  • nodePort

    外部机器(在windows浏览器)可以访问的端口;
    比如一个Web应用需要被其他用户访问,那么需要配置type=NodePort,而且配置nodePort=30001,那么其他机器就可以通过浏览器访问scheme://node:30001访问到该服务;
    
  • targetPort

    容器的端口,与制作容器时暴露的端口一致(Dockerfile中EXPOSE),例如docker.io官方的nginx暴露的是80端口;
    
  • port

    Kubernetes集群中的各个服务之间访问的端口,虽然mysql容器暴露了3306端口,但外部机器不能访问到mysql服务,因为他没有配置NodePort类型,该3306端口是集群内其他容器需要通过3306端口访问该服务;
    
    kubectl expose deployment springboot-k8s --port=8080 --target-port=8080 --type=NodePort
    

5.5.4 Ingress

外部请求进入k8s集群的必经入口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1hGquP57-1617614743960)(.\img\9.png)]

虽然k8s集群内部署的pod、service都有自己的ip,但是却无法提供外网访问,通过监听NodePort方式不了服务,这种方式并不灵活,生产环境也不建议使用

Ingress是k8s集群中的一个API资源对象,相当于一个集群网管,可以自定义路由规则来转发、管理、暴露服务(一组pod),比较灵活,生产环境建议使用此种方式

Ingress不是k8s内置的(安装好k8s之后,并没有安装ingress)

ingress需要单独安装,而且有多种类型Google Cloud Load Balancer、nginx、contour、istio等等

5.5.4.1 部署Ingress Nginx

(1)部署一个nginx容器化应用(为了掩饰将nginx服务的端口暴露出去)

kubectl create deployment nginx --image=nginx

(2)暴露该服务(为了掩饰将nginx服务的端口暴露出去)

kubectl expose deployment nginx --port=80 --target-port=80 --type=NodePort

(3)部署Ingress Nginx

https://github.com/kubernetes/ingress-nginx

ingress-nginx是使用NGINX作为反向代理和负载均衡器的Kubernetes的Ingress控制器;

https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/baremetal/deploy.yaml

deploy.yaml见 ./pkg/deploy.yaml

332行修改成阿里云镜像:

阿里云镜像首页:http://dev.aliyun.com/

修改镜像地址为:

registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.33.0

如下图

在这里插入图片描述

    spec:
      hostNetwork: true
      dnsPolicy: ClusterFirst
      containers:
        - name: controller
          image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.33.0
          imagePullPolicy: IfNotPresent
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

部署

kubectl apply -f  deploy.yaml

namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created

(4)查看Ingress状态

kubectl get service -n ingress-nginx
kubectl get deploy -n ingress-nginx
kubectl get pods -n ingress-nginx
5.5.4.2 配置Ingress Nginx规则

ingress-nginx-rule.yaml 见 ./pkg/ingress-nginx-rule.yaml

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8s-ingress
spec:
  rules:
  - host: www.abc.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: nginx              #此处对应的是服务,如果想暴露tomcat,改成tomcat的服务即可,相应的要改下面的服务端口
            port: 
              number: 80
kubectl apply -f ingress-nginx-rule.yaml

报错问题解决

在这里插入图片描述

kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission

然后再次执行:kubectl apply -f ingress-nginx-rule.yaml

检查

kubectl get ing(ress) 

5.6 部署SpringCloud微服务

1、项目本身打成jar包或者war包;
2、制作项目镜像(写Dockerfile文件);
3、用k8s部署镜像(命令方式、yaml方式);
4、对外暴露服务;

(1)微服务包

见 ./pkg/microservice 路径下

(2)制作Dockerfile(Node节点上)

vi Dockerfile-consumer

FROM jdk1.8.0_171
MAINTAINER zhuyan
ADD 0923-spring-cloud-alibaba-consumer-1.0.0.jar /opt
RUN chmod +x /opt/0923-spring-cloud-alibaba-consumer-1.0.0.jar
CMD java -jar /opt/0923-spring-cloud-alibaba-consumer-1.0.0.jar

vi Dockerfile-provider

FROM jdk1.8.0_171
MAINTAINER zhuyan
ADD 0923-spring-cloud-alibaba-provider-1.0.0.jar /opt
RUN chmod +x /opt/0923-spring-cloud-alibaba-provider-1.0.0.jar
CMD java -jar /opt/0923-spring-cloud-alibaba-provider-1.0.0.jar

vi Dockerfile-gateway

FROM jdk1.8.0_171
MAINTAINER zhuyan
ADD 0923-spring-cloud-alibaba-gateway-1.0.0.jar /opt
RUN chmod +x /opt/0923-spring-cloud-alibaba-gateway-1.0.0.jar
CMD java -jar /opt/0923-spring-cloud-alibaba-gateway-1.0.0.jar

(3)制作镜像(Node节点上)

docker build -t spring-cloud-alibaba-consumer -f Dockerfile-consumer .
docker build -t spring-cloud-alibaba-provider -f Dockerfile-provider .
docker build -t spring-cloud-alibaba-gateway -f Dockerfile-gateway .

(4)部署provider

kubectl create deployment spring-cloud-alibaba-provider --image=spring-cloud-alibaba-provider --dry-run -o yaml > provider.yaml

修改yaml文件,把镜像策略改成Never,从本地拉取 

containers:
      - image: spring-cloud-alibaba-provider
        name: 0923-spring-cloud-alibaba-provider-1.0.0.jar-8ntrx
        imagePullPolicy: Never            #修改镜像拉取策略
        
kubectl apply -f provider.yaml

kubectl get pod

(5)部署consumer

kubectl create deployment spring-cloud-alibaba-consumer --image=spring-cloud-alibaba-consumer --dry-run -o yaml > consumer.yaml

修改yaml文件,把镜像策略改成Never,从本地拉取 

containers:
      - image: spring-cloud-alibaba-consumer
        name: 0923-spring-cloud-alibaba-consumer-8ntrx
        imagePullPolicy: Never            #修改镜像拉取策略
        
kubectl apply -f consumer.yaml

kubectl expose deployment spring-cloud-alibaba-consumer --port=9090 --target-port=9090 --type=NodePort      (此步可省略,因为可以使用gateway进行暴露)

kubectl get pod

(5)部署gateway

kubectl create deployment spring-cloud-alibaba-gateway --image=spring-cloud-alibaba-gateway --dry-run -o yaml > gateway.yaml

修改yaml文件,把镜像策略改成Never,从本地拉取 

containers:
      - image: spring-cloud-alibaba-gateway
        name: 0923-spring-cloud-alibaba-gateway-8ntrx
        imagePullPolicy: Never            #修改镜像拉取策略
        
kubectl apply -f gateway.yaml

kubectl expose deployment spring-cloud-alibaba-gateway --port=80 --target-port=80 --type=NodePort

kubectl get pod
kubectl get svc    查看服务端口

(6)访问

通过上面得到的服务端口,如为 35610 ,则: http://192.168.65.133:35610/echo

(7)Ingress统一入口

查看ingress

kubectl get pods -n ingress-nginx

vi ingress-nginx-gateway-rule.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8s-ingress-cloud
spec:
  rules:
  - host: www.cloud.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: spring-cloud-alibaba-gateway
            port: 
              number: 80

应用规则

kubectl apply -f  ingress-nginx-gateway-rule.yaml

kubectl get ing    获取规则绑定的IP,如192.168.65.136

(8)采用ingress入口访问

在外部机器上配置hosts

规则绑定的ip www.cloud.com 如下

192.168.65.136	www.cloud.com  

访问:http://www.cloud.com/echo

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值