容器入门(K8s)

一.容器技术概述

定义:容器是容器image运行时的实例【软件界的集装箱(隔离,封装)】

1.1虚拟机与容器的区别

虚拟机比容器的体积大

容器比虚拟机启动速度快

相同条件下容器比虚拟机运行实例多

容器共享系统内核,虚拟机不共享系统内核

容器实现技术为:利用Linux内核技术namespace/cgroup等实现;虚拟机实现技术为:依赖虚拟化技术实现,由Hypervisor层实现对资源的隔离

容器隔离效果为进程级别的隔离,虚拟机为系统资源级别的隔离

资源消耗,容器消耗资源小于虚拟机

容器镜像为分层镜像,虚拟机为非分层镜像

1.2附加;namespace以及cgroup解读

Namespace是将内核的全局资源做封装,使得每个Namespace都有一份独立的资源,因此不同的进程在各自的Namespace内对同一种资源的使用不会互相干扰。
Cgroup(control group)是内核提供的一种资源隔离的机制,可以实现对进程所使用的cpu、内存物理资源、及网络带宽等进行限制。还可以通过分配的CPU时间片数量及磁盘IO宽带大小控制任务运行的优先级

1.2.1在linux内核支持下的6种Namespace

IPC:隔离System IPC和POSIX消息队列

        IPC也就是进程间通信,Linux下有多种进程间通信,比如socket、共享内存、Posix消息队列和SystemV IPC等,这里的IPC namespace针对的是SystemV IPC和Posix消息队列,其会用标识符表示不同的消息队列,进程间通过找到标识符对应的消息队列来完成通信,IPC namespace做的事情就是相同的标识符在不同namespace上对应不同的消息队列,这样不同namespace的进程无法完成进程间通信。

Network:隔离网络资源

         Network Namespace隔离网络资源,每个Network Namespace都有自己的网络设备、IP地址、路由表、/proc/net目录、端口号等。每个Network Namespace会有一个loopback设备(除此之外不会有任何其他网络设备)。因此用户需要在这里面做自己的网络配置。IP工具已经支持Network Namespace,可以通过它来为新的Network Namespace配置网络功能。

Mount:隔离文件系统挂载点

         Mount namesapce用户隔离文件系统挂载点,每个进程能看到的文件系统都记录在/proc/$$/mounts里。在创建了一个新的Mount Namespace后,进程系统对文件系统挂载/卸载的动作就不会影响到其他Namespace。

PID:隔离进程ID

        PID Namespace用于隔离进程PID号,这样一来,不同的Namespace里的进程PID号就可以是一样的了。当创建一个PID Namespace时,第一个进程的PID号是1,也就是init进程。init进程有一些特殊之处,例如init进程需要负责回收所有孤儿进程的资源。另外,发送给init进程的任何信号都会被屏蔽,即使发送的是SIGKILL信号,也就是说,在容器内无法“杀死”init进程。

UTS:隔离主机名和域名

         UTS Namespace用于对主机名和域名进行隔离,也就是uname系统调用使用的结构体structutsname里的nodename和domainname这两个字段,UTS这个名字也是由此而来的。为什么需要uts namespace呢,因为为主机名可以用来代替IP地址,比如局域网通过主机名访问机器。

User:隔离用户ID和组ID

        User Namespace用来隔离用户资源,比如一个进程在Namespace里的用户和组ID与它在host里的ID可以不一样,这样可以做到,一个host的普通用户可以在该容器(user namespace)下拥有root权限,但是它的特权被限定在容器内。(容器内的这类root用户,实际上还是有很多特权操作不能执行,基本上如果这个特权操作会影响到其他容器或者host,就不会被允许)

1.2.2Cgroup解析

cpu 子系统: 主要限制进程的 cpu 使用率。
cpuacct 子系统: 可以统计 cgroups 中的进程的 cpu 使用报告。
cpuset 子系统: 为cgroups中的进程分配单独的cpu节点或者内存节点。
memory 子系统: 可以限制进程的 memory 使用量。
blkio 子系统: 可以限制进程的块设备 io。
devices 子系统: 可以控制进程能够访问某些设备。
net_cls 子系统: 可以标记cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
freezer 子系统: 可以挂起或者恢复 cgroups 中的进程。
ns 子系统: 可以使不同 cgroups 下面的进程使用不同的 namespace。

2.容器的安装与管理

2.1容器的安装

Ubuntu(使用 apt-get 进行安装)

2.1.1安装必要的系统工具

sudo apt-get update

sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common

2.1.2安装GPG证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
 2.1.3写入软件源信息

sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

 2.1.4更新并安装Docker-CE

sudo apt-get -y update

sudo apt-get -y install docker-ce

2.1.5安装指定版本的docker-ce
2.1.5.1查找Docker-ce的版本

apt-cache madison docker-ce

2.1.5.2安装指定版本(例如)

sudo apt-get -y install docker-ce=[5:20.10.15~3-0~ubuntu-jammy]

 2.1.6安装校验

docker version

 ps:更多系统安装参考docker-ce镜像_docker-ce下载地址_docker-ce安装教程-阿里巴巴开源镜像站

2.2容器的使用

2.2.1配置镜像加速器

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'

{ "registry-mirrors": ["https://y04tl95m.mirror.aliyuncs.com"] }

EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

2.3docker生命周期管理命令

  • docker create:创建一个容器
  • docker start:启动一个容器
  • docker run:创建并启动一个容器       --name:指定容器名字        -d:指定容器运行于前台还是后台        -p指定容器暴露端口号(宿主主机端口号唯一,可以重定向到容器端口)        --rm:当容器停止时,自动删除
  • docker pause:暂停一个容器
  • docker unpause:恢复一个容器
  • docker restart:重启一个容器
  • docker stop:停止一个运行的容器
  • docker rm:删除一个处于终止状态的容器
  • docker kill:杀死容器进程
  • docker --help:不会看帮助
  • docker ps:查看运行中的容器
  • docker container ls:查看运行中的容器
  • docker ps -a:查看所有容器
  • docker stop <id/name>:停止容器
  • docker kill <id/name>:停止容器
  • docker rm <id/name>:删除一个停止的容器
  • docker rm <id/name> -f :删除启动的容器

进入容器的方法:

docker exec      命令

例如:docker exec -it syf2 bash

二.容器镜像

1.容器镜像结构

1.1Linux操作系统结构

linux操作系统是由内核空间和用户空间构成

kernel:Linux系统内核

rootfs:linux系统中的用户空间文件系统,rootfs是一个操作系统所包含的文件,配置和目录,但并不包括操作系统kernel

1.2容器镜像

容器镜像就是容器模板,容器是镜像的运行实例,runtime根据容器镜像创建容器

容器镜像挂载在容器的根目录下是为容器中的应用提供隔离后执行环境的文件系统

        容器镜像打包了整个操作系统的文件和目录(rootfs),当然也包括应用本身,即应用及其所需要的所有依赖,都在被封装在容器镜像中,保证了本地环境和云端环境的高度一致

容器镜像采用分层结构

        所有容器共享宿主机Kernel,并且不能修改宿主机Kernel,即,容器运行过程中使用容器镜像里的文件,使用宿主机OS上的Kernel

1.3容器镜像分层结构

Docker镜像引入层layer的概念,个人理解为:镜像制作每一个步骤都是一个新的镜像层,新的镜像层比上一个镜像层多一些东西。

容器由若干只读镜像层和最上面的一个可写容器层构成,分层结构可以使镜像共享,容器创建、分发非常高效。

1.4UnionFS联合文件系统

UnionFS主要功能是将多个不同位置的目录联合挂载到同一目录下

        每一层镜像都是LInux操作系统与目录的一部分,在使用镜像时,docker会将所有的镜像层联合挂载到一个统一的挂载点上,成为一个完整的操作系统来使用。

1.5容器copy-on-write特性

创建文件:新文件只能被添加在容器层中

删除文件:依据容器分层结构从上往下依次查找,找到后,在容器层中记录该删除操作(具体实现方法为:UnionFS会在容器层中创建一个“whiteout”文件,将被删除的文件“遮挡起来”)

修改文件:依据容器分层由上往下依次查找,找到后,将镜像层中的数据复制到容器层进行修改,修改后的数据保存在容器层中

读取文件:依据容器分层结构由上往下依次查找

2.构建容器镜像

2.1镜像的基本命令

docker search        搜索镜像

docker pull        下载镜像

docker push        上传镜像        之前        docker login        登录镜像仓库

docker images或docker imager ls        查找本地镜像

docker rmi        删除镜像

2.2镜像命名

[registry-host]:[port]/username/imagename:tag

docker tag        修改命名

2.3构建镜像

  • docker commit
  • dockerfile

build context:为镜像构建提供所需的文件或目录

FROM        指定base镜像

MAINTANER        注明镜像作者

RUN        运行指定命令

ADD        将文件从build context 复制到镜像中(自动解压)

COPY        将文件从build context 复制版到镜像中(原文件,不进行任何操作)

ENV        设置环境变量

EXPOSE        指定容器中的应用监听的端口

USER        设置启动容器的用户

CMD        设置在容器启动时运行指定的脚本或命令

ENTRYPOINT        指定的是一个可执行的脚本或者程序的路径

VOLUME        将文件或目录声明为volume,挂载到容器中

WORKDIR        设置镜像的当前工作目录

docker build        执行dockerfile脚本

三.容器存储

1.容器的存储机制

1.1Storage Driver:管理镜像层和容器层

Storage Driver处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户提供了多层数据合并后的统一视图

所有Storage Driver 都使用可堆叠图像层和写时复制(CoW)策略

docker info命令可以查看当前系统上的Storage Driver

1.2Docker数据管理

docker容器中持久化数据一般采用两种存储方式

  • volume

由Docker管理,时将特定目录挂载给容器

        docker会在指定路径下为每一个volume生成一个目录,作为mount源

                路径:        /var/lib/docker/volumes

        可通过-v将volume挂载给一个容器

                -v格式:        <host path>:<container path>

docker volume ls        查看卷信息

docker inspect        查看容器中的Mounts信息

  • bind mount

可以手工创建目录,相当于linux硬链接,两个目录指向同一块数据

2.数据共享

2.1数据共享--主机与容器间

主机与容器数据共享

  • volume:将Host的数据copy到容器的volume中
    • 使用docker cp 命令在容器与Host之间复制数据
  • bind mount:将Host上的目录或文件mount到容器中

volume container        其他容器再引用这个

四.Kubernetes架构介绍

1.Kubernetes架构

Kubernetes作用

  • 集群方式部署调度容器应用
  • 应用的弹性伸缩
  • 提供容器间的负载均衡
  • 轻松的升级应用程序容器的新版本应用的健康检查和自动修复

一个基础的Kubernetes集群包含一个master节点和多个node节点,每个节点可以是一台物理机也可以是一台虚拟机

1.1Master节点提供的集群控制,对集群做出全局性决策,例如调度等通常在master节点上不运行用户容器

Kube-apiserver

        Kube-apiserver对外暴露了KubernetesAPI。它是Kubernetes的前端控制层。它被设计为水平扩展,即通过部署更多实例来缩放

Etcd

        etcd用于Kubernetes的后端存储,所有集群数据都存储在此处,始终为Kubernetes集群的etcd数据提供备份计划

kube-controller-manager

        运行控制器,它们是处理集群中常规任务的后台线程,逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成独立的可执行文件,并在单个进程中运行

kube-scheduler

        监视没有分配节点的新创建的pod,选择一个节点供他们运行

1.2节点组件运行在每一个Node节点上,维护运行的pod并提供Kubernetes运行时的环境

Kube-proxy

        Kube-proxy用于管理service的访问入口,包括集群内pod到service的访问和集群外访问service

Kubelet

        Kubelet是在集群内每个节点中运行的一个代理,用于保证pod的运行

容器引擎

通常使用docker来运行容器,也可使用rkt等作为替代方案

1.3推荐Add-ons

Core-dns:为整个集群提供dns服务

ingress Controller:为service提供外网访问入口

Dashboard:提供图形化管理界面

Meric:提供集群资源监控

Flannel/Calico:为Kubernetes提供方便的网络规划服务

2.Kubernetes部署

Kubernetes部署_想做运维大佬的博客-CSDN博客

 五.Kubernetes集群访问和NameSpace

1.Kubernetes API和集群访问

1.1命令行接口-Kubectl

在kubernetes中的操作很多都是通过kubectl来完成,通过这个命令可以管理Deployment,Replicaset,ReplicationController,Rod等,进行操作,扩容,删除等全生命周期操作,同时可以对管理对象进行查看或监控资源使用情况。

Kubectl语法

kubectl [command] [TYPE] [NAME] [flags]

  • command:指定你希望的操作,如create,get,describe,delete等
  • TYPE:指定操作对象的类型,如deployment,RS,Pod等
  • NAME:指定对象的名字
  • Flags:可选的标志位   flags:--image=nginx(创建资源使用的镜像是nginx)

常用的Command:

  • Create:创建资源
  • Apply:应用资源的配置变更,也可以代替create创建新的资源
  • Get:查看资源
  • Describe:查看资源的详细描述
  • Delete:删除资源

1.2使用yaml文件

Yaml格式要求

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab建,只允许使用空格
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • #表示注释,从这个字符一直到行尾都会被解析器忽略
  • 字符串可以不用引号标注
  • 列表项通过减号“-”加一个空格,多个项使用同样缩进级别作为同一列表部分
  • map结构里面的键值对(key/value)用冒号“;”来分隔

1.3Yaml文件格式

  • apiVersion:版本号        固定为apps/v1,如果使用1.9以前版本的kubernetes,填写apps/v1beta2
  • Kind:类型,选择创建资源类型,可以填写pod,replicaset等
  • Metadata:元数据,其中name项指定了名称,label项指定标签
  • Spec:描述pod的规格
  • containers:定义容器属性,在范例中,容器名字时mypod,镜像为busybox

1.4Resources

查看当前集群的Resources

kubectl api-resources

2.namespace

2.1命名空间-namespace

  • 命名空间提供了良好的资源隔离,可以用于区分不同的项目,用户等,如开发测试使用的namespace,或者生产使用的namespace
  • Namesoace是对一组资源和对象的抽象集合
  • Kubernetes集群安装后,初始状态下有default,kube-public和kube-system三个namespace。
    • Kube-system:kubernetes系统创建对象所使用的命名空间
    • Default:没有指明使用其他命名空间的对象所使用的默认命名空间
    • kube-public:此命名空间下的资源可以被所有人访问(包括未认证用户)

2.2常用命名空间命令

查看存在哪些namespace

kubectl get namespace

对指定命名空间进行操作,如创建pod,查看pod等,以下是我们之前使用过的查看系统域中pod命令

kubectl get pod --namespace=kube-system 

也可用简写的方式

kubectl get pod -n kube-system 

 六.Pod管理与使用

1.Pod基本概念

1.1Pod

  • Pod是ubernetes管理的最小基础单元
  • 一个Pod中封装了
    • 一个或多个紧耦合容器
    • 存储资源
    • 独立IP
    • 容器运行的选项

1.2Pod的两种模式

  • 只包含一个应用容器的Pod
    • 一个Pod一个容器的模式实在Kubenetes中主流的使用场景
    • 在这种场景中Pod可以被看作是一个包装纸包装着的容器,Kuberetes不能直接管理容器,而是需要通过管理Pod来管理容器
  • 包含多个应用的Pod
    • 仅当两种容器紧耦合,且需要共享相同的资源时使用这种模式
    • 这些在一个Pod内的容器形成一个统一的服务单元
      • 例如:一个容器从共享卷提供文件,而另一个容器刷新或更新资源Pod将这些容器和存储资源作为单个可管理的实体包装在一起

1.3Pod内部结构

  • 一个Pod中会分配一个pause容器,被称为根容器
    • Pause容器的状态代表整个Pod的状态
      • Pod中多个容器共享Pause容器的ip和存储,容器间可以通过localhost互访

1.5Pod生命周期

Pod一旦被创建,会被master调度到某一个具体的node上进行绑定,Pod会呈现不同的状态

Pending(悬决)    Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。
Running(运行中)    Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded(成功)    Pod 中的所有容器都已成功终止,并且不会再重启。
Failed(失败)    Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
Unknown(未知)    因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。

2.使用Pod

2.1创建一个Pod

  • 通过命令创建Pod

命令行
kubectl run <podname> --image=<imagename>

示例:通过命令生成yaml文件
k run hanmei2 --image=httpd --dry-run=client -o yaml > hanmei2.yaml

  •  通过yaml创建Pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

  •  应用yaml文件

k create -f
k appply -f

  • 生成yaml或者json格式

k get pod <podname> -o yaml > <filename>
k get pod <podname> -o json > <filename>

2.2Pod管理常用命令

k get pod -owide        查看详细的Pod

k describe pod <容器名>        查看Pod的完整信息

k delete pod <容器名>        删除容器

k exec -it <podname> -- /bin/sh        进入Pod

k exec -it <podname> --container <容器名> -- /bin/sh

k edit pod <podname>     修改yaml文件格式


k patch pod <podname>        
示例:
k patch pods pod1 -p '{"metadata": {"labels": {"run": "hanmei"}}}'

修改yaml文件
k apply -f

2.3在Pod运行多个container 

apiVersion: v1
kind: Pod
metadata:
name: kucc4
spec:
containers:
- name: nginx
image: nginx
- name: redis
image: redis
- name: memcached
image: memcached
- name: consul
image: consul

 2.4Sidecar容器

  • Sidecar容器
    • 日志代理/转发
    • Service Mesh,比如 istio,Linkerd;
    • 代理
    • 探活 :检查某些组件是不是正常工作
    • 其他辅助性的工作,比如拷贝文件,下载文件等

2.5Init Container

 Init Container与应用容器本质上是一样的,但它们是仅运行一次就结束的任务,并且必须在成功执行后,系统才能继续执行下一个容器,可以用在例如应用容器启动前做的一些初始化工作

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28    
    command: ['sh', '-c', "sleep 10"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "sleep 10"]

 2.6Static-Pod

  • Static-Pod由特定节点上的kubelet守护程序直接管理,不需要使用API-server监视它们。
  • kubelet会监视每个静态Pod(并在崩溃时重新启动它)
  • 静态Pod始终绑定到一个Kubelet在特定节点上

把yaml文件放到节点上/etc/kubernetes/manifests/路径下,就可以实现staticpod

七.Label与Annotation

1.标签(Label)

1.1Label

  • 标签(Label)是附在kubernetes对象(如Pod,deployment等)上的键值对(key-value)可以在创建时指定,也可以在创建后指定
  • Label的值本身不具备具体含义,但可以通过label来筛选对象特定子集,便于管理
  • 每一个对象可以有多个标签

 1.2创建标签的动机

便于对Pod做上线和升级以及更多

1.3标签的语法

  • 标签由一组键值对构成
  • Label key的组成
    • Key值必须是唯一的
    • 可以使用前缀,使用/分隔,前缀必须是DNS子域,不得超过253个字符,系统中自动化组件创建的label必须指定前缀,kubernetes/由kubernetes保留
    • 不得超过63个字符
    • 起始必须是字母或数字,中间可以有连字符,下划线和点
  • Label value的组成
    • 不得超过63个字符
    • 起始必须是字母或数字,中间件可以有连字符,下划线和点

1.4创建时指定标签

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
    version: new
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
 

 1.5管理标签的常用命令

查看标签

--show-labels
 -L:查看某一个标签
 -l:筛选对象

 添加标签

k label

示例:给节点打标签
kubectl label nodes k8s-node2 node-role.kubernetes.io/worker=

删除标签

k label <类型> <名字> <key>-

2.Annotation

2.1Annotation

  • Annotation与Label区别
    • Label主要用于选择对象,可以挑选出满足特定条件的对象
    • Annotation不能用于标识及选择对象,主要用于注释信息
  • Annotation的操作
    • 查看Annotation

k describe <类型> / <名字> 

         添加Annotation

k annotate <类型> <名字> <key>=<value>

        删除Annotation

k annotate <类型> <名字> <key>-

八.Pod控制器 

Pod控制器介绍与使用

  • 用来控制Pod的具体状态和行为
  • 根据不同的应用场景分为以下控制器
    • replicaset实现Pod副本数的管理
    • deployment是常用的控制器对象,能进行应用部署,副本数管理,滚动升级,弹性伸缩等操作
    • daemonset在每个node上都运行一个Pod
    • job用于执行一次性任务
    • cron job用于定时执行周期性任务
    • statefulset用于保证有状态应用

1.RS与Deployment

1.1Kubernetes管理对象

  • ReplicaSet(简称RS)
    • ReplicaSet是新一代的RC主要功能就是维持Pod的数量稳定,指定Pod的运行位置等,主要是更新了api,支持更多功能
    • ReplicaSet不建议直接使用,而是用更上层的概念Deployment
  • Deployment
    • 目前最常用的控制器就是Deployment,创建Deployment时也会自动创建ReplicaSet
    • Deployment可以管理一个或多个RS,并且通过RS来管理Pod

1.2创建和使用RS

创建RS

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # 按你的实际情况修改副本数
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: httpd
        image: httpd

 使用RS

k scale rs <name> --replicas <数量>        改变RS数量(也可以通过修改yaml文件来改变RS数量)

k get rs        查看RS

 1.3创建Deployment

使用yaml文件创建

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

k apply -f deployment.yaml

使用命令行创建

 k create deployment mydep --image=httpd --replicas 3

 修改副本数量

k scale deployment mydep  --replicas 5

 1.4Deployment弹性伸缩

  • 容器对比虚拟机,最大的优势在于可以灵活的弹性伸缩,而这一部分工作由kubernetes进行调度
  • Deployment弹性伸缩本质是Pod数量增加或减少
  • 弹性伸缩可以支持自动化部署,并在很短的时间内实现数量变更
  • 修改yaml文件中的replica参数实现
  • 使用scale命令应用变更完成扩容或减容

1.5升级

当使用deployment需要升级时,可以使用roling update功能滚动升级deployment所有Pod

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.0
        ports:
        - containerPort: 80

k apply -f deployment2.yaml --record

#检查升级
k get deploymnet  nginx-deployment -owide

回滚

查看更新版本

 k rollout history deployment nginx-deployment 

查看某一个版本的详细信息

  k rollout history deployment nginx-deployment --revision <num>

回滚版本

 k rollout undo deployment nginx-deployment --to-revision <num>

删除deployment

 k delete deployment nginx-deployment

2.DaemonSet

2.1DsemonSet的特性

  • DaemonSet部署的副本Pod会分布在各个Node上,当有Node加入集群时,也会为他们新增一个Pod,当有Node从集群移除时,这些Pod也会被回收,删除Daemount将会删除它创建的所有Pod
  • DaemonSet典型场景
    • 在集群的每个节点上运行存储Daemon,如gusterd,ceph
    • 在每个节点上运行日志收集Daemon,如flunend或logstash
    • 在每个节点上运行监控Daemon,如Prometheus Node Exporter

2.2创建DaemonSet

  • 创建DaemonSet的yaml文件和创建deployment使用的类似
  • 类型(Kind)选择DsemonSet
  • DaemonSet的yaml文件不需要副本数量项
  • 默认情况下DaemonSet会在所有Node上创建Pod

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.0
        ports:
        - containerPort: 80

 k apply -f daemonset.yaml

 查看DaemonSet

root@k8s-master:~# k get daemonsets.apps
root@k8s-master:~# k get pods -owide

删除daemonSet

  k delete daemonsets.apps nginx-deployment

3.StatefulSet

 有状态的应用

  • 有些情况下希望运行一些和上述不同的应用,包括使用持久化存储,稳定的网络标志,Pod与Pod之间并不是完全平等(即使它们用同一个镜像创建)这类服务通常称为有状态的服务,它的实现不在依靠ReplicaSet,而是用StatefulSet,它具备以下特性:
    • 稳定的持久化存储,Pod重新调度后访问相同的持久化数据,使用PVC来实现
    • 稳定的网络标识,Pod重新调度后,PodName和HostName不变,基于Headless Service实现
    • Pod都有一个序号,可以有序的进行扩展,部署等操作

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # 必须匹配 .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # 默认值是 1
  minReadySeconds: 10 # 默认值是 0
  template:
    metadata:
      labels:
        app: nginx # 必须匹配 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.k8s.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web 

4.Job与CronJob

创建jobs'

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4


k apply -f job.yaml

查看输出结果

 k logs <podname>

删除job

 k delete job <jobname>

创建cronjob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure


k apply -f cronjob.yaml

查看任务结果

 k logs <podname>

 删除cronjob

k delete cronjob <jobname>

九.Service服务发现

1.Service基本概念

创建deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-deployment
  labels:
    app: httpdep
spec:
  replicas: 3
  selector:
    matchLabels:
      app: http
  template:
    metadata:
      labels:
        app: http
    spec:
      containers:
      - name: http
        image: httpd
        ports:
        - containerPort: 80

 # k apply -f deployment1.yaml

 创建service

apiVersion: v1
kind: Service
metadata:
  name: http-service
spec:
  selector:
    app: http
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80 

 # k apply -f httpsvc1.yaml

检查

# k get svc
# k get endpoint
# iptables -nL -t nat | grep 8080
# curl <clusterip>:<port> 

1.1Pod的特征

Pod有自己独立的IP

Pod可以被创建,销毁

当扩缩容时,Pod的数量会发生改变

当Pod故障时,replicaset会创建的Pod

1.2Service

在Pod进行如此多变化时,业务如何被访问

  • Kubernetes Service定义了这样一种抽象:逻辑上的一组Pod,一种可以访问他们的策略--通常被称为微服务,这一组Pod能够被Service访问到,通常是通过Label Selector实现的
  • Service的实现类型
    • ClusterIP:提供一个集群内部的虚拟IP地址以供Pod访问(默认模式)
    • NodePort:在Node上打开一个端口以供外部访问
    • LoadBalancer:通过外部的负载均衡器来访问

1.3Endpoint Controller 

  • 负责生成和维护所有endpoint对象的控制器
  • 负责监听service和对应Pod变化
  • 监听到Service被删除,则删除和该Service同名的endpoint对象
  • 监听到新的Service被创建,则根据新建Service信息获取相关的Pod列表,然后创建对应的endpoint对象
  • 监听到Pod事件,则更新对应的Service和endpoint对象,将Pod IP记录到endpoint中

1.4Kube-proxy IPVS

 从K8s的1.8版本开始,Kube-proxy引入了IPVS模式。IPVS模式与iptable实现方式类似,但采用的hash表,因此当Service数量达到一定规模时,hash查表的速度优势就会体现出来从而提高Service的服务性能

2.服务发现

创建service

apiVersion: v1
kind: Service
metadata:
  name: http-service
spec:
  type: NodePort
  selector:
    app: http
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80
      nodePort: 30007

 # k apply -f nodeport.yam;

检查

root@k8s-master:~# k get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
http-service   NodePort    10.108.129.211   <none>        8080:30007/TCP   4s

root@k8s-master:~# curl 192.168.248.10:30007
<html><body><h1>It works!</h1></body></html>

 使用命令创建Service

 语法结构:
kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type]

示例:
root@k8s-master:~# k expose deployment http-deployment --port=8080 --target-port 80 --name http-service --type NodePort

3.集群中的DNS

创建clientpod用于测试域名

#k run clientpod --image busybox -- /bin/sh -c "sleep 3000"
root@k8s-master:~# k exec -it clientpod -- /bin/sh

/ # nslookup 10.106.192.6
Server:         10.96.0.10
Address:        10.96.0.10:53

6.192.106.10.in-addr.arpa       name = http-service.default.svc.cluster.local

3.1CoreDNS

  • CoreDNS是一个轻量级的DNS服务器,通过插件的形式在Kubernetes集群内实现,提供服务发现功能,使得用户除了可以用IP访问服务器外,也可用域名来访问服务

3.2DNS记录 

  • 服务的DNS记录名称为:
    • <服务名称>.<namespace>.svc.cluster.local
  • 服务后端的deployment中Pod的DNS记录名称为
    • <PodIP>.<服务名称>.<namespace>.svc.cluster.local 
  • ClientPod访问服务时,可以使用<服务名称>.<namespace>便捷抵达服务。甚至在ClientPod与服务在同一namespace时,直接用<服务名称>进行访问

4.Headless Service

创建statefulset和headless service

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web

 # k apply -f statefulset.yaml

 检查(使用clientpod用于测试域名)

root@k8s-master:~# k exec -it clientpod -- /bin/sh
/ # nslookup nginx
Server:         10.96.0.10
Address:        10.96.0.10:53

Name:   nginx.default.svc.cluster.local
Address: 192.168.36.72
Name:   nginx.default.svc.cluster.local
Address: 192.168.169.138


/ # nslookup 192.168.36.72
Server:         10.96.0.10
Address:        10.96.0.10:53

72.36.168.192.in-addr.arpa      name = web-0.nginx.default.svc.cluster.local


/ # ping web-0.nginx.default.svc.cluster.local
PING web-0.nginx.default.svc.cluster.local (192.168.36.72): 56 data bytes
64 bytes from 192.168.36.72: seq=0 ttl=62 time=0.458 ms
64 bytes from 192.168.36.72: seq=1 ttl=62 time=0.525 ms

4.1Headless Service

  • 有时候不需要或者不想要负载均衡,以及单独的Service IP可以通过指定ClisterIP的值为“None”来创建Headless Service
  • 对这类Service并不会分配Cluster IP,kube-proxy不会处理它们,并且平台也不会为他们进行负载均衡和路由
  • 对定义sekector的Headless Service,意味着后端有一些提供业务的Pod,Endpoint控制器在API中创建了Endpoints记录。当通过域名访问服务时,流量会被直接转发到对应的Pod上

 5.Ingress

  • Ingress公开了从集群外部带集群内service的HTTP和HTTPS路由。在ingress资源上定义了流量路由规则控制,可以通过创建ingress实现针对URL,path,SSL的请求转发

 安装ingress控制器

 k apply -f /root/yaml/ingress_nginx.yaml 

 查看ingress controller

 root@k8s-master:~/yaml# k -n ingress-nginx get pod -owide
NAME                                        READY   STATUS      RESTARTS   AGE     IP                NODE        NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-jr5zn        0/1     Completed   0          3m20s   192.168.169.139   k8s-node2   <none>           <none>
ingress-nginx-admission-patch-vhf9n         0/1     Completed   0          3m20s   192.168.36.73     k8s-node1   <none>           <none>
ingress-nginx-controller-55c686bfb9-jzq4b   1/1     Running     0          3m20s   192.168.248.11    k8s-node1   <none>           <none>

 设置缺省ingressClass

 
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  labels:
    app.kubernetes.io/component: controller
  name: nginx
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
spec:
  controller: k8s.io/ingress-nginx

 
root@k8s-master:~/yaml# k apply -f defaultingressclass.yaml
ingressclass.networking.k8s.io/nginx configured
root@k8s-master:~/yaml# k get ingressclasses.networking.k8s.io
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       13m
root@k8s-master:~/yaml# k describe ingressclasses.networking.k8s.io nginx
Name:         nginx
Labels:       app.kubernetes.io/component=controller
Annotations:  ingressclass.kubernetes.io/is-default-class: true
Controller:   k8s.io/ingress-nginx
Events:       <none>

 准备deployment和serivce

 # k create deployment http1 --image=httpd
# k expose deployment http1 --port=8080 --target-port=80

创建单个服务的ingress 

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
spec:
  defaultBackend:
    service:
      name: http1
      port:
        number: 8080

 # k apply -f ingress1.yaml

 检查

 
#  k get ingress
#  k describe ingress test-ingress
#  curl <ingress控制器的IP地址>

创建基于名称虚拟托管

准备deployment和serivce

root@k8s-master:~# k create deployment http2 --image httpd
deployment.apps/http2 created
root@k8s-master:~# k expose deployment http2 --port 8081 --target-port 80
service/http2 exposed
root@k8s-master:~# k exec -it http2-c79d48d9c-vz9wd -- /bin/bash
root@http2-c79d48d9c-vz9wd:/usr/local/apache2# cd htdocs/
root@http2-c79d48d9c-vz9wd:/usr/local/apache2/htdocs# ls
index.html
root@http2-c79d48d9c-vz9wd:/usr/local/apache2/htdocs# echo helloworld > index.html
root@http2-c79d48d9c-vz9wd:/usr/local/apache2/htdocs# exit

 创建ingress

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: http1
            port:
              number: 8080
  - host: bar.foo.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: http2
            port:
              number: 8081

# k apply -f ingress2.yaml 

 添加域名记录

 vim /etc/hosts或者公司DNS服务器

 验证

 curl bar.foo.com
curl foo.bar.com

 基于路径虚拟托管

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /http1
        pathType: Prefix
        backend:
          service:
            name: http1
            port:
              number: 8080
      - path: /http2
        pathType: Prefix
        backend:
          service:
            name: http2
            port:
              number: 8081

# k apply -f ingress3.yaml
root@k8s-master:~# curl 192.168.248.11/http1
<html><body><h1>It works!</h1></body></html> 

十.Kubernetes存储

1.EmptyDir

1.1Volume

  • 在一个Pod使用过程中,会进行很多操作,修改一些文件,安装一些程序等,但当重启容器后,会发现容器又回到了初始状态,所有修改都丢失了
  • 除了希望数据不在Pod重启后丢失,我们有时候也需要在Pod间共享文件,因此,Kubernetes抽象除了Volume对象来解决这两个问题

1.2EmptyDir 

当Pod指定到某个节点上时,首先创建的是一个empytDir卷,并且只要Pod在该节点上运行卷就一直存在,就像它的名称表示的那样,卷最初是空的,尽管Pod中的容器挂载emptyDir卷的路径可能相同也可能不同,但是这些容器都可以读写emptyDir卷中相同的文件当Pod因为某些原因被从节点上删除时,emptyDir卷中的数据也会永久删除,emptyDir的生命周期与Pod一致如果将Pod删除,可以看到对应的目录也不复存在

emptydir

 特点:容器故障时数据不丢失,POD删除时数据随着删除

 
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: httpd
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi

2.hostPath

 hostPath卷能将主机节点文件系统上的文件或目录挂载到Pod中

特点:POD删除数据仍旧保留

 apiVersion: v1
kind: Pod
metadata:
  name: test-pd2
spec:
  containers:
  - image: httpd
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 宿主上目录位置
      path: /data
      # 此字段为可选
      type: DirectoryOrCreate

3.PV和PVC 

  •  pv是集群中由管理员配置的一块存储空间他是集群中的资源,就像节点是集群中的资源一样,PV是卷插件,和之前介绍的volumes类似,但它有一个独立于单个Pod的生命周期,PV的后端可以是NFS,ISCSI或者云存储等
  • PVC是用户的存储请求,它类似于Pod:Pod消耗节点资源,而PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存),PVC可以请求PV特定的接入模式和大小。

创建PV

  • kind选择PersistentVolume
  • name命名PV,在PVC中可调用
  • capacity指定PV的容量
  • accessModes指定访问模式
    • ReadWriteOnce:该卷能够以读写模式被加载到一个节点上
    • ReadOnlyMany:该卷能够以只读模式加载到多个节点上
    • ReadWriteMany:该卷能够以读写模式被多个节点同时加载 
  • persistentVolumeReclaimPolicy指定PV的回收策略
    • Retain(保留),不删除,需要手动回收
    • Recycle(回收,基本擦除,类似rm -rf),使其可供其他PVC申请
    • Delete(删除),关联存储将被删除,如Azure Disk或OpenStack Cinder 
  • nfs字段配置NFS服务器信息,在创建PV前,已搭完NFS服务器
    • pv支持挂载选项包括NFS,ISCSI,Cinder卷,CephFS等 

创建PVC

Kind,类型指定为PVC

accessModes,保持与PV一致

volumeName,使用的PV名称,用于PVC找到正确的PV

requests:指定PV的容量,如果不存在满足该容量需求的PV,则PVC无法绑定任何PV

创建Pod时,可以使用该方式定义volumes,使用pv和PVC

 准备nfs存储

#master充当的NFS Server
root@k8s-master:~# apt install nfs-kernel-server -y
root@k8s-master:~# mkdir /nfs
root@k8s-master:~# chmod 777 /nfs
root@k8s-master:~# vim /etc/exports
#添加如下行
/nfs    *(rw,sync)

root@k8s-master:~# systemctl start nfs-kernel-server
root@k8s-master:~# systemctl enable nfs-kernel-server
root@k8s-master:~# systemctl restart nfs-kernel-server.service 
root@k8s-master:~# showmount -e
Export list for k8s-master:
/nfs *

root@k8s-master:~# mkdir /nfs/pv{1..5}
root@k8s-master:~# chmod 777 /nfs/pv{1..5}

#在所有node节点上执行
root@k8s-node1:~# apt install nfs-common -y
root@k8s-node1:~# showmount -e <master ip>

 创建PV

 apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs/pv1
    server: 192.168.248.10

 创建PVC

 apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

 POD使用PVC

 apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: pvc1

 回收

删除POD,PV、PVC和数据都在

删除PVC,取决于回收机制,如果机制是recycle,则PV在,数据不在。

动态卷供给

1.安装插件

k apply -f  /root/yaml/openebs-operator.yaml 


如果镜像下载不下来,请在每个worker节点上导入openebs.tar
 docker load < openebs.tar
然后等待几分钟后检查openebs pod是否都可正常了
root@k8s-master:~# k get pods -n openebs
NAME                                           READY   STATUS    RESTARTS   AGE
openebs-localpv-provisioner-57f895b46b-xbpt8   1/1     Running   0          29m
openebs-ndm-4tfvn                              1/1     Running   0          29m
openebs-ndm-cluster-exporter-f86785b9-2q4qd    1/1     Running   0          29m
openebs-ndm-gszht                              1/1     Running   0          29m
openebs-ndm-node-exporter-hwlbp                1/1     Running   0          29m
openebs-ndm-node-exporter-x7zmt                1/1     Running   0          29m
openebs-ndm-operator-84b94df6c9-q88hp          1/1     Running   0          29m
 

 2.创建PVC

 apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: openebs-hostpath
  resources:
    requests:
      storage: 1Gi

 3.创建POD

 apiVersion: v1
kind: Pod
metadata:
  name: mypod2
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: mypvc1

 4.检查PV是否正确创建

 root@k8s-master:~# k get pods
NAME     READY   STATUS    RESTARTS   AGE
mypod2   1/1     Running   0          3m15s
root@k8s-master:~# k get pvc
NAME     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
mypvc1   Bound    pvc-42a95417-fd57-4e88-8d86-cad4c79fa209   1Gi        RWO            openebs-hostpath   4m47s
root@k8s-master:~# k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS       REASON   AGE
pvc-42a95417-fd57-4e88-8d86-cad4c79fa209   1Gi        RWO            Delete           Bound    default/mypvc1   openebs-hostpath            105s

 5.如何设置默认storageclass

 kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
root@k8s-master:~# k get storageclasses.storage.k8s.io -A
NAME                         PROVISIONER        RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
openebs-device               openebs.io/local   Delete          WaitForFirstConsumer   false                  26m
openebs-hostpath (default)   openebs.io/local   Delete          WaitForFirstConsumer   false                  26m

 6.设置自动扩展

 #  k edit storageclasses.storage.k8s.io openebs-hostpath
在最后一行添加
allowVolumeExpansion: true

 十一.ConfigMap与Secret

1.ConfigMap

1.1ConfigMap的功能

  • ConfigMap用于容器的配置文件管理,它作为 多个properties文件的应用,类似一个专门存储配置文件的目录,里面存放着各种配置文件
  • ConfigMap实现了image和应用程序的配置文件,命令行参数和环境变量等信息解耦
  • ConfigMap和Secrets类似,但ConfigMap用于处理不含敏感信息的配置文件

1.2ConfigMap使用注意事项 

  1. ConfigMap必须在创建Pod前创建完成,如果Pod调用ConfigMap失败,则无法创建
  2. Pod只能使用在同一Namespace中的ConfigMap
  3. ConfigMap创建方式通常使用文件方式
  4. ConfigMap使用方式通常使用volume方式
  5. 以volume方式挂载ConfigMap更新ConfigMap或删除重建ConfigMap,Pod内挂载的配置信息会热更新(如果想要快速更新完成就重启Pod)

 从目录创建

mkdir ~/configmap
vim account
vim dbinfo
k create cm appcm1 --from-file /root/configmap
k describe cm appcm1

 从文件创建

k create cm appcm2 --from-file /root/configmap/dbinfo

从参数值创建

 k create cm appcm3 --from-literal username=hanmei --from-literal password=hanmei321

 从YAML文件创建

apiVersion: v1
kind: ConfigMap
metadata:
  name: appcm4
data:
  name: hanmei
  password: hanmei123
  dbinfo: |
    dbserver=dbserver01
    dbname=dbname01

k apply -f cm1.yaml 

使用方法

 通过环境变量


apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: busybox
      command: ["sleep", "3600"]
      env:
        - name: accountname # 请注意这里和 ConfigMap 中的键名是不一样的
          valueFrom:
            configMapKeyRef:
              name: appcm4           # 这个值来自 ConfigMap
              key: name # 需要取值的键
      envFrom:
        - configMapRef:
            name: appcm4
 

 k apply -f cmpod1.yaml
# 检查 
k exec -it configmap-demo-pod -- /bin/sh
env

挂载卷

apiVersion: v1
kind: Pod
metadata:
  name: cmpod2
spec:
  containers:
  - name: cmc1
    image: busybox
    command: ["sleep","300000"]
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    configMap:
      name: appcm4

k apply -f cmpod2.yaml
k exec -it cmpod2 -- /bin/sh
cd /etc/foo
ls 

2.Secret

2.1Secret概述

  • Secret是一种包含少量敏感信息例如:密码,token或key的对象。这样的信息可能会被放在Pod spec中或者镜像中,将其放在一个secret对象中可以更好的控制它的用途,并降低意外暴露的风险
  • CongigMap主要解决配置文件的存储问题而Secret主要用来解决密码,token,密钥等敏感数据
    • 在创建,查看和编辑Pod的流程中Secret暴露风险较小
    • 系统会对Secret对象采取额外的预防措施,例如避免将其写入磁盘中可能的位置
    • 只有Pod请求的Secret在其容器中才是可见的,一个Pod不能访问另一个Pod的Secret

从文件创建

kubectl create secret generic password --from-file=s1.txt 

从参数值创建

 kubectl create secret generic password2 --from-literal password=hanmei123

 从YAML文件创建

apiVersion: v1
kind: Secret
metadata:
  name: password3
data:
  password: aGFubWVpMTIz


base64位计算
:r! echo -n <明文> | base64

使用方法

apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
  labels:
    name: secret-test
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: password3
  containers:
  - name: scontainer
    image: busybox
    command: ["sleep","300000"]
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"
 

k apply -f secpod1.yaml
k exec -it secret-test-pod -- /bin/sh
cd /etc/secret-volume
ls 

十三.主机调度 

1.NodeSelector

  • NodeSelector是节点选择约束的最简单推荐形式。nodeSelector是在yaml中定义PodSpec的一个字段
  • 它指定键值对的映射,为了使Pod可以在节点上运行,该节点必须具有每个指示的键值对作为标签(它可以具有其他标签)最常见的用法是一对键值对

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
      nodeSelector:
        disktype: ssd 

 k label node k8s-node1 disktype=ssd
k apply -f nodeselect.yaml
k get pods -owide

2.NodeName

  •  Pod.spec.nodeName用于强制约束将Pod调度到指定的Node节点上,这里是“调度”但其实指定了nodeName的Pod会直接跳过Scheduler的调度逻辑,直接写入PodList列表,该匹配规则是强制匹配
  • nodeName用于选择节点的一些限制是:
    • 如果指定的节点不存在,则容器将不会运行,并且在某些情况下可能会自动删除
    • 如果命名节点没有足够的资源来容纳该Pod,则该Pod将失败,其原因将指示原因,例如Outfmemory或OutOfcpu
    • 云环境中的节点名称并非总是可预测或稳定的

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment2
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
      nodeName: k8s-node2
 

3.Taints and Tolerations

3.1Taints

  • 什么是Taints
    • 节点亲和性是pod的一种属性(偏好或硬性要求),它使pod被吸引到一类特定的节点。Taints则相反,它使节点能够排斥一类特定的pod
  • 创建污点
    • kubectl taint node <name> <key>=<value>.<effect> 
  • 删除污点
    • kubectl taint node <name> <key>:<effect>- 
  • Taints effect可以定义为:
    • NoSchedule表示不允许调度,已调度的不影响
    • PreferNoSchedule表示尽量不调度
    • NoExecute表示不允许调度,已经运行的Pod副本会执行删除的动作

k taint node k8s-node2 env=test:NoSchedule 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment2
  labels:
    app: nginx
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80 

 #验证
k get pods -owide
查看所有的pod没有被调度至k8s-node2上

#删除污点
k taint node k8s-node2 env- 

3.2Tolerations

  •  什么是Tolerations
    • Taint和Tolerations相互配合,可以用来避免Pod被分配到不合适的节点上,每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的Pod是不会被该节点接受的,如果将Tolerations应用于Pod上,则表示这些Pod可以被调度到具有匹配taint的节点上

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment2  labels:
    app: nginx
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
      tolerations:
      - key: "env"
        operator: "Equal"
        value: "test"
        effect: "NoSchedule"

 #验证
k get pods -owide
查看所有的pod可以被调度带有env:test污点的node上

4.Affinity and Antiaffinity

  •  亲和和反亲和的约束类型
    • 语言更具表现力(不仅是and或完全匹配)
    • 规则除了硬性要求(完全匹配)还可以使用“软性要求”/偏好要求
    • 分别可以通过Node节点的Labe与Pod的Label实现亲和和反亲和
  •  亲和和反亲和的两种类型
    • requireuringSchedulinglgnoredDuringExecution(硬性要求)
    • prefereDuringSchedulinglgnoredDuringExecution(软性要求)
  • 运算符(operator)
    • ln,Notin,Exists,DoesNotExist,Gt,Lt,可以使用NotIn和DoesNotExist实现节点的反亲和行为
    • (=        !=        包含,不包含        >        <) 

节点亲和反亲和 

k label node k8s-node1 disktype=ssd 

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: with-node-affinity
    image: nginx
 

 POD亲和/反亲和

#先要给pod1打标签app=nginx

apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - nginx
        topologyKey: kubernetes.io/hostname
  containers:
  - name: nginx2
    image: nginx

 十三.集群安全

1.RBAC权限控制

1.1访问控制概述

  • 客户端认证操作由API Server配置的一个到多个认证插件完成。收到请求后,APIServer依次调用为其配置的认证插件来认证客户端身份,直到其中一个插件可以识别出请求者的身份为止
  • 授权操作也由一个到多个授权插件进行,它负责确定那些通过认证的用户是否有执行发出的资源操作请求,如创建,读取,删除等,随后,通过授权检测的用户发出的操作请求还要经由一个或多个准入控制插件遍历检测,比如检测目标Namesoace资源对象是否存在,检查是否违反系统资源限制等等,其中任何的检查失败都会导致该操作失败

1.2基础概念

 用户(User)

是一个可以独立访问计算机系统中的数据或者用数据表示的其他资源主体(Subject)

许可(Permission)

就是允许对一个或多个客体(object)执行的操作(action)

角色(Role)代表了一种权利,资格,可由多种许可构成

1.3Kubernetes中的用户和用户组

  •  在Kubernetes中客户端访问API服务的途径通常有三种,Kubectl,客户端库或者直接使用REST接口进行请求,故可以执行这几类请求的主体(subject)也被kubernetes分为两类
    • User Account(用户账号):一般是指由独立于Kubernetes之外的其他服务管理的用户账号,Kubernetes中不存在表示此类用户账号的对象,作用于系统全局,名称必须全局唯一
    • Service Account(服务账号):为Pod中的进程调用KubernetesAPI设计,通常需要绑定于特定的名称空间。作用仅局限在他们所在的Namespace,他们由API Serve创建,或者通过Api调用手动创建,附带着一组存储为Secret的用于访问API Server的凭据
  •  这两类账号都可以隶属于一个或多个用户组,用户组本身没有操作权限,但是附加在组上的权限可由其内部的所有用户继承,实现高效的授权管理机制

1.4Role和ClusterRole

  •  RBAC授权插件支持Role和ClusterRole两类角色,他们本质上都是标准的Kubernetes的API对象
  • ClusterRole作用于集群级别,用于集群级组件授权
  • kubernetes还提供了四个预先定义好的ClusteRole来供用户直接使用
    • cluster-admin:整个kubernetes中权限最高的角色
    • admin:规定了大部分资源(不包括node)的权限
    • edit:规定了大部分资源的修改权限的角色
    • view:规定了大部分资源只读权限的角色
  • Role作用于名称空间级别 

1.5RoleBinding和ClusterRoleBinding

  •  Role和ClusterRole只负责定义权限和作用范围,但角色本身并不是动作执行的主体,所以他们需要绑定(binding)到主体(如user,group或service account)上,这个绑定过程其实就是一个授予主体权限的过程
  • Kubernetes提供了两种绑定类型RoleBinding和ClusterRoleBinding,他们本质上也是Kubernetes的API对象
    • RoleBinding用于将Role或Cluster-Role中定义的权限赋予一个或一组用户,但RoleBinding仅能够引用同一名称空间中的Role对象完成授权,RoleBinding可以通过编写yaml文件来创建,也可以直接使用kubectl create rolebinding的命令创建

1.6创建ServiceAccount 

大部分时候我们很少接触UserAccount这种类型用户更多使用和操作的是ServiceAccount这类用户

通过yaml文件定义一个最简单的serviceAccount对象只需要Name和Namespace这两个最基本的字段 

1.7ServiceAccount 

  • Service account是为了方便Pod里面的进程调用KubernetesAPI或其他外部服务而设计的。它与User account不同
    • User account是人为设计的而service account则是为Pod中的进程调用KubernetesAPI而设计
    • User account是跨namespace的,而service accout则是仅局限它所在的namespace
    • 每个namespce都会自动创建一个default service account

1.8ServiceAccount

  •  开启ServiceAccount Admission Controller后
    • 每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)
    • 验证Pod引用的service account已经存在,否则拒绝创建
    • 如果Pod没有指定imagePullSecrets则把service account的imagePullSecrets加到Pod中
    • 每个Contauner启动后都会挂载该Service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/

当创建Pod的时候,如果没有指定一个service account 系统会自动在与该Pod相同的namespace下为其指派一个default service account而pod和apiserver之间进行通信的账号,称为serviceAccountName 

默认的ServiceAccount并没有关联任何Role此时它有访问APIService的绝大多数权限,但无法观察到其他名称空间Pod的相关属性信息 

 查看当前用户认证信息

root@k8s-master:~# k config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.248.10:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED
 

创建密钥对

cd /etc/kubernetes/pki/
openssl genrsa -out hanmei.key 2048
openssl req -new -key hanmei.key -out hanmei.csr -subj "/CN=hanmei/O=kubernetes"
openssl x509 -req -in hanmei.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out hanmei.crt -days 365 

 创建用户账号

k config set-credentials hanmei --client-key hanmei.key --client-certificate hanmei.crt
 

创建安全上下文

k config set-context hanmei@kubernetes --cluster kubernetes --user hanmei
 

验证信息

root@k8s-master:/etc/kubernetes/pki# k config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.248.10:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: hanmei
  name: hanmei@kubernetes
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: hanmei
  user:
    client-certificate: /etc/kubernetes/pki/hanmei.crt
    client-key: /etc/kubernetes/pki/hanmei.key
- name: kubernetes-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED 

切换安全上下文

root@k8s-master:/etc/kubernetes/pki# cd ~
root@k8s-master:~# k config use-context hanmei@kubernetes
Switched to context "hanmei@kubernetes".
root@k8s-master:~# k get pods
Error from server (Forbidden): pods is forbidden: User "hanmei" cannot list resource "pods" in API group "" in the namespace "default"
只完成了认下没有授权 

回管理员,准备完成授权操作

root@k8s-master:~# k config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes". 

 创建自义定的clusterrole

root@k8s-master:~# cat clusterrole1.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: controlleradmin
rules:
- apiGroups: ["apps"]
  resources: ["deployments","daemonsets","statefulsets"]
  verbs: ["get", "watch", "list","create"]
 

 k apply -f clusterrole1.yaml

ClusterRoleBinding


apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: hanmei-controlleradmin
subjects:
- kind: User
  name: hanmei
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: controlleradmin
  apiGroup: rbac.authorization.k8s.io
 

k apply -f crb1.yaml 

验证

root@k8s-master:~# k config use-context hanmei@kubernetes
Switched to context "hanmei@kubernetes".
root@k8s-master:~# k get pods
Error from server (Forbidden): pods is forbidden: User "hanmei" cannot list resource "pods" in API group "" in the namespace "default"
root@k8s-master:~# k get deployments.apps
No resources found in default namespace.
root@k8s-master:~# k create deployment mydep --image=nginx
deployment.apps/mydep created
root@k8s-master:~# k get deployments.apps
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
mydep   0/1     1            0           5s

结果:不能访问POD,但是可以创建deployment和查看deployment
 

 ServiceAccount

 创建NameSpace,并查看default的服务帐号

root@k8s-master:~# k create ns dashboard

root@k8s-master:~# k get sa -n dashboard
NAME      SECRETS   AGE
default   0         14s

 在命令空间中创建服务帐号

root@k8s-master:~# k create serviceaccount sa01 -n dashboard
serviceaccount/sa01 created
root@k8s-master:~# k get sa -n dashboard
NAME      SECRETS   AGE
default   0         74s
sa01      0         8s

 创建Role

 kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods -n dashboard

 .创建rolebinding

kubectl -n dashboard create rolebinding sa01-pod-reader --role pod-reader --user sa01
 

 将服务帐号绑定给POD

 apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: dashboard
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
  serviceAccount: sa01

k apply -f sapod1.yaml 

2.网络策略

十四.集群日常维护

1.日志查看

1.使用kubectl describe查看

2.使用kubectl logs查看

3.使用sidecar查看

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-1
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-2
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/2.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

2.集群监控

监控

安装metric

k apply -f /root/yaml/metric.yaml

 检查是否安装成功

 k get pods -A | grep -i metric

 查看资源状态

 k top nodes
k top pods
    -A
    -l
    --sort-by 

3.节点维护

禁止调度新的POD

k cordon  <nodename>

 驱逐该节点上的所有POD

 k drain nodes <nodename>
     --ignore-daemonsets 
     --delete-emptydir-data  
   --force

 恢复调度

 k uncordon nodes <nodename>

4.ETCD备份和恢复

安装etcdctl 

 apt install etcd-client -y

 查看证书信息

 #第一种方法
k -n kube-system describe pods etcd-k8s-master
#第二种方法
cat /etc/kubernetes/mainfests/etcd.yaml

 etcd备份

 ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379   --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key   snapshot save etcd.db

 验证

 ETCDCTL_API=3 etcdctl --write-out=table snapshot status etcd.db
 

恢复etcd 

 1.停止kubelet
systemctl stop kubelet
2.删除默认etcd路径下所有文件
rm -rf /var/lib/etcd/
3.恢复
 ETCDCTL_API=3 etcdctl  --endpoints 127.0.0.1:2379 snapshot restore --data-dir /var/lib/etcd etcd.db  --skip-hash-check
4.启动kubelet
systemctl start kubelet

5.集群升级

参考网址:升级 kubeadm 集群 | Kubernetes

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想做运维大佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值