• 目的: 解决容器编排问题: 1,某个容器宕机进行候补;2,高并发下扩容
  • 功能:自我修复,密钥管理,负载均衡,服务发现、、、、

重启

  • 在有 yaml 文件的情况下可以直接使用kubectl replace --force -f xxxx.yaml 来强制替换Pod 的 API 对象,从而达到重启的目的
  • 没有 yaml 文件,直接使用的 Pod 对象。kubectl get pod {podname} -n {namespace} -o yaml | kubectl replace --force -f -

命令的意思是get 当前运行的 pod 的 yaml声明,并管道重定向输出到 kubectl replace命令的标准输入,从而达到重启的目的。 

kubernetes组件

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

master:集群的控制平面,负责集群的决策 ( 管理 )

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

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

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

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

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

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

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

Docker : 负责节点上容器的各种操作

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的运行环境

下面,以部署一个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中。

这样,外界用户就可以访问集群中的nginx服务了

etcd存储信息,apiserver接受命令,让scheduler选node返回,apiserver再让controllermanager调用kubelet控制docker启动一个服务的pod。

yaml

  • 大小写敏感

  • 使用缩进表示层级关系

  • 缩进不允许使用tab,只允许空格( 低版本限制 )

  • 缩进的空格数不重要,只要相同层级的元素左对齐即可

  • '#'表示注释

kubectl命令

kubectl命令的语法如下:

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 run nginx-pod --image=nginx:1.17.1 --port=80

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

    kubectl create/patch -f nginx-pod.yaml

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

    kubectl apply -f nginx-pod.yaml

例子:

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

```shell
# 创建一个namespace
[root@master ~]# kubectl create namespace dev
namespace/dev created

# 获取namespace
[root@master ~]# kubectl get ns
NAME              STATUS   AGE
default           Active   21h
dev               Active   21s
kube-node-lease   Active   21h
kube-public       Active   21h
kube-system       Active   21h

# 在此namespace下创建并运行一个nginx的Pod
[root@master ~]# kubectl run pod --image=nginx:latest -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.
deployment.apps/pod created

# 查看新创建的pod
[root@master ~]# kubectl get pod -n dev
NAME  READY   STATUS    RESTARTS   AGE
pod   1/1     Running   0          21s

# 删除指定的pod
[root@master ~]# kubectl delete pod pod-864f9875b9-pcw7x
pod "pod" deleted

# 删除指定的namespace
[root@master ~]# kubectl delete ns dev
namespace "dev" deleted
```

创建一个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:latest

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

[root@master ~]# kubectl create -f nginxpod.yaml
namespace/dev created
pod/nginxpod created

此时发现创建了两个资源对象,分别是namespace和pod

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

[root@master ~]#  kubectl get -f nginxpod.yaml
NAME            STATUS   AGE
namespace/dev   Active   18s
​
NAME            READY   STATUS    RESTARTS   AGE
pod/nginxpod    1/1     Running   0          17s

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

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

[root@master ~]# kubectl delete -f nginxpod.yaml
namespace "dev" deleted
pod "nginxpod" deleted

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

namespace

默认k8s集群下各个pod可以相互访问,将pod划分在不同的namespace下进行隔离。

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: "2021-05-08T04:44:16Z"
  name: default
  resourceVersion: "151"
  selfLink: /api/v1/namespaces/default
  uid: 7405f73a-e486-43d4-9db6-145f1409f090
spec:
  finalizers:
  - kubernetes
status:
  phase: Active

kubectl create/get/describe/delete ns  ns名称

pod

一个pod中存在一个或多个容器,是k8s集群进行管理的最小粒度;每个都有pause容器,以此评估整个pod的健康状态,设置ip地址以实现pod内部的通讯。

创建并运行

kubectl run nginx --image=nginx:latest --port=80 --namespace dev

 kubectl run (pod控制器名称) [参数] 
# --image  指定Pod的镜像
# --port   指定端口
# --namespace  指定namespace

查看某个ns下pods信息

kubectl get pods  -n nsname  ( -o wide)   (-o wide显示详细信息)

获得-n指定namespace 下的pod

[root@master ~]# kubectl get pod -n kube-system
NAMESPACE     NAME                             READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-68g6v         1/1     Running   0          2d1h
kube-system   coredns-6955765f44-cs5r8         1/1     Running   0          2d1h

查看指定详细信息

kubectl  describe pod nginx -n nsname

删除ns下的pod

# 先来查询一下当前namespace下的Pod控制器
[root@master ~]# kubectl get deploy -n  dev
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           9m7s

# 接下来,删除此PodPod控制器
[root@master ~]# kubectl delete deploy nginx -n dev
deployment.apps "nginx" deleted

# 稍等片刻,再查询Pod,发现Pod被删除了
[root@master ~]# kubectl get pods -n dev
No resources found in dev namespace.

yaml创建

资源的五个有要素:

apiversion,kind,metadata,spec,status

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  #容器需要监听的端口号
      hostPort: int       #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string    #端口协议,支持TCP和UDP,默认TCP
    env:   #容器运行前需设置的环境变量列表
    - name: string  #环境变量名称
      value: string #环境变量的值
    resources: #资源限制和请求的设置
      limits:  #资源限制的设置
        cpu: string     #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string  #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests: #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string #内存请求,容器启动的初始可用数量
    lifecycle: #生命周期钩子
        postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
        preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
    livenessProbe:  #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
      exec:         #对Pod容器内检查方式设置为exec方式
        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
       initialDelaySeconds: 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表示将该Pod调度到包含这个label的node上
  imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
  - name: string
  hostNetwork: false   #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
  volumes:   #在该pod上定义共享存储卷列表
  - name: string    #共享存储卷名称 (volumes类型有很多种)
    emptyDir: {}       #类型为emtyDir的存储卷,与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 create -f pod-nginx.yaml

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

eg:

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;"]
    env: # 设置环境变量列表
    - name: "username"
      value: "admin"
    - name: "password"
      value: "123456"

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

查看详情(报错)

 kubectl describe pod pod-resources -n dev

进入某个容器内部进行操作:

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

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

[root@k8s-master01 pod]# kubectl exec pod-command -n dev -it -c busybox /bin/sh
/ # echo %username

创建pod

apiserver注册pod对象。分配的主机等各种信息到etcd,scheduler分配主机,kubelet调用启动容器;

容器探测

liveness probes:

用于检测是否处于正常状态,否则重启

spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:  # 其实就是访问http://127.0.0.1:80/hello  
        scheme: HTTP #支持的协议,http或者https
        port: 80 #端口号
        path: /hello #URI地址

    livenessProbe:
      tcpSocket:
        port: 8080 # 尝试访问8080端口

describe查看结果,,,

readiness probes

用于检测是否可以接受请求,不能的话不会转发流量

pod调度

定向调度

spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  nodeName: node1 # 指定调度到node1节点上

  containers:
  - name: nginx
    image: nginx:1.17.1
  nodeSelector: 
    nodeenv: pro # 指定调度到具有nodeenv=pro标签的节点上

若没有满足的node,则不会运行

pod控制器

几种pod控制器

  • ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级

  • Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本

replicaset

deployment

一般通过pod控制器控制pod;;

创建

kubectl create deploy ngnix --image=nginx:latest --port=80 --replicas=3 -n nsname

查看pod

kubectl get pods -n nsname

查看deploy

kubectl get deploy -n nsname

label

标识各种对象,pod,ns,service等用于区分,如version,env,tier

pod打标签

kubectl label pod nginx-pod version=1.0 -n nsname

更新标签

kubectl label pod nginx-pod  version=1.1 -n nsname  --overwrite

筛选

kubeclt  get pod -n nsname -l version=2.0  --show-labels

kubctl get pod -n nsname -l version!=2.0 --show-labels

(-l参数用作标签的筛选,)

删除

kubectl label pod nginx-pod version- -n nsname

service

同类的pod对外的访问接口。实现服务发现和负载均衡

--type=ClusterIP         只有集群内访问

--type=NodePort   外部也可以访问

# 暴露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.109.179.231   <none>        80/TCP    3m51s   run=nginx




[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:31928/TC)
[root@master ~]# kubectl get svc  svc-nginx2  -n dev -o wide
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE    SELECTOR
svc-nginx2    NodePort    10.100.94.0      <none>        80:31928/TCP   9s     run=nginx

# 接下来就可以通过集群外的主机访问 节点IP:31928访问服务了
# 例如在的电脑主机上通过浏览器访问下面的地址
http://192.168.5.4:31928/

删除service

kubectl delete svc svcname -n nsname 

配置方式

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

apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
  namespace: dev
spec:
  clusterIP: 10.109.179.231 #固定svc的内网ip
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
  type: ClusterIP

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

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

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

docker

  • vs vm为什么快?不需要加载os,直接使用宿主机的内核;;;不需要硬件资源虚拟化,直接使用物理机硬件资源,更少的抽象层
    1. Docker常用命令
  1. 帮助启动类命令
    1. 启动docker: systemctl start docker
    2. 停止docker: systemctl stop docker
    3. 重启docker: systemctl restart docker
    4. 查看docker状态: systemctl status docker
    5. 开机启动: systemctl enable docker
    6. 查看docker概要信息: docker info
    7. 列出镜像  docker images
    8. 搜索匹配镜像 docker search
    9. 下载镜像  docker pull 名字
    10. 运行容器 docker run image   -d后台运行并返回容器id;-p: 指定端口映射,小写p
    11. docker ps  查看现在运行的容器
    12. docker start/restart/stop/kill/rm 容器id或容器名
    13. 进入运行的容器并使用命令行交互: docker exec -it id /bin/bash
    14. docker commit  提交镜像

运行redis完整实例:

docker pull redis

docker run -d -p 6379:6379 redis

docker run  -p 6379:6379 --name myredis --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf  即本机/app/redis/redis.conf进行配置后docker中运行,无敌!

  -v创建容器数据卷 run -e传递环境变量,run -d后台运行容器,并返回容器ID;

修改配置文件后重启docker restart myredis

docker ps 得到id

docker exec -it id /bin/bash

PLUS 容器数据卷:

使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

特点:1:数据卷可在容器之间共享或重用数据2:卷中的更改可以直接实时生效,爽3:数据卷中的更改不会包含在镜像的更新中4:数据卷的生命周期一直持续到没有容器使用它为止

运行一个带有容器卷存储功能的容器实例

  •  docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录      镜像名

docker加载

一层层的文件系统(分层的好处,共享资源:如公用bootfs)

bootfs=bootloader+kernel  加载内核

rootfs (root file system) ,在bootfs之上包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如UbuntuCentos等等。 

镜像层只读。容器层可写;;

DockerFile解析

Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

eg:centos中部署jdk环境

dockerfile:

FROM centos
MAINTAINER zzyy<zzyybs@126.com>
 
ENV MYPATH /usr/local
WORKDIR $MYPATH
 
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包;;此时把宿主机与Dockerfile文件在同一位置的jdk-8u171-linux-x64.tar.gz添加到容器中
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

#·当前容器对外暴露出的端口 
EXPOSE 80
 
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash

docker buld -t 镜像名字 .  (镜像名称后有一个空格和一个.) 

docker-compose

三部曲

  1. 编写dockerfile定义各个微服务应用并构建镜像
  2. 使用docker-compose.yml定义一组关联的应用容器
  3. 执行docker-compose up启动运行程序
  • Compose常用命令
Compose常用命令
docker-compose -h                           # 查看帮助
docker-compose up                           # 启动所有docker-compose服务
docker-compose up -d                        # 启动所有docker-compose服务并后台运行
docker-compose down                         # 停止并删除容器、网络、卷、镜像。
docker-compose exec  yml里面的服务id                 # 进入容器实例内部  
docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps                      # 展示当前docker-compose编排过的运行的所有容器
docker-compose top                     # 展示当前docker-compose编排过的容器进程
 
docker-compose logs  yml里面的服务id     # 查看容器输出日志
docker-compose config     # 检查配置
docker-compose config -q  # 检查配置,有问题才有输出
docker-compose restart   # 重启服务
docker-compose start     # 启动服务
docker-compose stop      # 停止服务

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐