kubernetes学习

从B站学习的k8s相关基础,有兴趣的自行访问:Kubernetes(K8S) 入门进阶实战完整教程,黑马程序员K8S全套教程(基础+高级)_哔哩哔哩_bilibili

第一章 kubernetes介绍

本章节主要介绍应用程序在服务器上部署方式演变以及kubernetes的概念、组件和工作原理。

1.1 应用部署方式演变


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

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

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

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

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

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

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

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

优点:

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

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

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

容器化部署方式给带来了很多遍历,但是也会出现一些问题,比如说:

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

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

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

1.2 kubernets简介


kubernetes,是一个全新的基于容器技术的分部式架构领先方案,是谷歌严格保密几十年的秘密武器——Brog系统的一个开源版本,于2014年9月发布第一个版本,2015年7月发布第一个正式版本

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

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

1.3 kubernetes组件


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

master:集群的控制平面,负责集群的决策

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

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

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

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

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

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

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

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服务了

1.4 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的集群环境

2.1 环境规划


2.1.1 集群类型

kubernetes集群大体上分为两类:一主多从和多主多从

  1. 一主多从:一台Master节点和多台Node节点,搭建简单,但是有单机故障风险,适用于测试环境
  2. 多主多从:堕胎Master节点和多台Node节点,搭建麻烦,安全性高,适合用于生产环境

说明:为了测试简单,本次搭建的是 一主两从 类型的集群

2.1.2 安装方式

kubenetes有多种部署方式,目前主流的方式有kubeadm、minkube、二进制包

  1. minikube:一个用于快速搭建单节点kubernetes的工具
  2. kubeadm:一个用于快速搭建kubernetes集群的工具
  3. 二进制包:从官网下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有效
  4. 说明:现在需要安装kubernetes的集群环境,但是又不想过于麻烦,所以选择使用kuberadm方式

2.1.3 主机规划

作用

IP地址

操作系统

配置

Master

172.20.60.121

Centos7.9 基础设施服务器

2颗CPU  2G内存  50G硬盘

Node1

172.20.60.122

Centos7.9 基础设施服务器

2颗CPU  2G内存  50G硬盘

Node2

172.20.60.123

Centos7.9 基础设施服务器

2颗CPU  2G内存  50G硬盘

2.2 环境搭建


本次环境搭建需要安装三台linux系统(一主二从),内置CentOS7.9系统,然后每台linux中分别安装docker(18.06.3),kubeadm(1.17.4)、kubelet(1.17.4)、kubelctl(1.17.4)程序

2.2.1 主机安装

安装虚拟机过程中注意下面选项的设置

  1. 操作系统环境:CPU(2C)内存(2G) 硬盘(50G)
  2. 语言选择:中文简体
  3. 软件选择:基础设施服务器
  4. 分区选择:自动分区
  5. 网络配置:保密

2.2.2 环境初始化

以下内容,三个主机节点均要做

(1) 检查操作系统的版本

#此方式下安装kubernetes集群要求CentOS版本再7.5或之上

(2) 主机名解析

给每个主机修改对应的名称,命令如下:

# 主机名为各主机的名(master、node1、node2)
[root@master ~] hostnamectl set-hostname 主机名

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

#主机名解析 编辑三天服务器的/etc/hosts文件,添加下面内容

192.168.10.1 master

192.168.10.2 node1

192.168.10.3 node2

(3) 时间同步

kubernetes要求集群中的节点时间必须精确一致,这里直接使用chronyd服务从网络同步时间

企业中建议配置内部的时间同步服务器

#启动chronyd服务

[root@master ~]# systemctl start chronyd

#设置chronyd服务开机自启

[root@master ~]# systemctl enable chronyd

#chronyd服务启动稍等几秒钟,久可以使用date命令验证时间了

[root@master ~]# date

(4) 禁止iptables和firewalld服务

[root@master ~]# systemctl stop firewalld

[root@master ~]# systemctl disable firewalld

[root@master ~]# systemctl stop iptables

[root@master ~]# systemctl disable iptables

(5) 禁用selinux

selinux是linux系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的奇葩问题

#编辑 /etc/selinux/config 文件。修改SELINUX的值为disabled

#注意修改完毕之后需要重启linux服务

[root@master ~]# vim  /etc/selinux/config
# 将SELINUX=Enforcing改成如下内容
SELINUX=disabled

(6) 禁用swap分区

swap分区指的是虚拟内存分区,他的作用是再物理内存使用完后,讲磁盘空间虚拟成内存来使用,启用swap设备会对系统得性能产生非常负面的影响,因此kubernetes要求么个节点都要禁用swap设备,但是如果因为某些原因不能关闭swap分区,就需要再集群安装过程中通过明确的参数进行配置说明

#编辑分区配置文件/etc/fstab,注释swap分区一行

#注意修改完毕之后需要重启linux服务

#/dev/mapper/centos-swap swap   swap   defaults   0   0

(7) 修改linux的内核参数

#修改linux的内核参数,添加网桥过滤和地址转发功能

#编辑/etc/sysctl.d/kubernetes.conf文件,添加如下配置:

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

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

net.ipv4.ip_forward = 1

#重新加载配置

[root@master ~]# sysctl -p

#加载网桥过滤模块

[root@master ~]# modprobe br_netfilter

#查看网桥过滤模块是否加载成功

[root@master ~]# lsmod | grep br_netfilter

(8) 配置ipvs功能

在kubernetes中service有两种模型,一种是基于iptables的,一种是基于ipvs的

两者相比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动载入ipvs模块

#安装ipset和ipvsadm

[root@master ~]# yum install ipset ipvsadm -y

#添加需要加载的模块写入脚本文件

[root@master ~]# cat <<EOF > /etc/sysconfig/modules/ipvs.modules

#!/bin/bash

modprobe ip_vs

modprobe ip_vs_rr

modprobe ip_vs_wrr

modprobe ip_vs_sh

modprobe nf_conntrack_ipv4

EOF

#为脚本添加执行权限

[root@master ~]# chmod +x /etc/sysconfig/modules/ipvs.modules

#执行脚本文件

[root@master ~]# /bin/bash  /etc/sysconfig/modules/ipvs.modules

#查看对应的模块是否加载成功reboot

[root@master ~]# lsmod | grep ip_vs

[root@master ~]# lsmod | grep nf_conntrack_ipv4

(9) 重启服务器

上面步骤完成之后,需要重新启动linux系统

[root@master ~]# reboot

2.2.3 安装docker

#1 切换镜像源

​
[root@master ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

​

#2 查看当前镜像源种支持的docker版本

yum list docker-ce --showduplicates

#3 安装特定版本中的docker-ce

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

[root@master ~]# yum install --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7 -y

#4 添加一个配置文件

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

​
[root@master ~]# mkdir /etc/docker

[root@master ~]# tee /etc/docker/daemon.json <<-'EOF'

{

  "registry-mirrors": ["https://o1o5o1sd.mirror.aliyuncs.com"]

}

EOF

​

#5 启动docker

[root@master ~]# systemctl daemon-reload

[root@master ~]# systemctl restart docker

[root@master ~]# systemctl enable docker

#6 检查docker状态和版本

[root@master ~]# docker version

2.2.4 安装kubernetes组件

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

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

​
[kubernetes]

name=Kubernetes

baseurl=kubernetes-yum-repos-kubernetes-el7-x86_64安装包下载_开源镜像站-阿里云

enabled=1

gpgcheck=0

repo_gpgcheck=0

gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg

http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

​

#安装kubeadm、kubelet和kubectl

[root@master ~]# yum install --setopt=obsoletes=0 kubeadm-1.17.4-0 kubelet-1.17.4-0 kubectl-1.17.4-0 -y

#配置kubelet的cgroup

#编辑/etc/sysconfig/kubelet,添加下面的配置

KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"

KUBE_PROXY_MODE="ipvs"

#4 设置kubelet开机自启

[root@master ~]# systemctl enable kubelet

2.2.5 准备集群镜像

#在安装kubernetes集群之前,必须要提前准备好集群需要的镜像,所需镜像可以通过下面命令查看

[root@master ~]# kubeadm config image list

#下载镜像

#此镜像在kubernetes的仓库中,由于网络原因,无法连接,下面提供了一种替代方案,粘贴shell脚本代码,输入回车即可

images=(

kube-apiserver:v1.17.4

kube-controller-manager:v1.17.4

kube-scheduler:v1.17.4

kube-proxy:v1.17.4

pause:3.1

etcd:3.4.3-0

coredns:1.6.5

)


for imageName in ${images[@]};do

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName

docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName

docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName

done

2.2.6 集群初始化

下面开始对集群进行初始化,并将node节点加入到集群中

下面的操作只需要在master节点上执行即可

#创建集群,--kubernetes-version是版本号,--pod-network-cidr是pod网络,--service-cidr是service网络,--apiserver-advertise-address是master节点的地址

[root@master ~]# kubeadm init --kubernetes-version=v1.17.4 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --apiserver-advertise-address=masterIP地址


#创建必要文件,初始化后会返回给出以下的命令

[root@master ~]# mkdir -p $HOME/.kube

[root@master ~]# sudo cp -i /etc/kubernetes/admin.conf  $HOME/.kube/config

[root@master ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

下面的操作只需要在node节点上执行即可

#将node节点加入集群,初始化成功后会返回以下命令,可以直接粘贴执行,这些token值有时效性,建议初始化后立即加入节点,否则就要重新生成token值

节点添加完后,master节点上可以执行以下命令进行查看节点状态

[root@master ~]# kubectl get nodes

NAME     STATUS     ROLES    AGE     VERSION

master   NotReady   master   2m12s   v1.17.4

node1    NotReady   <none>   16s     v1.17.4

node2    NotReady   <none>   9s      v1.17.4

2.2.7 安装网络插件

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

下面操作依旧只在master节点执行即可,插件使用的是DaemonSet的控制器,他会在每个节点上都运行

#获取fannel的配置文件

​[root@master ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

​

#修改文件中quay.io仓库为quay-mirror.qiniu.com

[root@master ~]# kubectl apply -f kub-flannel.yml

#稍等片刻,再次查看集群节点状态

[root@master ~]# kubectl get nodes

NAME     STATUS   ROLES    AGE   VERSION

master   Ready    master   15h   v1.17.4

node1    Ready    <none>   15h   v1.17.4

node2    Ready    <none>   15h   v1.17.4

至此,kubernetes的集群环境搭建完成

2.3 服务部署


接下来在kubernetes集群中部署一个nginx程序,测试下集群是否在正常工作

#部署nginx

[root@master ~]# kubectl create deployment nginx --image=nginx:1.14-alpine

#暴露端口

[root@master ~]# kubectl expose deployment nginx --port=80 --type=NodePort

#查看服务状态

[root@master ~]# kubectl get pods,svc

NAME                                       READY   STATUS    RESTARTS   AGE

pod/nginx-6867cdf567-2g84h   1/1          Running    0                    59s


NAME                       TYPE          CLUSTER-IP      EXTERNAL-IP     PORT(S)           AGE

service/kubernetes   ClusterIP     10.96.0.1            <none>                443/TCP           16h

service/nginx             NodePort    10.100.197.13   <none>                 80:31115/TCP   23s

​​​​​​​

#最后在电脑上访问下部署的nginx服务

​​​​​​​第三章 资源管理

本章节主要介绍yaml语法和kubernetes的资源管理方式

3.1 资源管理介绍


在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes

kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署服务,其实就是kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。

kubernetes的最小管理单元是pod而不是容器,所以只能将容器放在pod中,而kubernetes一般也不会直接管理Pod,而是通过Pod控制器来管理Pod的

pod可以提供服务之后,就要考虑如何访问Pod中服务,kubernetes提供了Service资源实现这个功能。

当然,如果Pod中程序的数据需要持久化,kubernetes还提供了各种存储系统。

学习kubernetes的核心,就是学习如何对集群上的Pod、Pod控制器、Service、存储等各种资源进行操作

3.2 YAML语法介绍


YAML是一个类似XML、JSON的标记性语言。

YAML强调以数据为中心,并不是表示语言为重点、因而YAML本身的定义比较简单,号称“一种人性化的数据格式语言”。

YAML的语法比较简单,主要有下面几个:

  1. 大小写敏感
  2. 使用缩进表示层级关系
  3. 缩进不允许使用tab,只允许空格(低版本限制)
  4. 缩进的空格数不重要,只要相同层级的元素左对齐即可
  5. ‘#’表示注释

YAML支持一下几种数据类型

  1. 纯量:单个的、不可再分的值
  2. 对象:键值对的集合,又称映射(mapping) /  哈希(HASH) /  字典(dictionary)
  3. 数组:一组按次序排列的值,又称为序列(sequence) /  列表(list)

#纯量,就是指的一个简单的值,字符串、布尔值、整数、浮点数、Null、时间、日期

#1 布尔类型

c1: true(或者True)、false(或者False)

#2 整型

c2: 234

#3 浮点型

c3:3.14

#4 null类型

c4:~   # 使用~表示null

#5 日期类型

c5:2018-02-17    # 日期必须使用ISO  8601格式,即yyyy-MM-dd

#6 时间类型

c5:2018-02-17T15:02:31+08:00  #时间使用ISO 8601格式,时间和日期之间使用T链接,最后使用+代表时区

#7 字符串类型

c7:heima    # 简单写法,直接写值,如果字符传中间有特殊字符,必须使用双引号或者单引号包裹

c8:line1

        line2    # 字符过多的情况可以拆分多行,每一行会被转化成一个空格

# 对象

#形式一(推荐)

heima

    age:15

    address:Beijing

#形式二(了解)

heima:{age:15,address:Beijing}

#数组

#形式一(推荐):

address

   -  顺义

   -  昌平

#形式二(了解):

address:[顺义,昌平]

小提示:

1、书写yaml切记  :后面要加一个空格

2、如果需要将多段yaml配置放在一个文件中,中间要使用 --- 分隔

3、下面是一个yaml转json的网站,可以通过它验证yaml是否书写正确

https://www.json2yaml.com/convert-yaml-to-json

3.3 资源管理方式


  1. 命令式对象管理:直接使用命令去操作kubernetes资源

kubectl run nginx-pod --image=nginx:1.7.1 --port=80

  1. 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源

kubectl create/patch  -f nginx-pod.yaml

  1. 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源

kubectl apply -f  nginx-pod.yaml

类型

操作对象

适用环境

优点

缺点

命令式对象管理

对象

测试

简单

只能操作活动对象,无法审计、跟踪

命令式对象配置

文件

开发

可以审计

项目大时,配置文件多,操作麻烦

声明式对象配置

目录

开发

支持目录操作

意外情况下难以调试

3.3.1 命令式对象管理

kubectl命令

  kubectl是kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。kuberctl命令的语法如下:

kubectl  [command] [type] [name] [flags]

comand:指定要对资源执行资源执行的操作,例如create、get、delete

type:指定资源类型,比如deployment、pod、service

name:指定资源名称,名称大小写敏感

flags:指定额外的可选参数

#查看所有pod

kubectl get pod

#查看某个pod

kubectl get pod pod_name

#查看某个pod,以yaml格式展示结果

kubectl get pod pod_name -o yaml

资源类型

kubernetes中所有的内容都抽象为资源,可以通过下面的命令进行查看:

kubectl api-resources

操作

kubernetes允许对资源进行多种操作,可以通过--help查看详细的操作命令

kubectl --help

经常使用的操作有下面这些:

命令分类

命令

翻译

命令作用

基本命令

create

创建

创建一个资源

edit

编辑

编辑一个资源

get

获取

获取一个资源

patch

更新

更新一个资源

delete

删除

删除一个资源

explain

解释

展示资源文档

运行和调试

run

运行

在集群中运行一个指定的镜像

expose

暴露

暴露资源为Service

describe

描述

显示资源内部信息

logs

日志

输出容器在pod中的日志

attach

缠绕

进入运行中的容器

exec

执行

执行容器中的一个命令

cp

复制

在pod内外复制文件

rollout

首次展示

管理资源的发布

scale

规模

扩(缩)容Pod的数量

autoscale

自动调整

自动调整Pod的数量

高级命令

apply

rc

通过文件对资源进行配置

label

标签

更新资源上的标签

其他命令

cluster-info

集群信息

显示集群信息

version

版本

显示当前Service和Client的版本

3.3.1 命令是对象管理

kubectl命令

   kubectl是kubernetes集群的命令行工具,通过它能够对集群上个今年新内容器化应用的安装部署,kubectl命令的语法如下:

kubectl  [command]  [type]  [name]  [flage]

  1. command:指定要对资源执行的操作,例如create、get、delete
  2. type:指定资源类型,比如deployment、pod、service
  3. name:指定资源的名称、名称大小写敏感
  4. flags:指定额外的可选参数

#查看所有pod

kubectl get pod

#查看某个pod

kubectl get pod pod_name

#查看某个个pod,以yaml格式展示结果

kubectl get pod pod_name -o yaml

资源类型

kubernetes中所有的内容都抽象为资源,可以通过下面的命令进行查看:

kubectl api-resources

经常使用的资源有下面这些:

资源分类

资源名称

缩写

资源作用

集群级别资源

nodes

no

集群组成部分

namespace

ns

隔离Pod

Pod资源

pods

po

装载容器

pod资源控制器

replicationcontrollers

rc

控制pod资源

replication

rs

控制pod资源

deployments

ds

控制pod资源

daemonsets

控制pod资源

jobs

控制pod资源

cronjobs

cj

控制jpod资源

horizontalpodautoscalers

hpa

控制jpod资源

satefulsets

sts

控制pod资源

服务发现资源

services

svc

统一pod对外接口

ingress

ing

统一pod对外接口

存储控制资源

volumeattachments

存储

persistentvolumes

pv

存储

persistentvolumeclaims

pvc

存储

配置资源

configmaps

cm

配置

secrets

配置

操作

kubernetes允许对资源进行多种操作,可以通过--help查看详细的操作命令

kubectl  --help

经常使用的操作有下面这些:

命令分类

命令

翻译

命令作用

基本命令

create

创建

创建一个资源

edit

编辑

编辑一个资源

get

获取

获取一个资源

patch

更新

更新一个资源

delete

删除

删除一个资源

explain

解释

展示资源文档

运行和调试

run

运行

在集群中运行一个指定的镜像

expose

暴露

暴露资源为Service

describe

描述

显示资源内部信息

logs

日志

输出容器再pod中的日志

attach

缠绕

进入运行中的容器

exec

执行

执行容器中的一个命令

cp

复制

在Pod内外复制文件

rollout

首次展示

管理资源的发布

scale

规模

扩(缩)容Pod的数量

autoscale

自动调整

自动调整Pod的数量

高级命令

apply

rc

通过文件对资源进行配置

label

标签

通过文件对资源进行配置

其他命令

cluster-info

集群信息

显示集群信息

version

版本

显示当给钱Service和Client的版本

下面以一个namespace的创建和删除,简单演示下命令的使用:

#创建一个namespace

[root@master ~]# kubectl create ns dev

namespace/dev created

#获取namespace

[root@master ~]# kubectl get ns

NAME              STATUS   AGE

default           Active   27d

dev               Active   16s

kube-flannel      Active   27d

kube-node-lease   Active   27d

kube-public       Active   27d

kube-system       Active   27d

#在此namespace下创建并运行一个nginx的pod

[root@master ~]# kubectl run pod --image=nginx:1.17.1 -n dev

kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl--generator=run-pod/v1 or kubectl create instead.

deployment.apps/pod created

#查看新创建的pod

[root@master ~]# kubectl get  pods -n dev

NAME                  READY   STATUS    RESTARTS   AGE

pod-cbb995bbf-qv8lt   1/1     Running   0          36s

#删除指定的pod

[root@master ~]# kubectl delete pod pod-cbb995bbf-qv8lt -n dev

pod "pod-cbb995bbf-qv8lt" deleted

#删除指定的namspace

[root@master ~]# kubectl delete ns dev

namespace "dev" deleted

扩展:kubectl可以再node节点上运行吗?

kubectl 的运行是需要进行配置的,他的配置文件时$HOME/.kube,如果想要再node节点运行此命令,需要将master上的.kube文件复制到node节点上,即再master节点上执行下面操作:

scp -r  HOME/.kube   node1 : HOME/

3.3.2 命令式对象配置

命令式对象配置就是使用命令配合配置文件一起来操作kubernetes资源

1)创建一个nginxpod.yaml,内容如下:

apiVersion: v1

kind: Namespace

metadata:

  name: dev

---

apiVersion: v1

kind: Pod

metadata:

  name: nginxpod

  namespace: dev

spec:

  containers:

  - name: nginx-containers

    image: nginx:1.17.1

2) 执行create命令,创建资源:

[root@master ~]# kubectl create -f nginxpod.yaml

namespace/dev created

pod/nginxpod created

此时发现创建两个资源对象,分别是namspace、pod

3)执行get命令,查看资源:

[root@master ~]# kubectl get -f nginxpod.yaml

NAME            STATUS   AGE

namespace/dev   Active   28s

NAME           READY   STATUS    RESTARTS   AGE

pod/nginxpod   1/1     Running   0          28s

这样就显示了两个资源对象的信息

4)执行delete命令,删除资源:

[root@master ~]# kubectl delete -f nginxpod.yaml

namespace "dev" deleted

pod "nginxpod" deleted

此时发现两个资源对象被删除了

总结:

         命令式对象配置的方式操作资源,可以简单的认为:命令 + yaml配置文件(里面是命令需要的各种参数)

3.3.3 声明式对象配置

声明式对象配置跟命令式对象配置很相似,但是它只有一个命令apply

#首先执行一次kubctl apply -f yaml文件,发现创建了资源

[root@master ~]# kubectl apply -f nginxpod.yaml

namespace/dev created

pod/nginxpod created

#再次执行一次kubectl apply -f yaml文件,发现资源没有变动

[root@master ~]# kubectl apply -f nginxpod.yaml

namespace/dev unchanged

pod/nginxpod unchanged

总结:

         其实声明式对象配置就是使用apply描述一个资源最终的状态(在yaml中定义状态)

         使用apply操作资源:

                如果资源不存在,就创建,相当于   kubectl create

                如果资源存在,就更新,相当于   kubectl patch

扩展:三种方式应该怎么用?

创建/更新资源     使用声明式对象配置 kubectl apply -f   xxx.yaml

删除资源              使用命令式对象配置 kubectl delete -f  xxx.yaml

查询资源              使用命令式对象管理 kubectl get(describe) 资源名称

第四章 实战入门

本章节将介绍如何在kubernetes集群中部署一个nginx服务,并能够对其进行访问

4.1 Namespace


     Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离

    默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那次是就可以将两个Pod划分到不通的namespace下,kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同组的资源进行隔离使用和管理。

    可以通过kubernetes的授权机制,将不通的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。

截图.png

kubernetes在集群启动之后,会默认创建几个namespace

[root@node1 ~]# kubectl get namespace

NAME                  STATUS   AGE

default                  Active       28d   # 所有未指定Namespace的对象都会被分配在default命名空间

kube-flannel          Active      28d   # 在Kubernetes集群中的每个节点上运行一个DaemonSet,用于部署和管理flanneld

kube-node-lease   Active      28d   # 集群节点之间的心跳维护,v1.13开始引入

kube-public           Active      28d   # 此命名空间下的资源可以被所有人访问(包括未认证用户)

kube-system         Active      28d   # 所有由Kubernetes系统创建的资源都处于这个命名空间

下面来看namesapce资源的具体操作:

查看

# 1 查看所有的ns     命令: kubectl get ns

[root@master ~]# kubectl get ns

NAME                   STATUS   AGE

default                      Active   29d

kube-flannel             Active   29d

kube-node-lease      Active   29d

kube-public              Active   29d

kube-system            Active   29d

# 2 查看指定ns    命令:kubectl  get  ns  ns名称

[root@master ~]# kubectl get ns kube-system

NAME          STATUS   AGE

kube-system   Active   29d

# 3 指定输出格式    命令:kubectl   get ns ns名称   -o  格式参数

# kubernetes支持的格式有很多,比较常见的是wide、json、yaml

[root@master ~]# kubectl get ns default -o yaml

apiVersion: v1

kind: Namespace

metadata:

  creationTimestamp: "2023-10-08T10:17:52Z"

  name: default

  resourceVersion: "145"

  selfLink: /api/v1/namespaces/default

  uid: dbc10978-556e-4589-8bf8-55d8a4a239a0

spec:

  finalizers:

  - kubernetes

status:

  phase: Active

# 4 查看ns详情    命令: kubectl  describe ns ns名称

[root@master ~]# kubectl describe ns default

Name:         default

Labels:       <none>

Annotations:  <none>

Status:       Active   #Active  命名空间正在使用中    Terminaling    正在删除命名空间

# ResourceQuota   针对namespace做的资源限制

# LimitRange针对namespace中的每个组件做的资源限制

No resource quota.

No LimitRange resource.

创建

# 创建namespace

[root@master ~]# kubectl create ns dev

namespace/dev created

删除

#删除namespace

[root@master ~]# kubectl delete ns dev

namespace "dev" deleted

配置方式

首先准备一个yaml文件:ns-dev.yaml

apiVersion: v1

kind: Namespace

metadata:

   name:dev

然后就可以执行对应的创建和删除命令了:

   创建:kubectl create -f ns-dev.yaml

   删除:kubectl delete -f ns-dev.yaml

4.2 Pod


Pod是kubernetes集群进行管理的最小单元,程序要运行必须要部署在容器中,而容器必须要存在于Pod中

Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。

截图.png

kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过下main命令查看:

[root@master ~]# kubectl get pod -n kube-system

NAME                                                   READY   STATUS                          RESTARTS   AGE

coredns-6955765f44-6744x                      1/1     Running                                    4          29d

coredns-6955765f44-6wh7j                       1/1     Running                                   5          27d

etcd-master                                                1/1     Running                                   8          29d

kube-apiserver-master                               1/1     Running                                   9          29d

kube-controller-manager-master                1/1     Running                                  12         29d

kube-flannel-ds-dcl6h                                 0/1     Init:ImagePullBackOff             2          29d

kube-flannel-ds-kd5q4                                0/1     Init:ImagePullBackOff             2          29d

kube-flannel-ds-lgfsb                                  0/1     Init:ImagePullBackOff             2          29d

kube-proxy-4wbnc                                      1/1     Running                                  2          29d

kube-proxy-fzrml                                         1/1     Running                                 2          29d

kube-proxy-nw86k                                       1/1     Running                                 2          29d

kube-scheduler-master                                1/1     Running                                15         29d

创建并运行

kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的

#命令格式: kubectl  run  (pod控制器名称)  [参数]

# --image       指定Pod的惊醒

# --port           指定端口

# --namespace     指定namespace

[root@master ~]# kubectl run nginx --image=nginx:1.17.1 --port=80 --namespace dev

kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.

deployment.apps/nginx created

查看Pod信息

#查看Pod基本信息

[root@master ~]# kubectl get pods -n dev

NAME                     READY   STATUS    RESTARTS   AGE

nginx-64777cd554-4z2tb   1/1     Running   0          19s

#查看Pod的详细信息

[root@master ~]# kubectl describe pod nginx-64777cd554-m94vx -n dev

Name:         nginx-64777cd554-m94vx

Namespace:    dev

Priority:     0

Node:         node2/172.20.60.123

Start Time:   Thu, 23 Nov 2023 16:09:14 +0800

Labels:       pod-template-hash=64777cd554

run=nginx

Annotations:  <none>

Status:       Running

IP:           10.244.2.12

IPs:

IP:           10.244.2.12

Controlled By:  ReplicaSet/nginx-64777cd554

Containers:

nginx:

Container ID:   docker://0cf1167eb68d15ed9c3a369ccb94354d898c6b854e1ecb6b4d6867e0f2f101ab

Image:          nginx:1.17.1

Image ID:       docker-pullable://nginx@sha256:b4b9b3eee194703fc2fa8afa5b7510c77ae70cfba567af1376a573a967c03dbb

Port:           80/TCP

Host Port:      0/TCP

State:          Running

Started:      Thu, 23 Nov 2023 16:09:15 +0800

Ready:          True

Restart Count:  0

Environment:    <none>

Mounts:

/var/run/secrets/kubernetes.io/serviceaccount from default-token-2r657 (ro)

Conditions:

Type              Status

Initialized       True

Ready             True

ContainersReady   True

PodScheduled      True

Volumes:

default-token-2r657:

Type:        Secret (a volume populated by a Secret)

SecretName:  default-token-2r657

Optional:    false

QoS Class:       BestEffort

Node-Selectors:  <none>

Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s

node.kubernetes.io/unreachable:NoExecute for 300s

Events:

Type    Reason     Age   From               Message

Normal  Scheduled  10m   default-scheduler  Successfully assigned dev/nginx-64777cd554-m94vx to node2

Normal  Pulled     10m   kubelet, node2     Container image "nginx:1.17.1" already present on machine

Normal  Created    10m   kubelet, node2     Created container nginx

Normal  Started    10m   kubelet, node2     Started container nginx

访问Pod

[root@master ~]# curl 10.244.2.12:80

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

<style>

body {

width: 35em;

margin: 0 auto;

font-family: Tahoma, Verdana, Arial, sans-serif;

}

</style>

</head>

<body>

<h1>Welcome to nginx!</h1>

<p>If you see this page, the nginx web server is successfully installed and

working. Further configuration is required.</p>

<p>For online documentation and support please refer to

<a href="nginx news">nginx.org</a>.<br/>

Commercial support is available at

<a href="Advanced Load Balancer, Web Server, & Reverse Proxy - NGINX">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>

</body>

</html>

删除指定Pod

#删除指定Pod

[root@master ~]# kubectl delete pod nginx-64777cd554-m94vx -n dev

pod "nginx-64777cd554-m94vx" deleted

#此时,显示删除Pod成功,但是再查询,发现又新增了一个

[root@master ~]# kubectl get pod -n dev

NAME                     READY   STATUS              RESTARTS   AGE

nginx-64777cd554-qcfd5   0/1     ContainerCreating   0          15s

#这是因为当前Pod是由Pod控制器创建得,控制器会监控Pod状况,一旦发现Pod死亡,会立即重建

#此时想要删除Pod,必须删除Pod控制器

#先来查询一下当前namespace下得Pod控制器

[root@master ~]# kubectl get deployment -n dev

NAME    READY   UP-TO-DATE   AVAILABLE   AGE

nginx   1/1     1            1           23m

#接下来,删除此Pod控制器

[root@master ~]# kubectl delete deployment  nginx -n dev

deployment.apps "nginx" deleted

#稍等片刻,再查询Pod,发现Pod被删除了

[root@master ~]# kubectl get pod -n dev

No resources found in dev namespace.

配置操作

创建一个pod-nginx.yaml,内容如下:

apiVersion: v1

kind: Pod

metadata:

  name: nginx

  namespace: dev

spec:

  containers:

  - image: nginx:1.17.1

    imagePullPolicy: IfNotPresent

    name: pod

    ports:

    - name: nginx-port

      containerPort: 80

      protocol: TCP

然后就可以执行对应的创建和删除命令了:

   创建:kubectl  create  -f  pod-nginx.yaml

   删除:kubectl  delete  -f  pod-nginx.yaml

4.3 Label


Label是kubernetes系统中的一个重要概念。它的作用就是再资源上添加标识,用来对它们区分和选择。

Label的特点:

  1. 一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
  2. 一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去
  3. Label通常再资源对象定义时确定,当然也可以再对象创建后动态添加或者删除

可以通过Label实现资源的多维度的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。

一些常用的Label示例如下:

  1. 版本标签:“version":"release",“version”:”stable“.......
  2. 环境标签:"environment":”dev","environment":"test","environment":"pro"
  3. 架构标签:"tier":"fontend","tier":"backend"

标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:

             Label用于给某个资源对象定义标识

             Label selector用于查询和筛选拥有某些标签的资源对象

当前有两种Label Selector:

  1. 基于等式的Label Selector

           name = slave:选择所有包含Label种key="name"且value=“slave”的对象

           env !=production:选择所有包括Label中的key=“env”且value不等于"production"的对象

  1. 基于集合的Label Selector

            name in (master,slave):选择所有包含Label中的key="name"且value=“master”或“slave”的对象

            name not in (frontend):选择所有包含Label中的key="name"且value不等于”frontend“的对象

标签的选择条件可以试用多个,此时将多个Label Selector进行组合,试用逗号“,”分隔即可。例如:

name=slave,env!=production

name not in (fronternd),env!=production

命令方式

#查看标签

[root@master ~]# kubectl get pod -n dev --show-labels

NAME    READY   STATUS    RESTARTS   AGE     LABELS

nginx   1/1     Running   0          9m52s   <none>

#为pod资源打标签

[root@master ~]# kubectl label pod nginx -n dev version=1.0

pod/nginx labeled

#重写覆盖pod资源标签

[root@master ~]# kubectl label pod nginx -n dev version=2.0 --overwrite

pod/nginx labeled

#筛选标签

[root@master ~]# kubectl get pod -n dev -l version=2.0 --show-labels

NAME    READY   STATUS    RESTARTS   AGE   LABELS

nginx         1/1        Running             0           27h    tier=back,version=2.0

[root@master ~]# kubectl get pod -n dev -l version!=2.0 --show-labels

NAME     READY   STATUS    RESTARTS   AGE   LABELS

nginx1        1/1       Running             0           26h   version=1.0

#删除标签

[root@master ~]# kubectl label pod nginx version- -n dev

pod/nginx labeled

配置方式

apiVersion: V1

kind: Pod

metadata:

  name: nginx

  namespace: dev

labels:

    version: "1.0"

    enV: "test"

spec:

  containers:

  - image: nginx:1.17.1 

    name: pod

    ports:

    - name: nginx-port

      containerPort: 80

      protocol: TCP

然后就可以执行对应的更新命令了:kubectl apply -f pod-nginx.yaml

4.4 Deployment


  在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。

  在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。

截图.png

命令操作

# 命令格式:kubectl run deployment 名称 [参数]

# --image   指定pod的镜像

# --port       指定端口

# --replicas  指定创建pod数量

# --namespace  指定namespace

[root@master ~]# kubectl run nginx1 --image=nginx:1.17.1 --port=80 --replicas=3 -n dev

kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.

#查看创建的pod

[root@master ~]# kubectl get pod -n dev

NAME                                  READY   STATUS    RESTARTS   AGE

nginx1-79d7bd676b-24qnv   1/1         Running           0             96m

nginx1-79d7bd676b-dvbwc   1/1         Running           0             96m

nginx1-79d7bd676b-hk6k2   1/1          Running           0             96m

#查看deployment的信息

[root@master ~]# kubectl get deploy -n dev

NAME     READY   UP-TO-DATE   AVAILABLE   AGE

nginx1        3/3                3                    3             98m

# UP-TO-DATE:成功升级的副本数量

# AVAILABLE:可用副本的数量

[root@master ~]# kubectl get deploy -n dev -o wide

NAME     READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES         SELECTOR

nginx1        3/3                  3                   3            2d1h           nginx1         nginx:1.17.1     run=nginx1

# 查看deployment的详细信息

[root@master ~]# kubectl describe deploy nginx1 -n dev

Name:                   nginx1

Namespace:              dev

CreationTimestamp:      Wed, 29 Nov 2023 10:12:14 +0800

Labels:                 run=nginx1

Annotations:            deployment.kubernetes.io/revision: 1

Selector:               run=nginx1

Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

Labels:  run=nginx1

Containers:

nginx1:

Image:        nginx:1.17.1

Port:         80/TCP

Host Port:    0/TCP

Environment:  <none>

Mounts:       <none>

Volumes:        <none>

Conditions:

Type           Status  Reason

Available      True    MinimumReplicasAvailable

Progressing    True    NewReplicaSetAvailable

OldReplicaSets:  <none>

NewReplicaSet:   nginx1-79d7bd676b (3/3 replicas created)

Events:          <none>

# 删除

[root@master ~]# kubectl delete deploy nginx1 -n dev

deployment.apps "nginx1" deleted

配置操作

创建一个deploy-nginx.yaml,内容如下:

apiVersion: apps/v1

kind: Deployment

metadata:

   name: nginx

   namespace: dev

spec:

   replicas: 3

   selector:

       matchLabels:

           run: nginx

   template:

       metadata:

           labels:

               run: nginx

       spec:

          containers:

          - image: nginx:1.17.1

            name: nginx

            ports:

              - containerPort: 80

                protocol: TCP

4.5 Service


通过上小节的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。

虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:

  1. Pod IP 会随着Pod的重建产生变化
  2. Pod IP 仅仅试集群内可见的虚拟IP,外部无法访问

这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。

Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。

截图.png

操作一:创建集群内部可以访问Service

# 暴露Service

[root@master ~]# kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev

service/svc-nginx1 exposed

# 查看service

[root@master ~]# kubectl get svc svc-nginx1 -n dev -o wide

NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE   SELECTOR

svc-nginx1   ClusterIP   10.111.61.3             <none>        80/TCP     38s      run=nginx

# 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的

# 可以通过这个IP访问当前service对应的POD

[root@master ~]# curl 10.111.61.3:80

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

<style>

    body {

        width: 35em;

        margin: 0 auto;

        font-family: Tahoma, Verdana, Arial, sans-serif;

    }

</style>

</head>

<body>

<h1>Welcome to nginx!</h1>

..........

</body>

</html>

操作二:创建集群外部也可以访问的Service

# 上面创建的Service的type类型为ClusterIP,这个IP地址只用集群内部可访问

# 如果需要创建外部也可以访问的Servie,需要修改type为NodePort

[root@master ~]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n                                                                                                                           dev

service/svc-nginx2 exposed

#此时查看,会发现出现了NodePort类型的Service,而且有一对Port(80:31118/TCP)

[root@master ~]# kubectl get svc  -n dev -o wide

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE   SELECTOR

svc-nginx1   ClusterIP   10.111.61.3              <none>        80/TCP              40m   run=nginx

svc-nginx2   NodePort    10.107.207.143       <none>        80:31118/TCP   13s   run=nginx

#接下来就可以通过集群外的主机访问  http://节点IP:31118 服务了

#例如在的电脑主机上通过浏览器访问下面的地址

http://172.20.60.121:31118

删除Service

[root@master ~]# kubectl delete svc svc-nginx1 -n dev

service "svc-nginx1" deleted

配置方式

创建一个svc-nginx.yaml,内容如下:

apiVersion: v1

kind: Service

metadata:

   name: svc-nginx

   namespace: dev

spec:

    clusterIP: 10.109.179.231

    ports:

    - port: 80

      protocol: TCP

      targetPort: 80

    selector:

        run: nginx

    type: ClusterIP

然后就可以执行对应的创建和删除命令了:

   创建:kubectl  create  -f   svc-nginx.yaml

   删除:kubectl  delete  -f   svc-nginx.yaml

小结

       至此,已经掌握了Namespace、Pod、Deployment、Service资源的基本操作,有了这些操作,就可以再kubernetes集群中实现一个服务的简单部署和访问了,但是如果想要更好的使用kubernetes,就需要深入学习这几种资源的细节和原理。

第五章 Pod详解

本章节将详细介绍Pod资源各种配置(yaml)和原理

5.1 Pod介绍


5.1.1 Pod结构

截图.png

每个Pod中都可以包含一个或者多个容器,这些容器可以分为类型:

  1. 用户程序所在的容器,数量可多可少
  2. Pause容器,这是每个Pod都会有的一个跟容器,它的作用有两个:

可以以它伟依据,评估整个Pod的健康状态

可以在根容器上设置ip地址,其他容器比ip(Pod IP),以实现Pod内部的网络通信

这里是Pod内部的通信,Pod的之间的通信采用虚拟二层网络技术来实现,我们当前环境用的是Flannel

5.1.2 Pod定义

下面是Pod的资源清单:

apiVersion: v1       #必选,版本号,例如v1

kind: Pod              #必选,资源类型,例如Pod

metadata:            #必选,元数据

   name: string     #必选,Pod名称

   namespace: string    #Pod所属的命名空间,默认为"default"

   labels:                       #自定义标签列表

      - name: string

spec:   #必选,Pod中容器的详细定义

    containers:    #必选,Pod中容器列表

    - name: string     #必选,让其名称

      image: string    #必选,容器的镜像名称

      imagePullPolicy: [ Always|Never|IfNotPresent ]   #获取镜像的策略

      command: [string]    #容器的启动命令列表,入不指定,使用打包时使用的启动命令

      args: [string]             #容器的启动命令参数列表

      workingDir: [string]   #容器的工作目录          

      volumeMounts:         #挂载到容器内部的存储卷配置

      -  name: string          #因公pod定义的共享存储卷的名称,需用volumes[ ]部分定义的卷名

         mountPath: string  #存储卷再容器内mount的绝对路径,英少于512字符

         readOnly: boolean #是否为只读模式

      ports:  #需要暴露的端口号列表

      -  name: string   #环境变量名称

         containerPort: int  #容器需要监听的端口号

         protocol: string      #端口协议,支持TCP和UDP,默认TCP

      env:           #容器运行前需要设置的环境变量列表

      -  name: string   #环境变量名称

         value: string   #环境变量的值

      resources: #资源限制和请求的设置

         limits:     #资源限制的设置

            cpu: string              #CPU的限制,单位为core书,将用于docker  run  --cpu-shares参数

            memory: string       #内存限制,单位可以为Mib/Gib,将用于dokcer  run  --memory参数

         requests:  #资源请求的设置

            cpu: string               #CPU的限制,容器启动的初始可用数量

            memory: string        #内存请求,容器启动的初始可用数量

        lifecycle:   #生命周期钩子

            postStart:        #容器启动后立即执行此钩子,如果执行失败,会更具重启策略进行重启

            postStop:        #容器终止前执行此钩子,无论结果如果,容器都会终止

        livenessProbe:    #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器

            exec:               #对Pod容器内检查方式设置为

               command: [string]  #exec方式需要指定的命令或脚本

            httpGet:           #对Pod内容器健康检查方法设置为HttpGet,需要指定Path、port

               path: string

               port: number

               host: string

               scheme: string

               HttpHeaders:

               -   name: string

                   value: string

            tcpSocket:        #对Pod内容器检查方式设置为tcpSocket方式

                   port: number

            initialDelaySecond: 0         #容器启动完成后首次探测的时间,单位为秒

            timeoutSeconds: 0            #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒

            periodSeconds: 0             #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次

            successThreshold: 0

            failureThreshold: 0

            securityContext:

                   privileged: false

restartPolicy: [Always | Never | onFailure ]   #Pod的重启策略

nodeName: <string>    #设置NodeName表示将该Pod调度到指定到名称的node节点上

nodeSelector: obeject  #设置NodeSelector

imagePullSecrets:        #Pull镜像是使用secret名称,已key:secretkey格式指定

-  name:string

hostNetwork: false       #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络

volumes:                      #在该pod上定义共享存储卷列表

-  name:string              #共享存储卷名(volumes类型有很多种)

   emptyDir: {}              #类型为emptyDir的存储卷,于Pod同生命周期的一个临时目录。为空值

   hostPath: string       #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录

        path: string          #Pod所在宿主机的目录,将被用于同期中mount的目录

   secret:                      #类型为secret的存储卷,挂载集群于定义的secret对象到容器内部

        scretname: string

        items:

        -  key: string

           path: string

   configMap:               #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部

        name: string

        items:

         -  key: string

            path: string

#小提示

#在这里,可通过一个命令来查看每种资源的可配置项

#kubectl explain 资源类型             查看某种资源可以配置的一级属性

#kubectl explain 资源类型.属性     查看属性的子属性

[root@master ~]# kubectl explain pod

KIND:     Pod

VERSION:  v1

DESCRIPTION:

Pod is a collection of containers that can run on a host. This resource is

created by clients and scheduled onto hosts.

FIELDS:

apiVersion   <string>

kind <string>

metadata     <Object>

spec <Object>

status       <Object>

[root@master ~]# kubectl explain pod.metadata

KIND:     Pod

VERSION:  v1

RESOURCE: metadata <Object>

在kubernetes中基本所有资源的一级属性基本都一样

  1. apiVersion  <string>    版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到
  2. kind  <string>              类型,由kubernetes内部定义,版本号必须可以用kubectl api-resources查询到
  3. metadata  <Object>    元数据,主要是资源标识和说明,常用的由name、namespace、labels等
  4. spec  <Object>            描述,只是配置中最重要的一部分,里面是对各种资源配置的详细描述
  5. status  <Object>          状态信息,里面的内容不需要自定义,由kubernetes自动生成

在上面的属性中,spec是接下来研究的重点,继续看下他的常见子属性:

  1. contianers    <[]Object>       容器列表,用于定义容器的详细信息
  2. nodeName   <String>          根据nodeName的值蒋pod调度到指定的Node节点上
  3. nodeSelector    <map[]>      根据NodeSelectort中定义的信息悬着蒋该Pod调度到包含这些label的Node上
  4. hostNetwork     <boolean>   是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主网络
  5. volumes      <[]Object>         存储卷,用于定义Pod上面挂载的存储信息
  6. restartPolicy    <string>        重启策略,表示Pod在遇到故障的时候的处理策略

5.2 Pod配置

本小节主要来研究 pod.spec.contianers 属性,这也是pod配置中最为关键的一项配置

[root@master ~]# kubectl explain pod.spec.containers

KIND:     Pod

VERSION:  v1

RESOURCE: containers <[]Object>         #数组,代表可以有多个容器

FIELDS:

   name   <string>                #容器名称

   image       <string>           #容器需要的镜像地址

   imagePullPolicy   <string>    #镜像拉取策略

   command      <[]string>     #容器的命令列表,如不指定,使用打包时使用的启动命令

   args     <[]string>                #容器的启动参数列表          

    env  <[]Object>                 #容器环境的配置

   ports                                    #容器需要暴露的端口号列表

   resources       <Object>       #资源限制和资源请求的设置

5.2.1 基本配置

创建pod-base.yaml文件,内容如下:

apiVersion: v1

kind: Pod

metadata:

    name: pod-base

    namespace: dev

    labels:

         user: test

spec:

    containers:

      - name: nginx

        image: nginx:1.17.1

      - name: busybox

        image: busybox:1.30

上面定义了一个比较简单Pod的配置,里面有两个容器

nginx:用1.17.1版本的nginx镜像创建(nginx是一个轻量级web容器)

busybox:用1.30版本的busybox镜像创建(busybox是一个小巧的linux命令合集)

#创建Pod

[root@master ~]# kubectl create -f pod-base.yaml

pod/pod-base created

#查看Pod状况

#READY   1/2   :表示当前Pod中有2个容器,其中1个准备就绪,1个未就绪

#RESTARTS    :重启次数,因为有1个容器故障了,Pod一直在重启试图恢复

[root@master ~]# kubectl get pods -n dev

5.2.2 镜像拉取

创建pod-imagepullpolicy.yaml文件,内容如下:

apiVersion: v1

kind: Pod

metadata:

      name: pod-imagepullpolicy

      namespace: dev

spec:

      containers:

       - name: nginx

         image: nginx:1.17.1

         imagePullPolicy: Always    #用于设置镜像拉取策略

       - name: busybox

         image: busybox:1.30

imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:

  1. Always:总是从远程仓库拉取镜像(一直用远程下载)
  2. IfNotPresent:本地有则使用本地镜像(本地有就本地   本地没有就远程下载)
  3. Never:只是用本地镜像,从不去远程仓库拉取,本地没有就报错(一直使用本地下载)

默认值说明:

    如果镜像tag为具体版本号,默认策略时:IfNotPresent

    如果镜像tag为:latest(最终版本),默认策略时always

#创建Pod

[root@master ~]# kubectl create -f pod-imagepullpolicy.yaml

pod/pod-imagepullpolicy created

#查看pod详情

[root@master ~]# kubectl get pods -n dev

NAME                  READY   STATUS             RESTARTS   AGE

pod-imagepullpolicy   1/2     CrashLoopBackOff   3          2m2s

5.2.3 启动命令

在前面的案例中,一直有个问题没有解决,就是busybox容器一直没有成功运行,那么到底事什么原因导致这个容器的故障呢?

原来busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭。

解决方法就是让其一直在运行,这就用到了command配置。

创建pod-command.yaml文件,内容如下:

apiVersion: v1

kind: Pod

metadata:

   name: pod-command

   namespace: dev

spec:

    containers:

    - name: nginx

      image: nginx:1.17.1

    - name: busybox

      image: busybox:1.30

      command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt;sleep 3;done;"]

command,用于在pod中的容器初始化完毕之后运行一个命令。

稍微解释下上面命令的意思:

   "/bin/bash","-c",使用sh执行命令

   touch /tmp/hello.txt;  创建一个/tmp/hello.txt 文件

   while true;do /bin/echo $(date +%T)>> /tmp/hello.txt;sleep 3;done; 每隔3秒向文件中写入当前时间

#创建Pod

[root@master ~]# kubectl create -f pod-command

pod/pod-command created

#查看Pod状态

#此时发现两个Pod都正常运行了

[root@master ~]# kubectl get pods -n dev

NAME               READY   STATUS    RESTARTS   AGE

pod-command   2/2          Running              0           25s

#进入pod中的busybox容器,查看文件内容

#补充一个命令  kubectl exec pod名称 -n 命名空间 -it -c  容器名称 /bin/sh 在容器内部执行命令

#使用这个命令就可以进入某个容器的内部,然后进行相关操作了

#比如,可以查看txt文件的内容

[root@master ~]# kubectl exec pod-command -n dev -it -c busybox /bin/sh

/ # tail -f /tmp/hello.txt

00:44:05

00:44:08

00:44:11

00:44:14

特别说明:

   通过上面发现command已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个args选项,用于传递参数呢?这其实跟docker有点关系,kubernetes中的command、args两项其实是可以实现覆盖Dockerfile中ENTRYPOINT的功能。

1 如果commmand和args均没有写,那么Dockerfile的配置。

2 如果command写了,但args没有写,那么Dockerfile默认的默认的配置会被忽略,执行输入的command

3 如果command没写,但args写了,那么Dockerfile中配置的ENTRYPOINT的命令会被执行,使用当前args的参数

4 如果command和args都写了,那么Dockerfile的配置会被忽略,执行command并追加上args参数

5.2.4环境变量

创建pod-env.yaml文件,内容如下:

apiVersion: v1

kind: Pod

metadata:

    name: pod-env

    namespace: dev

spec:

    containers:

    - name: busybox

      image: busybox:1.30

      command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60;done;"]

      env:  #设置环境变量列表

      - name: "username"

        value: "admin"

      - name: "password"

        value: "123456"

env,环境变量,用于在pod中的容器设置环境变量。

#创建Pod

[root@master ~]# kubectl create -f pod-env.yaml

pod/pod-env created

#进入容器,输出环境变量

[root@master ~]# kubectl exec pod-env -n dev -c busybox -it /bin/sh

/ # echo $password

123456

/ # echo $username

admin

这种方式不是很推荐,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。

5.2.5 端口设置

本小节来介绍容器的端口暴露,也就是containers的ports选项。

首先看下ports支持的子选项:

[root@master ~]# kubectl explain pod.spec.containers.ports

KIND:     Pod

VERSION:  v1

RESOURCE: ports <[]Object>

FIELDS:

   name              <string>   #端口名称,如果指定,必须保证name在pod中是唯一的

   containerPort  <integer> #容器要监听的端口(0<x<65536)

   hostPort          <integer> #容器要在主机上公开的端口,如果设置,主机上只能运行容器的一个副本(一般省略)

   hostIP             <string>   #要将外部端口绑定到主机IP(一般省略)

   protocol          <string>   #端口协议。必须是UDP、TCP或SCTP。默认为"TCP"

接下来,编写以恶搞测试案例,创建pod-ports.yaml

apiVersion: v1

kind: Pod

metadata:

    name: pod-ports

    namespace: dev

spec:

     containers:

     - name: nginx

       image: nginx:1.17.1

       ports: #设置容器暴露的端口列表

       - name: nginx-port

         containerPort: 80

         protocol: TCP

#创建Pod

[root@master ~]# kubectl create -f pod-ports.yaml

pod/pod-ports created

#查看pod

#在下面可以明显看到配置信息[root@master ~]# kubectl get pod pod-ports -n dev -o yaml

.......

spec:

containers:

  1. image: nginx:1.17.1

imagePullPolicy: IfNotPresent

name: nginx

ports:

    1. containerPort: 80

name: nginx-port

protocol: TCP

.......

访问容器中的程序需要使用的是podIp:contianerPort

5.2.6 资源配额

容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其他容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resource选项实现,他有两个子选项:

  1. limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启
  2. requests:用于设置容器需要的最少资源,如果环境资源不够,容器将无法启动

可以通过上面两个选项设置资源的上下限。

接下来,编写一个测试案例,创建pod-resources.yaml

apiVersion: v1

kind: Pod

metadata:

      name: pod-resources

      namespace: dev

spec:

       containers:

       - name: nginx

         image: nginx:1.17.1

         resources: #资源配额

              limits:   #限制资源(上限)

                 cpu: "2"  # cpu限制,单位core数

                 memory: "10Gi"  #内存限制

              requests: #请求资源(下限)

                 cpu: "2"  #cpu限制,单位core数

                 memory: "10Gi"  #内存限制

在这对cpu和memory的单位做一个说明:

  1. cpu:core数,可以为证书或小数
  2. memory:内存打下,可以使用Gi、Mi、G、M等形式

#运行Pod

[root@master ~]# kubectl create -f pod-resources.yaml

pod/pod-resources created

#查看发现pod运行正常

[root@master ~]# kubectl get pod pod-resources -n dev

NAME            READY   STATUS    RESTARTS   AGE

pod-resources   1/1        Running            0          8m38s

#查看pod详细信息

[root@master ~]# kubectl get pod pod-resources -n dev -o yaml

........

spec:

  containers:

  - image: nginx:1.17.1

    imagePullPolicy: IfNotPresent

    name: nginx

    resources:

      limits:

        cpu: "2"

        memory: 10Gi

      requests:

        cpu: "1"

        memory: 10Mi

.......

[root@master ~]# kubectl describe pod pod-resources -n dev

.......

Containers:

  nginx:

    Container ID:   docker://eca379d6cac437e16a2c91047889f7d365517ec561dad5f683993e55bf565180

    Image:          nginx:1.17.1

    Image ID:       docker-pullable://nginx@sha256:b4b9b3eee194703fc2fa8afa5b7510c77ae70cfba567af1376a573a967c03dbb

    Port:           <none>

    Host Port:      <none>

    State:          Running

      Started:      Wed, 24 Jan 2024 09:45:17 +0800

    Ready:          True

    Restart Count:  0

    Limits:

      cpu:     2

      memory:  10Gi

    Requests:

      cpu:        1

      memory:     10Mi

......

#接下来,停止Pod

[root@master ~]# kubectl delete -f pod-resources.yaml

pod "pod-resources" deleted

#修改limits和requests参数,使其一致,都为2核cpu和10G内存

#运行pod,发现pod运行异常,这是由于当前环境没有满足这些需求的节点

[root@master ~]# kubectl create -f pod-resources.yaml

pod/pod-resources created

[root@master ~]# kubectl get pod pod-resources -n dev

NAME            READY   STATUS    RESTARTS   AGE

pod-resources   0/1     Pending   0          21s

5.3 Pod生命周期

我们一般将pod对象从创建至终得这段时间范围称为pod得生命周期,它主要包含下面得过程:

pod创建

  1. 运行初始化容器(init container)过程
  2. 运行主机容器(main container)过程
    1. 容器启用后钩子(post start)、容器中之前钩子(pre stop)
    2. 容器得存活性探测(liveness probe)、就绪性探测(readiness probe)
  3. pod终止过程

截图.png

在整个生命周期中,Pod会出现5种状态(相位),分别如下:

  1. 挂起(Pending):apiserver已经创建了pod资源对象,但它尚未备调度完成或人处于下载镜像的过程种
  2. 运行(Running):pod已经调度至某节点,并且所有容器都已经被kubelet创建完成
  3. 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
  4. 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
  5. 未知(Unkonwn):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致

5.3.1 创建和终止

pod的创建过程

  1. 用户通过kubectl或其他api客户端提交需要创建的pod信息给apiServer
  2. apiServer开始生成pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端
  3. apiServer开始反映etcd中的pod对象的变化,其他组件使用watch机制来跟踪检查apiServer上的变动
  4. scheduler发现有新的pod对象要创建,开始为Pod分配主机并将结果信息更新至apiServer
  5. node节点上的kubelet发现有pod调度过来,尝试调用docker启动容器,并将结果回送至apiSever
  6. apiServer及那个接收到的pod状态信息存入etcd中

截图.png

pod的终止过程

  1. 用户向apiServer发送删除pod对象的命令
  2. apiServer中的pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),pod被视为dead
  3. 将pod标记为terminating状态
  4. kubelet在监控到pod对向转为terminating状态的同时启动pod关闭过程
  5. 端点控制器监控到pod对象的关闭行为时将其从所有匹配到此断电的service资源的端点列表中移除
  6. 如果当前pod对象定义了perStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行
  7. pod对象中的容器进程收到停止信号
  8. 宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号
  9. kubelet请求apiServer将此pod资源的宽限期设置为0从而完成删除操作,此时pod对于用户已不可见

5.3.2 初始化容器

初始化容器实在pod的主容器启动之前要运行的容器,主要是做一些祝融其的前置工作,它具有两大特征:

  1. 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它指导成功完成
  2. 初始化容器必须按照定义的顺序执行,当前仅当前一个成功之后,后面的一个才能运行

初始化容器有很多的应用场景,下面列出的是最常见的几个:

  1. 提供主容器镜像中不具备的工具程序或自定义代码
  2. 初始化容器要先宇应用容器串行启动并运行完成,因此可用于延后应用容器的启动直至其依赖的条件得到满足

接下来做一个案例,模拟下面这个需求:

     假设要以主容器来运行nginx,但是要求在运行nginx之前先要能连接上mysql和redis所在服务器

      为了简化测试,事先规定好mysql(172.20.45.153)和redis(172.20.45.154)服务器的地址

创建pod-initcontainer.yaml,内容如下:

apiVersion: v1

kind: Pod

metadata:

    name: pod-initcontainer

    namespace: dev

spec:

    containers:

    - name: main-container

      image: nginx:1.17.1

      ports:

      - name: nginx-port

        containerPort: 80

    initContainers:

    - name: test-mysql

      image: busybox:1.30

      command: ['sh','-c','until ping 172.20.45.153  -c 1; do echo waiting for mysql...;sleep 2;done;']

    - name: test-redis

      image: busybox:1.30

      command:  ['sh','-c','until ping 172.20.45.154  -c 1; do echo waiting for redis...;sleep 2;done;']

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值